Skip to content

Commit 376c526

Browse files
authored
Merge pull request #11318 from CenterForOpenScience/revert-11151-add-new-notifications-data-model
Revert "[ENG-8064] Add New Notifications Data Model (Refactor Notifications Phase 2)"
2 parents a179750 + 4c35e47 commit 376c526

File tree

391 files changed

+14711
-13867
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

391 files changed

+14711
-13867
lines changed

addons/base/views.py

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from framework.flask import redirect
3535
from framework.sentry import log_exception
3636
from framework.transactions.handlers import no_auto_transaction
37+
from website import mails
3738
from website import settings
3839
from addons.base import signals as file_signals
3940
from addons.base.utils import format_last_known_metadata, get_mfr_url
@@ -51,7 +52,7 @@
5152
DraftRegistration,
5253
Guid,
5354
FileVersionUserMetadata,
54-
FileVersion, NotificationType
55+
FileVersion
5556
)
5657
from osf.metrics import PreprintView, PreprintDownload
5758
from osf.utils import permissions
@@ -63,7 +64,7 @@
6364
from website.util import rubeus
6465

6566
# import so that associated listener is instantiated and gets emails
66-
from notifications.file_event_notifications import FileEvent # noqa
67+
from website.notifications.events.files import FileEvent # noqa
6768

