def notify(uid, event, user, node, timestamp, **context): """ :param uid: node's id :param event: type of notification :param user: user "sending" notification :param node: the node :param timestamp: time :param context: optional variables specific to templates target_user: used with comment_replies :return: """ node_subscribers = [] subscription = NotificationSubscription.load(utils.to_subscription_key(uid, event)) if subscription: for notification_type in constants.NOTIFICATION_TYPES: subscribed_users = getattr(subscription, notification_type, []) node_subscribers.extend(subscribed_users) if subscribed_users and notification_type != 'none': for recipient in subscribed_users: event = 'comment_replies' if context.get('target_user') == recipient else event send([recipient._id], notification_type, uid, event, user, node, timestamp, **context) return check_parent(uid, event, node_subscribers, user, node, timestamp, **context)
def notify(uid, event, user, node, timestamp, **context): """ :param uid: node's id :param event: type of notification :param user: user "sending" notification :param node: the node :param timestamp: time :param context: optional variables specific to templates target_user: used with comment_replies :return: """ node_subscribers = [] subscription = NotificationSubscription.load( utils.to_subscription_key(uid, event)) if subscription: for notification_type in constants.NOTIFICATION_TYPES: subscribed_users = getattr(subscription, notification_type, []) node_subscribers.extend(subscribed_users) if subscribed_users and notification_type != 'none': for recipient in subscribed_users: event = 'comment_replies' if context.get( 'target_user') == recipient else event send([recipient._id], notification_type, uid, event, user, node, timestamp, **context) return check_parent(uid, event, node_subscribers, user, node, timestamp, **context)
def get_user_subscriptions(user, event): user_subscription = NotificationSubscription.load( utils.to_subscription_key(user._id, event)) return { key: getattr(user_subscription, key, []) for key in constants.NOTIFICATION_TYPES }
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 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 check_parent(uid, event, node_subscribers, user, orig_node, timestamp, **context): """ Check subscription object for the event on the parent project and send transactional email to indirect subscribers. """ node = website_models.Node.load(uid) target_user = context.get('target_user', None) if node and node.parent_id: key = utils.to_subscription_key(node.parent_id, event) subscription = NotificationSubscription.load(key) if not subscription: return check_parent(node.parent_id, event, node_subscribers, user, orig_node, timestamp, **context) for notification_type in constants.NOTIFICATION_TYPES: subscribed_users = getattr(subscription, notification_type, []) for u in subscribed_users: if u not in node_subscribers and node.has_permission(u, 'read'): if notification_type != 'none': event = 'comment_replies' if target_user == u else event send([u._id], notification_type, uid, event, user, orig_node, timestamp, **context) node_subscribers.append(u) return check_parent(node.parent_id, event, node_subscribers, user, orig_node, timestamp, **context) return node_subscribers
def check_parent(uid, event, node_subscribers, **context): """ Check subscription object for the event on the parent project and send transactional email to indirect subscribers. """ node = website_models.Node.load(uid) target_user = context.get('target_user', None) if node and node.parent_id: key = utils.to_subscription_key(node.parent_id, event) subscription = NotificationSubscription.load(key) if not subscription: return check_parent(node.parent_id, event, node_subscribers, **context) for notification_type in constants.NOTIFICATION_TYPES: subscribed_users = getattr(subscription, notification_type, []) for u in subscribed_users: if u not in node_subscribers and node.has_permission( u, 'read'): if notification_type != 'none': event = 'comment_replies' if target_user == u else event send([u._id], notification_type, uid, event, **context) node_subscribers.append(u) return check_parent(node.parent_id, event, node_subscribers, **context) return node_subscribers
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 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 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, []) for user in users: if node.has_permission(user, 'read'): node_subscriptions[notification_type].append(user._id) return node_subscriptions
def notify(uid, event, **context): node_subscribers = [] subscription = NotificationSubscription.load(utils.to_subscription_key(uid, event)) if subscription: for notification_type in constants.NOTIFICATION_TYPES: subscribed_users = getattr(subscription, notification_type, []) node_subscribers.extend(subscribed_users) if subscribed_users and notification_type != 'none': event = 'comment_replies' if context.get('target_user') else event send([u._id for u in subscribed_users], notification_type, uid, event, **context) return check_parent(uid, event, node_subscribers, **context)
def add_global_subscriptions(): notification_type = 'email_transactional' user_events = constants.USER_SUBSCRIPTIONS_AVAILABLE for user in models.User.find(): if user.is_active and user.is_registered: 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: subscription = NotificationSubscription(_id=user_event_id, owner=user, event_name=user_event) subscription.add_user_to_subscription(user, notification_type) subscription.save() logger.info('No subscription found. {} created.'.format(subscription)) else: logger.info('Subscription {} found.'.format(subscription))
def notify(uid, event, **context): node_subscribers = [] subscription = NotificationSubscription.load( utils.to_subscription_key(uid, event)) if subscription: for notification_type in constants.NOTIFICATION_TYPES: subscribed_users = getattr(subscription, notification_type, []) node_subscribers.extend(subscribed_users) if subscribed_users and notification_type != 'none': for user in subscribed_users: event = 'comment_replies' if context.get( 'target_user') == user else event send([user._id], notification_type, uid, event, **context) return check_parent(uid, event, node_subscribers, **context)
def add_global_subscriptions(): notification_type = 'email_transactional' user_events = constants.USER_SUBSCRIPTIONS_AVAILABLE for user in models.User.find(): if user.is_active and user.is_registered: 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: subscription = NotificationSubscription( _id=user_event_id, owner=user, event_name=user_event) subscription.add_user_to_subscription( user, notification_type) subscription.save() logger.info('No subscription found. {} created.'.format( subscription)) else: logger.info('Subscription {} found.'.format(subscription))
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 get_user_subscriptions(user, event): user_subscription = NotificationSubscription.load(utils.to_subscription_key(user._id, event)) return {key: getattr(user_subscription, key, []) for key in constants.NOTIFICATION_TYPES}
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_status.HTTP_400_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_status.HTTP_404_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_status.HTTP_400_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_status.HTTP_403_FORBIDDEN) if isinstance(node, Registration): sentry.log_message( '{!r} attempted to subscribe to registration, {}'.format( user, target_id)) raise HTTPError(http_status.HTTP_400_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_status.HTTP_400_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 test_to_subscription_key(self): key = utils.to_subscription_key('xyz', 'comments') assert_equal(key, 'xyz_comments')
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') 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 = Node.load(target_id) 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: 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.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 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)}