Additional Tests for Notification, Token and Email

Change-Id: I57f1df7790fd258ea1b5b9365b15816872941b3a
This commit is contained in:
Amelia Cordwell 2017-06-22 17:33:20 +12:00 committed by Adrian Turjak
parent 1600a7bdf6
commit 5e16b575ad
11 changed files with 946 additions and 33 deletions

View File

@ -6,5 +6,7 @@ exclude_lines =
if settings.DEBUG:
raise AssertionError
raise NotImplementedError
self.fail
omit =
adjutant/wsgi.py
setup.py

View File

@ -39,7 +39,9 @@ def send_email(to_addresses, context, conf, task):
# message headers
from_email = conf.get('from')
if not from_email:
from_email = conf['reply']
from_email = conf.get('reply')
if not from_email:
return
elif "%(task_uuid)s" in from_email:
from_email = from_email % {'task_uuid': task.uuid}

View File

@ -31,8 +31,11 @@ class SendAdditionalEmailAction(BaseAction):
self.emails.add(self.action.task.keystone_user['username'])
else:
try:
self.emails.add(self.action.task.keystone_user['email'])
except KeyError:
id_manager = user_store.IdentityManager()
email = id_manager.get_user(
self.action.task.keystone_user['user_id']).email
self.emails.add(email)
except AttributeError:
self.add_note("Could not add current user email address")
if conf.get('email_roles'):
@ -52,7 +55,7 @@ class SendAdditionalEmailAction(BaseAction):
self.emails.add(user.email)
if conf.get('email_task_cache'):
task_emails = self.task.cache.get('additional_emails', [])
task_emails = self.action.task.cache.get('additional_emails', [])
if isinstance(task_emails, six.string_types):
task_emails = [task_emails]
for email in task_emails:

View File

