launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #04402
[Merge] lp:~jml/launchpad/create-private-ppa-814567 into lp:launchpad
Jonathan Lange has proposed merging lp:~jml/launchpad/create-private-ppa-814567 into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #814567 in Launchpad itself: "Need extra round-trip to create a private PPA via webservice"
https://bugs.launchpad.net/launchpad/+bug/814567
For more details, see:
https://code.launchpad.net/~jml/launchpad/create-private-ppa-814567/+merge/69539
This branch makes it possible to create private PPAs over the webservice.
I couldn't find a good way to do the check on creation. Currently the ability to change privacy is controlled by a Zope attribute security check. I don't know how that works wrt object creation, and I *certainly* don't know how that works given that Archive.private is a property with side effects.
Thus, I duplicated the check that takes place in the security permission.
I also couldn't find a good set of tests that I could repurpose to make sure that setting .private and specifying private=True behaved the same.
Note that setting .private over the API raises 401 Unauthorized, but specifying private to createPPA raises 400 Bad Request.
--
https://code.launchpad.net/~jml/launchpad/create-private-ppa-814567/+merge/69539
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jml/launchpad/create-private-ppa-814567 into lp:launchpad.
=== modified file 'lib/lp/registry/interfaces/person.py'
--- lib/lp/registry/interfaces/person.py 2011-05-31 03:49:23 +0000
+++ lib/lp/registry/interfaces/person.py 2011-07-27 19:34:00 +0000
@@ -1400,16 +1400,20 @@
@operation_parameters(
name=TextLine(required=True, constraint=name_validator),
displayname=TextLine(required=False),
- description=TextLine(required=False))
+ description=TextLine(required=False),
+ private=Bool(required=False),
+ )
@export_factory_operation(Interface, []) # Really IArchive.
@operation_for_version("beta")
- def createPPA(name=None, displayname=None, description=None):
+ def createPPA(name=None, displayname=None, description=None, private=False):
"""Create a PPA.
:param name: A string with the name of the new PPA to create. If
not specified, defaults to 'ppa'.
:param displayname: The displayname for the new PPA.
:param description: The description for the new PPA.
+ :param private: Whether or not to create a private PPA. Defaults to
+ False, which means the PPA will be public.
:raises: `PPACreationError` if an error is encountered
:return: a PPA `IArchive` record.
=== modified file 'lib/lp/registry/model/person.py'
--- lib/lp/registry/model/person.py 2011-06-16 20:12:00 +0000
+++ lib/lp/registry/model/person.py 2011-07-27 19:34:00 +0000
@@ -2739,17 +2739,17 @@
"""See `IPerson`."""
return getUtility(IArchiveSet).getPPAOwnedByPerson(self, name)
- def createPPA(self, name=None, displayname=None, description=None):
+ def createPPA(self, name=None, displayname=None, description=None,
+ private=False):
"""See `IPerson`."""
- errors = Archive.validatePPA(self, name)
+ errors = Archive.validatePPA(self, name, private)
if errors:
raise PPACreationError(errors)
ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
- ppa = getUtility(IArchiveSet).new(
+ return getUtility(IArchiveSet).new(
owner=self, purpose=ArchivePurpose.PPA,
distribution=ubuntu, name=name, displayname=displayname,
description=description)
- return ppa
def isBugContributor(self, user=None):
"""See `IPerson`."""
=== modified file 'lib/lp/soyuz/model/archive.py'
--- lib/lp/soyuz/model/archive.py 2011-07-22 13:28:35 +0000
+++ lib/lp/soyuz/model/archive.py 2011-07-27 19:34:00 +0000
@@ -1947,8 +1947,12 @@
self.enabled_restricted_families = restricted
@classmethod
- def validatePPA(self, person, proposed_name):
+ def validatePPA(self, person, proposed_name, private=False):
ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
+ if private:
+ commercial = getUtility(ILaunchpadCelebrities).commercial_admin
+ if not person.inTeam(commercial):
+ return '%s is not allowed to make private PPAs' % (person.name,)
if person.isTeam() and (
person.subscriptionpolicy in OPEN_TEAM_POLICY):
return "Open teams cannot have PPAs."
=== modified file 'lib/lp/soyuz/stories/webservice/xx-person-createppa.txt'
--- lib/lp/soyuz/stories/webservice/xx-person-createppa.txt 2011-02-13 22:54:48 +0000
+++ lib/lp/soyuz/stories/webservice/xx-person-createppa.txt 2011-07-27 19:34:00 +0000
@@ -30,3 +30,31 @@
Status: 400 Bad Request
...
A PPA cannot have the same name as its distribution.
+
+== Creating private PPAs ==
+
+Our PPA owner now has a single PPA.
+
+ >>> print_self_link_of_entries(webservice.get(
+ ... ppa_owner['ppas_collection_link']).jsonBody())
+ http://api.launchpad.dev/beta/~.../+archive/ppa
+
+They aren't a commercial admin, so they cannot create private PPAs.
+
+ >>> print ppa_owner_webservice.named_post(
+ ... ppa_owner['self_link'], 'createPPA', {}, name='whatever',
+ ... displayname='My secret new PPA', description='Secretness!',
+ ... private=True,
+ ... )
+ HTTP/1.1 400 Bad Request
+ Status: 400
+ ...
+ ... is not allowed to make private PPAs
+
+After attempting and failing to create a private PPA, they still have the same
+single PPA they had at the beginning:
+
+ >>> print_self_link_of_entries(webservice.get(
+ ... ppa_owner['ppas_collection_link']).jsonBody())
+ http://api.launchpad.dev/beta/~.../+archive/ppa
+
=== modified file 'lib/lp/soyuz/tests/test_archive.py'
--- lib/lp/soyuz/tests/test_archive.py 2011-07-22 13:31:35 +0000
+++ lib/lp/soyuz/tests/test_archive.py 2011-07-27 19:34:00 +0000
@@ -1624,7 +1624,7 @@
set(archive.getComponentsForUploader(person)))
-class TestvalidatePPA(TestCaseWithFactory):
+class TestValidatePPA(TestCaseWithFactory):
layer = DatabaseFunctionalLayer
@@ -1639,6 +1639,23 @@
'A PPA cannot have the same name as its distribution.',
Archive.validatePPA(ppa_owner, 'ubuntu'))
+ def test_private_ppa_non_commercial_admin(self):
+ ppa_owner = self.factory.makePerson()
+ self.assertEqual(
+ '%s is not allowed to make private PPAs' % (ppa_owner.name,),
+ Archive.validatePPA(ppa_owner, self.factory.getUniqueString(),
+ private=True))
+
+ def test_private_ppa_commercial_admin(self):
+ ppa_owner = self.factory.makePerson()
+ with celebrity_logged_in('admin'):
+ comm = getUtility(ILaunchpadCelebrities).commercial_admin
+ comm.addMember(ppa_owner, comm.teamowner)
+ self.assertIs(
+ None,
+ Archive.validatePPA(ppa_owner, self.factory.getUniqueString(),
+ private=True))
+
def test_two_ppas(self):
ppa = self.factory.makeArchive(name='ppa')
self.assertEqual("You already have a PPA named 'ppa'.",