Skip to content
This repository has been archived by the owner on Jan 19, 2021. It is now read-only.

Commit

Permalink
[Fix bug 1258997] Allow group curators to resend group invitation email.
Browse files Browse the repository at this point in the history
  • Loading branch information
johngian committed Mar 28, 2016
1 parent c3a07fd commit 38b6fe6
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 4 deletions.
50 changes: 50 additions & 0 deletions mozillians/groups/tests/test_views/test_invite.py
@@ -1,7 +1,9 @@
from django.core.urlresolvers import reverse

from mock import patch, ANY
from nose.tools import eq_, ok_

from mozillians.common.templatetags.helpers import urlparams
from mozillians.common.tests import TestCase
from mozillians.groups.models import GroupMembership, Invite
from mozillians.groups.tests import InviteFactory
Expand Down Expand Up @@ -59,3 +61,51 @@ def test_accept_reject_user_not_redeemer(self):
url = reverse('groups:accept_reject_invitation', args=[invite.pk, 'accept'])
response = client.get(url, follow=True)
eq_(response.status_code, 404)

@patch('mozillians.groups.views.notify_redeemer_invitation')
@patch('mozillians.groups.views.messages.success')
def test_send_invitation_email(self, mock_success, mock_notification):
curator = UserFactory.create()
redeemer = UserFactory.create(userprofile={'full_name': 'Foo Bar'})
invite = InviteFactory.create(inviter=curator.userprofile, redeemer=redeemer.userprofile)
invite.group.curators.add(curator.userprofile)

with self.login(curator) as client:
url = urlparams(reverse('groups:send_invitation_email',
args=[invite.pk]), 'invitation')
response = client.get(url, follow=True)
eq_(response.status_code, 200)

mock_notification.delay.assert_called_once_with(invite.pk)
msg = 'Invitation to Foo Bar has been sent successfully.'
mock_success.assert_called_once_with(ANY, msg)

@patch('mozillians.groups.views.notify_redeemer_invitation')
@patch('mozillians.groups.views.messages.success')
def test_send_invitation_email_different_curator(self, mock_success, mock_notification):
curator, inviter = UserFactory.create_batch(2)
redeemer = UserFactory.create(userprofile={'full_name': 'Foo Bar'})
invite = InviteFactory.create(inviter=inviter.userprofile, redeemer=redeemer.userprofile)
invite.group.curators.add(curator.userprofile)
invite.group.curators.add(inviter.userprofile)

with self.login(curator) as client:
url = urlparams(reverse('groups:send_invitation_email',
args=[invite.pk]), 'invitation')
response = client.get(url, follow=True)
eq_(response.status_code, 200)

mock_notification.delay.assert_called_once_with(invite.pk)
msg = 'Invitation to Foo Bar has been sent successfully.'
mock_success.assert_called_once_with(ANY, msg)

def test_send_invitation_email_no_curator_manager(self):
inviter, redeemer = UserFactory.create_batch(2)
invite = InviteFactory.create(inviter=inviter.userprofile, redeemer=redeemer.userprofile)
user = UserFactory.create()

with self.login(user) as client:
url = urlparams(reverse('groups:send_invitation_email',
args=[invite.pk]), 'invitation')
response = client.get(url, follow=True)
eq_(response.status_code, 404)
2 changes: 2 additions & 0 deletions mozillians/groups/urls.py
Expand Up @@ -46,6 +46,8 @@
name='curators-autocomplete'),
# Invites section
url('^groups/invite/(?P<invite_pk>\d+)/delete/$', 'views.delete_invite', name='delete_invite'),
url('^groups/invite/(?P<invite_pk>\d+)/notify/$', 'views.send_invitation_email',
name='send_invitation_email'),
url('^groups/(?P<invite_pk>\d+)/(?P<action>accept|reject)/$',
'views.accept_reject_invitation', name='accept_reject_invitation'),
)
25 changes: 23 additions & 2 deletions mozillians/groups/views.py
Expand Up @@ -21,8 +21,9 @@
from mozillians.groups import forms
from mozillians.groups.models import Group, GroupMembership, Invite, Skill
from mozillians.groups.tasks import (notify_curators_invitation_accepted,
notify_redeemer_invitation_invalid,
notify_curators_invitation_rejected)
notify_curators_invitation_rejected,
notify_redeemer_invitation,
notify_redeemer_invitation_invalid)
from mozillians.users.models import UserProfile


Expand Down Expand Up @@ -554,3 +555,23 @@ def accept_reject_invitation(request, invite_pk, action):
invite.delete()

return redirect(reverse('groups:show_group', args=[invite.group.url]))


@never_cache
def send_invitation_email(request, invite_pk):
"""Send group invitation email."""

invite = get_object_or_404(Invite, pk=invite_pk)
is_curator = invite.group.curators.filter(pk=request.user.userprofile.pk).exists()
is_manager = request.user.userprofile.is_manager

if not (is_curator or is_manager):
raise Http404

notify_redeemer_invitation.delay(invite.pk)
msg = _(u'Invitation to {0} has been sent successfully.'.format(invite.redeemer))
messages.success(request, msg)
next_section = request.GET.get('next')
next_url = urlparams(reverse('groups:group_edit', args=[invite.group.url]), next_section)

return HttpResponseRedirect(next_url)
5 changes: 3 additions & 2 deletions mozillians/jinja2/groups/includes/group_edit_invitation.html
Expand Up @@ -30,10 +30,11 @@
</div>
<div class="col-sm-4">
<div class="invite-controls right">
<a href="{{ url('groups:delete_invite', redeemer.groups_invited.get(group=group).pk) }}?next=invitation">
{% set invite_pk = redeemer.groups_invited.get(group=group).pk %}
<a href="{{ url('groups:delete_invite', invite_pk) }}?next=invitation">
<span class="glyphicon glyphicon-remove" title="{{ _('Delete') }}" aria-hidden="true"></span>
</a>
<a href="#">
<a href="{{ url('groups:send_invitation_email', invite_pk) }}?next=invitation">
<span class="glyphicon glyphicon-repeat"title="{{ _('Resend') }}" aria-hidden="true"></span>
</a>
</div>
Expand Down

0 comments on commit 38b6fe6

Please sign in to comment.