Merge lp:~gmb/launchpad/dont-leak-privacy-in-notifications-bug-373683 into lp:launchpad/db-devel

Proposed by Graham Binns
Status: Merged
Merged at revision: 9442
Proposed branch: lp:~gmb/launchpad/dont-leak-privacy-in-notifications-bug-373683
Merge into: lp:launchpad/db-devel
Diff against target: 188 lines (+148/-7)
2 files modified
lib/lp/bugs/adapters/bugchange.py (+34/-6)
lib/lp/bugs/tests/test_bugchanges.py (+114/-1)
To merge this branch: bzr merge lp:~gmb/launchpad/dont-leak-privacy-in-notifications-bug-373683
Reviewer Review Type Date Requested Status
Leonard Richardson (community) code Approve
Review via email: mp+27051@code.launchpad.net

Commit message

Private bug summaries will no longer be included in bug duplication notifications.

Description of the change

This branch fixes bug 373683 by preventing bug notifications generated when a bug is marked a duplicate of a private bug from including the private bug's summary.

I've made the following changes:

 * lib/lp/bugs/adapters/bugchange.py
  * I've updated BugDuplicateChange to make it not include private bug summaries.
 * lib/lp/bugs/tests/test_bugchange.py
  * I've updated the tests to test the above change.

I did consider refactoring BugDuplicateChange.getBugNotification() to make it into something that wasn't just a bunch of nested if/elif/elses, but I couldn't think of an elegant solution (feel free to suggest one). That said, the method is pretty short so I'm not sure I'm not just bikeshedding.

To post a comment you must log in.
Revision history for this message
Leonard Richardson (leonardr) wrote :

r=me with some minor changes.

Did you mean to merge this with devel rather than db-devel? I make that mistake all the time.

Rather than bikeshedding the logic of the message generator, I suggest you just define four constants so you don't write the same string multiple times.

