Merge lp:~wgrant/launchpad/bug-750607 into lp:launchpad

Proposed by William Grant
Status: Merged
Approved by: William Grant
Approved revision: no longer in the source branch.
Merged at revision: 13058
Proposed branch: lp:~wgrant/launchpad/bug-750607
Merge into: lp:launchpad
Diff against target: 110 lines (+53/-9)
3 files modified
lib/canonical/launchpad/security.py (+15/-8)
lib/lp/code/tests/test_branch.py (+8/-0)
lib/lp/code/tests/test_branchmergeproposal.py (+30/-1)
To merge this branch: bzr merge lp:~wgrant/launchpad/bug-750607
Reviewer Review Type Date Requested Status
Henning Eggers (community) Approve
Review via email: mp+61069@code.launchpad.net

Commit message

[r=henninge][bug=750607] launchpad.View on BranchMergeProposal now requires launchpad.View on prerequisite_branch, if one is set.

Description of the change

Users can't see BranchMergeProposal:+index unless they can see the prerequisite_branch, if any. This is enforced by an Unauthorized when accessing the prereq's attributes, not by BranchMergeProposal's security declarations.

This branch fixes the launchpad.View BranchMergeProposal adapter to require access to prerequisite_branch, if it is set.

To post a comment you must log in.
Revision history for this message
Henning Eggers (henninge) wrote :

Ah, do you remember those days when lambdas were considered inappropriate in LP code? Good riddance! Welcome concise code using "map" and "all". Thanks for the reading pleasure. ;-)

I have one remark, though. Is there a reason for not using getUtility(ILaunchpadCelebrities).admin or are you simply not aware of it?

Cheers,
Henning

review: Approve
Revision history for this message
William Grant (wgrant) wrote :

I'm aware of it, but I find celebrities to be extremely distasteful.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/security.py'
2--- lib/canonical/launchpad/security.py 2011-05-03 04:39:43 +0000
3+++ lib/canonical/launchpad/security.py 2011-05-16 07:27:38 +0000
4@@ -1892,24 +1892,31 @@
5 permission = 'launchpad.View'
6 usedfor = IBranchMergeProposal
7
8+ @property
9+ def branches(self):
10+ required = [self.obj.source_branch, self.obj.target_branch]
11+ if self.obj.prerequisite_branch:
12+ required.append(self.obj.prerequisite_branch)
13+ return required
14+
15 def checkAuthenticated(self, user):
16 """Is the user able to view the branch merge proposal?
17
18- The user can see a merge proposal between two branches
19- that the user can see.
20+ The user can see a merge proposal if they can see the source, target
21+ and prerequisite branches.
22 """
23- return (AccessBranch(self.obj.source_branch).checkAuthenticated(user)
24- and
25- AccessBranch(self.obj.target_branch).checkAuthenticated(user))
26+ return all(map(
27+ lambda b: AccessBranch(b).checkAuthenticated(user),
28+ self.branches))
29
30 def checkUnauthenticated(self):
31 """Is anyone able to view the branch merge proposal?
32
33 Anyone can see a merge proposal between two public branches.
34 """
35- return (AccessBranch(self.obj.source_branch).checkUnauthenticated()
36- and
37- AccessBranch(self.obj.target_branch).checkUnauthenticated())
38+ return all(map(
39+ lambda b: AccessBranch(b).checkUnauthenticated(),
40+ self.branches))
41
42
43 class PreviewDiffView(AuthorizationBase):
44
45=== modified file 'lib/lp/code/tests/test_branch.py'
46--- lib/lp/code/tests/test_branch.py 2011-01-25 19:47:56 +0000
47+++ lib/lp/code/tests/test_branch.py 2011-05-16 07:27:38 +0000
48@@ -58,6 +58,14 @@
49 """
50 self.assertAuthenticatedView(branch, None, can_access)
51
52+ def assertCanView(self, person, secured_object):
53+ """Assert 'person' can view 'secured_object'."""
54+ self.assertPermission(True, person, secured_object, 'launchpad.View')
55+
56+ def assertCannotView(self, person, secured_object):
57+ """Assert 'person' cannot view 'secured_object'."""
58+ self.assertPermission(False, person, secured_object, 'launchpad.View')
59+
60 def assertCanEdit(self, person, secured_object):
61 """Assert 'person' can edit 'secured_object'.
62
63
64=== modified file 'lib/lp/code/tests/test_branchmergeproposal.py'
65--- lib/lp/code/tests/test_branchmergeproposal.py 2010-10-04 19:50:45 +0000
66+++ lib/lp/code/tests/test_branchmergeproposal.py 2011-05-16 07:27:38 +0000
67@@ -11,9 +11,13 @@
68 from canonical.testing.layers import DatabaseFunctionalLayer
69 from lp.code.interfaces.linkedbranch import ICanHasLinkedBranch
70 from lp.code.tests.test_branch import PermissionTest
71+from lp.registry.interfaces.person import IPersonSet
72 from lp.registry.interfaces.pocket import PackagePublishingPocket
73 from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
74-from lp.testing import run_with_login
75+from lp.testing import (
76+ run_with_login,
77+ with_celebrity_logged_in,
78+ )
79
80
81 class TestEditMergeProposal(PermissionTest):
82@@ -73,3 +77,28 @@
83 self.assertCanEdit(person, proposal.target_branch)
84 # And that means they can edit the proposal too
85 self.assertCanEdit(person, proposal)
86+
87+
88+class TestViewMergeProposal(PermissionTest):
89+
90+ layer = DatabaseFunctionalLayer
91+
92+ @with_celebrity_logged_in('admin')
93+ def assertBranchAccessRequired(self, attr):
94+ person = self.factory.makePerson()
95+ prereq = self.factory.makeBranch()
96+ proposal = self.factory.makeBranchMergeProposal(
97+ prerequisite_branch=prereq)
98+ self.assertCanView(person, proposal)
99+ getattr(proposal, attr).setPrivate(
100+ True, getUtility(IPersonSet).getByName('admins'))
101+ self.assertCannotView(person, proposal)
102+
103+ def test_source_branch_access_required(self):
104+ self.assertBranchAccessRequired('source_branch')
105+
106+ def test_target_branch_access_required(self):
107+ self.assertBranchAccessRequired('target_branch')
108+
109+ def test_prerequisite_branch_access_required(self):
110+ self.assertBranchAccessRequired('prerequisite_branch')