From f4734b161afdd87b79dea47b3132776eb2628bf2 Mon Sep 17 00:00:00 2001 From: zhengxie Date: Thu, 28 Dec 2017 18:00:49 +0800 Subject: [PATCH 1/2] [notification] Notify inviter on guest accept invitation. --- seahub/invitations/signals.py | 5 ++ seahub/invitations/views.py | 6 +++ .../management/commands/send_notices.py | 21 ++++++++ seahub/notifications/models.py | 48 +++++++++++++++++++ .../templates/notifications/notice_email.html | 3 ++ .../notifications/user_notification_tr.html | 5 +- seahub/notifications/views.py | 2 +- seahub/templates/snippets/notice_html.html | 3 ++ tests/seahub/invitations/test_views.py | 14 ++++++ .../management/commands/test_send_notices.py | 19 +++++++- 10 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 seahub/invitations/signals.py diff --git a/seahub/invitations/signals.py b/seahub/invitations/signals.py new file mode 100644 index 0000000000..5060493ca6 --- /dev/null +++ b/seahub/invitations/signals.py @@ -0,0 +1,5 @@ +# Copyright (c) 2012-2016 Seafile Ltd. +import django.dispatch + +accept_guest_invitation_successful = django.dispatch.Signal( + providing_args=["invitation_obj"]) diff --git a/seahub/invitations/views.py b/seahub/invitations/views.py index 0d0fe6daca..24f92e7f1d 100644 --- a/seahub/invitations/views.py +++ b/seahub/invitations/views.py @@ -10,6 +10,7 @@ from seahub.auth import get_backends from seahub.base.accounts import User from seahub.constants import GUEST_USER from seahub.invitations.models import Invitation +from seahub.invitations.signals import accept_guest_invitation_successful from seahub.settings import SITE_ROOT def token_view(request, token): @@ -38,6 +39,11 @@ def token_view(request, token): for backend in get_backends(): u.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) auth_login(request, u) + + # send signal to notify inviter + accept_guest_invitation_successful.send( + sender=None, invitation_obj=i) + return HttpResponseRedirect(SITE_ROOT) return render_to_response('invitations/token_view.html', { diff --git a/seahub/notifications/management/commands/send_notices.py b/seahub/notifications/management/commands/send_notices.py index ccef67efbc..f0a379a69a 100644 --- a/seahub/notifications/management/commands/send_notices.py +++ b/seahub/notifications/management/commands/send_notices.py @@ -20,6 +20,7 @@ import seahub.settings as settings from seahub.avatar.templatetags.avatar_tags import avatar from seahub.avatar.util import get_default_avatar_url from seahub.base.templatetags.seahub_tags import email2nickname +from seahub.invitations.models import Invitation from seahub.profile.models import Profile # Get an instance of a logger @@ -169,6 +170,20 @@ class Command(BaseCommand): notice.author = author return notice + def format_guest_invitation_accepted_msg(self, notice): + d = json.loads(notice.detail) + inv_id = d['invitation_id'] + try: + inv = Invitation.objects.get(pk=inv_id) + except Invitation.DoesNotExist: + self.delete() + return None + + notice.inv_accepter = inv.accepter + notice.inv_url = '#invitations/' + notice.inv_accept_at = inv.accept_time.strftime("%Y-%m-%d %H:%M:%S") + return notice + def get_user_language(self, username): return Profile.objects.get_user_language(username) @@ -255,6 +270,12 @@ class Command(BaseCommand): elif notice.is_file_comment_msg(): notice = self.format_file_comment_msg(notice) + elif notice.is_guest_invitation_accepted_msg(): + notice = self.format_guest_invitation_accepted_msg(notice) + + if notice is None: + continue + notices.append(notice) if not notices: diff --git a/seahub/notifications/models.py b/seahub/notifications/models.py index a94a9bfb64..b9b4d3ca94 100644 --- a/seahub/notifications/models.py +++ b/seahub/notifications/models.py @@ -6,6 +6,7 @@ import json import logging from django.db import models +from django.conf import settings from django.forms import ModelForm, Textarea from django.utils.html import escape from django.utils.translation import ugettext as _ @@ -16,8 +17,10 @@ from seaserv import seafile_api, ccnet_api from seahub.base.fields import LowerCaseCharField from seahub.base.templatetags.seahub_tags import email2nickname +from seahub.invitations.models import Invitation from seahub.utils.repo import get_repo_shared_users from seahub.utils import normalize_cache_key +from seahub.utils.timeutils import datetime_to_isoformat_timestr # Get an instance of a logger logger = logging.getLogger(__name__) @@ -48,6 +51,7 @@ MSG_TYPE_REPO_SHARE = 'repo_share' MSG_TYPE_REPO_SHARE_TO_GROUP = 'repo_share_to_group' MSG_TYPE_USER_MESSAGE = 'user_message' MSG_TYPE_FILE_COMMENT = 'file_comment' +MSG_TYPE_GUEST_INVITATION_ACCEPTED = 'guest_invitation_accepted' USER_NOTIFICATION_COUNT_CACHE_PREFIX = 'USER_NOTIFICATION_COUNT_' @@ -86,6 +90,9 @@ def file_comment_msg_to_json(repo_id, file_path, author, comment): 'author': author, 'comment': comment}) +def guest_invitation_accepted_msg_to_json(invitation_id): + return json.dumps({'invitation_id': invitation_id}) + def get_cache_key_of_unseen_notifications(username): return normalize_cache_key(username, USER_NOTIFICATION_COUNT_CACHE_PREFIX) @@ -278,6 +285,13 @@ class UserNotificationManager(models.Manager): """ return self._add_user_notification(to_user, MSG_TYPE_FILE_COMMENT, detail) + def add_guest_invitation_accepted_msg(self, to_user, detail): + """Nofity ``to_user`` that a guest has accpeted an invitation. + """ + return self._add_user_notification( + to_user, MSG_TYPE_GUEST_INVITATION_ACCEPTED, detail) + + class UserNotification(models.Model): to_user = LowerCaseCharField(db_index=True, max_length=255) msg_type = models.CharField(db_index=True, max_length=30) @@ -369,6 +383,9 @@ class UserNotification(models.Model): def is_file_comment_msg(self): return self.msg_type == MSG_TYPE_FILE_COMMENT + def is_guest_invitation_accepted_msg(self): + return self.msg_type == MSG_TYPE_GUEST_INVITATION_ACCEPTED + def group_message_detail_to_dict(self): """Parse group message detail, returns dict contains ``group_id`` and ``msg_from``. @@ -692,6 +709,28 @@ class UserNotification(models.Model): } return msg + def format_guest_invitation_accepted_msg(self): + try: + d = json.loads(self.detail) + except Exception as e: + logger.error(e) + return _(u"Internal error") + + inv_id = d['invitation_id'] + try: + inv = Invitation.objects.get(pk=inv_id) + except Invitation.DoesNotExist: + self.delete() + return + + msg = _('Guest %(user)s accepted your invitation at %(time)s.') % { + 'user': inv.accepter, + 'href': settings.SITE_ROOT + '#invitations/', + 'time': inv.accept_time.strftime("%Y-%m-%d %H:%M:%S"), + } + return msg + + ########## handle signals from django.core.urlresolvers import reverse from django.dispatch import receiver @@ -700,6 +739,7 @@ from seahub.signals import upload_file_successful, comment_file_successful from seahub.group.signals import grpmsg_added, group_join_request, add_user_to_group from seahub.share.signals import share_repo_to_user_successful, \ share_repo_to_group_successful +from seahub.invitations.signals import accept_guest_invitation_successful @receiver(upload_file_successful) def add_upload_file_msg_cb(sender, **kwargs): @@ -803,3 +843,11 @@ def comment_file_successful_cb(sender, **kwargs): for u in notify_users: detail = file_comment_msg_to_json(repo.id, file_path, author, comment) UserNotification.objects.add_file_comment_msg(u, detail) + +@receiver(accept_guest_invitation_successful) +def accept_guest_invitation_successful_cb(sender, **kwargs): + inv_obj = kwargs['invitation_obj'] + + detail = guest_invitation_accepted_msg_to_json(inv_obj.pk) + UserNotification.objects.add_guest_invitation_accepted_msg( + inv_obj.inviter, detail) diff --git a/seahub/notifications/templates/notifications/notice_email.html b/seahub/notifications/templates/notifications/notice_email.html index 88eb8996c4..1fb790d41f 100644 --- a/seahub/notifications/templates/notifications/notice_email.html +++ b/seahub/notifications/templates/notifications/notice_email.html @@ -53,6 +53,9 @@ You've got {{num}} new notices on {{ site_name }}: {% elif notice.is_file_comment_msg %}

