← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~salgado/launchpad/bug-683106 into lp:launchpad

 

Guilherme Salgado has proposed merging lp:~salgado/launchpad/bug-683106 into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  #683106 ISpecification.all_specifications returns an empty list for anonymous users of the API
  https://bugs.launchpad.net/bugs/683106


Add a launchpad.View security adapter for ISpecification so that collections
of it can be seen anonymously on the webservice
-- 
https://code.launchpad.net/~salgado/launchpad/bug-683106/+merge/42351
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~salgado/launchpad/bug-683106 into lp:launchpad.
=== modified file 'lib/canonical/launchpad/security.py'
--- lib/canonical/launchpad/security.py	2010-11-26 18:12:16 +0000
+++ lib/canonical/launchpad/security.py	2010-12-01 12:05:01 +0000
@@ -44,7 +44,10 @@
 from lp.answers.interfaces.faqtarget import IFAQTarget
 from lp.answers.interfaces.question import IQuestion
 from lp.answers.interfaces.questiontarget import IQuestionTarget
-from lp.blueprints.interfaces.specification import ISpecification
+from lp.blueprints.interfaces.specification import (
+    ISpecification,
+    ISpecificationPublic,
+    )
 from lp.blueprints.interfaces.specificationbranch import ISpecificationBranch
 from lp.blueprints.interfaces.specificationsubscription import (
     ISpecificationSubscription,
@@ -494,6 +497,17 @@
         return True
 
 
+class AnonymousAccessToISpecificationPublic(AnonymousAuthorization):
+    """Anonymous users have launchpad.View on ISpecificationPublic.
+
+    This is only needed because lazr.restful is hard-coded to check that
+    permission before returning things in a collection.
+    """
+
+    permission = 'launchpad.View'
+    usedfor = ISpecificationPublic
+
+
 class EditSpecificationByTargetOwnerOrOwnersOrAdmins(AuthorizationBase):
     """We want everybody "related" to a specification to be able to edit it.
     You are related if you have a role on the spec, or if you have a role on

=== modified file 'lib/lp/blueprints/interfaces/specification.py'
--- lib/lp/blueprints/interfaces/specification.py	2010-11-29 18:53:45 +0000
+++ lib/lp/blueprints/interfaces/specification.py	2010-12-01 12:05:01 +0000
@@ -14,6 +14,7 @@
     'INewSpecificationTarget',
     'INewSpecificationProjectTarget',
     'ISpecification',
+    'ISpecificationPublic',
     'ISpecificationSet',
     'ISpecificationDelta',
     ]

=== modified file 'lib/lp/blueprints/tests/test_webservice.py'
--- lib/lp/blueprints/tests/test_webservice.py	2010-11-29 18:53:45 +0000
+++ lib/lp/blueprints/tests/test_webservice.py	2010-12-01 12:05:01 +0000
@@ -5,15 +5,23 @@
 
 __metaclass__ = type
 
+from zope.security.management import endInteraction
+
 from canonical.testing import DatabaseFunctionalLayer
 from canonical.launchpad.testing.pages import webservice_for_person
 from lp.blueprints.interfaces.specification import (
     SpecificationDefinitionStatus,
     )
 from lp.testing import (
+<<<<<<< TREE
     launchpadlib_for,
     TestCaseWithFactory,
     )
+=======
+    launchpadlib_for, TestCaseWithFactory)
+    launchpadlib_for_anonymous,
+    ws_object,
+>>>>>>> MERGE-SOURCE
 
 
 class SpecificationWebserviceTestCase(TestCaseWithFactory):
@@ -215,6 +223,18 @@
         names = [s.name for s in specifications]
         self.assertContentEqual(expected_names, names)
 
+    def test_anonymous_access_to_collection(self):
+        product = self.factory.makeProduct()
+        self.factory.makeSpecification(product=product, name="spec1")
+        self.factory.makeSpecification(product=product, name="spec2")
+        # Need to endInteraction() because launchpadlib_for_anonymous() will
+        # setup a new one.
+        endInteraction()
+        lplib = launchpadlib_for_anonymous('lplib-test', version='devel')
+        ws_product = ws_object(lplib, product)
+        self.assertNamesOfSpecificationsAre(
+            ["spec1", "spec2"], ws_product.all_specifications)
+
     def test_product_all_specifications(self):
         product = self.factory.makeProduct()
         self.factory.makeSpecification(product=product, name="spec1")

=== modified file 'lib/lp/testing/__init__.py'
--- lib/lp/testing/__init__.py	2010-11-26 10:52:10 +0000
+++ lib/lp/testing/__init__.py	2010-12-01 12:05:01 +0000
@@ -154,6 +154,7 @@
 from lp.testing._webservice import (
     launchpadlib_credentials_for,
     launchpadlib_for,
+    launchpadlib_for_anonymous,
     oauth_access_token_for,
     )
 from lp.testing.fixture import ZopeEventHandlerFixture

=== modified file 'lib/lp/testing/_webservice.py'
--- lib/lp/testing/_webservice.py	2010-10-23 16:44:23 +0000
+++ lib/lp/testing/_webservice.py	2010-12-01 12:05:01 +0000
@@ -8,6 +8,7 @@
 __all__ = [
     'launchpadlib_credentials_for',
     'launchpadlib_for',
+    'launchpadlib_for_anonymous',
     'oauth_access_token_for',
     ]
 
@@ -17,6 +18,7 @@
 
 from launchpadlib.credentials import (
     AccessToken,
+    AnonymousAccessToken,
     Credentials,
     )
 from launchpadlib.launchpad import Launchpad
@@ -118,6 +120,21 @@
     shutil.rmtree(cache, ignore_errors=True)
 
 
+def launchpadlib_for_anonymous(
+    consumer_name, version=None, service_root="http://api.launchpad.dev/";):
+    """Create a Launchpad object for the anonymous user.
+
+    :param consumer_name: An OAuth consumer name.
+    :param version: The version of the web service to access.
+    :param service_root: The root URL of the web service to access.
+
+    :return: A launchpadlib.Launchpad object.
+    """
+    token = AnonymousAccessToken()
+    credentials = Credentials(consumer_name, access_token=token)
+    return Launchpad(credentials, service_root, version=version)
+
+
 def launchpadlib_for(
     consumer_name, person, permission=OAuthPermission.WRITE_PRIVATE,
     context=None, version=None, service_root="http://api.launchpad.dev/";):