@ -0,0 +1,237 @@
# Copyright (C) 2015 Catalyst IT Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
from django.core import mail
from adjutant.actions.v1.misc import SendAdditionalEmailAction
from adjutant.actions.utils import send_email
from adjutant.api.models import Task
from adjutant.api.v1.tests import (FakeManager,
modify_dict_settings, AdjutantTestCase)
from smtplib import SMTPException
default_email_conf = {
'from': "adjutant@example.com",
'reply': 'adjutant@example.com',
'template': 'initial.txt',
'html_template': 'completed.txt',
'subject': 'additional email'
}
class FailEmail(mock.MagicMock):
def send(self, *args, **kwargs):
raise SMTPException
@mock.patch('adjutant.actions.user_store.IdentityManager',
FakeManager)
class MiscActionTests(AdjutantTestCase):
def test_send_email(self):
# include html template
to_address = "test@example.com"
task = Task.objects.create(
ip_address="0.0.0.0",
keystone_user={}
)
context = {
'task': task,
'actions': ["action_1", "action_2"]
}
result = send_email(to_address, context, default_email_conf, task)
# check the email itself
self.assertNotEqual(result, None)
self.assertEqual(len(mail.outbox), 1)
self.assertTrue("action_1" in mail.outbox[0].body)
def test_send_email_no_addresses(self):
to_address = []
task = Task.objects.create(
ip_address="0.0.0.0",
keystone_user={}
)
context = {
'task': task,
'actions': ["action_1", "action_2"]
}
result = send_email(to_address, context, default_email_conf, task)
self.assertEqual(result, None)
self.assertEqual(len(mail.outbox), 0)
@mock.patch('adjutant.actions.utils.EmailMultiAlternatives',
FailEmail)
@modify_dict_settings(DEFAULT_ACTION_SETTINGS={
'operation': 'update',
'key_list': ['SendAdditionalEmailAction', 'token'],
'value': {
'email_task_cache': True,
'subject': 'Email Subject',
'template': 'token.txt'
}
}, DEFAULT_TASK_SETTINGS={
'operation': 'delete',
'key_list': ['notifications'],
})
def test_send_additional_email_fail(self):
"""
Tests that a failure to send an additional email doesn't cause
it to become invalid or break.
"""
task = Task.objects.create(
ip_address="0.0.0.0",
keystone_user={},
task_type='edit_roles',
)
# setup settings
action = SendAdditionalEmailAction({}, task=task, order=1)
action.pre_approve()
self.assertEquals(action.valid, True)
task.cache["additional_emails"] = ["thisguy@righthere.com",
"nope@example.com"]
action.post_approve()
self.assertEquals(action.valid, True)
self.assertEqual(len(mail.outbox), 0)
self.assertTrue(
"Unable to send additional email. Stage: token" in
action.action.task.action_notes['SendAdditionalEmailAction'][1])
action.submit({})
self.assertEquals(action.valid, True)
@modify_dict_settings(DEFAULT_ACTION_SETTINGS={
'operation': 'update',
'key_list': ['SendAdditionalEmailAction', 'token'],
'value': {
'email_task_cache': True,
'subject': 'Email Subject',
'template': 'token.txt'
}
})
def test_send_additional_email_task_cache(self):
"""
Tests sending an additional email with the address placed in the
task cache.
"""
task = Task.objects.create(
ip_address="0.0.0.0",
keystone_user={}
)
# setup settings
action = SendAdditionalEmailAction({}, task=task, order=1)
action.pre_approve()
self.assertEquals(action.valid, True)
task.cache["additional_emails"] = ["thisguy@righthere.com",
"nope@example.com"]
action.post_approve()
self.assertEquals(action.valid, True)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(set(mail.outbox[0].to),
set(["thisguy@righthere.com", "nope@example.com"]))
action.submit({})
self.assertEquals(action.valid, True)
self.assertEqual(len(mail.outbox), 1)
@modify_dict_settings(DEFAULT_ACTION_SETTINGS={
'operation': 'update',
'key_list': ['SendAdditionalEmailAction', 'token'],
'value': {
'email_task_cache': True,
'subject': 'Email Subject',
'template': 'token.txt'
}
})
def test_send_additional_email_task_cache_none_set(self):
"""
Tests sending an additional email with 'email_task_cache' set but
no address placed in the task cache.
"""
task = Task.objects.create(
ip_address="0.0.0.0",
keystone_user={}
)
# setup settings
action = SendAdditionalEmailAction({}, task=task, order=1)
action.pre_approve()
self.assertEquals(action.valid, True)
action.post_approve()
self.assertEquals(action.valid, True)
self.assertEqual(len(mail.outbox), 0)
action.submit({})
self.assertEquals(action.valid, True)
@modify_dict_settings(DEFAULT_ACTION_SETTINGS={
'operation': 'update',
'key_list': ['SendAdditionalEmailAction', 'token'],
'value': {
'email_additional_addresses': ['anadminwhocares@example.com'],
'subject': 'Email Subject',
'template': 'token.txt'
}
})
def test_send_additional_email_email_in_settings(self):
"""
Tests sending an additional email with the address placed in the
task cache.
"""
task = Task.objects.create(
ip_address="0.0.0.0",
keystone_user={}
)
# setup settings
action = SendAdditionalEmailAction({}, task=task, order=1)
action.pre_approve()
self.assertEquals(action.valid, True)
action.post_approve()
self.assertEquals(action.valid, True)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to,
["anadminwhocares@example.com"])
action.submit({})
self.assertEquals(action.valid, True)
self.assertEqual(len(mail.outbox), 1)

View File