{% blocktrans with file_url=notice.file_url file_name=notice.file_name author=notice.author %}File {{file_name}} has a new comment from user {{author}}{% endblocktrans %}

+ {% elif notice.is_guest_invitation_accepted_msg %} +

{% blocktrans with user=notice.inv_accepter inv_url=notice.inv_url time=notice.inv_accept_at %}Guest {{user}} accepted your invitation at {{time}}.{% endblocktrans %}

+ {% endif %} {{ notice.timestamp|date:"Y-m-d G:i:s"}} diff --git a/seahub/notifications/templates/notifications/user_notification_tr.html b/seahub/notifications/templates/notifications/user_notification_tr.html index e7db05be50..c54ad24ef1 100644 --- a/seahub/notifications/templates/notifications/user_notification_tr.html +++ b/seahub/notifications/templates/notifications/user_notification_tr.html @@ -33,7 +33,10 @@

{{ notice.format_group_join_request|safe }}

{% elif notice.is_file_comment_msg %}

{{ notice.format_file_comment_msg|safe }}

- + + {% elif notice.is_guest_invitation_accepted_msg %} +

{{ notice.format_guest_invitation_accepted_msg|safe }}

+ {% endif %} {{ notice.timestamp|translate_seahub_time }} diff --git a/seahub/notifications/views.py b/seahub/notifications/views.py index 2a8f2bb3cc..efefa28619 100644 --- a/seahub/notifications/views.py +++ b/seahub/notifications/views.py @@ -197,6 +197,6 @@ def add_notice_from_info(notices): notice.default_avatar_url = default_avatar_url else: - pass + notice.default_avatar_url = default_avatar_url return notices diff --git a/seahub/templates/snippets/notice_html.html b/seahub/templates/snippets/notice_html.html index 3187539ce9..fe65bac56d 100644 --- a/seahub/templates/snippets/notice_html.html +++ b/seahub/templates/snippets/notice_html.html @@ -36,6 +36,9 @@ {% elif notice.is_file_comment_msg %}

