Merge lp:~wgrant/launchpad/hide-inaccessible-bugs into lp:launchpad

Proposed by William Grant
Status: Merged
Approved by: William Grant
Approved revision: no longer in the source branch.
Merged at revision: 12607
Proposed branch: lp:~wgrant/launchpad/hide-inaccessible-bugs
Merge into: lp:launchpad
Prerequisite: lp:~wgrant/launchpad/delete-nullbugtask
Diff against target: 419 lines (+31/-159)
16 files modified
lib/canonical/launchpad/browser/launchpad.py (+1/-1)
lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt (+2/-2)
lib/canonical/launchpad/pagetests/webservice/security.txt (+2/-4)
lib/lp/bugs/browser/bugtask.py (+7/-5)
lib/lp/bugs/browser/malone.py (+1/-1)
lib/lp/bugs/browser/tests/bugtask-edit-views.txt (+0/-78)
lib/lp/bugs/browser/tests/test_bugattachment_file_access.py (+3/-3)
lib/lp/bugs/browser/tests/test_bugtask.py (+2/-2)
lib/lp/bugs/stories/bug-privacy/20-private-distro-bug-not-visible-to-anonymous.txt (+1/-1)
lib/lp/bugs/stories/bug-privacy/30-private-distro-bug-not-visible-to-nonsubscriber-user.txt (+1/-1)
lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.txt (+2/-2)
lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt (+1/-1)
lib/lp/bugs/stories/cve/xx-cve-link-to-modified-target.txt (+0/-39)
lib/lp/bugs/stories/upstream-bugprivacy/10-file-private-upstream-bug.txt (+3/-3)
lib/lp/bugs/stories/upstream-bugprivacy/30-private-upstream-bug-not-accessible-to-anonymous.txt (+3/-10)
lib/lp/bugs/stories/upstream-bugprivacy/50-private-upstream-bug-not-accessible-to-nonsubscriber-user.txt (+2/-6)
To merge this branch: bzr merge lp:~wgrant/launchpad/hide-inaccessible-bugs
Reviewer Review Type Date Requested Status
Steve Kowalik (community) code Approve
Review via email: mp+53529@code.launchpad.net

Commit message

[bug=365489,589701,712094,735353] [r=stevenk][bug=735353] Make private bugs 404 for users who cannot see them, and remove NullBugTask.

Description of the change

This branch brings private bugs inline with private teams, denying their existence for users who cannot see them. A few tests needed to be updated.

I also dropped xx-cve-link-to-modified-target.txt, as it is rendered obsolete by a prereq -- there is no chance of an OOPS any more, as the form submission redirects to the new location, avoiding a NullBugTask.

To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) wrote :