75 # extra notificationse by mistake.
118 # extra notificationse by mistake.
(Should be 'notifications')

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/adapters/bugchange.py'
2--- lib/lp/bugs/adapters/bugchange.py 2010-01-20 17:46:53 +0000
3+++ lib/lp/bugs/adapters/bugchange.py 2010-06-09 16:28:30 +0000
4@@ -366,17 +366,45 @@
5
6 def getBugNotification(self):
7 if self.old_value is not None and self.new_value is not None:
8- text = ("** This bug is no longer a duplicate of bug %d\n"
9- " %s\n"
10+ if self.old_value.private:
11+ old_value_text = (
12+ "** This bug is no longer a duplicate of private bug "
13+ "%d" % self.old_value.id)
14+ else:
15+ old_value_text = (
16+ "** This bug is no longer a duplicate of bug %d\n"
17+ " %s" % (self.old_value.id, self.old_value.title))
18+ if self.new_value.private:
19+ new_value_text = (
20+ "** This bug has been marked a duplicate of private bug "
21+ "%d" % self.new_value.id)
22+ else:
23+ new_value_text = (
24 "** This bug has been marked a duplicate of bug %d\n"
25- " %s" % (self.old_value.id, self.old_value.title,
26- self.new_value.id, self.new_value.title))
27+ " %s" % (self.new_value.id, self.new_value.title))
28+
29+ text = "\n".join((old_value_text, new_value_text))
30+
31 elif self.old_value is None:
32- text = ("** This bug has been marked a duplicate of bug %d\n"
33+ if self.new_value.private:
34+ text = (
35+ "** This bug has been marked a duplicate of private bug "
36+ "%d" % self.new_value.id)
37+ else:
38+ text = (
39+ "** This bug has been marked a duplicate of bug %d\n"
40 " %s" % (self.new_value.id, self.new_value.title))
41+
42 elif self.new_value is None:
43- text = ("** This bug is no longer a duplicate of bug %d\n"
44+ if self.old_value.private:
45+ text = (
46+ "** This bug is no longer a duplicate of private bug "
47+ "%d" % self.old_value.id)
48+ else:
49+ text = (
50+ "** This bug is no longer a duplicate of bug %d\n"
51 " %s" % (self.old_value.id, self.old_value.title))
52+
53 else:
54 raise AssertionError(
55 "There is no change: both the old bug and new bug are None.")
56
57=== modified file 'lib/lp/bugs/tests/test_bugchanges.py'
58--- lib/lp/bugs/tests/test_bugchanges.py 2010-06-03 18:55:41 +0000
59+++ lib/lp/bugs/tests/test_bugchanges.py 2010-06-09 16:28:30 +0000
60@@ -1265,7 +1265,7 @@
61 self.saveOldChanges(self.bug, append=True)
62 # Save the initial "bug created" notifications before
63 # marking this bug a duplicate, so that we don't get
64- # extra notificationse by mistake.
65+ # extra notifications by mistake.
66 duplicate_bug_recipients = duplicate_bug.getBugNotificationRecipients(
67 level=BugNotificationLevel.METADATA).getRecipients()
68 self.changeAttribute(duplicate_bug, 'duplicateof', self.bug)
69@@ -1360,6 +1360,119 @@
70 expected_activity=expected_activity,
71 expected_notification=expected_notification)
72
73+ def test_duplicate_private_bug(self):
74+ # When a bug is marked as the duplicate of a private bug the
75+ # private bug's summary won't be included in the notification.
76+ private_bug = self.factory.makeBug()
77+ private_bug.setPrivate(True, self.user)
78+ public_bug = self.factory.makeBug()
79+ self.saveOldChanges(private_bug)
80+ self.saveOldChanges(public_bug)
81+
82+ # Save the initial "bug created" notifications before
83+ # marking this bug a duplicate, so that we don't get
84+ # extra notifications by mistake.
85+ public_bug_recipients = public_bug.getBugNotificationRecipients(
86+ level=BugNotificationLevel.METADATA).getRecipients()
87+ self.changeAttribute(public_bug, 'duplicateof', private_bug)
88+
89+ expected_activity = {
90+ 'person': self.user,
91+ 'whatchanged': 'marked as duplicate',
92+ 'oldvalue': None,
93+ 'newvalue': str(private_bug.id),
94+ }
95+
96+ expected_notification = {
97+ 'person': self.user,
98+ 'text': (
99+ "** This bug has been marked a duplicate of private bug %d"
100+ % private_bug.id),
101+ 'recipients': public_bug_recipients,
102+ }
103+
104+ self.assertRecordedChange(
105+ expected_activity=expected_activity,
106+ expected_notification=expected_notification,
107+ bug=public_bug)
108+
109+ def test_unmarked_as_duplicate_of_private_bug(self):
110+ # When a bug is unmarked as a duplicate of a private bug,
111+ # the private bug's summary isn't sent in the notification.
112+ private_bug = self.factory.makeBug()
113+ private_bug.setPrivate(True, self.user)
114+ public_bug = self.factory.makeBug()
115+
116+ # Save the initial "bug created" notifications before
117+ # marking this bug a duplicate, so that we don't get
118+ # extra notifications by mistake.
119+ public_bug_recipients = public_bug.getBugNotificationRecipients(
120+ level=BugNotificationLevel.METADATA).getRecipients()
121+ self.changeAttribute(public_bug, 'duplicateof', private_bug)
122+
123+ self.saveOldChanges(private_bug)
124+ self.saveOldChanges(public_bug)
125+
126+ self.changeAttribute(public_bug, 'duplicateof', None)
127+
128+ expected_activity = {
129+ 'person': self.user,
130+ 'whatchanged': 'removed duplicate marker',
131+ 'oldvalue': str(private_bug.id),
132+ 'newvalue': None,
133+ }
134+
135+ expected_notification = {
136+ 'person': self.user,
137+ 'text': (
138+ "** This bug is no longer a duplicate of private bug %d"
139+ % private_bug.id),
140+ 'recipients': public_bug_recipients,
141+ }
142+
143+ self.assertRecordedChange(
144+ expected_activity=expected_activity,
145+ expected_notification=expected_notification,
146+ bug=public_bug)
147+
148+ def test_changed_private_duplicate(self):
149+ # When a bug is change from being the duplicate of a private bug
150+ # to being the duplicate of a public bug, the private bug's
151+ # summary won't be sent in the notification.
152+ private_bug = self.factory.makeBug()
153+ private_bug.setPrivate(True, self.user)
154+ duplicate_bug = self.factory.makeBug()
155+ public_bug = self.factory.makeBug()
156+ bug_recipients = duplicate_bug.getBugNotificationRecipients(
157+ level=BugNotificationLevel.METADATA).getRecipients()
158+
159+ self.changeAttribute(duplicate_bug, 'duplicateof', private_bug)
160+ self.saveOldChanges(duplicate_bug)
161+
162+ self.changeAttribute(duplicate_bug, 'duplicateof', public_bug)
163+
164+ expected_activity = {
165+ 'person': self.user,
166+ 'whatchanged': 'changed duplicate marker',
167+ 'oldvalue': str(private_bug.id),
168+ 'newvalue': str(public_bug.id),
169+ }
170+
171+ expected_notification = {
172+ 'person': self.user,
173+ 'text': (
174+ "** This bug is no longer a duplicate of private bug %d\n"
175+ "** This bug has been marked a duplicate of bug %d\n"
176+ " %s" % (private_bug.id, public_bug.id,
177+ public_bug.title)),
178+ 'recipients': bug_recipients,
179+ }
180+
181+ self.assertRecordedChange(
182+ expected_activity=expected_activity,
183+ expected_notification=expected_notification,
184+ bug=duplicate_bug)
185+
186 def test_convert_to_question_no_comment(self):
187 # When a bug task is converted to a question, its status is
188 # first set to invalid, which causes the normal notifications for

Subscribers

People subscribed via source and target branches

to status/vote changes: