Merge lp:~gary/launchpad/revert12041 into lp:launchpad

Proposed by Gary Poster
Status: Merged
Approved by: Francis J. Lacoste
Approved revision: no longer in the source branch.
Merged at revision: 12080
Proposed branch: lp:~gary/launchpad/revert12041
Merge into: lp:launchpad
Diff against target: 280 lines (+109/-16)
6 files modified
lib/canonical/launchpad/browser/librarian.py (+14/-13)
lib/canonical/launchpad/rest/bytestorage.py (+28/-0)
lib/canonical/launchpad/zcml/webservice.zcml (+13/-0)
lib/lp/bugs/interfaces/bugattachment.py (+2/-2)
lib/lp/bugs/stories/webservice/xx-bug.txt (+41/-1)
lib/lp/services/fields/__init__.py (+11/-0)
To merge this branch: bzr merge lp:~gary/launchpad/revert12041
Reviewer Review Type Date Requested Status
Francis J. Lacoste (community) Approve
Review via email: mp+43811@code.launchpad.net

Commit message

[r=flacoste][ui=none][no-qa] revert r12041, which is qa-bad and blocking deployment.

Description of the change

This reverts r12041, which is qa-bad and blocking deployment per the deployable revision report (https://devpad.canonical.com/~lpqateam/qa_reports/deployment-stable.html). No-one from the bugs team is around to confirm that what I am doing is correct, but it looks right to me from what I know of the situation.

Practically, this branch is merely the result of ``bzr merge -r12041..12040``. I did nothing else other than look at the output.

To post a comment you must log in.
Revision history for this message
Francis J. Lacoste (flacoste) wrote :

Looks sane

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/browser/librarian.py'
--- lib/canonical/launchpad/browser/librarian.py 2010-12-07 11:00:09 +0000
+++ lib/canonical/launchpad/browser/librarian.py 2010-12-15 19:14:18 +0000
@@ -85,11 +85,11 @@
8585
86 If the file is public, it will redirect to the files http url.86 If the file is public, it will redirect to the files http url.
8787
88 Otherwise if the feature flag publicrestrictedlibrarian is set to 'on'88 Otherwise if the feature flag publicrestrictedlibrarian is set to 'on' this
89 this will allocate a token and redirect to the aliases private url.89 will allocate a token and redirect to the aliases private url.
9090
91 Otherwise it will proxy the file in the appserver.91 Otherwise it will proxy the file in the appserver.
9292
93 Once we no longer have any proxy code at all it should be possible to93 Once we no longer have any proxy code at all it should be possible to
94 consolidate this with LibraryFileAliasView.94 consolidate this with LibraryFileAliasView.
9595
@@ -98,7 +98,7 @@
98 we have to take special care about their origin.98 we have to take special care about their origin.
99 SafeStreamOrRedirectLibraryFileAliasView is used when we do not trust the99 SafeStreamOrRedirectLibraryFileAliasView is used when we do not trust the
100 content, otherwise StreamOrRedirectLibraryFileAliasView. We are working100 content, otherwise StreamOrRedirectLibraryFileAliasView. We are working
101 to remove both of these views entirely, but some transition will be101 to remove both of these views entirely, but some transition will be
102 needed.102 needed.
103103
104 The context provides a file-like interface - it can be opened and closed104 The context provides a file-like interface - it can be opened and closed
@@ -161,7 +161,7 @@
161161
162 def browserDefault(self, request):162 def browserDefault(self, request):
163 """Decides how to deliver the file.163 """Decides how to deliver the file.
164164
165 The options are:165 The options are:
166 - redirect to the contexts http url166 - redirect to the contexts http url
167 - redirect to a time limited secure url167 - redirect to a time limited secure url
@@ -182,7 +182,7 @@
182 # Public file, just point the client at the right place.182 # Public file, just point the client at the right place.
183 return RedirectionView(self.context.http_url, self.request), ()183 return RedirectionView(self.context.http_url, self.request), ()
184 if getFeatureFlag(u'publicrestrictedlibrarian') != 'on':184 if getFeatureFlag(u'publicrestrictedlibrarian') != 'on':
185 # Restricted file and we have not enabled the public185 # Restricted file and we have not enabled the public
186 # restricted librarian yet :- deliver inline.186 # restricted librarian yet :- deliver inline.
187 self._when_streaming()187 self._when_streaming()
188 return self, ()188 return self, ()
@@ -203,12 +203,12 @@
203 """Hook for SafeStreamOrRedirectLibraryFileAliasView."""203 """Hook for SafeStreamOrRedirectLibraryFileAliasView."""
204204
205205
206
206class SafeStreamOrRedirectLibraryFileAliasView(MixedFileAliasView):207class SafeStreamOrRedirectLibraryFileAliasView(MixedFileAliasView):
207 """A view for Librarian files that sets the content disposition header."""208 """A view for Librarian files that sets the content disposition header."""
208209
209 def _when_streaming(self):210 def _when_streaming(self):
210 super(211 super(SafeStreamOrRedirectLibraryFileAliasView, self)._when_streaming()
211 SafeStreamOrRedirectLibraryFileAliasView, self)._when_streaming()
212 self.request.response.setHeader(212 self.request.response.setHeader(
213 'Content-Disposition', 'attachment')213 'Content-Disposition', 'attachment')
214214
@@ -257,17 +257,18 @@
257class ProxiedLibraryFileAlias:257class ProxiedLibraryFileAlias:
258 """A `LibraryFileAlias` decorator for use in URL generation.258 """A `LibraryFileAlias` decorator for use in URL generation.
259259
260 The URL's output by this decorator will always point at the webapp. This260 The URL's output by this decorator will always point at the webapp. This is
261 is useful when:261 useful when:
262 - the webapp has to be contacted to get access to a file (required for262 - we are proxying files via the webapp (as we do at the moment)
263 restricted files).263 - when the webapp has to be contacted to get access to a file (the case
264 for restricted files in the future)
264 - files might change from public to private and thus not work even if the265 - files might change from public to private and thus not work even if the
265 user has access to the once its private, unless they go via the webapp.266 user has access to the once its private, unless they go via the webapp.
266267
267 This should be used anywhere we are outputting URL's to LibraryFileAliases268 This should be used anywhere we are outputting URL's to LibraryFileAliases
268 other than directly in rendered pages. For rendered pages, using a269 other than directly in rendered pages. For rendered pages, using a
269 LibraryFileAlias directly is OK as at that point the status of the file270 LibraryFileAlias directly is OK as at that point the status of the file
270 is known.271 is know.
271272
272 Overrides `ILibraryFileAlias.http_url` to always point to the webapp URL,273 Overrides `ILibraryFileAlias.http_url` to always point to the webapp URL,
273 even when called from the webservice domain.274 even when called from the webservice domain.
274275
=== modified file 'lib/canonical/launchpad/rest/bytestorage.py'
--- lib/canonical/launchpad/rest/bytestorage.py 2010-11-18 18:42:05 +0000
+++ lib/canonical/launchpad/rest/bytestorage.py 2010-12-15 19:14:18 +0000
@@ -6,6 +6,7 @@
6__metaclass__ = type6__metaclass__ = type
7__all__ = [7__all__ = [
8 'LibraryBackedByteStorage',8 'LibraryBackedByteStorage',
9 'RestrictedLibraryBackedByteStorage',
9]10]
1011
1112
@@ -15,6 +16,7 @@
15from zope.component import getUtility16from zope.component import getUtility
16from zope.interface import implements17from zope.interface import implements
1718
19from canonical.launchpad.browser.librarian import ProxiedLibraryFileAlias
18from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet20from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
19from canonical.launchpad.webapp.interfaces import ICanonicalUrlData21from canonical.launchpad.webapp.interfaces import ICanonicalUrlData
2022
@@ -73,3 +75,29 @@
73 def deleteStored(self):75 def deleteStored(self):
74 """See `IByteStorage`."""76 """See `IByteStorage`."""
75 setattr(self.entry, self.field.__name__, None)77 setattr(self.entry, self.field.__name__, None)
78
79
80class RestrictedLibraryBackedByteStorage(LibraryBackedByteStorage):
81 """See `IByteStorage`.
82
83 This variant of LibraryBackedByteStorage provides an alias_url
84 which points to a StreamOrRedirectLibraryFileAliasView for
85 restricted Librarian files.
86 """
87
88 @property
89 def alias_url(self):
90 """See `IByteStorage`."""
91 if self.file_alias.restricted:
92 # XXX Abel Deuring 2010-09-03, bug=629804
93 # This is a bad hack: We can't give ordinary users API access to
94 # restricted files at present. But we can allow access to
95 # some machines in the data center (and should do that).
96 # We need here an HTTP URL, not an HTTPS URL, so we don't
97 # use getUrl(). Since http_url uses not an official domain
98 # name, all we do is expose an unaccessible HTTP URL also
99 # users outside of the data center, instead of the HTTPS URL
100 # returned by getURL().
101 return self.file_alias.http_url
102 else:
103 return self.file_alias.getURL()
76104
=== modified file 'lib/canonical/launchpad/zcml/webservice.zcml'
--- lib/canonical/launchpad/zcml/webservice.zcml 2010-11-18 18:42:05 +0000
+++ lib/canonical/launchpad/zcml/webservice.zcml 2010-12-15 19:14:18 +0000
@@ -43,6 +43,19 @@
43 <allow interface='lazr.restful.interfaces.IByteStorage' />43 <allow interface='lazr.restful.interfaces.IByteStorage' />
44 </class>44 </class>
4545
46 <!-- Registration for the class that manages an entry's RestrictedBytes
47 fields. -->
48 <adapter
49 for="lazr.restful.interfaces.IEntry
50 lp.services.fields.IRestrictedBytes"
51 provides="lazr.restful.interfaces.IByteStorage"
52 factory="canonical.launchpad.rest.bytestorage.RestrictedLibraryBackedByteStorage"
53 />
54
55 <class class="canonical.launchpad.rest.bytestorage.RestrictedLibraryBackedByteStorage">
56 <allow interface='lazr.restful.interfaces.IByteStorage' />
57 </class>
58
46 <!-- WebService uses the default LaunchpadRootNavigation -->59 <!-- WebService uses the default LaunchpadRootNavigation -->
47 <view60 <view
48 for="canonical.launchpad.interfaces.launchpad.IWebServiceApplication"61 for="canonical.launchpad.interfaces.launchpad.IWebServiceApplication"
4962
=== modified file 'lib/lp/bugs/interfaces/bugattachment.py'
--- lib/lp/bugs/interfaces/bugattachment.py 2010-11-18 18:42:05 +0000
+++ lib/lp/bugs/interfaces/bugattachment.py 2010-12-15 19:14:18 +0000
@@ -39,7 +39,7 @@
39from canonical.launchpad import _39from canonical.launchpad import _
40from canonical.launchpad.interfaces.launchpad import IHasBug40from canonical.launchpad.interfaces.launchpad import IHasBug
41from canonical.launchpad.interfaces.message import IMessage41from canonical.launchpad.interfaces.message import IMessage
42from lp.services.fields import Title42from lp.services.fields import RestrictedBytes, Title
4343
4444
45class BugAttachmentType(DBEnumeratedType):45class BugAttachmentType(DBEnumeratedType):
@@ -115,7 +115,7 @@
115 libraryfile = Bytes(title=_("The attachment content."),115 libraryfile = Bytes(title=_("The attachment content."),
116 required=True)116 required=True)
117 data = exported(117 data = exported(
118 Bytes(title=_("The attachment content."),118 RestrictedBytes(title=_("The attachment content."),
119 required=True,119 required=True,
120 readonly=True))120 readonly=True))
121 message = exported(121 message = exported(
122122
=== modified file 'lib/lp/bugs/stories/webservice/xx-bug.txt'
--- lib/lp/bugs/stories/webservice/xx-bug.txt 2010-12-07 11:00:09 +0000
+++ lib/lp/bugs/stories/webservice/xx-bug.txt 2010-12-15 19:14:18 +0000
@@ -1360,6 +1360,46 @@
1360 ---1360 ---
13611361
13621362
1363Attachments of private bugs
1364~~~~~~~~~~~~~~~~~~~~~~~~~~~
1365
1366Attachments of private bugs are served by the app server itself.
1367
1368 >>> print webservice.patch(
1369 ... bug_one['self_link'], 'application/json', dumps(dict(private=True)))
1370 HTTP/1.1 209 Content Returned...
1371
1372 >>> response = webservice.named_post(
1373 ... bug_one['self_link'], 'addAttachment',
1374 ... data="67890", filename="more-numbers.txt", content_type='foo/bar',
1375 ... comment="The numbers you asked for.")
1376 >>> attachments = webservice.get(
1377 ... bug_one['attachments_collection_link']).jsonBody()
1378 >>> attachment = attachments['entries'][0]
1379 >>> pprint_entry(attachment)
1380 bug_link:...
1381 data_link: u'http://api.launchpad.dev/beta/bugs/1/+attachment/.../data'
1382 ...
1383
1384XXX Abel Deuring 2010-09-03, bug=629804: Please note that the http URLs in this
1385example are part of a temporary hack. Please see the comment in
1386canonical.launchpad.rest.bytestorage.RestrictedLibraryBackedByteStorage.
1387alias_url for details.
1388
1389 >>> response = webservice.get(attachment['data_link'])
1390 >>> print response
1391 HTTP/1.1 303 See Other
1392 Status: 303 See Other
1393 ...
1394 Location: http://localhost:58005/94/more-numbers.txt
1395 ...
1396
1397 >>> # Let's make the bug public again for later tests.
1398 >>> print webservice.patch(
1399 ... bug_one['self_link'], 'application/json', dumps(dict(private=False)))
1400 HTTP/1.1 209 Content Returned...
1401
1402
1363Searching for bugs1403Searching for bugs
1364------------------1404------------------
13651405
@@ -2093,7 +2133,7 @@
2093 next_collection_link: u'http://.../bugs/1/activity?ws.start=5&ws.size=5'2133 next_collection_link: u'http://.../bugs/1/activity?ws.start=5&ws.size=5'
2094 resource_type_link: u'http://.../#bug_activity-page-resource'2134 resource_type_link: u'http://.../#bug_activity-page-resource'
2095 start: 02135 start: 0
2096 total_size: 232136 total_size: 26
2097 ...2137 ...
20982138
2099 >>> bug_nine_activity = webservice.get(2139 >>> bug_nine_activity = webservice.get(
21002140
=== modified file 'lib/lp/services/fields/__init__.py'
--- lib/lp/services/fields/__init__.py 2010-12-07 11:00:09 +0000
+++ lib/lp/services/fields/__init__.py 2010-12-15 19:14:18 +0000
@@ -22,6 +22,7 @@
22 'ILocationField',22 'ILocationField',
23 'INoneableTextLine',23 'INoneableTextLine',
24 'IPasswordField',24 'IPasswordField',
25 'IRestrictedBytes',
25 'IStrippedTextLine',26 'IStrippedTextLine',
26 'ISummary',27 'ISummary',
27 'ITag',28 'ITag',
@@ -45,6 +46,7 @@
45 'ProductBugTracker',46 'ProductBugTracker',
46 'ProductNameField',47 'ProductNameField',
47 'PublicPersonChoice',48 'PublicPersonChoice',
49 'RestrictedBytes',
48 'SearchTag',50 'SearchTag',
49 'StrippedTextLine',51 'StrippedTextLine',
50 'Summary',52 'Summary',
@@ -227,6 +229,10 @@
227 """229 """
228230
229231
232class IRestrictedBytes(IBytes):
233 """A marker interface used for restricted LibraryFileAlias fields."""
234
235
230class StrippedTextLine(TextLine):236class StrippedTextLine(TextLine):
231 implements(IStrippedTextLine)237 implements(IStrippedTextLine)
232238
@@ -836,3 +842,8 @@
836 else:842 else:
837 # The vocabulary prevents the revealing of private team names.843 # The vocabulary prevents the revealing of private team names.
838 raise PrivateTeamNotAllowed(value)844 raise PrivateTeamNotAllowed(value)
845
846
847class RestrictedBytes(Bytes):
848 """A field for restricted LibraryFileAlias records."""
849 implements(IRestrictedBytes)