Merge lp:~jelmer/launchpad/refactor-permissions into lp:launchpad
- refactor-permissions
- Merge into devel
Proposed by
Jelmer Vernooij
Status: | Merged |
---|---|
Approved by: | Brad Crittenden |
Approved revision: | no longer in the source branch. |
Merged at revision: | 10869 |
Proposed branch: | lp:~jelmer/launchpad/refactor-permissions |
Merge into: | lp:launchpad |
Diff against target: |
1138 lines (+356/-318) 19 files modified
lib/canonical/launchpad/security.py (+7/-8) lib/lp/archiveuploader/nascentupload.py (+2/-3) lib/lp/archiveuploader/permission.py (+0/-246) lib/lp/archiveuploader/tests/nascentupload-packageset.txt (+2/-2) lib/lp/archiveuploader/tests/test_permission.py (+12/-14) lib/lp/bugs/model/bugnomination.py (+1/-1) lib/lp/code/model/recipebuilder.py (+2/-3) lib/lp/code/model/sourcepackagerecipe.py (+3/-4) lib/lp/code/model/tests/test_sourcepackagerecipe.py (+2/-3) lib/lp/code/tests/test_branch.py (+4/-5) lib/lp/soyuz/browser/archive.py (+2/-1) lib/lp/soyuz/doc/archive.txt (+11/-11) lib/lp/soyuz/doc/archivepermission.txt (+1/-1) lib/lp/soyuz/doc/nascentupload.txt (+2/-3) lib/lp/soyuz/interfaces/archive.py (+136/-1) lib/lp/soyuz/model/archive.py (+94/-5) lib/lp/soyuz/model/archivepermission.py (+2/-2) lib/lp/soyuz/model/binarypackagebuildbehavior.py (+2/-3) lib/lp/soyuz/tests/test_archive.py (+71/-2) |
To merge this branch: | bzr merge lp:~jelmer/launchpad/refactor-permissions |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brad Crittenden (community) | code | Approve | |
Review via email: mp+23216@code.launchpad.net |
Commit message
Move archive permission checking functions onto Archive.
Description of the change
This move some of the permission checking functions for archives on the Archive method and removes a couple of duplicate functions in the process.
This is in preparation of exposing these methods over the web API, as requested by james_w.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/canonical/launchpad/security.py' | |||
2 | --- lib/canonical/launchpad/security.py 2010-04-26 15:02:03 +0000 | |||
3 | +++ lib/canonical/launchpad/security.py 2010-05-11 14:12:39 +0000 | |||
4 | @@ -12,8 +12,6 @@ | |||
5 | 12 | from zope.component import getAdapter, getUtility | 12 | from zope.component import getAdapter, getUtility |
6 | 13 | 13 | ||
7 | 14 | from canonical.launchpad.interfaces.account import IAccount | 14 | from canonical.launchpad.interfaces.account import IAccount |
8 | 15 | from lp.archiveuploader.permission import ( | ||
9 | 16 | can_upload_to_archive, check_upload_to_archive) | ||
10 | 17 | from canonical.launchpad.interfaces.emailaddress import IEmailAddress | 15 | from canonical.launchpad.interfaces.emailaddress import IEmailAddress |
11 | 18 | from lp.registry.interfaces.announcement import IAnnouncement | 16 | from lp.registry.interfaces.announcement import IAnnouncement |
12 | 19 | from lp.soyuz.interfaces.archive import IArchive | 17 | from lp.soyuz.interfaces.archive import IArchive |
13 | @@ -1475,9 +1473,9 @@ | |||
14 | 1475 | # user to retry build if so. | 1473 | # user to retry build if so. |
15 | 1476 | # strict_component is True because the source package already exists, | 1474 | # strict_component is True because the source package already exists, |
16 | 1477 | # otherwise, how can they give it back? | 1475 | # otherwise, how can they give it back? |
18 | 1478 | check_perms = check_upload_to_archive( | 1476 | check_perms = self.obj.archive.checkUpload( |
19 | 1479 | user.person, self.obj.distroseries, | 1477 | user.person, self.obj.distroseries, |
21 | 1480 | self.obj.sourcepackagerelease.sourcepackagename, self.obj.archive, | 1478 | self.obj.sourcepackagerelease.sourcepackagename, |
22 | 1481 | self.obj.current_component, self.obj.pocket, | 1479 | self.obj.current_component, self.obj.pocket, |
23 | 1482 | strict_component=True) | 1480 | strict_component=True) |
24 | 1483 | return check_perms == None | 1481 | return check_perms == None |
25 | @@ -1718,7 +1716,8 @@ | |||
26 | 1718 | # one combination that allows us to upload the corresponding source | 1716 | # one combination that allows us to upload the corresponding source |
27 | 1719 | # package. | 1717 | # package. |
28 | 1720 | for ssp in ssp_list: | 1718 | for ssp in ssp_list: |
30 | 1721 | if can_upload_to_archive(person_role.person, ssp): | 1719 | archive = ssp.sourcepackage.get_default_archive() |
31 | 1720 | if archive.canUploadSuiteSourcePackage(person_role.person, ssp): | ||
32 | 1722 | return True | 1721 | return True |
33 | 1723 | return False | 1722 | return False |
34 | 1724 | 1723 | ||
35 | @@ -2047,7 +2046,7 @@ | |||
36 | 2047 | return True | 2046 | return True |
37 | 2048 | 2047 | ||
38 | 2049 | # Uploaders can view private PPAs. | 2048 | # Uploaders can view private PPAs. |
40 | 2050 | if self.obj.is_ppa and self.obj.canUpload(user.person): | 2049 | if self.obj.is_ppa and self.obj.checkArchivePermission(user.person): |
41 | 2051 | return True | 2050 | return True |
42 | 2052 | 2051 | ||
43 | 2053 | return False | 2052 | return False |
44 | @@ -2062,7 +2061,7 @@ | |||
45 | 2062 | 2061 | ||
46 | 2063 | No one can upload to disabled archives. | 2062 | No one can upload to disabled archives. |
47 | 2064 | 2063 | ||
49 | 2065 | PPA upload rights are managed via `IArchive.canUpload`; | 2064 | PPA upload rights are managed via `IArchive.checkArchivePermission`; |
50 | 2066 | 2065 | ||
51 | 2067 | Appending to PRIMARY, PARTNER or COPY archives is restricted to owners. | 2066 | Appending to PRIMARY, PARTNER or COPY archives is restricted to owners. |
52 | 2068 | 2067 | ||
53 | @@ -2079,7 +2078,7 @@ | |||
54 | 2079 | if user.inTeam(self.obj.owner): | 2078 | if user.inTeam(self.obj.owner): |
55 | 2080 | return True | 2079 | return True |
56 | 2081 | 2080 | ||
58 | 2082 | if self.obj.is_ppa and self.obj.canUpload(user.person): | 2081 | if self.obj.is_ppa and self.obj.checkArchivePermission(user.person): |
59 | 2083 | return True | 2082 | return True |
60 | 2084 | 2083 | ||
61 | 2085 | celebrities = getUtility(ILaunchpadCelebrities) | 2084 | celebrities = getUtility(ILaunchpadCelebrities) |
62 | 2086 | 2085 | ||
63 | === modified file 'lib/lp/archiveuploader/nascentupload.py' | |||
64 | --- lib/lp/archiveuploader/nascentupload.py 2010-02-26 16:52:46 +0000 | |||
65 | +++ lib/lp/archiveuploader/nascentupload.py 2010-05-11 14:12:39 +0000 | |||
66 | @@ -28,7 +28,6 @@ | |||
67 | 28 | from lp.archiveuploader.nascentuploadfile import ( | 28 | from lp.archiveuploader.nascentuploadfile import ( |
68 | 29 | UploadError, UploadWarning, CustomUploadFile, SourceUploadFile, | 29 | UploadError, UploadWarning, CustomUploadFile, SourceUploadFile, |
69 | 30 | BaseBinaryUploadFile) | 30 | BaseBinaryUploadFile) |
70 | 31 | from lp.archiveuploader.permission import check_upload_to_archive | ||
71 | 32 | from lp.archiveuploader.utils import determine_source_file_type | 31 | from lp.archiveuploader.utils import determine_source_file_type |
72 | 33 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 32 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
73 | 34 | from lp.registry.interfaces.sourcepackage import SourcePackageFileType | 33 | from lp.registry.interfaces.sourcepackage import SourcePackageFileType |
74 | @@ -489,8 +488,8 @@ | |||
75 | 489 | source_name = getUtility( | 488 | source_name = getUtility( |
76 | 490 | ISourcePackageNameSet).queryByName(self.changes.dsc.package) | 489 | ISourcePackageNameSet).queryByName(self.changes.dsc.package) |
77 | 491 | 490 | ||
80 | 492 | rejection_reason = check_upload_to_archive( | 491 | rejection_reason = archive.checkUpload( |
81 | 493 | uploader, self.policy.distroseries, source_name, archive, | 492 | uploader, self.policy.distroseries, source_name, |
82 | 494 | self.changes.dsc.component, self.policy.pocket, not self.is_new) | 493 | self.changes.dsc.component, self.policy.pocket, not self.is_new) |
83 | 495 | 494 | ||
84 | 496 | if rejection_reason is not None: | 495 | if rejection_reason is not None: |
85 | 497 | 496 | ||
86 | === removed file 'lib/lp/archiveuploader/permission.py' | |||
87 | --- lib/lp/archiveuploader/permission.py 2010-02-02 14:01:02 +0000 | |||
88 | +++ lib/lp/archiveuploader/permission.py 1970-01-01 00:00:00 +0000 | |||
89 | @@ -1,246 +0,0 @@ | |||
90 | 1 | # Copyright 2009 Canonical Ltd. This software is licensed under the | ||
91 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
92 | 3 | |||
93 | 4 | """Permissions for uploading a package to an archive.""" | ||
94 | 5 | |||
95 | 6 | __metaclass__ = type | ||
96 | 7 | __all__ = [ | ||
97 | 8 | 'CannotUploadToArchive', | ||
98 | 9 | 'CannotUploadToPPA', | ||
99 | 10 | 'can_upload_to_archive', | ||
100 | 11 | 'check_upload_to_archive', | ||
101 | 12 | 'check_upload_to_pocket', | ||
102 | 13 | 'components_valid_for', | ||
103 | 14 | 'verify_upload', | ||
104 | 15 | ] | ||
105 | 16 | |||
106 | 17 | from zope.component import getUtility | ||
107 | 18 | |||
108 | 19 | from lp.registry.interfaces.pocket import PackagePublishingPocket | ||
109 | 20 | from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet | ||
110 | 21 | from lp.soyuz.interfaces.archive import ArchivePurpose | ||
111 | 22 | |||
112 | 23 | |||
113 | 24 | class CannotUploadToArchive(Exception): | ||
114 | 25 | """A reason for not being able to upload to an archive.""" | ||
115 | 26 | |||
116 | 27 | _fmt = '%(person)s has no upload rights to %(archive)s.' | ||
117 | 28 | |||
118 | 29 | def __init__(self, **args): | ||
119 | 30 | """Construct a `CannotUploadToArchive`.""" | ||
120 | 31 | Exception.__init__(self, self._fmt % args) | ||
121 | 32 | |||
122 | 33 | |||
123 | 34 | class CannotUploadToPocket(Exception): | ||
124 | 35 | """Returned when a pocket is closed for uploads.""" | ||
125 | 36 | |||
126 | 37 | def __init__(self, distroseries, pocket): | ||
127 | 38 | Exception.__init__(self, | ||
128 | 39 | "Not permitted to upload to the %s pocket in a series in the " | ||
129 | 40 | "'%s' state." % (pocket.name, distroseries.status.name)) | ||
130 | 41 | |||
131 | 42 | |||
132 | 43 | class CannotUploadToPPA(CannotUploadToArchive): | ||
133 | 44 | """Raised when a person cannot upload to a PPA.""" | ||
134 | 45 | |||
135 | 46 | _fmt = 'Signer has no upload rights to this PPA.' | ||
136 | 47 | |||
137 | 48 | |||
138 | 49 | class NoRightsForArchive(CannotUploadToArchive): | ||
139 | 50 | """Raised when a person has absolutely no upload rights to an archive.""" | ||
140 | 51 | |||
141 | 52 | _fmt = ( | ||
142 | 53 | "The signer of this package has no upload rights to this " | ||
143 | 54 | "distribution's primary archive. Did you mean to upload to " | ||
144 | 55 | "a PPA?") | ||
145 | 56 | |||
146 | 57 | |||
147 | 58 | class InsufficientUploadRights(CannotUploadToArchive): | ||
148 | 59 | """Raised when a person has insufficient upload rights.""" | ||
149 | 60 | _fmt = ( | ||
150 | 61 | "The signer of this package is lacking the upload rights for " | ||
151 | 62 | "the source package, component or package set in question.") | ||
152 | 63 | |||
153 | 64 | |||
154 | 65 | class NoRightsForComponent(CannotUploadToArchive): | ||
155 | 66 | """Raised when a person tries to upload to a component without permission. | ||
156 | 67 | """ | ||
157 | 68 | |||
158 | 69 | _fmt = ( | ||
159 | 70 | "Signer is not permitted to upload to the component '%(component)s'.") | ||
160 | 71 | |||
161 | 72 | def __init__(self, component): | ||
162 | 73 | CannotUploadToArchive.__init__(self, component=component.name) | ||
163 | 74 | |||
164 | 75 | |||
165 | 76 | class InvalidPocketForPPA(CannotUploadToArchive): | ||
166 | 77 | """PPAs only support some pockets.""" | ||
167 | 78 | |||
168 | 79 | _fmt = "PPA uploads must be for the RELEASE pocket." | ||
169 | 80 | |||
170 | 81 | |||
171 | 82 | class InvalidPocketForPartnerArchive(CannotUploadToArchive): | ||
172 | 83 | """Partner archives only support some pockets.""" | ||
173 | 84 | |||
174 | 85 | _fmt = "Partner uploads must be for the RELEASE or PROPOSED pocket." | ||
175 | 86 | |||
176 | 87 | |||
177 | 88 | class ArchiveDisabled(CannotUploadToArchive): | ||
178 | 89 | """Uploading to a disabled archive is not allowed.""" | ||
179 | 90 | |||
180 | 91 | _fmt = ("%(archive_name)s is disabled.") | ||
181 | 92 | |||
182 | 93 | def __init__(self, archive_name): | ||
183 | 94 | CannotUploadToArchive.__init__(self, archive_name=archive_name) | ||
184 | 95 | |||
185 | 96 | |||
186 | 97 | def components_valid_for(archive, person): | ||
187 | 98 | """Return the components that 'person' can upload to 'archive'. | ||
188 | 99 | |||
189 | 100 | :param archive: The `IArchive` than 'person' wishes to upload to. | ||
190 | 101 | :param person: An `IPerson` wishing to upload to an archive. | ||
191 | 102 | :return: A `set` of `IComponent`s that 'person' can upload to. | ||
192 | 103 | """ | ||
193 | 104 | permission_set = getUtility(IArchivePermissionSet) | ||
194 | 105 | permissions = permission_set.componentsForUploader(archive, person) | ||
195 | 106 | return set(permission.component for permission in permissions) | ||
196 | 107 | |||
197 | 108 | |||
198 | 109 | def can_upload_to_archive(person, suitesourcepackage, archive=None): | ||
199 | 110 | """Check if 'person' upload 'suitesourcepackage' to 'archive'. | ||
200 | 111 | |||
201 | 112 | :param person: An `IPerson` who might be uploading. | ||
202 | 113 | :param suitesourcepackage: An `ISuiteSourcePackage` to be uploaded. | ||
203 | 114 | :param archive: The `IArchive` to upload to. If not provided, defaults | ||
204 | 115 | to the default archive for the source package. (See | ||
205 | 116 | `ISourcePackage.get_default_archive`). | ||
206 | 117 | :return: True if they can, False if they cannot. | ||
207 | 118 | """ | ||
208 | 119 | sourcepackage = suitesourcepackage.sourcepackage | ||
209 | 120 | if archive is None: | ||
210 | 121 | archive = sourcepackage.get_default_archive() | ||
211 | 122 | pocket = suitesourcepackage.pocket | ||
212 | 123 | distroseries = sourcepackage.distroseries | ||
213 | 124 | sourcepackagename = sourcepackage.sourcepackagename | ||
214 | 125 | component = sourcepackage.latest_published_component | ||
215 | 126 | # strict_component is True because the source package already exists | ||
216 | 127 | # (otherwise we couldn't have a suitesourcepackage object) and | ||
217 | 128 | # nascentupload passes True as a matter of policy when the package exists. | ||
218 | 129 | reason = check_upload_to_archive( | ||
219 | 130 | person, distroseries, sourcepackagename, archive, component, pocket, | ||
220 | 131 | strict_component=True) | ||
221 | 132 | return reason is None | ||
222 | 133 | |||
223 | 134 | |||
224 | 135 | def check_upload_to_pocket(archive, distroseries, pocket): | ||
225 | 136 | """Check if uploading to a particular pocket in an archive is possible. | ||
226 | 137 | |||
227 | 138 | :param archive: A `IArchive` | ||
228 | 139 | :param distroseries: A `IDistroSeries` | ||
229 | 140 | :param pocket: A `PackagePublishingPocket` | ||
230 | 141 | """ | ||
231 | 142 | if archive.purpose == ArchivePurpose.PARTNER: | ||
232 | 143 | if pocket not in ( | ||
233 | 144 | PackagePublishingPocket.RELEASE, | ||
234 | 145 | PackagePublishingPocket.PROPOSED): | ||
235 | 146 | return InvalidPocketForPartnerArchive() | ||
236 | 147 | elif archive.is_ppa: | ||
237 | 148 | if pocket != PackagePublishingPocket.RELEASE: | ||
238 | 149 | return InvalidPocketForPPA() | ||
239 | 150 | else: | ||
240 | 151 | # Uploads to the partner archive are allowed in any distroseries | ||
241 | 152 | # state. | ||
242 | 153 | # XXX julian 2005-05-29 bug=117557: | ||
243 | 154 | # This is a greasy hack until bug #117557 is fixed. | ||
244 | 155 | if not distroseries.canUploadToPocket(pocket): | ||
245 | 156 | return CannotUploadToPocket(distroseries, pocket) | ||
246 | 157 | |||
247 | 158 | |||
248 | 159 | def check_upload_to_archive(person, distroseries, sourcepackagename, archive, | ||
249 | 160 | component, pocket, strict_component=True): | ||
250 | 161 | """Check if 'person' upload 'suitesourcepackage' to 'archive'. | ||
251 | 162 | |||
252 | 163 | :param person: An `IPerson` who might be uploading. | ||
253 | 164 | :param distroseries: The `IDistroSeries` being uploaded to. | ||
254 | 165 | :param sourcepackagename: The `ISourcePackageName` being uploaded. | ||
255 | 166 | :param archive: The `IArchive` to upload to. If not provided, defaults | ||
256 | 167 | to the default archive for the source package. (See | ||
257 | 168 | `ISourcePackage.get_default_archive`). | ||
258 | 169 | :param component: The `Component` being uploaded to. | ||
259 | 170 | :param pocket: The `PackagePublishingPocket` of 'distroseries' being | ||
260 | 171 | uploaded to. | ||
261 | 172 | :return: The reason for not being able to upload, None otherwise. | ||
262 | 173 | """ | ||
263 | 174 | reason = check_upload_to_pocket(archive, distroseries, pocket) | ||
264 | 175 | if reason is not None: | ||
265 | 176 | return reason | ||
266 | 177 | return verify_upload( | ||
267 | 178 | person, sourcepackagename, archive, component, distroseries, | ||
268 | 179 | strict_component) | ||
269 | 180 | |||
270 | 181 | |||
271 | 182 | def packagesets_valid_for(archive, person): | ||
272 | 183 | """Return the package sets that 'person' can upload to 'archive'. | ||
273 | 184 | |||
274 | 185 | :param archive: The `IArchive` than 'person' wishes to upload to. | ||
275 | 186 | :param person: An `IPerson` wishing to upload to an archive. | ||
276 | 187 | :return: A `set` of `IPackageset`s that 'person' can upload to. | ||
277 | 188 | """ | ||
278 | 189 | permission_set = getUtility(IArchivePermissionSet) | ||
279 | 190 | permissions = permission_set.packagesetsForUploader(archive, person) | ||
280 | 191 | return set(permission.packageset for permission in permissions) | ||
281 | 192 | |||
282 | 193 | |||
283 | 194 | def verify_upload(person, sourcepackagename, archive, component, | ||
284 | 195 | distroseries, strict_component=True): | ||
285 | 196 | """Can 'person' upload 'sourcepackagename' to 'archive'? | ||
286 | 197 | |||
287 | 198 | :param person: The `IPerson` trying to upload to the package. Referred to | ||
288 | 199 | as 'the signer' in upload code. | ||
289 | 200 | :param sourcepackagename: The source package being uploaded. None if the | ||
290 | 201 | package is new. | ||
291 | 202 | :param archive: The `IArchive` being uploaded to. | ||
292 | 203 | :param component: The `IComponent` that the source package belongs to. | ||
293 | 204 | :param distroseries: The upload's target distro series. | ||
294 | 205 | :param strict_component: True if access to the specific component for the | ||
295 | 206 | package is needed to upload to it. If False, then access to any | ||
296 | 207 | package will do. | ||
297 | 208 | :return: CannotUploadToArchive if 'person' cannot upload to the archive, | ||
298 | 209 | None otherwise. | ||
299 | 210 | """ | ||
300 | 211 | if not archive.enabled: | ||
301 | 212 | return ArchiveDisabled(archive.displayname) | ||
302 | 213 | |||
303 | 214 | # For PPAs... | ||
304 | 215 | if archive.is_ppa: | ||
305 | 216 | if not archive.canUpload(person): | ||
306 | 217 | return CannotUploadToPPA() | ||
307 | 218 | else: | ||
308 | 219 | return None | ||
309 | 220 | |||
310 | 221 | # For any other archive... | ||
311 | 222 | ap_set = getUtility(IArchivePermissionSet) | ||
312 | 223 | |||
313 | 224 | if sourcepackagename is not None: | ||
314 | 225 | # Check whether user may upload because he holds a permission for | ||
315 | 226 | # - the given source package directly | ||
316 | 227 | # - a package set in the correct distro series that includes the | ||
317 | 228 | # given source package | ||
318 | 229 | source_allowed = archive.canUpload(person, sourcepackagename) | ||
319 | 230 | set_allowed = ap_set.isSourceUploadAllowed( | ||
320 | 231 | archive, sourcepackagename, person, distroseries) | ||
321 | 232 | if source_allowed or set_allowed: | ||
322 | 233 | return None | ||
323 | 234 | |||
324 | 235 | if not components_valid_for(archive, person): | ||
325 | 236 | if not packagesets_valid_for(archive, person): | ||
326 | 237 | return NoRightsForArchive() | ||
327 | 238 | else: | ||
328 | 239 | return InsufficientUploadRights() | ||
329 | 240 | |||
330 | 241 | if (component is not None | ||
331 | 242 | and strict_component | ||
332 | 243 | and not archive.canUpload(person, component)): | ||
333 | 244 | return NoRightsForComponent(component) | ||
334 | 245 | |||
335 | 246 | return None | ||
336 | 247 | 0 | ||
337 | === modified file 'lib/lp/archiveuploader/tests/nascentupload-packageset.txt' | |||
338 | --- lib/lp/archiveuploader/tests/nascentupload-packageset.txt 2009-10-02 15:00:09 +0000 | |||
339 | +++ lib/lp/archiveuploader/tests/nascentupload-packageset.txt 2010-05-11 14:12:39 +0000 | |||
340 | @@ -39,8 +39,8 @@ | |||
341 | 39 | >>> bar_failed.is_rejected | 39 | >>> bar_failed.is_rejected |
342 | 40 | True | 40 | True |
343 | 41 | >>> print bar_failed.rejection_message | 41 | >>> print bar_failed.rejection_message |
346 | 42 | The signer of this package has no upload rights to this distribution's | 42 | The signer of this package is lacking the upload rights for the source |
347 | 43 | primary archive. Did you mean to upload to a PPA? | 43 | package, component or package set in question. |
348 | 44 | 44 | ||
349 | 45 | 45 | ||
350 | 46 | We can grant selective, package set based upload permissions to the user | 46 | We can grant selective, package set based upload permissions to the user |
351 | 47 | 47 | ||
352 | === modified file 'lib/lp/archiveuploader/tests/test_permission.py' | |||
353 | --- lib/lp/archiveuploader/tests/test_permission.py 2010-02-08 10:56:18 +0000 | |||
354 | +++ lib/lp/archiveuploader/tests/test_permission.py 2010-05-11 14:12:39 +0000 | |||
355 | @@ -12,8 +12,6 @@ | |||
356 | 12 | 12 | ||
357 | 13 | from canonical.testing import DatabaseFunctionalLayer | 13 | from canonical.testing import DatabaseFunctionalLayer |
358 | 14 | 14 | ||
359 | 15 | from lp.archiveuploader.permission import ( | ||
360 | 16 | check_upload_to_archive, components_valid_for) | ||
361 | 17 | from lp.registry.interfaces.series import SeriesStatus | 15 | from lp.registry.interfaces.series import SeriesStatus |
362 | 18 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 16 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
363 | 19 | from lp.soyuz.interfaces.archive import ArchivePurpose | 17 | from lp.soyuz.interfaces.archive import ArchivePurpose |
364 | @@ -29,21 +27,22 @@ | |||
365 | 29 | # By default, a person cannot upload to any component of an archive. | 27 | # By default, a person cannot upload to any component of an archive. |
366 | 30 | archive = self.factory.makeArchive() | 28 | archive = self.factory.makeArchive() |
367 | 31 | person = self.factory.makePerson() | 29 | person = self.factory.makePerson() |
369 | 32 | self.assertEqual(set(), components_valid_for(archive, person)) | 30 | self.assertEqual(set(), |
370 | 31 | set(archive.getComponentsForUploader(person))) | ||
371 | 33 | 32 | ||
372 | 34 | def test_components_for_person_with_permissions(self): | 33 | def test_components_for_person_with_permissions(self): |
373 | 35 | # If a person has been explicitly granted upload permissions to a | 34 | # If a person has been explicitly granted upload permissions to a |
374 | 36 | # particular component, then those components are included in | 35 | # particular component, then those components are included in |
376 | 37 | # components_valid_for. | 36 | # IArchive.getComponentsForUploader. |
377 | 38 | archive = self.factory.makeArchive() | 37 | archive = self.factory.makeArchive() |
378 | 39 | component = self.factory.makeComponent() | 38 | component = self.factory.makeComponent() |
379 | 40 | person = self.factory.makePerson() | 39 | person = self.factory.makePerson() |
380 | 41 | # Only admins or techboard members can add permissions normally. That | 40 | # Only admins or techboard members can add permissions normally. That |
381 | 42 | # restriction isn't relevant to this test. | 41 | # restriction isn't relevant to this test. |
382 | 43 | ap_set = removeSecurityProxy(getUtility(IArchivePermissionSet)) | 42 | ap_set = removeSecurityProxy(getUtility(IArchivePermissionSet)) |
386 | 44 | ap_set.newComponentUploader(archive, person, component) | 43 | ap = ap_set.newComponentUploader(archive, person, component) |
387 | 45 | self.assertEqual( | 44 | self.assertEqual(set([ap]), |
388 | 46 | set([component]), components_valid_for(archive, person)) | 45 | set(archive.getComponentsForUploader(person))) |
389 | 47 | 46 | ||
390 | 48 | 47 | ||
391 | 49 | class TestPermission(TestCaseWithFactory): | 48 | class TestPermission(TestCaseWithFactory): |
392 | @@ -67,8 +66,8 @@ | |||
393 | 67 | pocket = PackagePublishingPocket.RELEASE | 66 | pocket = PackagePublishingPocket.RELEASE |
394 | 68 | self.assertIs( | 67 | self.assertIs( |
395 | 69 | None, | 68 | None, |
398 | 70 | check_upload_to_archive( | 69 | archive.checkUpload( |
399 | 71 | person, distroseries, spn, archive, component, pocket, | 70 | person, distroseries, spn, component, pocket, |
400 | 72 | strict_component)) | 71 | strict_component)) |
401 | 73 | 72 | ||
402 | 74 | def assertCannotUpload(self, reason, person, spn, archive, component, | 73 | def assertCannotUpload(self, reason, person, spn, archive, component, |
403 | @@ -87,8 +86,8 @@ | |||
404 | 87 | if distroseries is None: | 86 | if distroseries is None: |
405 | 88 | distroseries = self.factory.makeDistroSeries() | 87 | distroseries = self.factory.makeDistroSeries() |
406 | 89 | pocket = PackagePublishingPocket.RELEASE | 88 | pocket = PackagePublishingPocket.RELEASE |
409 | 90 | exception = check_upload_to_archive( | 89 | exception = archive.checkUpload( |
410 | 91 | person, distroseries, spn, archive, component, pocket) | 90 | person, distroseries, spn, component, pocket) |
411 | 92 | self.assertEqual(reason, str(exception)) | 91 | self.assertEqual(reason, str(exception)) |
412 | 93 | 92 | ||
413 | 94 | def test_random_person_cannot_upload_to_ppa(self): | 93 | def test_random_person_cannot_upload_to_ppa(self): |
414 | @@ -137,9 +136,8 @@ | |||
415 | 137 | archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY) | 136 | archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY) |
416 | 138 | spn = self.factory.makeSourcePackageName() | 137 | spn = self.factory.makeSourcePackageName() |
417 | 139 | self.assertCannotUpload( | 138 | self.assertCannotUpload( |
421 | 140 | ("The signer of this package has no upload rights to this " | 139 | ("The signer of this package is lacking the upload rights for " |
422 | 141 | "distribution's primary archive. Did you mean to upload to " | 140 | "the source package, component or package set in question."), |
420 | 142 | "a PPA?"), | ||
423 | 143 | person, spn, archive, None) | 141 | person, spn, archive, None) |
424 | 144 | 142 | ||
425 | 145 | def test_package_specific_rights(self): | 143 | def test_package_specific_rights(self): |
426 | 146 | 144 | ||
427 | === modified file 'lib/lp/bugs/model/bugnomination.py' | |||
428 | --- lib/lp/bugs/model/bugnomination.py 2009-08-26 09:31:57 +0000 | |||
429 | +++ lib/lp/bugs/model/bugnomination.py 2010-05-11 14:12:39 +0000 | |||
430 | @@ -144,7 +144,7 @@ | |||
431 | 144 | upload_component.component | 144 | upload_component.component |
432 | 145 | for upload_component in distribution.uploaders) | 145 | for upload_component in distribution.uploaders) |
433 | 146 | for packagename_or_component in bug_packagenames_and_components: | 146 | for packagename_or_component in bug_packagenames_and_components: |
435 | 147 | if distribution.main_archive.canUpload( | 147 | if distribution.main_archive.checkArchivePermission( |
436 | 148 | person, packagename_or_component): | 148 | person, packagename_or_component): |
437 | 149 | return True | 149 | return True |
438 | 150 | 150 | ||
439 | 151 | 151 | ||
440 | === modified file 'lib/lp/code/model/recipebuilder.py' | |||
441 | --- lib/lp/code/model/recipebuilder.py 2010-04-29 14:54:05 +0000 | |||
442 | +++ lib/lp/code/model/recipebuilder.py 2010-05-11 14:12:39 +0000 | |||
443 | @@ -15,7 +15,6 @@ | |||
444 | 15 | 15 | ||
445 | 16 | from canonical.config import config | 16 | from canonical.config import config |
446 | 17 | 17 | ||
447 | 18 | from lp.archiveuploader.permission import check_upload_to_pocket | ||
448 | 19 | from lp.buildmaster.interfaces.buildfarmjobbehavior import ( | 18 | from lp.buildmaster.interfaces.buildfarmjobbehavior import ( |
449 | 20 | IBuildFarmJobBehavior) | 19 | IBuildFarmJobBehavior) |
450 | 21 | from lp.buildmaster.interfaces.builder import CannotBuild | 20 | from lp.buildmaster.interfaces.builder import CannotBuild |
451 | @@ -158,8 +157,8 @@ | |||
452 | 158 | 157 | ||
453 | 159 | # This should already have been checked earlier, but just check again | 158 | # This should already have been checked earlier, but just check again |
454 | 160 | # here in case of programmer errors. | 159 | # here in case of programmer errors. |
457 | 161 | reason = check_upload_to_pocket( | 160 | reason = build.archive.checkUploadToPocket( |
458 | 162 | build.archive, build.distroseries, build.pocket) | 161 | build.distroseries, build.pocket) |
459 | 163 | assert reason is None, ( | 162 | assert reason is None, ( |
460 | 164 | "%s (%s) can not be built for pocket %s: invalid pocket due " | 163 | "%s (%s) can not be built for pocket %s: invalid pocket due " |
461 | 165 | "to the series status of %s." % | 164 | "to the series status of %s." % |
462 | 166 | 165 | ||
463 | === modified file 'lib/lp/code/model/sourcepackagerecipe.py' | |||
464 | --- lib/lp/code/model/sourcepackagerecipe.py 2010-04-30 12:33:16 +0000 | |||
465 | +++ lib/lp/code/model/sourcepackagerecipe.py 2010-05-11 14:12:39 +0000 | |||
466 | @@ -22,7 +22,6 @@ | |||
467 | 22 | from canonical.database.datetimecol import UtcDateTimeCol | 22 | from canonical.database.datetimecol import UtcDateTimeCol |
468 | 23 | from canonical.launchpad.interfaces.lpstorm import IMasterStore | 23 | from canonical.launchpad.interfaces.lpstorm import IMasterStore |
469 | 24 | 24 | ||
470 | 25 | from lp.archiveuploader.permission import check_upload_to_archive | ||
471 | 26 | from lp.code.interfaces.sourcepackagerecipe import ( | 25 | from lp.code.interfaces.sourcepackagerecipe import ( |
472 | 27 | ISourcePackageRecipe, ISourcePackageRecipeSource, | 26 | ISourcePackageRecipe, ISourcePackageRecipeSource, |
473 | 28 | ISourcePackageRecipeData) | 27 | ISourcePackageRecipeData) |
474 | @@ -153,9 +152,9 @@ | |||
475 | 153 | if archive.purpose != ArchivePurpose.PPA: | 152 | if archive.purpose != ArchivePurpose.PPA: |
476 | 154 | raise NonPPABuildRequest | 153 | raise NonPPABuildRequest |
477 | 155 | component = getUtility(IComponentSet)["multiverse"] | 154 | component = getUtility(IComponentSet)["multiverse"] |
481 | 156 | reject_reason = check_upload_to_archive( | 155 | reject_reason = archive.checkUpload( |
482 | 157 | requester, distroseries, self.sourcepackagename, | 156 | requester, self.distroseries, self.sourcepackagename, |
483 | 158 | archive, component, pocket) | 157 | component, pocket) |
484 | 159 | if reject_reason is not None: | 158 | if reject_reason is not None: |
485 | 160 | raise reject_reason | 159 | raise reject_reason |
486 | 161 | 160 | ||
487 | 162 | 161 | ||
488 | === modified file 'lib/lp/code/model/tests/test_sourcepackagerecipe.py' | |||
489 | --- lib/lp/code/model/tests/test_sourcepackagerecipe.py 2010-04-30 12:33:16 +0000 | |||
490 | +++ lib/lp/code/model/tests/test_sourcepackagerecipe.py 2010-05-11 14:12:39 +0000 | |||
491 | @@ -24,8 +24,8 @@ | |||
492 | 24 | from canonical.testing.layers import DatabaseFunctionalLayer, AppServerLayer | 24 | from canonical.testing.layers import DatabaseFunctionalLayer, AppServerLayer |
493 | 25 | 25 | ||
494 | 26 | from canonical.launchpad.webapp.authorization import check_permission | 26 | from canonical.launchpad.webapp.authorization import check_permission |
497 | 27 | from lp.archiveuploader.permission import ( | 27 | from lp.soyuz.interfaces.archive import ( |
498 | 28 | ArchiveDisabled, CannotUploadToArchive, InvalidPocketForPPA) | 28 | ArchiveDisabled, ArchivePurpose, CannotUploadToArchive, InvalidPocketForPPA) |
499 | 29 | from lp.buildmaster.interfaces.buildqueue import IBuildQueue | 29 | from lp.buildmaster.interfaces.buildqueue import IBuildQueue |
500 | 30 | from lp.buildmaster.model.buildqueue import BuildQueue | 30 | from lp.buildmaster.model.buildqueue import BuildQueue |
501 | 31 | from lp.code.interfaces.sourcepackagerecipe import ( | 31 | from lp.code.interfaces.sourcepackagerecipe import ( |
502 | @@ -40,7 +40,6 @@ | |||
503 | 40 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 40 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
504 | 41 | from lp.services.job.interfaces.job import ( | 41 | from lp.services.job.interfaces.job import ( |
505 | 42 | IJob, JobStatus) | 42 | IJob, JobStatus) |
506 | 43 | from lp.soyuz.interfaces.archive import ArchivePurpose | ||
507 | 44 | from lp.testing import ( | 43 | from lp.testing import ( |
508 | 45 | ANONYMOUS, launchpadlib_for, login, login_person, person_logged_in, | 44 | ANONYMOUS, launchpadlib_for, login, login_person, person_logged_in, |
509 | 46 | TestCaseWithFactory, ws_object) | 45 | TestCaseWithFactory, ws_object) |
510 | 47 | 46 | ||
511 | === modified file 'lib/lp/code/tests/test_branch.py' | |||
512 | --- lib/lp/code/tests/test_branch.py 2010-03-18 17:49:21 +0000 | |||
513 | +++ lib/lp/code/tests/test_branch.py 2010-05-11 14:12:39 +0000 | |||
514 | @@ -12,7 +12,6 @@ | |||
515 | 12 | from canonical.launchpad.webapp.authorization import check_permission | 12 | from canonical.launchpad.webapp.authorization import check_permission |
516 | 13 | from canonical.testing import DatabaseFunctionalLayer | 13 | from canonical.testing import DatabaseFunctionalLayer |
517 | 14 | 14 | ||
518 | 15 | from lp.archiveuploader.permission import verify_upload | ||
519 | 16 | from lp.code.enums import ( | 15 | from lp.code.enums import ( |
520 | 17 | BranchSubscriptionDiffSize, BranchSubscriptionNotificationLevel, | 16 | BranchSubscriptionDiffSize, BranchSubscriptionNotificationLevel, |
521 | 18 | CodeReviewNotificationLevel) | 17 | CodeReviewNotificationLevel) |
522 | @@ -277,8 +276,8 @@ | |||
523 | 277 | distroseries = archive.distribution.currentseries | 276 | distroseries = archive.distribution.currentseries |
524 | 278 | self.assertIs( | 277 | self.assertIs( |
525 | 279 | None, | 278 | None, |
528 | 280 | verify_upload( | 279 | archive.verifyUpload( |
529 | 281 | person, spn, archive, component, distroseries, | 280 | person, spn, component, distroseries, |
530 | 282 | strict_component)) | 281 | strict_component)) |
531 | 283 | 282 | ||
532 | 284 | def assertCannotUpload( | 283 | def assertCannotUpload( |
533 | @@ -295,8 +294,8 @@ | |||
534 | 295 | """ | 294 | """ |
535 | 296 | if distroseries is None: | 295 | if distroseries is None: |
536 | 297 | distroseries = archive.distribution.currentseries | 296 | distroseries = archive.distribution.currentseries |
539 | 298 | exception = verify_upload( | 297 | exception = archive.verifyUpload( |
540 | 299 | person, spn, archive, component, distroseries) | 298 | person, spn, component, distroseries) |
541 | 300 | self.assertEqual(reason, str(exception)) | 299 | self.assertEqual(reason, str(exception)) |
542 | 301 | 300 | ||
543 | 302 | def test_package_upload_permissions_grant_branch_edit(self): | 301 | def test_package_upload_permissions_grant_branch_edit(self): |
544 | 303 | 302 | ||
545 | === modified file 'lib/lp/soyuz/browser/archive.py' | |||
546 | --- lib/lp/soyuz/browser/archive.py 2010-04-30 03:10:17 +0000 | |||
547 | +++ lib/lp/soyuz/browser/archive.py 2010-05-11 14:12:39 +0000 | |||
548 | @@ -1236,7 +1236,8 @@ | |||
549 | 1236 | # XXX cprov 2009-07-17 bug=385503: copies cannot be properly traced | 1236 | # XXX cprov 2009-07-17 bug=385503: copies cannot be properly traced |
550 | 1237 | # that's why we explicitly don't allow them do be done via the UI | 1237 | # that's why we explicitly don't allow them do be done via the UI |
551 | 1238 | # in main archives, only PPAs. | 1238 | # in main archives, only PPAs. |
553 | 1239 | return self.context.is_ppa and self.context.canUpload(self.user) | 1239 | return (self.context.is_ppa and |
554 | 1240 | self.context.checkArchivePermission(self.user)) | ||
555 | 1240 | 1241 | ||
556 | 1241 | def createDestinationArchiveField(self): | 1242 | def createDestinationArchiveField(self): |
557 | 1242 | """Create the 'destination_archive' field.""" | 1243 | """Create the 'destination_archive' field.""" |
558 | 1243 | 1244 | ||
559 | === modified file 'lib/lp/soyuz/doc/archive.txt' | |||
560 | --- lib/lp/soyuz/doc/archive.txt 2010-05-06 10:05:49 +0000 | |||
561 | +++ lib/lp/soyuz/doc/archive.txt 2010-05-11 14:12:39 +0000 | |||
562 | @@ -276,7 +276,7 @@ | |||
563 | 276 | 276 | ||
564 | 277 | Uploads to copy archives are not allowed. | 277 | Uploads to copy archives are not allowed. |
565 | 278 | 278 | ||
567 | 279 | >>> rebuild_archive.canUpload(cprov) | 279 | >>> rebuild_archive.checkArchivePermission(cprov) |
568 | 280 | Traceback (most recent call last): | 280 | Traceback (most recent call last): |
569 | 281 | ... | 281 | ... |
570 | 282 | AssertionError: Uploads to copy archives are not allowed. | 282 | AssertionError: Uploads to copy archives are not allowed. |
571 | @@ -2106,7 +2106,7 @@ | |||
572 | 2106 | 2106 | ||
573 | 2107 | == Archive Permission Checking == | 2107 | == Archive Permission Checking == |
574 | 2108 | 2108 | ||
576 | 2109 | IArchive has two public methods, canUpload() and canAdministerQueue() | 2109 | IArchive has two public methods, checkArchivePermission() and canAdministerQueue() |
577 | 2110 | that check a user's permission to upload and/or administer a | 2110 | that check a user's permission to upload and/or administer a |
578 | 2111 | distroseries upload queue respectively. See archivepermission.txt | 2111 | distroseries upload queue respectively. See archivepermission.txt |
579 | 2112 | for more details. | 2112 | for more details. |
580 | @@ -2114,40 +2114,40 @@ | |||
581 | 2114 | >>> ubuntu_team = getUtility(IPersonSet).getByName('ubuntu-team') | 2114 | >>> ubuntu_team = getUtility(IPersonSet).getByName('ubuntu-team') |
582 | 2115 | >>> carlos = getUtility(IPersonSet).getByName('carlos') | 2115 | >>> carlos = getUtility(IPersonSet).getByName('carlos') |
583 | 2116 | 2116 | ||
585 | 2117 | >>> ubuntu.main_archive.canUpload(carlos, main_component) | 2117 | >>> ubuntu.main_archive.checkArchivePermission(carlos, main_component) |
586 | 2118 | False | 2118 | False |
587 | 2119 | 2119 | ||
588 | 2120 | >>> ubuntu.main_archive.canAdministerQueue(carlos, main_component) | 2120 | >>> ubuntu.main_archive.canAdministerQueue(carlos, main_component) |
589 | 2121 | False | 2121 | False |
590 | 2122 | 2122 | ||
592 | 2123 | >>> ubuntu.main_archive.canUpload(ubuntu_team, main_component) | 2123 | >>> ubuntu.main_archive.checkArchivePermission(ubuntu_team, main_component) |
593 | 2124 | True | 2124 | True |
594 | 2125 | 2125 | ||
595 | 2126 | >>> ubuntu.main_archive.canAdministerQueue(ubuntu_team, main_component) | 2126 | >>> ubuntu.main_archive.canAdministerQueue(ubuntu_team, main_component) |
596 | 2127 | True | 2127 | True |
597 | 2128 | 2128 | ||
599 | 2129 | canUpload() can also check someone's permission to upload a specific | 2129 | checkArchivePermission() can also check someone's permission to upload a specific |
600 | 2130 | source package. Carlos, who does not have permission to upload to any | 2130 | source package. Carlos, who does not have permission to upload to any |
601 | 2131 | Ubuntu components, has permission to upload "mozilla-firefox". | 2131 | Ubuntu components, has permission to upload "mozilla-firefox". |
602 | 2132 | 2132 | ||
603 | 2133 | >>> from canonical.launchpad.interfaces import ISourcePackageNameSet | 2133 | >>> from canonical.launchpad.interfaces import ISourcePackageNameSet |
604 | 2134 | >>> mozilla = getUtility( | 2134 | >>> mozilla = getUtility( |
605 | 2135 | ... ISourcePackageNameSet).queryByName("mozilla-firefox") | 2135 | ... ISourcePackageNameSet).queryByName("mozilla-firefox") |
607 | 2136 | >>> ubuntu.main_archive.canUpload(carlos, mozilla) | 2136 | >>> ubuntu.main_archive.checkArchivePermission(carlos, mozilla) |
608 | 2137 | True | 2137 | True |
609 | 2138 | 2138 | ||
610 | 2139 | Cprov does not have permission, however. | 2139 | Cprov does not have permission, however. |
611 | 2140 | 2140 | ||
613 | 2141 | >>> ubuntu.main_archive.canUpload(cprov, mozilla) | 2141 | >>> ubuntu.main_archive.checkArchivePermission(cprov, mozilla) |
614 | 2142 | False | 2142 | False |
615 | 2143 | 2143 | ||
617 | 2144 | canUpload() also works in the same way for PPAs. By default, it allows | 2144 | checkArchivePermission() also works in the same way for PPAs. By default, it allows |
618 | 2145 | anyone in the PPA owning team to upload. | 2145 | anyone in the PPA owning team to upload. |
619 | 2146 | 2146 | ||
621 | 2147 | >>> cprov_archive.canUpload(cprov) | 2147 | >>> cprov_archive.checkArchivePermission(cprov) |
622 | 2148 | True | 2148 | True |
623 | 2149 | 2149 | ||
625 | 2150 | >>> cprov_archive.canUpload(carlos) | 2150 | >>> cprov_archive.checkArchivePermission(carlos) |
626 | 2151 | False | 2151 | False |
627 | 2152 | 2152 | ||
628 | 2153 | We can also create an ArchivePermission entry for carlos to be able to upload | 2153 | We can also create an ArchivePermission entry for carlos to be able to upload |
629 | @@ -2159,7 +2159,7 @@ | |||
630 | 2159 | 2159 | ||
631 | 2160 | Carlos can now upload to Joe's PPA: | 2160 | Carlos can now upload to Joe's PPA: |
632 | 2161 | 2161 | ||
634 | 2162 | >>> joes_ppa.canUpload(carlos) | 2162 | >>> joes_ppa.checkArchivePermission(carlos) |
635 | 2163 | True | 2163 | True |
636 | 2164 | 2164 | ||
637 | 2165 | Note that when creating a new permission, trying to specify a component other | 2165 | Note that when creating a new permission, trying to specify a component other |
638 | 2166 | 2166 | ||
639 | === modified file 'lib/lp/soyuz/doc/archivepermission.txt' | |||
640 | --- lib/lp/soyuz/doc/archivepermission.txt 2010-03-08 17:06:41 +0000 | |||
641 | +++ lib/lp/soyuz/doc/archivepermission.txt 2010-05-11 14:12:39 +0000 | |||
642 | @@ -108,7 +108,7 @@ | |||
643 | 108 | ... ubuntu) | 108 | ... ubuntu) |
644 | 109 | Traceback (most recent call last): | 109 | Traceback (most recent call last): |
645 | 110 | ... | 110 | ... |
647 | 111 | AssertionError: 'item' is not an IComponent, IPackageset or an | 111 | AssertionError: 'item' ... is not an IComponent, IPackageset or an |
648 | 112 | ISourcePackageName | 112 | ISourcePackageName |
649 | 113 | 113 | ||
650 | 114 | IArchivePermissionSet also has some helpers to make it very easy to | 114 | IArchivePermissionSet also has some helpers to make it very easy to |
651 | 115 | 115 | ||
652 | === modified file 'lib/lp/soyuz/doc/nascentupload.txt' | |||
653 | --- lib/lp/soyuz/doc/nascentupload.txt 2010-03-11 16:09:29 +0000 | |||
654 | +++ lib/lp/soyuz/doc/nascentupload.txt 2010-05-11 14:12:39 +0000 | |||
655 | @@ -879,9 +879,8 @@ | |||
656 | 879 | >>> bar_failed.is_rejected | 879 | >>> bar_failed.is_rejected |
657 | 880 | True | 880 | True |
658 | 881 | >>> print bar_failed.rejection_message | 881 | >>> print bar_failed.rejection_message |
662 | 882 | The signer of this package has no upload rights to this distribution's | 882 | The signer of this package is lacking the upload rights for the source |
663 | 883 | primary archive. Did you mean to upload to a PPA? | 883 | package, component or package set in question. |
661 | 884 | |||
664 | 885 | 884 | ||
665 | 886 | Even in a rejected upload using 'insecure' policy, the DSC signing key | 885 | Even in a rejected upload using 'insecure' policy, the DSC signing key |
666 | 887 | and the changesfile sigining key are stored in NascentUpload instance | 886 | and the changesfile sigining key are stored in NascentUpload instance |
667 | 888 | 887 | ||
668 | === modified file 'lib/lp/soyuz/interfaces/archive.py' | |||
669 | --- lib/lp/soyuz/interfaces/archive.py 2010-03-26 17:30:33 +0000 | |||
670 | +++ lib/lp/soyuz/interfaces/archive.py 2010-05-11 14:12:39 +0000 | |||
671 | @@ -11,12 +11,15 @@ | |||
672 | 11 | 'ALLOW_RELEASE_BUILDS', | 11 | 'ALLOW_RELEASE_BUILDS', |
673 | 12 | 'AlreadySubscribed', | 12 | 'AlreadySubscribed', |
674 | 13 | 'ArchiveDependencyError', | 13 | 'ArchiveDependencyError', |
675 | 14 | 'ArchiveDisabled', | ||
676 | 14 | 'ArchiveNotPrivate', | 15 | 'ArchiveNotPrivate', |
677 | 15 | 'ArchivePurpose', | 16 | 'ArchivePurpose', |
678 | 16 | 'ArchiveStatus', | 17 | 'ArchiveStatus', |
679 | 17 | 'CannotCopy', | 18 | 'CannotCopy', |
680 | 18 | 'CannotSwitchPrivacy', | 19 | 'CannotSwitchPrivacy', |
681 | 19 | 'ComponentNotFound', | 20 | 'ComponentNotFound', |
682 | 21 | 'CannotUploadToPPA', | ||
683 | 22 | 'CannotUploadToPocket', | ||
684 | 20 | 'DistroSeriesNotFound', | 23 | 'DistroSeriesNotFound', |
685 | 21 | 'IArchive', | 24 | 'IArchive', |
686 | 22 | 'IArchiveAppend', | 25 | 'IArchiveAppend', |
687 | @@ -26,10 +29,15 @@ | |||
688 | 26 | 'IArchivePublic', | 29 | 'IArchivePublic', |
689 | 27 | 'IArchiveSet', | 30 | 'IArchiveSet', |
690 | 28 | 'IDistributionArchive', | 31 | 'IDistributionArchive', |
691 | 32 | 'InsufficientUploadRights', | ||
692 | 29 | 'InvalidComponent', | 33 | 'InvalidComponent', |
693 | 34 | 'InvalidPocketForPartnerArchive', | ||
694 | 35 | 'InvalidPocketForPPA', | ||
695 | 30 | 'IPPA', | 36 | 'IPPA', |
696 | 31 | 'IPPAActivateForm', | 37 | 'IPPAActivateForm', |
697 | 32 | 'MAIN_ARCHIVE_PURPOSES', | 38 | 'MAIN_ARCHIVE_PURPOSES', |
698 | 39 | 'NoRightsForArchive', | ||
699 | 40 | 'NoRightsForComponent', | ||
700 | 33 | 'NoSuchPPA', | 41 | 'NoSuchPPA', |
701 | 34 | 'NoTokensForTeams', | 42 | 'NoTokensForTeams', |
702 | 35 | 'PocketNotFound', | 43 | 'PocketNotFound', |
703 | @@ -133,6 +141,79 @@ | |||
704 | 133 | webservice_error(400) # Bad request. | 141 | webservice_error(400) # Bad request. |
705 | 134 | 142 | ||
706 | 135 | 143 | ||
707 | 144 | class CannotUploadToArchive(Exception): | ||
708 | 145 | """A reason for not being able to upload to an archive.""" | ||
709 | 146 | |||
710 | 147 | _fmt = '%(person)s has no upload rights to %(archive)s.' | ||
711 | 148 | |||
712 | 149 | def __init__(self, **args): | ||
713 | 150 | """Construct a `CannotUploadToArchive`.""" | ||
714 | 151 | Exception.__init__(self, self._fmt % args) | ||
715 | 152 | |||
716 | 153 | |||
717 | 154 | class InvalidPocketForPartnerArchive(CannotUploadToArchive): | ||
718 | 155 | """Partner archives only support some pockets.""" | ||
719 | 156 | |||
720 | 157 | _fmt = "Partner uploads must be for the RELEASE or PROPOSED pocket." | ||
721 | 158 | |||
722 | 159 | |||
723 | 160 | class CannotUploadToPocket(Exception): | ||
724 | 161 | """Returned when a pocket is closed for uploads.""" | ||
725 | 162 | |||
726 | 163 | def __init__(self, distroseries, pocket): | ||
727 | 164 | Exception.__init__(self, | ||
728 | 165 | "Not permitted to upload to the %s pocket in a series in the " | ||
729 | 166 | "'%s' state." % (pocket.name, distroseries.status.name)) | ||
730 | 167 | |||
731 | 168 | |||
732 | 169 | class CannotUploadToPPA(CannotUploadToArchive): | ||
733 | 170 | """Raised when a person cannot upload to a PPA.""" | ||
734 | 171 | |||
735 | 172 | _fmt = 'Signer has no upload rights to this PPA.' | ||
736 | 173 | |||
737 | 174 | |||
738 | 175 | class NoRightsForArchive(CannotUploadToArchive): | ||
739 | 176 | """Raised when a person has absolutely no upload rights to an archive.""" | ||
740 | 177 | |||
741 | 178 | _fmt = ( | ||
742 | 179 | "The signer of this package has no upload rights to this " | ||
743 | 180 | "distribution's primary archive. Did you mean to upload to " | ||
744 | 181 | "a PPA?") | ||
745 | 182 | |||
746 | 183 | |||
747 | 184 | class InsufficientUploadRights(CannotUploadToArchive): | ||
748 | 185 | """Raised when a person has insufficient upload rights.""" | ||
749 | 186 | _fmt = ( | ||
750 | 187 | "The signer of this package is lacking the upload rights for " | ||
751 | 188 | "the source package, component or package set in question.") | ||
752 | 189 | |||
753 | 190 | |||
754 | 191 | class NoRightsForComponent(CannotUploadToArchive): | ||
755 | 192 | """Raised when a person tries to upload to a component without permission. | ||
756 | 193 | """ | ||
757 | 194 | |||
758 | 195 | _fmt = ( | ||
759 | 196 | "Signer is not permitted to upload to the component '%(component)s'.") | ||
760 | 197 | |||
761 | 198 | def __init__(self, component): | ||
762 | 199 | CannotUploadToArchive.__init__(self, component=component.name) | ||
763 | 200 | |||
764 | 201 | |||
765 | 202 | class InvalidPocketForPPA(CannotUploadToArchive): | ||
766 | 203 | """PPAs only support some pockets.""" | ||
767 | 204 | |||
768 | 205 | _fmt = "PPA uploads must be for the RELEASE pocket." | ||
769 | 206 | |||
770 | 207 | |||
771 | 208 | class ArchiveDisabled(CannotUploadToArchive): | ||
772 | 209 | """Uploading to a disabled archive is not allowed.""" | ||
773 | 210 | |||
774 | 211 | _fmt = ("%(archive_name)s is disabled.") | ||
775 | 212 | |||
776 | 213 | def __init__(self, archive_name): | ||
777 | 214 | CannotUploadToArchive.__init__(self, archive_name=archive_name) | ||
778 | 215 | |||
779 | 216 | |||
780 | 136 | class IArchivePublic(IHasOwner, IPrivacy): | 217 | class IArchivePublic(IHasOwner, IPrivacy): |
781 | 137 | """An Archive interface for publicly available operations.""" | 218 | """An Archive interface for publicly available operations.""" |
782 | 138 | id = Attribute("The archive ID.") | 219 | id = Attribute("The archive ID.") |
783 | @@ -380,7 +461,7 @@ | |||
784 | 380 | :return: A list of `IArchivePermission` records. | 461 | :return: A list of `IArchivePermission` records. |
785 | 381 | """ | 462 | """ |
786 | 382 | 463 | ||
788 | 383 | def canUpload(person, component_or_package=None): | 464 | def checkArchivePermission(person, component_or_package=None): |
789 | 384 | """Check to see if person is allowed to upload to component. | 465 | """Check to see if person is allowed to upload to component. |
790 | 385 | 466 | ||
791 | 386 | :param person: An `IPerson` whom should be checked for authentication. | 467 | :param person: An `IPerson` whom should be checked for authentication. |
792 | @@ -395,6 +476,53 @@ | |||
793 | 395 | 476 | ||
794 | 396 | """ | 477 | """ |
795 | 397 | 478 | ||
796 | 479 | def canUploadSuiteSourcePackage(person, suitesourcepackage): | ||
797 | 480 | """Check if 'person' upload 'suitesourcepackage' to 'archive'. | ||
798 | 481 | |||
799 | 482 | :param person: An `IPerson` who might be uploading. | ||
800 | 483 | :param suitesourcepackage: An `ISuiteSourcePackage` to be uploaded. | ||
801 | 484 | :return: True if they can, False if they cannot. | ||
802 | 485 | """ | ||
803 | 486 | |||
804 | 487 | def checkUploadToPocket(distroseries, pocket): | ||
805 | 488 | """Check if uploading to a particular pocket in an archive is possible. | ||
806 | 489 | |||
807 | 490 | :param distroseries: A `IDistroSeries` | ||
808 | 491 | :param pocket: A `PackagePublishingPocket` | ||
809 | 492 | :return: Reason why uploading is not possible or None | ||
810 | 493 | """ | ||
811 | 494 | |||
812 | 495 | def checkUpload(person, distroseries, sourcepackagename, component, | ||
813 | 496 | pocket, strict_component=True): | ||
814 | 497 | """Check if 'person' upload 'suitesourcepackage' to 'archive'. | ||
815 | 498 | |||
816 | 499 | :param person: An `IPerson` who might be uploading. | ||
817 | 500 | :param distroseries: The `IDistroSeries` being uploaded to. | ||
818 | 501 | :param sourcepackagename: The `ISourcePackageName` being uploaded. | ||
819 | 502 | :param component: The `Component` being uploaded to. | ||
820 | 503 | :param pocket: The `PackagePublishingPocket` of 'distroseries' being | ||
821 | 504 | uploaded to. | ||
822 | 505 | :return: The reason for not being able to upload, None otherwise. | ||
823 | 506 | """ | ||
824 | 507 | |||
825 | 508 | def verifyUpload(person, sourcepackagename, component, | ||
826 | 509 | distroseries, strict_component=True): | ||
827 | 510 | """Can 'person' upload 'sourcepackagename' to this archive ? | ||
828 | 511 | |||
829 | 512 | :param person: The `IPerson` trying to upload to the package. Referred to | ||
830 | 513 | as 'the signer' in upload code. | ||
831 | 514 | :param sourcepackagename: The source package being uploaded. None if the | ||
832 | 515 | package is new. | ||
833 | 516 | :param archive: The `IArchive` being uploaded to. | ||
834 | 517 | :param component: The `IComponent` that the source package belongs to. | ||
835 | 518 | :param distroseries: The upload's target distro series. | ||
836 | 519 | :param strict_component: True if access to the specific component for the | ||
837 | 520 | package is needed to upload to it. If False, then access to any | ||
838 | 521 | package will do. | ||
839 | 522 | :return: CannotUploadToArchive if 'person' cannot upload to the archive, | ||
840 | 523 | None otherwise. | ||
841 | 524 | """ | ||
842 | 525 | |||
843 | 398 | def canAdministerQueue(person, component): | 526 | def canAdministerQueue(person, component): |
844 | 399 | """Check to see if person is allowed to administer queue items. | 527 | """Check to see if person is allowed to administer queue items. |
845 | 400 | 528 | ||
846 | @@ -564,6 +692,13 @@ | |||
847 | 564 | 'person' is allowed to upload to. | 692 | 'person' is allowed to upload to. |
848 | 565 | """ | 693 | """ |
849 | 566 | 694 | ||
850 | 695 | def getComponentsForUploader(person): | ||
851 | 696 | """Return the components that 'person' can upload to this archive. | ||
852 | 697 | |||
853 | 698 | :param person: An `IPerson` wishing to upload to an archive. | ||
854 | 699 | :return: A `set` of `IComponent`s that 'person' can upload to. | ||
855 | 700 | """ | ||
856 | 701 | |||
857 | 567 | @operation_parameters( | 702 | @operation_parameters( |
858 | 568 | sourcepackagename=TextLine( | 703 | sourcepackagename=TextLine( |
859 | 569 | title=_("Source package name"), required=True), | 704 | title=_("Source package name"), required=True), |
860 | 570 | 705 | ||
861 | === modified file 'lib/lp/soyuz/model/archive.py' | |||
862 | --- lib/lp/soyuz/model/archive.py 2010-05-06 10:05:49 +0000 | |||
863 | +++ lib/lp/soyuz/model/archive.py 2010-05-11 14:12:39 +0000 | |||
864 | @@ -58,11 +58,14 @@ | |||
865 | 58 | from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease | 58 | from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease |
866 | 59 | from lp.registry.model.teammembership import TeamParticipation | 59 | from lp.registry.model.teammembership import TeamParticipation |
867 | 60 | from lp.soyuz.interfaces.archive import ( | 60 | from lp.soyuz.interfaces.archive import ( |
870 | 61 | AlreadySubscribed, ArchiveDependencyError, ArchiveNotPrivate, | 61 | AlreadySubscribed, ArchiveDependencyError, ArchiveDisabled, |
871 | 62 | ArchivePurpose, ArchiveStatus, CannotCopy, CannotSwitchPrivacy, | 62 | ArchiveNotPrivate, ArchivePurpose, ArchiveStatus, CannotCopy, |
872 | 63 | CannotSwitchPrivacy, CannotUploadToPPA, CannotUploadToPocket, | ||
873 | 63 | DistroSeriesNotFound, IArchive, IArchiveSet, IDistributionArchive, | 64 | DistroSeriesNotFound, IArchive, IArchiveSet, IDistributionArchive, |
876 | 64 | InvalidComponent, IPPA, MAIN_ARCHIVE_PURPOSES, NoSuchPPA, | 65 | InsufficientUploadRights, InvalidPocketForPPA, |
877 | 65 | NoTokensForTeams, PocketNotFound, VersionRequiresName, | 66 | InvalidPocketForPartnerArchive, InvalidComponent, IPPA, |
878 | 67 | MAIN_ARCHIVE_PURPOSES, NoRightsForArchive, NoRightsForComponent, | ||
879 | 68 | NoSuchPPA, NoTokensForTeams, PocketNotFound, VersionRequiresName, | ||
880 | 66 | default_name_by_purpose) | 69 | default_name_by_purpose) |
881 | 67 | from lp.soyuz.interfaces.archiveauthtoken import IArchiveAuthTokenSet | 70 | from lp.soyuz.interfaces.archiveauthtoken import IArchiveAuthTokenSet |
882 | 68 | from lp.soyuz.interfaces.archivearch import IArchiveArchSet | 71 | from lp.soyuz.interfaces.archivearch import IArchiveArchSet |
883 | @@ -954,7 +957,7 @@ | |||
884 | 954 | source_ids, | 957 | source_ids, |
885 | 955 | archive=self) | 958 | archive=self) |
886 | 956 | 959 | ||
888 | 957 | def canUpload(self, user, component_or_package=None): | 960 | def checkArchivePermission(self, user, component_or_package=None): |
889 | 958 | """See `IArchive`.""" | 961 | """See `IArchive`.""" |
890 | 959 | assert not self.is_copy, "Uploads to copy archives are not allowed." | 962 | assert not self.is_copy, "Uploads to copy archives are not allowed." |
891 | 960 | # PPA access is immediately granted if the user is in the PPA | 963 | # PPA access is immediately granted if the user is in the PPA |
892 | @@ -977,6 +980,87 @@ | |||
893 | 977 | return self._authenticate( | 980 | return self._authenticate( |
894 | 978 | user, component_or_package, ArchivePermissionType.UPLOAD) | 981 | user, component_or_package, ArchivePermissionType.UPLOAD) |
895 | 979 | 982 | ||
896 | 983 | def canUploadSuiteSourcePackage(self, person, suitesourcepackage): | ||
897 | 984 | """See `IArchive`.""" | ||
898 | 985 | sourcepackage = suitesourcepackage.sourcepackage | ||
899 | 986 | pocket = suitesourcepackage.pocket | ||
900 | 987 | distroseries = sourcepackage.distroseries | ||
901 | 988 | sourcepackagename = sourcepackage.sourcepackagename | ||
902 | 989 | component = sourcepackage.latest_published_component | ||
903 | 990 | # strict_component is True because the source package already exists | ||
904 | 991 | # (otherwise we couldn't have a suitesourcepackage object) and | ||
905 | 992 | # nascentupload passes True as a matter of policy when the package exists. | ||
906 | 993 | reason = self.checkUpload( | ||
907 | 994 | person, distroseries, sourcepackagename, component, pocket, | ||
908 | 995 | strict_component=True) | ||
909 | 996 | return reason is None | ||
910 | 997 | |||
911 | 998 | def checkUploadToPocket(self, distroseries, pocket): | ||
912 | 999 | """See `IArchive`.""" | ||
913 | 1000 | if self.purpose == ArchivePurpose.PARTNER: | ||
914 | 1001 | if pocket not in ( | ||
915 | 1002 | PackagePublishingPocket.RELEASE, | ||
916 | 1003 | PackagePublishingPocket.PROPOSED): | ||
917 | 1004 | return InvalidPocketForPartnerArchive() | ||
918 | 1005 | elif self.is_ppa: | ||
919 | 1006 | if pocket != PackagePublishingPocket.RELEASE: | ||
920 | 1007 | return InvalidPocketForPPA() | ||
921 | 1008 | else: | ||
922 | 1009 | # Uploads to the partner archive are allowed in any distroseries | ||
923 | 1010 | # state. | ||
924 | 1011 | # XXX julian 2005-05-29 bug=117557: | ||
925 | 1012 | # This is a greasy hack until bug #117557 is fixed. | ||
926 | 1013 | if not distroseries.canUploadToPocket(pocket): | ||
927 | 1014 | return CannotUploadToPocket(distroseries, pocket) | ||
928 | 1015 | |||
929 | 1016 | def checkUpload(self, person, distroseries, sourcepackagename, component, | ||
930 | 1017 | pocket, strict_component=True): | ||
931 | 1018 | """See `IArchive`.""" | ||
932 | 1019 | reason = self.checkUploadToPocket(distroseries, pocket) | ||
933 | 1020 | if reason is not None: | ||
934 | 1021 | return reason | ||
935 | 1022 | return self.verifyUpload( | ||
936 | 1023 | person, sourcepackagename, component, distroseries, | ||
937 | 1024 | strict_component) | ||
938 | 1025 | |||
939 | 1026 | def verifyUpload(self, person, sourcepackagename, component, | ||
940 | 1027 | distroseries, strict_component=True): | ||
941 | 1028 | """See `IArchive`.""" | ||
942 | 1029 | if not self.enabled: | ||
943 | 1030 | return ArchiveDisabled(self.displayname) | ||
944 | 1031 | |||
945 | 1032 | # For PPAs... | ||
946 | 1033 | if self.is_ppa: | ||
947 | 1034 | if not self.checkArchivePermission(person): | ||
948 | 1035 | return CannotUploadToPPA() | ||
949 | 1036 | else: | ||
950 | 1037 | return None | ||
951 | 1038 | |||
952 | 1039 | if sourcepackagename is not None: | ||
953 | 1040 | # Check whether user may upload because they hold a permission for | ||
954 | 1041 | # - the given source package directly | ||
955 | 1042 | # - a package set in the correct distro series that includes the | ||
956 | 1043 | # given source package | ||
957 | 1044 | source_allowed = self.checkArchivePermission(person, | ||
958 | 1045 | sourcepackagename) | ||
959 | 1046 | set_allowed = self.isSourceUploadAllowed( | ||
960 | 1047 | sourcepackagename, person, distroseries) | ||
961 | 1048 | if source_allowed or set_allowed: | ||
962 | 1049 | return None | ||
963 | 1050 | |||
964 | 1051 | if not self.getComponentsForUploader(person): | ||
965 | 1052 | if not self.getPackagesetsForUploader(person): | ||
966 | 1053 | return NoRightsForArchive() | ||
967 | 1054 | else: | ||
968 | 1055 | return InsufficientUploadRights() | ||
969 | 1056 | |||
970 | 1057 | if (component is not None | ||
971 | 1058 | and strict_component | ||
972 | 1059 | and not self.checkArchivePermission(person, component)): | ||
973 | 1060 | return NoRightsForComponent(component) | ||
974 | 1061 | |||
975 | 1062 | return None | ||
976 | 1063 | |||
977 | 980 | def canAdministerQueue(self, user, component): | 1064 | def canAdministerQueue(self, user, component): |
978 | 981 | """See `IArchive`.""" | 1065 | """See `IArchive`.""" |
979 | 982 | return self._authenticate( | 1066 | return self._authenticate( |
980 | @@ -1050,6 +1134,11 @@ | |||
981 | 1050 | return permission_set.deletePackagesetUploader( | 1134 | return permission_set.deletePackagesetUploader( |
982 | 1051 | self, person, packageset, explicit) | 1135 | self, person, packageset, explicit) |
983 | 1052 | 1136 | ||
984 | 1137 | def getComponentsForUploader(self, person): | ||
985 | 1138 | """See `IArchive`.""" | ||
986 | 1139 | permission_set = getUtility(IArchivePermissionSet) | ||
987 | 1140 | return permission_set.componentsForUploader(self, person) | ||
988 | 1141 | |||
989 | 1053 | def getPackagesetsForUploader(self, person): | 1142 | def getPackagesetsForUploader(self, person): |
990 | 1054 | """See `IArchive`.""" | 1143 | """See `IArchive`.""" |
991 | 1055 | permission_set = getUtility(IArchivePermissionSet) | 1144 | permission_set = getUtility(IArchivePermissionSet) |
992 | 1056 | 1145 | ||
993 | === modified file 'lib/lp/soyuz/model/archivepermission.py' | |||
994 | --- lib/lp/soyuz/model/archivepermission.py 2010-03-08 17:06:41 +0000 | |||
995 | +++ lib/lp/soyuz/model/archivepermission.py 2010-05-11 14:12:39 +0000 | |||
996 | @@ -151,8 +151,8 @@ | |||
997 | 151 | prejoins.append("packageset") | 151 | prejoins.append("packageset") |
998 | 152 | else: | 152 | else: |
999 | 153 | raise AssertionError( | 153 | raise AssertionError( |
1002 | 154 | "'item' is not an IComponent, IPackageset or an " | 154 | "'item' %r is not an IComponent, IPackageset or an " |
1003 | 155 | "ISourcePackageName") | 155 | "ISourcePackageName" % item) |
1004 | 156 | 156 | ||
1005 | 157 | query = " AND ".join(clauses) | 157 | query = " AND ".join(clauses) |
1006 | 158 | auth = ArchivePermission.select( | 158 | auth = ArchivePermission.select( |
1007 | 159 | 159 | ||
1008 | === modified file 'lib/lp/soyuz/model/binarypackagebuildbehavior.py' | |||
1009 | --- lib/lp/soyuz/model/binarypackagebuildbehavior.py 2010-04-12 05:52:01 +0000 | |||
1010 | +++ lib/lp/soyuz/model/binarypackagebuildbehavior.py 2010-05-11 14:12:39 +0000 | |||
1011 | @@ -15,7 +15,6 @@ | |||
1012 | 15 | 15 | ||
1013 | 16 | from canonical.launchpad.webapp import urlappend | 16 | from canonical.launchpad.webapp import urlappend |
1014 | 17 | 17 | ||
1015 | 18 | from lp.archiveuploader.permission import check_upload_to_pocket | ||
1016 | 19 | from lp.buildmaster.interfaces.buildfarmjobbehavior import ( | 18 | from lp.buildmaster.interfaces.buildfarmjobbehavior import ( |
1017 | 20 | IBuildFarmJobBehavior) | 19 | IBuildFarmJobBehavior) |
1018 | 21 | from lp.buildmaster.model.buildfarmjobbehavior import ( | 20 | from lp.buildmaster.model.buildfarmjobbehavior import ( |
1019 | @@ -123,8 +122,8 @@ | |||
1020 | 123 | 122 | ||
1021 | 124 | # This should already have been checked earlier, but just check again | 123 | # This should already have been checked earlier, but just check again |
1022 | 125 | # here in case of programmer errors. | 124 | # here in case of programmer errors. |
1025 | 126 | reason = check_upload_to_pocket( | 125 | reason = build.archive.checkUploadToPocket(build.distroseries, |
1026 | 127 | build.archive, build.distroseries, build.pocket) | 126 | build.pocket) |
1027 | 128 | assert reason is None, ( | 127 | assert reason is None, ( |
1028 | 129 | "%s (%s) can not be built for pocket %s: invalid pocket due " | 128 | "%s (%s) can not be built for pocket %s: invalid pocket due " |
1029 | 130 | "to the series status of %s." % | 129 | "to the series status of %s." % |
1030 | 131 | 130 | ||
1031 | === modified file 'lib/lp/soyuz/tests/test_archive.py' | |||
1032 | --- lib/lp/soyuz/tests/test_archive.py 2010-05-03 07:48:54 +0000 | |||
1033 | +++ lib/lp/soyuz/tests/test_archive.py 2010-05-11 14:12:39 +0000 | |||
1034 | @@ -18,13 +18,16 @@ | |||
1035 | 18 | from lp.buildmaster.interfaces.buildbase import BuildStatus | 18 | from lp.buildmaster.interfaces.buildbase import BuildStatus |
1036 | 19 | from lp.registry.interfaces.distribution import IDistributionSet | 19 | from lp.registry.interfaces.distribution import IDistributionSet |
1037 | 20 | from lp.registry.interfaces.person import IPersonSet | 20 | from lp.registry.interfaces.person import IPersonSet |
1038 | 21 | from lp.registry.interfaces.pocket import PackagePublishingPocket | ||
1039 | 21 | from lp.services.job.interfaces.job import JobStatus | 22 | from lp.services.job.interfaces.job import JobStatus |
1040 | 23 | from lp.soyuz.interfaces.archive import (IArchiveSet, ArchivePurpose, | ||
1041 | 24 | ArchiveStatus, CannotSwitchPrivacy, InvalidPocketForPartnerArchive, | ||
1042 | 25 | InvalidPocketForPPA) | ||
1043 | 22 | from lp.services.worlddata.interfaces.country import ICountrySet | 26 | from lp.services.worlddata.interfaces.country import ICountrySet |
1044 | 23 | from lp.soyuz.interfaces.archive import ( | ||
1045 | 24 | IArchiveSet, ArchivePurpose, ArchiveStatus, CannotSwitchPrivacy) | ||
1046 | 25 | from lp.soyuz.interfaces.archivearch import IArchiveArchSet | 27 | from lp.soyuz.interfaces.archivearch import IArchiveArchSet |
1047 | 26 | from lp.soyuz.interfaces.binarypackagename import IBinaryPackageNameSet | 28 | from lp.soyuz.interfaces.binarypackagename import IBinaryPackageNameSet |
1048 | 27 | from lp.soyuz.interfaces.binarypackagerelease import BinaryPackageFormat | 29 | from lp.soyuz.interfaces.binarypackagerelease import BinaryPackageFormat |
1049 | 30 | from lp.soyuz.interfaces.component import IComponentSet | ||
1050 | 28 | from lp.soyuz.interfaces.processor import IProcessorFamilySet | 31 | from lp.soyuz.interfaces.processor import IProcessorFamilySet |
1051 | 29 | from lp.soyuz.interfaces.publishing import PackagePublishingStatus | 32 | from lp.soyuz.interfaces.publishing import PackagePublishingStatus |
1052 | 30 | from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild | 33 | from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild |
1053 | @@ -345,6 +348,7 @@ | |||
1054 | 345 | self.failUnlessEqual( | 348 | self.failUnlessEqual( |
1055 | 346 | self.sourcepackagereleases[0], result[0]) | 349 | self.sourcepackagereleases[0], result[0]) |
1056 | 347 | 350 | ||
1057 | 351 | |||
1058 | 348 | class TestCorrespondingDebugArchive(TestCaseWithFactory): | 352 | class TestCorrespondingDebugArchive(TestCaseWithFactory): |
1059 | 349 | 353 | ||
1060 | 350 | layer = LaunchpadZopelessLayer | 354 | layer = LaunchpadZopelessLayer |
1061 | @@ -520,6 +524,7 @@ | |||
1062 | 520 | self.archive.disable() | 524 | self.archive.disable() |
1063 | 521 | self.assertRaises(AssertionError, self.archive.disable) | 525 | self.assertRaises(AssertionError, self.archive.disable) |
1064 | 522 | 526 | ||
1065 | 527 | |||
1066 | 523 | class TestCollectLatestPublishedSources(TestCaseWithFactory): | 528 | class TestCollectLatestPublishedSources(TestCaseWithFactory): |
1067 | 524 | """Ensure that the private helper method works as expected.""" | 529 | """Ensure that the private helper method works as expected.""" |
1068 | 525 | 530 | ||
1069 | @@ -566,6 +571,70 @@ | |||
1070 | 566 | self.assertEqual('0.5.11~ppa1', pubs[0].source_package_version) | 571 | self.assertEqual('0.5.11~ppa1', pubs[0].source_package_version) |
1071 | 567 | 572 | ||
1072 | 568 | 573 | ||
1073 | 574 | class TestArchiveCanUpload(TestCaseWithFactory): | ||
1074 | 575 | """Test the various methods that verify whether uploads are allowed to | ||
1075 | 576 | happen.""" | ||
1076 | 577 | |||
1077 | 578 | layer = LaunchpadZopelessLayer | ||
1078 | 579 | |||
1079 | 580 | def test_checkArchivePermission_by_PPA_owner(self): | ||
1080 | 581 | # Uploading to a PPA should be allowed for a user that is the owner | ||
1081 | 582 | owner = self.factory.makePerson(name="somebody") | ||
1082 | 583 | archive = self.factory.makeArchive(owner=owner) | ||
1083 | 584 | self.assertEquals(True, archive.checkArchivePermission(owner)) | ||
1084 | 585 | someone_unrelated = self.factory.makePerson(name="somebody-unrelated") | ||
1085 | 586 | self.assertEquals(False, | ||
1086 | 587 | archive.checkArchivePermission(someone_unrelated)) | ||
1087 | 588 | |||
1088 | 589 | def test_checkArchivePermission_distro_archive(self): | ||
1089 | 590 | # Regular users can not upload to ubuntu | ||
1090 | 591 | ubuntu = getUtility(IDistributionSet).getByName('ubuntu') | ||
1091 | 592 | archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY, | ||
1092 | 593 | distribution=ubuntu) | ||
1093 | 594 | main = getUtility(IComponentSet)["main"] | ||
1094 | 595 | # A regular user doesn't have access | ||
1095 | 596 | somebody = self.factory.makePerson(name="somebody") | ||
1096 | 597 | self.assertEquals(False, | ||
1097 | 598 | archive.checkArchivePermission(somebody, main)) | ||
1098 | 599 | # An ubuntu core developer does have access | ||
1099 | 600 | kamion = getUtility(IPersonSet).getByName('kamion') | ||
1100 | 601 | self.assertEquals(True, archive.checkArchivePermission(kamion, main)) | ||
1101 | 602 | |||
1102 | 603 | def test_checkArchivePermission_ppa(self): | ||
1103 | 604 | ubuntu = getUtility(IDistributionSet).getByName('ubuntu') | ||
1104 | 605 | owner = self.factory.makePerson(name="eigenaar") | ||
1105 | 606 | archive = self.factory.makeArchive(purpose=ArchivePurpose.PPA, | ||
1106 | 607 | distribution=ubuntu, | ||
1107 | 608 | owner=owner) | ||
1108 | 609 | somebody = self.factory.makePerson(name="somebody") | ||
1109 | 610 | # The owner has access | ||
1110 | 611 | self.assertEquals(True, archive.checkArchivePermission(owner)) | ||
1111 | 612 | # Somebody unrelated does not | ||
1112 | 613 | self.assertEquals(False, archive.checkArchivePermission(somebody)) | ||
1113 | 614 | |||
1114 | 615 | def test_checkUpload_partner_invalid_pocket(self): | ||
1115 | 616 | # Partner archives only have release and proposed pockets | ||
1116 | 617 | archive = self.factory.makeArchive(purpose=ArchivePurpose.PARTNER) | ||
1117 | 618 | self.assertIsInstance(archive.checkUpload(self.factory.makePerson(), | ||
1118 | 619 | self.factory.makeDistroSeries(), | ||
1119 | 620 | self.factory.makeSourcePackageName(), | ||
1120 | 621 | self.factory.makeComponent(), | ||
1121 | 622 | PackagePublishingPocket.UPDATES), | ||
1122 | 623 | InvalidPocketForPartnerArchive) | ||
1123 | 624 | |||
1124 | 625 | def test_checkUpload_ppa_invalid_pocket(self): | ||
1125 | 626 | # PPA archives only have release pockets | ||
1126 | 627 | archive = self.factory.makeArchive(purpose=ArchivePurpose.PPA) | ||
1127 | 628 | self.assertIsInstance(archive.checkUpload(self.factory.makePerson(), | ||
1128 | 629 | self.factory.makeDistroSeries(), | ||
1129 | 630 | self.factory.makeSourcePackageName(), | ||
1130 | 631 | self.factory.makeComponent(), | ||
1131 | 632 | PackagePublishingPocket.PROPOSED), | ||
1132 | 633 | InvalidPocketForPPA) | ||
1133 | 634 | |||
1134 | 635 | # XXX: JRV 20100511: IArchive.canUploadSuiteSourcePackage needs tests | ||
1135 | 636 | |||
1136 | 637 | |||
1137 | 569 | class TestUpdatePackageDownloadCount(TestCaseWithFactory): | 638 | class TestUpdatePackageDownloadCount(TestCaseWithFactory): |
1138 | 570 | """Ensure that updatePackageDownloadCount works as expected.""" | 639 | """Ensure that updatePackageDownloadCount works as expected.""" |
1139 | 571 | 640 |
Hi Jelmer this refactoring looks good. In test_archive.py please end all comments with punctuation.