While I think that returning 404 sounds more like security-through-oh-look-nothing-to-see-here-move-along, I think that is better than returning a 401, and nice work on killing a six year old XXX, and removal of a doctest.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/browser/launchpad.py'
2--- lib/canonical/launchpad/browser/launchpad.py 2011-03-08 21:03:55 +0000
3+++ lib/canonical/launchpad/browser/launchpad.py 2011-03-16 00:53:41 +0000
4@@ -707,7 +707,7 @@
5 except NotFoundError:
6 raise NotFound(self.context, bug_number)
7 if not check_permission("launchpad.View", bug):
8- raise Unauthorized("Bug %s is private" % bug_number)
9+ return None
10 # Empty the traversal stack, since we're redirecting.
11 self.request.setTraversalStack([])
12 # And perform a temporary redirect.
13
14=== modified file 'lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt'
15--- lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt 2011-01-12 23:07:40 +0000
16+++ lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt 2011-03-16 00:53:41 +0000
17@@ -288,8 +288,8 @@
18 traversed we will get a 404. For paths using the old attachments/<id>
19 form, a 404 will be issued immediately; no redirect will be sent.
20
21->>> check_not_found("/firefox/+bug/2/attachments/1")
22->>> check_not_found("/firefox/+bug/2/+attachment/1")
23+>>> check_not_found("/tomcat/+bug/2/attachments/1")
24+>>> check_not_found("/tomcat/+bug/2/+attachment/1")
25 >>> check_not_found("/bugs/2/attachments/1")
26 >>> check_not_found("/bugs/2/+attachment/1")
27
28
29=== modified file 'lib/canonical/launchpad/pagetests/webservice/security.txt'
30--- lib/canonical/launchpad/pagetests/webservice/security.txt 2011-02-13 22:10:04 +0000
31+++ lib/canonical/launchpad/pagetests/webservice/security.txt 2011-03-16 00:53:41 +0000
32@@ -21,9 +21,8 @@
33 But the 'no-priv' user can't see bug number 14, which is private.
34
35 >>> print user_webservice.get("/bugs/14")
36- HTTP/1.1 401 Unauthorized
37+ HTTP/1.1 404 Not Found
38 ...
39- Bug 14 is private
40
41 >>> nopriv_output = user_webservice.get(
42 ... "/bugs?ws.size=100").jsonBody()
43@@ -37,9 +36,8 @@
44 operating on public data.
45
46 >>> print public_webservice.get("/bugs/14")
47- HTTP/1.1 401 Unauthorized
48+ HTTP/1.1 404 Not Found
49 ...
50- Bug 14 is private
51
52 >>> public_output = public_webservice.get(
53 ... "/bugs?ws.size=50").jsonBody()
54
55=== modified file 'lib/lp/bugs/browser/bugtask.py'
56--- lib/lp/bugs/browser/bugtask.py 2011-03-16 00:53:40 +0000
57+++ lib/lp/bugs/browser/bugtask.py 2011-03-16 00:53:41 +0000
58@@ -491,17 +491,19 @@
59 If the bug has been reported, but not in this specific context, a
60 redirect to the default context will be returned.
61
62- Raises NotFoundError if no bug with the given name is found.
63-
64- If the context type does provide IProduct, IDistribution,
65- IDistroSeries, ISourcePackage or IDistributionSourcePackage
66- a TypeError is raised.
67+ Returns None if no bug with the given name is found, or the
68+ bug is not accessible to the current user.
69 """
70 context = self.context
71
72 # Raises NotFoundError if no bug is found
73 bug = getUtility(IBugSet).getByNameOrID(name)
74
75+ # Get out now if the user cannot view the bug. Continuing may
76+ # reveal information about its context
77+ if not check_permission('launchpad.View', bug):
78+ return None
79+
80 # Loop through this bug's tasks to try and find the appropriate task
81 # for this context. We always want to return a task, whether or not
82 # the user has the permission to see it so that, for example, an
83
84=== modified file 'lib/lp/bugs/browser/malone.py'
85--- lib/lp/bugs/browser/malone.py 2010-08-20 20:31:18 +0000
86+++ lib/lp/bugs/browser/malone.py 2011-03-16 00:53:41 +0000
87@@ -67,7 +67,7 @@
88 # /malone/$bug.id Just Work
89 bug = getUtility(IBugSet).getByNameOrID(name)
90 if not check_permission("launchpad.View", bug):
91- raise Unauthorized("Bug %s is private" % name)
92+ return None
93 return bug
94
95
96
97=== modified file 'lib/lp/bugs/browser/tests/bugtask-edit-views.txt'
98--- lib/lp/bugs/browser/tests/bugtask-edit-views.txt 2011-03-16 00:53:40 +0000
99+++ lib/lp/bugs/browser/tests/bugtask-edit-views.txt 2011-03-16 00:53:41 +0000
100@@ -77,89 +77,11 @@
101 >>> edit_view.initialize()
102 >>> for error in edit_view.errors:
103 ... print error
104-<<<<<<< TREE
105 (u"Launchpad doesn't know of any source package named 'no-such-package'
106 in Ubuntu.", None)
107
108 An error is reported to the user when a bug is retargeted and there is
109 an existing task for the same target.
110-=======
111- (u"Launchpad doesn't know of any source package named 'no-such-package' in Ubuntu.", None)
112-
113-If we try to change the source package to a package name that another
114-distribution task already has, an error message will occur. First,
115-let's add an evolution (Ubuntu) task to bug two.
116-
117- >>> from lp.bugs.interfaces.bugtask import IBugTaskSet
118- >>> from lp.registry.interfaces.distribution import IDistributionSet
119- >>> bug_two = getUtility(IBugSet).get(2)
120- >>> ubuntu = getUtility(IDistributionSet).getByName("ubuntu")
121- >>> ubuntu_evolution = ubuntu.getSourcePackage('evolution')
122- >>> ubuntu_evolution_task = getUtility(IBugTaskSet).createTask(
123- ... bug=bug_two, owner=getUtility(ILaunchBag).user,
124- ... distribution=ubuntu,
125- ... sourcepackagename=ubuntu_evolution.sourcepackagename)
126- >>> import transaction
127- >>> transaction.commit()
128-
129-Now we try changing the generic Ubuntu task to evolution, which will
130-fail.
131-
132- >>> ubuntu_task = bug_two.bugtasks[1]
133- >>> ubuntu_task.bugtargetdisplayname
134- u'Ubuntu'
135- >>> edit_form = {
136- ... 'ubuntu.actions.save': 'Save Changes',
137- ... 'ubuntu.status': 'In Progress',
138- ... 'ubuntu.importance':
139- ... ubuntu_thunderbird_task.importance.title,
140- ... 'ubuntu.ubuntu_thunderbird.assignee.option':
141- ... 'ubuntu.assignee.assign_to_nobody',
142- ... 'ubuntu.sourcepackagename': ubuntu_evolution.name,
143- ... }
144- >>> request = LaunchpadTestRequest(form=edit_form, method='POST')
145- >>> edit_view = getMultiAdapter(
146- ... (ubuntu_task, request), name='+editstatus')
147- >>> edit_view.initialize()
148- >>> for error in edit_view.errors:
149- ... print error
150- This bug has already been reported on evolution (ubuntu).
151-
152-This also works if we try to reassign an accepted distribution series
153-task. Since we aren't allowed to edit the current development task
154-directly, let's add a grumpy task first.
155-
156- >>> login('foo.bar@canonical.com')
157- >>> ubuntu_grumpy = ubuntu.getSeries('grumpy')
158- >>> nomination = bug_two.addNomination(
159- ... target=ubuntu_grumpy, owner=getUtility(ILaunchBag).user)
160- >>> nomination.approve(getUtility(ILaunchBag).user)
161- >>> transaction.commit()
162-
163- >>> ubuntu_grumpy_task = bug_two.bugtasks[5]
164- >>> ubuntu_grumpy_task.bugtargetdisplayname
165- u'Ubuntu Grumpy'
166-
167- >>> edit_form = {
168- ... 'ubuntu_grumpy.actions.save': 'Save Changes',
169- ... 'ubuntu_grumpy.status': 'In Progress',
170- ... 'ubuntu_grumpy.importance':
171- ... ubuntu_grumpy_task.importance.title,
172- ... 'ubuntu_grumpy.assignee.option':
173- ... 'ubuntu_grumpy.assignee.assign_to_nobody',
174- ... 'ubuntu_grumpy.sourcepackagename': ubuntu_evolution.name,
175- ... }
176- >>> request = LaunchpadTestRequest(form=edit_form, method='POST')
177- >>> edit_view = getMultiAdapter(
178- ... (ubuntu_grumpy_task, request), name='+editstatus')
179- >>> edit_view.initialize()
180- >>> for error in edit_view.errors:
181- ... print error
182- This bug has already been reported on evolution (ubuntu).
183-
184- >>> login('test@canonical.com')
185-
186->>>>>>> MERGE-SOURCE
187
188 == Edit the Product ==
189
190
191=== modified file 'lib/lp/bugs/browser/tests/test_bugattachment_file_access.py'
192--- lib/lp/bugs/browser/tests/test_bugattachment_file_access.py 2011-01-19 13:28:16 +0000
193+++ lib/lp/bugs/browser/tests/test_bugattachment_file_access.py 2011-03-16 00:53:41 +0000
194@@ -33,7 +33,7 @@
195 AppServerLayer,
196 LaunchpadFunctionalLayer,
197 )
198-from lazr.restfulclient.errors import Unauthorized as RestfulUnauthorized
199+from lazr.restfulclient.errors import NotFound as RestfulNotFound
200 from lp.bugs.browser.bugattachment import BugAttachmentFileNavigation
201 import lp.services.features
202 from lp.services.features.flags import NullFeatureController
203@@ -226,9 +226,9 @@
204 self.assertEqual(['token'], params.keys())
205
206 # If a user which cannot access the private bug itself tries to
207- # to access the attachment, an Unauthorized error is raised.
208+ # to access the attachment, an NotFound error is raised.
209 other_launchpad = launchpadlib_for(
210 'test_unauthenticated', other_user, version='devel')
211 self.assertRaises(
212- RestfulUnauthorized, other_launchpad._browser.get,
213+ RestfulNotFound, other_launchpad._browser.get,
214 ws_bugattachment.data._wadl_resource._url)
215
216=== modified file 'lib/lp/bugs/browser/tests/test_bugtask.py'
217--- lib/lp/bugs/browser/tests/test_bugtask.py 2011-03-12 15:03:57 +0000
218+++ lib/lp/bugs/browser/tests/test_bugtask.py 2011-03-16 00:53:41 +0000
219@@ -550,7 +550,7 @@
220
221 layer = DatabaseFunctionalLayer
222
223- def test_retartget_already_exists_error(self):
224+ def test_retarget_already_exists_error(self):
225 user = self.factory.makePerson()
226 login_person(user)
227 ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
228@@ -576,7 +576,7 @@
229 'ubuntu_rabbit.sourcepackagename': 'mouse',
230 }
231 view = create_initialized_view(
232- bug_task_2, name='+editstatus-page', form=form, principal=user)
233+ bug_task_2, name='+editstatus', form=form, principal=user)
234 self.assertEqual(1, len(view.errors))
235 self.assertEqual(
236 'This bug has already been reported on mouse (ubuntu).',
237
238=== modified file 'lib/lp/bugs/stories/bug-privacy/20-private-distro-bug-not-visible-to-anonymous.txt'
239--- lib/lp/bugs/stories/bug-privacy/20-private-distro-bug-not-visible-to-anonymous.txt 2009-06-12 16:36:02 +0000
240+++ lib/lp/bugs/stories/bug-privacy/20-private-distro-bug-not-visible-to-anonymous.txt 2011-03-16 00:53:41 +0000
241@@ -5,7 +5,7 @@
242 >>> anon_browser.open("http://launchpad.dev/bugs/14")
243 Traceback (most recent call last):
244 ...
245- Unauthorized: ...
246+ NotFound: ...
247
248 And not in bug listings.
249
250
251=== modified file 'lib/lp/bugs/stories/bug-privacy/30-private-distro-bug-not-visible-to-nonsubscriber-user.txt'
252--- lib/lp/bugs/stories/bug-privacy/30-private-distro-bug-not-visible-to-nonsubscriber-user.txt 2009-06-12 16:36:02 +0000
253+++ lib/lp/bugs/stories/bug-privacy/30-private-distro-bug-not-visible-to-nonsubscriber-user.txt 2011-03-16 00:53:41 +0000
254@@ -6,7 +6,7 @@
255 >>> browser.open("http://launchpad.dev/bugs/14")
256 Traceback (most recent call last):
257 ...
258- Unauthorized: ...
259+ NotFound: ...
260
261 Nor in a search listing.
262
263
264=== modified file 'lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.txt'
265--- lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.txt 2010-12-18 14:47:17 +0000
266+++ lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.txt 2011-03-16 00:53:41 +0000
267@@ -65,10 +65,10 @@
268 >>> browser.open('http://bugs.launchpad.dev/bugs/4')
269 Traceback (most recent call last):
270 ...
271- Unauthorized: Bug 4 is private
272+ NotFound: ...
273
274 >>> anon_browser.open('http://bugs.launchpad.dev/bugs/4')
275 Traceback (most recent call last):
276 ...
277- Unauthorized: Bug 4 is private
278+ NotFound: ...
279
280
281=== modified file 'lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt'
282--- lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt 2010-05-19 05:47:50 +0000
283+++ lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt 2011-03-16 00:53:41 +0000
284@@ -99,7 +99,7 @@
285 ... 'http://bugs.launchpad.dev/bugs/bugtrackers/mozilla.org/2000')
286 Traceback (most recent call last):
287 ...
288- Unauthorized:...
289+ NotFound:...
290
291 Set the bug back to public:
292
293
294=== removed file 'lib/lp/bugs/stories/cve/xx-cve-link-to-modified-target.txt'
295--- lib/lp/bugs/stories/cve/xx-cve-link-to-modified-target.txt 2009-06-12 16:36:02 +0000
296+++ lib/lp/bugs/stories/cve/xx-cve-link-to-modified-target.txt 1970-01-01 00:00:00 +0000
297@@ -1,39 +0,0 @@
298-= Linking a CVE to a Bug With a Modified Target =
299-
300-We shouldn't get an OOPS when linking a CVE report to a bug that's been
301-modified.
302-
303- >>> import transaction
304- >>> user_browser.open(
305- ... 'http://bugs.launchpad.dev/firefox/+bug/4/+linkcve')
306- >>> admin_browser.open(
307- ... 'http://bugs.launchpad.dev/firefox/+bug/4/')
308- >>> admin_browser.getControl('Project').value = "jokosher"
309- >>> admin_browser.getControl(name='firefox.actions.save').click()
310-
311- >>> user_browser.getControl('CVE Sequence Number').value = '2005-2737'
312- >>> user_browser.getControl('Continue').click()
313-
314- >>> for tag in find_tags_by_class(user_browser.contents, 'cve'):
315- ... print extract_text(tag)
316- 2005-2737
317-
318-Similarly, unlinking the CVE from the bug shouldn't cause an OOPS when
319-the bugtask has been retargeted.
320-
321- >>> user_browser.getLink('Remove CVE link').click()
322- >>> user_browser.url
323- 'http://bugs.launchpad.dev/jokosher/+bug/4/+unlinkcve'
324-
325- >>> admin_browser.getControl('Project').value = "firefox"
326- >>> admin_browser.getControl(name='jokosher.actions.save').click()
327-
328- >>> user_browser.getControl('CVE Sequence Number').value = '2005-2737'
329- >>> user_browser.getControl('Continue').click()
330-
331-There should now be no CVE links on the bugtask page:
332-
333- >>> len(find_tags_by_class(user_browser.contents, 'cve'))
334- 0
335-
336- >>> transaction.abort()
337
338=== modified file 'lib/lp/bugs/stories/upstream-bugprivacy/10-file-private-upstream-bug.txt'
339--- lib/lp/bugs/stories/upstream-bugprivacy/10-file-private-upstream-bug.txt 2010-10-09 16:36:22 +0000
340+++ lib/lp/bugs/stories/upstream-bugprivacy/10-file-private-upstream-bug.txt 2011-03-16 00:53:41 +0000
341@@ -106,14 +106,14 @@
342 == Checking basic access to the private bug pages ==
343
344 Trying to access the task edit page of a task on a private bug
345-redirects the anonymous user to the login page.
346+fails, because we pretend that inaccessible private bugs do not exist.
347
348 >>> browser = setupBrowser()
349 >>> browser.open(
350 ... "http://launchpad.dev/firefox/+bug/%s/+editstatus" % bug_id)
351 Traceback (most recent call last):
352 ...
353- Unauthorized:...
354+ NotFound:...
355
356 The no-privs user cannot access bug #10, because it's filed on a private bug on
357 which the no-privs is not an explicit subscriber.
358@@ -123,7 +123,7 @@
359 ... "http://launchpad.dev/firefox/+bug/%s/+editstatus" % bug_id)
360 Traceback (most recent call last):
361 ...
362- Unauthorized:...
363+ NotFound:...
364
365 Sample Person accesses the bug page of a private bug. He is allowed to
366 view the page because he is an explicit subscriber on the bug.
367
368=== modified file 'lib/lp/bugs/stories/upstream-bugprivacy/30-private-upstream-bug-not-accessible-to-anonymous.txt'
369--- lib/lp/bugs/stories/upstream-bugprivacy/30-private-upstream-bug-not-accessible-to-anonymous.txt 2009-06-12 16:36:02 +0000
370+++ lib/lp/bugs/stories/upstream-bugprivacy/30-private-upstream-bug-not-accessible-to-anonymous.txt 2011-03-16 00:53:41 +0000
371@@ -1,5 +1,5 @@
372 Trying to access a private upstream bug as an anonymous user results
373-in being redirecting to the login page.
374+in a page not found error.
375
376 >>> print http(r"""
377 ... GET /firefox/+bug/6 HTTP/1.1
378@@ -7,15 +7,8 @@
379 HTTP/1.1 200 Ok
380 ...
381
382-
383-XXX: Brad Bollenbach, 2005-09-30: The redirect URL below is unexpected. See
384-https://launchpad.net/launchpad/+bug/2730
385-
386 >>> print http(r"""
387 ... GET /firefox/+bug/14 HTTP/1.1
388 ... """)
389- HTTP/1.1 303 See Other
390- ...
391- Location: http://localhost/firefox/+bug/14/+index/+login
392- ...
393- <BLANKLINE>
394+ HTTP/1.1 404 Not Found
395+ ...
396
397=== modified file 'lib/lp/bugs/stories/upstream-bugprivacy/50-private-upstream-bug-not-accessible-to-nonsubscriber-user.txt'
398--- lib/lp/bugs/stories/upstream-bugprivacy/50-private-upstream-bug-not-accessible-to-nonsubscriber-user.txt 2009-09-09 23:16:08 +0000
399+++ lib/lp/bugs/stories/upstream-bugprivacy/50-private-upstream-bug-not-accessible-to-nonsubscriber-user.txt 2011-03-16 00:53:41 +0000
400@@ -15,9 +15,7 @@
401 ... GET /firefox/+bug/14 HTTP/1.1
402 ... Authorization: Basic bm8tcHJpdkBjYW5vbmljYWwuY29tOnRlc3Q=
403 ... """)
404- HTTP/1.1 403 Forbidden
405- ...
406- <title>Error: Launchpad system error</title>
407+ HTTP/1.1 404 Not Found
408 ...
409
410 This is also true if no-privs tries to access the bug from another
411@@ -27,7 +25,5 @@
412 ... GET /tomcat/+bug/14 HTTP/1.1
413 ... Authorization: Basic bm8tcHJpdkBjYW5vbmljYWwuY29tOnRlc3Q=
414 ... """)
415- HTTP/1.1 403 Forbidden
416- ...
417- <title>Error: Launchpad system error</title>
418+ HTTP/1.1 404 Not Found
419 ...