diff --git a/ckanext/ed/actions.py b/ckanext/ed/actions.py index f7a2766..5646d05 100644 --- a/ckanext/ed/actions.py +++ b/ckanext/ed/actions.py @@ -5,11 +5,15 @@ import zipfile from ckan.controllers.admin import get_sysadmins +from ckan.lib.mailer import MailerException +from ckan.logic.action.create import package_create as core_package_create from ckan.logic.action.get import package_search as core_package_search from ckan.logic.action.get import package_show as core_package_show from ckan.plugins import toolkit from ckanext.ed import helpers +from ckanext.ed.mailer import mail_package_publish_request_to_admins + SUPPORTED_RESOURCE_MIMETYPES = [ 'application/vnd.openxmlformats-officedocument.presentationml.presentation', @@ -161,3 +165,15 @@ def package_show(context, data_dict): if not can_edit and approval_pending: raise toolkit.ObjectNotFound return package + + +@toolkit.side_effect_free +def package_create(context, data_dict): + dataset_dict = core_package_create(context, data_dict) + if dataset_dict.get('approval_state') == 'approval_pending': + try: + mail_package_publish_request_to_admins(context, dataset_dict) + except MailerException: + message = '[email] Package Publishing request is not sent: {0}' + log.critical(message.format(data_dict.get('title'))) + return dataset_dict diff --git a/ckanext/ed/mailer.py b/ckanext/ed/mailer.py new file mode 100644 index 0000000..c60e719 --- /dev/null +++ b/ckanext/ed/mailer.py @@ -0,0 +1,42 @@ +import logging + +from ckan import model +from ckan.common import config +from ckan.plugins import toolkit +from ckan.lib.mailer import mail_user +from ckan.lib.base import render_jinja2 +from ckan.logic.action.get import member_list as core_member_list + +log = logging.getLogger(__name__) + + +def mail_package_publish_request_to_admins(context, data_dict): + members = core_member_list( + context=context, + data_dict={'id': data_dict.get('owner_org')} + ) + admin_ids = [i[0] for i in members if i[2] == 'Admin'] + for admin_id in admin_ids: + user = model.User.get(admin_id) + if user.email: + subj = _compose_email_subj(data_dict, event='request') + body = _compose_email_body(data_dict, user, event='request') + mail_user(user, subj, body) + log.debug('[email] Pakcage publishing request email sent to {0}'.format(user.name)) + + +def _compose_email_subj(data_dict, event='request'): + return '[US ED] Package Publishing {0}: {1}'.format(event.capitalize(), data_dict.get('title')) + + +def _compose_email_body(data_dict, user, event='request'): + pkg_link = toolkit.url_for('dataset_read', id=data_dict['name'], qualified=True) + return render_jinja2('emails/package_publish_{0}.txt'.format(event), { + 'admin_name': user.fullname or user.name, + 'site_title': config.get('ckan.site_title'), + 'site_url': config.get('ckan.site_url'), + 'package_title': data_dict.get('title'), + 'package_description': data_dict.get('notes', ''), + 'package_url': pkg_link, + 'publisher_name': data_dict.get('contact_name') + }) diff --git a/ckanext/ed/plugin.py b/ckanext/ed/plugin.py index d9512c4..77b25d9 100644 --- a/ckanext/ed/plugin.py +++ b/ckanext/ed/plugin.py @@ -27,6 +27,7 @@ def get_helpers(self): def get_actions(self): return { 'ed_prepare_zip_resources': actions.prepare_zip_resources, + 'package_create': actions.package_create, 'package_search': actions.package_search, 'package_show': actions.package_show } diff --git a/ckanext/ed/templates/emails/package_publish_request.txt b/ckanext/ed/templates/emails/package_publish_request.txt new file mode 100644 index 0000000..82dd5ac --- /dev/null +++ b/ckanext/ed/templates/emails/package_publish_request.txt @@ -0,0 +1,18 @@ +Dear {{ admin_name }}, + +A new package has been requested for publishing by {{ publisher_name }}: + + {{ package_title }} + + {{ package_description}} + +To approve or reject the request, please visit the following page (logged in as a office administrator): + + {{ package_url }} + +Have a nice day. + + +-- +Message sent by {{ site_title }} ({{ site_url }}) +This is an automated message, please don't respond to this address. diff --git a/ckanext/ed/tests/test_helpers.py b/ckanext/ed/tests/test_helpers.py index 1525ddb..02124ea 100644 --- a/ckanext/ed/tests/test_helpers.py +++ b/ckanext/ed/tests/test_helpers.py @@ -26,13 +26,16 @@ def test_get_recently_updated_datasets(self): def test_get_recently_updated_datasets_lists_only_approved(self): user = core_factories.User() - org = core_factories.Organization( + org_1 = core_factories.Organization( users=[{'name': user['name'], 'capacity': 'admin'}] ) - factories.Dataset(approval_state='approval_pending') - factories.Dataset(approval_state='approval_pending') - factories.Dataset(owner_org=org['id']) - dataset = factories.Dataset(owner_org=org['id']) + org_2 = core_factories.Organization( + users=[{'name': user['name'], 'capacity': 'admin'}] + ) + factories.Dataset(owner_org=org_2['id'], approval_state='approval_pending') + factories.Dataset(owner_org=org_2['id'], approval_state='approval_pending') + factories.Dataset(owner_org=org_1['id']) + dataset = factories.Dataset(owner_org=org_1['id']) result = helpers.get_recently_updated_datasets(user=user['name']) assert len(result) == 2, 'Epextec 2 but got %s' % len(result) diff --git a/ckanext/ed/tests/test_mailer.py b/ckanext/ed/tests/test_mailer.py new file mode 100644 index 0000000..5847a96 --- /dev/null +++ b/ckanext/ed/tests/test_mailer.py @@ -0,0 +1,51 @@ +import mock +from nose.tools import assert_raises, assert_equals + +from ckan import model +from ckan.tests import factories as core_factories +from ckan.tests import helpers as test_helpers +from ckanext.ed.tests import factories + +from ckanext.ed.mailer import mail_package_publish_request_to_admins + + +# Without jinja2 mocking it can't find a template in the test mode +class TestHelpers(test_helpers.FunctionalTestBase): + context = {'model': model, 'ignore_auth': True} + + @mock.patch('ckanext.ed.mailer.mail_user') + @mock.patch('ckanext.ed.mailer.render_jinja2') + def test_mail_package_publish_request_to_admins(self, mock_render_jinja2, mock_mail_user): + admin_1 = core_factories.User() + admin_2 = core_factories.User() + editor = core_factories.User() + office = core_factories.Organization( + users=[ + {'name': admin_1['name'], 'capacity': 'admin'}, + {'name': admin_2['name'], 'capacity': 'admin'}, + {'name': editor['name'], 'capacity': 'editor'}, + ], + name='us-ed', + id='us-ed' + ) + mail_package_publish_request_to_admins( + self.context, + _create_dataset_dict('test', office['name']) + ) + assert_equals(mock_mail_user.call_count, 2) + assert_equals(mock_render_jinja2.call_args[0][0], 'emails/package_publish_request.txt') + + +def _create_dataset_dict(package_name, office_name='us-ed'): + return { + 'name': package_name, + 'contact_name': 'Stu Shepard', + 'program_code': '321', + 'access_level': 'public', + 'bureau_code': '123', + 'contact_email': '%s@email.com' % package_name, + 'notes': 'notes', + 'owner_org': office_name, + 'title': 'Title', + 'identifier': 'identifier' + }