Merge lp:~edwin-grubbs/launchpad/bug-498181-addmember-notify-oops into lp:launchpad

Proposed by Edwin Grubbs
Status: Merged
Approved by: Curtis Hovey
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~edwin-grubbs/launchpad/bug-498181-addmember-notify-oops
Merge into: lp:launchpad
Diff against target: 73 lines (+35/-3)
3 files modified
lib/canonical/launchpad/mailnotification.py (+5/-2)
lib/lp/registry/interfaces/person.py (+2/-0)
lib/lp/registry/stories/webservice/xx-person.txt (+28/-1)
To merge this branch: bzr merge lp:~edwin-grubbs/launchpad/bug-498181-addmember-notify-oops
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+17333@code.launchpad.net

Commit message

Fix oops when a user proposes another person as a member of a team via the REST API.

To post a comment you must log in.
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

Summary
-------

In the UI, a user can only propose themself or a team they admin as a
member of another team. Some users of launchpadlib, started proposing
other people to keep track of their mentees. When the proposed member's
email addresses are hidden, this would result in an oops, since
addMember() would trigger an event that tries to email all the
admins of the team with the Reply-To header set to the email of
the proposed member. Since the member is being proposed by someone
else in the same way that teams are proposed, the Reply-To
will be set to the reviewer's email address.

Tests
-----

./bin/test -vv -t webservice/xx-person.txt

Demo and Q/A
------------

With launchpadlib, propose a member with hidden email addresses.

Revision history for this message
Curtis Hovey (sinzui) wrote :

This is a fine compromise betweent he API and Web interfaces. I have one grammatical suggestion.

=== modified file 'lib/canonical/launchpad/mailnotification.py'
--- lib/canonical/launchpad/mailnotification.py 2009-12-05 18:37:28 +0000
+++ lib/canonical/launchpad/mailnotification.py 2010-01-14 01:55:22 +0000
@@ -953,10 +953,13 @@
             'new-member-notification-for-admins.txt')
         subject = '%s joined %s' % (person.name, team.name)
     elif membership.status == proposed:
- if person.isTeam():
+ # In the UI, a user can only propose themself or a team they

grammar: s/themself/himself/

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== renamed file 'lib/canonical/launchpad/emailtemplates/pending-membership-approval-for-teams.txt' => 'lib/canonical/launchpad/emailtemplates/pending-membership-approval-for-third-party.txt'
2=== modified file 'lib/canonical/launchpad/mailnotification.py'
3--- lib/canonical/launchpad/mailnotification.py 2009-12-05 18:37:28 +0000
4+++ lib/canonical/launchpad/mailnotification.py 2010-01-14 23:01:13 +0000
5@@ -953,10 +953,13 @@
6 'new-member-notification-for-admins.txt')
7 subject = '%s joined %s' % (person.name, team.name)
8 elif membership.status == proposed:
9- if person.isTeam():
10+ # In the UI, a user can only propose himself or a team he
11+ # admins. Some users of the REST API have a workflow, where
12+ # they propose users that are designated as mentees (Bug 498181).
13+ if reviewer != person:
14 headers = {"Reply-To": reviewer.preferredemail.email}
15 template = get_email_template(
16- 'pending-membership-approval-for-teams.txt')
17+ 'pending-membership-approval-for-third-party.txt')
18 else:
19 headers = {"Reply-To": person.preferredemail.email}
20 template = get_email_template('pending-membership-approval.txt')
21
22=== modified file 'lib/lp/registry/interfaces/person.py'
23--- lib/lp/registry/interfaces/person.py 2010-01-07 06:27:46 +0000
24+++ lib/lp/registry/interfaces/person.py 2010-01-14 23:01:13 +0000
25@@ -1421,6 +1421,8 @@
26
27 :param status: `TeamMembershipStatus` value must be either
28 Approved, Proposed or Admin.
29+ If the new member is a team, the status will be changed to
30+ Invited unless the user is also an admin of that team.
31
32 :param force_team_add: If the person is actually a team and
33 force_team_add is False, the team will actually be invited to
34
35=== modified file 'lib/lp/registry/stories/webservice/xx-person.txt'
36--- lib/lp/registry/stories/webservice/xx-person.txt 2009-12-17 10:33:34 +0000
37+++ lib/lp/registry/stories/webservice/xx-person.txt 2010-01-14 23:01:13 +0000
38@@ -545,7 +545,34 @@
39 ... "/~landscape-developers/+member/salgado").jsonBody()['status']
40 u'Deactivated'
41
42-Adding an arbitrary member to a team:
43+Though it is not possible through the Launchpad UI, some users of the
44+REST API propose other people (as opposed to teams) as part of a
45+mentoring process (Bug 498181).
46+
47+ >>> from canonical.launchpad.testing.pages import webservice_for_person
48+ >>> from canonical.launchpad.webapp.interfaces import OAuthPermission
49+ >>> from lp.registry.interfaces.person import IPersonSet
50+ >>> from zope.component import getUtility
51+ >>> login(ANONYMOUS)
52+ >>> owner = getUtility(IPersonSet).getByName('owner')
53+ >>> logout()
54+ >>> owner_webservice = webservice_for_person(
55+ ... owner, permission=OAuthPermission.WRITE_PRIVATE)
56+
57+ # The sample user (name12) is used to verify that it works when
58+ # the new member's email address is hidden.
59+ >>> print owner_webservice.named_post(
60+ ... webservice.getAbsoluteUrl('~otherteam'), 'addMember', {},
61+ ... person=webservice.getAbsoluteUrl('/~name12'),
62+ ... status='Proposed', comment='Just a test')
63+ HTTP/1.1 200 Ok
64+ ...
65+ >>> owner_webservice.get("/~otherteam/+member/name12"
66+ ... ).jsonBody()['status']
67+ u'Proposed'
68+
69+Adding a team as a new member will result in the membership being
70+set to the Invited status.
71
72 >>> print webservice.named_post(
73 ... ubuntu_team['self_link'], 'addMember', {},