Merge lp:~henninge/launchpad/bug-503454-security-py into lp:launchpad

Proposed by Henning Eggers
Status: Merged
Approved by: Edwin Grubbs
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~henninge/launchpad/bug-503454-security-py
Merge into: lp:launchpad
Diff against target: 1321 lines (+302/-263)
7 files modified
lib/canonical/launchpad/doc/hasowner-authorization.txt (+5/-5)
lib/canonical/launchpad/doc/personroles.txt (+130/-0)
lib/canonical/launchpad/interfaces/launchpad.py (+8/-1)
lib/canonical/launchpad/security.py (+129/-240)
lib/canonical/launchpad/tests/test_personroles.py (+10/-4)
lib/canonical/launchpad/utilities/personroles.py (+14/-7)
lib/lp/code/doc/branch-visibility.txt (+6/-6)
To merge this branch: bzr merge lp:~henninge/launchpad/bug-503454-security-py
Reviewer Review Type Date Requested Status
Edwin Grubbs (community) code Approve
Review via email: mp+17241@code.launchpad.net

Commit message

Updated security.py to use PersonRoles. Added doctest for PersonRoles.

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

= Bug 506454 =

This is a tech-dept relief that applies some refactoring to security.py. It may seem like a lot of work for the transition but afterwards will make it more straight forward to write security checkers.

This branch introduces and API change for "checkAuthenticated" which used to receive an "IPerson" object as its "user" parameter which has now been changed to be an "IPersonRoles" object. The old object can still be reached via "user.person".

This branch also contains a change to IPersonRoles and its implementation because at least one test wanted to check the "driver" attribute of an object although the object also has a "drivers" attribute (IHasDrivers). Although this may actually be a bug (why should the driver of a product have less permissions than the driver of a productseries?) I provided an explicit isOneOfDrivers method. This also makes isDriver symmetrical to isOwner.

Some tests needed to be adapted because they used "checkAuthenticated" on an object that implements "IAuthorization". "checkAuthenticated" has been replaced by "checkAccountAuthenticated" in "IAuthorization".

The diff is overly long because of the many very similar changes in security.py.

== Implementation details ==

lib/canonical/launchpad/doc/hasowner-authorization.txt

 * Replaced checkAuthenticated with checkAccountAuthenticated.
 * Added some print statements.

lib/canonical/launchpad/doc/personroles.txt

 * New doc test for PersonRoles so people have no fear of using it in security.py. ;-)

lib/canonical/launchpad/interfaces/launchpad.py

 * Added isOneOfDrivers method to IPersonRoles interface.

lib/canonical/launchpad/security.py

 * The main change in this branch: AuthorizationBase.checkAccountAuthenticated applies the IPersonRoles adapter to the IPerson object which it derives from the account. So unless checkAccountAuthenticated gets overwritten, checkAuthenticated reveives an IPersonRoles object instead of an IPerson object.
 * Replaced all calls to user.inTeam(celebrity.some_celeb) with user.in_some_celeb.
 * Replaced owner and driver checks with the respective methods from IPersonRoles.
 * Where ever the user object is still needed as an IPerson object, it was replaced with user.person.
 * A few checkers were optimized in the course of this refactoring.

lib/canonical/launchpad/utilities/personroles.py

 * Implementation of isOneOfDrivers which is mostly the previous implementation of isDriver but now checks for the IHasDrivers interface instead of the actual attribute. (Bye-bye duck-typing, hello contract-typing. :)

lib/lp/code/doc/branch-visibility.txt

 * Mechanical replacement of checkAuthenticated with checkAccountAuthenticated.

== Tests ==

As almost all of Launchpad is affected by security.py, only the full test suite gives that feeling of security.
Test PersonRoles itself like this:

bin/test -vvct personroles -t celebrities

== QA ==

Launchpad still working as it used to? Good.

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/canonical/launchpad/security.py
  lib/canonical/launchpad/doc/hasowne...

Read more...

Revision history for this message
Henning Eggers (henninge) wrote :

Found room for a little more improvement. I'd better stop now, though. ;-)

Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (5.5 KiB)

Hi Henning,

This branch is a nice improvement. It's always good to shrink files.

I have a few comments below, but I also would like this change made,
which isn't actually part of your diff. In PersonRoles.__getattr__
please add info to the exception you raise so that it matches the error
python gives you for its default types such as:
    AttributeError: 'int' object has no attribute 'foo'

merge-conditional

-Edwin

>=== added file 'lib/canonical/launchpad/doc/personroles.txt'
>--- lib/canonical/launchpad/doc/personroles.txt 1970-01-01 00:00:00 +0000
>+++ lib/canonical/launchpad/doc/personroles.txt 2010-01-13 16:45:40 +0000
>@@ -0,0 +1,131 @@
>+= PersonRoles =
>+
>+To make the checking for certain roles that a person can have more convenient

This makes it a little easier to read:
    "To make it more convenient to check which roles a person has,"

>+the IPersonRoles adapter is provided. It's main use is to easily check if a
>+person is the member of a celebrity team or is a celebrity person. In
>+addition, methods for common checks are provided, too.
>+
>+The IPersonRoles interface is closely tight to the ILaunchpadCelebrities
>+interface. Any addition or removal of a person celebrity must be reflected in
>+adding or removing the corresponding property in IPersonRoles. Luckily the
>+celbrities.txt doctest includes a check for this and will give a useful
>+information of which attribute needs to be added or removed. Both interfaces

s/celbrities.txt/celebrities.txt/
s/give a useful/give useful/
s/information of/information on/

>+are found in the same file. There is no need to adapt the implementation
>+class PersonRoles, though (thanks to __getattr__).
>+
>+PersonRoles is most prominent in AuthenticationBase in security.py. The user
>+parameter to checkAuthenticated is a PersonRoles object (used to be a Person
>+object).

s/used to be/was/
or "this used to be" to differentiate it from "this is used to be".
Otherwise, it's not clear if "this" or "this is" was dropped until
you get to the middle of the sentence.

>+== The person object and the adapter ==
>+
>+PersonRoles is registered as an unnamed adapter for IPersonRoles.
>+
>+ >>> from canonical.launchpad.interfaces.launchpad import IPersonRoles
>+ >>> person = factory.makePerson()
>+ >>> print IPersonRoles(person)
>+ <canonical.launchpad.utilities.personroles.PersonRoles object at ...>
>+
>+The original Person object can be reached through the person attribute.
>+
>+ >>> roles = IPersonRoles(person)
>+ >>> print roles.person is person
>+ True
>+
>+
>+== Celebrity persons ==
>+
>+There are a number of celebrity persons defined in ILaunchpadCelebrities.
>+PersonRoles has a corresponding attribute of the same name prefixed with
>+"in_" to check if the person in question is a member of this celebrity or is
>+this celebrity. The following tests are identical.
>+
>+ >>> from canonical.launchpad.interfaces.launchpad import (
>+ ... ILaunchpadCelebrities)
>+ >>> rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts
>+ >>> print person.inTeam(rosetta_experts)
>+ False
>+
>+ >>> print roles.in_rosetta_experts
>+ False
>+
>+The tes...

Read more...

review: Approve (code)
Revision history for this message
Henning Eggers (henninge) wrote :

Am 13.01.2010 22:06, Edwin Grubbs schrieb:
> Review: Approve code
> Hi Henning,
>
> This branch is a nice improvement. It's always good to shrink files.
>
> I have a few comments below, but I also would like this change made,
> which isn't actually part of your diff. In PersonRoles.__getattr__
> please add info to the exception you raise so that it matches the error
> python gives you for its default types such as:
> AttributeError: 'int' object has no attribute 'foo'
>
> merge-conditional
>

Thank you very much for your suggestions which I liked very much. All
were implemented. ;-)

An incremental diff is attached.

Cheers,
Henning

