Merge lp:~julian-edwards/launchpad/perms-for-changing-uploaders--bug-828894 into lp:launchpad

Proposed by Julian Edwards
Status: Merged
Approved by: Julian Edwards
Approved revision: no longer in the source branch.
Merged at revision: 13797
Proposed branch: lp:~julian-edwards/launchpad/perms-for-changing-uploaders--bug-828894
Merge into: lp:launchpad
Diff against target: 478 lines (+144/-131)
7 files modified
lib/canonical/launchpad/security.py (+16/-9)
lib/lp/soyuz/configure.zcml (+1/-25)
lib/lp/soyuz/doc/archivepermission.txt (+3/-40)
lib/lp/soyuz/interfaces/archive.py (+41/-41)
lib/lp/soyuz/interfaces/archivepermission.py (+9/-0)
lib/lp/soyuz/stories/webservice/xx-archive.txt (+67/-11)
lib/lp/soyuz/tests/test_archive.py (+7/-5)
To merge this branch: bzr merge lp:~julian-edwards/launchpad/perms-for-changing-uploaders--bug-828894
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+72220@code.launchpad.net

Commit message

[r=sinzui][bug=828894] Fix the permissions required to change uploader-related permissions on a distribution.

Description of the change

= Summary =
Fix the permissions required to change uploader-related permissions
on a distribution.

== Proposed fix ==
There are three types of upload permissions for a distribution's primary
archive:
 1. component-based
 2. package-based
 3. packageset-based

Right now to change #1 and #2 you need to be in the team that owns the archive
object. To change #3 you need to be an admin or a member of Ubuntu Techboard.

These 2 rules are basically useless for anything other than Ubuntu because
 * There's no way to alter the archive owner other than via SQL
 * Derived distros don't want Ubuntu Techboard changing their permissions!

This branch fixes this situation so that the two different rules are unified
so that you need to be in the *distribution's* owning team (this is Maintainer
on the distro page) to change these permissions.

== Pre-implementation notes ==

Discussed with Gavin as I had a PEBKAC moment working out how the heck
we'd got by without an EditArchive security adapter up until now but it turns
out that it inherits the IHasOwner magic.

== Implementation details ==

