Skip to content

Commit

Permalink
add notify_email_irods_request setting (#1939)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Sep 13, 2024
1 parent 237d7da commit 7032cb2
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Added
- REST API list view pagination (#1994)
- **Samplesheets**
- REST API list view pagination (#1994)
- ``notify_email_irods_request`` user app setting (#1939)

Changed
-------
Expand Down
39 changes: 25 additions & 14 deletions samplesheets/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
PROJECT_TYPE_PROJECT = SODAR_CONSTANTS['PROJECT_TYPE_PROJECT']
PROJECT_ACTION_CREATE = SODAR_CONSTANTS['PROJECT_ACTION_CREATE']
PROJECT_ACTION_UPDATE = SODAR_CONSTANTS['PROJECT_ACTION_UPDATE']
APP_SETTING_SCOPE_PROJECT = SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT']
APP_SETTING_SCOPE_USER = SODAR_CONSTANTS['APP_SETTING_SCOPE_USER']

# Local constants
SHEETS_INFO_SETTINGS = [
Expand Down Expand Up @@ -113,7 +115,7 @@ class ProjectAppPlugin(
#: App settings definition
app_settings = {
'allow_editing': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'BOOLEAN',
'label': 'Allow sample sheet editing',
'description': 'Allow editing of project sample sheets by '
Expand All @@ -122,29 +124,29 @@ class ProjectAppPlugin(
'default': True,
},
'display_config': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT_USER'],
'scope': APP_SETTING_SCOPE_USER,
'type': 'JSON',
'label': 'Sample sheet display configuration',
'description': 'User specific JSON configuration for column '
'display in project sample sheets',
},
'display_config_default': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'JSON',
'label': 'Default sample sheet display configuration',
'description': 'Default JSON configuration for column display in '
'project sample sheets',
'user_modifiable': False,
},
'sheet_config': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'JSON',
'label': 'Sample sheet editing configuration',
'description': 'JSON configuration for sample sheet editing',
'user_modifiable': False,
},
'edit_config_min_role': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'STRING',
'options': [
'superuser',
Expand All @@ -159,23 +161,23 @@ class ProjectAppPlugin(
'user_modifiable': True,
},
'sheet_sync_enable': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'BOOLEAN',
'default': False,
'label': 'Enable sheet synchronization',
'description': 'Enable sheet synchronization from a source project',
'user_modifiable': True,
},
'sheet_sync_url': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'STRING',
'label': 'URL for sheet synchronization',
'default': '',
'description': 'REST API URL for sheet synchronization',
'user_modifiable': True,
},
'sheet_sync_token': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'STRING',
'label': 'Token for sheet synchronization',
'default': '',
Expand All @@ -184,7 +186,7 @@ class ProjectAppPlugin(
'user_modifiable': True,
},
'sheet_table_height': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_USER'],
'scope': APP_SETTING_SCOPE_USER,
'type': 'INTEGER',
'label': 'Sample sheet table height',
'options': [250, 400, 600, 800],
Expand All @@ -194,7 +196,7 @@ class ProjectAppPlugin(
'user_modifiable': True,
},
'public_access_ticket': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'STRING',
'label': 'iRODS public access ticket',
'default': '',
Expand All @@ -203,7 +205,7 @@ class ProjectAppPlugin(
'user_modifiable': False,
},
'igv_genome': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'STRING',
'label': 'IGV session genome',
'default': IGV_DEFAULT_GENOME,
Expand All @@ -213,7 +215,7 @@ class ProjectAppPlugin(
'user_modifiable': True,
},
'igv_omit_bam': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'STRING',
'label': 'BAM and CRAM paths to omit from IGV sessions',
'default': ', '.join(settings.SHEETS_IGV_OMIT_BAM),
Expand All @@ -224,7 +226,7 @@ class ProjectAppPlugin(
'user_modifiable': True,
},
'igv_omit_vcf': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_PROJECT'],
'scope': APP_SETTING_SCOPE_PROJECT,
'type': 'STRING',
'label': 'VCF paths to omit from IGV sessions',
'default': ', '.join(settings.SHEETS_IGV_OMIT_VCF),
Expand All @@ -235,14 +237,23 @@ class ProjectAppPlugin(
'user_modifiable': True,
},
'template_output_dir_display': {
'scope': SODAR_CONSTANTS['APP_SETTING_SCOPE_USER'],
'scope': APP_SETTING_SCOPE_USER,
'type': 'BOOLEAN',
'label': 'Display template output directory field',
'default': False,
'description': 'Display output directory field for sample sheet '
'templates.',
'user_modifiable': True,
},
'notify_email_irods_request': {
'scope': APP_SETTING_SCOPE_USER,
'type': 'BOOLEAN',
'default': True,
'label': 'Receive email for iRODS data requests',
'description': 'Receive email notifications for iRODS data '
'request accepting and rejecting',
'user_modifiable': True,
},
}

#: Iconify icon
Expand Down
85 changes: 75 additions & 10 deletions samplesheets/tests/test_views_taskflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.conf import settings
from django.contrib import auth
from django.contrib.messages import get_messages
from django.core import mail
from django.forms.models import model_to_dict
from django.test import override_settings
from django.urls import reverse
Expand Down Expand Up @@ -1522,25 +1523,23 @@ def setUp(self):
def test_get(self):
"""Test IrodsDataRequestAcceptView GET"""
self.assert_irods_obj(self.obj_path)
self.make_irods_request(
request = self.make_irods_request(
project=self.project,
action=IRODS_REQUEST_ACTION_DELETE,
path=self.obj_path,
status=IRODS_REQUEST_STATUS_ACTIVE,
user=self.user_contributor,
)
self.assertEqual(IrodsDataRequest.objects.count(), 1)
obj = IrodsDataRequest.objects.first()

with self.login(self.user):
response = self.client.get(
reverse(
'samplesheets:irods_request_accept',
kwargs={'irodsdatarequest': obj.sodar_uuid},
kwargs={'irodsdatarequest': request.sodar_uuid},
),
{'confirm': True},
)
self.assertEqual(response.context['request_objects'][0], obj)
self.assertEqual(response.context['request_objects'][0], request)

def test_get_coll(self):
"""Test GET with collection request"""
Expand Down Expand Up @@ -1577,6 +1576,7 @@ def test_post(self):
self._assert_alert_count(EVENT_CREATE, self.user_delegate, 1)
self._assert_alert_count(EVENT_ACCEPT, self.user, 0)
self._assert_alert_count(EVENT_ACCEPT, self.user_delegate, 0)
mail_count = len(mail.outbox)

obj = IrodsDataRequest.objects.first()
with self.login(self.user):
Expand Down Expand Up @@ -1607,6 +1607,10 @@ def test_post(self):
self._assert_alert_count(EVENT_ACCEPT, self.user, 0)
self._assert_alert_count(EVENT_ACCEPT, self.user_delegate, 0)
self.assert_irods_obj(self.obj_path, False)
self.assertEqual(len(mail.outbox), mail_count + 1)
self.assertEqual(
mail.outbox[-1].recipients(), [self.user_contributor.email]
)

def test_post_no_request(self):
"""Test POST with non-existing delete request"""
Expand Down Expand Up @@ -1860,6 +1864,36 @@ def test_post_collection(self):
self.assertEqual(self.irods.collections.exists(coll_path), False)
self.assert_irods_obj(obj_path2, False)

def test_post_disable_email_notify(self):
"""Test POST wth disabled email notifications"""
app_settings.set(
APP_NAME,
'notify_email_irods_request',
False,
user=self.user_contributor,
)
self.assert_irods_obj(self.obj_path)
request = self.make_irods_request(
project=self.project,
action=IRODS_REQUEST_ACTION_DELETE,
path=self.obj_path,
status=IRODS_REQUEST_STATUS_ACTIVE,
user=self.user_contributor,
)
mail_count = len(mail.outbox)
with self.login(self.user):
self.client.post(
reverse(
'samplesheets:irods_request_accept',
kwargs={'irodsdatarequest': request.sodar_uuid},
),
{'confirm': True},
)
request.refresh_from_db()
self.assertEqual(request.status, IRODS_REQUEST_STATUS_ACCEPTED)
self.assert_irods_obj(self.obj_path, False)
self.assertEqual(len(mail.outbox), mail_count) # No new mail


class TestIrodsDataRequestAcceptBatchView(
IrodsDataRequestMixin, IrodsDataRequestViewTestBase
Expand Down Expand Up @@ -2154,8 +2188,8 @@ def setUp(self):
kwargs={'project': self.project.sodar_uuid},
)

def test_get_admin(self):
"""Test IrodsDataRequestRejectView GET as admin"""
def test_get_superuser(self):
"""Test IrodsDataRequestRejectView GET as superuser"""
self.assertEqual(IrodsDataRequest.objects.count(), 0)
self.assert_irods_obj(self.obj_path)
self._assert_alert_count(EVENT_REJECT, self.user, 0)
Expand All @@ -2168,6 +2202,7 @@ def test_get_admin(self):
status=IRODS_REQUEST_STATUS_ACTIVE,
user=self.user_contributor,
)
mail_count = len(mail.outbox)

with self.login(self.user):
response = self.client.get(
Expand Down Expand Up @@ -2196,10 +2231,13 @@ def test_get_admin(self):
self._assert_alert_count(EVENT_REJECT, self.user, 0)
self._assert_alert_count(EVENT_REJECT, self.user_delegate, 0)
self._assert_alert_count(EVENT_REJECT, self.user_contributor, 1)
self.assertEqual(len(mail.outbox), mail_count + 1)
self.assertEqual(
mail.outbox[-1].recipients(), [self.user_contributor.email]
)

def test_get_owner(self):
"""Test GET as owner"""
self.assertEqual(IrodsDataRequest.objects.count(), 0)
request = self.make_irods_request(
project=self.project,
action=IRODS_REQUEST_ACTION_DELETE,
Expand All @@ -2224,7 +2262,6 @@ def test_get_owner(self):

def test_get_delegate(self):
"""Test GET as delegate"""
self.assertEqual(IrodsDataRequest.objects.count(), 0)
request = self.make_irods_request(
project=self.project,
action=IRODS_REQUEST_ACTION_DELETE,
Expand All @@ -2249,7 +2286,6 @@ def test_get_delegate(self):

def test_get_contributor(self):
"""Test GET as contributor"""
self.assertEqual(IrodsDataRequest.objects.count(), 0)
request = self.make_irods_request(
project=self.project,
action=IRODS_REQUEST_ACTION_DELETE,
Expand Down Expand Up @@ -2329,6 +2365,35 @@ def test_get_no_request(self):
)
self.assertEqual(response.status_code, 404)

def test_get_disable_email_notify(self):
"""Test GET with disabled email notifications"""
app_settings.set(
APP_NAME,
'notify_email_irods_request',
False,
user=self.user_contributor,
)
self.assert_irods_obj(self.obj_path)
request = self.make_irods_request(
project=self.project,
action=IRODS_REQUEST_ACTION_DELETE,
path=self.obj_path,
status=IRODS_REQUEST_STATUS_ACTIVE,
user=self.user_contributor,
)
mail_count = len(mail.outbox)
with self.login(self.user):
self.client.get(
reverse(
'samplesheets:irods_request_reject',
kwargs={'irodsdatarequest': request.sodar_uuid},
),
)
request.refresh_from_db()
self.assertEqual(request.status, IRODS_REQUEST_STATUS_REJECTED)
self.assert_irods_obj(self.obj_path)
self.assertEqual(len(mail.outbox), mail_count)


class TestIrodsDataRequestRejectBatchView(
IrodsDataRequestMixin, IrodsDataRequestViewTestBase
Expand Down
6 changes: 6 additions & 0 deletions samplesheets/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,9 @@ def accept_request(
if (
settings.PROJECTROLES_SEND_EMAIL
and irods_request.user != request.user
and app_settings.get(
APP_NAME, 'notify_email_irods_request', user=irods_request.user
)
):
subject_body = 'iRODS delete request accepted'
message_body = EMAIL_DELETE_REQUEST_ACCEPT.format(
Expand Down Expand Up @@ -1068,6 +1071,9 @@ def reject_request(
if (
settings.PROJECTROLES_SEND_EMAIL
and irods_request.user != request.user
and app_settings.get(
APP_NAME, 'notify_email_irods_request', user=irods_request.user
)
):
subject_body = 'iRODS delete request rejected'
message_body = EMAIL_DELETE_REQUEST_REJECT.format(
Expand Down

0 comments on commit 7032cb2

Please sign in to comment.