6869
ERROR_MESSAGES = {'FILE_GONE': """
6970
<style>
@@ -225,6 +226,8 @@ def get_auth(auth, **kwargs):
225226
_check_resource_permissions(resource, auth, action)
226227

227228
provider_name = waterbutler_data['provider']
229+
waterbutler_settings = None
230+
waterbutler_credentials = None
228231
file_version = file_node = None
229232
if provider_name == 'osfstorage' or (not flag_is_active(request, features.ENABLE_GV)):
230233
file_version, file_node = _get_osfstorage_file_version_and_node(
@@ -573,31 +576,20 @@ def create_waterbutler_log(payload, **kwargs):
573576
params=payload
574577
)
575578

576-
if payload.get('email') or payload.get('errors'):
577-
if payload.get('email'):
578-
notification_type = NotificationType.Type.USER_FILE_OPERATION_SUCCESS.instance
579-
if payload.get('errors'):
580-
notification_type = NotificationType.Type.USER_FILE_OPERATION_FAILED.instance
581-
notification_type.emit(
582-
user=user,
583-
subscribed_object=node,
584-
event_context={
585-
'user_fullname': user.fullname,
586-
'action': payload['action'],
587-
'source_node': source_node._id,
588-
'source_node_title': source_node.title,
589-
'destination_node': destination_node._id,
590-
'destination_node_title': destination_node.title,
591-
'destination_node_parent_node_title': destination_node.parent_node.title if destination_node.parent_node else None,
592-
'source_path': payload['source']['materialized'],
593-
'source_addon': payload['source']['addon'],
594-
'destination_addon': payload['destination']['addon'],
595-
'osf_support_email': settings.OSF_SUPPORT_EMAIL,
596-
'logo': settings.OSF_LOGO,
597-
'OSF_LOGO_LIST': settings.OSF_LOGO_LIST,
598-
'OSF_LOGO': settings.OSF_LOGO,
599-
}
579+
if payload.get('email') is True or payload.get('errors'):
580+
mails.send_mail(
581+
user.username,
582+
mails.FILE_OPERATION_FAILED if payload.get('errors')
583+
else mails.FILE_OPERATION_SUCCESS,
584+
action=payload['action'],
585+
source_node=source_node,
586+
destination_node=destination_node,
587+
source_path=payload['source']['materialized'],
588+
source_addon=payload['source']['addon'],
589+
destination_addon=payload['destination']['addon'],
590+
osf_support_email=settings.OSF_SUPPORT_EMAIL
600591
)
592+
601593
if payload.get('errors'):
602594
# Action failed but our function succeeded
603595
# Bail out to avoid file_signals
@@ -611,8 +603,10 @@ def create_waterbutler_log(payload, **kwargs):
611603
target_node = AbstractNode.load(metadata.get('nid'))
612604
if target_node and payload['action'] != 'download_file':
613605
update_storage_usage_with_size(payload)
606+
614607
with transaction.atomic():
615608
file_signals.file_updated.send(target=node, user=user, event_type=action, payload=payload)
609+
616610
return {'status': 'success'}
617611

618612

addons/boa/tasks.py

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
from addons.boa.boa_error_code import BoaErrorCode
1515
from framework import sentry
1616
from framework.celery_tasks import app as celery_app
17-
from osf.models import OSFUser, NotificationType
17+
from osf.models import OSFUser
1818
from osf.utils.fields import ensure_str, ensure_bytes
1919
from website import settings as osf_settings
20+
from website.mails import send_mail, ADDONS_BOA_JOB_COMPLETE, ADDONS_BOA_JOB_FAILURE
2021

2122
logger = logging.getLogger(__name__)
2223

@@ -183,19 +184,18 @@ async def submit_to_boa_async(host, username, password, user_guid, project_guid,
183184

184185
logger.info('Successfully uploaded query output to OSF.')
185186
logger.debug('Task ends <<<<<<<<')
186-
NotificationType.Type.ADDONS_BOA_JOB_COMPLETE.instance.emit(
187-
user=user,
188-
event_context={
189-
'fullname': user.fullname,
190-
'query_file_name': query_file_name,
191-
'query_file_full_path': file_full_path,
192-
'output_file_name': output_file_name,
193-
'job_id': boa_job.id,
194-
'project_url': project_url,
195-
'boa_job_list_url': boa_settings.BOA_JOB_LIST_URL,
196-
'boa_support_email': boa_settings.BOA_SUPPORT_EMAIL,
197-
'osf_support_email': osf_settings.OSF_SUPPORT_EMAIL,
198-
}
187+
await sync_to_async(send_mail)(
188+
to_addr=user.username,
189+
mail=ADDONS_BOA_JOB_COMPLETE,
190+
fullname=user.fullname,
191+
query_file_name=query_file_name,
192+
query_file_full_path=file_full_path,
193+
output_file_name=output_file_name,
194+
job_id=boa_job.id,
195+
project_url=project_url,
196+
boa_job_list_url=boa_settings.BOA_JOB_LIST_URL,
197+
boa_support_email=boa_settings.BOA_SUPPORT_EMAIL,
198+
osf_support_email=osf_settings.OSF_SUPPORT_EMAIL,
199199
)
200200
return BoaErrorCode.NO_ERROR
201201

@@ -209,24 +209,22 @@ def handle_boa_error(message, code, username, fullname, project_url, query_file_
209209
sentry.log_message(message, skip_session=True)
210210
except Exception:
211211
pass
212-
NotificationType.Type.ADDONS_BOA_JOB_FAILURE.instance.emit(
213-
destination_address=username,
214-
event_context={
215-
'user_fullname': fullname,
216-
'code': code,
217-
'query_file_name': query_file_name,
218-
'file_size': file_size,
219-
'message': message,
220-
'max_file_size': boa_settings.MAX_SUBMISSION_SIZE,
221-
'query_file_full_path': query_file_full_path,
222-
'output_file_name': output_file_name,
223-
'job_id': job_id,
224-
'max_job_wait_hours': boa_settings.MAX_JOB_WAITING_TIME / 3600,
225-
'project_url': project_url,
226-
'boa_job_list_url': boa_settings.BOA_JOB_LIST_URL,
227-
'boa_support_email': boa_settings.BOA_SUPPORT_EMAIL,
228-
'osf_support_email': osf_settings.OSF_SUPPORT_EMAIL,
229-
230-
}
212+
send_mail(
213+
to_addr=username,
214+
mail=ADDONS_BOA_JOB_FAILURE,
215+
fullname=fullname,
216+
code=code,
217+
message=message,
218+
query_file_name=query_file_name,
219+
file_size=file_size,
220+
max_file_size=boa_settings.MAX_SUBMISSION_SIZE,
221+
query_file_full_path=query_file_full_path,
222+
output_file_name=output_file_name,
223+
job_id=job_id,
224+
max_job_wait_hours=boa_settings.MAX_JOB_WAITING_TIME / 3600,
225+
project_url=project_url,
226+
boa_job_list_url=boa_settings.BOA_JOB_LIST_URL,
227+
boa_support_email=boa_settings.BOA_SUPPORT_EMAIL,
228+
osf_support_email=osf_settings.OSF_SUPPORT_EMAIL,
231229
)
232230
return code

addons/boa/tests/test_tasks.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99
from addons.boa import settings as boa_settings
1010
from addons.boa.boa_error_code import BoaErrorCode
1111
from addons.boa.tasks import submit_to_boa, submit_to_boa_async, handle_boa_error
12-
from osf.models import NotificationType
1312
from osf_tests.factories import AuthUserFactory, ProjectFactory
1413
from tests.base import OsfTestCase
15-
from tests.utils import capture_notifications
1614
from website import settings as osf_settings
15+
from website.mails import ADDONS_BOA_JOB_COMPLETE, ADDONS_BOA_JOB_FAILURE
1716

1817
DEFAULT_REFRESH_JOB_INTERVAL = boa_settings.REFRESH_JOB_INTERVAL
1918
DEFAULT_MAX_JOB_WAITING_TIME = boa_settings.MAX_JOB_WAITING_TIME
@@ -39,6 +38,9 @@ def setUp(self):
3938
self.output_file_name = 'fake_boa_script_results.txt'
4039
self.job_id = '1a2b3c4d5e6f7g8'
4140

41+
from conftest import start_mock_send_grid
42+
self.mock_send_grid = start_mock_send_grid(self)
43+
4244
def tearDown(self):
4345
super().tearDown()
4446

@@ -53,26 +55,27 @@ def test_boa_error_code(self):
5355
assert BoaErrorCode.FILE_TOO_LARGE_ERROR == 6
5456
assert BoaErrorCode.JOB_TIME_OUT_ERROR == 7
5557

58+
@mock.patch('website.mails.settings.USE_EMAIL', True)
59+
@mock.patch('website.mails.settings.USE_CELERY', False)
5660
def test_handle_boa_error(self):
57-
with mock.patch('addons.boa.tasks.sentry.log_message', return_value=None) as mock_sentry_log_message:
58-
with mock.patch('addons.boa.tasks.logger.error', return_value=None) as mock_logger_error:
59-
with capture_notifications() as notifications:
60-
return_value = handle_boa_error(
61-
self.error_message,
62-
BoaErrorCode.UNKNOWN,
63-
self.user_username,
64-
self.user_fullname,
65-
self.project_url,
66-
self.file_full_path,
67-
file_size=self.file_size,
68-
output_file_name=self.output_file_name,
69-
job_id=self.job_id
70-
)
71-
assert len(notifications['emits']) == 1
72-
assert notifications['emits'][0]['type'] == NotificationType.Type.ADDONS_BOA_JOB_FAILURE
73-
mock_sentry_log_message.assert_called_with(self.error_message, skip_session=True)
74-
mock_logger_error.assert_called_with(self.error_message)
75-
assert return_value == BoaErrorCode.UNKNOWN
61+
with mock.patch('addons.boa.tasks.sentry.log_message', return_value=None) as mock_sentry_log_message, \
62+
mock.patch('addons.boa.tasks.logger.error', return_value=None) as mock_logger_error:
63+
return_value = handle_boa_error(
64+
self.error_message,
65+
BoaErrorCode.UNKNOWN,
66+
self.user_username,
67+
self.user_fullname,
68+
self.project_url,
69+
self.file_full_path,
70+
query_file_name=self.query_file_name,
71+
file_size=self.file_size,
72+
output_file_name=self.output_file_name,
73+
job_id=self.job_id
74+
)
75+
self.mock_send_grid.assert_called()
76+
mock_sentry_log_message.assert_called_with(self.error_message, skip_session=True)
77+
mock_logger_error.assert_called_with(self.error_message)
78+
assert return_value == BoaErrorCode.UNKNOWN
7679

7780

7881
class TestSubmitToBoa(OsfTestCase):
@@ -151,6 +154,14 @@ def setUp(self):
151154
boa_settings.REFRESH_JOB_INTERVAL = DEFAULT_REFRESH_JOB_INTERVAL
152155
boa_settings.MAX_JOB_WAITING_TIME = DEFAULT_MAX_JOB_WAITING_TIME
153156

157+
from conftest import start_mock_send_grid
158+
self.mock_send_grid = start_mock_send_grid(self)
159+
160+
def tearDown(self):
161+
super().tearDown()
162+
163+
@mock.patch('website.mails.settings.USE_EMAIL', True)
164+
@mock.patch('website.mails.settings.USE_CELERY', False)
154165
async def test_submit_success(self):
155166
with mock.patch('osf.models.user.OSFUser.objects.get', return_value=self.user), \
156167
mock.patch('osf.models.user.OSFUser.get_or_create_cookie', return_value=self.user_cookie), \
@@ -179,6 +190,7 @@ async def test_submit_success(self):
179190
assert self.mock_job.refresh.call_count == 4
180191
assert mock_async_sleep.call_count == 4
181192
mock_close.assert_called()
193+
self.mock_send_grid.assert_called()
182194
mock_handle_boa_error.assert_not_called()
183195

184196
async def test_download_error(self):

addons/osfstorage/tests/test_models.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
from osf import models
2525
from addons.osfstorage import utils
2626
from addons.osfstorage import settings
27-
from tests.utils import capture_notifications
2827
from website.files.exceptions import FileNodeCheckedOutError, FileNodeIsPrimaryFile
2928

3029
SessionStore = import_module(django_conf_settings.SESSION_ENGINE).SessionStore
@@ -746,8 +745,7 @@ def test_after_fork_copies_versions(self, node, node_settings, auth_obj):
746745
version = factories.FileVersionFactory()
747746
record.add_version(version)
748747

749-
with capture_notifications():
750-
fork = node.fork_node(auth_obj)
748+
fork = node.fork_node(auth_obj)
751749
fork_node_settings = fork.get_addon('osfstorage')
752750
fork_node_settings.reload()
753751

@@ -759,8 +757,7 @@ def test_fork_reverts_to_node_storage_region(self, user2, region, region2, node,
759757
"""
760758
Despite different user regions defaults, the forked node always stay in the same region as it's orginal node.
761759
"""
762-
with capture_notifications():
763-
fork = node.fork_node(Auth(user2))
760+
fork = node.fork_node(Auth(user2))
764761
assert fork.get_addon('osfstorage').region_id == region.id
765762

766763
# don't inherit or override region

addons/wiki/tests/test_wiki.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
from framework.auth import Auth
3030
from django.utils import timezone
3131
from addons.wiki.utils import to_mongo_key
32-
from tests.utils import capture_notifications
3332

3433
from .config import EXAMPLE_DOCS, EXAMPLE_OPS
3534

@@ -819,8 +818,7 @@ def test_uuids_differ_between_forks(self):
819818
assert project_res.status_code == 200
820819
self.project.reload()
821820

822-
with capture_notifications():
823-
fork = self.project.fork_node(Auth(self.user))
821+
fork = self.project.fork_node(Auth(self.user))
824822
assert fork.is_fork_of(self.project)
825823
fork_url = fork.web_url_for('project_wiki_view', wname=self.wname)
826824
fork_res = self.app.get(fork_url, auth=self.user.auth)
@@ -1086,8 +1084,7 @@ def test_get_sharejs_uuid(self):
10861084
# Differs across projects and forks
10871085
project = ProjectFactory()
10881086
assert sharejs_uuid != get_sharejs_uuid(project, wname)
1089-
with capture_notifications():
1090-
fork = self.project.fork_node(Auth(self.project.creator))
1087+
fork = self.project.fork_node(Auth(self.project.creator))
10911088
assert sharejs_uuid != get_sharejs_uuid(fork, wname)
10921089

10931090
def test_generate_share_uuid(self):

admin/common_auth/views.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from django.contrib.auth import login, REDIRECT_FIELD_NAME, authenticate, logout
1111

1212
from osf.models.user import OSFUser
13-
from osf.models import AdminProfile
13+
from osf.models import AdminProfile, AbstractProvider
1414
from admin.common_auth.forms import LoginForm, UserRegistrationForm, DeskUserForm
1515

1616

@@ -69,6 +69,16 @@ def form_valid(self, form):
6969

7070
# create AdminProfile for this new user
7171
profile, created = AdminProfile.objects.get_or_create(user=osf_user)
72+
73+
for group in form.cleaned_data.get('group_perms'):
74+
osf_user.groups.add(group)
75+
split = group.name.split('_')
76+
group_type = split[0]
77+
if group_type == 'reviews':
78+
provider_id = split[2]
79+
provider = AbstractProvider.objects.get(id=provider_id)
80+
provider.notification_subscriptions.get(event_name='new_pending_submissions').add_user_to_subscription(osf_user, 'email_transactional')
81+
7282
osf_user.save()
7383

7484
if created:

admin/nodes/views.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from admin.base.utils import change_embargo_date
2222
from admin.base.views import GuidView
2323
from admin.base.forms import GuidForm
24-
from admin.notifications.views import delete_selected_notifications
24+
from admin.notifications.views import detect_duplicate_notifications, delete_selected_notifications
2525

2626
from api.share.utils import update_share
2727
from api.caching.tasks import update_storage_usage_cache
@@ -100,6 +100,7 @@ def get_context_data(self, **kwargs):
100100
context = super().get_context_data(**kwargs)
101101
node = self.get_object()
102102

103+
detailed_duplicates = detect_duplicate_notifications(node_id=node.id)
103104
children = node.get_nodes(is_node_link=False)
104105
# Annotate guid because django templates prohibit accessing attributes that start with underscores
105106
children = AbstractNode.objects.filter(
@@ -110,6 +111,7 @@ def get_context_data(self, **kwargs):
110111
'STORAGE_LIMITS': settings.StorageLimits,
111112
'node': node,
112113
'children': children,
114+
'duplicates': detailed_duplicates
113115
})
114116

115117
return context

0 commit comments

Comments
 (0)