Several changes were needed:

 * Add a new security adapter for IArchive/launchpad.Edit that allows
   distro main archives to be edited by the distro owner or an admin, and
   leaves PPAs editable by their archive owners.

 * Remove the EditArchivePermissionSet security adapter, it is redundant
   because it can never have enough contextual information to be useful (it
   doesn't know what the archive is). We now rely on the utility only getting
   called via IArchive code.

 * Change the zcml declaration for IArchivePermissionSet to allow any caller
   to call its methods.

 * Remove unnecessary testing in lib/lp/soyuz/doc/archivepermission.txt

 * Add a warning in lib/lp/soyuz/interfaces/archivepermission.py about never
   exporting ArchivePermissionSet on the webservice because it has no
   good security model.

 * Fix lib/lp/soyuz/stories/webservice/xx-archive.txt to handle the new
   security checks.

 * Fix lib/lp/soyuz/tests/test_archive.py to not rely on the old checks
   to alter some of the uploader permissions.

== Tests ==

bin/test -cvvt test_archive -t xx-archive.txt -t archivepermission.txt

And probably more, I've not run this through ec2 yet.

== Demo and Q/A ==

Dogfood.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you for this fix. I believe with your change that there is exactly one call for user.in_ubuntu_techboard Which is used in security.py and defined in lp/registry/interfaces/role.py. Is there any chance you could also change EditPackagesetSet to not use that role and remove the role from code?

review: Approve (code)
Revision history for this message
Julian Edwards (julian-edwards) wrote :

Thanks Curtis. I won't do that change in this branch, but I'll file a bug and fix it soon, I'd forgotten about that.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/security.py'
--- lib/canonical/launchpad/security.py 2011-08-24 00:47:25 +0000
+++ lib/canonical/launchpad/security.py 2011-08-25 10:17:54 +0000
@@ -2246,6 +2246,22 @@
2246 return not self.obj.private and self.obj.enabled2246 return not self.obj.private and self.obj.enabled
22472247
22482248
2249class EditArchive(AuthorizationBase):
2250 """Restrict archive editing operations.
2251
2252 If the archive a primary archive then we check the user is in the
2253 distribution's owning team, otherwise we check the archive owner.
2254 """
2255 permission = 'launchpad.Edit'
2256 usedfor = IArchive
2257
2258 def checkAuthenticated(self, user):
2259 if self.obj.is_main:
2260 return user.isOwner(self.obj.distribution) or user.in_admin
2261
2262 return user.isOwner(self.obj) or user.in_admin
2263
2264
2249class AppendArchive(AuthorizationBase):2265class AppendArchive(AuthorizationBase):
2250 """Restrict appending (upload and copy) operations on archives.2266 """Restrict appending (upload and copy) operations on archives.
22512267
@@ -2535,15 +2551,6 @@
2535 usedfor = IWikiName2551 usedfor = IWikiName
25362552
25372553
2538class EditArchivePermissionSet(AuthorizationBase):
2539 permission = 'launchpad.Edit'
2540 usedfor = IArchivePermissionSet
2541
2542 def checkAuthenticated(self, user):
2543 """Users must be an admin or a member of the tech board."""
2544 return user.in_admin or user.in_ubuntu_techboard
2545
2546
2547class ViewPackageset(AnonymousAuthorization):2554class ViewPackageset(AnonymousAuthorization):
2548 """Anyone can view an IPackageset."""2555 """Anyone can view an IPackageset."""
2549 usedfor = IPackageset2556 usedfor = IPackageset
25502557
=== modified file 'lib/lp/soyuz/configure.zcml'
--- lib/lp/soyuz/configure.zcml 2011-08-24 00:47:25 +0000
+++ lib/lp/soyuz/configure.zcml 2011-08-25 10:17:54 +0000
@@ -471,31 +471,7 @@
471 class="lp.soyuz.model.archivepermission.ArchivePermissionSet"471 class="lp.soyuz.model.archivepermission.ArchivePermissionSet"
472 provides="lp.soyuz.interfaces.archivepermission.IArchivePermissionSet">472 provides="lp.soyuz.interfaces.archivepermission.IArchivePermissionSet">
473 <allow473 <allow
474 attributes="474 interface="lp.soyuz.interfaces.archivepermission.IArchivePermissionSet"/>
475 checkAuthenticated
476 componentsForUploader
477 uploadersForComponent
478 packagesForUploader
479 uploadersForPackage
480 queueAdminsForComponent
481 componentsForQueueAdmin
482 permissionsForPerson
483 uploadersForPackageset
484 packagesetsForUploader
485 packagesetsForSource
486 packagesetsForSourceUploader
487 isSourceUploadAllowed
488 newPackageUploader
489 newComponentUploader
490 newQueueAdmin
491 deletePackageUploader
492 deleteComponentUploader
493 deleteQueueAdmin"/>
494 <require
495 permission="launchpad.Edit"
496 attributes="
497 newPackagesetUploader
498 deletePackagesetUploader"/>
499 </securedutility>475 </securedutility>
500476
501 <!-- BinaryPackageBuild -->477 <!-- BinaryPackageBuild -->
502478
=== modified file 'lib/lp/soyuz/doc/archivepermission.txt'
--- lib/lp/soyuz/doc/archivepermission.txt 2011-08-24 00:47:25 +0000
+++ lib/lp/soyuz/doc/archivepermission.txt 2011-08-25 10:17:54 +0000
@@ -266,46 +266,9 @@
266~~~~~~~~~~~~~~~~~~~~266~~~~~~~~~~~~~~~~~~~~
267267
268There are some methods that will enable the caller to add and delete268There are some methods that will enable the caller to add and delete
269PackageSet based permissions. They currently require launchpad.Edit269PackageSet based permissions. They require no special permission to use
270permission to use, which enforces the user to be an admin or a member270because these methods should only ever be called from inside other security
271of the "techboard" (Ubuntu Technical Board) team.271proxied objects like IArchive.
272
273Set up a helper function to check access:
274
275 >>> from zope.security.checker import canAccess
276 >>> from zope.security.proxy import removeSecurityProxy
277 >>> restricted_methods = (
278 ... 'newPackagesetUploader',
279 ... 'deletePackagesetUploader',
280 ... )
281 >>> def checkAccess(true_or_false):
282 ... for method in restricted_methods:
283 ... assert(canAccess(permission_set, method) == true_or_false)
284 >>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
285 >>> from lp.registry.interfaces.person import IPersonSet
286 >>> from lp.registry.interfaces.teammembership import (
287 ... TeamMembershipStatus)
288 >>> personset = getUtility(IPersonSet)
289 >>> techboard = getUtility(ILaunchpadCelebrities).ubuntu_techboard
290 >>> techboard = removeSecurityProxy(techboard)
291
292Ordinary users have no access:
293
294 >>> login("test@canonical.com")
295 >>> checkAccess(False)
296
297Admins have access:
298
299 >>> login("foo.bar@canonical.com")
300 >>> checkAccess(True)
301
302Now add "test@canonical.com" to the techboard team and log in as him.
303
304 >>> person = personset.getByEmail("test@canonical.com")
305 >>> ignored = techboard.addMember(
306 ... person, reviewer=person, status=TeamMembershipStatus.APPROVED,
307 ... force_team_add=True)
308 >>> login_person(person)
309272
310newPackageUploader() creates a permission for a person to upload to a273newPackageUploader() creates a permission for a person to upload to a
311specific package:274specific package:
312275
=== modified file 'lib/lp/soyuz/interfaces/archive.py'
--- lib/lp/soyuz/interfaces/archive.py 2011-08-01 15:28:09 +0000
+++ lib/lp/soyuz/interfaces/archive.py 2011-08-25 10:17:54 +0000
@@ -711,29 +711,6 @@
711 """711 """
712712
713 @operation_parameters(713 @operation_parameters(
714 person=Reference(schema=IPerson),
715 # Really IPackageset, corrected in _schema_circular_imports to avoid
716 # circular import.
717 packageset=Reference(
718 Interface, title=_("Package set"), required=True),
719 explicit=Bool(
720 title=_("Explicit"), required=False))
721 # Really IArchivePermission, set in _schema_circular_imports to avoid
722 # circular import.
723 @export_factory_operation(Interface, [])
724 def newPackagesetUploader(person, packageset, explicit=False):
725 """Add a package set based permission for a person.
726
727 :param person: An `IPerson` for whom you want to add permission.
728 :param packageset: An `IPackageset`.
729 :param explicit: True if the package set in question requires
730 specialist skills for proper handling.
731
732 :return: The new `ArchivePermission`, or the existing one if it
733 already exists.
734 """
735
736 @operation_parameters(
737 # Really IPackageset, corrected in _schema_circular_imports to avoid714 # Really IPackageset, corrected in _schema_circular_imports to avoid
738 # circular import.715 # circular import.
739 packageset=Reference(716 packageset=Reference(
@@ -757,24 +734,6 @@
757 """734 """
758735
759 @operation_parameters(736 @operation_parameters(
760 person=Reference(schema=IPerson),
761 # Really IPackageset, corrected in _schema_circular_imports to avoid
762 # circular import.
763 packageset=Reference(
764 Interface, title=_("Package set"), required=True),
765 explicit=Bool(
766 title=_("Explicit"), required=False))
767 @export_write_operation()
768 def deletePackagesetUploader(person, packageset, explicit=False):
769 """Revoke upload permissions for a person.
770
771 :param person: An `IPerson` for whom you want to revoke permission.
772 :param packageset: An `IPackageset`.
773 :param explicit: The value of the 'explicit' flag for the permission
774 to be revoked.
775 """
776
777 @operation_parameters(
778 person=Reference(schema=IPerson))737 person=Reference(schema=IPerson))
779 # Really IArchivePermission, set in _schema_circular_imports to avoid738 # Really IArchivePermission, set in _schema_circular_imports to avoid
780 # circular import.739 # circular import.
@@ -1490,6 +1449,29 @@
14901449
1491 @operation_parameters(1450 @operation_parameters(
1492 person=Reference(schema=IPerson),1451 person=Reference(schema=IPerson),
1452 # Really IPackageset, corrected in _schema_circular_imports to avoid
1453 # circular import.
1454 packageset=Reference(
1455 Interface, title=_("Package set"), required=True),
1456 explicit=Bool(
1457 title=_("Explicit"), required=False))
1458 # Really IArchivePermission, set in _schema_circular_imports to avoid
1459 # circular import.
1460 @export_factory_operation(Interface, [])
1461 def newPackagesetUploader(person, packageset, explicit=False):
1462 """Add a package set based permission for a person.
1463
1464 :param person: An `IPerson` for whom you want to add permission.
1465 :param packageset: An `IPackageset`.
1466 :param explicit: True if the package set in question requires
1467 specialist skills for proper handling.
1468
1469 :return: The new `ArchivePermission`, or the existing one if it
1470 already exists.
1471 """
1472
1473 @operation_parameters(
1474 person=Reference(schema=IPerson),
1493 source_package_name=TextLine(1475 source_package_name=TextLine(
1494 title=_("Source Package Name"), required=True))1476 title=_("Source Package Name"), required=True))
1495 @export_write_operation()1477 @export_write_operation()
@@ -1528,6 +1510,24 @@
1528 :param component: An `IComponent` or textual component name.1510 :param component: An `IComponent` or textual component name.
1529 """1511 """
15301512
1513 @operation_parameters(
1514 person=Reference(schema=IPerson),
1515 # Really IPackageset, corrected in _schema_circular_imports to avoid
1516 # circular import.
1517 packageset=Reference(
1518 Interface, title=_("Package set"), required=True),
1519 explicit=Bool(
1520 title=_("Explicit"), required=False))
1521 @export_write_operation()
1522 def deletePackagesetUploader(person, packageset, explicit=False):
1523 """Revoke upload permissions for a person.
1524
1525 :param person: An `IPerson` for whom you want to revoke permission.
1526 :param packageset: An `IPackageset`.
1527 :param explicit: The value of the 'explicit' flag for the permission
1528 to be revoked.
1529 """
1530
1531 def enable():1531 def enable():
1532 """Enable the archive."""1532 """Enable the archive."""
15331533
15341534
=== modified file 'lib/lp/soyuz/interfaces/archivepermission.py'
--- lib/lp/soyuz/interfaces/archivepermission.py 2011-08-24 00:47:25 +0000
+++ lib/lp/soyuz/interfaces/archivepermission.py 2011-08-25 10:17:54 +0000
@@ -129,6 +129,15 @@
129class IArchivePermissionSet(Interface):129class IArchivePermissionSet(Interface):
130 """The interface for `ArchivePermissionSet`."""130 """The interface for `ArchivePermissionSet`."""
131131
132 # Do not export this utility directly on the webservice. There is
133 # no reasonable security model we can implement for it because it
134 # requires the archive context to be able to make an informed
135 # security decision.
136 #
137 # For this reason, the security declaration in the zcml is
138 # deliberately permissive. We don't expect anything to access this
139 # utility except the IArchive code, which is appropriately protected.
140
132 def checkAuthenticated(person, archive, permission, item):141 def checkAuthenticated(person, archive, permission, item):
133 """The `ArchivePermission` records that authenticate the person.142 """The `ArchivePermission` records that authenticate the person.
134143
135144
=== modified file 'lib/lp/soyuz/stories/webservice/xx-archive.txt'
--- lib/lp/soyuz/stories/webservice/xx-archive.txt 2011-08-24 00:47:25 +0000
+++ lib/lp/soyuz/stories/webservice/xx-archive.txt 2011-08-25 10:17:54 +0000
@@ -1,7 +1,7 @@
1Archives1Archives
2========2========
33
4Representations for IArchive can be fetch via the API for PPAs and4Representations for IArchive can be fetched via the API for PPAs and
5distribution archives.5distribution archives.
66
7 >>> cprov_archive = webservice.get("/~cprov/+archive/ppa").jsonBody()7 >>> cprov_archive = webservice.get("/~cprov/+archive/ppa").jsonBody()
@@ -270,24 +270,80 @@
270 >>> from canonical.launchpad.testing.pages import webservice_for_person270 >>> from canonical.launchpad.testing.pages import webservice_for_person
271 >>> from canonical.launchpad.webapp.interfaces import OAuthPermission271 >>> from canonical.launchpad.webapp.interfaces import OAuthPermission
272 >>> from lp.registry.interfaces.distribution import IDistributionSet272 >>> from lp.registry.interfaces.distribution import IDistributionSet
273 >>> from lp.testing.factory import LaunchpadObjectFactory
274 >>> factory = LaunchpadObjectFactory()
273275
274 >>> login(ANONYMOUS)276 >>> login('foo.bar@canonical.com')
275 >>> cjwatson = getUtility(IPersonSet).getByName('kamion')277 >>> cjwatson = getUtility(IPersonSet).getByName('kamion')
276 >>> ubuntu_db = getUtility(IDistributionSet).getByName('ubuntu')278 >>> ubuntu_db = getUtility(IDistributionSet).getByName('ubuntu')
277 >>> cjwatson.inTeam(ubuntu_db.main_archive.owner)279 >>> cjwatson.inTeam(ubuntu_db.main_archive.owner)
278 True280 True
279281
282Let's also make a new Person to own the Ubuntu distro.
283
284 >>> ubuntu_owner = factory.makePerson()
285 >>> ubuntu_db.owner = ubuntu_owner
286
280 >>> logout()287 >>> logout()
281288
282 >>> cjwatson_webservice = webservice_for_person(289 >>> cjwatson_webservice = webservice_for_person(
283 ... cjwatson, permission=OAuthPermission.WRITE_PUBLIC)290 ... cjwatson, permission=OAuthPermission.WRITE_PUBLIC)
284291 >>> ubuntu_owner_webservice = webservice_for_person(
292 ... ubuntu_owner, permission=OAuthPermission.WRITE_PUBLIC)
293 >>> name12 = webservice.get("/~name12").jsonBody()
294
295And here's a packageset to play with later:
296
297 >>> print webservice.named_post(
298 ... '/package-sets', 'new', {},
299 ... name=u'umbrella', description=u'Contains all source packages',
300 ... owner=name12['self_link'])
301 HTTP/1.1 201 Created
302 ...
303
304 >>> packageset = webservice.get("/package-sets/hoary/umbrella").jsonBody()
305
306
307To be able to amend any permissions on a distribution archive,
308you need to be one of the distribution owners - not one of the archive
309owners. Here, cjwatson cannot make a new package uploader, packageset
310uploader or component uploader.
311
312 >>> response = cjwatson_webservice.named_post(
313 ... ubuntu['main_archive_link'], 'newPackageUploader', {},
314 ... person=name12['self_link'],
315 ... source_package_name='mozilla-firefox')
316 >>> print response
317 HTTP/1.1 401 Unauthorized
318 ...
319 (<Archive at ...>, 'newPackageUploader', 'launchpad.Edit')
320
321 >>> response = cjwatson_webservice.named_post(
322 ... ubuntu['main_archive_link'], 'newPackagesetUploader', {},
323 ... person=name12['self_link'],
324 ... packageset=packageset['self_link'])
325 >>> print response
326 HTTP/1.1 401 Unauthorized
327 ...
328 (<Archive at ...>, 'newPackagesetUploader', 'launchpad.Edit')
329
330 >>> response = cjwatson_webservice.named_post(
331 ... ubuntu['main_archive_link'], 'newComponentUploader', {},
332 ... person=name12['self_link'],
333 ... component_name='restricted')
334 >>> print response
335 HTTP/1.1 401 Unauthorized
336 ...
337 (<Archive at ...>, 'newComponentUploader', 'launchpad.Edit')
338
339From here on we'll use ubuntu_owner, who does have permission as Ubuntu's
340owner.
285341
286`newPackageUploader` is a factory function that adds a new permission342`newPackageUploader` is a factory function that adds a new permission
287for a person to upload a package.343for a person to upload a package.
288344
289 >>> name12 = webservice.get("/~name12").jsonBody()345 >>> name12 = webservice.get("/~name12").jsonBody()
290 >>> response = cjwatson_webservice.named_post(346 >>> response = ubuntu_owner_webservice.named_post(
291 ... ubuntu['main_archive_link'], 'newPackageUploader', {},347 ... ubuntu['main_archive_link'], 'newPackageUploader', {},
292 ... person=name12['self_link'],348 ... person=name12['self_link'],
293 ... source_package_name='mozilla-firefox')349 ... source_package_name='mozilla-firefox')
@@ -306,7 +362,7 @@
306362
307deletePackageUploader() removes that permission:363deletePackageUploader() removes that permission:
308364
309 >>> print cjwatson_webservice.named_post(365 >>> print ubuntu_owner_webservice.named_post(
310 ... ubuntu['main_archive_link'], 'deletePackageUploader', {},366 ... ubuntu['main_archive_link'], 'deletePackageUploader', {},
311 ... person=name12['self_link'],367 ... person=name12['self_link'],
312 ... source_package_name='mozilla-firefox')368 ... source_package_name='mozilla-firefox')
@@ -348,7 +404,7 @@
348newComponentUploader adds a new permission for a person to upload to a404newComponentUploader adds a new permission for a person to upload to a
349component.405component.
350406
351 >>> response = cjwatson_webservice.named_post(407 >>> response = ubuntu_owner_webservice.named_post(
352 ... ubuntu['main_archive_link'], 'newComponentUploader', {},408 ... ubuntu['main_archive_link'], 'newComponentUploader', {},
353 ... person=name12['self_link'],409 ... person=name12['self_link'],
354 ... component_name='restricted')410 ... component_name='restricted')
@@ -382,7 +438,7 @@
382438
383deleteComponentUploader() removes that permission:439deleteComponentUploader() removes that permission:
384440
385 >>> print cjwatson_webservice.named_post(441 >>> print ubuntu_owner_webservice.named_post(
386 ... ubuntu['main_archive_link'], 'deleteComponentUploader', {},442 ... ubuntu['main_archive_link'], 'deleteComponentUploader', {},
387 ... person=name12['self_link'],443 ... person=name12['self_link'],
388 ... component_name='restricted')444 ... component_name='restricted')
@@ -411,7 +467,7 @@
411 this distribution's primary archive. Did you mean to upload to a PPA?467 this distribution's primary archive. Did you mean to upload to a PPA?
412468
413469
414Only the archive owners can add or remove component-uploaders.470For PPAs, only the archive owners can add or remove component-uploaders.
415471
416 >>> no_priv = webservice.get("/~no-priv").jsonBody()472 >>> no_priv = webservice.get("/~no-priv").jsonBody()
417473
@@ -479,7 +535,7 @@
479newQueueAdmin adds a new permission for a person to administer distroseries535newQueueAdmin adds a new permission for a person to administer distroseries
480queues in a particular component.536queues in a particular component.
481537
482 >>> response = webservice.named_post(538 >>> response = ubuntu_owner_webservice.named_post(
483 ... ubuntu['main_archive_link'], 'newQueueAdmin', {},539 ... ubuntu['main_archive_link'], 'newQueueAdmin', {},
484 ... person=name12['self_link'],540 ... person=name12['self_link'],
485 ... component_name='partner')541 ... component_name='partner')
@@ -487,7 +543,7 @@
487 HTTP/1.1 201 Created543 HTTP/1.1 201 Created
488 ...544 ...
489545
490 >>> new_permission = webservice.get(546 >>> new_permission = ubuntu_owner_webservice.get(
491 ... response.getHeader('Location')).jsonBody()547 ... response.getHeader('Location')).jsonBody()
492 >>> print new_permission['self_link']548 >>> print new_permission['self_link']
493 http://.../ubuntu/+archive/primary/+queue-admin/name12?type=component&item=partner549 http://.../ubuntu/+archive/primary/+queue-admin/name12?type=component&item=partner
@@ -501,7 +557,7 @@
501557
502deleteQueueAdmin removes that permission.558deleteQueueAdmin removes that permission.
503559
504 >>> print webservice.named_post(560 >>> print ubuntu_owner_webservice.named_post(
505 ... ubuntu['main_archive_link'], 'deleteQueueAdmin', {},561 ... ubuntu['main_archive_link'], 'deleteQueueAdmin', {},
506 ... person=name12['self_link'],562 ... person=name12['self_link'],
507 ... component_name='partner')563 ... component_name='partner')
508564
=== modified file 'lib/lp/soyuz/tests/test_archive.py'
--- lib/lp/soyuz/tests/test_archive.py 2011-08-24 00:47:25 +0000
+++ lib/lp/soyuz/tests/test_archive.py 2011-08-25 10:17:54 +0000
@@ -480,6 +480,9 @@
480 def test_checkArchivePermission_distro_archive(self):480 def test_checkArchivePermission_distro_archive(self):
481 # Regular users can not upload to ubuntu481 # Regular users can not upload to ubuntu
482 archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY)482 archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
483 # The factory sets the archive owner the same as the distro owner,
484 # change that here to ensure the security adapter checks are right.
485 removeSecurityProxy(archive).owner = self.factory.makePerson()
483 main = getUtility(IComponentSet)["main"]486 main = getUtility(IComponentSet)["main"]
484 # A regular user doesn't have access487 # A regular user doesn't have access
485 somebody = self.factory.makePerson()488 somebody = self.factory.makePerson()
@@ -487,7 +490,7 @@
487 archive.checkArchivePermission(somebody, main))490 archive.checkArchivePermission(somebody, main))
488 # An ubuntu core developer does have access491 # An ubuntu core developer does have access
489 coredev = self.factory.makePerson()492 coredev = self.factory.makePerson()
490 with person_logged_in(archive.owner):493 with person_logged_in(archive.distribution.owner):
491 archive.newComponentUploader(coredev, main.name)494 archive.newComponentUploader(coredev, main.name)
492 self.assertEquals(True, archive.checkArchivePermission(coredev, main))495 self.assertEquals(True, archive.checkArchivePermission(coredev, main))
493496
@@ -679,8 +682,7 @@
679 packageset = self.factory.makePackageset(682 packageset = self.factory.makePackageset(
680 distroseries=distroseries, packages=packages)683 distroseries=distroseries, packages=packages)
681 person = self.factory.makePerson()684 person = self.factory.makePerson()
682 techboard = getUtility(ILaunchpadCelebrities).ubuntu_techboard685 with person_logged_in(archive.distribution.owner):
683 with person_logged_in(techboard):
684 archive.newPackagesetUploader(person, packageset)686 archive.newPackagesetUploader(person, packageset)
685 return person, packageset687 return person, packageset
686688
@@ -2137,7 +2139,7 @@
2137 to_series, version) = self._setup_copy_data(2139 to_series, version) = self._setup_copy_data(
2138 target_purpose=ArchivePurpose.PRIMARY)2140 target_purpose=ArchivePurpose.PRIMARY)
2139 person = self.factory.makePerson()2141 person = self.factory.makePerson()
2140 with person_logged_in(target_archive.owner):2142 with person_logged_in(target_archive.distribution.owner):
2141 target_archive.newComponentUploader(person, "universe")2143 target_archive.newComponentUploader(person, "universe")
2142 target_archive.copyPackage(2144 target_archive.copyPackage(
2143 source_name, version, source_archive, to_pocket.name,2145 source_name, version, source_archive, to_pocket.name,
@@ -2244,7 +2246,7 @@
2244 to_series, version) = self._setup_copy_data(2246 to_series, version) = self._setup_copy_data(
2245 target_purpose=ArchivePurpose.PRIMARY)2247 target_purpose=ArchivePurpose.PRIMARY)
2246 person = self.factory.makePerson()2248 person = self.factory.makePerson()
2247 with person_logged_in(target_archive.owner):2249 with person_logged_in(target_archive.distribution.owner):
2248 target_archive.newComponentUploader(person, "universe")2250 target_archive.newComponentUploader(person, "universe")
2249 target_archive.copyPackages(2251 target_archive.copyPackages(
2250 [source_name], source_archive, to_pocket.name,2252 [source_name], source_archive, to_pocket.name,