Skip to content

Commit 31048c7

Browse files
Ostap-Zherebetskyicslzchenbodintsov
authored
[ENG-10538] Post-NR Project PR (#11623)
* Create global_file_updated and global_reviews subscriptions if missing * Use USER_FILE_UPDATED for group global_file_updated * Use REVIEWS_SUBMISSION_STATUS for group global_reviews * Add missing `is_digest=True` for new OSF user subscriptions * Extend otf subscription creation to apply to _node_file_updated group * Fix typo for `_is_digest` * add is_digest_type property * Add is_digest_type property to NotificationType and log message in emit method * Fix is_digest handling in NotificationType.emit method * Log message update in NotificationType.emit method for is_digest handling * fix unit tests * Move set-deafult-subscriptions out of non-effective try-except * Add fake_sent field to Notification model and update notification creation logic * add unique_together constraint * Add 'PARTIAL_SUCCESS' status to EmailTask model and update email task handling logic * NR migration [ENG-10040, ENG-10025, ENG-9854] * Remove subscription if notifications.tasks.send_moderator_email_task fails with permission error * Apply suggestion from @Ostap-Zherebetskyi * remove datetime * Add 'no_login_email_last_sent' field to OSFUser and update email task logic * Enforce and improve permission check for subscriptions * Fix typo in annotated_obj_qs for NODE_FILE_UPDATED * Add unit tests for testing node_file_updated subscription detail * Implement notifications cleanup task and related settings; add tests for functionality * Fix legacy subscription ID for NODE_FILE_UPDATED: "guid_files_updated" * Fix duplicate and mismatched type NODE_FILE(S)_UPDATED * removed email.py * Fix annotated qs for global reviews and update unit tests * Update tests for node_file(s)_updated subscription detail * Rename fixtures for notification subscription detail tests * Annotate with legacy_id for serializer to handle created subscriptions * Add unit tests for creating missing subscriptions on the fly * clear useless code * Rename migration name for NR post-release * Improve unit test: test_emit_frequency_none * Remove `seen` from `Notification` and re-make migrations * `mark_sent()` now handles `fake_sent=True`, and only `save()` once * Update default settings * remove useless import * Enhance SubscriptionList queryset with additional content types and refactor notification type handling * fix unit test * Refactor SubscriptionList queryset to use a single provider content type and update related notification handling; add script to update notification subscriptions' content types. * fix CR comments * Update comments * split into 3 files * remove populate_notification_subscriptions * Renamed files, refactor of populate notification subscriptions user global file updated * added try/except, added timers * converted populate_notification_subscriptions_user_global_reviews.py * fix batch time execution * converted populate_notification_subscriptions_node_file_updated * convert to separate update and create scripts * updated, added parameters * move to remove_after_use * add time track to last batch, fix proper time track for batch in node_file_updated * convert to use review_nt * Fix unit tests due to new constraints * Move missing subscription creation to a helper function in utils * Subscription list view now creates missing attributes on-the-fly * Note: only works for when filter on "legacy id"; logs message to sentry for tracking purpose when filter on "event names". * Fix broken `.exists()` due to complex annotated QS with `.distinct()` * fix names of tasks * Add notification subscriptions de-duplication v2 command * fix naming * Add deduplication command to notification migration * Fix notification handling by updating legacy ID suffix from '_files_updated' to '_file_updated' across utils and views; adjust related test cases accordingly. * fix unit tests * Update the name of the NotificationType NODE_FILE_UPDATED to be consistent * Rename notification type from node_files_updated to node_file_updated for consistency * clean keys * fix naming in templates, event_context * remove leftover comments * Refactor notification type references to use NotificationTypeEnum - Updated all instances of NotificationType.Type to NotificationTypeEnum in test files and application code. - Ensured consistency in notification type usage across various tests including auth, claims, events, and more. - This change improves clarity and maintainability by standardizing the notification type references. * Fix notification type reference for FILE_UPDATED * Refactor notification type references to use NotificationTypeEnum across views and scripts * fix unit tests * remove imports * fix USER_CROSSREF_DOI_PENDING event_context * sync naming * added explanation * Add Celery task to disable removed beat tasks from PeriodicTask entries * Apply suggestion from @Ostap-Zherebetskyi * Apply suggestion from @cslzchen * Add migrations to remove duplicate notification subscriptions and refactor notification model * removed comment * Refactor no-login email filtering to ensure last sent date is before last login date * Add test to exclude users logged in before no_login_email_last_sent * Refactor no-login email user filtering to exclude those with pending EmailTasks and recent no-login emails * Fix CollectionSubmission URLs to use absolute_url method for consistency * Refactor logo handling in notification methods to improve consistency and readability * Add management command to sync notification templates * Apply suggestion from @cslzchen * Add management command for deleting withdrawn or failed registration files to CeleryConfig * fix: update logo handling in send_moderator_email_task for favicon support --------- Co-authored-by: Longze Chen <cslzchen@gmail.com> Co-authored-by: Ostap Zherebetskyi <ozherebetskyi@exoft.net> Co-authored-by: Bohdan Odintsov <bodintsov@exoft.net>
1 parent afbbdae commit 31048c7

147 files changed

Lines changed: 2235 additions & 2770 deletions

File tree

Some content is hidden

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

addons/base/views.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
DraftRegistration,
5252
Guid,
5353
FileVersionUserMetadata,
54-
FileVersion, NotificationType
54+
FileVersion, NotificationTypeEnum
5555
)
5656
from osf.metrics import PreprintView, PreprintDownload
5757
from osf.utils import permissions
@@ -575,14 +575,13 @@ def create_waterbutler_log(payload, **kwargs):
575575

