diff --git a/conftest.py b/conftest.py index 34c9bdfc0364..edf96d46ba98 100644 --- a/conftest.py +++ b/conftest.py @@ -90,8 +90,8 @@ def fake(): 'mark': 'enable_search', 'replacement': mock.MagicMock() }, - 'website.search.elastic_search': { - 'mark': 'enable_search', + 'osf.external.messages.celery_publishers._publish_user_status_change': { + 'mark': 'enable_account_status_messaging', 'replacement': mock.MagicMock() } } diff --git a/framework/auth/signals.py b/framework/auth/signals.py index c538c0bc2792..4d3dfffff560 100644 --- a/framework/auth/signals.py +++ b/framework/auth/signals.py @@ -6,7 +6,9 @@ user_registered = signals.signal('user-registered') user_confirmed = signals.signal('user-confirmed') user_email_removed = signals.signal('user-email-removed') -user_merged = signals.signal('user-account-merged') +user_account_merged = signals.signal('user-account-merged') +user_account_deactivated = signals.signal('user-account-deactivated') +user_account_reactivated = signals.signal('user-account-reactivated') unconfirmed_user_created = signals.signal('unconfirmed-user-created') user_update_mailchimp_subscription = signals.signal('user-update-mailchimp-subscription') diff --git a/osf/external/messages/celery_publishers.py b/osf/external/messages/celery_publishers.py index b203712302b5..2e33324b2fd0 100644 --- a/osf/external/messages/celery_publishers.py +++ b/osf/external/messages/celery_publishers.py @@ -1,36 +1,44 @@ from kombu import Exchange from framework.celery_tasks import app as celery_app +from framework.celery_tasks.handlers import enqueue_task def publish_deactivated_user(user): - _publish_user_status_change( - body={ - 'action': 'deactivate', - 'user_uri': user.url, - }, + enqueue_task( + _publish_user_status_change.s( + body={ + 'action': 'deactivate', + 'user_uri': user.url, + }, + ) ) def publish_reactivate_user(user): - _publish_user_status_change( - body={ - 'action': 'reactivate', - 'user_uri': user.url, - }, + enqueue_task( + _publish_user_status_change.s( + body={ + 'action': 'reactivate', + 'user_uri': user.url, + }, + ) ) def publish_merged_user(user): assert user.merged_by, 'User received merge signal, but has no `merged_by` reference.' - _publish_user_status_change( - body={ - 'action': 'merge', - 'user_uri': user.url, - 'merged_user_uri': user.merged_by.url, - }, + enqueue_task( + _publish_user_status_change.s( + body={ + 'action': 'merge', + 'user_uri': user.url, + 'merged_user_uri': user.merged_by.url, + }, + ) ) +@celery_app.task() def _publish_user_status_change(body: dict): with celery_app.producer_pool.acquire() as producer: producer.publish( diff --git a/osf/models/user.py b/osf/models/user.py index f1e6576c155a..6ad8702716ad 100644 --- a/osf/models/user.py +++ b/osf/models/user.py @@ -750,10 +750,10 @@ def merge_user(self, user): for key, value in user.mailchimp_mailing_lists.items(): # subscribe to each list if either user was subscribed subscription = value or self.mailchimp_mailing_lists.get(key) - signals.user_merged.send(self, list_name=key, subscription=subscription) + signals.user_update_mailchimp_subscription.send(self, list_name=key, subscription=subscription) # clear subscriptions for merged user - signals.user_merged.send(user, list_name=key, subscription=False) + signals.user_update_mailchimp_subscription.send(user, list_name=key, subscription=False) for target_id, timestamp in user.comments_viewed_timestamp.items(): if not self.comments_viewed_timestamp.get(target_id): @@ -872,9 +872,8 @@ def merge_user(self, user): user.merged_by = self user.save() - from osf.external.messages.celery_publishers import publish_deactivated_user, publish_merged_user - publish_deactivated_user(self) - publish_merged_user(self) + signals.user_account_merged.send(user) + signals.user_account_deactivated.send(self) def _merge_users_preprints(self, user): """ @@ -989,6 +988,7 @@ def deactivate_account(self): # Call to `unsubscribe` above saves, and can lead to stale data self.reload() self.is_disabled = True + signals.user_account_deactivated.send(self) # we must call both methods to ensure the current session is cleared and all existing # sessions are revoked. @@ -996,8 +996,6 @@ def deactivate_account(self): if isinstance(req, FlaskRequest): logout() remove_sessions_for_user(self) - from osf.external.messages.celery_publishers import publish_deactivated_user - publish_deactivated_user(self) def reactivate_account(self): """ @@ -1007,8 +1005,7 @@ def reactivate_account(self): self.requested_deactivation = False from website.mailchimp_utils import subscribe_on_confirm subscribe_on_confirm(self) - from osf.external.messages.celery_publishers import publish_reactivate_user - publish_reactivate_user(self) + signals.user_account_reactivated.send(self) def update_is_active(self): """Update ``is_active`` to be consistent with the fields that diff --git a/osf_tests/test_user.py b/osf_tests/test_user.py index 2c4d961f77b8..147460de0519 100644 --- a/osf_tests/test_user.py +++ b/osf_tests/test_user.py @@ -17,7 +17,7 @@ from importlib import import_module from framework.auth.exceptions import ExpiredTokenError, InvalidTokenError, ChangePasswordError -from framework.auth.signals import user_merged +from framework.auth.signals import user_account_merged, user_account_deactivated, user_update_mailchimp_subscription from framework.analytics import get_total_activity_count from framework.exceptions import PermissionsError from framework.celery_tasks import handlers @@ -1507,7 +1507,7 @@ def test_send_user_merged_signal(self, mock_get_mailchimp_api, dupe, merge_dupe) with capture_signals() as mock_signals: merge_dupe() - assert mock_signals.signals_sent() == set([user_merged]) + assert mock_signals.signals_sent() == set([user_account_merged, user_account_deactivated, user_update_mailchimp_subscription]) @pytest.mark.enable_enqueue_task @mock.patch('website.mailchimp_utils.get_mailchimp_api') diff --git a/website/profile/views.py b/website/profile/views.py index 18e0bd655b0c..9079a54d5548 100644 --- a/website/profile/views.py +++ b/website/profile/views.py @@ -16,8 +16,11 @@ from framework.auth.decorators import must_be_confirmed from framework.auth.exceptions import ChangePasswordError from framework.auth.views import send_confirm_email -from framework.auth.signals import user_merged - +from framework.auth.signals import ( + user_account_merged, + user_account_deactivated, + user_account_reactivated, +) from framework.exceptions import HTTPError, PermissionsError from framework.flask import redirect # VOL-aware redirect from framework.status import push_status_message @@ -37,6 +40,11 @@ from website.util import api_v2_url, web_url_for, paths from website.util.sanitize import escape_html from addons.base import utils as addon_utils +from osf.external.messages.celery_publishers import ( + publish_reactivate_user, + publish_deactivated_user, + publish_merged_user +) from api.waffle.utils import storage_i18n_flag_active @@ -507,7 +515,7 @@ def user_choose_mailing_lists(auth, **kwargs): return {'message': 'Successfully updated mailing lists', 'result': all_mailing_lists}, 200 -@user_merged.connect +@user_update_mailchimp_subscription.connect def update_mailchimp_subscription(user, list_name, subscription): """ Update mailing list subscription in mailchimp. @@ -528,6 +536,24 @@ def update_mailchimp_subscription(user, list_name, subscription): pass +@user_account_merged.connect +def send_account_merged_message(user): + """ Sends a message using Celery messaging to alert other services that an osf.io user has been merged.""" + publish_merged_user(user) + + +@user_account_deactivated.connect +def send_account_deactivation_message(user): + """ Sends a message using Celery messaging to alert other services that an osf.io user has been deactivated.""" + publish_deactivated_user(user) + + +@user_account_reactivated.connect +def send_account_reactivation_message(user): + """ Sends a message using Celery messaging to alert other services that an osf.io user has been reactivated.""" + publish_reactivate_user(user) + + def mailchimp_get_endpoint(**kwargs): """Endpoint that the mailchimp webhook hits to check that the OSF is responding""" return {}, http_status.HTTP_200_OK diff --git a/website/signals.py b/website/signals.py index 2ae3bb4efd4d..8cef25cbf295 100644 --- a/website/signals.py +++ b/website/signals.py @@ -18,7 +18,10 @@ auth.user_confirmed, auth.user_email_removed, auth.user_registered, - auth.user_merged, + auth.user_account_deactivated, + auth.user_account_reactivated, + auth.user_account_merged, + auth.user_update_mailchimp_subscription, auth.unconfirmed_user_created, event.file_updated, conference.osf4m_user_created,