Merge lp://staging/~cprov/launchpad/bug-422965-archive-permission-api into lp://staging/launchpad
- bug-422965-archive-permission-api
- Merge into devel
Proposed by
Celso Providelo
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp://staging/~cprov/launchpad/bug-422965-archive-permission-api |
Merge into: | lp://staging/launchpad |
Diff against target: | None lines |
To merge this branch: | bzr merge lp://staging/~cprov/launchpad/bug-422965-archive-permission-api |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paul Hummer (community) | Approve | ||
Review via email: mp+12006@code.staging.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Celso Providelo (cprov) wrote : | # |
Revision history for this message
Paul Hummer (rockstar) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/soyuz/configure.zcml' |
2 | --- lib/lp/soyuz/configure.zcml 2009-09-03 15:04:13 +0000 |
3 | +++ lib/lp/soyuz/configure.zcml 2009-09-04 18:18:39 +0000 |
4 | @@ -394,6 +394,7 @@ |
5 | interface="lp.soyuz.interfaces.archive.IArchiveAppend"/> |
6 | <require |
7 | permission="launchpad.Edit" |
8 | + interface="lp.soyuz.interfaces.archive.IArchiveEdit" |
9 | set_attributes="description displayname"/> |
10 | <require |
11 | permission="launchpad.Commercial" |
12 | @@ -465,16 +466,16 @@ |
13 | packagesetsForUploader |
14 | packagesetsForSource |
15 | packagesetsForSourceUploader |
16 | - isSourceUploadAllowed"/> |
17 | - <require |
18 | - permission="launchpad.Edit" |
19 | - attributes=" |
20 | + isSourceUploadAllowed |
21 | newPackageUploader |
22 | newComponentUploader |
23 | newQueueAdmin |
24 | deletePackageUploader |
25 | deleteComponentUploader |
26 | - deleteQueueAdmin |
27 | + deleteQueueAdmin"/> |
28 | + <require |
29 | + permission="launchpad.Edit" |
30 | + attributes=" |
31 | newPackagesetUploader |
32 | deletePackagesetUploader"/> |
33 | </securedutility> |
34 | |
35 | === modified file 'lib/lp/soyuz/interfaces/archive.py' |
36 | --- lib/lp/soyuz/interfaces/archive.py 2009-09-02 21:28:11 +0000 |
37 | +++ lib/lp/soyuz/interfaces/archive.py 2009-09-17 17:24:04 +0000 |
38 | @@ -16,6 +16,7 @@ |
39 | 'DistroSeriesNotFound', |
40 | 'IArchive', |
41 | 'IArchiveAppend', |
42 | + 'IArchiveEdit', |
43 | 'IArchiveView', |
44 | 'IArchiveEditDependenciesForm', |
45 | 'IArchivePublic', |
46 | @@ -336,68 +337,6 @@ |
47 | :return: A list of `IArchivePermission` records. |
48 | """ |
49 | |
50 | - @operation_parameters(person=Reference(schema=IPerson)) |
51 | - # Really IArchivePermission, set below to avoid circular import. |
52 | - @operation_returns_collection_of(Interface) |
53 | - @export_read_operation() |
54 | - def getPermissionsForPerson(person): |
55 | - """Return the `IArchivePermission` records applicable to the person. |
56 | - |
57 | - :param person: An `IPerson` |
58 | - :return: A list of `IArchivePermission` records. |
59 | - """ |
60 | - |
61 | - @operation_parameters( |
62 | - source_package_name=TextLine( |
63 | - title=_("Source Package Name"), required=True)) |
64 | - # Really IArchivePermission, set below to avoid circular import. |
65 | - @operation_returns_collection_of(Interface) |
66 | - @export_read_operation() |
67 | - def getUploadersForPackage(source_package_name): |
68 | - """Return `IArchivePermission` records for the package's uploaders. |
69 | - |
70 | - :param source_package_name: An `ISourcePackageName` or textual name |
71 | - for the source package. |
72 | - :return: A list of `IArchivePermission` records. |
73 | - """ |
74 | - |
75 | - @operation_parameters( |
76 | - component_name=TextLine(title=_("Component Name"), required=False)) |
77 | - # Really IArchivePermission, set below to avoid circular import. |
78 | - @operation_returns_collection_of(Interface) |
79 | - @export_read_operation() |
80 | - def getUploadersForComponent(component_name=None): |
81 | - """Return `IArchivePermission` records for the component's uploaders. |
82 | - |
83 | - :param component_name: An `IComponent` or textual name for the |
84 | - component. |
85 | - :return: A list of `IArchivePermission` records. |
86 | - """ |
87 | - |
88 | - @operation_parameters( |
89 | - component_name=TextLine(title=_("Component Name"), required=True)) |
90 | - # Really IArchivePermission, set below to avoid circular import. |
91 | - @operation_returns_collection_of(Interface) |
92 | - @export_read_operation() |
93 | - def getQueueAdminsForComponent(component_name): |
94 | - """Return `IArchivePermission` records for authorised queue admins. |
95 | - |
96 | - :param component_name: An `IComponent` or textual name for the |
97 | - component. |
98 | - :return: A list of `IArchivePermission` records. |
99 | - """ |
100 | - |
101 | - @operation_parameters(person=Reference(schema=IPerson)) |
102 | - # Really IArchivePermission, set below to avoid circular import. |
103 | - @operation_returns_collection_of(Interface) |
104 | - @export_read_operation() |
105 | - def getComponentsForQueueAdmin(person): |
106 | - """Return `IArchivePermission` for the person's queue admin components |
107 | - |
108 | - :param person: An `IPerson` |
109 | - :return: A list of `IArchivePermission` records. |
110 | - """ |
111 | - |
112 | def canUpload(person, component_or_package=None): |
113 | """Check to see if person is allowed to upload to component. |
114 | |
115 | @@ -423,103 +362,6 @@ |
116 | queue for items with 'component'. |
117 | """ |
118 | |
119 | - # The following three factory methods are not in the |
120 | - # IArchiveEditRestricted interface because the rights to use them |
121 | - # does not depend on edit permissions to the archive. The code they |
122 | - # contain does all the necessary security checking and is well |
123 | - # tested in xx-archive.txt and archivepermissions.txt. |
124 | - |
125 | - @operation_parameters( |
126 | - person=Reference(schema=IPerson), |
127 | - source_package_name=TextLine( |
128 | - title=_("Source Package Name"), required=True)) |
129 | - # Really IArchivePermission, set below to avoid circular import. |
130 | - @export_factory_operation(Interface, []) |
131 | - def newPackageUploader(person, source_package_name): |
132 | - """Add permisson for a person to upload a package to this archive. |
133 | - |
134 | - :param person: An `IPerson` whom should be given permission. |
135 | - :param source_package_name: An `ISourcePackageName` or textual package |
136 | - name. |
137 | - :return: An `IArchivePermission` which is the newly-created |
138 | - permission. |
139 | - """ |
140 | - |
141 | - @operation_parameters( |
142 | - person=Reference(schema=IPerson), |
143 | - component_name=TextLine( |
144 | - title=_("Component Name"), required=True)) |
145 | - # Really IArchivePermission, set below to avoid circular import. |
146 | - @export_factory_operation(Interface, []) |
147 | - def newComponentUploader(person, component_name): |
148 | - """Add permission for a person to upload to a component. |
149 | - |
150 | - :param person: An `IPerson` whom should be given permission. |
151 | - :param component: An `IComponent` or textual component name. |
152 | - :return: An `IArchivePermission` which is the newly-created |
153 | - permission. |
154 | - :raises InvalidComponent: if this archive is a PPA and the component |
155 | - is not 'main'. |
156 | - """ |
157 | - |
158 | - @operation_parameters( |
159 | - person=Reference(schema=IPerson), |
160 | - component_name=TextLine( |
161 | - title=_("Component Name"), required=True)) |
162 | - # Really IArchivePermission, set below to avoid circular import. |
163 | - @export_factory_operation(Interface, []) |
164 | - def newQueueAdmin(person, component_name): |
165 | - """Add permission for a person to administer a distroseries queue. |
166 | - |
167 | - The supplied person will gain permission to administer the |
168 | - distroseries queue for packages in the supplied component. |
169 | - |
170 | - :param person: An `IPerson` whom should be given permission. |
171 | - :param component: An `IComponent` or textual component name. |
172 | - :return: An `IArchivePermission` which is the newly-created |
173 | - permission. |
174 | - """ |
175 | - |
176 | - @operation_parameters( |
177 | - person=Reference(schema=IPerson), |
178 | - source_package_name=TextLine( |
179 | - title=_("Source Package Name"), required=True)) |
180 | - @export_write_operation() |
181 | - def deletePackageUploader(person, source_package_name): |
182 | - """Revoke permission for the person to upload the package. |
183 | - |
184 | - :param person: An `IPerson` whose permission should be revoked. |
185 | - :param source_package_name: An `ISourcePackageName` or textual package |
186 | - name. |
187 | - """ |
188 | - |
189 | - @operation_parameters( |
190 | - person=Reference(schema=IPerson), |
191 | - component_name=TextLine( |
192 | - title=_("Component Name"), required=True)) |
193 | - @export_write_operation() |
194 | - def deleteComponentUploader(person, component_name): |
195 | - """Revoke permission for the person to upload to the component. |
196 | - |
197 | - :param person: An `IPerson` whose permission should be revoked. |
198 | - :param component: An `IComponent` or textual component name. |
199 | - """ |
200 | - |
201 | - @operation_parameters( |
202 | - person=Reference(schema=IPerson), |
203 | - component_name=TextLine( |
204 | - title=_("Component Name"), required=True)) |
205 | - @export_write_operation() |
206 | - def deleteQueueAdmin(person, component_name): |
207 | - """Revoke permission for the person to administer distroseries queues. |
208 | - |
209 | - The supplied person will lose permission to administer the |
210 | - distroseries queue for packages in the supplied component. |
211 | - |
212 | - :param person: An `IPerson` whose permission should be revoked. |
213 | - :param component: An `IComponent` or textual component name. |
214 | - """ |
215 | - |
216 | def getFileByName(filename): |
217 | """Return the corresponding `ILibraryFileAlias` in this context. |
218 | |
219 | @@ -926,6 +768,68 @@ |
220 | could not be found. |
221 | """ |
222 | |
223 | + @operation_parameters(person=Reference(schema=IPerson)) |
224 | + # Really IArchivePermission, set below to avoid circular import. |
225 | + @operation_returns_collection_of(Interface) |
226 | + @export_read_operation() |
227 | + def getPermissionsForPerson(person): |
228 | + """Return the `IArchivePermission` records applicable to the person. |
229 | + |
230 | + :param person: An `IPerson` |
231 | + :return: A list of `IArchivePermission` records. |
232 | + """ |
233 | + |
234 | + @operation_parameters( |
235 | + source_package_name=TextLine( |
236 | + title=_("Source Package Name"), required=True)) |
237 | + # Really IArchivePermission, set below to avoid circular import. |
238 | + @operation_returns_collection_of(Interface) |
239 | + @export_read_operation() |
240 | + def getUploadersForPackage(source_package_name): |
241 | + """Return `IArchivePermission` records for the package's uploaders. |
242 | + |
243 | + :param source_package_name: An `ISourcePackageName` or textual name |
244 | + for the source package. |
245 | + :return: A list of `IArchivePermission` records. |
246 | + """ |
247 | + |
248 | + @operation_parameters( |
249 | + component_name=TextLine(title=_("Component Name"), required=False)) |
250 | + # Really IArchivePermission, set below to avoid circular import. |
251 | + @operation_returns_collection_of(Interface) |
252 | + @export_read_operation() |
253 | + def getUploadersForComponent(component_name=None): |
254 | + """Return `IArchivePermission` records for the component's uploaders. |
255 | + |
256 | + :param component_name: An `IComponent` or textual name for the |
257 | + component. |
258 | + :return: A list of `IArchivePermission` records. |
259 | + """ |
260 | + |
261 | + @operation_parameters( |
262 | + component_name=TextLine(title=_("Component Name"), required=True)) |
263 | + # Really IArchivePermission, set below to avoid circular import. |
264 | + @operation_returns_collection_of(Interface) |
265 | + @export_read_operation() |
266 | + def getQueueAdminsForComponent(component_name): |
267 | + """Return `IArchivePermission` records for authorised queue admins. |
268 | + |
269 | + :param component_name: An `IComponent` or textual name for the |
270 | + component. |
271 | + :return: A list of `IArchivePermission` records. |
272 | + """ |
273 | + |
274 | + @operation_parameters(person=Reference(schema=IPerson)) |
275 | + # Really IArchivePermission, set below to avoid circular import. |
276 | + @operation_returns_collection_of(Interface) |
277 | + @export_read_operation() |
278 | + def getComponentsForQueueAdmin(person): |
279 | + """Return `IArchivePermission` for the person's queue admin components |
280 | + |
281 | + :param person: An `IPerson` |
282 | + :return: A list of `IArchivePermission` records. |
283 | + """ |
284 | + |
285 | |
286 | class IArchiveAppend(Interface): |
287 | """Archive interface for operations restricted by append privilege.""" |
288 | @@ -1043,7 +947,102 @@ |
289 | """ |
290 | |
291 | |
292 | -class IArchive(IArchivePublic, IArchiveAppend, IArchiveView): |
293 | +class IArchiveEdit(Interface): |
294 | + """Archive interface for operations restricted by edit privilege.""" |
295 | + |
296 | + @operation_parameters( |
297 | + person=Reference(schema=IPerson), |
298 | + source_package_name=TextLine( |
299 | + title=_("Source Package Name"), required=True)) |
300 | + # Really IArchivePermission, set below to avoid circular import. |
301 | + @export_factory_operation(Interface, []) |
302 | + def newPackageUploader(person, source_package_name): |
303 | + """Add permisson for a person to upload a package to this archive. |
304 | + |
305 | + :param person: An `IPerson` whom should be given permission. |
306 | + :param source_package_name: An `ISourcePackageName` or textual package |
307 | + name. |
308 | + :return: An `IArchivePermission` which is the newly-created |
309 | + permission. |
310 | + """ |
311 | + |
312 | + @operation_parameters( |
313 | + person=Reference(schema=IPerson), |
314 | + component_name=TextLine( |
315 | + title=_("Component Name"), required=True)) |
316 | + # Really IArchivePermission, set below to avoid circular import. |
317 | + @export_factory_operation(Interface, []) |
318 | + def newComponentUploader(person, component_name): |
319 | + """Add permission for a person to upload to a component. |
320 | + |
321 | + :param person: An `IPerson` whom should be given permission. |
322 | + :param component: An `IComponent` or textual component name. |
323 | + :return: An `IArchivePermission` which is the newly-created |
324 | + permission. |
325 | + :raises InvalidComponent: if this archive is a PPA and the component |
326 | + is not 'main'. |
327 | + """ |
328 | + |
329 | + @operation_parameters( |
330 | + person=Reference(schema=IPerson), |
331 | + component_name=TextLine( |
332 | + title=_("Component Name"), required=True)) |
333 | + # Really IArchivePermission, set below to avoid circular import. |
334 | + @export_factory_operation(Interface, []) |
335 | + def newQueueAdmin(person, component_name): |
336 | + """Add permission for a person to administer a distroseries queue. |
337 | + |
338 | + The supplied person will gain permission to administer the |
339 | + distroseries queue for packages in the supplied component. |
340 | + |
341 | + :param person: An `IPerson` whom should be given permission. |
342 | + :param component: An `IComponent` or textual component name. |
343 | + :return: An `IArchivePermission` which is the newly-created |
344 | + permission. |
345 | + """ |
346 | + |
347 | + @operation_parameters( |
348 | + person=Reference(schema=IPerson), |
349 | + source_package_name=TextLine( |
350 | + title=_("Source Package Name"), required=True)) |
351 | + @export_write_operation() |
352 | + def deletePackageUploader(person, source_package_name): |
353 | + """Revoke permission for the person to upload the package. |
354 | + |
355 | + :param person: An `IPerson` whose permission should be revoked. |
356 | + :param source_package_name: An `ISourcePackageName` or textual package |
357 | + name. |
358 | + """ |
359 | + |
360 | + @operation_parameters( |
361 | + person=Reference(schema=IPerson), |
362 | + component_name=TextLine( |
363 | + title=_("Component Name"), required=True)) |
364 | + @export_write_operation() |
365 | + def deleteComponentUploader(person, component_name): |
366 | + """Revoke permission for the person to upload to the component. |
367 | + |
368 | + :param person: An `IPerson` whose permission should be revoked. |
369 | + :param component: An `IComponent` or textual component name. |
370 | + """ |
371 | + |
372 | + @operation_parameters( |
373 | + person=Reference(schema=IPerson), |
374 | + component_name=TextLine( |
375 | + title=_("Component Name"), required=True)) |
376 | + @export_write_operation() |
377 | + def deleteQueueAdmin(person, component_name): |
378 | + """Revoke permission for the person to administer distroseries queues. |
379 | + |
380 | + The supplied person will lose permission to administer the |
381 | + distroseries queue for packages in the supplied component. |
382 | + |
383 | + :param person: An `IPerson` whose permission should be revoked. |
384 | + :param component: An `IComponent` or textual component name. |
385 | + """ |
386 | + |
387 | + |
388 | +class IArchive(IArchivePublic, IArchiveAppend, IArchiveEdit, IArchiveView): |
389 | """Main Archive interface.""" |
390 | export_as_webservice_entry() |
391 | |
392 | |
393 | === modified file 'lib/lp/soyuz/stories/webservice/xx-archive.txt' |
394 | --- lib/lp/soyuz/stories/webservice/xx-archive.txt 2009-09-04 07:29:56 +0000 |
395 | +++ lib/lp/soyuz/stories/webservice/xx-archive.txt 2009-09-04 18:18:39 +0000 |
396 | @@ -76,9 +76,9 @@ |
397 | |
398 | The archive has the following attributes: |
399 | |
400 | - >>> main_archive = webservice.get( |
401 | + >>> ubuntu_main_archive = webservice.get( |
402 | ... ubuntutest['main_archive_link']).jsonBody() |
403 | - >>> pprint_entry(main_archive) |
404 | + >>> pprint_entry(ubuntu_main_archive) |
405 | dependencies_collection_link: u'http://.../ubuntutest/+archive/primary/dependencies' |
406 | description: None |
407 | displayname: u'Primary Archive for Ubuntu Test' |
408 | @@ -186,10 +186,10 @@ |
409 | Permission collections can be retrieved with custom operations on the |
410 | archive. |
411 | |
412 | -getPermissionsForPerson returns all the permissions that a user has. |
413 | +`getPermissionsForPerson` returns all the permissions that a user has. |
414 | |
415 | - >>> ubuntu_team = webservice.get("/~ubuntu-team").jsonBody() |
416 | - >>> permissions = webservice.named_get( |
417 | + >>> ubuntu_team = user_webservice.get("/~ubuntu-team").jsonBody() |
418 | + >>> permissions = user_webservice.named_get( |
419 | ... ubuntutest['main_archive_link'], 'getPermissionsForPerson', |
420 | ... person=ubuntu_team['self_link']).jsonBody() |
421 | |
422 | @@ -211,11 +211,11 @@ |
423 | Archive Upload Rights ...~ubuntu-team main None |
424 | Archive Upload Rights ...~ubuntu-team universe None |
425 | |
426 | -getUploadersForPackage returns all the permissions where someone can |
427 | +`getUploadersForPackage` returns all the permissions where someone can |
428 | upload a particular package. |
429 | |
430 | >>> def show_mozilla_permissions(): |
431 | - ... permissions = webservice.named_get( |
432 | + ... permissions = user_webservice.named_get( |
433 | ... ubuntu['main_archive_link'], 'getUploadersForPackage', |
434 | ... source_package_name='mozilla-firefox').jsonBody() |
435 | ... show_permission_entries(permissions) |
436 | @@ -225,17 +225,35 @@ |
437 | |
438 | Passing a bad package name results in an error: |
439 | |
440 | - >>> print webservice.named_get( |
441 | + >>> print user_webservice.named_get( |
442 | ... ubuntu['main_archive_link'], 'getUploadersForPackage', |
443 | ... source_package_name="badpackage") |
444 | HTTP/1.1 400 Bad Request |
445 | ... |
446 | |
447 | -newPackageUploader() is a factory function that adds a new permission for |
448 | -a person to upload a package. |
449 | +Colin is a valid member of the team who owns the ubuntu primary archive. |
450 | + |
451 | + >>> from canonical.launchpad.testing.pages import webservice_for_person |
452 | + >>> from canonical.launchpad.webapp.interfaces import OAuthPermission |
453 | + >>> from lp.registry.interfaces.distribution import IDistributionSet |
454 | + |
455 | + >>> login(ANONYMOUS) |
456 | + >>> cjwatson = getUtility(IPersonSet).getByName('kamion') |
457 | + >>> ubuntu_db = getUtility(IDistributionSet).getByName('ubuntu') |
458 | + >>> cjwatson.inTeam(ubuntu_db.main_archive.owner) |
459 | + True |
460 | + |
461 | + >>> logout() |
462 | + |
463 | + >>> cjwatson_webservice = webservice_for_person( |
464 | + ... cjwatson, permission=OAuthPermission.WRITE_PUBLIC) |
465 | + |
466 | + |
467 | +`newPackageUploader` is a factory function that adds a new permission |
468 | +for a person to upload a package. |
469 | |
470 | >>> name12 = webservice.get("/~name12").jsonBody() |
471 | - >>> response = webservice.named_post( |
472 | + >>> response = cjwatson_webservice.named_post( |
473 | ... ubuntu['main_archive_link'], 'newPackageUploader', {}, |
474 | ... person=name12['self_link'], |
475 | ... source_package_name='mozilla-firefox') |
476 | @@ -243,7 +261,7 @@ |
477 | HTTP/1.1 201 Created |
478 | ... |
479 | |
480 | - >>> new_permission = webservice.get( |
481 | + >>> new_permission = user_webservice.get( |
482 | ... response.getHeader('Location')).jsonBody() |
483 | >>> print new_permission['self_link'] |
484 | http://.../ubuntu/+archive/primary/+upload/name12?type=packagename&item=mozilla-firefox |
485 | @@ -254,7 +272,7 @@ |
486 | |
487 | deletePackageUploader() removes that permission: |
488 | |
489 | - >>> print webservice.named_post( |
490 | + >>> print cjwatson_webservice.named_post( |
491 | ... ubuntu['main_archive_link'], 'deletePackageUploader', {}, |
492 | ... person=name12['self_link'], |
493 | ... source_package_name='mozilla-firefox') |
494 | @@ -270,7 +288,7 @@ |
495 | upload to a particular component: |
496 | |
497 | >>> def show_component_permissions(component=None): |
498 | - ... permissions = webservice.named_get( |
499 | + ... permissions = user_webservice.named_get( |
500 | ... ubuntu['main_archive_link'], 'getUploadersForComponent', |
501 | ... component_name=component).jsonBody() |
502 | ... show_permission_entries(permissions) |
503 | @@ -280,7 +298,7 @@ |
504 | |
505 | Passing a bad component name results in an error: |
506 | |
507 | - >>> print webservice.named_get( |
508 | + >>> print cjwatson_webservice.named_get( |
509 | ... ubuntu['main_archive_link'], 'getUploadersForComponent', |
510 | ... component_name="badcomponent") |
511 | HTTP/1.1 400 Bad Request |
512 | @@ -296,7 +314,7 @@ |
513 | newComponentUploader adds a new permission for a person to upload to a |
514 | component. |
515 | |
516 | - >>> response = webservice.named_post( |
517 | + >>> response = cjwatson_webservice.named_post( |
518 | ... ubuntu['main_archive_link'], 'newComponentUploader', {}, |
519 | ... person=name12['self_link'], |
520 | ... component_name='restricted') |
521 | @@ -304,7 +322,7 @@ |
522 | HTTP/1.1 201 Created |
523 | ... |
524 | |
525 | - >>> new_permission = webservice.get( |
526 | + >>> new_permission = user_webservice.get( |
527 | ... response.getHeader('Location')).jsonBody() |
528 | >>> print new_permission['self_link'] |
529 | http://.../ubuntu/+archive/primary/+upload/name12?type=component&item=restricted |
530 | @@ -315,10 +333,52 @@ |
531 | Archive Upload Rights ...~ubuntu-team restricted None |
532 | Archive Upload Rights ...~ubuntu-team universe None |
533 | |
534 | +deleteComponentUploader() removes that permission: |
535 | + |
536 | + >>> print cjwatson_webservice.named_post( |
537 | + ... ubuntu['main_archive_link'], 'deleteComponentUploader', {}, |
538 | + ... person=name12['self_link'], |
539 | + ... component_name='restricted') |
540 | + HTTP/1.1 200 Ok |
541 | + ... |
542 | + |
543 | +And we can see that it's gone: |
544 | + |
545 | + >>> show_component_permissions() |
546 | + Archive Upload Rights ...~ubuntu-team main None |
547 | + Archive Upload Rights ...~ubuntu-team restricted None |
548 | + Archive Upload Rights ...~ubuntu-team universe None |
549 | + |
550 | +Only the archive owners can add or remove component-uploaders. |
551 | + |
552 | + >>> no_priv = webservice.get("/~no-priv").jsonBody() |
553 | + |
554 | + >>> print user_webservice.named_post( |
555 | + ... cprov_archive['self_link'], 'newComponentUploader', {}, |
556 | + ... person=no_priv['self_link'], component_name='main') |
557 | + HTTP/1.1 401 Unauthorized |
558 | + ... |
559 | + |
560 | + >>> cprov_webservice = webservice_for_person( |
561 | + ... cprov, permission=OAuthPermission.WRITE_PUBLIC) |
562 | + |
563 | + >>> print cprov_webservice.named_post( |
564 | + ... cprov_archive['self_link'], 'newComponentUploader', {}, |
565 | + ... person=no_priv['self_link'], component_name='main') |
566 | + HTTP/1.1 201 Created |
567 | + ... |
568 | + |
569 | + >>> print cprov_webservice.named_post( |
570 | + ... cprov_archive['self_link'], 'deleteComponentUploader', {}, |
571 | + ... person=no_priv['self_link'], |
572 | + ... component_name='main') |
573 | + HTTP/1.1 200 Ok |
574 | + ... |
575 | + |
576 | If you add a new permission for someone to upload to a PPA, you must specify |
577 | the 'main' component, or an error is returned: |
578 | |
579 | - >>> response = webservice.named_post( |
580 | + >>> response = cprov_webservice.named_post( |
581 | ... cprov_archive['self_link'], 'newComponentUploader', {}, |
582 | ... person=name12['self_link'], component_name='restricted') |
583 | >>> print response |
584 | @@ -327,29 +387,6 @@ |
585 | InvalidComponent: Component for PPAs should be 'main' |
586 | <BLANKLINE> |
587 | |
588 | - >>> response = webservice.named_post( |
589 | - ... cprov_archive['self_link'], 'newComponentUploader', {}, |
590 | - ... person=name12['self_link'], component_name='main') |
591 | - >>> print response |
592 | - HTTP/1.1 201 Created |
593 | - ... |
594 | - |
595 | -deleteComponentUploader() removes that permission: |
596 | - |
597 | - >>> print webservice.named_post( |
598 | - ... ubuntu['main_archive_link'], 'deleteComponentUploader', {}, |
599 | - ... person=name12['self_link'], |
600 | - ... component_name='restricted') |
601 | - HTTP/1.1 200 Ok |
602 | - ... |
603 | - |
604 | -And we can see that it's gone: |
605 | - |
606 | - >>> show_component_permissions() |
607 | - Archive Upload Rights ...~ubuntu-team main None |
608 | - Archive Upload Rights ...~ubuntu-team restricted None |
609 | - Archive Upload Rights ...~ubuntu-team universe None |
610 | - |
611 | getQueueAdminsForComponent returns all the permissions where someone |
612 | can administer distroseries queues in a particular component. |
613 | |
614 | @@ -497,18 +534,9 @@ |
615 | For testing purpose we will create some publications. |
616 | |
617 | >>> login('foo.bar@canonical.com') |
618 | - |
619 | - >>> from lp.registry.interfaces.distribution import ( |
620 | - ... IDistributionSet) |
621 | - |
622 | - >>> ubuntu_distro = getUtility(IDistributionSet).getByName('ubuntu') |
623 | - |
624 | - >>> main_archive = ubuntu_distro.main_archive |
625 | - |
626 | - >>> from lp.soyuz.tests.test_publishing import ( |
627 | - ... SoyuzTestPublisher) |
628 | + >>> from lp.soyuz.tests.test_publishing import SoyuzTestPublisher |
629 | >>> test_publisher = SoyuzTestPublisher() |
630 | - >>> hoary = ubuntu_distro.getSeries('hoary') |
631 | + >>> hoary = ubuntu_db.getSeries('hoary') |
632 | >>> test_publisher.addFakeChroots(hoary) |
633 | >>> ignore = test_publisher.setUpDefaultDistroSeries(hoary) |
634 | |
635 | @@ -516,27 +544,22 @@ |
636 | ubuntu primary archive. |
637 | |
638 | >>> ignore = test_publisher.getPubSource( |
639 | - ... sourcename="package1", version="1.0", archive=main_archive) |
640 | - |
641 | - >>> ignore = test_publisher.getPubSource( |
642 | - ... sourcename="package1", version="1.1", archive=main_archive) |
643 | - |
644 | - >>> ignore = test_publisher.getPubSource( |
645 | - ... sourcename="package2", version="1.0", archive=main_archive) |
646 | + ... sourcename="package1", version="1.0", |
647 | + ... archive=ubuntu_db.main_archive) |
648 | + |
649 | + >>> ignore = test_publisher.getPubSource( |
650 | + ... sourcename="package1", version="1.1", |
651 | + ... archive=ubuntu_db.main_archive) |
652 | + |
653 | + >>> ignore = test_publisher.getPubSource( |
654 | + ... sourcename="package2", version="1.0", |
655 | + ... archive=ubuntu_db.main_archive) |
656 | |
657 | A test publication in Celso's PPA. |
658 | |
659 | - >>> cprov = getUtility(IPersonSet).getByName('cprov') |
660 | - |
661 | >>> ignore = test_publisher.getPubSource( |
662 | ... sourcename="package3", version="1.0", archive=cprov.archive) |
663 | |
664 | -Colin is a valid member of the team who owns the ubuntu primary archive. |
665 | - |
666 | - >>> cjwatson = getUtility(IPersonSet).getByName('kamion') |
667 | - >>> cjwatson.inTeam(main_archive.owner) |
668 | - True |
669 | - |
670 | Setup done, let's log out and continue with the tests. |
671 | |
672 | >>> logout() |
673 | @@ -557,13 +580,7 @@ |
674 | When accessed via Colin's key that can perform writes, the API will |
675 | respond positively. |
676 | |
677 | - >>> from canonical.launchpad.testing.pages import webservice_for_person |
678 | - >>> from canonical.launchpad.webapp.interfaces import OAuthPermission |
679 | - |
680 | - >>> admin_webservice = webservice_for_person( |
681 | - ... cjwatson, permission=OAuthPermission.WRITE_PUBLIC) |
682 | - |
683 | - >>> print admin_webservice.named_post( |
684 | + >>> print cjwatson_webservice.named_post( |
685 | ... ubuntu['main_archive_link'], 'syncSource', {}, |
686 | ... source_name='package3', version='1.0', |
687 | ... from_archive=cprov_archive['self_link'], to_pocket='release', |
688 | @@ -575,7 +592,7 @@ |
689 | PPA. The 'admin_write' key created for Colin isn't allowed to modify |
690 | Celso's PPA. |
691 | |
692 | - >>> print admin_webservice.named_post( |
693 | + >>> print cjwatson_webservice.named_post( |
694 | ... cprov_archive['self_link'], 'syncSource', {}, |
695 | ... source_name='package1', version='1.0', |
696 | ... from_archive=ubuntu['main_archive_link'], to_pocket='release', |
697 | @@ -639,7 +656,8 @@ |
698 | # It can be successfully synchronised to Celso's PPA. |
699 | >>> login('foo.bar@canonical.com') |
700 | >>> allowed_source = test_publisher.getPubSource( |
701 | - ... sourcename="allowed", version="1.0", archive=main_archive) |
702 | + ... sourcename="allowed", version="1.0", |
703 | + ... archive=ubuntu_db.main_archive) |
704 | >>> ignore = test_publisher.getPubBinaries(pub_source=allowed_source) |
705 | >>> logout() |
706 | |
707 | @@ -664,7 +682,7 @@ |
708 | ... source_name="allowed").jsonBody()['total_size'] |
709 | 0 |
710 | |
711 | -Keys with not enough permissions in Celso's PPA context are not |
712 | +Keys with insufficient permissions on Celso's PPA context are not |
713 | allowed to call the method at all. |
714 | |
715 | >>> print user_webservice.named_post( |
716 | @@ -675,7 +693,7 @@ |
717 | HTTP/1.1 401 Unauthorized |
718 | ... |
719 | |
720 | - >>> print admin_webservice.named_post( |
721 | + >>> print cjwatson_webservice.named_post( |
722 | ... cprov_archive['self_link'], 'syncSources', {}, |
723 | ... source_names=['package1', 'package2'], |
724 | ... from_archive=ubuntu['main_archive_link'], to_pocket='release', |
725 | @@ -899,9 +917,8 @@ |
726 | >>> from lp.soyuz.interfaces.component import IComponentSet |
727 | >>> from lp.registry.interfaces.pocket import PackagePublishingPocket |
728 | >>> login('foo.bar@canonical.com') |
729 | - >>> cprov_ppa_db = getUtility(IPersonSet).getByName('cprov').archive |
730 | - >>> dep = cprov_ppa_db.addArchiveDependency( |
731 | - ... cprov_ppa_db.distribution.main_archive, |
732 | + >>> dep = cprov.archive.addArchiveDependency( |
733 | + ... cprov.archive.distribution.main_archive, |
734 | ... PackagePublishingPocket.RELEASE, |
735 | ... component=getUtility(IComponentSet)['universe']) |
736 | >>> logout() |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
= Summary =
This branch fixes https:/ /bugs.edge. launchpad. net/bugs/ 422965.
Now the methods for reading and adjusting archive permissions are restricted to IArchive lp.Edit permission (owners) instead of the *special* IArchivePermiss ionSet (only tech board)
- From now own ubuntu-drivers will be able to allow new uploaders in ubuntu primary archive and PPA owners will be able to do the same for their PPAs.
== Tests ==
./bin/test -vv -t xx-archive.txt
== Demo and Q/A ==
Create a PPA if the user you are logged in doesn't have one, otherwise adjust the parameters of the code snipped below
1. Reading permissions: 'no-priv' ] ame(name= 'ppa')
user.display_ name, ppa.displayname) onsForPerson( person= user):
{{{
user = lp.people[
ppa = lp.me.getPPAByN
print 'Permission for %s in %s' % (
for perm in ppa.getPermissi
print perm.permission
}}}
2. Setting permission: 'no-priv' ] ame(name= 'ppa') newComponentUpl oader(person= user, component_ name='main' )
{{{
user = lp.people[
ppa = lp.me.getPPAByN
ppa.
}}}
= Launchpad lint =
Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.
Linting changed files: soyuz/stories/ webservice/ xx-archive. txt soyuz/interface s/archive. py soyuz/configure .zcml
lib/lp/
lib/lp/
lib/lp/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
iEYEARECAAYFAkq ykjkACgkQ7KBXuX yZSjB0xQCgkLYFy zzQ87e23tJDuY7A mJDw 82ziAtkXXhvfszi CW
RlkAn1yplbsf24s
=R4q7
-----END PGP SIGNATURE-----
== Pylint notices ==
lib/lp/ soyuz/interface s/archive. py declarations' (No module named restful) fields' (No module named restful)
39: [F0401] Unable to import 'lazr.enum' (No module named enum)
52: [F0401] Unable to import 'lazr.restful.
58: [F0401] Unable to import 'lazr.restful.