576576
if payload.get('email') or payload.get('errors'):
577577
if payload.get('email'):
578-
notification_type = NotificationType.Type.USER_FILE_OPERATION_SUCCESS.instance
578+
notification_type = NotificationTypeEnum.USER_FILE_OPERATION_SUCCESS.instance
579579
if payload.get('errors'):
580-
notification_type = NotificationType.Type.USER_FILE_OPERATION_FAILED.instance
580+
notification_type = NotificationTypeEnum.USER_FILE_OPERATION_FAILED.instance
581581
notification_type.emit(
582582
user=user,
583583
subscribed_object=node,
584584
event_context={
585-
'user_fullname': user.fullname,
586585
'action': payload['action'],
587586
'source_node': source_node._id,
588587
'source_node_title': source_node.title,

addons/boa/tasks.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
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, NotificationTypeEnum
1818
from osf.utils.fields import ensure_str, ensure_bytes
1919
from website import settings as osf_settings
2020

@@ -183,18 +183,15 @@ async def submit_to_boa_async(host, username, password, user_guid, project_guid,
183183

184184
logger.info('Successfully uploaded query output to OSF.')
185185
logger.debug('Task ends <<<<<<<<')
186-
NotificationType.Type.ADDONS_BOA_JOB_COMPLETE.instance.emit(
186+
NotificationTypeEnum.ADDONS_BOA_JOB_COMPLETE.instance.emit(
187187
user=user,
188188
event_context={
189189
'user_fullname': user.fullname,
190-
'query_file_name': query_file_name,
191190
'query_file_full_path': file_full_path,
192191
'output_file_name': output_file_name,
193192
'job_id': boa_job.id,
194193
'project_url': project_url,
195194
'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,
198195
}
199196
)
200197
return BoaErrorCode.NO_ERROR
@@ -209,12 +206,11 @@ def handle_boa_error(message, code, username, fullname, project_url, query_file_
209206
sentry.log_message(message, skip_session=True)
210207
except Exception:
211208
pass
212-
NotificationType.Type.ADDONS_BOA_JOB_FAILURE.instance.emit(
209+
NotificationTypeEnum.ADDONS_BOA_JOB_FAILURE.instance.emit(
213210
destination_address=username,
214211
event_context={
215212
'user_fullname': fullname,
216213
'code': code,
217-
'query_file_name': query_file_name,
218214
'file_size': file_size,
219215
'message': message,
220216
'max_file_size': boa_settings.MAX_SUBMISSION_SIZE,

addons/boa/tests/test_tasks.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
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
12+
from osf.models import NotificationTypeEnum
1313
from osf_tests.factories import AuthUserFactory, ProjectFactory
1414
from tests.base import OsfTestCase
1515
from tests.utils import capture_notifications
@@ -66,7 +66,7 @@ def test_handle_boa_error(self):
6666
job_id=self.job_id
6767
)
6868
assert len(notifications['emits']) == 1
69-
assert notifications['emits'][0]['type'] == NotificationType.Type.ADDONS_BOA_JOB_FAILURE
69+
assert notifications['emits'][0]['type'] == NotificationTypeEnum.ADDONS_BOA_JOB_FAILURE
7070
mock_sentry_log_message.assert_called_with(self.error_message, skip_session=True)
7171
mock_logger_error.assert_called_with(self.error_message)
7272
assert return_value == BoaErrorCode.UNKNOWN

addons/osfstorage/tests/test_models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from framework.auth import Auth
1111
from addons.osfstorage.models import OsfStorageFile, OsfStorageFileNode, OsfStorageFolder
12-
from osf.models import BaseFileNode, NotificationType
12+
from osf.models import BaseFileNode, NotificationTypeEnum
1313
from osf.exceptions import ValidationError
1414
from osf.utils.permissions import WRITE, ADMIN
1515

@@ -750,7 +750,7 @@ def test_after_fork_copies_versions(self, node, node_settings, auth_obj):
750750
fork = node.fork_node(auth_obj)
751751

752752
assert len(notifications['emits']) == 1
753-
assert notifications['emits'][0]['type'] == NotificationType.Type.NODE_CONTRIBUTOR_ADDED_DEFAULT
753+
assert notifications['emits'][0]['type'] == NotificationTypeEnum.NODE_CONTRIBUTOR_ADDED_DEFAULT
754754
fork_node_settings = fork.get_addon('osfstorage')
755755
fork_node_settings.reload()
756756

admin/management/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@
1717
re_path(r'^ingest_cedar_metadata_templates', views.IngestCedarMetadataTemplates.as_view(), name='ingest_cedar_metadata_templates'),
1818
re_path(r'^bulk_resync', views.BulkResync.as_view(), name='bulk-resync'),
1919
re_path(r'^empty_metadata_dataarchive_registration_bulk_resync', views.EmptyMetadataDataarchiveRegistrationBulkResync.as_view(),
20-
name='empty-metadata-dataarchive-registration-bulk-resync')
20+
name='empty-metadata-dataarchive-registration-bulk-resync'),
21+
re_path(r'^sync_notification_templates', views.SyncNotificationTemplates.as_view(),
22+
name='sync_notification_templates')
2123
]

admin/management/views.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from osf.management.commands.monthly_reporters_go import monthly_reporters_go
1212
from osf.management.commands.fetch_cedar_metadata_templates import ingest_cedar_metadata_templates
1313
from osf.management.commands.sync_doi_metadata import sync_doi_metadata, sync_doi_empty_metadata_dataarchive_registrations
14+
from osf.management.commands.populate_notification_types import populate_notification_types
1415
from scripts.find_spammy_content import manage_spammy_content
1516
from django.urls import reverse
1617
from django.shortcuts import redirect
@@ -172,3 +173,11 @@ def post(self, request):
172173
})
173174
messages.success(request, 'Resyncing with DataCite! It will take some time.')
174175
return redirect(reverse('management:commands'))
176+
177+
178+
class SyncNotificationTemplates(ManagementCommandPermissionView):
179+
180+
def post(self, request):
181+
populate_notification_types()
182+
messages.success(request, 'Notification templates have been successfully synced.')
183+
return redirect(reverse('management:commands'))

admin/providers/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django.shortcuts import redirect
22
from django.views.generic import TemplateView
33
from django.contrib import messages
4-
from osf.models import RegistrationProvider, OSFUser, CollectionProvider, NotificationType
4+
from osf.models import RegistrationProvider, OSFUser, CollectionProvider, NotificationTypeEnum
55
from website.settings import DOMAIN
66

77

@@ -63,7 +63,7 @@ def post(self, request, *args, **kwargs):
6363

6464
context['provider_url'] = f'{provider.domain or DOMAIN}{provider_type_word}/{(provider._id if not provider.domain else '').strip('/')}'
6565
messages.success(request, f'The following {target_type} was successfully added: {target_user.fullname} ({target_user.username})')
66-
notification_type = NotificationType.Type.PROVIDER_MODERATOR_ADDED
66+
notification_type = NotificationTypeEnum.PROVIDER_MODERATOR_ADDED
6767
notification_type.instance.emit(
6868
user=target_user,
6969
event_context=context,

admin/templates/management/commands.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,19 @@ <h4><u>Resync empty metadata dataarchive registrations with DataCite</u></h4>
152152
</nav>
153153
</form>
154154
</section>
155+
<section>
156+
<h4><u>Sync Notification Templates</u></h4>
157+
<p>
158+
Use this management command to sync notification templates. Warning: existing templates modifications via django admin will be overridden if they haven't been updated in code. In addition, templates are cached for 2 hours so changes won't be effective immediately.
159+
</p>
160+
<form method="post"
161+
action="{% url 'management:sync_notification_templates'%}">
162+
{% csrf_token %}
163+
<nav>
164+
<input class="btn btn-success" type="submit" value="Run" />
165+
</nav>
166+
</form>
167+
</section>
155168
</div>
156169
</section>
157170
{% endblock %}

admin/users/views.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from osf.models.base import Guid
2121
from osf.models.user import OSFUser
2222
from osf.models.spam import SpamStatus
23-
from osf.models.notification_type import NotificationType
23+
from osf.models.notification_type import NotificationTypeEnum
2424
from framework.auth import get_user
2525
from framework.auth.core import generate_verification_key
2626

@@ -184,12 +184,11 @@ def post(self, request, *args, **kwargs):
184184
message=f'User account {user.pk} disabled',
185185
action_flag=USER_REMOVED
186186
)
187-
NotificationType.Type.USER_REQUEST_DEACTIVATION_COMPLETE.instance.emit(
187+
NotificationTypeEnum.USER_REQUEST_DEACTIVATION_COMPLETE.instance.emit(
188188
user=user,
189189
event_context={
190190
'user_fullname': user.fullname,
191191
'contact_email': OSF_SUPPORT_EMAIL,
192-
'can_change_preferences': False,
193192
}
194193
)
195194
else:

admin_tests/preprints/test_views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from django.contrib.messages.storage.fallback import FallbackStorage
99

1010
from tests.base import AdminTestCase
11-
from osf.models import Preprint, PreprintLog, PreprintRequest, NotificationType
11+
from osf.models import Preprint, PreprintLog, PreprintRequest, NotificationTypeEnum
1212
from framework.auth import Auth
1313
from osf_tests.factories import (
1414
AuthUserFactory,
@@ -719,7 +719,7 @@ def test_can_unwithdraw_preprint_without_moderation_workflow(self, withdrawal_re
719719
machine_state=DefaultStates.INITIAL.value)
720720
withdrawal_request.run_submit(admin)
721721

722-
with assert_notification(type=NotificationType.Type.PREPRINT_REQUEST_WITHDRAWAL_APPROVED):
722+
with assert_notification(type=NotificationTypeEnum.PREPRINT_REQUEST_WITHDRAWAL_APPROVED):
723723
withdrawal_request.run_accept(admin, withdrawal_request.comment)
724724

725725
assert preprint.machine_state == 'withdrawn'

0 commit comments

Comments
 (0)