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.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.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