{{ notice.format_file_comment_msg|safe }}

+ + {% elif notice.is_guest_invitation_accepted_msg %} +

{{ notice.format_guest_invitation_accepted_msg|safe }}

{% endif %} diff --git a/tests/seahub/invitations/test_views.py b/tests/seahub/invitations/test_views.py index 5b96dfeca9..4d99d3e710 100644 --- a/tests/seahub/invitations/test_views.py +++ b/tests/seahub/invitations/test_views.py @@ -1,7 +1,9 @@ +import json from django.utils import timezone from django.core.urlresolvers import reverse from seahub.invitations.models import Invitation +from seahub.notifications.models import UserNotification from seahub.test_utils import BaseTestCase @@ -41,3 +43,15 @@ class TokenViewTest(BaseTestCase): }) self.assertEqual(302, resp.status_code) assert Invitation.objects.get(pk=self.iv.pk).accept_time is None + + def test_can_notify_inviter(self): + assert len(UserNotification.objects.filter(to_user=self.user.username)) == 0 + resp = self.client.post(self.url, { + 'password': 'passwd' + }) + self.assertEqual(302, resp.status_code) + + assert len(UserNotification.objects.filter(to_user=self.user.username)) == 1 + obj = UserNotification.objects.all()[0] + d = json.loads(obj.detail) + assert d['invitation_id'] == self.iv.pk diff --git a/tests/seahub/notifications/management/commands/test_send_notices.py b/tests/seahub/notifications/management/commands/test_send_notices.py index d10be401e3..c7b918b44a 100644 --- a/tests/seahub/notifications/management/commands/test_send_notices.py +++ b/tests/seahub/notifications/management/commands/test_send_notices.py @@ -1,8 +1,10 @@ from django.core import mail from django.core.management import call_command +from seahub.invitations.models import Invitation from seahub.notifications.models import ( - UserNotification, repo_share_msg_to_json, file_comment_msg_to_json) + UserNotification, repo_share_msg_to_json, file_comment_msg_to_json, + guest_invitation_accepted_msg_to_json) from seahub.profile.models import Profile from seahub.test_utils import BaseTestCase @@ -43,3 +45,18 @@ class CommandTest(BaseTestCase): assert mail.outbox[0].to[0] == 'a@a.com' assert 'new comment from user %s' % self.user.username in mail.outbox[0].body assert '/foo' in mail.outbox[0].body + + def test_send_guest_invitation_notice(self): + self.assertEqual(len(mail.outbox), 0) + + inv = Invitation.objects.add(self.user.username, 'test@test.com') + inv.accept() + + detail = guest_invitation_accepted_msg_to_json(inv.pk) + UserNotification.objects.add_guest_invitation_accepted_msg( + inv.inviter, detail) + + call_command('send_notices') + self.assertEqual(len(mail.outbox), 1) + assert mail.outbox[0].to[0] == self.user.username + assert 'Guest test@test.com' in mail.outbox[0].body From 8fe3e0fa53dc65529a0f23d51b0a0701600a5fcf Mon Sep 17 00:00:00 2001 From: zhengxie Date: Tue, 2 Jan 2018 10:42:06 +0800 Subject: [PATCH 2/2] [notification] Refactor code --- seahub/notifications/views.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/seahub/notifications/views.py b/seahub/notifications/views.py index efefa28619..953d4fe563 100644 --- a/seahub/notifications/views.py +++ b/seahub/notifications/views.py @@ -139,22 +139,17 @@ def add_notice_from_info(notices): ''' default_avatar_url = get_default_avatar_url() for notice in notices: + notice.default_avatar_url = default_avatar_url + if notice.is_user_message(): d = notice.user_message_detail_to_dict() if d.get('msg_from') is not None: notice.msg_from = d.get('msg_from') - else: - notice.default_avatar_url = default_avatar_url elif notice.is_group_msg(): d = notice.group_message_detail_to_dict() if d.get('msg_from') is not None: notice.msg_from = d.get('msg_from') - else: - notice.default_avatar_url = default_avatar_url - - elif notice.is_file_uploaded_msg(): - notice.default_avatar_url = default_avatar_url elif notice.is_repo_share_msg(): try: @@ -162,7 +157,6 @@ def add_notice_from_info(notices): notice.msg_from = d['share_from'] except Exception as e: logger.error(e) - notice.default_avatar_url = default_avatar_url elif notice.is_repo_share_to_group_msg(): try: @@ -170,7 +164,6 @@ def add_notice_from_info(notices): notice.msg_from = d['share_from'] except Exception as e: logger.error(e) - notice.default_avatar_url = default_avatar_url elif notice.is_group_join_request(): try: @@ -178,7 +171,6 @@ def add_notice_from_info(notices): notice.msg_from = d['username'] except Exception as e: logger.error(e) - notice.default_avatar_url = default_avatar_url elif notice.is_add_user_to_group(): try: @@ -186,7 +178,6 @@ def add_notice_from_info(notices): notice.msg_from = d['group_staff'] except Exception as e: logger.error(e) - notice.default_avatar_url = default_avatar_url elif notice.is_file_comment_msg(): try: @@ -194,9 +185,5 @@ def add_notice_from_info(notices): notice.msg_from = d['author'] except Exception as e: logger.error(e) - notice.default_avatar_url = default_avatar_url - - else: - notice.default_avatar_url = default_avatar_url return notices