Additional Tests for Notification, Token and Email
Change-Id: I57f1df7790fd258ea1b5b9365b15816872941b3a
This commit is contained in:
parent
1600a7bdf6
commit
5e16b575ad
@ -6,5 +6,7 @@ exclude_lines =
|
||||
if settings.DEBUG:
|
||||
raise AssertionError
|
||||
raise NotImplementedError
|
||||
self.fail
|
||||
omit =
|
||||
adjutant/wsgi.py
|
||||
setup.py
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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:
|
||||
|
237
adjutant/actions/v1/tests/test_misc_actions.py
Normal file
237
adjutant/actions/v1/tests/test_misc_actions.py
Normal 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)
|
@ -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.
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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'],
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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 = {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user