@ -19,13 +19,14 @@ from datetime import timedelta
from unittest import skip
from django.utils import timezone
from django.core import mail
import mock
from rest_framework import status
from rest_framework.test import APITestCase
from adjutant.api.models import Task, Token
from adjutant.api.models import Task, Token, Notification
from adjutant.api.v1.tests import (FakeManager, setup_temp_cache,
modify_dict_settings)
@ -189,8 +190,7 @@ class AdminAPITests(APITestCase):
def test_token_get(self):
"""
Token should contian task uuid, task_type, required fields, and it's
own value
Token should contain actions, task_type, required fields.
"""
user = mock.Mock()
@ -221,6 +221,46 @@ class AdminAPITests(APITestCase):
u'task_type': 'reset_password'})
self.assertEqual(1, Token.objects.count())
def test_token_list_get(self):
user = mock.Mock()
user.id = 'user_id'
user.name = "test@example.com"
user.email = "test@example.com"
user.domain = 'default'
user.password = "test_password"
setup_temp_cache({}, {user.id: user})
url = "/v1/actions/ResetPassword"
data = {'email': "test@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
response.data['notes'],
['If user with email exists, reset token will be issued.'])
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
first_task_id = Task.objects.all()[0].uuid
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/tokens/"
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
len(response.json()['tokens']), 2)
self.assertEqual(response.json()['tokens'][1]['task'],
first_task_id)
def test_task_complete(self):
"""
Can't approve a completed task.
@ -251,6 +291,66 @@ class AdminAPITests(APITestCase):
response.json(),
{'errors': ['This task has already been completed.']})
def test_status_page(self):
"""
Status page gives details of last_created_task, last_completed_task
and error notifcations
"""
setup_temp_cache({}, {})
url = "/v1/actions/CreateProject"
data = {'project_name': "test_project", 'email': "test@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/status/"
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()['last_created_task'][
'actions'][0]['data']['email'], 'test@example.com')
self.assertEqual(response.json()['last_completed_task'], None)
self.assertEqual(response.json()['error_notifications'], [])
# Create a second task and ensure it is the new last_created_task
url = "/v1/actions/CreateProject"
data = {'project_name': "test_project_2",
'email': "test_2@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
url = "/v1/status/"
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()['last_created_task'][
'actions'][0]['data']['email'], 'test_2@example.com')
self.assertEqual(response.json()['last_completed_task'], None)
self.assertEqual(response.json()['error_notifications'], [])
new_task = Task.objects.all()[0]
new_task.completed = True
new_task.save()
url = "/v1/status/"
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()['last_completed_task'][
'actions'][0]['data']['email'], 'test@example.com')
self.assertEqual(response.json()['last_created_task'][
'actions'][0]['data']['email'], 'test_2@example.com')
self.assertEqual(response.json()['error_notifications'], [])
def test_task_update(self):
"""
Creates a invalid task.
@ -305,6 +405,63 @@ class AdminAPITests(APITestCase):
response.json(),
{'notes': ['created token']})
def test_notification_get(self):
"""
Test that you can get details of an induvidual notfication.
"""
setup_temp_cache({}, {})
url = "/v1/actions/CreateProject"
data = {'project_name': "test_project", 'email': "test@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
new_task = Task.objects.all()[0]
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
note = Notification.objects.first().uuid
url = "/v1/notifications/%s" % note
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
response.json()['task'],
new_task.uuid)
self.assertEqual(
response.json()['notes'],
{u'notes': [u'New task for CreateProject.']})
self.assertEqual(
response.json()['error'], False)
def test_notification_doesnt_exist(self):
"""
Test that you get a 404 trying to access a non-existent notification.
"""
setup_temp_cache({}, {})
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
note = "notarealnotifiactionuuid"
url = "/v1/notifications/%s/" % note
response = self.client.get(url, headers=headers, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.json(),
{"errors": ["No notification with this id."]})
def test_notification_acknowledge(self):
"""
Test that you can acknowledge a notification.
@ -352,6 +509,89 @@ class AdminAPITests(APITestCase):
)
self.assertEqual(response.json(), {'notifications': []})
def test_notification_acknowledge_doesnt_exist(self):
"""
Test that you cant acknowledge a non-existent notification.
"""
setup_temp_cache({}, {})
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/notifications/dasdaaaiooiiobksd/"
response = self.client.post(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.json(),
{'errors':
['No notification with this id.']})
def test_notification_re_acknowledge(self):
"""
Test that you cant reacknowledge a notification.
"""
setup_temp_cache({}, {})
url = "/v1/actions/CreateProject"
data = {'project_name': "test_project", 'email': "test@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
note_id = Notification.objects.first().uuid
url = "/v1/notifications/%s/" % note_id
data = {'acknowledged': True}
response = self.client.post(url, data, format='json', headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(),
{'notes': ['Notification acknowledged.']})
response = self.client.post(url, data, format='json', headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(),
{'notes': ['Notification already acknowledged.']})
def test_notification_acknowledge_no_data(self):
"""
Test that you have to include 'acknowledged': True to the request.
"""
setup_temp_cache({}, {})
url = "/v1/actions/CreateProject"
data = {'project_name': "test_project", 'email': "test@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
note_id = Notification.objects.first().uuid
url = "/v1/notifications/%s/" % note_id
data = {}
response = self.client.post(url, data, format='json', headers=headers)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.json(),
{u'acknowledged': [u'this field is required.']})
def test_notification_acknowledge_list(self):
"""
Test that you can acknowledge a list of notifications.
@ -397,6 +637,91 @@ class AdminAPITests(APITestCase):
)
self.assertEqual(response.json(), {'notifications': []})
def test_notification_acknowledge_list_empty_list(self):
"""
Test that you cannot acknowledge an empty list of notifications.
"""
setup_temp_cache({}, {})
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/notifications"
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
data = {'notifications': []}
response = self.client.post(url, data, format='json', headers=headers)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.json(),
{u'notifications':
[u'this field is required and needs to be a list.']})
@modify_dict_settings(DEFAULT_TASK_SETTINGS={
'key_list': ['notifications'],
'operation': 'override',
'value': {
'EmailNotification': {
'standard': {
'emails': ['example@example.com'],
'reply': 'no-reply@example.com',
'template': 'notification.txt'
},
'error': {
'emails': ['example@example.com'],
'reply': 'no-reply@example.com',
'template': 'notification.txt'
}
}
}
}, TASK_SETTINGS={
'key_list': ['create_project', 'emails'],
'operation': 'override',
'value': {
'initial': None,
'token': None,
'completed': None
}
})
def test_notification_email(self):
"""
Tests the email notification engine
"""
setup_temp_cache({}, {})
url = "/v1/actions/CreateProject"
data = {'project_name': "test_project", 'email': "test@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
new_task = Task.objects.all()[0]
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/notifications"
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
response.data["notifications"][0]['task'],
new_task.uuid)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, 'create_project notification')
self.assertTrue("New task for CreateProject" in mail.outbox[0].body)
def test_token_expired_delete(self):
"""
test deleting of expired tokens.
@ -555,6 +880,124 @@ class AdminAPITests(APITestCase):
self.assertEqual(response.json(),
{'errors': ['No task with this id.']})
def test_token_reissue_task_cancelled(self):
"""
Tests that a cancelled task cannot have a token reissued
"""
user = mock.Mock()
user.id = 'user_id'
user.name = "test@example.com"
user.email = "test@example.com"
user.domain = 'default'
user.password = "test_password"
setup_temp_cache({}, {user.id: user})
url = "/v1/actions/ResetPassword"
data = {'email': "test@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
response.json()['notes'],
['If user with email exists, reset token will be issued.'])
task = Task.objects.all()[0]
task.cancelled = True
task.save()
self.assertEqual(Token.objects.count(), 1)
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/tokens/"
data = {"task": task.uuid}
response = self.client.post(url, data, format='json',
headers=headers)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.json(),
{'errors': ['This task has been cancelled.']})
def test_token_reissue_task_completed(self):
"""
Tests that a completed task cannot have a token reissued
"""
user = mock.Mock()
user.id = 'user_id'
user.name = "test@example.com"
user.email = "test@example.com"
user.domain = 'default'
user.password = "test_password"
setup_temp_cache({}, {user.id: user})
url = "/v1/actions/ResetPassword"
data = {'email': "test@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
response.json()['notes'],
['If user with email exists, reset token will be issued.'])
task = Task.objects.all()[0]
task.completed = True
task.save()
self.assertEqual(Token.objects.count(), 1)
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/tokens/"
data = {"task": task.uuid}
response = self.client.post(url, data, format='json',
headers=headers)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.json(),
{'errors': ['This task has already been completed.']})
def test_token_reissue_task_not_approve(self):
"""
Tests that an unapproved task cannot have a token reissued
"""
setup_temp_cache({}, {})
url = "/v1/actions/CreateProject"
data = {'email': "test@example.com", "project_name": "test_project"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
response.json()['notes'], [u'task created'])
task = Task.objects.all()[0]
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "admin,_member_",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/tokens/"
data = {"task": task.uuid}
response = self.client.post(url, data, format='json',
headers=headers)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.json(),
{'errors': ['This task has not been approved.']})
def test_cancel_task(self):
"""
Ensure the ability to cancel a task.

