Merge lp:~henninge/launchpad/bug-503454-security-py into lp:launchpad
- bug-503454-security-py
- Merge into devel
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 |
Related bugs: |
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.
Description of the change
Henning Eggers (henninge) wrote : | # |
Henning Eggers (henninge) wrote : | # |
Found room for a little more improvement. I'd better stop now, though. ;-)
Edwin Grubbs (edwin-grubbs) wrote : | # |
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.
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/
>--- lib/canonical/
>+++ lib/canonical/
>@@ -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 ILaunchpadCeleb
>+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.
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.
>+ >>> person = factory.
>+ >>> print IPersonRoles(
>+ <canonical.
>+
>+The original Person object can be reached through the person attribute.
>+
>+ >>> roles = IPersonRoles(
>+ >>> print roles.person is person
>+ True
>+
>+
>+== Celebrity persons ==
>+
>+There are a number of celebrity persons defined in ILaunchpadCeleb
>+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.
>+ ... ILaunchpadCeleb
>+ >>> rosetta_experts = getUtility(
>+ >>> print person.
>+ False
>+
>+ >>> print roles.in_
>+ False
>+
>+The tes...
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.
> 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
1 | === modified file 'lib/canonical/launchpad/doc/personroles.txt' | |||
2 | --- lib/canonical/launchpad/doc/personroles.txt 2010-01-12 17:07:32 +0000 | |||
3 | +++ lib/canonical/launchpad/doc/personroles.txt 2010-01-14 11:19:29 +0000 | |||
4 | @@ -1,6 +1,6 @@ | |||
5 | 1 | = PersonRoles = | 1 | = PersonRoles = |
6 | 2 | 2 | ||
8 | 3 | To make the checking for certain roles that a person can have more convenient | 3 | To make it more convenient to check which roles a person has, |
9 | 4 | the IPersonRoles adapter is provided. It's main use is to easily check if a | 4 | the IPersonRoles adapter is provided. It's main use is to easily check if a |
10 | 5 | person is the member of a celebrity team or is a celebrity person. In | 5 | person is the member of a celebrity team or is a celebrity person. In |
11 | 6 | addition, methods for common checks are provided, too. | 6 | addition, methods for common checks are provided, too. |
12 | @@ -8,14 +8,13 @@ | |||
13 | 8 | The IPersonRoles interface is closely tight to the ILaunchpadCelebrities | 8 | The IPersonRoles interface is closely tight to the ILaunchpadCelebrities |
14 | 9 | interface. Any addition or removal of a person celebrity must be reflected in | 9 | interface. Any addition or removal of a person celebrity must be reflected in |
15 | 10 | adding or removing the corresponding property in IPersonRoles. Luckily the | 10 | adding or removing the corresponding property in IPersonRoles. Luckily the |
18 | 11 | celbrities.txt doctest includes a check for this and will give a useful | 11 | celebrities.txt doctest includes a check for this and will give useful |
19 | 12 | information of which attribute needs to be added or removed. Both interfaces | 12 | information on which attribute needs to be added or removed. Both interfaces |
20 | 13 | are found in the same file. There is no need to adapt the implementation | 13 | are found in the same file. There is no need to adapt the implementation |
21 | 14 | class PersonRoles, though (thanks to __getattr__). | 14 | class PersonRoles, though (thanks to __getattr__). |
22 | 15 | 15 | ||
23 | 16 | PersonRoles is most prominent in AuthenticationBase in security.py. The user | 16 | PersonRoles is most prominent in AuthenticationBase in security.py. The user |
26 | 17 | parameter to checkAuthenticated is a PersonRoles object (used to be a Person | 17 | parameter to checkAuthenticated is a PersonRoles object (was a Person object). |
25 | 18 | object). | ||
27 | 19 | 18 | ||
28 | 20 | 19 | ||
29 | 21 | == The person object and the adapter == | 20 | == The person object and the adapter == |
30 | @@ -60,8 +59,8 @@ | |||
31 | 60 | True | 59 | True |
32 | 61 | 60 | ||
33 | 62 | To stay consistent, all attributes are prefixed with "in_" although the | 61 | To stay consistent, all attributes are prefixed with "in_" although the |
36 | 63 | attributes names of ILaunchpadCelebrities are not all lexically correct | 62 | attribute names of ILaunchpadCelebrities are not all lexically correct |
37 | 64 | plurals nor are all the attributes teams. This makes for odd sounding | 63 | plurals, nor are all the attributes teams. This makes for odd sounding |
38 | 65 | attribute names in IPersonRoles. | 64 | attribute names in IPersonRoles. |
39 | 66 | 65 | ||
40 | 67 | >>> print roles.in_admin | 66 | >>> print roles.in_admin |
41 | 68 | 67 | ||
42 | === modified file 'lib/canonical/launchpad/security.py' | |||
43 | --- lib/canonical/launchpad/security.py 2010-01-12 17:42:43 +0000 | |||
44 | +++ lib/canonical/launchpad/security.py 2010-01-14 11:21:36 +0000 | |||
45 | @@ -2215,11 +2215,10 @@ | |||
46 | 2215 | self.obj.person.hide_email_addresses): | 2215 | self.obj.person.hide_email_addresses): |
47 | 2216 | return True | 2216 | return True |
48 | 2217 | 2217 | ||
51 | 2218 | person = IPerson(account, None) | 2218 | user = IPersonRoles(IPerson(account, None), None) |
52 | 2219 | if person is None: | 2219 | if user is None: |
53 | 2220 | return False | 2220 | return False |
54 | 2221 | 2221 | ||
55 | 2222 | user = IPersonRoles(person) | ||
56 | 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) |
57 | 2224 | or user.in_commercial_admin | 2223 | or user.in_commercial_admin |
58 | 2225 | or user.in_registry_experts | 2224 | or user.in_registry_experts |
59 | 2226 | 2225 | ||
60 | === modified file 'lib/canonical/launchpad/utilities/personroles.py' | |||
61 | --- lib/canonical/launchpad/utilities/personroles.py 2010-01-12 14:52:41 +0000 | |||
62 | +++ lib/canonical/launchpad/utilities/personroles.py 2010-01-14 11:10:40 +0000 | |||
63 | @@ -26,10 +26,14 @@ | |||
64 | 26 | def __getattr__(self, name): | 26 | def __getattr__(self, name): |
65 | 27 | """Handle all in_* attributes.""" | 27 | """Handle all in_* attributes.""" |
66 | 28 | prefix = 'in_' | 28 | prefix = 'in_' |
67 | 29 | errortext = "'PersonRoles' object has no attribute '%s'" % name | ||
68 | 29 | if not name.startswith(prefix): | 30 | if not name.startswith(prefix): |
70 | 30 | raise AttributeError | 31 | raise AttributeError(errortext) |
71 | 31 | attribute = name[len(prefix):] | 32 | attribute = name[len(prefix):] |
73 | 32 | return self.person.inTeam(getattr(self._celebrities, attribute)) | 33 | try: |
74 | 34 | return self.person.inTeam(getattr(self._celebrities, attribute)) | ||
75 | 35 | except AttributeError: | ||
76 | 36 | raise AttributeError(errortext) | ||
77 | 33 | 37 | ||
78 | 34 | def isOwner(self, obj): | 38 | def isOwner(self, obj): |
79 | 35 | """See IPersonRoles.""" | 39 | """See IPersonRoles.""" |
Preview Diff
1 | === modified file 'lib/canonical/launchpad/doc/hasowner-authorization.txt' | |||
2 | --- lib/canonical/launchpad/doc/hasowner-authorization.txt 2009-08-13 15:12:16 +0000 | |||
3 | +++ lib/canonical/launchpad/doc/hasowner-authorization.txt 2010-01-15 07:14:13 +0000 | |||
4 | @@ -18,23 +18,23 @@ | |||
5 | 18 | >>> from canonical.launchpad.webapp.interfaces import IAuthorization | 18 | >>> from canonical.launchpad.webapp.interfaces import IAuthorization |
6 | 19 | >>> from zope.component import queryAdapter | 19 | >>> from zope.component import queryAdapter |
7 | 20 | >>> authorization = queryAdapter(foo, IAuthorization, 'launchpad.Edit') | 20 | >>> authorization = queryAdapter(foo, IAuthorization, 'launchpad.Edit') |
9 | 21 | >>> authorization.checkAuthenticated(salgado) | 21 | >>> print authorization.checkAccountAuthenticated(salgado.account) |
10 | 22 | True | 22 | True |
11 | 23 | 23 | ||
12 | 24 | So can a member of the Launchpad admins team. | 24 | So can a member of the Launchpad admins team. |
13 | 25 | 25 | ||
14 | 26 | >>> mark = getUtility(IPersonSet).getByName('mark') | 26 | >>> mark = getUtility(IPersonSet).getByName('mark') |
15 | 27 | >>> admins = getUtility(IPersonSet).getByName('admins') | 27 | >>> admins = getUtility(IPersonSet).getByName('admins') |
17 | 28 | >>> mark.inTeam(admins) | 28 | >>> print mark.inTeam(admins) |
18 | 29 | True | 29 | True |
20 | 30 | >>> authorization.checkAuthenticated(mark) | 30 | >>> print authorization.checkAccountAuthenticated(mark.account) |
21 | 31 | True | 31 | True |
22 | 32 | 32 | ||
23 | 33 | But someone who's not salgado nor a member of the admins team won't be | 33 | But someone who's not salgado nor a member of the admins team won't be |
24 | 34 | able to. | 34 | able to. |
25 | 35 | 35 | ||
26 | 36 | >>> sample_person = getUtility(IPersonSet).getByName('name12') | 36 | >>> sample_person = getUtility(IPersonSet).getByName('name12') |
28 | 37 | >>> sample_person.inTeam(admins) | 37 | >>> print sample_person.inTeam(admins) |
29 | 38 | False | 38 | False |
31 | 39 | >>> authorization.checkAuthenticated(sample_person) | 39 | >>> print authorization.checkAccountAuthenticated(sample_person) |
32 | 40 | False | 40 | False |
33 | 41 | 41 | ||
34 | === added file 'lib/canonical/launchpad/doc/personroles.txt' | |||
35 | --- lib/canonical/launchpad/doc/personroles.txt 1970-01-01 00:00:00 +0000 | |||
36 | +++ lib/canonical/launchpad/doc/personroles.txt 2010-01-15 07:14:13 +0000 | |||
37 | @@ -0,0 +1,130 @@ | |||
38 | 1 | = PersonRoles = | ||
39 | 2 | |||
40 | 3 | To make it more convenient to check which roles a person has, | ||
41 | 4 | the IPersonRoles adapter is provided. It's main use is to easily check if a | ||
42 | 5 | person is the member of a celebrity team or is a celebrity person. In | ||
43 | 6 | addition, methods for common checks are provided, too. | ||
44 | 7 | |||
45 | 8 | The IPersonRoles interface is closely tight to the ILaunchpadCelebrities | ||
46 | 9 | interface. Any addition or removal of a person celebrity must be reflected in | ||
47 | 10 | adding or removing the corresponding property in IPersonRoles. Luckily the | ||
48 | 11 | celebrities.txt doctest includes a check for this and will give useful | ||
49 | 12 | information on which attribute needs to be added or removed. Both interfaces | ||
50 | 13 | are found in the same file. There is no need to adapt the implementation | ||
51 | 14 | class PersonRoles, though (thanks to __getattr__). | ||
52 | 15 | |||
53 | 16 | PersonRoles is most prominent in AuthenticationBase in security.py. The user | ||
54 | 17 | parameter to checkAuthenticated is a PersonRoles object (was a Person object). | ||
55 | 18 | |||
56 | 19 | |||
57 | 20 | == The person object and the adapter == | ||
58 | 21 | |||
59 | 22 | PersonRoles is registered as an unnamed adapter for IPersonRoles. | ||
60 | 23 | |||
61 | 24 | >>> from canonical.launchpad.interfaces.launchpad import IPersonRoles | ||
62 | 25 | >>> person = factory.makePerson() | ||
63 | 26 | >>> print IPersonRoles(person) | ||
64 | 27 | <canonical.launchpad.utilities.personroles.PersonRoles object at ...> | ||
65 | 28 | |||
66 | 29 | The original Person object can be reached through the person attribute. | ||
67 | 30 | |||
68 | 31 | >>> roles = IPersonRoles(person) | ||
69 | 32 | >>> print roles.person is person | ||
70 | 33 | True | ||
71 | 34 | |||
72 | 35 | |||
73 | 36 | == Celebrity persons == | ||
74 | 37 | |||
75 | 38 | There are a number of celebrity persons defined in ILaunchpadCelebrities. | ||
76 | 39 | PersonRoles has a corresponding attribute of the same name prefixed with | ||
77 | 40 | "in_" to check if the person in question is a member of this celebrity or is | ||
78 | 41 | this celebrity. The following tests are identical. | ||
79 | 42 | |||
80 | 43 | >>> from canonical.launchpad.interfaces.launchpad import ( | ||
81 | 44 | ... ILaunchpadCelebrities) | ||
82 | 45 | >>> rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts | ||
83 | 46 | >>> print person.inTeam(rosetta_experts) | ||
84 | 47 | False | ||
85 | 48 | |||
86 | 49 | >>> print roles.in_rosetta_experts | ||
87 | 50 | False | ||
88 | 51 | |||
89 | 52 | The test will succeed once we make person a member of the team. Need to be an | ||
90 | 53 | admin to do that. | ||
91 | 54 | |||
92 | 55 | >>> login("foo.bar@canonical.com") | ||
93 | 56 | >>> rosetta_experts.addMember(person, rosetta_experts.teamowner) | ||
94 | 57 | (True, ...Approved>) | ||
95 | 58 | >>> print roles.in_rosetta_experts | ||
96 | 59 | True | ||
97 | 60 | |||
98 | 61 | To stay consistent, all attributes are prefixed with "in_" although the | ||
99 | 62 | attribute names of ILaunchpadCelebrities are not all lexically correct | ||
100 | 63 | plurals, nor are all the attributes teams. This makes for odd sounding | ||
101 | 64 | attribute names in IPersonRoles. | ||
102 | 65 | |||
103 | 66 | >>> print roles.in_admin | ||
104 | 67 | False | ||
105 | 68 | >>> print roles.in_janitor | ||
106 | 69 | False | ||
107 | 70 | |||
108 | 71 | >>> janitor = getUtility(ILaunchpadCelebrities).janitor | ||
109 | 72 | >>> janitor_roles = IPersonRoles(janitor) | ||
110 | 73 | >>> print janitor_roles.in_janitor | ||
111 | 74 | True | ||
112 | 75 | |||
113 | 76 | |||
114 | 77 | == inTeam == | ||
115 | 78 | |||
116 | 79 | The Person.inTeam method is available directly through PersonRoles. This can | ||
117 | 80 | be used to check for any non-celebrity team. | ||
118 | 81 | |||
119 | 82 | >>> new_team = factory.makeTeam() | ||
120 | 83 | >>> new_team.addMember(person, new_team.teamowner) | ||
121 | 84 | (True, ...Approved>) | ||
122 | 85 | >>> print person.inTeam(new_team) | ||
123 | 86 | True | ||
124 | 87 | |||
125 | 88 | >>> print roles.inTeam(new_team) | ||
126 | 89 | True | ||
127 | 90 | |||
128 | 91 | |||
129 | 92 | == isOwner, isDriver == | ||
130 | 93 | |||
131 | 94 | We can easily check for ownership and drivership. This is admittedly not much | ||
132 | 95 | shorter than calling inTeam but clearer to read. | ||
133 | 96 | |||
134 | 97 | >>> product = factory.makeProduct(owner=person) | ||
135 | 98 | >>> print roles.isOwner(product) | ||
136 | 99 | True | ||
137 | 100 | |||
138 | 101 | >>> print roles.isDriver(product) | ||
139 | 102 | False | ||
140 | 103 | >>> product.driver = person | ||
141 | 104 | >>> print roles.isDriver(product) | ||
142 | 105 | True | ||
143 | 106 | |||
144 | 107 | |||
145 | 108 | == isOneOfDrivers == | ||
146 | 109 | |||
147 | 110 | If an object implements IHasDrivers it lists all drivers of the object and | ||
148 | 111 | possible parent objects. The method isOneOfDrivers lets us check for those. | ||
149 | 112 | |||
150 | 113 | >>> productseries = factory.makeProductSeries(product=product) | ||
151 | 114 | >>> print roles.isDriver(productseries) | ||
152 | 115 | False | ||
153 | 116 | >>> print roles.isOneOfDrivers(productseries) | ||
154 | 117 | True | ||
155 | 118 | |||
156 | 119 | |||
157 | 120 | == isOneOf == | ||
158 | 121 | |||
159 | 122 | Finally, sometimes a person may be one of multiple roles for an object. The | ||
160 | 123 | method isOneOf makes checking all of these a breeze. | ||
161 | 124 | |||
162 | 125 | >>> spec = factory.makeSpecification() | ||
163 | 126 | >>> spec.assignee = person | ||
164 | 127 | >>> print roles.isOwner(spec) | ||
165 | 128 | False | ||
166 | 129 | >>> print roles.isOneOf(spec, ['owner', 'approver', 'assignee']) | ||
167 | 130 | True | ||
168 | 0 | 131 | ||
169 | === modified file 'lib/canonical/launchpad/interfaces/launchpad.py' | |||
170 | --- lib/canonical/launchpad/interfaces/launchpad.py 2010-01-12 15:39:36 +0000 | |||
171 | +++ lib/canonical/launchpad/interfaces/launchpad.py 2010-01-15 07:14:13 +0000 | |||
172 | @@ -223,7 +223,14 @@ | |||
173 | 223 | """Is this person the owner of the object?""" | 223 | """Is this person the owner of the object?""" |
174 | 224 | 224 | ||
175 | 225 | def isDriver(obj): | 225 | def isDriver(obj): |
177 | 226 | """Is this person one of the drivers of the object?""" | 226 | """Is this person the driver of the object?""" |
178 | 227 | |||
179 | 228 | def isOneOfDrivers(obj): | ||
180 | 229 | """Is this person on of the drivers of the object? | ||
181 | 230 | |||
182 | 231 | Works on objects that implement 'IHasDrivers' but will default to | ||
183 | 232 | isDriver if it doesn't, i.e. check the driver attribute. | ||
184 | 233 | """ | ||
185 | 227 | 234 | ||
186 | 228 | def isOneOf(obj, attributes): | 235 | def isOneOf(obj, attributes): |
187 | 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? |
188 | 230 | 237 | ||
189 | === modified file 'lib/canonical/launchpad/security.py' | |||
190 | --- lib/canonical/launchpad/security.py 2010-01-13 06:50:43 +0000 | |||
191 | +++ lib/canonical/launchpad/security.py 2010-01-15 07:14:13 +0000 | |||
192 | @@ -154,7 +154,7 @@ | |||
193 | 154 | if person is None: | 154 | if person is None: |
194 | 155 | return self.checkUnauthenticated() | 155 | return self.checkUnauthenticated() |
195 | 156 | else: | 156 | else: |
197 | 157 | return self.checkAuthenticated(person) | 157 | return self.checkAuthenticated(IPersonRoles(person)) |
198 | 158 | 158 | ||
199 | 159 | 159 | ||
200 | 160 | class ViewByLoggedInUser(AuthorizationBase): | 160 | class ViewByLoggedInUser(AuthorizationBase): |
201 | @@ -176,8 +176,7 @@ | |||
202 | 176 | usedfor = Interface | 176 | usedfor = Interface |
203 | 177 | 177 | ||
204 | 178 | def checkAuthenticated(self, user): | 178 | def checkAuthenticated(self, user): |
207 | 179 | admins = getUtility(ILaunchpadCelebrities).admin | 179 | return user.in_admin |
206 | 180 | return user.inTeam(admins) | ||
208 | 181 | 180 | ||
209 | 182 | 181 | ||
210 | 183 | class AdminByCommercialTeamOrAdmins(AuthorizationBase): | 182 | class AdminByCommercialTeamOrAdmins(AuthorizationBase): |
211 | @@ -185,9 +184,7 @@ | |||
212 | 185 | usedfor = Interface | 184 | usedfor = Interface |
213 | 186 | 185 | ||
214 | 187 | def checkAuthenticated(self, user): | 186 | def checkAuthenticated(self, user): |
218 | 188 | celebrities = getUtility(ILaunchpadCelebrities) | 187 | return user.in_commercial_admin or user.in_admin |
216 | 189 | return (user.inTeam(celebrities.commercial_admin) | ||
217 | 190 | or user.inTeam(celebrities.admin)) | ||
219 | 191 | 188 | ||
220 | 192 | 189 | ||
221 | 193 | class EditByRegistryExpertsOrAdmins(AuthorizationBase): | 190 | class EditByRegistryExpertsOrAdmins(AuthorizationBase): |
222 | @@ -195,7 +192,6 @@ | |||
223 | 195 | usedfor = ILaunchpadRoot | 192 | usedfor = ILaunchpadRoot |
224 | 196 | 193 | ||
225 | 197 | def checkAuthenticated(self, user): | 194 | def checkAuthenticated(self, user): |
226 | 198 | user = IPersonRoles(user) | ||
227 | 199 | return user.in_admin or user.in_registry_experts | 195 | return user.in_admin or user.in_registry_experts |
228 | 200 | 196 | ||
229 | 201 | 197 | ||
230 | @@ -204,7 +200,6 @@ | |||
231 | 204 | usedfor = None | 200 | usedfor = None |
232 | 205 | 201 | ||
233 | 206 | def checkAuthenticated(self, user): | 202 | def checkAuthenticated(self, user): |
234 | 207 | user = IPersonRoles(user) | ||
235 | 208 | return user.in_admin or user.in_registry_experts | 203 | return user.in_admin or user.in_registry_experts |
236 | 209 | 204 | ||
237 | 210 | 205 | ||
238 | @@ -241,7 +236,6 @@ | |||
239 | 241 | if self.obj.active: | 236 | if self.obj.active: |
240 | 242 | return True | 237 | return True |
241 | 243 | else: | 238 | else: |
242 | 244 | user = IPersonRoles(user) | ||
243 | 245 | return (user.in_commercial_admin or | 239 | return (user.in_commercial_admin or |
244 | 246 | user.in_admin or | 240 | user.in_admin or |
245 | 247 | user.in_registry_experts) | 241 | user.in_registry_experts) |
246 | @@ -258,7 +252,6 @@ | |||
247 | 258 | EditAccountBySelfOrAdmin, self).checkAccountAuthenticated(account) | 252 | EditAccountBySelfOrAdmin, self).checkAccountAuthenticated(account) |
248 | 259 | 253 | ||
249 | 260 | def checkAuthenticated(self, user): | 254 | def checkAuthenticated(self, user): |
250 | 261 | user = IPersonRoles(user) | ||
251 | 262 | return user.in_admin | 255 | return user.in_admin |
252 | 263 | 256 | ||
253 | 264 | 257 | ||
254 | @@ -271,7 +264,6 @@ | |||
255 | 271 | 264 | ||
256 | 272 | def checkAuthenticated(self, user): | 265 | def checkAuthenticated(self, user): |
257 | 273 | """Extend permission to registry experts.""" | 266 | """Extend permission to registry experts.""" |
258 | 274 | user = IPersonRoles(user) | ||
259 | 275 | return user.in_admin or user.in_registry_experts | 267 | return user.in_admin or user.in_registry_experts |
260 | 276 | 268 | ||
261 | 277 | 269 | ||
262 | @@ -280,7 +272,6 @@ | |||
263 | 280 | permission = 'launchpad.Moderate' | 272 | permission = 'launchpad.Moderate' |
264 | 281 | 273 | ||
265 | 282 | def checkAuthenticated(self, user): | 274 | def checkAuthenticated(self, user): |
266 | 283 | user = IPersonRoles(user) | ||
267 | 284 | return user.in_admin or user.in_registry_experts | 275 | return user.in_admin or user.in_registry_experts |
268 | 285 | 276 | ||
269 | 286 | 277 | ||
270 | @@ -289,8 +280,7 @@ | |||
271 | 289 | usedfor = IOAuthAccessToken | 280 | usedfor = IOAuthAccessToken |
272 | 290 | 281 | ||
273 | 291 | def checkAuthenticated(self, user): | 282 | def checkAuthenticated(self, user): |
276 | 292 | return (self.obj.person == user | 283 | return self.obj.person == user or user.in_admin |
275 | 293 | or user.inTeam(getUtility(ILaunchpadCelebrities).admin)) | ||
277 | 294 | 284 | ||
278 | 295 | 285 | ||
279 | 296 | class EditOAuthRequestToken(EditOAuthAccessToken): | 286 | class EditOAuthRequestToken(EditOAuthAccessToken): |
280 | @@ -303,7 +293,7 @@ | |||
281 | 303 | usedfor = IBugNomination | 293 | usedfor = IBugNomination |
282 | 304 | 294 | ||
283 | 305 | def checkAuthenticated(self, user): | 295 | def checkAuthenticated(self, user): |
285 | 306 | return self.obj.canApprove(user) | 296 | return self.obj.canApprove(user.person) |
286 | 307 | 297 | ||
287 | 308 | 298 | ||
288 | 309 | class EditByOwnersOrAdmins(AuthorizationBase): | 299 | class EditByOwnersOrAdmins(AuthorizationBase): |
289 | @@ -311,8 +301,7 @@ | |||
290 | 311 | usedfor = IHasOwner | 301 | usedfor = IHasOwner |
291 | 312 | 302 | ||
292 | 313 | def checkAuthenticated(self, user): | 303 | def checkAuthenticated(self, user): |
295 | 314 | return (user.inTeam(self.obj.owner) | 304 | return user.isOwner(self.obj) or user.in_admin |
294 | 315 | or user.inTeam(getUtility(ILaunchpadCelebrities).admin)) | ||
296 | 316 | 305 | ||
297 | 317 | 306 | ||
298 | 318 | class EditProduct(EditByOwnersOrAdmins): | 307 | class EditProduct(EditByOwnersOrAdmins): |
299 | @@ -338,9 +327,8 @@ | |||
300 | 338 | usedfor = IDistributionMirror | 327 | usedfor = IDistributionMirror |
301 | 339 | 328 | ||
302 | 340 | def checkAuthenticated(self, user): | 329 | def checkAuthenticated(self, user): |
306 | 341 | admins = getUtility(ILaunchpadCelebrities).admin | 330 | return (user.isOwner(self.obj.distribution) or |
307 | 342 | return (user.inTeam(self.obj.distribution.owner) or | 331 | user.in_admin or |
305 | 343 | user.inTeam(admins) or | ||
308 | 344 | user.inTeam(self.obj.distribution.mirror_admin)) | 332 | user.inTeam(self.obj.distribution.mirror_admin)) |
309 | 345 | 333 | ||
310 | 346 | 334 | ||
311 | @@ -350,9 +338,8 @@ | |||
312 | 350 | usedfor = IDistributionMirror | 338 | usedfor = IDistributionMirror |
313 | 351 | 339 | ||
314 | 352 | def checkAuthenticated(self, user): | 340 | def checkAuthenticated(self, user): |
318 | 353 | admins = getUtility(ILaunchpadCelebrities).admin | 341 | return (user.isOwner(self.obj) or user.in_admin or |
319 | 354 | return (user.inTeam(self.obj.owner) or user.inTeam(admins) or | 342 | user.isOwner(self.obj.distribution) or |
317 | 355 | user.inTeam(self.obj.distribution.owner) or | ||
320 | 356 | user.inTeam(self.obj.distribution.mirror_admin)) | 343 | user.inTeam(self.obj.distribution.mirror_admin)) |
321 | 357 | 344 | ||
322 | 358 | 345 | ||
323 | @@ -392,22 +379,14 @@ | |||
324 | 392 | 379 | ||
325 | 393 | def checkAuthenticated(self, user): | 380 | def checkAuthenticated(self, user): |
326 | 394 | assert self.obj.target | 381 | assert self.obj.target |
335 | 395 | admins = getUtility(ILaunchpadCelebrities).admin | 382 | goal = self.obj.goal |
336 | 396 | goaldrivers = [] | 383 | if goal is not None: |
337 | 397 | goalowner = None | 384 | if user.isOwner(goal) or user.isOneOfDrivers(goal): |
330 | 398 | if self.obj.goal is not None: | ||
331 | 399 | goalowner = self.obj.goal.owner | ||
332 | 400 | goaldrivers = self.obj.goal.drivers | ||
333 | 401 | for driver in goaldrivers: | ||
334 | 402 | if user.inTeam(driver): | ||
338 | 403 | return True | 385 | return True |
346 | 404 | return (user.inTeam(self.obj.target.owner) or | 386 | return (user.in_admin or |
347 | 405 | user.inTeam(goalowner) or | 387 | user.isOwner(self.obj.target) or |
348 | 406 | user.inTeam(self.obj.owner) or | 388 | user.isOneOf( |
349 | 407 | user.inTeam(self.obj.drafter) or | 389 | self.obj, ['owner','drafter', 'assignee', 'approver'])) |
343 | 408 | user.inTeam(self.obj.assignee) or | ||
344 | 409 | user.inTeam(self.obj.approver) or | ||
345 | 410 | user.inTeam(admins)) | ||
350 | 411 | 390 | ||
351 | 412 | 391 | ||
352 | 413 | class AdminSpecification(AuthorizationBase): | 392 | class AdminSpecification(AuthorizationBase): |
353 | @@ -416,13 +395,9 @@ | |||
354 | 416 | 395 | ||
355 | 417 | def checkAuthenticated(self, user): | 396 | def checkAuthenticated(self, user): |
356 | 418 | assert self.obj.target | 397 | assert self.obj.target |
364 | 419 | targetowner = self.obj.target.owner | 398 | return (user.isOwner(self.obj.target) or |
365 | 420 | targetdrivers = self.obj.target.drivers | 399 | user.isOneOfDrivers(self.obj.target) or |
366 | 421 | for driver in targetdrivers: | 400 | user.in_admin) |
360 | 422 | if user.inTeam(driver): | ||
361 | 423 | return True | ||
362 | 424 | admins = getUtility(ILaunchpadCelebrities).admin | ||
363 | 425 | return (user.inTeam(targetowner) or user.inTeam(admins)) | ||
367 | 426 | 401 | ||
368 | 427 | 402 | ||
369 | 428 | class DriverSpecification(AuthorizationBase): | 403 | class DriverSpecification(AuthorizationBase): |
370 | @@ -448,10 +423,8 @@ | |||
371 | 448 | usedfor = ISprintSpecification | 423 | usedfor = ISprintSpecification |
372 | 449 | 424 | ||
373 | 450 | def checkAuthenticated(self, user): | 425 | def checkAuthenticated(self, user): |
378 | 451 | admins = getUtility(ILaunchpadCelebrities).admin | 426 | sprint = self.obj.sprint |
379 | 452 | return (user.inTeam(self.obj.sprint.owner) or | 427 | return user.isOwner(sprint) or user.isDriver(sprint) or user.in_admin |
376 | 453 | user.inTeam(self.obj.sprint.driver) or | ||
377 | 454 | user.inTeam(admins)) | ||
380 | 455 | 428 | ||
381 | 456 | 429 | ||
382 | 457 | class DriveSprint(AuthorizationBase): | 430 | class DriveSprint(AuthorizationBase): |
383 | @@ -462,10 +435,9 @@ | |||
384 | 462 | usedfor = ISprint | 435 | usedfor = ISprint |
385 | 463 | 436 | ||
386 | 464 | def checkAuthenticated(self, user): | 437 | def checkAuthenticated(self, user): |
391 | 465 | admins = getUtility(ILaunchpadCelebrities).admin | 438 | return (user.isOwner(self.obj) or |
392 | 466 | return (user.inTeam(self.obj.owner) or | 439 | user.isDriver(self.obj) or |
393 | 467 | user.inTeam(self.obj.driver) or | 440 | user.in_admin) |
390 | 468 | user.inTeam(admins)) | ||
394 | 469 | 441 | ||
395 | 470 | 442 | ||
396 | 471 | class Sprint(AuthorizationBase): | 443 | class Sprint(AuthorizationBase): |
397 | @@ -474,12 +446,11 @@ | |||
398 | 474 | usedfor = ISprint | 446 | usedfor = ISprint |
399 | 475 | 447 | ||
400 | 476 | def checkAuthenticated(self, user): | 448 | def checkAuthenticated(self, user): |
407 | 477 | admins = getUtility(ILaunchpadCelebrities).admin | 449 | return (user.isOwner(self.obj) or |
408 | 478 | return (user.inTeam(self.obj.owner) or | 450 | user.isDriver(self.obj) or |
409 | 479 | user.inTeam(self.obj.driver) or | 451 | user.person in [attendance.attendee |
410 | 480 | user in [attendance.attendee | 452 | for attendance in self.obj.attendances] or |
411 | 481 | for attendance in self.obj.attendances] or | 453 | user.in_admin) |
406 | 482 | user.inTeam(admins)) | ||
412 | 483 | 454 | ||
413 | 484 | 455 | ||
414 | 485 | class EditSpecificationSubscription(AuthorizationBase): | 456 | class EditSpecificationSubscription(AuthorizationBase): |
415 | @@ -489,21 +460,17 @@ | |||
416 | 489 | usedfor = ISpecificationSubscription | 460 | usedfor = ISpecificationSubscription |
417 | 490 | 461 | ||
418 | 491 | def checkAuthenticated(self, user): | 462 | def checkAuthenticated(self, user): |
419 | 492 | admins = getUtility(ILaunchpadCelebrities).admin | ||
420 | 493 | if self.obj.specification.goal is not None: | 463 | if self.obj.specification.goal is not None: |
424 | 494 | for driver in self.obj.specification.goal.drivers: | 464 | if user.isOneOfDrivers(self.obj.specification.goal): |
425 | 495 | if user.inTeam(driver): | 465 | return True |
423 | 496 | return True | ||
426 | 497 | else: | 466 | else: |
430 | 498 | for driver in self.obj.specification.target.drivers: | 467 | if user.isOneOfDrivers(self.obj.specification.target): |
431 | 499 | if user.inTeam(driver): | 468 | return True |
429 | 500 | return True | ||
432 | 501 | return (user.inTeam(self.obj.person) or | 469 | return (user.inTeam(self.obj.person) or |
438 | 502 | user.inTeam(self.obj.specification.owner) or | 470 | user.isOneOf( |
439 | 503 | user.inTeam(self.obj.specification.assignee) or | 471 | self.obj.specification, |
440 | 504 | user.inTeam(self.obj.specification.drafter) or | 472 | ['owner','drafter', 'assignee', 'approver']) or |
441 | 505 | user.inTeam(self.obj.specification.approver) or | 473 | user.in_admin) |
437 | 506 | user.inTeam(admins)) | ||
442 | 507 | 474 | ||
443 | 508 | 475 | ||
444 | 509 | class OnlyRosettaExpertsAndAdmins(AuthorizationBase): | 476 | class OnlyRosettaExpertsAndAdmins(AuthorizationBase): |
445 | @@ -512,7 +479,6 @@ | |||
446 | 512 | 479 | ||
447 | 513 | def checkAuthenticated(self, user): | 480 | def checkAuthenticated(self, user): |
448 | 514 | """Allow Launchpad's admins and Rosetta experts edit all fields.""" | 481 | """Allow Launchpad's admins and Rosetta experts edit all fields.""" |
449 | 515 | user = IPersonRoles(user) | ||
450 | 516 | return user.in_admin or user.in_rosetta_experts | 482 | return user.in_admin or user.in_rosetta_experts |
451 | 517 | 483 | ||
452 | 518 | 484 | ||
453 | @@ -526,7 +492,6 @@ | |||
454 | 526 | Any Launchpad/Launchpad Translations administrator or owners are | 492 | Any Launchpad/Launchpad Translations administrator or owners are |
455 | 527 | able to change translation settings for a product. | 493 | able to change translation settings for a product. |
456 | 528 | """ | 494 | """ |
457 | 529 | user = IPersonRoles(user) | ||
458 | 530 | return (user.isOwner(self.obj) or | 495 | return (user.isOwner(self.obj) or |
459 | 531 | user.in_rosetta_experts or | 496 | user.in_rosetta_experts or |
460 | 532 | user.in_admin) | 497 | user.in_admin) |
461 | @@ -537,8 +502,7 @@ | |||
462 | 537 | usedfor = IProductSeries | 502 | usedfor = IProductSeries |
463 | 538 | 503 | ||
464 | 539 | def checkAuthenticated(self, user): | 504 | def checkAuthenticated(self, user): |
467 | 540 | vcs_imports = getUtility(ILaunchpadCelebrities).vcs_imports | 505 | return user.in_vcs_imports |
466 | 541 | return user.inTeam(vcs_imports) | ||
468 | 542 | 506 | ||
469 | 543 | 507 | ||
470 | 544 | class EditProjectMilestoneNever(AuthorizationBase): | 508 | class EditProjectMilestoneNever(AuthorizationBase): |
471 | @@ -556,16 +520,15 @@ | |||
472 | 556 | 520 | ||
473 | 557 | def checkAuthenticated(self, user): | 521 | def checkAuthenticated(self, user): |
474 | 558 | """Authorize the product or distribution owner.""" | 522 | """Authorize the product or distribution owner.""" |
477 | 559 | celebrities = getUtility(ILaunchpadCelebrities) | 523 | if user.in_admin: |
476 | 560 | if user.inTeam(celebrities.admin): | ||
478 | 561 | return True | 524 | return True |
479 | 562 | if (self.obj.series_target is not None | 525 | if (self.obj.series_target is not None |
481 | 563 | and user.inTeam(self.obj.series_target.driver)): | 526 | and user.isDriver(self.obj.series_target)): |
482 | 564 | # The user is a release manager. | 527 | # The user is a release manager. |
483 | 565 | # XXX sinzui 2009-07-18 bug=40978: The series_target should never | 528 | # XXX sinzui 2009-07-18 bug=40978: The series_target should never |
484 | 566 | # be None, but Milestones in the production DB are like this. | 529 | # be None, but Milestones in the production DB are like this. |
485 | 567 | return True | 530 | return True |
487 | 568 | return user.inTeam(self.obj.target.owner) | 531 | return user.isOwner(self.obj.target) |
488 | 569 | 532 | ||
489 | 570 | class AdminMilestoneByLaunchpadAdmins(AuthorizationBase): | 533 | class AdminMilestoneByLaunchpadAdmins(AuthorizationBase): |
490 | 571 | permission = 'launchpad.Admin' | 534 | permission = 'launchpad.Admin' |
491 | @@ -575,8 +538,7 @@ | |||
492 | 575 | """Only the Launchpad admins need this, we are only going to use it | 538 | """Only the Launchpad admins need this, we are only going to use it |
493 | 576 | for connecting up series and distroseriess where we did not have | 539 | for connecting up series and distroseriess where we did not have |
494 | 577 | them.""" | 540 | them.""" |
497 | 578 | admins = getUtility(ILaunchpadCelebrities).admin | 541 | return user.in_admin |
496 | 579 | return user.inTeam(admins) | ||
498 | 580 | 542 | ||
499 | 581 | 543 | ||
500 | 582 | class ModeratePersonSetByExpertsOrAdmins(ReviewByRegistryExpertsOrAdmins): | 544 | class ModeratePersonSetByExpertsOrAdmins(ReviewByRegistryExpertsOrAdmins): |
501 | @@ -591,8 +553,7 @@ | |||
502 | 591 | def checkAuthenticated(self, user): | 553 | def checkAuthenticated(self, user): |
503 | 592 | """Only the team owner and Launchpad admins need this. | 554 | """Only the team owner and Launchpad admins need this. |
504 | 593 | """ | 555 | """ |
507 | 594 | admins = getUtility(ILaunchpadCelebrities).admin | 556 | return user.inTeam(self.obj.teamowner) or user.in_admin |
506 | 595 | return user.inTeam(self.obj.teamowner) or user.inTeam(admins) | ||
508 | 596 | 557 | ||
509 | 597 | 558 | ||
510 | 598 | class EditTeamByTeamOwnerOrTeamAdminsOrAdmins(AuthorizationBase): | 559 | class EditTeamByTeamOwnerOrTeamAdminsOrAdmins(AuthorizationBase): |
511 | @@ -650,8 +611,7 @@ | |||
512 | 650 | """ | 611 | """ |
513 | 651 | if self.obj.team.visibility == PersonVisibility.PUBLIC: | 612 | if self.obj.team.visibility == PersonVisibility.PUBLIC: |
514 | 652 | return True | 613 | return True |
517 | 653 | admins = getUtility(ILaunchpadCelebrities).admin | 614 | if user.in_admin or user.inTeam(self.obj.team): |
516 | 654 | if user.inTeam(admins) or user.inTeam(self.obj.team): | ||
518 | 655 | return True | 615 | return True |
519 | 656 | return False | 616 | return False |
520 | 657 | 617 | ||
521 | @@ -665,8 +625,7 @@ | |||
522 | 665 | 625 | ||
523 | 666 | The admin team can also edit any Person. | 626 | The admin team can also edit any Person. |
524 | 667 | """ | 627 | """ |
527 | 668 | admins = getUtility(ILaunchpadCelebrities).admin | 628 | return self.obj.id == user.person.id or user.in_admin |
526 | 669 | return self.obj.id == user.id or user.inTeam(admins) | ||
528 | 670 | 629 | ||
529 | 671 | 630 | ||
530 | 672 | class EditTranslationsPersonByPerson(AuthorizationBase): | 631 | class EditTranslationsPersonByPerson(AuthorizationBase): |
531 | @@ -675,8 +634,7 @@ | |||
532 | 675 | 634 | ||
533 | 676 | def checkAuthenticated(self, user): | 635 | def checkAuthenticated(self, user): |
534 | 677 | person = self.obj.person | 636 | person = self.obj.person |
537 | 678 | admins = getUtility(ILaunchpadCelebrities).admin | 637 | return person == user.person or user.in_admin |
536 | 679 | return person == user or user.inTeam(admins) | ||
538 | 680 | 638 | ||
539 | 681 | 639 | ||
540 | 682 | class ViewPersonLocation(AuthorizationBase): | 640 | class ViewPersonLocation(AuthorizationBase): |
541 | @@ -690,8 +648,7 @@ | |||
542 | 690 | if self.obj.visible: | 648 | if self.obj.visible: |
543 | 691 | return True | 649 | return True |
544 | 692 | else: | 650 | else: |
547 | 693 | admins = getUtility(ILaunchpadCelebrities).admin | 651 | return user.person == self.obj.person or user.in_admin |
546 | 694 | return user == self.obj.person or user.inTeam(admins) | ||
548 | 695 | 652 | ||
549 | 696 | 653 | ||
550 | 697 | class EditPersonBySelf(AuthorizationBase): | 654 | class EditPersonBySelf(AuthorizationBase): |
551 | @@ -700,7 +657,7 @@ | |||
552 | 700 | 657 | ||
553 | 701 | def checkAuthenticated(self, user): | 658 | def checkAuthenticated(self, user): |
554 | 702 | """A user can edit the Person who is herself.""" | 659 | """A user can edit the Person who is herself.""" |
556 | 703 | return self.obj.id == user.id | 660 | return self.obj.id == user.person.id |
557 | 704 | 661 | ||
558 | 705 | 662 | ||
559 | 706 | class ViewPublicOrPrivateTeamMembers(AuthorizationBase): | 663 | class ViewPublicOrPrivateTeamMembers(AuthorizationBase): |
560 | @@ -718,26 +675,21 @@ | |||
561 | 718 | return True | 675 | return True |
562 | 719 | return False | 676 | return False |
563 | 720 | 677 | ||
568 | 721 | def checkAccountAuthenticated(self, account): | 678 | def checkAuthenticated(self, user): |
569 | 722 | """See `IAuthorization.checkAccountAuthenticated`. | 679 | """Verify that the user can view the team's membership. |
566 | 723 | |||
567 | 724 | Verify that the user can view the team's membership. | ||
570 | 725 | 680 | ||
571 | 726 | Anyone can see a public team's membership. Only a team member | 681 | Anyone can see a public team's membership. Only a team member |
572 | 727 | or a Launchpad admin can view a private membership. | 682 | or a Launchpad admin can view a private membership. |
573 | 728 | """ | 683 | """ |
574 | 729 | if self.obj.visibility == PersonVisibility.PUBLIC: | 684 | if self.obj.visibility == PersonVisibility.PUBLIC: |
575 | 730 | return True | 685 | return True |
581 | 731 | user = IPerson(account, None) | 686 | if user.in_admin or user.inTeam(self.obj): |
577 | 732 | if user is None: | ||
578 | 733 | return False | ||
579 | 734 | admins = getUtility(ILaunchpadCelebrities).admin | ||
580 | 735 | if user.inTeam(admins) or user.inTeam(self.obj): | ||
582 | 736 | return True | 687 | return True |
583 | 737 | # We also grant visibility of the private team to administrators of | 688 | # We also grant visibility of the private team to administrators of |
584 | 738 | # other teams that have been invited to join the private team. | 689 | # other teams that have been invited to join the private team. |
585 | 739 | for invitee in self.obj.invited_members: | 690 | for invitee in self.obj.invited_members: |
587 | 740 | if invitee.is_team and invitee in user.getAdministratedTeams(): | 691 | if (invitee.is_team and |
588 | 692 | invitee in user.person.getAdministratedTeams()): | ||
589 | 741 | return True | 693 | return True |
590 | 742 | return False | 694 | return False |
591 | 743 | 695 | ||
592 | @@ -779,9 +731,7 @@ | |||
593 | 779 | usedfor = IDistribution | 731 | usedfor = IDistribution |
594 | 780 | 732 | ||
595 | 781 | def checkAuthenticated(self, user): | 733 | def checkAuthenticated(self, user): |
599 | 782 | admins = getUtility(ILaunchpadCelebrities).admin | 734 | return user.isOwner(self.obj) or user.in_admin |
597 | 783 | return (user.inTeam(self.obj.owner) or | ||
598 | 784 | user.inTeam(admins)) | ||
600 | 785 | 735 | ||
601 | 786 | 736 | ||
602 | 787 | class AppendDistributionByDriversOrOwnersOrAdmins(AuthorizationBase): | 737 | class AppendDistributionByDriversOrOwnersOrAdmins(AuthorizationBase): |
603 | @@ -794,13 +744,11 @@ | |||
604 | 794 | usedfor = IDistribution | 744 | usedfor = IDistribution |
605 | 795 | 745 | ||
606 | 796 | def checkAuthenticated(self, user): | 746 | def checkAuthenticated(self, user): |
608 | 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: |
609 | 798 | # Drivers of derivative distributions can create a series that | 748 | # Drivers of derivative distributions can create a series that |
610 | 799 | # they will be the release manager for. | 749 | # they will be the release manager for. |
611 | 800 | return True | 750 | return True |
615 | 801 | admins = getUtility(ILaunchpadCelebrities).admin | 751 | return user.isOwner(self.obj) or user.in_admin |
613 | 802 | return (user.inTeam(self.obj.owner) or | ||
614 | 803 | user.inTeam(admins)) | ||
616 | 804 | 752 | ||
617 | 805 | 753 | ||
618 | 806 | class EditDistributionSourcePackageByDistroOwnersOrAdmins(AuthorizationBase): | 754 | class EditDistributionSourcePackageByDistroOwnersOrAdmins(AuthorizationBase): |
619 | @@ -810,9 +758,8 @@ | |||
620 | 810 | usedfor = IDistributionSourcePackage | 758 | usedfor = IDistributionSourcePackage |
621 | 811 | 759 | ||
622 | 812 | def checkAuthenticated(self, user): | 760 | def checkAuthenticated(self, user): |
623 | 813 | admins = getUtility(ILaunchpadCelebrities).admin | ||
624 | 814 | return (user.inTeam(self.obj.distribution.owner) or | 761 | return (user.inTeam(self.obj.distribution.owner) or |
626 | 815 | user.inTeam(admins)) | 762 | user.in_admin) |
627 | 816 | 763 | ||
628 | 817 | 764 | ||
629 | 818 | class AdminDistroSeries(AdminByAdminsTeam): | 765 | class AdminDistroSeries(AdminByAdminsTeam): |
630 | @@ -846,10 +793,9 @@ | |||
631 | 846 | # The series driver (release manager) may edit a series if the | 793 | # The series driver (release manager) may edit a series if the |
632 | 847 | # distribution is an `IDerivativeDistribution` | 794 | # distribution is an `IDerivativeDistribution` |
633 | 848 | return True | 795 | return True |
634 | 849 | admins = getUtility(ILaunchpadCelebrities).admin | ||
635 | 850 | return (user.inTeam(self.obj.owner) or | 796 | return (user.inTeam(self.obj.owner) or |
636 | 851 | user.inTeam(self.obj.distribution.owner) or | 797 | user.inTeam(self.obj.distribution.owner) or |
638 | 852 | user.inTeam(admins)) | 798 | user.in_admin) |
639 | 853 | 799 | ||
640 | 854 | 800 | ||
641 | 855 | class SeriesDrivers(AuthorizationBase): | 801 | class SeriesDrivers(AuthorizationBase): |
642 | @@ -862,11 +808,9 @@ | |||
643 | 862 | usedfor = IHasDrivers | 808 | usedfor = IHasDrivers |
644 | 863 | 809 | ||
645 | 864 | def checkAuthenticated(self, user): | 810 | def checkAuthenticated(self, user): |
651 | 865 | for driver in self.obj.drivers: | 811 | return (user.isOneOfDrivers(self.obj) or |
652 | 866 | if user.inTeam(driver): | 812 | user.isOwner(self.obj) or |
653 | 867 | return True | 813 | user.in_admin) |
649 | 868 | admins = getUtility(ILaunchpadCelebrities).admin | ||
650 | 869 | return user.inTeam(self.obj.owner) or user.inTeam(admins) | ||
654 | 870 | 814 | ||
655 | 871 | 815 | ||
656 | 872 | class ViewProductSeries(AuthorizationBase): | 816 | class ViewProductSeries(AuthorizationBase): |
657 | @@ -901,10 +845,9 @@ | |||
658 | 901 | # Rosetta experts need to be able to upload translations. | 845 | # Rosetta experts need to be able to upload translations. |
659 | 902 | # Bazaar experts need to be able to change the linked branches. | 846 | # Bazaar experts need to be able to change the linked branches. |
660 | 903 | # Registry admins are just special. | 847 | # Registry admins are just special. |
665 | 904 | celebrities = getUtility(ILaunchpadCelebrities) | 848 | if (user.in_registry_experts or |
666 | 905 | if (user.inTeam(celebrities.registry_experts) or | 849 | user.in_bazaar_experts or |
667 | 906 | user.inTeam(celebrities.bazaar_experts) or | 850 | user.in_rosetta_experts): |
664 | 907 | user.inTeam(celebrities.rosetta_experts)): | ||
668 | 908 | return True | 851 | return True |
669 | 909 | return EditByOwnersOrAdmins.checkAuthenticated(self, user) | 852 | return EditByOwnersOrAdmins.checkAuthenticated(self, user) |
670 | 910 | 853 | ||
671 | @@ -920,9 +863,8 @@ | |||
672 | 920 | usedfor = IHasBug | 863 | usedfor = IHasBug |
673 | 921 | 864 | ||
674 | 922 | def checkAuthenticated(self, user): | 865 | def checkAuthenticated(self, user): |
675 | 923 | admins = getUtility(ILaunchpadCelebrities).admin | ||
676 | 924 | 866 | ||
678 | 925 | if user.inTeam(admins): | 867 | if user.in_admin: |
679 | 926 | # Admins can always edit bugtasks, whether they're reported on a | 868 | # Admins can always edit bugtasks, whether they're reported on a |
680 | 927 | # private bug or not. | 869 | # private bug or not. |
681 | 928 | return True | 870 | return True |
682 | @@ -946,7 +888,7 @@ | |||
683 | 946 | usedfor = IHasBug | 888 | usedfor = IHasBug |
684 | 947 | 889 | ||
685 | 948 | def checkAuthenticated(self, user): | 890 | def checkAuthenticated(self, user): |
687 | 949 | return self.obj.bug.userCanView(user) | 891 | return self.obj.bug.userCanView(user.person) |
688 | 950 | 892 | ||
689 | 951 | def checkUnauthenticated(self): | 893 | def checkUnauthenticated(self): |
690 | 952 | """Allow anonymous users to see non-private bugs only.""" | 894 | """Allow anonymous users to see non-private bugs only.""" |
691 | @@ -962,11 +904,10 @@ | |||
692 | 962 | """Allow any logged in user to edit a public bug, and only | 904 | """Allow any logged in user to edit a public bug, and only |
693 | 963 | explicit subscribers to edit private bugs. | 905 | explicit subscribers to edit private bugs. |
694 | 964 | """ | 906 | """ |
695 | 965 | admins = getUtility(ILaunchpadCelebrities).admin | ||
696 | 966 | if not self.obj.private: | 907 | if not self.obj.private: |
697 | 967 | # This is a public bug. | 908 | # This is a public bug. |
698 | 968 | return True | 909 | return True |
700 | 969 | elif user.inTeam(admins): | 910 | elif user.in_admin: |
701 | 970 | # Admins can edit all bugs. | 911 | # Admins can edit all bugs. |
702 | 971 | return True | 912 | return True |
703 | 972 | else: | 913 | else: |
704 | @@ -990,7 +931,7 @@ | |||
705 | 990 | """Allow any user to see non-private bugs, but only explicit | 931 | """Allow any user to see non-private bugs, but only explicit |
706 | 991 | subscribers to see private bugs. | 932 | subscribers to see private bugs. |
707 | 992 | """ | 933 | """ |
709 | 993 | return self.obj.userCanView(user) | 934 | return self.obj.userCanView(user.person) |
710 | 994 | 935 | ||
711 | 995 | def checkUnauthenticated(self): | 936 | def checkUnauthenticated(self): |
712 | 996 | """Allow anonymous users to see non-private bugs only.""" | 937 | """Allow anonymous users to see non-private bugs only.""" |
713 | @@ -1056,17 +997,11 @@ | |||
714 | 1056 | return True | 997 | return True |
715 | 1057 | 998 | ||
716 | 1058 | # Project drivers can view any project announcements. | 999 | # Project drivers can view any project announcements. |
717 | 1059 | assert self.obj.target | ||
718 | 1060 | if self.obj.target.drivers: | ||
719 | 1061 | for driver in self.obj.target.drivers: | ||
720 | 1062 | if user.inTeam(driver): | ||
721 | 1063 | return True | ||
722 | 1064 | if user.inTeam(self.obj.target.owner): | ||
723 | 1065 | return True | ||
724 | 1066 | |||
725 | 1067 | # Launchpad admins can view any announcement. | 1000 | # Launchpad admins can view any announcement. |
728 | 1068 | admins = getUtility(ILaunchpadCelebrities).admin | 1001 | assert self.obj.target |
729 | 1069 | return user.inTeam(admins) | 1002 | return (user.isOneOfDrivers(self.obj.target) or |
730 | 1003 | user.isOwner(self.obj.target) or | ||
731 | 1004 | user.in_admin) | ||
732 | 1070 | 1005 | ||
733 | 1071 | 1006 | ||
734 | 1072 | class EditAnnouncement(AuthorizationBase): | 1007 | class EditAnnouncement(AuthorizationBase): |
735 | @@ -1077,15 +1012,9 @@ | |||
736 | 1077 | """Allow the project owner and drivers to edit any project news.""" | 1012 | """Allow the project owner and drivers to edit any project news.""" |
737 | 1078 | 1013 | ||
738 | 1079 | assert self.obj.target | 1014 | assert self.obj.target |
748 | 1080 | if self.obj.target.drivers: | 1015 | return (user.isOneOfDrivers(self.obj.target) or |
749 | 1081 | for driver in self.obj.target.drivers: | 1016 | user.isOwner(self.obj.target) or |
750 | 1082 | if user.inTeam(driver): | 1017 | user.in_admin) |
742 | 1083 | return True | ||
743 | 1084 | if user.inTeam(self.obj.target.owner): | ||
744 | 1085 | return True | ||
745 | 1086 | |||
746 | 1087 | admins = getUtility(ILaunchpadCelebrities).admin | ||
747 | 1088 | return user.inTeam(admins) | ||
751 | 1089 | 1018 | ||
752 | 1090 | 1019 | ||
753 | 1091 | class UseApiDoc(AuthorizationBase): | 1020 | class UseApiDoc(AuthorizationBase): |
754 | @@ -1101,9 +1030,7 @@ | |||
755 | 1101 | experts.""" | 1030 | experts.""" |
756 | 1102 | 1031 | ||
757 | 1103 | def checkAuthenticated(self, user): | 1032 | def checkAuthenticated(self, user): |
761 | 1104 | bzrexperts = getUtility(ILaunchpadCelebrities).bazaar_experts | 1033 | return user.in_admin or user.in_bazaar_experts |
759 | 1105 | admins = getUtility(ILaunchpadCelebrities).admin | ||
760 | 1106 | return user.inTeam(admins) or user.inTeam(bzrexperts) | ||
762 | 1107 | 1034 | ||
763 | 1108 | 1035 | ||
764 | 1109 | class OnlyVcsImportsAndAdmins(AuthorizationBase): | 1036 | class OnlyVcsImportsAndAdmins(AuthorizationBase): |
765 | @@ -1111,9 +1038,7 @@ | |||
766 | 1111 | experts.""" | 1038 | experts.""" |
767 | 1112 | 1039 | ||
768 | 1113 | def checkAuthenticated(self, user): | 1040 | def checkAuthenticated(self, user): |
772 | 1114 | vcsexpert = getUtility(ILaunchpadCelebrities).vcs_imports | 1041 | return user.in_admin or user.in_vcs_imports |
770 | 1115 | admins = getUtility(ILaunchpadCelebrities).admin | ||
771 | 1116 | return user.inTeam(admins) or user.inTeam(vcsexpert) | ||
773 | 1117 | 1042 | ||
774 | 1118 | 1043 | ||
775 | 1119 | class AdminTheBazaar(OnlyVcsImportsAndAdmins): | 1044 | class AdminTheBazaar(OnlyVcsImportsAndAdmins): |
776 | @@ -1252,11 +1177,10 @@ | |||
777 | 1252 | def checkAuthenticated(self, user): | 1177 | def checkAuthenticated(self, user): |
778 | 1253 | """Allow anyone that can edit translations, owner, experts and admis. | 1178 | """Allow anyone that can edit translations, owner, experts and admis. |
779 | 1254 | """ | 1179 | """ |
780 | 1255 | rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts | ||
781 | 1256 | 1180 | ||
782 | 1257 | return (EditByOwnersOrAdmins.checkAuthenticated(self, user) or | 1181 | return (EditByOwnersOrAdmins.checkAuthenticated(self, user) or |
785 | 1258 | self.obj.canEditTranslations(user) or | 1182 | self.obj.canEditTranslations(user.person) or |
786 | 1259 | user.inTeam(rosetta_experts)) | 1183 | user.in_rosetta_experts) |
787 | 1260 | 1184 | ||
788 | 1261 | 1185 | ||
789 | 1262 | class AdminTranslator(OnlyRosettaExpertsAndAdmins): | 1186 | class AdminTranslator(OnlyRosettaExpertsAndAdmins): |
790 | @@ -1370,7 +1294,7 @@ | |||
791 | 1370 | 1294 | ||
792 | 1371 | # As a special case, the Ubuntu translation group owners can | 1295 | # As a special case, the Ubuntu translation group owners can |
793 | 1372 | # manage Ubuntu uploads. | 1296 | # manage Ubuntu uploads. |
795 | 1373 | if self.obj.isUbuntuAndIsUserTranslationGroupOwner(user): | 1297 | if self.obj.isUbuntuAndIsUserTranslationGroupOwner(user.person): |
796 | 1374 | return True | 1298 | return True |
797 | 1375 | 1299 | ||
798 | 1376 | return False | 1300 | return False |
799 | @@ -1386,7 +1310,7 @@ | |||
800 | 1386 | """ | 1310 | """ |
801 | 1387 | if AdminTranslationImportQueueEntry.checkAuthenticated(self, user): | 1311 | if AdminTranslationImportQueueEntry.checkAuthenticated(self, user): |
802 | 1388 | return True | 1312 | return True |
804 | 1389 | if self.obj.isUserUploaderOrOwner(user): | 1313 | if self.obj.isUserUploaderOrOwner(user.person): |
805 | 1390 | return True | 1314 | return True |
806 | 1391 | 1315 | ||
807 | 1392 | return False | 1316 | return False |
808 | @@ -1408,7 +1332,7 @@ | |||
809 | 1408 | 1332 | ||
810 | 1409 | permission_set = getUtility(IArchivePermissionSet) | 1333 | permission_set = getUtility(IArchivePermissionSet) |
811 | 1410 | permissions = permission_set.componentsForQueueAdmin( | 1334 | permissions = permission_set.componentsForQueueAdmin( |
813 | 1411 | self.obj.distroseries.main_archive, user) | 1335 | self.obj.distroseries.main_archive, user.person) |
814 | 1412 | return permissions.count() > 0 | 1336 | return permissions.count() > 0 |
815 | 1413 | 1337 | ||
816 | 1414 | 1338 | ||
817 | @@ -1431,7 +1355,7 @@ | |||
818 | 1431 | 1355 | ||
819 | 1432 | permission_set = getUtility(IArchivePermissionSet) | 1356 | permission_set = getUtility(IArchivePermissionSet) |
820 | 1433 | permissions = permission_set.componentsForQueueAdmin( | 1357 | permissions = permission_set.componentsForQueueAdmin( |
822 | 1434 | self.obj.archive, user) | 1358 | self.obj.archive, user.person) |
823 | 1435 | if permissions.count() == 0: | 1359 | if permissions.count() == 0: |
824 | 1436 | return False | 1360 | return False |
825 | 1437 | allowed_components = set( | 1361 | allowed_components = set( |
826 | @@ -1449,11 +1373,7 @@ | |||
827 | 1449 | 1373 | ||
828 | 1450 | def checkAuthenticated(self, user): | 1374 | def checkAuthenticated(self, user): |
829 | 1451 | """Allow admins and buildd_admins.""" | 1375 | """Allow admins and buildd_admins.""" |
835 | 1452 | lp_admin = getUtility(ILaunchpadCelebrities).admin | 1376 | return user.in_buildd_admin or user.in_admin |
831 | 1453 | if user.inTeam(lp_admin): | ||
832 | 1454 | return True | ||
833 | 1455 | buildd_admin = getUtility(ILaunchpadCelebrities).buildd_admin | ||
834 | 1456 | return user.inTeam(buildd_admin) | ||
836 | 1457 | 1377 | ||
837 | 1458 | 1378 | ||
838 | 1459 | class AdminBuilderSet(AdminByBuilddAdmin): | 1379 | class AdminBuilderSet(AdminByBuilddAdmin): |
839 | @@ -1500,11 +1420,12 @@ | |||
840 | 1500 | # Primary or partner section here: is the user in question allowed | 1420 | # Primary or partner section here: is the user in question allowed |
841 | 1501 | # to upload to the respective component? Allow user to retry build | 1421 | # to upload to the respective component? Allow user to retry build |
842 | 1502 | # if so. | 1422 | # if so. |
844 | 1503 | if self.obj.archive.canUpload(user, self.obj.current_component): | 1423 | archive = self.obj.archive |
845 | 1424 | if archive.canUpload(user.person, self.obj.current_component): | ||
846 | 1504 | return True | 1425 | return True |
847 | 1505 | else: | 1426 | else: |
850 | 1506 | return self.obj.archive.canUpload( | 1427 | return archive.canUpload( |
851 | 1507 | user, self.obj.sourcepackagerelease.sourcepackagename) | 1428 | user.person, self.obj.sourcepackagerelease.sourcepackagename) |
852 | 1508 | 1429 | ||
853 | 1509 | 1430 | ||
854 | 1510 | class ViewBuildRecord(EditBuildRecord): | 1431 | class ViewBuildRecord(EditBuildRecord): |
855 | @@ -1524,8 +1445,7 @@ | |||
856 | 1524 | return True | 1445 | return True |
857 | 1525 | 1446 | ||
858 | 1526 | # LP admins may also see it. | 1447 | # LP admins may also see it. |
861 | 1527 | lp_admin = getUtility(ILaunchpadCelebrities).admin | 1448 | if user.in_admin: |
860 | 1528 | if user.inTeam(lp_admin): | ||
862 | 1529 | return True | 1449 | return True |
863 | 1530 | 1450 | ||
864 | 1531 | # If the permission check on the sourcepackagerelease for this | 1451 | # If the permission check on the sourcepackagerelease for this |
865 | @@ -1611,10 +1531,10 @@ | |||
866 | 1611 | 1531 | ||
867 | 1612 | def can_edit_team(team, user): | 1532 | def can_edit_team(team, user): |
868 | 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.""" |
870 | 1614 | if user.inTeam(getUtility(ILaunchpadCelebrities).admin): | 1534 | if user.in_admin: |
871 | 1615 | return True | 1535 | return True |
872 | 1616 | else: | 1536 | else: |
874 | 1617 | return team in user.getAdministratedTeams() | 1537 | return team in user.person.getAdministratedTeams() |
875 | 1618 | 1538 | ||
876 | 1619 | 1539 | ||
877 | 1620 | class AdminLanguageSet(OnlyRosettaExpertsAndAdmins): | 1540 | class AdminLanguageSet(OnlyRosettaExpertsAndAdmins): |
878 | @@ -1638,7 +1558,7 @@ | |||
879 | 1638 | usedfor = IBranch | 1558 | usedfor = IBranch |
880 | 1639 | 1559 | ||
881 | 1640 | def checkAuthenticated(self, user): | 1560 | def checkAuthenticated(self, user): |
883 | 1641 | return self.obj.visibleByUser(user) | 1561 | return self.obj.visibleByUser(user.person) |
884 | 1642 | 1562 | ||
885 | 1643 | def checkUnauthenticated(self): | 1563 | def checkUnauthenticated(self): |
886 | 1644 | return self.obj.visibleByUser(None) | 1564 | return self.obj.visibleByUser(None) |
887 | @@ -1652,7 +1572,7 @@ | |||
888 | 1652 | def checkAuthenticated(self, user): | 1572 | def checkAuthenticated(self, user): |
889 | 1653 | can_edit = ( | 1573 | can_edit = ( |
890 | 1654 | user.inTeam(self.obj.owner) or | 1574 | user.inTeam(self.obj.owner) or |
892 | 1655 | user_has_special_branch_access(user) or | 1575 | user_has_special_branch_access(user.person) or |
893 | 1656 | can_upload_linked_package(user, self.obj)) | 1576 | can_upload_linked_package(user, self.obj)) |
894 | 1657 | if can_edit: | 1577 | if can_edit: |
895 | 1658 | return True | 1578 | return True |
896 | @@ -1666,12 +1586,12 @@ | |||
897 | 1666 | return False | 1586 | return False |
898 | 1667 | vcs_imports = getUtility(ILaunchpadCelebrities).vcs_imports | 1587 | vcs_imports = getUtility(ILaunchpadCelebrities).vcs_imports |
899 | 1668 | return ( | 1588 | return ( |
901 | 1669 | user.inTeam(vcs_imports) | 1589 | user.in_vcs_imports |
902 | 1670 | or (self.obj.owner == vcs_imports | 1590 | or (self.obj.owner == vcs_imports |
903 | 1671 | and user.inTeam(code_import.registrant))) | 1591 | and user.inTeam(code_import.registrant))) |
904 | 1672 | 1592 | ||
905 | 1673 | 1593 | ||
907 | 1674 | def can_upload_linked_package(person, branch): | 1594 | def can_upload_linked_package(person_role, branch): |
908 | 1675 | """True if person may upload the package linked to `branch`.""" | 1595 | """True if person may upload the package linked to `branch`.""" |
909 | 1676 | # No associated `ISuiteSourcePackage` data -> not an official branch. | 1596 | # No associated `ISuiteSourcePackage` data -> not an official branch. |
910 | 1677 | # Abort. | 1597 | # Abort. |
911 | @@ -1686,7 +1606,7 @@ | |||
912 | 1686 | # one combination that allows us to upload the corresponding source | 1606 | # one combination that allows us to upload the corresponding source |
913 | 1687 | # package. | 1607 | # package. |
914 | 1688 | for ssp in ssp_list: | 1608 | for ssp in ssp_list: |
916 | 1689 | if can_upload_to_archive(person, ssp): | 1609 | if can_upload_to_archive(person_role.person, ssp): |
917 | 1690 | return True | 1610 | return True |
918 | 1691 | return False | 1611 | return False |
919 | 1692 | 1612 | ||
920 | @@ -1697,9 +1617,8 @@ | |||
921 | 1697 | usedfor = IBranch | 1617 | usedfor = IBranch |
922 | 1698 | 1618 | ||
923 | 1699 | def checkAuthenticated(self, user): | 1619 | def checkAuthenticated(self, user): |
927 | 1700 | celebs = getUtility(ILaunchpadCelebrities) | 1620 | return (user.in_admin or |
928 | 1701 | return (user.inTeam(celebs.admin) or | 1621 | user.in_bazaar_experts) |
926 | 1702 | user.inTeam(celebs.bazaar_experts)) | ||
929 | 1703 | 1622 | ||
930 | 1704 | 1623 | ||
931 | 1705 | # Please keep this in sync with AdminPOTemplateDetails. Note that | 1624 | # Please keep this in sync with AdminPOTemplateDetails. Note that |
932 | @@ -1788,10 +1707,9 @@ | |||
933 | 1788 | Any team member can edit a branch subscription for their team. | 1707 | Any team member can edit a branch subscription for their team. |
934 | 1789 | Launchpad Admins can also edit any branch subscription. | 1708 | Launchpad Admins can also edit any branch subscription. |
935 | 1790 | """ | 1709 | """ |
936 | 1791 | celebs = getUtility(ILaunchpadCelebrities) | ||
937 | 1792 | return (user.inTeam(self.obj.person) or | 1710 | return (user.inTeam(self.obj.person) or |
940 | 1793 | user.inTeam(celebs.admin) or | 1711 | user.in_admin or |
941 | 1794 | user.inTeam(celebs.bazaar_experts)) | 1712 | user.in_bazaar_experts) |
942 | 1795 | 1713 | ||
943 | 1796 | 1714 | ||
944 | 1797 | class BranchSubscriptionView(BranchSubscriptionEdit): | 1715 | class BranchSubscriptionView(BranchSubscriptionEdit): |
945 | @@ -1903,13 +1821,12 @@ | |||
946 | 1903 | * the reviewer for the target_branch | 1821 | * the reviewer for the target_branch |
947 | 1904 | * an administrator | 1822 | * an administrator |
948 | 1905 | """ | 1823 | """ |
949 | 1906 | celebs = getUtility(ILaunchpadCelebrities) | ||
950 | 1907 | return (user.inTeam(self.obj.registrant) or | 1824 | return (user.inTeam(self.obj.registrant) or |
951 | 1908 | user.inTeam(self.obj.source_branch.owner) or | 1825 | user.inTeam(self.obj.source_branch.owner) or |
952 | 1909 | user.inTeam(self.obj.target_branch.owner) or | 1826 | user.inTeam(self.obj.target_branch.owner) or |
953 | 1910 | user.inTeam(self.obj.target_branch.reviewer) or | 1827 | user.inTeam(self.obj.target_branch.reviewer) or |
956 | 1911 | user.inTeam(celebs.admin) or | 1828 | user.in_admin or |
957 | 1912 | user.inTeam(celebs.bazaar_experts)) | 1829 | user.in_bazaar_experts) |
958 | 1913 | 1830 | ||
959 | 1914 | 1831 | ||
960 | 1915 | class ViewEntitlement(AuthorizationBase): | 1832 | class ViewEntitlement(AuthorizationBase): |
961 | @@ -1927,10 +1844,9 @@ | |||
962 | 1927 | Any team member can edit a branch subscription for their team. | 1844 | Any team member can edit a branch subscription for their team. |
963 | 1928 | Launchpad Admins can also edit any branch subscription. | 1845 | Launchpad Admins can also edit any branch subscription. |
964 | 1929 | """ | 1846 | """ |
965 | 1930 | admins = getUtility(ILaunchpadCelebrities).admin | ||
966 | 1931 | return (user.inTeam(self.obj.person) or | 1847 | return (user.inTeam(self.obj.person) or |
967 | 1932 | user.inTeam(self.obj.registrant) or | 1848 | user.inTeam(self.obj.registrant) or |
969 | 1933 | user.inTeam(admins)) | 1849 | user.in_admin) |
970 | 1934 | 1850 | ||
971 | 1935 | 1851 | ||
972 | 1936 | class AdminDistroSeriesLanguagePacks( | 1852 | class AdminDistroSeriesLanguagePacks( |
973 | @@ -1972,8 +1888,7 @@ | |||
974 | 1972 | if not self.obj.private: | 1888 | if not self.obj.private: |
975 | 1973 | return True | 1889 | return True |
976 | 1974 | 1890 | ||
979 | 1975 | admins = getUtility(ILaunchpadCelebrities).admin | 1891 | return user.inTeam(self.obj.owner) or user.in_admin |
978 | 1976 | return user.inTeam(self.obj.owner) or user.inTeam(admins) | ||
980 | 1977 | 1892 | ||
981 | 1978 | def checkUnauthenticated(self): | 1893 | def checkUnauthenticated(self): |
982 | 1979 | return not self.obj.private | 1894 | return not self.obj.private |
983 | @@ -1991,8 +1906,7 @@ | |||
984 | 1991 | 1906 | ||
985 | 1992 | def checkAuthenticated(self, user): | 1907 | def checkAuthenticated(self, user): |
986 | 1993 | """We give for now access only to Canonical employees.""" | 1908 | """We give for now access only to Canonical employees.""" |
989 | 1994 | hwdb_team = getUtility(ILaunchpadCelebrities).hwdb_team | 1909 | return user.in_hwdb_team |
988 | 1995 | return user.inTeam(hwdb_team) | ||
990 | 1996 | 1910 | ||
991 | 1997 | def checkUnauthenticated(self): | 1911 | def checkUnauthenticated(self): |
992 | 1998 | """No access for anonymous users.""" | 1912 | """No access for anonymous users.""" |
993 | @@ -2054,9 +1968,7 @@ | |||
994 | 2054 | return True | 1968 | return True |
995 | 2055 | 1969 | ||
996 | 2056 | # Administrator are allowed to view private archives. | 1970 | # Administrator are allowed to view private archives. |
1000 | 2057 | celebrities = getUtility(ILaunchpadCelebrities) | 1971 | if user.in_admin or user.in_commercial_admin: |
998 | 2058 | if (user.inTeam(celebrities.admin) | ||
999 | 2059 | or user.inTeam(celebrities.commercial_admin)): | ||
1001 | 2060 | return True | 1972 | return True |
1002 | 2061 | 1973 | ||
1003 | 2062 | # Owners can view the PPA. | 1974 | # Owners can view the PPA. |
1004 | @@ -2064,7 +1976,7 @@ | |||
1005 | 2064 | return True | 1976 | return True |
1006 | 2065 | 1977 | ||
1007 | 2066 | # Uploaders can view private PPAs. | 1978 | # Uploaders can view private PPAs. |
1009 | 2067 | if self.obj.is_ppa and self.obj.canUpload(user): | 1979 | if self.obj.is_ppa and self.obj.canUpload(user.person): |
1010 | 2068 | return True | 1980 | return True |
1011 | 2069 | 1981 | ||
1012 | 2070 | return False | 1982 | return False |
1013 | @@ -2096,13 +2008,13 @@ | |||
1014 | 2096 | if user.inTeam(self.obj.owner): | 2008 | if user.inTeam(self.obj.owner): |
1015 | 2097 | return True | 2009 | return True |
1016 | 2098 | 2010 | ||
1018 | 2099 | if self.obj.is_ppa and self.obj.canUpload(user): | 2011 | if self.obj.is_ppa and self.obj.canUpload(user.person): |
1019 | 2100 | return True | 2012 | return True |
1020 | 2101 | 2013 | ||
1021 | 2102 | celebrities = getUtility(ILaunchpadCelebrities) | 2014 | celebrities = getUtility(ILaunchpadCelebrities) |
1022 | 2103 | if (self.obj.is_main and | 2015 | if (self.obj.is_main and |
1023 | 2104 | self.obj.distribution == celebrities.ubuntu and | 2016 | self.obj.distribution == celebrities.ubuntu and |
1025 | 2105 | user.inTeam(celebrities.ubuntu_security)): | 2017 | user.in_ubuntu_security): |
1026 | 2106 | return True | 2018 | return True |
1027 | 2107 | 2019 | ||
1028 | 2108 | return False | 2020 | return False |
1029 | @@ -2118,7 +2030,7 @@ | |||
1030 | 2118 | usedfor = IArchiveAuthToken | 2030 | usedfor = IArchiveAuthToken |
1031 | 2119 | 2031 | ||
1032 | 2120 | def checkAuthenticated(self, user): | 2032 | def checkAuthenticated(self, user): |
1034 | 2121 | if user == self.obj.person: | 2033 | if user.person == self.obj.person: |
1035 | 2122 | return True | 2034 | return True |
1036 | 2123 | auth_edit = EditArchiveAuthToken(self.obj) | 2035 | auth_edit = EditArchiveAuthToken(self.obj) |
1037 | 2124 | return auth_edit.checkAuthenticated(user) | 2036 | return auth_edit.checkAuthenticated(user) |
1038 | @@ -2137,8 +2049,7 @@ | |||
1039 | 2137 | auth_append = AppendArchive(self.obj.archive) | 2049 | auth_append = AppendArchive(self.obj.archive) |
1040 | 2138 | if auth_append.checkAuthenticated(user): | 2050 | if auth_append.checkAuthenticated(user): |
1041 | 2139 | return True | 2051 | return True |
1044 | 2140 | admins = getUtility(ILaunchpadCelebrities).admin | 2052 | return user.in_admin |
1043 | 2141 | return user.inTeam(admins) | ||
1045 | 2142 | 2053 | ||
1046 | 2143 | 2054 | ||
1047 | 2144 | class ViewPersonalArchiveSubscription(AuthorizationBase): | 2055 | class ViewPersonalArchiveSubscription(AuthorizationBase): |
1048 | @@ -2151,15 +2062,14 @@ | |||
1049 | 2151 | usedfor = IPersonalArchiveSubscription | 2062 | usedfor = IPersonalArchiveSubscription |
1050 | 2152 | 2063 | ||
1051 | 2153 | def checkAuthenticated(self, user): | 2064 | def checkAuthenticated(self, user): |
1053 | 2154 | if user == self.obj.subscriber: | 2065 | if user.person == self.obj.subscriber: |
1054 | 2155 | return True | 2066 | return True |
1055 | 2156 | append_archive = AppendArchive(self.obj.archive) | 2067 | append_archive = AppendArchive(self.obj.archive) |
1056 | 2157 | 2068 | ||
1057 | 2158 | if append_archive.checkAuthenticated(user): | 2069 | if append_archive.checkAuthenticated(user): |
1058 | 2159 | return True | 2070 | return True |
1059 | 2160 | 2071 | ||
1062 | 2161 | admins = getUtility(ILaunchpadCelebrities).admin | 2072 | return user.in_admin |
1061 | 2162 | return user.inTeam(admins) | ||
1063 | 2163 | 2073 | ||
1064 | 2164 | 2074 | ||
1065 | 2165 | class ViewArchiveSubscriber(AuthorizationBase): | 2075 | class ViewArchiveSubscriber(AuthorizationBase): |
1066 | @@ -2190,8 +2100,7 @@ | |||
1067 | 2190 | auth_append = AppendArchive(self.obj.archive) | 2100 | auth_append = AppendArchive(self.obj.archive) |
1068 | 2191 | if auth_append.checkAuthenticated(user): | 2101 | if auth_append.checkAuthenticated(user): |
1069 | 2192 | return True | 2102 | return True |
1072 | 2193 | admins = getUtility(ILaunchpadCelebrities).admin | 2103 | return user.in_admin |
1071 | 2194 | return user.inTeam(admins) | ||
1073 | 2195 | 2104 | ||
1074 | 2196 | 2105 | ||
1075 | 2197 | class ViewSourcePackagePublishingHistory(AuthorizationBase): | 2106 | class ViewSourcePackagePublishingHistory(AuthorizationBase): |
1076 | @@ -2203,8 +2112,7 @@ | |||
1077 | 2203 | view_archive = ViewArchive(self.obj.archive) | 2112 | view_archive = ViewArchive(self.obj.archive) |
1078 | 2204 | if view_archive.checkAuthenticated(user): | 2113 | if view_archive.checkAuthenticated(user): |
1079 | 2205 | return True | 2114 | return True |
1082 | 2206 | admins = getUtility(ILaunchpadCelebrities).admin | 2115 | return user.in_admin |
1081 | 2207 | return user.inTeam(admins) | ||
1083 | 2208 | 2116 | ||
1084 | 2209 | def checkUnauthenticated(self): | 2117 | def checkUnauthenticated(self): |
1085 | 2210 | return not self.obj.archive.private | 2118 | return not self.obj.archive.private |
1086 | @@ -2262,8 +2170,7 @@ | |||
1087 | 2262 | usedfor = IMailingListSet | 2170 | usedfor = IMailingListSet |
1088 | 2263 | 2171 | ||
1089 | 2264 | def checkAuthenticated(self, user): | 2172 | def checkAuthenticated(self, user): |
1092 | 2265 | experts = getUtility(ILaunchpadCelebrities).mailing_list_experts | 2173 | return user.in_mailing_list_experts |
1091 | 2266 | return user.inTeam(experts) | ||
1093 | 2267 | 2174 | ||
1094 | 2268 | 2175 | ||
1095 | 2269 | class ConfigureTeamMailingList(AuthorizationBase): | 2176 | class ConfigureTeamMailingList(AuthorizationBase): |
1096 | @@ -2284,12 +2191,10 @@ | |||
1097 | 2284 | """ | 2191 | """ |
1098 | 2285 | # The team owner, the Launchpad mailing list experts and the Launchpad | 2192 | # The team owner, the Launchpad mailing list experts and the Launchpad |
1099 | 2286 | # administrators can all view a team's +mailinglist page. | 2193 | # administrators can all view a team's +mailinglist page. |
1100 | 2287 | celebrities = getUtility(ILaunchpadCelebrities) | ||
1101 | 2288 | team = ITeam(self.obj) | 2194 | team = ITeam(self.obj) |
1106 | 2289 | return ( | 2195 | is_team_owner = ( |
1107 | 2290 | (team is not None and team in user.getAdministratedTeams()) or | 2196 | team is not None and team in user.person.getAdministratedTeams()) |
1108 | 2291 | user.inTeam(celebrities.admin) or | 2197 | return is_team_owner or user.in_admin or user.in_mailing_list_experts |
1105 | 2292 | user.inTeam(celebrities.mailing_list_experts)) | ||
1109 | 2293 | 2198 | ||
1110 | 2294 | 2199 | ||
1111 | 2295 | class ViewEmailAddress(AuthorizationBase): | 2200 | class ViewEmailAddress(AuthorizationBase): |
1112 | @@ -2319,15 +2224,14 @@ | |||
1113 | 2319 | self.obj.person.hide_email_addresses): | 2224 | self.obj.person.hide_email_addresses): |
1114 | 2320 | return True | 2225 | return True |
1115 | 2321 | 2226 | ||
1117 | 2322 | user = IPerson(account, None) | 2227 | user = IPersonRoles(IPerson(account, None), None) |
1118 | 2323 | if user is None: | 2228 | if user is None: |
1119 | 2324 | return False | 2229 | return False |
1120 | 2325 | 2230 | ||
1121 | 2326 | celebrities = getUtility(ILaunchpadCelebrities) | ||
1122 | 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) |
1126 | 2328 | or user.inTeam(celebrities.commercial_admin) | 2232 | or user.in_commercial_admin |
1127 | 2329 | or user.inTeam(celebrities.registry_experts) | 2233 | or user.in_registry_experts |
1128 | 2330 | or user.inTeam(celebrities.admin)) | 2234 | or user.in_admin) |
1129 | 2331 | 2235 | ||
1130 | 2332 | 2236 | ||
1131 | 2333 | class EditEmailAddress(EditByOwnersOrAdmins): | 2237 | class EditEmailAddress(EditByOwnersOrAdmins): |
1132 | @@ -2348,10 +2252,7 @@ | |||
1133 | 2348 | 2252 | ||
1134 | 2349 | def checkAuthenticated(self, user): | 2253 | def checkAuthenticated(self, user): |
1135 | 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.""" |
1140 | 2351 | celebrities = getUtility(ILaunchpadCelebrities) | 2255 | return user.in_admin or user.in_ubuntu_techboard |
1137 | 2352 | return ( | ||
1138 | 2353 | user.inTeam(celebrities.admin) | ||
1139 | 2354 | or user.inTeam(celebrities.ubuntu_techboard)) | ||
1141 | 2355 | 2256 | ||
1142 | 2356 | 2257 | ||
1143 | 2357 | class LinkOfficialSourcePackageBranches(AuthorizationBase): | 2258 | class LinkOfficialSourcePackageBranches(AuthorizationBase): |
1144 | @@ -2367,10 +2268,7 @@ | |||
1145 | 2367 | return False | 2268 | return False |
1146 | 2368 | 2269 | ||
1147 | 2369 | def checkAuthenticated(self, user): | 2270 | def checkAuthenticated(self, user): |
1152 | 2370 | celebrities = getUtility(ILaunchpadCelebrities) | 2271 | return user.in_ubuntu_branches or user.in_admin |
1149 | 2371 | return ( | ||
1150 | 2372 | user.inTeam(celebrities.ubuntu_branches) | ||
1151 | 2373 | or user.inTeam(celebrities.admin)) | ||
1153 | 2374 | 2272 | ||
1154 | 2375 | 2273 | ||
1155 | 2376 | class ChangeOfficialSourcePackageBranchLinks(AuthorizationBase): | 2274 | class ChangeOfficialSourcePackageBranchLinks(AuthorizationBase): |
1156 | @@ -2386,10 +2284,7 @@ | |||
1157 | 2386 | return False | 2284 | return False |
1158 | 2387 | 2285 | ||
1159 | 2388 | def checkAuthenticated(self, user): | 2286 | def checkAuthenticated(self, user): |
1164 | 2389 | celebrities = getUtility(ILaunchpadCelebrities) | 2287 | return user.in_ubuntu_branches or user.in_admin |
1161 | 2390 | return ( | ||
1162 | 2391 | user.inTeam(celebrities.ubuntu_branches) | ||
1163 | 2392 | or user.inTeam(celebrities.admin)) | ||
1165 | 2393 | 2288 | ||
1166 | 2394 | 2289 | ||
1167 | 2395 | class EditPackageset(AuthorizationBase): | 2290 | class EditPackageset(AuthorizationBase): |
1168 | @@ -2398,10 +2293,7 @@ | |||
1169 | 2398 | 2293 | ||
1170 | 2399 | def checkAuthenticated(self, user): | 2294 | def checkAuthenticated(self, user): |
1171 | 2400 | """The owner of a package set can edit the object.""" | 2295 | """The owner of a package set can edit the object.""" |
1176 | 2401 | celebrities = getUtility(ILaunchpadCelebrities) | 2296 | return user.isOwner(self.obj) or user.in_admin |
1173 | 2402 | return ( | ||
1174 | 2403 | user.inTeam(self.obj.owner) | ||
1175 | 2404 | or user.inTeam(celebrities.admin)) | ||
1177 | 2405 | 2297 | ||
1178 | 2406 | 2298 | ||
1179 | 2407 | class EditPackagesetSet(AuthorizationBase): | 2299 | class EditPackagesetSet(AuthorizationBase): |
1180 | @@ -2410,7 +2302,4 @@ | |||
1181 | 2410 | 2302 | ||
1182 | 2411 | def checkAuthenticated(self, user): | 2303 | def checkAuthenticated(self, user): |
1183 | 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.""" |
1188 | 2413 | celebrities = getUtility(ILaunchpadCelebrities) | 2305 | return user.in_admin or user.in_ubuntu_techboard |
1185 | 2414 | return ( | ||
1186 | 2415 | user.inTeam(celebrities.admin) | ||
1187 | 2416 | or user.inTeam(celebrities.ubuntu_techboard)) | ||
1189 | 2417 | 2306 | ||
1190 | === modified file 'lib/canonical/launchpad/tests/test_personroles.py' | |||
1191 | --- lib/canonical/launchpad/tests/test_personroles.py 2010-01-08 16:16:50 +0000 | |||
1192 | +++ lib/canonical/launchpad/tests/test_personroles.py 2010-01-15 07:14:13 +0000 | |||
1193 | @@ -103,14 +103,20 @@ | |||
1194 | 103 | roles = IPersonRoles(self.person) | 103 | roles = IPersonRoles(self.person) |
1195 | 104 | self.assertTrue(roles.isDriver(sprint)) | 104 | self.assertTrue(roles.isDriver(sprint)) |
1196 | 105 | 105 | ||
1200 | 106 | def test_isDriver_multiple_drivers(self): | 106 | def test_isOneOfDrivers(self): |
1201 | 107 | # The person can be one of multiple drivers of if a product and its | 107 | # The person can be one of multiple drivers of if an object |
1202 | 108 | # series each has a driver. | 108 | # implements IHasDrivers. |
1203 | 109 | productseries = self.factory.makeProductSeries() | 109 | productseries = self.factory.makeProductSeries() |
1204 | 110 | productseries.product.driver = self.person | 110 | productseries.product.driver = self.person |
1205 | 111 | productseries.driver = self.factory.makePerson() | 111 | productseries.driver = self.factory.makePerson() |
1206 | 112 | roles = IPersonRoles(self.person) | 112 | roles = IPersonRoles(self.person) |
1208 | 113 | self.assertTrue(roles.isDriver(productseries)) | 113 | self.assertTrue(roles.isOneOfDrivers(productseries)) |
1209 | 114 | |||
1210 | 115 | def test_isOneOfDrivers_no_drivers(self): | ||
1211 | 116 | # If the object does not implement IHasDrivers, False is returned. | ||
1212 | 117 | sprint = self.factory.makeSprint() | ||
1213 | 118 | roles = IPersonRoles(self.person) | ||
1214 | 119 | self.assertFalse(roles.isOneOfDrivers(sprint)) | ||
1215 | 114 | 120 | ||
1216 | 115 | def test_isOneOf(self): | 121 | def test_isOneOf(self): |
1217 | 116 | # Objects may have multiple roles that a person can fulfill. | 122 | # Objects may have multiple roles that a person can fulfill. |
1218 | 117 | 123 | ||
1219 | === modified file 'lib/canonical/launchpad/utilities/personroles.py' | |||
1220 | --- lib/canonical/launchpad/utilities/personroles.py 2010-01-06 14:00:20 +0000 | |||
1221 | +++ lib/canonical/launchpad/utilities/personroles.py 2010-01-15 07:14:13 +0000 | |||
1222 | @@ -9,7 +9,7 @@ | |||
1223 | 9 | from zope.interface import implements | 9 | from zope.interface import implements |
1224 | 10 | from zope.component import adapts, getUtility | 10 | from zope.component import adapts, getUtility |
1225 | 11 | from canonical.launchpad.interfaces import ( | 11 | from canonical.launchpad.interfaces import ( |
1227 | 12 | ILaunchpadCelebrities, IPersonRoles) | 12 | IHasDrivers, ILaunchpadCelebrities, IPersonRoles) |
1228 | 13 | 13 | ||
1229 | 14 | from lp.registry.interfaces.person import IPerson | 14 | from lp.registry.interfaces.person import IPerson |
1230 | 15 | 15 | ||
1231 | @@ -26,10 +26,14 @@ | |||
1232 | 26 | def __getattr__(self, name): | 26 | def __getattr__(self, name): |
1233 | 27 | """Handle all in_* attributes.""" | 27 | """Handle all in_* attributes.""" |
1234 | 28 | prefix = 'in_' | 28 | prefix = 'in_' |
1235 | 29 | errortext = "'PersonRoles' object has no attribute '%s'" % name | ||
1236 | 29 | if not name.startswith(prefix): | 30 | if not name.startswith(prefix): |
1238 | 30 | raise AttributeError | 31 | raise AttributeError(errortext) |
1239 | 31 | attribute = name[len(prefix):] | 32 | attribute = name[len(prefix):] |
1241 | 32 | return self.person.inTeam(getattr(self._celebrities, attribute)) | 33 | try: |
1242 | 34 | return self.person.inTeam(getattr(self._celebrities, attribute)) | ||
1243 | 35 | except AttributeError: | ||
1244 | 36 | raise AttributeError(errortext) | ||
1245 | 33 | 37 | ||
1246 | 34 | def isOwner(self, obj): | 38 | def isOwner(self, obj): |
1247 | 35 | """See IPersonRoles.""" | 39 | """See IPersonRoles.""" |
1248 | @@ -37,10 +41,13 @@ | |||
1249 | 37 | 41 | ||
1250 | 38 | def isDriver(self, obj): | 42 | def isDriver(self, obj): |
1251 | 39 | """See IPersonRoles.""" | 43 | """See IPersonRoles.""" |
1256 | 40 | drivers = getattr(obj, 'drivers', None) | 44 | return self.person.inTeam(obj.driver) |
1257 | 41 | if drivers is None: | 45 | |
1258 | 42 | return self.person.inTeam(obj.driver) | 46 | def isOneOfDrivers(self, obj): |
1259 | 43 | for driver in drivers: | 47 | """See IPersonRoles.""" |
1260 | 48 | if not IHasDrivers.providedBy(obj): | ||
1261 | 49 | return self.isDriver(obj) | ||
1262 | 50 | for driver in obj.drivers: | ||
1263 | 44 | if self.person.inTeam(driver): | 51 | if self.person.inTeam(driver): |
1264 | 45 | return True | 52 | return True |
1265 | 46 | return False | 53 | return False |
1266 | 47 | 54 | ||
1267 | === modified file 'lib/lp/code/doc/branch-visibility.txt' | |||
1268 | --- lib/lp/code/doc/branch-visibility.txt 2009-08-13 15:12:16 +0000 | |||
1269 | +++ lib/lp/code/doc/branch-visibility.txt 2010-01-15 07:14:13 +0000 | |||
1270 | @@ -66,7 +66,7 @@ | |||
1271 | 66 | >>> access = AccessBranch(branch) | 66 | >>> access = AccessBranch(branch) |
1272 | 67 | >>> access.checkUnauthenticated() | 67 | >>> access.checkUnauthenticated() |
1273 | 68 | True | 68 | True |
1275 | 69 | >>> access.checkAuthenticated(no_priv_person) | 69 | >>> access.checkAccountAuthenticated(no_priv_person.account) |
1276 | 70 | True | 70 | True |
1277 | 71 | 71 | ||
1278 | 72 | Branches that are private are accessible by the owner and subscribers. | 72 | Branches that are private are accessible by the owner and subscribers. |
1279 | @@ -83,7 +83,7 @@ | |||
1280 | 83 | False | 83 | False |
1281 | 84 | >>> branch.owner == no_priv_person | 84 | >>> branch.owner == no_priv_person |
1282 | 85 | True | 85 | True |
1284 | 86 | >>> access.checkAuthenticated(no_priv_person) | 86 | >>> access.checkAccountAuthenticated(no_priv_person.account) |
1285 | 87 | True | 87 | True |
1286 | 88 | 88 | ||
1287 | 89 | Check the configuration of the AccessBranch authorization. | 89 | Check the configuration of the AccessBranch authorization. |
1288 | @@ -108,7 +108,7 @@ | |||
1289 | 108 | >>> lp_admins = getUtility(ILaunchpadCelebrities).admin | 108 | >>> lp_admins = getUtility(ILaunchpadCelebrities).admin |
1290 | 109 | >>> mark.inTeam(lp_admins) | 109 | >>> mark.inTeam(lp_admins) |
1291 | 110 | True | 110 | True |
1293 | 111 | >>> access.checkAuthenticated(mark) | 111 | >>> access.checkAccountAuthenticated(mark.account) |
1294 | 112 | True | 112 | True |
1295 | 113 | 113 | ||
1296 | 114 | 114 | ||
1297 | @@ -125,7 +125,7 @@ | |||
1298 | 125 | True | 125 | True |
1299 | 126 | >>> jdub.inTeam(lp_admins) | 126 | >>> jdub.inTeam(lp_admins) |
1300 | 127 | False | 127 | False |
1302 | 128 | >>> access.checkAuthenticated(jdub) | 128 | >>> access.checkAccountAuthenticated(jdub.account) |
1303 | 129 | False | 129 | False |
1304 | 130 | 130 | ||
1305 | 131 | Subscribing the Ubuntu team to the branch will allow Jeff to have access | 131 | Subscribing the Ubuntu team to the branch will allow Jeff to have access |
1306 | @@ -141,7 +141,7 @@ | |||
1307 | 141 | ... CodeReviewNotificationLevel.NOEMAIL) | 141 | ... CodeReviewNotificationLevel.NOEMAIL) |
1308 | 142 | <BranchSubscription ...> | 142 | <BranchSubscription ...> |
1309 | 143 | 143 | ||
1311 | 144 | >>> access.checkAuthenticated(jdub) | 144 | >>> access.checkAccountAuthenticated(jdub.account) |
1312 | 145 | True | 145 | True |
1313 | 146 | 146 | ||
1314 | 147 | 147 | ||
1315 | @@ -153,7 +153,7 @@ | |||
1316 | 153 | >>> ddaa = person_set.getByName('ddaa') | 153 | >>> ddaa = person_set.getByName('ddaa') |
1317 | 154 | >>> ddaa.inTeam(lp_admins) | 154 | >>> ddaa.inTeam(lp_admins) |
1318 | 155 | False | 155 | False |
1320 | 156 | >>> access.checkAuthenticated(ddaa) | 156 | >>> access.checkAccountAuthenticated(ddaa.account) |
1321 | 157 | False | 157 | False |
1322 | 158 | 158 | ||
1323 | 159 | 159 |
= 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 "checkAuthentic ated" 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 "checkAuthentic ated" on an object that implements "IAuthorization". "checkAuthentic ated" has been replaced by "checkAccountAu thenticated" 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 checkAccountAut henticated.
* 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: AuthorizationBa se.checkAccount Authenticated applies the IPersonRoles adapter to the IPerson object which it derives from the account. So unless checkAccountAut henticated gets overwritten, checkAuthenticated reveives an IPersonRoles object instead of an IPerson object. celebrity. some_celeb) with user.in_some_celeb.
* Replaced all calls to user.inTeam(
* 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 checkAccountAut henticated.
== 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: /launchpad/ security. py /launchpad/ doc/hasowne. ..
lib/canonical
lib/canonical