def add_global_subscriptions(dry=True): OSFUser = apps.get_model('osf.OSFUser') notification_type = 'email_transactional' user_events = constants.USER_SUBSCRIPTIONS_AVAILABLE count = 0 with transaction.atomic(): for user in OSFUser.objects.filter(is_registered=True, date_confirmed__isnull=False): changed = False if not user.is_active: continue for user_event in user_events: user_event_id = to_subscription_key(user._id, user_event) subscription = NotificationSubscription.load(user_event_id) if not subscription: logger.info('No {} subscription found for user {}. Subscribing...'.format(user_event, user._id)) subscription = NotificationSubscription(_id=user_event_id, owner=user, event_name=user_event) subscription.save() # Need to save in order to access m2m fields subscription.add_user_to_subscription(user, notification_type) subscription.save() changed = True else: logger.info('User {} already has a {} subscription'.format(user._id, user_event)) if changed: count += 1 logger.info('Added subscriptions for {} users'.format(count)) if dry: raise RuntimeError('Dry mode -- rolling back transaction')
def reviews_submit_notification_moderators(self, timestamp, context): # imports moved here to avoid AppRegistryNotReady error from osf.models import NotificationSubscription from website.profile.utils import get_profile_image_url from website.notifications import emails from website import settings # Get NotificationSubscription instance, which contains reference to all subscribers provider_subscription = NotificationSubscription.load('{}_new_pending_submissions'.format(context['reviewable'].provider._id)) # Set message context['message'] = u'submitted {}.'.format(context['reviewable'].node.title) # Set url for profile image of the submitter context['profile_image_url'] = get_profile_image_url(context['referrer']) # Set submission url context['reviews_submission_url'] = '{}reviews/preprints/{}/{}'.format(settings.DOMAIN, context['reviewable'].provider._id, context['reviewable']._id) # Store emails to be sent to subscribers instantly (at a 5 min interval) emails.store_emails(provider_subscription.email_transactional.all().values_list('guids___id', flat=True), 'email_transactional', 'new_pending_submissions', context['referrer'], context['reviewable'].node, timestamp, abstract_provider=context['reviewable'].provider, **context) # Store emails to be sent to subscribers daily emails.store_emails(provider_subscription.email_digest.all().values_list('guids___id', flat=True), 'email_digest', 'new_pending_submissions', context['referrer'], context['reviewable'].node, timestamp, abstract_provider=context['reviewable'].provider, **context)
def get_user_subscriptions(user, event): if user.is_disabled: return {} user_subscription = NotificationSubscription.load(utils.to_subscription_key(user._id, event)) if user_subscription: return {key: list(getattr(user_subscription, key).all().values_list('guids___id', flat=True)) for key in constants.NOTIFICATION_TYPES} else: return {key: [] for key in constants.NOTIFICATION_TYPES}
def add_reviews_notification_setting(notification_type): active_users = OSFUser.objects.filter( date_confirmed__isnull=False).exclude( date_disabled__isnull=False).exclude( is_active=False).order_by('id') total_active_users = active_users.count() logger.info('About to add a global_reviews setting for {} users.'.format( total_active_users)) total_created = 0 for user in active_users.iterator(): user_subscription_id = to_subscription_key(user._id, notification_type) subscription = NotificationSubscription.load(user_subscription_id) if not subscription: logger.info( 'No {} subscription found for user {}. Subscribing...'.format( notification_type, user._id)) subscription = NotificationSubscription( _id=user_subscription_id, owner=user, event_name=notification_type) subscription.save() # Need to save in order to access m2m fields subscription.add_user_to_subscription(user, 'email_transactional') else: logger.info('User {} already has a {} subscription'.format( user._id, notification_type)) total_created += 1 logger.info('Added subscriptions for {}/{} users'.format( total_created, total_active_users))
def check_node(node, event): """Return subscription for a particular node and event.""" node_subscriptions = {key: [] for key in constants.NOTIFICATION_TYPES} if node: subscription = NotificationSubscription.load(utils.to_subscription_key(node._id, event)) for notification_type in node_subscriptions: users = getattr(subscription, notification_type, []) if users: for user in users.exclude(date_disabled__isnull=False): if node.has_permission(user, READ): node_subscriptions[notification_type].append(user._id) return node_subscriptions
def check_node(node, event): """Return subscription for a particular node and event.""" node_subscriptions = {key: [] for key in constants.NOTIFICATION_TYPES} if node: subscription = NotificationSubscription.load(utils.to_subscription_key(node._id, event)) for notification_type in node_subscriptions: users = getattr(subscription, notification_type, []) if users: for user in users.exclude(date_disabled__isnull=False): if node.has_permission(user, 'read'): node_subscriptions[notification_type].append(user._id) return node_subscriptions
def add_reviews_notification_setting(notification_type, state=None): if state: OSFUser = state.get_model('osf', 'OSFUser') NotificationSubscription = state.get_model('osf', 'NotificationSubscription') else: from osf.models import OSFUser, NotificationSubscription active_users = OSFUser.objects.filter(date_confirmed__isnull=False).exclude(date_disabled__isnull=False).exclude(is_active=False).order_by('id') total_active_users = active_users.count() logger.info('About to add a global_reviews setting for {} users.'.format(total_active_users)) total_created = 0 for user in active_users.iterator(): user_subscription_id = to_subscription_key(user._id, notification_type) subscription = NotificationSubscription.load(user_subscription_id) if not subscription: logger.info('No {} subscription found for user {}. Subscribing...'.format(notification_type, user._id)) subscription = NotificationSubscription(_id=user_subscription_id, owner=user, event_name=notification_type) subscription.save() # Need to save in order to access m2m fields subscription.add_user_to_subscription(user, 'email_transactional') else: logger.info('User {} already has a {} subscription'.format(user._id, notification_type)) total_created += 1 logger.info('Added subscriptions for {}/{} users'.format(total_created, total_active_users))
def reviews_withdrawal_requests_notification(self, timestamp, context): # imports moved here to avoid AppRegistryNotReady error from osf.models import NotificationSubscription from website.notifications.emails import store_emails from website.profile.utils import get_profile_image_url from website import settings # Get NotificationSubscription instance, which contains reference to all subscribers provider_subscription = NotificationSubscription.load( '{}_new_pending_submissions'.format( context['reviewable'].provider._id)) preprint = context['reviewable'] preprint_word = preprint.provider.preprint_word # Set message context['message'] = u'has requested withdrawal of the {} "{}".'.format( preprint_word, preprint.title) # Set url for profile image of the submitter context['profile_image_url'] = get_profile_image_url(context['requester']) # Set submission url context['reviews_submission_url'] = '{}reviews/preprints/{}/{}'.format( settings.DOMAIN, preprint.provider._id, preprint._id) email_transactional_ids = list( provider_subscription.email_transactional.all().values_list( 'guids___id', flat=True)) email_digest_ids = list( provider_subscription.email_digest.all().values_list('guids___id', flat=True)) # Store emails to be sent to subscribers instantly (at a 5 min interval) store_emails(email_transactional_ids, 'email_transactional', 'new_pending_submissions', context['requester'], preprint, timestamp, abstract_provider=preprint.provider, **context) # Store emails to be sent to subscribers daily store_emails(email_digest_ids, 'email_digest', 'new_pending_submissions', context['requester'], preprint, timestamp, abstract_provider=preprint.provider, **context)
def add_global_subscriptions(dry=True): OSFUser = apps.get_model('osf.OSFUser') notification_type = 'email_transactional' user_events = constants.USER_SUBSCRIPTIONS_AVAILABLE count = 0 with transaction.atomic(): for user in OSFUser.objects.filter(is_registered=True, date_confirmed__isnull=False): changed = False if not user.is_active: continue for user_event in user_events: user_event_id = to_subscription_key(user._id, user_event) subscription = NotificationSubscription.load(user_event_id) if not subscription: logger.info( 'No {} subscription found for user {}. Subscribing...'. format(user_event, user._id)) subscription = NotificationSubscription( _id=user_event_id, owner=user, event_name=user_event) subscription.save( ) # Need to save in order to access m2m fields subscription.add_user_to_subscription( user, notification_type) subscription.save() changed = True else: logger.info('User {} already has a {} subscription'.format( user._id, user_event)) if changed: count += 1 logger.info('Added subscriptions for {} users'.format(count)) if dry: raise RuntimeError('Dry mode -- rolling back transaction')
def reviews_submit_notification_moderators(self, timestamp, context): # imports moved here to avoid AppRegistryNotReady error from osf.models import NotificationSubscription from website.profile.utils import get_profile_image_url from website.notifications import emails from website import settings # Get NotificationSubscription instance, which contains reference to all subscribers provider_subscription = NotificationSubscription.load( '{}_new_pending_submissions'.format( context['reviewable'].provider._id)) # Set message context['message'] = u'submitted {}.'.format( context['reviewable'].node.title) # Set url for profile image of the submitter context['profile_image_url'] = get_profile_image_url(context['referrer']) # Set submission url context['reviews_submission_url'] = '{}reviews/preprints/{}/{}'.format( settings.DOMAIN, context['reviewable'].provider._id, context['reviewable']._id) # Store emails to be sent to subscribers instantly (at a 5 min interval) emails.store_emails( provider_subscription.email_transactional.all().values_list( 'guids___id', flat=True), 'email_transactional', 'new_pending_submissions', context['referrer'], context['reviewable'].node, timestamp, abstract_provider=context['reviewable'].provider, **context) # Store emails to be sent to subscribers daily emails.store_emails(provider_subscription.email_digest.all().values_list( 'guids___id', flat=True), 'email_digest', 'new_pending_submissions', context['referrer'], context['reviewable'].node, timestamp, abstract_provider=context['reviewable'].provider, **context)
def configure_subscription(auth): user = auth.user json_data = request.get_json() target_id = json_data.get('id') event = json_data.get('event') notification_type = json_data.get('notification_type') path = json_data.get('path') provider = json_data.get('provider') if not event or (notification_type not in NOTIFICATION_TYPES and notification_type != 'adopt_parent'): raise HTTPError(http.BAD_REQUEST, data=dict( message_long='Must provide an event and notification type for subscription.') ) node = AbstractNode.load(target_id) if 'file_updated' in event and path is not None and provider is not None: wb_path = path.lstrip('/') event = wb_path + '_file_updated' event_id = utils.to_subscription_key(target_id, event) if not node: # if target_id is not a node it currently must be the current user if not target_id == user._id: sentry.log_message( '{!r} attempted to subscribe to either a bad ' 'id or non-node non-self id, {}'.format(user, target_id) ) raise HTTPError(http.NOT_FOUND) if notification_type == 'adopt_parent': sentry.log_message( '{!r} attempted to adopt_parent of a none node id, {}'.format(user, target_id) ) raise HTTPError(http.BAD_REQUEST) owner = user else: if not node.has_permission(user, 'read'): sentry.log_message('{!r} attempted to subscribe to private node, {}'.format(user, target_id)) raise HTTPError(http.FORBIDDEN) if notification_type != 'adopt_parent': owner = node else: if 'file_updated' in event and len(event) > len('file_updated'): pass else: parent = node.parent_node if not parent: sentry.log_message( '{!r} attempted to adopt_parent of ' 'the parentless project, {!r}'.format(user, node) ) raise HTTPError(http.BAD_REQUEST) # If adopt_parent make sure that this subscription is None for the current User subscription = NotificationSubscription.load(event_id) if not subscription: return {} # We're done here subscription.remove_user_from_subscription(user) return {} subscription = NotificationSubscription.load(event_id) if not subscription: subscription = NotificationSubscription(_id=event_id, owner=owner, event_name=event) subscription.save() if node and node._id not in user.notifications_configured: user.notifications_configured[node._id] = True user.save() subscription.add_user_to_subscription(user, notification_type) subscription.save() return {'message': 'Successfully subscribed to {} list on {}'.format(notification_type, event_id)}
def configure_subscription(auth): user = auth.user json_data = request.get_json() target_id = json_data.get('id') event = json_data.get('event') notification_type = json_data.get('notification_type') path = json_data.get('path') provider = json_data.get('provider') if not event or (notification_type not in NOTIFICATION_TYPES and notification_type != 'adopt_parent'): raise HTTPError( http.BAD_REQUEST, data=dict( message_long= 'Must provide an event and notification type for subscription.' )) node = AbstractNode.load(target_id) if 'file_updated' in event and path is not None and provider is not None: wb_path = path.lstrip('/') event = wb_path + '_file_updated' event_id = utils.to_subscription_key(target_id, event) if not node: # if target_id is not a node it currently must be the current user if not target_id == user._id: sentry.log_message('{!r} attempted to subscribe to either a bad ' 'id or non-node non-self id, {}'.format( user, target_id)) raise HTTPError(http.NOT_FOUND) if notification_type == 'adopt_parent': sentry.log_message( '{!r} attempted to adopt_parent of a none node id, {}'.format( user, target_id)) raise HTTPError(http.BAD_REQUEST) owner = user else: if not node.has_permission(user, READ): sentry.log_message( '{!r} attempted to subscribe to private node, {}'.format( user, target_id)) raise HTTPError(http.FORBIDDEN) if isinstance(node, Registration): sentry.log_message( '{!r} attempted to subscribe to registration, {}'.format( user, target_id)) raise HTTPError(http.BAD_REQUEST) if notification_type != 'adopt_parent': owner = node else: if 'file_updated' in event and len(event) > len('file_updated'): pass else: parent = node.parent_node if not parent: sentry.log_message('{!r} attempted to adopt_parent of ' 'the parentless project, {!r}'.format( user, node)) raise HTTPError(http.BAD_REQUEST) # If adopt_parent make sure that this subscription is None for the current User subscription = NotificationSubscription.load(event_id) if not subscription: return {} # We're done here subscription.remove_user_from_subscription(user) return {} subscription = NotificationSubscription.load(event_id) if not subscription: subscription = NotificationSubscription(_id=event_id, owner=owner, event_name=event) subscription.save() if node and node._id not in user.notifications_configured: user.notifications_configured[node._id] = True user.save() subscription.add_user_to_subscription(user, notification_type) subscription.save() return { 'message': 'Successfully subscribed to {} list on {}'.format( notification_type, event_id) }