def remove_tag(req, person_stub, tag_slug, tag_category): """ web service to remove tag from profile, users are only able to remove their own tags """ person = Person.objects.get(stub=person_stub) tag = Tag.objects.get(slug=tag_slug) taggeditem = TaggedItem.objects.get(tag_category__slug=tag_category, object_id=person.id, tag=tag) taggeditem.delete() person.expire_cache() expire_cache_group('tags') url = reverse('staff_directory:person', args=[person.stub]) if person.user != req.user: # create email info email_info = EmailInfo( subject='A tag was removed from your user profile.', text_template='staff_directory/email/user_untagged.txt', html_template='staff_directory/email/user_untagged.html', to_address=person.user.email, ) # set notification title = '%s %s removed the "%s" tag from your profile' % \ (req.user.first_name, req.user.last_name, tag) Notification.set_notification(req.user, req.user, "untagged", tag, person.user, title, url, email_info) return HttpResponseRedirect(url)
def test_mark_all_as_read(self): self.client.login(username='******', password='******') login_user = get_user_model().objects.get(pk=1) other_user = get_user_model().objects.get(pk=3) notification1 = Notification.set_notification( owner=login_user, actor=login_user, verb="tagged", obj="message", target=login_user, title="You tagged someone", url="http://url.com/") notification2 = Notification.set_notification( owner=other_user, actor=other_user, verb="tagged", obj="message", target=login_user, title="You tagged someone", url="http://url.com/") notification3 = Notification.set_notification( owner=login_user, actor=login_user, verb="tagged", obj="message", target=other_user, title="You tagged someone", url="http://url.com/") self.assertFalse(notification1.viewed) self.assertFalse(notification2.viewed) self.assertFalse(notification3.viewed) response = self.client.post( '/notifications/mark_all_as_read/') self.assertEquals(200, response.status_code) notification1 = Notification.objects.get(pk=notification1.pk) notification2 = Notification.objects.get(pk=notification2.pk) notification3 = Notification.objects.get(pk=notification3.pk) self.assertTrue(notification1.viewed) self.assertTrue(notification2.viewed) self.assertFalse(notification3.viewed)
def save(self, *args, **kwargs): url = reverse('staff_directory:show_thanks', args=()) email_info = EmailInfo( subject="You were thanked in the staff directory!", text_template='staff_directory/email/user_thanked.txt', html_template='staff_directory/email/user_thanked.html', to_address=self.recipient.user.email, ) # Notify recipient title ="%s thanked you for %s" %\ (self.praise_nominator.person.full_name, NOUN[self.cfpb_value]) Notification.set_notification(self.praise_nominator, self.praise_nominator, "thanked", self, self.recipient.user, title, url, email_info) # Notify nominator title = "You thanked %s for %s" %\ (self.recipient.full_name, NOUN[self.cfpb_value]) Notification.set_notification(self.praise_nominator, self.praise_nominator, "thanked", self, self.praise_nominator, title, url) return super(Praise, self).save(*args, **kwargs)
def test_clear_cache_keys(client): ckey = Notification.__cache_key_notification_count__.format( user_id=1, type=1 ) cache.set(ckey, 100) Notification.clear_cache_keys(1, 'subscripple') assert not cache.has(ckey)
def test_clear_cache_keys_wrong_type(client): ckey = Notification.__cache_key_notification_count__.format( user_id=1, type='subscripple' ) cache.set(ckey, 100) with pytest.raises(APIException): Notification.clear_cache_keys(1, 'not_real_type')
def send_idea_notifications(sender, comment, request, **kwargs): # If installed in collab try: from core.notifications.models import Notification from core.notifications.email import EmailInfo from core.helpers import normalize idea = comment.content_object if comment.is_anonymous: title = u'Someone commented on "%s"' % idea.title text_template = 'new_comment_anonymous.txt' html_template = 'new_comment_anonymous.html' else: title = u'%s %s comented on "%s"' % (normalize( comment.user.first_name), normalize( comment.user.last_name), idea.title) text_template = 'new_comment.txt' html_template = 'new_comment.html' for user in idea.members: if user != comment.user: email_info = EmailInfo( subject=title, text_template='idea/email/%s' % text_template, html_template='idea/email/%s' % html_template, to_address=user.email, ) Notification.set_notification(comment.user, comment.user, "commented", idea, user, title, idea.url(), email_info) except ImportError: pass
def send_idea_notifications(sender, comment, request, **kwargs): # If installed in collab try: from core.notifications.models import Notification from core.notifications.email import EmailInfo from core.helpers import normalize idea = comment.content_object title = u"%s %s commented on %s" % (normalize(comment.user.first_name), normalize(comment.user.last_name), idea.title) for user in idea.members: if user != comment.user: email_info = EmailInfo( subject = title, text_template = 'idea/email/new_comment.txt', html_template = 'idea/email/new_comment.html', to_address = user.email, ) Notification.set_notification(comment.user, comment.user, "commented", idea, user, title, idea.url(), email_info) except ImportError: pass
def modify_notification(id: int, read: bool): """ Change the read status of a notification. Requires the ``notifications_modify`` permission. Modifying another user's notifications requires the ``notifications_modify_others`` permission. .. :quickref: Notification; Flag notification as read/unread. **Example response**: .. parsed-literal:: { "status": "success", "response": "Notification 1243 marked as read." } :>json str response: Response message :statuscode 200: Successfully modified notification. :statuscode 403: User does not have permission to modify notifications. :statuscode 404: Notification does not exist. """ noti = Notification.from_pk(id, asrt=NotificationPermissions.MODIFY_OTHERS, error=True) noti.read = read db.session.commit() Notification.clear_cache_keys(noti.user_id, noti.type) return flask.jsonify( f'Notification {id} marked as {"read" if read else "unread"}.')
def clear_notifications(read: bool, user: User, type: str = None): """ Clear a user's notifications; optionally of a specific type. Requires the ``notifications_modify`` permission. Clearing another user's notifications requires the ``notifications_modify_others`` permission. .. :quickref: Notification; View notifications of a type. **Example response**: .. parsed-literal:: { "status": "success", "response": "All notifications cleared." } :>json str response: Response message :statuscode 200: Successfully cleared notifications. :statuscode 403: User does not have permission to clear notifications. """ if not read: raise APIException('You cannot set all notifications to unread.') Notification.update_many( pks=Notification.get_pks_from_type(user.id, type, include_read=False), update={'read': True}, ) Notification.clear_cache_keys(user.id) return flask.jsonify( f'{"All" if not type else type} notifications cleared.')
def test_clear_cache_keys_without_type(client): ckey = Notification.__cache_key_notification_count__.format( user_id=1, type=1 ) cache.set(ckey, 100) Notification.clear_cache_keys(1) assert not cache.has(ckey)
def add_tag(req, person_stub='', tag='', category_slug='', is_ajax=False, redirect_to_tags_page=False): """ adds a tag to a user if they do not have tagging turned off """ if req.method == 'POST': if tag == '': tag = req.POST.get('tag', '').strip() if category_slug == '': category_slug = req.POST.get('tag_category_slug', '').strip() if tag == '': return json_response( {'error': 'Please enter a tag that is not blank.'}) elif person_stub == '': return json_response({'error': 'Person not found.'}) person = Person.objects.get(stub=person_stub) # make sure tag does not already exist try: taggeditem = TaggedItem.objects.get( tag_category__slug=category_slug, object_id=person.id, tag__name__iexact=tag) except Exception: taggeditem = add_tags(person, tag, category_slug, req.user, 'person') person.expire_cache() expire_cache_group('tags') url = reverse('staff_directory:person', args=[person.stub]) if person.user != req.user: email_info = EmailInfo( subject='You were tagged in the staff directory!', text_template='staff_directory/email/user_tagged.txt', html_template='staff_directory/email/user_tagged.html', to_address=person.user.email, ) # set notification title = '%s %s tagged you with "%s"' % \ (req.user.first_name, req.user.last_name, tag) Notification.set_notification(req.user, req.user, "tagged", tag, person.user, title, url, email_info) if is_ajax: if redirect_to_tags_page: return json_response({ 'redirect': reverse('staff_directory:show_by_tag', args=[taggeditem.tag.slug]) }) return json_response({ 'redirect': reverse('staff_directory:person', args=[person.stub]) }) else: return HttpResponseRedirect( reverse('staff_directory:person', args=[person.stub]))
def respond(req, id): user_form = get_object_or_404(Form, slug=id) already_responded = AnonymousResponse.objects.check_dupe(user_form.id, req.user.username) if not already_responded: if req.GET: for field in user_form.field_set.all(): if req.GET.has_key(field.label): field.default_value = req.GET[field.label] field.save() response_form = ResponseForm( req.POST or None, form=user_form, user=req.user) if not user_form.is_closed and response_form.is_valid(): form_response = response_form.save() #set notification title = '%s %s submitted the "%s" form' % \ (req.user.first_name, req.user.last_name, user_form) url = "/forms/results/%s/" % user_form.slug if user_form.owner.exists(): if user_form.collect_users: title = '%s %s submitted the "%s" form' % \ (req.user.first_name, req.user.last_name, user_form) text_template = 'form_respond.txt' html_template = 'form_respond.html' else: title = 'Someone submitted the "%s" form' % user_form text_template = 'form_respond_anonymous.txt' html_template = 'form_respond_anonymous.html' for o in user_form.owner.all(): if o != req.user: email_info = EmailInfo( subject=title, text_template='form_builder/email/%s' % text_template, html_template='form_builder/email/%s' % html_template, to_address=o.email ) Notification.set_notification(req.user, req.user, "submitted", user_form, o, title, url, email_info) return HttpResponseRedirect(reverse('form_builder:form_thanks', args=[form_response.pk])) return render_to_response('form_builder/respond.html', {'user_form': user_form, 'response_form': response_form}, context_instance=RequestContext(req)) else: context = RequestContext(req) context['form_title'] = user_form.title return render_to_response('form_builder/thanks.html', {}, context_instance=context)
def _dispatch_notifications( post: 'ForumPost', type: str, user_ids: List[int] ) -> None: for user_id in user_ids: Notification.new( user_id=user_id, type=type, contents={'thread_id': 1, 'post_id': 1, 'from': post.user_id}, )
def test_modify_notification(app, authed_client): add_permissions(app, 'notifications_modify') response = authed_client.put( '/notifications/1', data=json.dumps({'read': True}) ) print(response.get_json()) assert response.status_code == 200 assert not len(Notification.get_all_unread(1)['subscripple']) assert len(Notification.get_all_unread(1)['quote']) == 1
def add_tag(req, person_stub='', tag='', category_slug='', is_ajax=False, redirect_to_tags_page=False): """ adds a tag to a user if they do not have tagging turned off """ if req.method == 'POST': if tag == '': tag = req.POST.get('tag', '').strip() if category_slug == '': category_slug = req.POST.get('tag_category_slug', '').strip() if tag == '': return json_response({'error': 'Please enter a tag that is not blank.'}) elif person_stub == '': return json_response({'error': 'Person not found.'}) person = Person.objects.get(stub=person_stub) # make sure tag does not already exist try: taggeditem = TaggedItem.objects.get( tag_category__slug=category_slug, object_id=person.id, tag__name__iexact=tag) except Exception: taggeditem = add_tags(person, tag, category_slug, req.user, 'person') person.expire_cache() expire_cache_group('tags') url = reverse('staff_directory:person', args=[person.stub]) if person.user != req.user: email_info = EmailInfo( subject='You were tagged in the staff directory!', text_template='staff_directory/email/user_tagged.txt', html_template='staff_directory/email/user_tagged.html', to_address=person.user.email, ) # set notification title = '%s %s tagged you with "%s"' % \ (req.user.first_name, req.user.last_name, tag) Notification.set_notification(req.user, req.user, "tagged", tag, person.user, title, url, email_info) if is_ajax: if redirect_to_tags_page: return json_response({'redirect': reverse('staff_directory:show_by_tag', args=[taggeditem.tag.slug])}) return json_response({'redirect': reverse('staff_directory:person', args=[person.stub])}) else: return HttpResponseRedirect(reverse('staff_directory:person', args=[person.stub]))
def test_get_notification_model(client): noti = Notification.from_pk(1) assert noti.id == 1 assert noti.user_id == 1 assert noti.type == 'subscripple' assert noti.contents['contents'] == 'A Subscribe!' assert noti.read is False
def test_get_unread_notifications(client): unread = Notification.get_all_unread(1) assert unread['subscripple'][0].id == 1 assert len(unread['subscripple']) == 1 assert unread['quote'][0].id == 3 assert len(unread['quote']) == 1 assert len(unread['unreal']) == 0
def view_notifications(user: User): """ View all pending notifications for a user. This includes thread subscriptions, collage notifications, torrent notifications, and inbox messages. Requires the ``notifications_view`` permission. Viewing the notifications of another user requires the ``notifications_view_others`` permission. .. :quickref: Notification; View unread notifications. **Example response**: .. parsed-literal:: { "status": "success", "response": { "notification type 1": [ "<Notification>", "<Notification>" ], "notification type 2": [ "<Notification>", "<Notification>" ] } } :>json dict response: A dictionary of notification types and lists of notifications :statuscode 200: Successfully viewed notifications. :statuscode 403: User does not have access to view notifications. """ return flask.jsonify(Notification.get_all_unread(user.id))
def test_new_notification(client): noti = Notification.new( user_id=1, type='subscripple', contents={'contents': 'New Subscrippletion!'}, ) assert noti.id == 7 assert noti.contents['contents'] == 'New Subscrippletion!' assert noti.read is False
def test_new_notification_new_type(client): noti = Notification.new( user_id=1, type='new_type', contents={'contents': 'New Type!'} ) assert noti.id == 7 assert noti.contents['contents'] == 'New Type!' assert noti.type_id == 4 assert noti.type == 'new_type' assert noti.read is False
def test_clear_notifications(app, authed_client): add_permissions(app, 'notifications_modify') assert ( authed_client.put( '/notifications', data=json.dumps({'read': True}) ).status_code == 200 ) n = Notification.get_all_unread(1) assert all(len(v) == 0 for v in n.values())
def test_clear_notifications_type(app, authed_client): add_permissions(app, 'notifications_modify') assert ( authed_client.put( '/notifications/quote', data=json.dumps({'read': True}) ).status_code == 200 ) n = Notification.get_all_unread(1) assert len(n['quote']) == 0 assert len(n['subscripple']) == 1
def test_mark_as_read(self): self.client.login(username='******', password='******') user = get_user_model().objects.get(pk=1) notification = Notification.set_notification( user, user, "tagged", user, user, "You tagged someone", "http://url.com/") self.assertFalse(notification.viewed) response = self.client.post( '/notifications/mark_as_read/' + str(notification.pk)) self.assertEquals(200, response.status_code) notification = Notification.objects.get(pk=notification.pk) self.assertTrue(notification.viewed)
def view_notification_type( type: str, user: User, page: int = 1, limit: int = 50, include_read: bool = False, ): """ View all pending notifications of a specific type. Requires the ``notifications_view`` permission. Viewing the notifications of another user requires the ``notifications_view_others`` permission. .. :quickref: Notification; View notifications of a type. **Example request**: .. parsed-literal:: GET /notifications/type_1 HTTP/1.1 { "page": 1, "limit": 50, "include_read": False } **Example response**: .. parsed-literal:: { "status": "success", "response": [ "<Notification>", "<Notification>" ] } :>json dict response: A list of notifications :statuscode 200: Successfully viewed notifications. :statuscode 400: Notification type is invalid. :statuscode 403: User does not have access to view notifications. """ return flask.jsonify( Notification.from_type(user.id, type, include_read=include_read))
def user_info(req): user = {} user_info = {} user['first_name'] = req.user.first_name user['last_name'] = req.user.last_name user['stub'] = req.user.get_profile().stub user_info['user'] = user notifications = Notification.get_unread(req.user) fields = ['id', 'title', 'timestamp', 'url'] tmp_notification = [] for notification in notifications: notification_dict = {} for field in fields: notification_dict[field] = unicode(getattr(notification, field)).encode("utf-8", "replace") tmp_notification.append(notification_dict) user_info['notifications'] = tmp_notification return HttpResponse(json.dumps(user_info), content_type="application/json")
def test_get_and_mark_unread(self): user = get_user_model().objects.get(pk=2) target = get_user_model().objects.get(pk=1) notification = Notification(owner=user, actor=user, verb="tagged", obj="Wonderful", target=target, title="John tagged you with \"Wonderful\"", viewed=False) notification.save() with self.assertNumQueries(2): Notification.get_and_mark_unread(target) notification = Notification.objects.get(pk=notification.pk) self.assertTrue(notification.viewed)
def user_info(req): user = {} user_info = {} user['first_name'] = req.user.first_name user['last_name'] = req.user.last_name user['stub'] = req.user.get_profile().stub user_info['user'] = user notifications = Notification.get_unread(req.user) fields = ['id', 'title', 'timestamp', 'url'] tmp_notification = [] for notification in notifications: notification_dict = {} for field in fields: notification_dict[field] = unicode(getattr(notification, field)).encode( "utf-8", "replace") tmp_notification.append(notification_dict) user_info['notifications'] = tmp_notification return HttpResponse(json.dumps(user_info), content_type="application/json")
def test_get_and_mark_unread_no_unread(self): user = get_user_model().objects.get(pk=1) with self.assertNumQueries(1): Notification.get_and_mark_unread(user)
def test_get_notification_from_type_false(client): with pytest.raises(APIException) as e: Notification.from_type(1, 'bahaha', include_read=True) assert e.value.message == 'bahaha is not a notification type.'
def test_get_notification_from_type_include_read(client): notis = Notification.from_type(1, 'unreal', include_read=True) assert len(notis) == 1
def test_get_notification_from_type_read(client): notis = Notification.from_type(1, 'unreal') assert len(notis) == 0
def test_get_notification_from_type(client): notis = Notification.from_type(1, 'quote') assert len(notis) == 1 assert notis[0].id == 3
def widget(req): return render_to_response('notifications/widget.html', {'notifications': Notification.get_unread( req.user)}, context_instance=RequestContext(req))
def test_get_notification_counts(client): assert Notification.get_notification_counts(1) == { 'subscripple': 1, 'quote': 1, 'unreal': 0, }
def test_get_pks_from_type(client): pks = Notification.get_pks_from_type(1, 'subscripple') assert pks == [1]