=== modified file 'lib/canonical/launchpad/doc/personroles.txt'
--- lib/canonical/launchpad/doc/personroles.txt 2010-01-12 17:07:32 +0000
+++ lib/canonical/launchpad/doc/personroles.txt 2010-01-14 11:19:29 +0000
@@ -1,6 +1,6 @@
1= PersonRoles =1= PersonRoles =
22
3To make the checking for certain roles that a person can have more convenient3To make it more convenient to check which roles a person has,
4the IPersonRoles adapter is provided. It's main use is to easily check if a4the IPersonRoles adapter is provided. It's main use is to easily check if a
5person is the member of a celebrity team or is a celebrity person. In5person is the member of a celebrity team or is a celebrity person. In
6addition, methods for common checks are provided, too.6addition, methods for common checks are provided, too.
@@ -8,14 +8,13 @@
8The IPersonRoles interface is closely tight to the ILaunchpadCelebrities8The IPersonRoles interface is closely tight to the ILaunchpadCelebrities
9interface. Any addition or removal of a person celebrity must be reflected in9interface. Any addition or removal of a person celebrity must be reflected in
10adding or removing the corresponding property in IPersonRoles. Luckily the10adding or removing the corresponding property in IPersonRoles. Luckily the
11celbrities.txt doctest includes a check for this and will give a useful11celebrities.txt doctest includes a check for this and will give useful
12information of which attribute needs to be added or removed. Both interfaces12information on which attribute needs to be added or removed. Both interfaces
13are found in the same file. There is no need to adapt the implementation13are found in the same file. There is no need to adapt the implementation
14class PersonRoles, though (thanks to __getattr__).14class PersonRoles, though (thanks to __getattr__).
1515
16PersonRoles is most prominent in AuthenticationBase in security.py. The user16PersonRoles is most prominent in AuthenticationBase in security.py. The user
17parameter to checkAuthenticated is a PersonRoles object (used to be a Person17parameter to checkAuthenticated is a PersonRoles object (was a Person object).
18object).
1918
2019
21== The person object and the adapter ==20== The person object and the adapter ==
@@ -60,8 +59,8 @@
60 True59 True
6160
62To stay consistent, all attributes are prefixed with "in_" although the61To stay consistent, all attributes are prefixed with "in_" although the
63attributes names of ILaunchpadCelebrities are not all lexically correct62attribute names of ILaunchpadCelebrities are not all lexically correct
64plurals nor are all the attributes teams. This makes for odd sounding63plurals, nor are all the attributes teams. This makes for odd sounding
65attribute names in IPersonRoles.64attribute names in IPersonRoles.
6665
67 >>> print roles.in_admin66 >>> print roles.in_admin
6867
=== modified file 'lib/canonical/launchpad/security.py'
--- lib/canonical/launchpad/security.py 2010-01-12 17:42:43 +0000
+++ lib/canonical/launchpad/security.py 2010-01-14 11:21:36 +0000
@@ -2215,11 +2215,10 @@
2215 self.obj.person.hide_email_addresses):2215 self.obj.person.hide_email_addresses):
2216 return True2216 return True
22172217
2218 person = IPerson(account, None)2218 user = IPersonRoles(IPerson(account, None), None)
2219 if person is None:2219 if user is None:
2220 return False2220 return False
22212221
2222 user = IPersonRoles(person)
2223 return (self.obj.person is not None and user.inTeam(self.obj.person)2222 return (self.obj.person is not None and user.inTeam(self.obj.person)
2224 or user.in_commercial_admin2223 or user.in_commercial_admin
2225 or user.in_registry_experts2224 or user.in_registry_experts
22262225
=== modified file 'lib/canonical/launchpad/utilities/personroles.py'
--- lib/canonical/launchpad/utilities/personroles.py 2010-01-12 14:52:41 +0000
+++ lib/canonical/launchpad/utilities/personroles.py 2010-01-14 11:10:40 +0000
@@ -26,10 +26,14 @@
26 def __getattr__(self, name):26 def __getattr__(self, name):
27 """Handle all in_* attributes."""27 """Handle all in_* attributes."""
28 prefix = 'in_'28 prefix = 'in_'
29 errortext = "'PersonRoles' object has no attribute '%s'" % name
29 if not name.startswith(prefix):30 if not name.startswith(prefix):
30 raise AttributeError31 raise AttributeError(errortext)
31 attribute = name[len(prefix):]32 attribute = name[len(prefix):]
32 return self.person.inTeam(getattr(self._celebrities, attribute))33 try:
34 return self.person.inTeam(getattr(self._celebrities, attribute))
35 except AttributeError:
36 raise AttributeError(errortext)
3337
34 def isOwner(self, obj):38 def isOwner(self, obj):
35 """See IPersonRoles."""39 """See IPersonRoles."""

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/doc/hasowner-authorization.txt'
--- lib/canonical/launchpad/doc/hasowner-authorization.txt 2009-08-13 15:12:16 +0000
+++ lib/canonical/launchpad/doc/hasowner-authorization.txt 2010-01-15 07:14:13 +0000
@@ -18,23 +18,23 @@
18 >>> from canonical.launchpad.webapp.interfaces import IAuthorization18 >>> from canonical.launchpad.webapp.interfaces import IAuthorization
19 >>> from zope.component import queryAdapter19 >>> from zope.component import queryAdapter
20 >>> authorization = queryAdapter(foo, IAuthorization, 'launchpad.Edit')20 >>> authorization = queryAdapter(foo, IAuthorization, 'launchpad.Edit')
21 >>> authorization.checkAuthenticated(salgado)21 >>> print authorization.checkAccountAuthenticated(salgado.account)
22 True22 True
2323
24So can a member of the Launchpad admins team.24So can a member of the Launchpad admins team.
2525
26 >>> mark = getUtility(IPersonSet).getByName('mark')26 >>> mark = getUtility(IPersonSet).getByName('mark')
27 >>> admins = getUtility(IPersonSet).getByName('admins')27 >>> admins = getUtility(IPersonSet).getByName('admins')
28 >>> mark.inTeam(admins)28 >>> print mark.inTeam(admins)
29 True29 True
30 >>> authorization.checkAuthenticated(mark)30 >>> print authorization.checkAccountAuthenticated(mark.account)
31 True31 True
3232
33But someone who's not salgado nor a member of the admins team won't be33But someone who's not salgado nor a member of the admins team won't be
34able to.34able to.
3535
36 >>> sample_person = getUtility(IPersonSet).getByName('name12')36 >>> sample_person = getUtility(IPersonSet).getByName('name12')
37 >>> sample_person.inTeam(admins)37 >>> print sample_person.inTeam(admins)
38 False38 False
39 >>> authorization.checkAuthenticated(sample_person)39 >>> print authorization.checkAccountAuthenticated(sample_person)
40 False40 False
4141
=== added file 'lib/canonical/launchpad/doc/personroles.txt'
--- lib/canonical/launchpad/doc/personroles.txt 1970-01-01 00:00:00 +0000
+++ lib/canonical/launchpad/doc/personroles.txt 2010-01-15 07:14:13 +0000
@@ -0,0 +1,130 @@
1= PersonRoles =
2
3To make it more convenient to check which roles a person has,
4the IPersonRoles adapter is provided. It's main use is to easily check if a
5person is the member of a celebrity team or is a celebrity person. In
6addition, methods for common checks are provided, too.
7
8The IPersonRoles interface is closely tight to the ILaunchpadCelebrities
9interface. Any addition or removal of a person celebrity must be reflected in
10adding or removing the corresponding property in IPersonRoles. Luckily the
11celebrities.txt doctest includes a check for this and will give useful
12information on which attribute needs to be added or removed. Both interfaces
13are found in the same file. There is no need to adapt the implementation
14class PersonRoles, though (thanks to __getattr__).
15
16PersonRoles is most prominent in AuthenticationBase in security.py. The user
17parameter to checkAuthenticated is a PersonRoles object (was a Person object).
18
19
20== The person object and the adapter ==
21
22PersonRoles is registered as an unnamed adapter for IPersonRoles.
23
24 >>> from canonical.launchpad.interfaces.launchpad import IPersonRoles
25 >>> person = factory.makePerson()
26 >>> print IPersonRoles(person)
27 <canonical.launchpad.utilities.personroles.PersonRoles object at ...>
28
29The original Person object can be reached through the person attribute.
30
31 >>> roles = IPersonRoles(person)
32 >>> print roles.person is person
33 True
34
35
36== Celebrity persons ==
37
38There are a number of celebrity persons defined in ILaunchpadCelebrities.
39PersonRoles has a corresponding attribute of the same name prefixed with
40"in_" to check if the person in question is a member of this celebrity or is
41this celebrity. The following tests are identical.
42
43 >>> from canonical.launchpad.interfaces.launchpad import (
44 ... ILaunchpadCelebrities)
45 >>> rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts
46 >>> print person.inTeam(rosetta_experts)
47 False
48
49 >>> print roles.in_rosetta_experts
50 False
51
52The test will succeed once we make person a member of the team. Need to be an
53admin to do that.
54
55 >>> login("foo.bar@canonical.com")
56 >>> rosetta_experts.addMember(person, rosetta_experts.teamowner)
57 (True, ...Approved>)
58 >>> print roles.in_rosetta_experts
59 True
60
61To stay consistent, all attributes are prefixed with "in_" although the
62attribute names of ILaunchpadCelebrities are not all lexically correct
63plurals, nor are all the attributes teams. This makes for odd sounding
64attribute names in IPersonRoles.
65
66 >>> print roles.in_admin
67 False
68 >>> print roles.in_janitor
69 False
70
71 >>> janitor = getUtility(ILaunchpadCelebrities).janitor
72 >>> janitor_roles = IPersonRoles(janitor)
73 >>> print janitor_roles.in_janitor
74 True
75
76
77== inTeam ==
78
79The Person.inTeam method is available directly through PersonRoles. This can
80be used to check for any non-celebrity team.
81
82 >>> new_team = factory.makeTeam()
83 >>> new_team.addMember(person, new_team.teamowner)
84 (True, ...Approved>)
85 >>> print person.inTeam(new_team)
86 True
87
88 >>> print roles.inTeam(new_team)
89 True
90
91
92== isOwner, isDriver ==
93
94We can easily check for ownership and drivership. This is admittedly not much
95shorter than calling inTeam but clearer to read.
96
97 >>> product = factory.makeProduct(owner=person)
98 >>> print roles.isOwner(product)
99 True
100
101 >>> print roles.isDriver(product)
102 False
103 >>> product.driver = person
104 >>> print roles.isDriver(product)
105 True
106
107
108== isOneOfDrivers ==
109
110If an object implements IHasDrivers it lists all drivers of the object and
111possible parent objects. The method isOneOfDrivers lets us check for those.
112
113 >>> productseries = factory.makeProductSeries(product=product)
114 >>> print roles.isDriver(productseries)
115 False
116 >>> print roles.isOneOfDrivers(productseries)
117 True
118
119
120== isOneOf ==
121
122Finally, sometimes a person may be one of multiple roles for an object. The
123method isOneOf makes checking all of these a breeze.
124
125 >>> spec = factory.makeSpecification()
126 >>> spec.assignee = person
127 >>> print roles.isOwner(spec)
128 False
129 >>> print roles.isOneOf(spec, ['owner', 'approver', 'assignee'])
130 True
0131
=== modified file 'lib/canonical/launchpad/interfaces/launchpad.py'
--- lib/canonical/launchpad/interfaces/launchpad.py 2010-01-12 15:39:36 +0000
+++ lib/canonical/launchpad/interfaces/launchpad.py 2010-01-15 07:14:13 +0000
@@ -223,7 +223,14 @@
223 """Is this person the owner of the object?"""223 """Is this person the owner of the object?"""
224224
225 def isDriver(obj):225 def isDriver(obj):
226 """Is this person one of the drivers of the object?"""226 """Is this person the driver of the object?"""
227
228 def isOneOfDrivers(obj):
229 """Is this person on of the drivers of the object?
230
231 Works on objects that implement 'IHasDrivers' but will default to
232 isDriver if it doesn't, i.e. check the driver attribute.
233 """
227234
228 def isOneOf(obj, attributes):235 def isOneOf(obj, attributes):
229 """Is this person one of the roles in relation to the object?236 """Is this person one of the roles in relation to the object?
230237
=== modified file 'lib/canonical/launchpad/security.py'
--- lib/canonical/launchpad/security.py 2010-01-13 06:50:43 +0000
+++ lib/canonical/launchpad/security.py 2010-01-15 07:14:13 +0000
@@ -154,7 +154,7 @@
154 if person is None:154 if person is None:
155 return self.checkUnauthenticated()155 return self.checkUnauthenticated()
156 else:156 else:
157 return self.checkAuthenticated(person)157 return self.checkAuthenticated(IPersonRoles(person))
158158
159159
160class ViewByLoggedInUser(AuthorizationBase):160class ViewByLoggedInUser(AuthorizationBase):
@@ -176,8 +176,7 @@
176 usedfor = Interface176 usedfor = Interface
177177
178 def checkAuthenticated(self, user):178 def checkAuthenticated(self, user):
179 admins = getUtility(ILaunchpadCelebrities).admin179 return user.in_admin
180 return user.inTeam(admins)
181180
182181
183class AdminByCommercialTeamOrAdmins(AuthorizationBase):182class AdminByCommercialTeamOrAdmins(AuthorizationBase):
@@ -185,9 +184,7 @@
185 usedfor = Interface184 usedfor = Interface
186185
187 def checkAuthenticated(self, user):186 def checkAuthenticated(self, user):
188 celebrities = getUtility(ILaunchpadCelebrities)187 return user.in_commercial_admin or user.in_admin
189 return (user.inTeam(celebrities.commercial_admin)
190 or user.inTeam(celebrities.admin))
191188
192189
193class EditByRegistryExpertsOrAdmins(AuthorizationBase):190class EditByRegistryExpertsOrAdmins(AuthorizationBase):
@@ -195,7 +192,6 @@
195 usedfor = ILaunchpadRoot192 usedfor = ILaunchpadRoot
196193
197 def checkAuthenticated(self, user):194 def checkAuthenticated(self, user):
198 user = IPersonRoles(user)
199 return user.in_admin or user.in_registry_experts195 return user.in_admin or user.in_registry_experts
200196
201197
@@ -204,7 +200,6 @@
204 usedfor = None200 usedfor = None
205201
206 def checkAuthenticated(self, user):202 def checkAuthenticated(self, user):
207 user = IPersonRoles(user)
208 return user.in_admin or user.in_registry_experts203 return user.in_admin or user.in_registry_experts
209204
210205
@@ -241,7 +236,6 @@
241 if self.obj.active:236 if self.obj.active:
242 return True237 return True
243 else:238 else:
244 user = IPersonRoles(user)
245 return (user.in_commercial_admin or239 return (user.in_commercial_admin or
246 user.in_admin or240 user.in_admin or
247 user.in_registry_experts)241 user.in_registry_experts)
@@ -258,7 +252,6 @@
258 EditAccountBySelfOrAdmin, self).checkAccountAuthenticated(account)252 EditAccountBySelfOrAdmin, self).checkAccountAuthenticated(account)
259253
260 def checkAuthenticated(self, user):254 def checkAuthenticated(self, user):
261 user = IPersonRoles(user)
262 return user.in_admin255 return user.in_admin
263256
264257
@@ -271,7 +264,6 @@
271264
272 def checkAuthenticated(self, user):265 def checkAuthenticated(self, user):
273 """Extend permission to registry experts."""266 """Extend permission to registry experts."""
274 user = IPersonRoles(user)
275 return user.in_admin or user.in_registry_experts267 return user.in_admin or user.in_registry_experts
276268
277269
@@ -280,7 +272,6 @@
280 permission = 'launchpad.Moderate'272 permission = 'launchpad.Moderate'
281273
282 def checkAuthenticated(self, user):274 def checkAuthenticated(self, user):
283 user = IPersonRoles(user)
284 return user.in_admin or user.in_registry_experts275 return user.in_admin or user.in_registry_experts
285276
286277
@@ -289,8 +280,7 @@
289 usedfor = IOAuthAccessToken280 usedfor = IOAuthAccessToken
290281
291 def checkAuthenticated(self, user):282 def checkAuthenticated(self, user):
292 return (self.obj.person == user283 return self.obj.person == user or user.in_admin
293 or user.inTeam(getUtility(ILaunchpadCelebrities).admin))
294284
295285
296class EditOAuthRequestToken(EditOAuthAccessToken):286class EditOAuthRequestToken(EditOAuthAccessToken):
@@ -303,7 +293,7 @@
303 usedfor = IBugNomination293 usedfor = IBugNomination
304294
305 def checkAuthenticated(self, user):295 def checkAuthenticated(self, user):
306 return self.obj.canApprove(user)296 return self.obj.canApprove(user.person)
307297
308298
309class EditByOwnersOrAdmins(AuthorizationBase):299class EditByOwnersOrAdmins(AuthorizationBase):
@@ -311,8 +301,7 @@
311 usedfor = IHasOwner301 usedfor = IHasOwner
312302
313 def checkAuthenticated(self, user):303 def checkAuthenticated(self, user):
314 return (user.inTeam(self.obj.owner)304 return user.isOwner(self.obj) or user.in_admin
315 or user.inTeam(getUtility(ILaunchpadCelebrities).admin))
316305
317306
318class EditProduct(EditByOwnersOrAdmins):307class EditProduct(EditByOwnersOrAdmins):
@@ -338,9 +327,8 @@
338 usedfor = IDistributionMirror327 usedfor = IDistributionMirror
339328
340 def checkAuthenticated(self, user):329 def checkAuthenticated(self, user):
341 admins = getUtility(ILaunchpadCelebrities).admin330 return (user.isOwner(self.obj.distribution) or
342 return (user.inTeam(self.obj.distribution.owner) or331 user.in_admin or
343 user.inTeam(admins) or
344 user.inTeam(self.obj.distribution.mirror_admin))332 user.inTeam(self.obj.distribution.mirror_admin))
345333
346334
@@ -350,9 +338,8 @@
350 usedfor = IDistributionMirror338 usedfor = IDistributionMirror
351339
352 def checkAuthenticated(self, user):340 def checkAuthenticated(self, user):
353 admins = getUtility(ILaunchpadCelebrities).admin341 return (user.isOwner(self.obj) or user.in_admin or
354 return (user.inTeam(self.obj.owner) or user.inTeam(admins) or342 user.isOwner(self.obj.distribution) or
355 user.inTeam(self.obj.distribution.owner) or
356 user.inTeam(self.obj.distribution.mirror_admin))343 user.inTeam(self.obj.distribution.mirror_admin))
357344
358345
@@ -392,22 +379,14 @@
392379
393 def checkAuthenticated(self, user):380 def checkAuthenticated(self, user):
394 assert self.obj.target381 assert self.obj.target
395 admins = getUtility(ILaunchpadCelebrities).admin382 goal = self.obj.goal
396 goaldrivers = []383 if goal is not None:
397 goalowner = None384 if user.isOwner(goal) or user.isOneOfDrivers(goal):
398 if self.obj.goal is not None:
399 goalowner = self.obj.goal.owner
400 goaldrivers = self.obj.goal.drivers
401 for driver in goaldrivers:
402 if user.inTeam(driver):
403 return True385 return True
404 return (user.inTeam(self.obj.target.owner) or386 return (user.in_admin or
405 user.inTeam(goalowner) or387 user.isOwner(self.obj.target) or
406 user.inTeam(self.obj.owner) or388 user.isOneOf(
407 user.inTeam(self.obj.drafter) or389 self.obj, ['owner','drafter', 'assignee', 'approver']))
408 user.inTeam(self.obj.assignee) or
409 user.inTeam(self.obj.approver) or
410 user.inTeam(admins))
411390
412391
413class AdminSpecification(AuthorizationBase):392class AdminSpecification(AuthorizationBase):
@@ -416,13 +395,9 @@
416395
417 def checkAuthenticated(self, user):396 def checkAuthenticated(self, user):
418 assert self.obj.target397 assert self.obj.target
419 targetowner = self.obj.target.owner398 return (user.isOwner(self.obj.target) or
420 targetdrivers = self.obj.target.drivers399 user.isOneOfDrivers(self.obj.target) or
421 for driver in targetdrivers:400 user.in_admin)
422 if user.inTeam(driver):
423 return True
424 admins = getUtility(ILaunchpadCelebrities).admin
425 return (user.inTeam(targetowner) or user.inTeam(admins))
426401
427402
428class DriverSpecification(AuthorizationBase):403class DriverSpecification(AuthorizationBase):
@@ -448,10 +423,8 @@
448 usedfor = ISprintSpecification423 usedfor = ISprintSpecification
449424
450 def checkAuthenticated(self, user):425 def checkAuthenticated(self, user):
451 admins = getUtility(ILaunchpadCelebrities).admin426 sprint = self.obj.sprint
452 return (user.inTeam(self.obj.sprint.owner) or427 return user.isOwner(sprint) or user.isDriver(sprint) or user.in_admin
453 user.inTeam(self.obj.sprint.driver) or
454 user.inTeam(admins))
455428
456429
457class DriveSprint(AuthorizationBase):430class DriveSprint(AuthorizationBase):
@@ -462,10 +435,9 @@
462 usedfor = ISprint435 usedfor = ISprint
463436
464 def checkAuthenticated(self, user):437 def checkAuthenticated(self, user):
465 admins = getUtility(ILaunchpadCelebrities).admin438 return (user.isOwner(self.obj) or
466 return (user.inTeam(self.obj.owner) or439 user.isDriver(self.obj) or
467 user.inTeam(self.obj.driver) or440 user.in_admin)
468 user.inTeam(admins))
469441
470442
471class Sprint(AuthorizationBase):443class Sprint(AuthorizationBase):
@@ -474,12 +446,11 @@
474 usedfor = ISprint446 usedfor = ISprint
475447
476 def checkAuthenticated(self, user):448 def checkAuthenticated(self, user):
477 admins = getUtility(ILaunchpadCelebrities).admin449 return (user.isOwner(self.obj) or
478 return (user.inTeam(self.obj.owner) or450 user.isDriver(self.obj) or
479 user.inTeam(self.obj.driver) or451 user.person in [attendance.attendee
480 user in [attendance.attendee452 for attendance in self.obj.attendances] or
481 for attendance in self.obj.attendances] or453 user.in_admin)
482 user.inTeam(admins))
483454
484455
485class EditSpecificationSubscription(AuthorizationBase):456class EditSpecificationSubscription(AuthorizationBase):
@@ -489,21 +460,17 @@
489 usedfor = ISpecificationSubscription460 usedfor = ISpecificationSubscription
490461
491 def checkAuthenticated(self, user):462 def checkAuthenticated(self, user):
492 admins = getUtility(ILaunchpadCelebrities).admin
493 if self.obj.specification.goal is not None:463 if self.obj.specification.goal is not None:
494 for driver in self.obj.specification.goal.drivers:464 if user.isOneOfDrivers(self.obj.specification.goal):
495 if user.inTeam(driver):465 return True
496 return True
497 else:466 else:
498 for driver in self.obj.specification.target.drivers:467 if user.isOneOfDrivers(self.obj.specification.target):
499 if user.inTeam(driver):468 return True
500 return True
501 return (user.inTeam(self.obj.person) or469 return (user.inTeam(self.obj.person) or
502 user.inTeam(self.obj.specification.owner) or470 user.isOneOf(
503 user.inTeam(self.obj.specification.assignee) or471 self.obj.specification,
504 user.inTeam(self.obj.specification.drafter) or472 ['owner','drafter', 'assignee', 'approver']) or
505 user.inTeam(self.obj.specification.approver) or473 user.in_admin)
506 user.inTeam(admins))
507474
508475
509class OnlyRosettaExpertsAndAdmins(AuthorizationBase):476class OnlyRosettaExpertsAndAdmins(AuthorizationBase):
@@ -512,7 +479,6 @@
512479
513 def checkAuthenticated(self, user):480 def checkAuthenticated(self, user):
514 """Allow Launchpad's admins and Rosetta experts edit all fields."""481 """Allow Launchpad's admins and Rosetta experts edit all fields."""
515 user = IPersonRoles(user)
516 return user.in_admin or user.in_rosetta_experts482 return user.in_admin or user.in_rosetta_experts
517483
518484
@@ -526,7 +492,6 @@
526 Any Launchpad/Launchpad Translations administrator or owners are492 Any Launchpad/Launchpad Translations administrator or owners are
527 able to change translation settings for a product.493 able to change translation settings for a product.
528 """494 """
529 user = IPersonRoles(user)
530 return (user.isOwner(self.obj) or495 return (user.isOwner(self.obj) or
531 user.in_rosetta_experts or496 user.in_rosetta_experts or
532 user.in_admin)497 user.in_admin)
@@ -537,8 +502,7 @@
537 usedfor = IProductSeries502 usedfor = IProductSeries
538503
539 def checkAuthenticated(self, user):504 def checkAuthenticated(self, user):
540 vcs_imports = getUtility(ILaunchpadCelebrities).vcs_imports505 return user.in_vcs_imports
541 return user.inTeam(vcs_imports)
542506
543507
544class EditProjectMilestoneNever(AuthorizationBase):508class EditProjectMilestoneNever(AuthorizationBase):
@@ -556,16 +520,15 @@
556520
557 def checkAuthenticated(self, user):521 def checkAuthenticated(self, user):
558 """Authorize the product or distribution owner."""522 """Authorize the product or distribution owner."""
559 celebrities = getUtility(ILaunchpadCelebrities)523 if user.in_admin:
560 if user.inTeam(celebrities.admin):
561 return True524 return True
562 if (self.obj.series_target is not None525 if (self.obj.series_target is not None
563 and user.inTeam(self.obj.series_target.driver)):526 and user.isDriver(self.obj.series_target)):
564 # The user is a release manager.527 # The user is a release manager.
565 # XXX sinzui 2009-07-18 bug=40978: The series_target should never528 # XXX sinzui 2009-07-18 bug=40978: The series_target should never
566 # be None, but Milestones in the production DB are like this.529 # be None, but Milestones in the production DB are like this.
567 return True530 return True
568 return user.inTeam(self.obj.target.owner)531 return user.isOwner(self.obj.target)
569532
570class AdminMilestoneByLaunchpadAdmins(AuthorizationBase):533class AdminMilestoneByLaunchpadAdmins(AuthorizationBase):
571 permission = 'launchpad.Admin'534 permission = 'launchpad.Admin'
@@ -575,8 +538,7 @@
575 """Only the Launchpad admins need this, we are only going to use it538 """Only the Launchpad admins need this, we are only going to use it
576 for connecting up series and distroseriess where we did not have539 for connecting up series and distroseriess where we did not have
577 them."""540 them."""
578 admins = getUtility(ILaunchpadCelebrities).admin541 return user.in_admin
579 return user.inTeam(admins)
580542
581543
582class ModeratePersonSetByExpertsOrAdmins(ReviewByRegistryExpertsOrAdmins):544class ModeratePersonSetByExpertsOrAdmins(ReviewByRegistryExpertsOrAdmins):
@@ -591,8 +553,7 @@
591 def checkAuthenticated(self, user):553 def checkAuthenticated(self, user):
592 """Only the team owner and Launchpad admins need this.554 """Only the team owner and Launchpad admins need this.
593 """555 """
594 admins = getUtility(ILaunchpadCelebrities).admin556 return user.inTeam(self.obj.teamowner) or user.in_admin
595 return user.inTeam(self.obj.teamowner) or user.inTeam(admins)
596557
597558
598class EditTeamByTeamOwnerOrTeamAdminsOrAdmins(AuthorizationBase):559class EditTeamByTeamOwnerOrTeamAdminsOrAdmins(AuthorizationBase):
@@ -650,8 +611,7 @@
650 """611 """
651 if self.obj.team.visibility == PersonVisibility.PUBLIC:612 if self.obj.team.visibility == PersonVisibility.PUBLIC:
652 return True613 return True
653 admins = getUtility(ILaunchpadCelebrities).admin614 if user.in_admin or user.inTeam(self.obj.team):
654 if user.inTeam(admins) or user.inTeam(self.obj.team):
655 return True615 return True
656 return False616 return False
657617
@@ -665,8 +625,7 @@
665625
666 The admin team can also edit any Person.626 The admin team can also edit any Person.
667 """627 """
668 admins = getUtility(ILaunchpadCelebrities).admin628 return self.obj.id == user.person.id or user.in_admin
669 return self.obj.id == user.id or user.inTeam(admins)
670629
671630
672class EditTranslationsPersonByPerson(AuthorizationBase):631class EditTranslationsPersonByPerson(AuthorizationBase):
@@ -675,8 +634,7 @@
675634
676 def checkAuthenticated(self, user):635 def checkAuthenticated(self, user):
677 person = self.obj.person636 person = self.obj.person
678 admins = getUtility(ILaunchpadCelebrities).admin637 return person == user.person or user.in_admin
679 return person == user or user.inTeam(admins)
680638
681639
682class ViewPersonLocation(AuthorizationBase):640class ViewPersonLocation(AuthorizationBase):
@@ -690,8 +648,7 @@
690 if self.obj.visible:648 if self.obj.visible:
691 return True649 return True
692 else:650 else:
693 admins = getUtility(ILaunchpadCelebrities).admin651 return user.person == self.obj.person or user.in_admin
694 return user == self.obj.person or user.inTeam(admins)
695652
696653
697class EditPersonBySelf(AuthorizationBase):654class EditPersonBySelf(AuthorizationBase):
@@ -700,7 +657,7 @@
700657
701 def checkAuthenticated(self, user):658 def checkAuthenticated(self, user):
702 """A user can edit the Person who is herself."""659 """A user can edit the Person who is herself."""
703 return self.obj.id == user.id660 return self.obj.id == user.person.id
704661
705662
706class ViewPublicOrPrivateTeamMembers(AuthorizationBase):663class ViewPublicOrPrivateTeamMembers(AuthorizationBase):
@@ -718,26 +675,21 @@
718 return True675 return True
719 return False676 return False
720677
721 def checkAccountAuthenticated(self, account):678 def checkAuthenticated(self, user):
722 """See `IAuthorization.checkAccountAuthenticated`.679 """Verify that the user can view the team's membership.
723
724 Verify that the user can view the team's membership.
725680
726 Anyone can see a public team's membership. Only a team member681 Anyone can see a public team's membership. Only a team member
727 or a Launchpad admin can view a private membership.682 or a Launchpad admin can view a private membership.
728 """683 """
729 if self.obj.visibility == PersonVisibility.PUBLIC:684 if self.obj.visibility == PersonVisibility.PUBLIC:
730 return True685 return True
731 user = IPerson(account, None)686 if user.in_admin or user.inTeam(self.obj):
732 if user is None:
733 return False
734 admins = getUtility(ILaunchpadCelebrities).admin
735 if user.inTeam(admins) or user.inTeam(self.obj):
736 return True687 return True
737 # We also grant visibility of the private team to administrators of688 # We also grant visibility of the private team to administrators of
738 # other teams that have been invited to join the private team.689 # other teams that have been invited to join the private team.
739 for invitee in self.obj.invited_members:690 for invitee in self.obj.invited_members:
740 if invitee.is_team and invitee in user.getAdministratedTeams():691 if (invitee.is_team and
692 invitee in user.person.getAdministratedTeams()):
741 return True693 return True
742 return False694 return False
743695
@@ -779,9 +731,7 @@
779 usedfor = IDistribution731 usedfor = IDistribution
780732
781 def checkAuthenticated(self, user):733 def checkAuthenticated(self, user):
782 admins = getUtility(ILaunchpadCelebrities).admin734 return user.isOwner(self.obj) or user.in_admin
783 return (user.inTeam(self.obj.owner) or
784 user.inTeam(admins))
785735
786736
787class AppendDistributionByDriversOrOwnersOrAdmins(AuthorizationBase):737class AppendDistributionByDriversOrOwnersOrAdmins(AuthorizationBase):
@@ -794,13 +744,11 @@
794 usedfor = IDistribution744 usedfor = IDistribution
795745
796 def checkAuthenticated(self, user):746 def checkAuthenticated(self, user):
797 if user.inTeam(self.obj.driver) and not self.obj.full_functionality:747 if user.isDriver(self.obj) and not self.obj.full_functionality:
798 # Drivers of derivative distributions can create a series that748 # Drivers of derivative distributions can create a series that
799 # they will be the release manager for.749 # they will be the release manager for.
800 return True750 return True
801 admins = getUtility(ILaunchpadCelebrities).admin751 return user.isOwner(self.obj) or user.in_admin
802 return (user.inTeam(self.obj.owner) or
803 user.inTeam(admins))
804752
805753
806class EditDistributionSourcePackageByDistroOwnersOrAdmins(AuthorizationBase):754class EditDistributionSourcePackageByDistroOwnersOrAdmins(AuthorizationBase):
@@ -810,9 +758,8 @@
810 usedfor = IDistributionSourcePackage758 usedfor = IDistributionSourcePackage
811759
812 def checkAuthenticated(self, user):760 def checkAuthenticated(self, user):
813 admins = getUtility(ILaunchpadCelebrities).admin
814 return (user.inTeam(self.obj.distribution.owner) or761 return (user.inTeam(self.obj.distribution.owner) or
815 user.inTeam(admins))762 user.in_admin)
816763
817764
818class AdminDistroSeries(AdminByAdminsTeam):765class AdminDistroSeries(AdminByAdminsTeam):
@@ -846,10 +793,9 @@
846 # The series driver (release manager) may edit a series if the793 # The series driver (release manager) may edit a series if the
847 # distribution is an `IDerivativeDistribution`794 # distribution is an `IDerivativeDistribution`
848 return True795 return True
849 admins = getUtility(ILaunchpadCelebrities).admin
850 return (user.inTeam(self.obj.owner) or796 return (user.inTeam(self.obj.owner) or
851 user.inTeam(self.obj.distribution.owner) or797 user.inTeam(self.obj.distribution.owner) or
852 user.inTeam(admins))798 user.in_admin)
853799
854800
855class SeriesDrivers(AuthorizationBase):801class SeriesDrivers(AuthorizationBase):
@@ -862,11 +808,9 @@
862 usedfor = IHasDrivers808 usedfor = IHasDrivers
863809
864 def checkAuthenticated(self, user):810 def checkAuthenticated(self, user):
865 for driver in self.obj.drivers:811 return (user.isOneOfDrivers(self.obj) or
866 if user.inTeam(driver):812 user.isOwner(self.obj) or
867 return True813 user.in_admin)
868 admins = getUtility(ILaunchpadCelebrities).admin
869 return user.inTeam(self.obj.owner) or user.inTeam(admins)
870814
871815
872class ViewProductSeries(AuthorizationBase):816class ViewProductSeries(AuthorizationBase):
@@ -901,10 +845,9 @@
901 # Rosetta experts need to be able to upload translations.845 # Rosetta experts need to be able to upload translations.
902 # Bazaar experts need to be able to change the linked branches.846 # Bazaar experts need to be able to change the linked branches.
903 # Registry admins are just special.847 # Registry admins are just special.
904 celebrities = getUtility(ILaunchpadCelebrities)848 if (user.in_registry_experts or
905 if (user.inTeam(celebrities.registry_experts) or849 user.in_bazaar_experts or
906 user.inTeam(celebrities.bazaar_experts) or850 user.in_rosetta_experts):
907 user.inTeam(celebrities.rosetta_experts)):
908 return True851 return True
909 return EditByOwnersOrAdmins.checkAuthenticated(self, user)852 return EditByOwnersOrAdmins.checkAuthenticated(self, user)
910853
@@ -920,9 +863,8 @@
920 usedfor = IHasBug863 usedfor = IHasBug
921864
922 def checkAuthenticated(self, user):865 def checkAuthenticated(self, user):
923 admins = getUtility(ILaunchpadCelebrities).admin
924866
925 if user.inTeam(admins):867 if user.in_admin:
926 # Admins can always edit bugtasks, whether they're reported on a868 # Admins can always edit bugtasks, whether they're reported on a
927 # private bug or not.869 # private bug or not.
928 return True870 return True
@@ -946,7 +888,7 @@
946 usedfor = IHasBug888 usedfor = IHasBug
947889
948 def checkAuthenticated(self, user):890 def checkAuthenticated(self, user):
949 return self.obj.bug.userCanView(user)891 return self.obj.bug.userCanView(user.person)
950892
951 def checkUnauthenticated(self):893 def checkUnauthenticated(self):
952 """Allow anonymous users to see non-private bugs only."""894 """Allow anonymous users to see non-private bugs only."""
@@ -962,11 +904,10 @@
962 """Allow any logged in user to edit a public bug, and only904 """Allow any logged in user to edit a public bug, and only
963 explicit subscribers to edit private bugs.905 explicit subscribers to edit private bugs.
964 """906 """
965 admins = getUtility(ILaunchpadCelebrities).admin
966 if not self.obj.private:907 if not self.obj.private:
967 # This is a public bug.908 # This is a public bug.
968 return True909 return True
969 elif user.inTeam(admins):910 elif user.in_admin:
970 # Admins can edit all bugs.911 # Admins can edit all bugs.
971 return True912 return True
972 else:913 else:
@@ -990,7 +931,7 @@
990 """Allow any user to see non-private bugs, but only explicit931 """Allow any user to see non-private bugs, but only explicit
991 subscribers to see private bugs.932 subscribers to see private bugs.
992 """933 """
993 return self.obj.userCanView(user)934 return self.obj.userCanView(user.person)
994935
995 def checkUnauthenticated(self):936 def checkUnauthenticated(self):
996 """Allow anonymous users to see non-private bugs only."""937 """Allow anonymous users to see non-private bugs only."""
@@ -1056,17 +997,11 @@
1056 return True997 return True
1057998
1058 # Project drivers can view any project announcements.999 # Project drivers can view any project announcements.
1059 assert self.obj.target
1060 if self.obj.target.drivers:
1061 for driver in self.obj.target.drivers:
1062 if user.inTeam(driver):
1063 return True
1064 if user.inTeam(self.obj.target.owner):
1065 return True
1066
1067 # Launchpad admins can view any announcement.1000 # Launchpad admins can view any announcement.
1068 admins = getUtility(ILaunchpadCelebrities).admin1001 assert self.obj.target
1069 return user.inTeam(admins)1002 return (user.isOneOfDrivers(self.obj.target) or
1003 user.isOwner(self.obj.target) or
1004 user.in_admin)
10701005
10711006
1072class EditAnnouncement(AuthorizationBase):1007class EditAnnouncement(AuthorizationBase):
@@ -1077,15 +1012,9 @@
1077 """Allow the project owner and drivers to edit any project news."""1012 """Allow the project owner and drivers to edit any project news."""
10781013
1079 assert self.obj.target1014 assert self.obj.target
1080 if self.obj.target.drivers:1015 return (user.isOneOfDrivers(self.obj.target) or
1081 for driver in self.obj.target.drivers:1016 user.isOwner(self.obj.target) or
1082 if user.inTeam(driver):1017 user.in_admin)
1083 return True
1084 if user.inTeam(self.obj.target.owner):
1085 return True
1086
1087 admins = getUtility(ILaunchpadCelebrities).admin
1088 return user.inTeam(admins)
10891018
10901019
1091class UseApiDoc(AuthorizationBase):1020class UseApiDoc(AuthorizationBase):
@@ -1101,9 +1030,7 @@
1101 experts."""1030 experts."""
11021031
1103 def checkAuthenticated(self, user):1032 def checkAuthenticated(self, user):
1104 bzrexperts = getUtility(ILaunchpadCelebrities).bazaar_experts1033 return user.in_admin or user.in_bazaar_experts
1105 admins = getUtility(ILaunchpadCelebrities).admin
1106 return user.inTeam(admins) or user.inTeam(bzrexperts)
11071034
11081035
1109class OnlyVcsImportsAndAdmins(AuthorizationBase):1036class OnlyVcsImportsAndAdmins(AuthorizationBase):
@@ -1111,9 +1038,7 @@
1111 experts."""1038 experts."""
11121039
1113 def checkAuthenticated(self, user):1040 def checkAuthenticated(self, user):
1114 vcsexpert = getUtility(ILaunchpadCelebrities).vcs_imports1041 return user.in_admin or user.in_vcs_imports
1115 admins = getUtility(ILaunchpadCelebrities).admin
1116 return user.inTeam(admins) or user.inTeam(vcsexpert)
11171042
11181043
1119class AdminTheBazaar(OnlyVcsImportsAndAdmins):1044class AdminTheBazaar(OnlyVcsImportsAndAdmins):
@@ -1252,11 +1177,10 @@
1252 def checkAuthenticated(self, user):1177 def checkAuthenticated(self, user):
1253 """Allow anyone that can edit translations, owner, experts and admis.1178 """Allow anyone that can edit translations, owner, experts and admis.
1254 """1179 """
1255 rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts
12561180
1257 return (EditByOwnersOrAdmins.checkAuthenticated(self, user) or1181 return (EditByOwnersOrAdmins.checkAuthenticated(self, user) or
1258 self.obj.canEditTranslations(user) or1182 self.obj.canEditTranslations(user.person) or
1259 user.inTeam(rosetta_experts))1183 user.in_rosetta_experts)
12601184
12611185
1262class AdminTranslator(OnlyRosettaExpertsAndAdmins):1186class AdminTranslator(OnlyRosettaExpertsAndAdmins):
@@ -1370,7 +1294,7 @@
13701294
1371 # As a special case, the Ubuntu translation group owners can1295 # As a special case, the Ubuntu translation group owners can
1372 # manage Ubuntu uploads.1296 # manage Ubuntu uploads.
1373 if self.obj.isUbuntuAndIsUserTranslationGroupOwner(user):1297 if self.obj.isUbuntuAndIsUserTranslationGroupOwner(user.person):
1374 return True1298 return True
13751299
1376 return False1300 return False
@@ -1386,7 +1310,7 @@
1386 """1310 """
1387 if AdminTranslationImportQueueEntry.checkAuthenticated(self, user):1311 if AdminTranslationImportQueueEntry.checkAuthenticated(self, user):
1388 return True1312 return True
1389 if self.obj.isUserUploaderOrOwner(user):1313 if self.obj.isUserUploaderOrOwner(user.person):
1390 return True1314 return True
13911315
1392 return False1316 return False
@@ -1408,7 +1332,7 @@
14081332
1409 permission_set = getUtility(IArchivePermissionSet)1333 permission_set = getUtility(IArchivePermissionSet)
1410 permissions = permission_set.componentsForQueueAdmin(1334 permissions = permission_set.componentsForQueueAdmin(
1411 self.obj.distroseries.main_archive, user)1335 self.obj.distroseries.main_archive, user.person)
1412 return permissions.count() > 01336 return permissions.count() > 0
14131337
14141338
@@ -1431,7 +1355,7 @@
14311355
1432 permission_set = getUtility(IArchivePermissionSet)1356 permission_set = getUtility(IArchivePermissionSet)
1433 permissions = permission_set.componentsForQueueAdmin(1357 permissions = permission_set.componentsForQueueAdmin(
1434 self.obj.archive, user)1358 self.obj.archive, user.person)
1435 if permissions.count() == 0:1359 if permissions.count() == 0:
1436 return False1360 return False
1437 allowed_components = set(1361 allowed_components = set(
@@ -1449,11 +1373,7 @@
14491373
1450 def checkAuthenticated(self, user):1374 def checkAuthenticated(self, user):
1451 """Allow admins and buildd_admins."""1375 """Allow admins and buildd_admins."""
1452 lp_admin = getUtility(ILaunchpadCelebrities).admin1376 return user.in_buildd_admin or user.in_admin
1453 if user.inTeam(lp_admin):
1454 return True
1455 buildd_admin = getUtility(ILaunchpadCelebrities).buildd_admin
1456 return user.inTeam(buildd_admin)
14571377
14581378
1459class AdminBuilderSet(AdminByBuilddAdmin):1379class AdminBuilderSet(AdminByBuilddAdmin):
@@ -1500,11 +1420,12 @@
1500 # Primary or partner section here: is the user in question allowed1420 # Primary or partner section here: is the user in question allowed
1501 # to upload to the respective component? Allow user to retry build1421 # to upload to the respective component? Allow user to retry build
1502 # if so.1422 # if so.
1503 if self.obj.archive.canUpload(user, self.obj.current_component):1423 archive = self.obj.archive
1424 if archive.canUpload(user.person, self.obj.current_component):
1504 return True1425 return True
1505 else:1426 else:
1506 return self.obj.archive.canUpload(1427 return archive.canUpload(
1507 user, self.obj.sourcepackagerelease.sourcepackagename)1428 user.person, self.obj.sourcepackagerelease.sourcepackagename)
15081429
15091430
1510class ViewBuildRecord(EditBuildRecord):1431class ViewBuildRecord(EditBuildRecord):
@@ -1524,8 +1445,7 @@
1524 return True1445 return True
15251446
1526 # LP admins may also see it.1447 # LP admins may also see it.
1527 lp_admin = getUtility(ILaunchpadCelebrities).admin1448 if user.in_admin:
1528 if user.inTeam(lp_admin):
1529 return True1449 return True
15301450
1531 # If the permission check on the sourcepackagerelease for this1451 # If the permission check on the sourcepackagerelease for this
@@ -1611,10 +1531,10 @@
16111531
1612def can_edit_team(team, user):1532def can_edit_team(team, user):
1613 """Return True if the given user has edit rights for the given team."""1533 """Return True if the given user has edit rights for the given team."""
1614 if user.inTeam(getUtility(ILaunchpadCelebrities).admin):1534 if user.in_admin:
1615 return True1535 return True
1616 else:1536 else:
1617 return team in user.getAdministratedTeams()1537 return team in user.person.getAdministratedTeams()
16181538
16191539
1620class AdminLanguageSet(OnlyRosettaExpertsAndAdmins):1540class AdminLanguageSet(OnlyRosettaExpertsAndAdmins):
@@ -1638,7 +1558,7 @@
1638 usedfor = IBranch1558 usedfor = IBranch
16391559
1640 def checkAuthenticated(self, user):1560 def checkAuthenticated(self, user):
1641 return self.obj.visibleByUser(user)1561 return self.obj.visibleByUser(user.person)
16421562
1643 def checkUnauthenticated(self):1563 def checkUnauthenticated(self):
1644 return self.obj.visibleByUser(None)1564 return self.obj.visibleByUser(None)
@@ -1652,7 +1572,7 @@
1652 def checkAuthenticated(self, user):1572 def checkAuthenticated(self, user):
1653 can_edit = (1573 can_edit = (
1654 user.inTeam(self.obj.owner) or1574 user.inTeam(self.obj.owner) or
1655 user_has_special_branch_access(user) or1575 user_has_special_branch_access(user.person) or
1656 can_upload_linked_package(user, self.obj))1576 can_upload_linked_package(user, self.obj))
1657 if can_edit:1577 if can_edit:
1658 return True1578 return True
@@ -1666,12 +1586,12 @@
1666 return False1586 return False
1667 vcs_imports = getUtility(ILaunchpadCelebrities).vcs_imports1587 vcs_imports = getUtility(ILaunchpadCelebrities).vcs_imports
1668 return (1588 return (
1669 user.inTeam(vcs_imports)1589 user.in_vcs_imports
1670 or (self.obj.owner == vcs_imports1590 or (self.obj.owner == vcs_imports
1671 and user.inTeam(code_import.registrant)))1591 and user.inTeam(code_import.registrant)))
16721592
16731593
1674def can_upload_linked_package(person, branch):1594def can_upload_linked_package(person_role, branch):
1675 """True if person may upload the package linked to `branch`."""1595 """True if person may upload the package linked to `branch`."""
1676 # No associated `ISuiteSourcePackage` data -> not an official branch.1596 # No associated `ISuiteSourcePackage` data -> not an official branch.
1677 # Abort.1597 # Abort.
@@ -1686,7 +1606,7 @@
1686 # one combination that allows us to upload the corresponding source1606 # one combination that allows us to upload the corresponding source
1687 # package.1607 # package.
1688 for ssp in ssp_list:1608 for ssp in ssp_list:
1689 if can_upload_to_archive(person, ssp):1609 if can_upload_to_archive(person_role.person, ssp):
1690 return True1610 return True
1691 return False1611 return False
16921612
@@ -1697,9 +1617,8 @@
1697 usedfor = IBranch1617 usedfor = IBranch
16981618
1699 def checkAuthenticated(self, user):1619 def checkAuthenticated(self, user):
1700 celebs = getUtility(ILaunchpadCelebrities)1620 return (user.in_admin or
1701 return (user.inTeam(celebs.admin) or1621 user.in_bazaar_experts)
1702 user.inTeam(celebs.bazaar_experts))
17031622
17041623
1705# Please keep this in sync with AdminPOTemplateDetails. Note that1624# Please keep this in sync with AdminPOTemplateDetails. Note that
@@ -1788,10 +1707,9 @@
1788 Any team member can edit a branch subscription for their team.1707 Any team member can edit a branch subscription for their team.
1789 Launchpad Admins can also edit any branch subscription.1708 Launchpad Admins can also edit any branch subscription.
1790 """1709 """
1791 celebs = getUtility(ILaunchpadCelebrities)
1792 return (user.inTeam(self.obj.person) or1710 return (user.inTeam(self.obj.person) or
1793 user.inTeam(celebs.admin) or1711 user.in_admin or
1794 user.inTeam(celebs.bazaar_experts))1712 user.in_bazaar_experts)
17951713
17961714
1797class BranchSubscriptionView(BranchSubscriptionEdit):1715class BranchSubscriptionView(BranchSubscriptionEdit):
@@ -1903,13 +1821,12 @@
1903 * the reviewer for the target_branch1821 * the reviewer for the target_branch
1904 * an administrator1822 * an administrator
1905 """1823 """
1906 celebs = getUtility(ILaunchpadCelebrities)
1907 return (user.inTeam(self.obj.registrant) or1824 return (user.inTeam(self.obj.registrant) or
1908 user.inTeam(self.obj.source_branch.owner) or1825 user.inTeam(self.obj.source_branch.owner) or
1909 user.inTeam(self.obj.target_branch.owner) or1826 user.inTeam(self.obj.target_branch.owner) or
1910 user.inTeam(self.obj.target_branch.reviewer) or1827 user.inTeam(self.obj.target_branch.reviewer) or
1911 user.inTeam(celebs.admin) or1828 user.in_admin or
1912 user.inTeam(celebs.bazaar_experts))1829 user.in_bazaar_experts)
19131830
19141831
1915class ViewEntitlement(AuthorizationBase):1832class ViewEntitlement(AuthorizationBase):
@@ -1927,10 +1844,9 @@
1927 Any team member can edit a branch subscription for their team.1844 Any team member can edit a branch subscription for their team.
1928 Launchpad Admins can also edit any branch subscription.1845 Launchpad Admins can also edit any branch subscription.
1929 """1846 """
1930 admins = getUtility(ILaunchpadCelebrities).admin
1931 return (user.inTeam(self.obj.person) or1847 return (user.inTeam(self.obj.person) or
1932 user.inTeam(self.obj.registrant) or1848 user.inTeam(self.obj.registrant) or
1933 user.inTeam(admins))1849 user.in_admin)
19341850
19351851
1936class AdminDistroSeriesLanguagePacks(1852class AdminDistroSeriesLanguagePacks(
@@ -1972,8 +1888,7 @@
1972 if not self.obj.private:1888 if not self.obj.private:
1973 return True1889 return True
19741890
1975 admins = getUtility(ILaunchpadCelebrities).admin1891 return user.inTeam(self.obj.owner) or user.in_admin
1976 return user.inTeam(self.obj.owner) or user.inTeam(admins)
19771892
1978 def checkUnauthenticated(self):1893 def checkUnauthenticated(self):
1979 return not self.obj.private1894 return not self.obj.private
@@ -1991,8 +1906,7 @@
19911906
1992 def checkAuthenticated(self, user):1907 def checkAuthenticated(self, user):
1993 """We give for now access only to Canonical employees."""1908 """We give for now access only to Canonical employees."""
1994 hwdb_team = getUtility(ILaunchpadCelebrities).hwdb_team1909 return user.in_hwdb_team
1995 return user.inTeam(hwdb_team)
19961910
1997 def checkUnauthenticated(self):1911 def checkUnauthenticated(self):
1998 """No access for anonymous users."""1912 """No access for anonymous users."""
@@ -2054,9 +1968,7 @@
2054 return True1968 return True
20551969
2056 # Administrator are allowed to view private archives.1970 # Administrator are allowed to view private archives.
2057 celebrities = getUtility(ILaunchpadCelebrities)1971 if user.in_admin or user.in_commercial_admin:
2058 if (user.inTeam(celebrities.admin)
2059 or user.inTeam(celebrities.commercial_admin)):
2060 return True1972 return True
20611973
2062 # Owners can view the PPA.1974 # Owners can view the PPA.
@@ -2064,7 +1976,7 @@
2064 return True1976 return True
20651977
2066 # Uploaders can view private PPAs.1978 # Uploaders can view private PPAs.
2067 if self.obj.is_ppa and self.obj.canUpload(user):1979 if self.obj.is_ppa and self.obj.canUpload(user.person):
2068 return True1980 return True
20691981
2070 return False1982 return False
@@ -2096,13 +2008,13 @@
2096 if user.inTeam(self.obj.owner):2008 if user.inTeam(self.obj.owner):
2097 return True2009 return True
20982010
2099 if self.obj.is_ppa and self.obj.canUpload(user):2011 if self.obj.is_ppa and self.obj.canUpload(user.person):
2100 return True2012 return True
21012013
2102 celebrities = getUtility(ILaunchpadCelebrities)2014 celebrities = getUtility(ILaunchpadCelebrities)
2103 if (self.obj.is_main and2015 if (self.obj.is_main and
2104 self.obj.distribution == celebrities.ubuntu and2016 self.obj.distribution == celebrities.ubuntu and
2105 user.inTeam(celebrities.ubuntu_security)):2017 user.in_ubuntu_security):
2106 return True2018 return True
21072019
2108 return False2020 return False
@@ -2118,7 +2030,7 @@
2118 usedfor = IArchiveAuthToken2030 usedfor = IArchiveAuthToken
21192031
2120 def checkAuthenticated(self, user):2032 def checkAuthenticated(self, user):
2121 if user == self.obj.person:2033 if user.person == self.obj.person:
2122 return True2034 return True
2123 auth_edit = EditArchiveAuthToken(self.obj)2035 auth_edit = EditArchiveAuthToken(self.obj)
2124 return auth_edit.checkAuthenticated(user)2036 return auth_edit.checkAuthenticated(user)
@@ -2137,8 +2049,7 @@
2137 auth_append = AppendArchive(self.obj.archive)2049 auth_append = AppendArchive(self.obj.archive)
2138 if auth_append.checkAuthenticated(user):2050 if auth_append.checkAuthenticated(user):
2139 return True2051 return True
2140 admins = getUtility(ILaunchpadCelebrities).admin2052 return user.in_admin
2141 return user.inTeam(admins)
21422053
21432054
2144class ViewPersonalArchiveSubscription(AuthorizationBase):2055class ViewPersonalArchiveSubscription(AuthorizationBase):
@@ -2151,15 +2062,14 @@
2151 usedfor = IPersonalArchiveSubscription2062 usedfor = IPersonalArchiveSubscription
21522063
2153 def checkAuthenticated(self, user):2064 def checkAuthenticated(self, user):
2154 if user == self.obj.subscriber:2065 if user.person == self.obj.subscriber:
2155 return True2066 return True
2156 append_archive = AppendArchive(self.obj.archive)2067 append_archive = AppendArchive(self.obj.archive)
21572068
2158 if append_archive.checkAuthenticated(user):2069 if append_archive.checkAuthenticated(user):
2159 return True2070 return True
21602071
2161 admins = getUtility(ILaunchpadCelebrities).admin2072 return user.in_admin
2162 return user.inTeam(admins)
21632073
21642074
2165class ViewArchiveSubscriber(AuthorizationBase):2075class ViewArchiveSubscriber(AuthorizationBase):
@@ -2190,8 +2100,7 @@
2190 auth_append = AppendArchive(self.obj.archive)2100 auth_append = AppendArchive(self.obj.archive)
2191 if auth_append.checkAuthenticated(user):2101 if auth_append.checkAuthenticated(user):
2192 return True2102 return True
2193 admins = getUtility(ILaunchpadCelebrities).admin2103 return user.in_admin
2194 return user.inTeam(admins)
21952104
21962105
2197class ViewSourcePackagePublishingHistory(AuthorizationBase):2106class ViewSourcePackagePublishingHistory(AuthorizationBase):
@@ -2203,8 +2112,7 @@
2203 view_archive = ViewArchive(self.obj.archive)2112 view_archive = ViewArchive(self.obj.archive)
2204 if view_archive.checkAuthenticated(user):2113 if view_archive.checkAuthenticated(user):
2205 return True2114 return True
2206 admins = getUtility(ILaunchpadCelebrities).admin2115 return user.in_admin
2207 return user.inTeam(admins)
22082116
2209 def checkUnauthenticated(self):2117 def checkUnauthenticated(self):
2210 return not self.obj.archive.private2118 return not self.obj.archive.private
@@ -2262,8 +2170,7 @@
2262 usedfor = IMailingListSet2170 usedfor = IMailingListSet
22632171
2264 def checkAuthenticated(self, user):2172 def checkAuthenticated(self, user):
2265 experts = getUtility(ILaunchpadCelebrities).mailing_list_experts2173 return user.in_mailing_list_experts
2266 return user.inTeam(experts)
22672174
22682175
2269class ConfigureTeamMailingList(AuthorizationBase):2176class ConfigureTeamMailingList(AuthorizationBase):
@@ -2284,12 +2191,10 @@
2284 """2191 """
2285 # The team owner, the Launchpad mailing list experts and the Launchpad2192 # The team owner, the Launchpad mailing list experts and the Launchpad
2286 # administrators can all view a team's +mailinglist page.2193 # administrators can all view a team's +mailinglist page.
2287 celebrities = getUtility(ILaunchpadCelebrities)
2288 team = ITeam(self.obj)2194 team = ITeam(self.obj)
2289 return (2195 is_team_owner = (
2290 (team is not None and team in user.getAdministratedTeams()) or2196 team is not None and team in user.person.getAdministratedTeams())
2291 user.inTeam(celebrities.admin) or2197 return is_team_owner or user.in_admin or user.in_mailing_list_experts
2292 user.inTeam(celebrities.mailing_list_experts))
22932198
22942199
2295class ViewEmailAddress(AuthorizationBase):2200class ViewEmailAddress(AuthorizationBase):
@@ -2319,15 +2224,14 @@
2319 self.obj.person.hide_email_addresses):2224 self.obj.person.hide_email_addresses):
2320 return True2225 return True
23212226
2322 user = IPerson(account, None)2227 user = IPersonRoles(IPerson(account, None), None)
2323 if user is None:2228 if user is None:
2324 return False2229 return False
23252230
2326 celebrities = getUtility(ILaunchpadCelebrities)
2327 return (self.obj.person is not None and user.inTeam(self.obj.person)2231 return (self.obj.person is not None and user.inTeam(self.obj.person)
2328 or user.inTeam(celebrities.commercial_admin)2232 or user.in_commercial_admin
2329 or user.inTeam(celebrities.registry_experts)2233 or user.in_registry_experts
2330 or user.inTeam(celebrities.admin))2234 or user.in_admin)
23312235
23322236
2333class EditEmailAddress(EditByOwnersOrAdmins):2237class EditEmailAddress(EditByOwnersOrAdmins):
@@ -2348,10 +2252,7 @@
23482252
2349 def checkAuthenticated(self, user):2253 def checkAuthenticated(self, user):
2350 """Users must be an admin or a member of the tech board."""2254 """Users must be an admin or a member of the tech board."""
2351 celebrities = getUtility(ILaunchpadCelebrities)2255 return user.in_admin or user.in_ubuntu_techboard
2352 return (
2353 user.inTeam(celebrities.admin)
2354 or user.inTeam(celebrities.ubuntu_techboard))
23552256
23562257
2357class LinkOfficialSourcePackageBranches(AuthorizationBase):2258class LinkOfficialSourcePackageBranches(AuthorizationBase):
@@ -2367,10 +2268,7 @@
2367 return False2268 return False
23682269
2369 def checkAuthenticated(self, user):2270 def checkAuthenticated(self, user):
2370 celebrities = getUtility(ILaunchpadCelebrities)2271 return user.in_ubuntu_branches or user.in_admin
2371 return (
2372 user.inTeam(celebrities.ubuntu_branches)
2373 or user.inTeam(celebrities.admin))
23742272
23752273
2376class ChangeOfficialSourcePackageBranchLinks(AuthorizationBase):2274class ChangeOfficialSourcePackageBranchLinks(AuthorizationBase):
@@ -2386,10 +2284,7 @@
2386 return False2284 return False
23872285
2388 def checkAuthenticated(self, user):2286 def checkAuthenticated(self, user):
2389 celebrities = getUtility(ILaunchpadCelebrities)2287 return user.in_ubuntu_branches or user.in_admin
2390 return (
2391 user.inTeam(celebrities.ubuntu_branches)
2392 or user.inTeam(celebrities.admin))
23932288
23942289
2395class EditPackageset(AuthorizationBase):2290class EditPackageset(AuthorizationBase):
@@ -2398,10 +2293,7 @@
23982293
2399 def checkAuthenticated(self, user):2294 def checkAuthenticated(self, user):
2400 """The owner of a package set can edit the object."""2295 """The owner of a package set can edit the object."""
2401 celebrities = getUtility(ILaunchpadCelebrities)2296 return user.isOwner(self.obj) or user.in_admin
2402 return (
2403 user.inTeam(self.obj.owner)
2404 or user.inTeam(celebrities.admin))
24052297
24062298
2407class EditPackagesetSet(AuthorizationBase):2299class EditPackagesetSet(AuthorizationBase):
@@ -2410,7 +2302,4 @@
24102302
2411 def checkAuthenticated(self, user):2303 def checkAuthenticated(self, user):
2412 """Users must be an admin or a member of the tech board."""2304 """Users must be an admin or a member of the tech board."""
2413 celebrities = getUtility(ILaunchpadCelebrities)2305 return user.in_admin or user.in_ubuntu_techboard
2414 return (
2415 user.inTeam(celebrities.admin)
2416 or user.inTeam(celebrities.ubuntu_techboard))
24172306
=== modified file 'lib/canonical/launchpad/tests/test_personroles.py'
--- lib/canonical/launchpad/tests/test_personroles.py 2010-01-08 16:16:50 +0000
+++ lib/canonical/launchpad/tests/test_personroles.py 2010-01-15 07:14:13 +0000
@@ -103,14 +103,20 @@
103 roles = IPersonRoles(self.person)103 roles = IPersonRoles(self.person)
104 self.assertTrue(roles.isDriver(sprint))104 self.assertTrue(roles.isDriver(sprint))
105105
106 def test_isDriver_multiple_drivers(self):106 def test_isOneOfDrivers(self):
107 # The person can be one of multiple drivers of if a product and its107 # The person can be one of multiple drivers of if an object
108 # series each has a driver.108 # implements IHasDrivers.
109 productseries = self.factory.makeProductSeries()109 productseries = self.factory.makeProductSeries()
110 productseries.product.driver = self.person110 productseries.product.driver = self.person
111 productseries.driver = self.factory.makePerson()111 productseries.driver = self.factory.makePerson()
112 roles = IPersonRoles(self.person)112 roles = IPersonRoles(self.person)
113 self.assertTrue(roles.isDriver(productseries))113 self.assertTrue(roles.isOneOfDrivers(productseries))
114
115 def test_isOneOfDrivers_no_drivers(self):
116 # If the object does not implement IHasDrivers, False is returned.
117 sprint = self.factory.makeSprint()
118 roles = IPersonRoles(self.person)
119 self.assertFalse(roles.isOneOfDrivers(sprint))
114120
115 def test_isOneOf(self):121 def test_isOneOf(self):
116 # Objects may have multiple roles that a person can fulfill.122 # Objects may have multiple roles that a person can fulfill.
117123
=== modified file 'lib/canonical/launchpad/utilities/personroles.py'
--- lib/canonical/launchpad/utilities/personroles.py 2010-01-06 14:00:20 +0000
+++ lib/canonical/launchpad/utilities/personroles.py 2010-01-15 07:14:13 +0000
@@ -9,7 +9,7 @@
9from zope.interface import implements9from zope.interface import implements
10from zope.component import adapts, getUtility10from zope.component import adapts, getUtility
11from canonical.launchpad.interfaces import (11from canonical.launchpad.interfaces import (
12 ILaunchpadCelebrities, IPersonRoles)12 IHasDrivers, ILaunchpadCelebrities, IPersonRoles)
1313
14from lp.registry.interfaces.person import IPerson14from lp.registry.interfaces.person import IPerson
1515
@@ -26,10 +26,14 @@
26 def __getattr__(self, name):26 def __getattr__(self, name):
27 """Handle all in_* attributes."""27 """Handle all in_* attributes."""
28 prefix = 'in_'28 prefix = 'in_'
29 errortext = "'PersonRoles' object has no attribute '%s'" % name
29 if not name.startswith(prefix):30 if not name.startswith(prefix):
30 raise AttributeError31 raise AttributeError(errortext)
31 attribute = name[len(prefix):]32 attribute = name[len(prefix):]
32 return self.person.inTeam(getattr(self._celebrities, attribute))33 try:
34 return self.person.inTeam(getattr(self._celebrities, attribute))
35 except AttributeError:
36 raise AttributeError(errortext)
3337
34 def isOwner(self, obj):38 def isOwner(self, obj):
35 """See IPersonRoles."""39 """See IPersonRoles."""
@@ -37,10 +41,13 @@
3741
38 def isDriver(self, obj):42 def isDriver(self, obj):
39 """See IPersonRoles."""43 """See IPersonRoles."""
40 drivers = getattr(obj, 'drivers', None)44 return self.person.inTeam(obj.driver)
41 if drivers is None:45
42 return self.person.inTeam(obj.driver)46 def isOneOfDrivers(self, obj):
43 for driver in drivers:47 """See IPersonRoles."""
48 if not IHasDrivers.providedBy(obj):
49 return self.isDriver(obj)
50 for driver in obj.drivers:
44 if self.person.inTeam(driver):51 if self.person.inTeam(driver):
45 return True52 return True
46 return False53 return False
4754
=== modified file 'lib/lp/code/doc/branch-visibility.txt'
--- lib/lp/code/doc/branch-visibility.txt 2009-08-13 15:12:16 +0000
+++ lib/lp/code/doc/branch-visibility.txt 2010-01-15 07:14:13 +0000
@@ -66,7 +66,7 @@
66 >>> access = AccessBranch(branch)66 >>> access = AccessBranch(branch)
67 >>> access.checkUnauthenticated()67 >>> access.checkUnauthenticated()
68 True68 True
69 >>> access.checkAuthenticated(no_priv_person)69 >>> access.checkAccountAuthenticated(no_priv_person.account)
70 True70 True
7171
72Branches that are private are accessible by the owner and subscribers.72Branches that are private are accessible by the owner and subscribers.
@@ -83,7 +83,7 @@
83 False83 False
84 >>> branch.owner == no_priv_person84 >>> branch.owner == no_priv_person
85 True85 True
86 >>> access.checkAuthenticated(no_priv_person)86 >>> access.checkAccountAuthenticated(no_priv_person.account)
87 True87 True
8888
89Check the configuration of the AccessBranch authorization.89Check the configuration of the AccessBranch authorization.
@@ -108,7 +108,7 @@
108 >>> lp_admins = getUtility(ILaunchpadCelebrities).admin108 >>> lp_admins = getUtility(ILaunchpadCelebrities).admin
109 >>> mark.inTeam(lp_admins)109 >>> mark.inTeam(lp_admins)
110 True110 True
111 >>> access.checkAuthenticated(mark)111 >>> access.checkAccountAuthenticated(mark.account)
112 True112 True
113113
114114
@@ -125,7 +125,7 @@
125 True125 True
126 >>> jdub.inTeam(lp_admins)126 >>> jdub.inTeam(lp_admins)
127 False127 False
128 >>> access.checkAuthenticated(jdub)128 >>> access.checkAccountAuthenticated(jdub.account)
129 False129 False
130130
131Subscribing the Ubuntu team to the branch will allow Jeff to have access131Subscribing the Ubuntu team to the branch will allow Jeff to have access
@@ -141,7 +141,7 @@
141 ... CodeReviewNotificationLevel.NOEMAIL)141 ... CodeReviewNotificationLevel.NOEMAIL)
142 <BranchSubscription ...>142 <BranchSubscription ...>
143143
144 >>> access.checkAuthenticated(jdub)144 >>> access.checkAccountAuthenticated(jdub.account)
145 True145 True
146146
147147
@@ -153,7 +153,7 @@
153 >>> ddaa = person_set.getByName('ddaa')153 >>> ddaa = person_set.getByName('ddaa')
154 >>> ddaa.inTeam(lp_admins)154 >>> ddaa.inTeam(lp_admins)
155 False155 False
156 >>> access.checkAuthenticated(ddaa)156 >>> access.checkAccountAuthenticated(ddaa.account)
157 False157 False
158158
159159