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
=== modified file 'lib/lp/bugs/adapters/bugchange.py'
--- lib/lp/bugs/adapters/bugchange.py 2010-01-20 17:46:53 +0000
+++ lib/lp/bugs/adapters/bugchange.py 2010-06-09 16:28:30 +0000
@@ -366,17 +366,45 @@
366366
367 def getBugNotification(self):367 def getBugNotification(self):
368 if self.old_value is not None and self.new_value is not None:368 if self.old_value is not None and self.new_value is not None:
369 text = ("** This bug is no longer a duplicate of bug %d\n"369 if self.old_value.private:
370 " %s\n"370 old_value_text = (
371 "** This bug is no longer a duplicate of private bug "
372 "%d" % self.old_value.id)
373 else:
374 old_value_text = (
375 "** This bug is no longer a duplicate of bug %d\n"
376 " %s" % (self.old_value.id, self.old_value.title))
377 if self.new_value.private:
378 new_value_text = (
379 "** This bug has been marked a duplicate of private bug "
380 "%d" % self.new_value.id)
381 else:
382 new_value_text = (
371 "** This bug has been marked a duplicate of bug %d\n"383 "** This bug has been marked a duplicate of bug %d\n"
372 " %s" % (self.old_value.id, self.old_value.title,384 " %s" % (self.new_value.id, self.new_value.title))
373 self.new_value.id, self.new_value.title))385
386 text = "\n".join((old_value_text, new_value_text))
387
374 elif self.old_value is None:388 elif self.old_value is None:
375 text = ("** This bug has been marked a duplicate of bug %d\n"389 if self.new_value.private:
390 text = (
391 "** This bug has been marked a duplicate of private bug "
392 "%d" % self.new_value.id)
393 else:
394 text = (
395 "** This bug has been marked a duplicate of bug %d\n"
376 " %s" % (self.new_value.id, self.new_value.title))396 " %s" % (self.new_value.id, self.new_value.title))
397
377 elif self.new_value is None:398 elif self.new_value is None:
378 text = ("** This bug is no longer a duplicate of bug %d\n"399 if self.old_value.private:
400 text = (
401 "** This bug is no longer a duplicate of private bug "
402 "%d" % self.old_value.id)
403 else:
404 text = (
405 "** This bug is no longer a duplicate of bug %d\n"
379 " %s" % (self.old_value.id, self.old_value.title))406 " %s" % (self.old_value.id, self.old_value.title))
407
380 else:408 else:
381 raise AssertionError(409 raise AssertionError(
382 "There is no change: both the old bug and new bug are None.")410 "There is no change: both the old bug and new bug are None.")
383411
=== modified file 'lib/lp/bugs/tests/test_bugchanges.py'
--- lib/lp/bugs/tests/test_bugchanges.py 2010-06-03 18:55:41 +0000
+++ lib/lp/bugs/tests/test_bugchanges.py 2010-06-09 16:28:30 +0000
@@ -1265,7 +1265,7 @@
1265 self.saveOldChanges(self.bug, append=True)1265 self.saveOldChanges(self.bug, append=True)
1266 # Save the initial "bug created" notifications before1266 # Save the initial "bug created" notifications before
1267 # marking this bug a duplicate, so that we don't get1267 # marking this bug a duplicate, so that we don't get
1268 # extra notificationse by mistake.1268 # extra notifications by mistake.
1269 duplicate_bug_recipients = duplicate_bug.getBugNotificationRecipients(1269 duplicate_bug_recipients = duplicate_bug.getBugNotificationRecipients(
1270 level=BugNotificationLevel.METADATA).getRecipients()1270 level=BugNotificationLevel.METADATA).getRecipients()
1271 self.changeAttribute(duplicate_bug, 'duplicateof', self.bug)1271 self.changeAttribute(duplicate_bug, 'duplicateof', self.bug)
@@ -1360,6 +1360,119 @@
1360 expected_activity=expected_activity,1360 expected_activity=expected_activity,
1361 expected_notification=expected_notification)1361 expected_notification=expected_notification)
13621362
1363 def test_duplicate_private_bug(self):
1364 # When a bug is marked as the duplicate of a private bug the
1365 # private bug's summary won't be included in the notification.
1366 private_bug = self.factory.makeBug()
1367 private_bug.setPrivate(True, self.user)
1368 public_bug = self.factory.makeBug()
1369 self.saveOldChanges(private_bug)
1370 self.saveOldChanges(public_bug)
1371
1372 # Save the initial "bug created" notifications before
1373 # marking this bug a duplicate, so that we don't get
1374 # extra notifications by mistake.
1375 public_bug_recipients = public_bug.getBugNotificationRecipients(
1376 level=BugNotificationLevel.METADATA).getRecipients()
1377 self.changeAttribute(public_bug, 'duplicateof', private_bug)
1378
1379 expected_activity = {
1380 'person': self.user,
1381 'whatchanged': 'marked as duplicate',
1382 'oldvalue': None,
1383 'newvalue': str(private_bug.id),
1384 }
1385
1386 expected_notification = {
1387 'person': self.user,
1388 'text': (
1389 "** This bug has been marked a duplicate of private bug %d"
1390 % private_bug.id),
1391 'recipients': public_bug_recipients,
1392 }
1393
1394 self.assertRecordedChange(
1395 expected_activity=expected_activity,
1396 expected_notification=expected_notification,
1397 bug=public_bug)
1398
1399 def test_unmarked_as_duplicate_of_private_bug(self):
1400 # When a bug is unmarked as a duplicate of a private bug,
1401 # the private bug's summary isn't sent in the notification.
1402 private_bug = self.factory.makeBug()
1403 private_bug.setPrivate(True, self.user)
1404 public_bug = self.factory.makeBug()
1405
1406 # Save the initial "bug created" notifications before
1407 # marking this bug a duplicate, so that we don't get
1408 # extra notifications by mistake.
1409 public_bug_recipients = public_bug.getBugNotificationRecipients(
1410 level=BugNotificationLevel.METADATA).getRecipients()
1411 self.changeAttribute(public_bug, 'duplicateof', private_bug)
1412
1413 self.saveOldChanges(private_bug)
1414 self.saveOldChanges(public_bug)
1415
1416 self.changeAttribute(public_bug, 'duplicateof', None)
1417
1418 expected_activity = {
1419 'person': self.user,
1420 'whatchanged': 'removed duplicate marker',
1421 'oldvalue': str(private_bug.id),
1422 'newvalue': None,
1423 }
1424
1425 expected_notification = {
1426 'person': self.user,
1427 'text': (
1428 "** This bug is no longer a duplicate of private bug %d"
1429 % private_bug.id),
1430 'recipients': public_bug_recipients,
1431 }
1432
1433 self.assertRecordedChange(
1434 expected_activity=expected_activity,
1435 expected_notification=expected_notification,
1436 bug=public_bug)
1437
1438 def test_changed_private_duplicate(self):
1439 # When a bug is change from being the duplicate of a private bug
1440 # to being the duplicate of a public bug, the private bug's
1441 # summary won't be sent in the notification.
1442 private_bug = self.factory.makeBug()
1443 private_bug.setPrivate(True, self.user)
1444 duplicate_bug = self.factory.makeBug()
1445 public_bug = self.factory.makeBug()
1446 bug_recipients = duplicate_bug.getBugNotificationRecipients(
1447 level=BugNotificationLevel.METADATA).getRecipients()
1448
1449 self.changeAttribute(duplicate_bug, 'duplicateof', private_bug)
1450 self.saveOldChanges(duplicate_bug)
1451
1452 self.changeAttribute(duplicate_bug, 'duplicateof', public_bug)
1453
1454 expected_activity = {
1455 'person': self.user,
1456 'whatchanged': 'changed duplicate marker',
1457 'oldvalue': str(private_bug.id),
1458 'newvalue': str(public_bug.id),
1459 }
1460
1461 expected_notification = {
1462 'person': self.user,
1463 'text': (
1464 "** This bug is no longer a duplicate of private bug %d\n"
1465 "** This bug has been marked a duplicate of bug %d\n"
1466 " %s" % (private_bug.id, public_bug.id,
1467 public_bug.title)),
1468 'recipients': bug_recipients,
1469 }
1470
1471 self.assertRecordedChange(
1472 expected_activity=expected_activity,
1473 expected_notification=expected_notification,
1474 bug=duplicate_bug)
1475
1363 def test_convert_to_question_no_comment(self):1476 def test_convert_to_question_no_comment(self):
1364 # When a bug task is converted to a question, its status is1477 # When a bug task is converted to a question, its status is
1365 # first set to invalid, which causes the normal notifications for1478 # first set to invalid, which causes the normal notifications for

Subscribers

People subscribed via source and target branches

to status/vote changes: