Merge lp:~stevenk/launchpad/product-limitedview-with-team-aag into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Approved by: William Grant
Approved revision: no longer in the source branch.
Merged at revision: 16413
Proposed branch: lp:~stevenk/launchpad/product-limitedview-with-team-aag
Merge into: lp:launchpad
Diff against target: 127 lines (+35/-16)
5 files modified
lib/lp/registry/interfaces/sharingservice.py (+2/-2)
lib/lp/registry/services/sharingservice.py (+14/-4)
lib/lp/registry/services/tests/test_sharingservice.py (+16/-7)
lib/lp/registry/tests/test_product.py (+2/-2)
lib/lp/security.py (+1/-1)
To merge this branch: bzr merge lp:~stevenk/launchpad/product-limitedview-with-team-aag
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+142441@code.launchpad.net

Commit message

The LimitedView security adapter on IProduct now deals with AccessArtifactGrants that have been granted to teams.

Description of the change

Currently, the LimitedView security adapter for IProduct checks if a user has an AccessArtifactGrant on a bug, branch or specification for the private project. This is fine, and works well, except that it doesn't work if a team the user is a member has the AAG. As such, I've rewritten ISharingService.userHasGrantsOnPillar() to respect TeamParticipation.

I have done some drive-by on some asserts, using assert{True,False} rather than assertEqual({True,False}, and fixed one indentation error I noticed.

I have more than enough LoC credit for the +19 gain.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
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/registry/interfaces/sharingservice.py'
2--- lib/lp/registry/interfaces/sharingservice.py 2012-12-02 01:51:46 +0000
3+++ lib/lp/registry/interfaces/sharingservice.py 2013-01-09 05:39:20 +0000
4@@ -1,4 +1,4 @@
5-# Copyright 2012 Canonical Ltd. This software is licensed under the
6+# Copyright 2012-2013 Canonical Ltd. This software is licensed under the
7 # GNU Affero General Public License version 3 (see the file LICENSE).
8
9 """Interfaces for sharing service."""
10@@ -117,7 +117,7 @@
11 :return: a (bugtasks, branches, specifications) tuple
12 """
13
14- def userHasGrantsOnPillar(pillar, user):
15+ def checkPillarArtifactAccess(pillar, user):
16 """Return True if user has any grants on pillar else return False."""
17
18 @export_read_operation()
19
20=== modified file 'lib/lp/registry/services/sharingservice.py'
21--- lib/lp/registry/services/sharingservice.py 2012-12-02 03:30:18 +0000
22+++ lib/lp/registry/services/sharingservice.py 2013-01-09 05:39:20 +0000
23@@ -1,4 +1,4 @@
24-# Copyright 2012 Canonical Ltd. This software is licensed under the
25+# Copyright 2012-2013 Canonical Ltd. This software is licensed under the
26 # GNU Affero General Public License version 3 (see the file LICENSE).
27
28 """Classes for pillar and artifact sharing service."""
29@@ -227,10 +227,20 @@
30
31 return bugtasks, branches, specifications
32
33- def userHasGrantsOnPillar(self, pillar, user):
34+ def checkPillarArtifactAccess(self, pillar, user):
35 """See `ISharingService`."""
36- return not self.getArtifactGrantsForPersonOnPillar(
37- pillar, user).is_empty()
38+ tables = [
39+ AccessPolicyGrantFlat,
40+ Join(
41+ TeamParticipation,
42+ TeamParticipation.teamID == AccessPolicyGrantFlat.grantee_id),
43+ Join(
44+ AccessPolicy,
45+ AccessPolicy.id == AccessPolicyGrantFlat.policy_id)]
46+ return not IStore(AccessPolicyGrantFlat).using(*tables).find(
47+ AccessPolicyGrantFlat,
48+ AccessPolicy.product_id == pillar.id,
49+ TeamParticipation.personID == user.id).is_empty()
50
51 @available_with_permission('launchpad.Driver', 'pillar')
52 def getSharedBugs(self, pillar, person, user):
53
54=== modified file 'lib/lp/registry/services/tests/test_sharingservice.py'
55--- lib/lp/registry/services/tests/test_sharingservice.py 2012-11-29 20:27:19 +0000
56+++ lib/lp/registry/services/tests/test_sharingservice.py 2013-01-09 05:39:20 +0000
57@@ -1,4 +1,4 @@
58-# Copyright 2012 Canonical Ltd. This software is licensed under the
59+# Copyright 2012-2013 Canonical Ltd. This software is licensed under the
60 # GNU Affero General Public License version 3 (see the file LICENSE).
61
62 __metaclass__ = type
63@@ -1762,19 +1762,28 @@
64 self.service.sharePillarInformation(
65 product, wrong_person, product.owner,
66 {InformationType.PRIVATESECURITY: SharingPermission.ALL})
67- self.assertEqual(
68- False,
69+ self.assertFalse(
70 self.service.checkPillarAccess(
71 [product], InformationType.USERDATA, wrong_person))
72- self.assertEqual(
73- True,
74+ self.assertTrue(
75 self.service.checkPillarAccess(
76 [product], InformationType.USERDATA, right_person))
77
78+ def test_checkPillarArtifactAccess_respects_teams(self):
79+ owner = self.factory.makePerson()
80+ product = self.factory.makeProduct(
81+ information_type=InformationType.PROPRIETARY, owner=owner)
82+ user = self.factory.makePerson()
83+ team = self.factory.makeTeam(
84+ membership_policy=TeamMembershipPolicy.MODERATED, members=[user])
85+ with person_logged_in(owner):
86+ bug = self.factory.makeBug(target=product)
87+ bug.subscribe(team, owner)
88+ self.assertTrue(self.service.checkPillarArtifactAccess(product, user))
89+
90 def test_checkPillarAccess_no_policy(self):
91 # checkPillarAccess returns False if there's no policy.
92- self.assertEqual(
93- False,
94+ self.assertFalse(
95 self.service.checkPillarAccess(
96 [self.factory.makeProduct()], InformationType.PUBLIC,
97 self.factory.makePerson()))
98
99=== modified file 'lib/lp/registry/tests/test_product.py'
100--- lib/lp/registry/tests/test_product.py 2013-01-03 03:41:13 +0000
101+++ lib/lp/registry/tests/test_product.py 2013-01-09 05:39:20 +0000
102@@ -1,4 +1,4 @@
103-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
104+# Copyright 2009-2013 Canonical Ltd. This software is licensed under the
105 # GNU Affero General Public License version 3 (see the file LICENSE).
106
107 __metaclass__ = type
108@@ -1184,7 +1184,7 @@
109 # The second access does not require another query.
110 product.description
111 self.assertEqual(
112- queries_for_first_user_access, len(recorder.queries))
113+ queries_for_first_user_access, len(recorder.queries))
114
115 def test_userCanView_works_with_IPersonRoles(self):
116 # userCanView() maintains a cache of users known to have the
117
118=== modified file 'lib/lp/security.py'
119--- lib/lp/security.py 2013-01-04 06:25:25 +0000
120+++ lib/lp/security.py 2013-01-09 05:39:20 +0000
121@@ -448,7 +448,7 @@
122 def checkAuthenticated(self, user):
123 return (
124 super(LimitedViewProduct, self).checkAuthenticated(user) or
125- getUtility(IService, 'sharing').userHasGrantsOnPillar(
126+ getUtility(IService, 'sharing').checkPillarArtifactAccess(
127 self.obj, user))
128
129