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

Proposed by Guilherme Salgado
Status: Merged
Merged at revision: 12011
Proposed branch: lp:~salgado/launchpad/bug-683106
Merge into: lp:launchpad
Diff against target: 141 lines (+50/-1)
5 files modified
lib/canonical/launchpad/security.py (+15/-1)
lib/lp/blueprints/interfaces/specification.py (+1/-0)
lib/lp/blueprints/tests/test_webservice.py (+16/-0)
lib/lp/testing/__init__.py (+1/-0)
lib/lp/testing/_webservice.py (+17/-0)
To merge this branch: bzr merge lp:~salgado/launchpad/bug-683106
Reviewer Review Type Date Requested Status
Jelmer Vernooij (community) Approve
Review via email: mp+42351@code.launchpad.net

Commit message

[r=jelmer][ui=none][bug=683106]

Description of the change

Add a launchpad.View security adapter for ISpecification so that collections
of it can be seen anonymously on the webservice

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve

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-11-26 18:12:16 +0000
3+++ lib/canonical/launchpad/security.py 2010-12-01 13:02:06 +0000
4@@ -44,7 +44,10 @@
5 from lp.answers.interfaces.faqtarget import IFAQTarget
6 from lp.answers.interfaces.question import IQuestion
7 from lp.answers.interfaces.questiontarget import IQuestionTarget
8-from lp.blueprints.interfaces.specification import ISpecification
9+from lp.blueprints.interfaces.specification import (
10+ ISpecification,
11+ ISpecificationPublic,
12+ )
13 from lp.blueprints.interfaces.specificationbranch import ISpecificationBranch
14 from lp.blueprints.interfaces.specificationsubscription import (
15 ISpecificationSubscription,
16@@ -494,6 +497,17 @@
17 return True
18
19
20+class AnonymousAccessToISpecificationPublic(AnonymousAuthorization):
21+ """Anonymous users have launchpad.View on ISpecificationPublic.
22+
23+ This is only needed because lazr.restful is hard-coded to check that
24+ permission before returning things in a collection.
25+ """
26+
27+ permission = 'launchpad.View'
28+ usedfor = ISpecificationPublic
29+
30+
31 class EditSpecificationByTargetOwnerOrOwnersOrAdmins(AuthorizationBase):
32 """We want everybody "related" to a specification to be able to edit it.
33 You are related if you have a role on the spec, or if you have a role on
34
35=== modified file 'lib/lp/blueprints/interfaces/specification.py'
36--- lib/lp/blueprints/interfaces/specification.py 2010-11-29 18:53:45 +0000
37+++ lib/lp/blueprints/interfaces/specification.py 2010-12-01 13:02:06 +0000
38@@ -14,6 +14,7 @@
39 'INewSpecificationTarget',
40 'INewSpecificationProjectTarget',
41 'ISpecification',
42+ 'ISpecificationPublic',
43 'ISpecificationSet',
44 'ISpecificationDelta',
45 ]
46
47=== modified file 'lib/lp/blueprints/tests/test_webservice.py'
48--- lib/lp/blueprints/tests/test_webservice.py 2010-11-29 18:53:45 +0000
49+++ lib/lp/blueprints/tests/test_webservice.py 2010-12-01 13:02:06 +0000
50@@ -5,6 +5,8 @@
51
52 __metaclass__ = type
53
54+from zope.security.management import endInteraction
55+
56 from canonical.testing import DatabaseFunctionalLayer
57 from canonical.launchpad.testing.pages import webservice_for_person
58 from lp.blueprints.interfaces.specification import (
59@@ -12,7 +14,9 @@
60 )
61 from lp.testing import (
62 launchpadlib_for,
63+ launchpadlib_for_anonymous,
64 TestCaseWithFactory,
65+ ws_object,
66 )
67
68
69@@ -215,6 +219,18 @@
70 names = [s.name for s in specifications]
71 self.assertContentEqual(expected_names, names)
72
73+ def test_anonymous_access_to_collection(self):
74+ product = self.factory.makeProduct()
75+ self.factory.makeSpecification(product=product, name="spec1")
76+ self.factory.makeSpecification(product=product, name="spec2")
77+ # Need to endInteraction() because launchpadlib_for_anonymous() will
78+ # setup a new one.
79+ endInteraction()
80+ lplib = launchpadlib_for_anonymous('lplib-test', version='devel')
81+ ws_product = ws_object(lplib, product)
82+ self.assertNamesOfSpecificationsAre(
83+ ["spec1", "spec2"], ws_product.all_specifications)
84+
85 def test_product_all_specifications(self):
86 product = self.factory.makeProduct()
87 self.factory.makeSpecification(product=product, name="spec1")
88
89=== modified file 'lib/lp/testing/__init__.py'
90--- lib/lp/testing/__init__.py 2010-11-26 10:52:10 +0000
91+++ lib/lp/testing/__init__.py 2010-12-01 13:02:06 +0000
92@@ -154,6 +154,7 @@
93 from lp.testing._webservice import (
94 launchpadlib_credentials_for,
95 launchpadlib_for,
96+ launchpadlib_for_anonymous,
97 oauth_access_token_for,
98 )
99 from lp.testing.fixture import ZopeEventHandlerFixture
100
101=== modified file 'lib/lp/testing/_webservice.py'
102--- lib/lp/testing/_webservice.py 2010-10-23 16:44:23 +0000
103+++ lib/lp/testing/_webservice.py 2010-12-01 13:02:06 +0000
104@@ -8,6 +8,7 @@
105 __all__ = [
106 'launchpadlib_credentials_for',
107 'launchpadlib_for',
108+ 'launchpadlib_for_anonymous',
109 'oauth_access_token_for',
110 ]
111
112@@ -17,6 +18,7 @@
113
114 from launchpadlib.credentials import (
115 AccessToken,
116+ AnonymousAccessToken,
117 Credentials,
118 )
119 from launchpadlib.launchpad import Launchpad
120@@ -118,6 +120,21 @@
121 shutil.rmtree(cache, ignore_errors=True)
122
123
124+def launchpadlib_for_anonymous(
125+ consumer_name, version=None, service_root="http://api.launchpad.dev/"):
126+ """Create a Launchpad object for the anonymous user.
127+
128+ :param consumer_name: An OAuth consumer name.
129+ :param version: The version of the web service to access.
130+ :param service_root: The root URL of the web service to access.
131+
132+ :return: A launchpadlib.Launchpad object.
133+ """
134+ token = AnonymousAccessToken()
135+ credentials = Credentials(consumer_name, access_token=token)
136+ return Launchpad(credentials, service_root, version=version)
137+
138+
139 def launchpadlib_for(
140 consumer_name, person, permission=OAuthPermission.WRITE_PRIVATE,
141 context=None, version=None, service_root="http://api.launchpad.dev/"):