View File

@ -110,6 +110,40 @@ class OpenstackAPITests(APITestCase):
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.json()['users']), 2)
self.assertTrue(b'test2@example.com' in response.content)
def test_user_detail(self):
"""
Confirm that the user detail view functions as expected
"""
user = mock.Mock()
user.id = 'test_user_id'
user.name = 'test@example.com'
user.email = 'test@example.com'
project = mock.Mock()
project.id = 'test_project_id'
project.name = 'test_project'
project.domain = 'default'
project.roles = {user.id: ['_member_']}
setup_temp_cache({'test_project': project}, {user.id: user})
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "project_admin,_member_,project_mod",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/openstack/users/%s" % user.id
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()['username'], 'test@example.com')
self.assertEqual(response.json()['roles'], ["_member_"])
def test_user_list_managable(self):
"""

View File

@ -731,6 +731,131 @@ class TaskViewTests(AdjutantAPITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEquals(user.name, 'new_test@example.com')
@modify_dict_settings(TASK_SETTINGS=[
{'key_list': ['update_email', 'additional_actions'],
'operation': 'append',
'value': ['SendAdditionalEmailAction']},
{'key_list': ['update_email', 'action_settings',
'SendAdditionalEmailAction', 'initial'],
'operation': 'update',
'value': {
'subject': 'email_update_additional',
'template': 'email_update_started.txt',
'email_roles': [],
'email_current_user': True,
}
}
])
def test_update_email_task_send_email_to_current_user(self):
"""
Tests the email update workflow, and ensures that when setup
to send a confirmation email to the old email address it does.
"""
user = mock.Mock()
user.id = 'test_user_id'
user.name = "test@example.com"
user.email = "test@example.com"
user.domain = 'default'
setup_temp_cache({}, {user.id: user})
url = "/v1/actions/UpdateEmail"
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "project_admin,_member_,project_mod",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
data = {'new_email': "new_test@example.com"}
response = self.client.post(url, data, format='json', headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'notes': ['created token']})
self.assertEqual(len(mail.outbox), 2)
self.assertEqual(mail.outbox[0].to, ['test@example.com'])
self.assertEqual(mail.outbox[0].subject, 'email_update_additional')
self.assertEqual(mail.outbox[1].to, ['new_test@example.com'])
self.assertEqual(mail.outbox[1].subject, 'Your Token')
new_token = Token.objects.all()[0]
url = "/v1/tokens/" + new_token.token
data = {'confirm': True}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(user.name, 'new_test@example.com')
self.assertEqual(len(mail.outbox), 3)
@modify_dict_settings(TASK_SETTINGS=[
{'key_list': ['update_email', 'additional_actions'],
'operation': 'append',
'value': ['SendAdditionalEmailAction']},
{'key_list': ['update_email', 'action_settings',
'SendAdditionalEmailAction', 'initial'],
'operation': 'update',
'value': {
'subject': 'email_update_additional',
'template': 'email_update_started.txt',
'email_roles': [],
'email_current_user': True}
}
])
@override_settings(USERNAME_IS_EMAIL=False)
def test_update_email_task_send_email_current_name_not_email(self):
"""
Tests the email update workflow when USERNAME_IS_EMAIL=False, and
ensures that when setup to send a confirmation email to the old
email address it does.
"""
user = mock.Mock()
user.id = 'test_user_id'
user.name = "nkdfslnkls"
user.email = "test@example.com"
user.domain = 'default'
setup_temp_cache({}, {user.id: user})
url = "/v1/actions/UpdateEmail"
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "project_admin,_member_,project_mod",
'username': "nkdfslnkls",
'user_id': "test_user_id",
'authenticated': True,
'email': 'test@example.com',
}
data = {'new_email': "new_test@example.com"}
response = self.client.post(url, data, format='json', headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'notes': ['created token']})
self.assertEqual(len(mail.outbox), 2)
self.assertEqual(mail.outbox[0].to, ['test@example.com'])
self.assertEqual(mail.outbox[0].subject, 'email_update_additional')
self.assertEqual(mail.outbox[1].to, ['new_test@example.com'])
self.assertEqual(mail.outbox[1].subject, 'Your Token')
new_token = Token.objects.all()[0]
url = "/v1/tokens/" + new_token.token
data = {'confirm': True}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(mail.outbox), 3)
def test_update_email_task_invalid_email(self):
user = mock.Mock()
@ -1112,6 +1237,71 @@ class TaskViewTests(AdjutantAPITestCase):
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
@modify_dict_settings(
TASK_SETTINGS=[
{'key_list': ['invite_user', 'additional_actions'],
'operation': 'append',
'value': ['SendAdditionalEmailAction']},
{'key_list': ['invite_user', 'action_settings',
'SendAdditionalEmailAction', 'initial'],
'operation': 'update',
'value': {
'subject': 'email_update_additional',
'template': 'email_update_started.txt',
'email_roles': ['project_admin'],
'email_current_user': False,
}
}
])
def test_additional_emails_role_no_email(self):
"""
Tests that setting email roles to something that has no people to
send to that the update action doesn't fall over
"""
project = mock.Mock()
project.id = 'test_project_id'
project.name = 'test_project'
project.domain = 'default'
user = mock.Mock()
user.id = 'test_user_id'
user.name = "test@example.com"
user.email = "test@example.com"
user.domain = 'default'
project.roles = {user.id: ['_member_']}
setup_temp_cache({'test_project': project}, {user.id: user})
url = "/v1/actions/InviteUser"
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "project_admin,_member_,project_mod",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
data = {'email': "new_test@example.com",
'roles': ['_member_']}
response = self.client.post(url, data, format='json', headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'notes': ['created token']})
self.assertEqual(len(mail.outbox), 1)
# Test that the token email gets sent to the other addresses
self.assertEqual(mail.outbox[0].to[0], 'new_test@example.com')
new_token = Token.objects.all()[0]
url = "/v1/tokens/" + new_token.token
data = {'confirm': True, 'password': '1234'}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
@modify_dict_settings(
TASK_SETTINGS=[
{'key_list': ['invite_user', 'additional_actions'],

View File

@ -106,9 +106,11 @@ class NotificationList(APIViewWithLogger):
return Response({'notes': ['Notifications acknowledged.']},
status=200)
else:
return Response({'notifications': ["this field is required" +
"needs to be a list."]},
status=400)
return Response(
{'notifications': [
"this field is required and needs to be a list."
]},
status=400)
class NotificationDetail(APIViewWithLogger):
@ -680,11 +682,6 @@ class TokenDetail(APIViewWithLogger):
['This task has been cancelled.']},
status=400)
if token.expires < timezone.now():
token.delete()
return Response({'errors': ['This token has expired.']},
status=400)
required_fields = []
actions = []
@ -727,11 +724,6 @@ class TokenDetail(APIViewWithLogger):
['This task has been cancelled.']},
status=400)
if token.expires < timezone.now():
token.delete()
return Response({'errors': ['This token has expired.']},
status=400)
required_fields = set()
actions = []
for action in token.task.actions:

View File

@ -136,17 +136,10 @@ LOGGING = CONFIG['LOGGING']
EMAIL_BACKEND = CONFIG['EMAIL_SETTINGS']['EMAIL_BACKEND']
EMAIL_TIMEOUT = 60
if CONFIG['EMAIL_SETTINGS'].get('EMAIL_HOST'):
EMAIL_HOST = CONFIG['EMAIL_SETTINGS']['EMAIL_HOST']
if CONFIG['EMAIL_SETTINGS'].get('EMAIL_PORT'):
EMAIL_PORT = CONFIG['EMAIL_SETTINGS']['EMAIL_PORT']
if CONFIG['EMAIL_SETTINGS'].get('EMAIL_HOST_USER'):
EMAIL_HOST_USER = CONFIG['EMAIL_SETTINGS']['EMAIL_HOST_USER']
if CONFIG['EMAIL_SETTINGS'].get('EMAIL_HOST_PASSWORD'):
EMAIL_HOST_PASSWORD = CONFIG['EMAIL_SETTINGS']['EMAIL_HOST_PASSWORD']
EMAIL_HOST = CONFIG['EMAIL_SETTINGS'].get('EMAIL_HOST')
EMAIL_PORT = CONFIG['EMAIL_SETTINGS'].get('EMAIL_PORT')
EMAIL_HOST_USER = CONFIG['EMAIL_SETTINGS'].get('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = CONFIG['EMAIL_SETTINGS'].get('EMAIL_HOST_PASSWORD')
# setting to control if user name and email are allowed
# to have different values.

View File

@ -106,7 +106,21 @@ DEFAULT_TASK_SETTINGS = {
'template': 'completed.txt',
'subject': 'Task completed'
}
}
},
'notifications': {
'EmailNotification': {
'standard': {
'emails': ['example@example.com'],
'reply': 'no-reply@example.com',
'template': 'notification.txt'
},
'error': {
'emails': ['example@example.com'],
'reply': 'no-reply@example.com',
'template': 'notification.txt'
}
}
},
}
DEFAULT_ACTION_SETTINGS = {
@ -240,6 +254,9 @@ TASK_SETTINGS = {
'initial': None,
},
},
'edit_user': {
'role_blacklist': ['admin']
}
}
ROLES_MAPPING = {

View File

@ -197,7 +197,7 @@ DEFAULT_ACTION_SETTINGS:
# email_roles:
# - project_admin
# Or sends to an email set in the task cache
# email_in_task_cache: true
# email_task_cache: true
# Or sends to an arbitrary admin email
# email_additional_addresses:
# - admin@example.org