Merge lp:~wgrant/launchpad/bug-1100164 into lp:launchpad
- bug-1100164
- Merge into devel
Proposed by
William Grant
Status: | Merged |
---|---|
Approved by: | Steve Kowalik |
Approved revision: | no longer in the source branch. |
Merged at revision: | 16452 |
Proposed branch: | lp:~wgrant/launchpad/bug-1100164 |
Merge into: | lp:launchpad |
Diff against target: |
591 lines (+121/-124) 16 files modified
lib/lp/registry/browser/configure.zcml (+4/-4) lib/lp/registry/browser/productrelease.py (+2/-19) lib/lp/registry/browser/tests/test_milestone.py (+33/-0) lib/lp/registry/browser/tests/test_productrelease.py (+12/-55) lib/lp/registry/configure.zcml (+4/-1) lib/lp/registry/interfaces/productrelease.py (+7/-1) lib/lp/registry/model/milestone.py (+0/-6) lib/lp/registry/model/productrelease.py (+13/-1) lib/lp/registry/stories/product/xx-product-files.txt (+12/-0) lib/lp/registry/templates/product-index.pt (+1/-0) lib/lp/registry/templates/productrelease-add-from-series.pt (+0/-7) lib/lp/registry/templates/productrelease-add.pt (+0/-7) lib/lp/registry/templates/productrelease-portlet-data.pt (+8/-2) lib/lp/registry/tests/test_milestone.py (+2/-13) lib/lp/registry/tests/test_productrelease.py (+17/-1) lib/lp/security.py (+6/-7) |
To merge this branch: | bzr merge lp:~wgrant/launchpad/bug-1100164 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Steve Kowalik (community) | code | Approve | |
Review via email: mp+144856@code.launchpad.net |
Commit message
Permit proprietary products to have releases, forbid them from adding release files.
Description of the change
Proprietary products are currently banned from having releases due to a misunderstanding in the late stages of implementation. This branch rescinds that ban and instates a new one on release *files* -- the real leak.
The addReleaseFile and +adddownloadfile reject attempts to add a file, and the listing/link are hidden from Milestone/
And I secured the Zope permissions for ProductRelease.
To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/registry/browser/configure.zcml' |
2 | --- lib/lp/registry/browser/configure.zcml 2012-12-10 20:07:39 +0000 |
3 | +++ lib/lp/registry/browser/configure.zcml 2013-01-25 06:18:24 +0000 |
4 | @@ -2012,7 +2012,7 @@ |
5 | provides="lp.services.webapp.interfaces.IBreadcrumb" |
6 | for="lp.registry.interfaces.productrelease.IProductRelease" |
7 | factory="lp.registry.browser.milestone.MilestoneBreadcrumb" |
8 | - permission="zope.Public"/> |
9 | + permission="launchpad.View"/> |
10 | <browser:url |
11 | for="lp.registry.interfaces.productrelease.IProductRelease" |
12 | path_expression="version" |
13 | @@ -2027,21 +2027,21 @@ |
14 | name="+index"/> |
15 | <browser:pages |
16 | for="lp.registry.interfaces.productrelease.IProductRelease" |
17 | - permission="zope.Public"> |
18 | + permission="launchpad.View"> |
19 | <browser:page |
20 | name="+portlet-downloads" |
21 | template="../templates/productrelease-portlet-downloads.pt"/> |
22 | </browser:pages> |
23 | <browser:page |
24 | for="lp.registry.interfaces.productrelease.IProductRelease" |
25 | - permission="zope.Public" |
26 | + permission="launchpad.View" |
27 | name="+index" |
28 | class="lp.registry.browser.milestone.MilestoneView" |
29 | template="../templates/milestone-index.pt"/> |
30 | <browser:page |
31 | for="lp.registry.interfaces.productrelease.IProductRelease" |
32 | class="lp.registry.browser.productrelease.ProductReleaseRdfView" |
33 | - permission="zope.Public" |
34 | + permission="launchpad.View" |
35 | name="+rdf" |
36 | attribute="__call__"/> |
37 | <browser:page |
38 | |
39 | === modified file 'lib/lp/registry/browser/productrelease.py' |
40 | --- lib/lp/registry/browser/productrelease.py 2012-12-10 20:47:40 +0000 |
41 | +++ lib/lp/registry/browser/productrelease.py 2013-01-25 06:18:24 +0000 |
42 | @@ -39,7 +39,6 @@ |
43 | LaunchpadEditFormView, |
44 | LaunchpadFormView, |
45 | ) |
46 | -from lp.app.enums import InformationType |
47 | from lp.app.widgets.date import DateTimeWidget |
48 | from lp.registry.browser import ( |
49 | BaseRdfView, |
50 | @@ -136,11 +135,6 @@ |
51 | notify(ObjectCreatedEvent(newrelease)) |
52 | |
53 | @property |
54 | - def releases_allowed(self): |
55 | - return (self.context.product.information_type != |
56 | - InformationType.PROPRIETARY) |
57 | - |
58 | - @property |
59 | def label(self): |
60 | """The form label.""" |
61 | return smartquote('Create a new release for %s' % |
62 | @@ -166,11 +160,6 @@ |
63 | ] |
64 | |
65 | def initialize(self): |
66 | - if (self.context.product.information_type == |
67 | - InformationType.EMBARGOED): |
68 | - self.request.response.addWarningNotification( |
69 | - _("Any releases added for %s will be PUBLIC." % |
70 | - self.context.product.displayname)) |
71 | if self.context.product_release is not None: |
72 | self.request.response.addErrorNotification( |
73 | _("A project release already exists for this milestone.")) |
74 | @@ -202,14 +191,6 @@ |
75 | 'changelog', |
76 | ] |
77 | |
78 | - def initialize(self): |
79 | - if (self.context.product.information_type == |
80 | - InformationType.EMBARGOED): |
81 | - self.request.response.addWarningNotification( |
82 | - _("Any releases added for %s will be PUBLIC." % |
83 | - self.context.displayname)) |
84 | - super(ProductReleaseFromSeriesAddView, self).initialize() |
85 | - |
86 | def setUpFields(self): |
87 | super(ProductReleaseFromSeriesAddView, self).setUpFields() |
88 | self._prependKeepMilestoneActiveField() |
89 | @@ -294,6 +275,8 @@ |
90 | |
91 | def validate(self, data): |
92 | """See `LaunchpadFormView`.""" |
93 | + if not self.context.can_have_release_files: |
94 | + self.addError('Only public projects can have download files.') |
95 | file_name = None |
96 | filecontent = self.request.form.get(self.widgets['filecontent'].name) |
97 | if filecontent: |
98 | |
99 | === modified file 'lib/lp/registry/browser/tests/test_milestone.py' |
100 | --- lib/lp/registry/browser/tests/test_milestone.py 2012-11-15 22:22:38 +0000 |
101 | +++ lib/lp/registry/browser/tests/test_milestone.py 2013-01-25 06:18:24 +0000 |
102 | @@ -117,6 +117,39 @@ |
103 | with person_logged_in(None): |
104 | browser = self.getViewBrowser(milestone, '+index') |
105 | |
106 | + def test_downloads_listed(self): |
107 | + # When a release exists a list of download files and a link to |
108 | + # add more are shown. |
109 | + owner = self.factory.makePerson() |
110 | + product = self.factory.makeProduct(owner=owner) |
111 | + release = self.factory.makeProductRelease(product=product) |
112 | + with person_logged_in(owner): |
113 | + owner_browser = self.getViewBrowser( |
114 | + release.milestone, '+index', user=owner) |
115 | + html = owner_browser.contents |
116 | + self.assertIn('Download files for this release', html) |
117 | + self.assertIn('Add download file', html) |
118 | + with person_logged_in(None): |
119 | + owner_browser = self.getViewBrowser(release.milestone, '+index') |
120 | + html = owner_browser.contents |
121 | + self.assertIn('Download files for this release', html) |
122 | + self.assertNotIn('Add download file', html) |
123 | + |
124 | + def test_downloads_section_hidden_for_proprietary_product(self): |
125 | + # Only public projects can have download files, so the downloads |
126 | + # section is replaced with a message indicating this. |
127 | + owner = self.factory.makePerson() |
128 | + product = self.factory.makeProduct( |
129 | + owner=owner, information_type=InformationType.PROPRIETARY) |
130 | + with person_logged_in(owner): |
131 | + release = self.factory.makeProductRelease(product=product) |
132 | + owner_browser = self.getViewBrowser( |
133 | + release.milestone, '+index', user=owner) |
134 | + html = owner_browser.contents |
135 | + self.assertIn( |
136 | + 'Only public projects can have download files.', html) |
137 | + self.assertNotIn('Add download file', html) |
138 | + |
139 | |
140 | class TestAddMilestoneViews(TestCaseWithFactory): |
141 | |
142 | |
143 | === modified file 'lib/lp/registry/browser/tests/test_productrelease.py' |
144 | --- lib/lp/registry/browser/tests/test_productrelease.py 2012-12-11 13:40:11 +0000 |
145 | +++ lib/lp/registry/browser/tests/test_productrelease.py 2013-01-25 06:18:24 +0000 |
146 | @@ -9,7 +9,6 @@ |
147 | from lp.app.enums import InformationType |
148 | from lp.services.webapp.escaping import html_escape |
149 | from lp.testing import ( |
150 | - BrowserTestCase, |
151 | person_logged_in, |
152 | TestCaseWithFactory, |
153 | ) |
154 | @@ -17,60 +16,6 @@ |
155 | from lp.testing.views import create_initialized_view |
156 | |
157 | |
158 | -class NonPublicProductReleaseViewTestCase(BrowserTestCase): |
159 | - |
160 | - layer = LaunchpadFunctionalLayer |
161 | - |
162 | - def test_proprietary_add_milestone(self): |
163 | - owner = self.factory.makePerson() |
164 | - product = self.factory.makeProduct(name='fnord', |
165 | - owner=owner, information_type=InformationType.PROPRIETARY) |
166 | - milestone = self.factory.makeMilestone(product=product) |
167 | - with person_logged_in(owner): |
168 | - browser = self.getViewBrowser( |
169 | - milestone, view_name="+addrelease", user=owner) |
170 | - msg = 'Fnord is PROPRIETARY. It cannot have any releases.' |
171 | - self.assertTrue(html_escape(msg) in browser.contents) |
172 | - |
173 | - def test_proprietary_add_series(self): |
174 | - owner = self.factory.makePerson() |
175 | - product = self.factory.makeProduct(name='fnord', |
176 | - owner=owner, information_type=InformationType.PROPRIETARY) |
177 | - series = self.factory.makeProductSeries(product=product, name='bnord') |
178 | - with person_logged_in(owner): |
179 | - browser = self.getViewBrowser( |
180 | - series, view_name="+addrelease", user=owner) |
181 | - msg = ('The bnord series of Fnord is PROPRIETARY.' |
182 | - ' It cannot have any releases.') |
183 | - self.assertTrue(html_escape(msg) in browser.contents) |
184 | - |
185 | - def test_embargoed_add_milestone(self): |
186 | - owner = self.factory.makePerson() |
187 | - product = self.factory.makeProduct(name='fnord', |
188 | - owner=owner, information_type=InformationType.EMBARGOED) |
189 | - milestone = self.factory.makeMilestone(product=product) |
190 | - with person_logged_in(owner): |
191 | - view = create_initialized_view(milestone, name="+addrelease") |
192 | - notifications = [ |
193 | - nm.message for nm in view.request.response.notifications] |
194 | - self.assertEqual( |
195 | - [html_escape("Any releases added for Fnord will be PUBLIC.")], |
196 | - notifications) |
197 | - |
198 | - def test_embargoed_add_series(self): |
199 | - owner = self.factory.makePerson() |
200 | - product = self.factory.makeProduct(name='fnord', |
201 | - owner=owner, information_type=InformationType.EMBARGOED) |
202 | - series = self.factory.makeProductSeries(product=product, name='bnord') |
203 | - with person_logged_in(owner): |
204 | - view = create_initialized_view(series, name="+addrelease") |
205 | - notifications = [ |
206 | - nm.message for nm in view.request.response.notifications] |
207 | - self.assertEqual( |
208 | - [html_escape("Any releases added for bnord will be PUBLIC.")], |
209 | - notifications) |
210 | - |
211 | - |
212 | class ProductReleaseAddDownloadFileViewTestCase(TestCaseWithFactory): |
213 | |
214 | layer = LaunchpadFunctionalLayer |
215 | @@ -111,3 +56,15 @@ |
216 | self.assertEqual( |
217 | [html_escape("The file '%s' is already uploaded." % file_name)], |
218 | view.errors) |
219 | + |
220 | + def test_refuses_proprietary_products(self): |
221 | + owner = self.factory.makePerson() |
222 | + product = self.factory.makeProduct( |
223 | + owner=owner, information_type=InformationType.PROPRIETARY) |
224 | + with person_logged_in(owner): |
225 | + release = self.factory.makeProductRelease(product=product) |
226 | + form = self.makeForm('something.tar.gz') |
227 | + view = create_initialized_view( |
228 | + release, '+adddownloadfile', form=form) |
229 | + self.assertEqual( |
230 | + ['Only public projects can have download files.'], view.errors) |
231 | |
232 | === modified file 'lib/lp/registry/configure.zcml' |
233 | --- lib/lp/registry/configure.zcml 2012-12-06 16:09:31 +0000 |
234 | +++ lib/lp/registry/configure.zcml 2013-01-25 06:18:24 +0000 |
235 | @@ -1875,10 +1875,13 @@ |
236 | <allow |
237 | interface="lp.registry.interfaces.productrelease.IProductReleasePublic"/> |
238 | <require |
239 | + permission="launchpad.View" |
240 | + interface="lp.registry.interfaces.productrelease.IProductReleaseView"/> |
241 | + <require |
242 | permission="launchpad.Edit" |
243 | interface="lp.registry.interfaces.productrelease.IProductReleaseEditRestricted"/> |
244 | <require |
245 | - permission="zope.Public" |
246 | + permission="launchpad.Edit" |
247 | set_schema="lp.registry.interfaces.productrelease.IProductRelease"/> |
248 | </class> |
249 | <adapter |
250 | |
251 | === modified file 'lib/lp/registry/interfaces/productrelease.py' |
252 | --- lib/lp/registry/interfaces/productrelease.py 2012-11-21 21:29:29 +0000 |
253 | +++ lib/lp/registry/interfaces/productrelease.py 2013-01-25 06:18:24 +0000 |
254 | @@ -274,6 +274,10 @@ |
255 | |
256 | id = Int(title=_('ID'), required=True, readonly=True) |
257 | |
258 | + |
259 | +class IProductReleaseView(Interface): |
260 | + """launchpad.View-restricted `IProductRelease` properties.""" |
261 | + |
262 | datereleased = exported( |
263 | Datetime( |
264 | title=_('Date released'), required=True, |
265 | @@ -334,6 +338,8 @@ |
266 | Text(title=u'Constructed title for a project release.', readonly=True) |
267 | ) |
268 | |
269 | + can_have_release_files = Attribute("Whether release files can be added.") |
270 | + |
271 | product = exported( |
272 | Reference(title=u'The project that made this release.', |
273 | schema=Interface, readonly=True), |
274 | @@ -371,7 +377,7 @@ |
275 | """Does the release have a file that matches the name?""" |
276 | |
277 | |
278 | -class IProductRelease(IProductReleaseEditRestricted, |
279 | +class IProductRelease(IProductReleaseEditRestricted, IProductReleaseView, |
280 | IProductReleasePublic): |
281 | """A specific release (i.e. version) of a product. |
282 | |
283 | |
284 | === modified file 'lib/lp/registry/model/milestone.py' |
285 | --- lib/lp/registry/model/milestone.py 2013-01-22 05:07:31 +0000 |
286 | +++ lib/lp/registry/model/milestone.py 2013-01-25 06:18:24 +0000 |
287 | @@ -36,7 +36,6 @@ |
288 | from zope.component import getUtility |
289 | from zope.interface import implements |
290 | |
291 | -from lp.app.enums import InformationType |
292 | from lp.app.errors import NotFoundError |
293 | from lp.blueprints.model.specification import Specification |
294 | from lp.blueprints.model.specificationsearch import ( |
295 | @@ -56,7 +55,6 @@ |
296 | from lp.bugs.model.structuralsubscription import ( |
297 | StructuralSubscriptionTargetMixin, |
298 | ) |
299 | -from lp.registry.errors import ProprietaryProduct |
300 | from lp.registry.interfaces.milestone import ( |
301 | IHasMilestones, |
302 | IMilestone, |
303 | @@ -277,10 +275,6 @@ |
304 | def createProductRelease(self, owner, datereleased, |
305 | changelog=None, release_notes=None): |
306 | """See `IMilestone`.""" |
307 | - info_type = self.product.information_type |
308 | - if info_type == InformationType.PROPRIETARY: |
309 | - raise ProprietaryProduct( |
310 | - "Proprietary products cannot have releases.") |
311 | if self.product_release is not None: |
312 | raise MultipleProductReleases() |
313 | release = ProductRelease( |
314 | |
315 | === modified file 'lib/lp/registry/model/productrelease.py' |
316 | --- lib/lp/registry/model/productrelease.py 2012-11-21 21:29:29 +0000 |
317 | +++ lib/lp/registry/model/productrelease.py 2013-01-25 06:18:24 +0000 |
318 | @@ -25,8 +25,12 @@ |
319 | from zope.component import getUtility |
320 | from zope.interface import implements |
321 | |
322 | +from lp.app.enums import InformationType |
323 | from lp.app.errors import NotFoundError |
324 | -from lp.registry.errors import InvalidFilename |
325 | +from lp.registry.errors import ( |
326 | + InvalidFilename, |
327 | + ProprietaryProduct, |
328 | + ) |
329 | from lp.registry.interfaces.person import ( |
330 | validate_person, |
331 | validate_public_person, |
332 | @@ -104,6 +108,11 @@ |
333 | """See `IProductRelease`.""" |
334 | return self.milestone.title |
335 | |
336 | + @property |
337 | + def can_have_release_files(self): |
338 | + """See `IProductRelease`.""" |
339 | + return self.product.information_type == InformationType.PUBLIC |
340 | + |
341 | @staticmethod |
342 | def normalizeFilename(filename): |
343 | # Replace slashes in the filename with less problematic dashes. |
344 | @@ -141,6 +150,9 @@ |
345 | file_type=UpstreamFileType.CODETARBALL, |
346 | description=None): |
347 | """See `IProductRelease`.""" |
348 | + if not self.can_have_release_files: |
349 | + raise ProprietaryProduct( |
350 | + "Only public projects can have download files.") |
351 | if self.hasReleaseFile(filename): |
352 | raise InvalidFilename |
353 | # Create the alias for the file. |
354 | |
355 | === modified file 'lib/lp/registry/stories/product/xx-product-files.txt' |
356 | --- lib/lp/registry/stories/product/xx-product-files.txt 2012-12-10 13:43:47 +0000 |
357 | +++ lib/lp/registry/stories/product/xx-product-files.txt 2013-01-25 06:18:24 +0000 |
358 | @@ -47,6 +47,18 @@ |
359 | File Description Downloads |
360 | firefox_0.9.2.orig.tar.gz (md5) - |
361 | |
362 | +Only public projects can have download files, so the portlet is omitted |
363 | +otherwise. |
364 | + |
365 | + >>> from lp.app.enums import InformationType |
366 | + >>> login('admin@canonical.com') |
367 | + >>> prop_prod = factory.makeProduct( |
368 | + ... name='prop-prod', information_type=InformationType.PROPRIETARY) |
369 | + >>> logout() |
370 | + >>> admin_browser.open('http://launchpad.dev/prop-prod') |
371 | + >>> print find_tag_by_id(admin_browser.contents, 'downloads') |
372 | + None |
373 | + |
374 | |
375 | Deletion is only for the privileged |
376 | =================================== |
377 | |
378 | === modified file 'lib/lp/registry/templates/product-index.pt' |
379 | --- lib/lp/registry/templates/product-index.pt 2012-12-07 20:37:04 +0000 |
380 | +++ lib/lp/registry/templates/product-index.pt 2013-01-25 06:18:24 +0000 |
381 | @@ -236,6 +236,7 @@ |
382 | <div tal:replace="structure context/@@+get-involved" /> |
383 | |
384 | <div id="downloads" class="top-portlet downloads" |
385 | + tal:condition="context/information_type/enumvalue:PUBLIC" |
386 | tal:define="release view/latest_release_with_download_files"> |
387 | <h2>Downloads</h2> |
388 | |
389 | |
390 | === modified file 'lib/lp/registry/templates/productrelease-add-from-series.pt' |
391 | --- lib/lp/registry/templates/productrelease-add-from-series.pt 2012-12-10 20:24:40 +0000 |
392 | +++ lib/lp/registry/templates/productrelease-add-from-series.pt 2013-01-25 06:18:24 +0000 |
393 | @@ -64,7 +64,6 @@ |
394 | </metal:block> |
395 | |
396 | <div metal:fill-slot="main"> |
397 | - <tal:releases-allowed condition="view/releases_allowed"> |
398 | <div metal:use-macro="context/@@launchpad_form/form"> |
399 | <div metal:fill-slot="extra_info" tal:condition="context/releases" |
400 | style="border-bottom: solid 1px black"> |
401 | @@ -78,12 +77,6 @@ |
402 | </ul> |
403 | </div> |
404 | </div> |
405 | - </tal:releases-allowed> |
406 | - <tal:releases-forbidden condition="not: view/releases_allowed"> |
407 | - The <tal:seriesname replace="context/displayname" |
408 | - /> series of <tal:productname replace="context/product/displayname" |
409 | - /> is PROPRIETARY. It cannot have any releases. |
410 | - </tal:releases-forbidden> |
411 | </div> |
412 | |
413 | </body> |
414 | |
415 | === modified file 'lib/lp/registry/templates/productrelease-add.pt' |
416 | --- lib/lp/registry/templates/productrelease-add.pt 2012-12-10 20:24:40 +0000 |
417 | +++ lib/lp/registry/templates/productrelease-add.pt 2013-01-25 06:18:24 +0000 |
418 | @@ -14,7 +14,6 @@ |
419 | </metal:block> |
420 | |
421 | <div metal:fill-slot="main"> |
422 | - <tal:releases-allowed condition="view/releases_allowed"> |
423 | <div metal:use-macro="context/@@launchpad_form/form"> |
424 | <div id="other-releases" |
425 | metal:fill-slot="extra_info" |
426 | @@ -30,12 +29,6 @@ |
427 | </ul> |
428 | </div> |
429 | </div> |
430 | - </tal:releases-allowed> |
431 | - <tal:releases-forbidden condition="not: view/releases_allowed"> |
432 | - <tal:productname replace="context/product/displayname" |
433 | - /> is PROPRIETARY. It cannot have any releases. |
434 | - </tal:releases-forbidden> |
435 | - |
436 | </div> |
437 | |
438 | </body> |
439 | |
440 | === modified file 'lib/lp/registry/templates/productrelease-portlet-data.pt' |
441 | --- lib/lp/registry/templates/productrelease-portlet-data.pt 2012-09-10 03:45:21 +0000 |
442 | +++ lib/lp/registry/templates/productrelease-portlet-data.pt 2013-01-25 06:18:24 +0000 |
443 | @@ -6,8 +6,10 @@ |
444 | |
445 | <div class="portlet" |
446 | tal:define="has_edit view/release/required:launchpad.Edit;"> |
447 | - <form method="POST" tal:attributes="action request/URL"> |
448 | - <h2>Download files for this release</h2> |
449 | + <h2>Download files for this release</h2> |
450 | + <form |
451 | + tal:condition="view/release/can_have_release_files" |
452 | + method="POST" tal:attributes="action request/URL"> |
453 | |
454 | <p id="how-to-verify" tal:condition="view/download_files"> |
455 | After you've downloaded a file, you can verify its authenticity |
456 | @@ -64,8 +66,12 @@ |
457 | </ul> |
458 | </div> |
459 | </form> |
460 | + <tal:nofiles tal:condition="not:view/release/can_have_release_files"> |
461 | + <em>Only public projects can have download files.</em> |
462 | + </tal:nofiles> |
463 | </div> |
464 | |
465 | + |
466 | <div class="top-portlet"> |
467 | <h2>Release notes <a tal:replace="structure view/release/menu:context/edit/fmt:icon" /></h2> |
468 | |
469 | |
470 | === modified file 'lib/lp/registry/tests/test_milestone.py' |
471 | --- lib/lp/registry/tests/test_milestone.py 2012-12-26 01:04:05 +0000 |
472 | +++ lib/lp/registry/tests/test_milestone.py 2013-01-25 06:18:24 +0000 |
473 | @@ -5,8 +5,8 @@ |
474 | |
475 | __metaclass__ = type |
476 | |
477 | -import datetime |
478 | from operator import attrgetter |
479 | +import unittest |
480 | |
481 | from storm.exceptions import NoneError |
482 | from zope.component import getUtility |
483 | @@ -45,18 +45,16 @@ |
484 | from lp.testing.matchers import DoesNotSnapshot |
485 | |
486 | |
487 | -class MilestoneTest(TestCaseWithFactory): |
488 | +class MilestoneTest(unittest.TestCase): |
489 | """Milestone tests.""" |
490 | |
491 | layer = LaunchpadFunctionalLayer |
492 | |
493 | def setUp(self): |
494 | - super(MilestoneTest, self).setUp() |
495 | login(ANONYMOUS) |
496 | |
497 | def tearDown(self): |
498 | logout() |
499 | - super(MilestoneTest, self).tearDown() |
500 | |
501 | def testMilestoneSetIterator(self): |
502 | """Test of MilestoneSet.__iter__().""" |
503 | @@ -116,15 +114,6 @@ |
504 | all_visible_milestones_ids, |
505 | [1, 2, 3]) |
506 | |
507 | - def test_proprietary_product_milestones_cannot_have_releases(self): |
508 | - owner = self.factory.makePerson() |
509 | - product = self.factory.makeProduct( |
510 | - owner=owner, information_type=InformationType.PROPRIETARY) |
511 | - milestone = self.factory.makeMilestone(product=product) |
512 | - with person_logged_in(owner): |
513 | - self.assertRaises(ProprietaryProduct, |
514 | - milestone.createProductRelease, owner, datetime.date.today()) |
515 | - |
516 | |
517 | class MilestoneSecurityAdaperTestCase(TestCaseWithFactory): |
518 | """A TestCase for the security adapter of milestones.""" |
519 | |
520 | === modified file 'lib/lp/registry/tests/test_productrelease.py' |
521 | --- lib/lp/registry/tests/test_productrelease.py 2012-11-19 20:42:45 +0000 |
522 | +++ lib/lp/registry/tests/test_productrelease.py 2013-01-25 06:18:24 +0000 |
523 | @@ -7,7 +7,11 @@ |
524 | |
525 | from zope.component import getUtility |
526 | |
527 | -from lp.registry.errors import InvalidFilename |
528 | +from lp.app.enums import InformationType |
529 | +from lp.registry.errors import ( |
530 | + InvalidFilename, |
531 | + ProprietaryProduct, |
532 | + ) |
533 | from lp.registry.interfaces.productrelease import ( |
534 | IProductReleaseSet, |
535 | UpstreamFileType, |
536 | @@ -70,6 +74,7 @@ |
537 | |
538 | def test_addReleaseFile(self): |
539 | release = self.factory.makeProductRelease() |
540 | + self.assertTrue(release.can_have_release_files) |
541 | maintainer = release.milestone.product.owner |
542 | with person_logged_in(maintainer): |
543 | release_file = release.addReleaseFile( |
544 | @@ -89,3 +94,14 @@ |
545 | self.assertRaises( |
546 | InvalidFilename, release.addReleaseFile, |
547 | library_file.filename, 'test', 'text/plain', maintainer) |
548 | + |
549 | + def test_addReleaseFile_only_works_on_public_products(self): |
550 | + owner = self.factory.makePerson() |
551 | + product = self.factory.makeProduct( |
552 | + information_type=InformationType.PROPRIETARY, owner=owner) |
553 | + with person_logged_in(owner): |
554 | + release = self.factory.makeProductRelease(product=product) |
555 | + self.assertFalse(release.can_have_release_files) |
556 | + self.assertRaises( |
557 | + ProprietaryProduct, release.addReleaseFile, |
558 | + 'README', 'test', 'text/plain', owner) |
559 | |
560 | === modified file 'lib/lp/security.py' |
561 | --- lib/lp/security.py 2013-01-16 04:51:47 +0000 |
562 | +++ lib/lp/security.py 2013-01-25 06:18:24 +0000 |
563 | @@ -529,11 +529,6 @@ |
564 | usedfor = IDistributionMirror |
565 | |
566 | |
567 | -class ViewAbstractMilestone(AnonymousAuthorization): |
568 | - """Anyone can view an IMilestone or an IProjectGroupMilestone.""" |
569 | - usedfor = IAbstractMilestone |
570 | - |
571 | - |
572 | class EditSpecificationBranch(AuthorizationBase): |
573 | |
574 | usedfor = ISpecificationBranch |
575 | @@ -1740,10 +1735,14 @@ |
576 | self, user) |
577 | |
578 | |
579 | -class ViewProductRelease(AnonymousAuthorization): |
580 | - |
581 | +class ViewProductRelease(DelegatedAuthorization): |
582 | + permission = 'launchpad.View' |
583 | usedfor = IProductRelease |
584 | |
585 | + def __init__(self, obj): |
586 | + super(ViewProductRelease, self).__init__( |
587 | + obj, obj.milestone, 'launchpad.View') |
588 | + |
589 | |
590 | class AdminTranslationImportQueueEntry(AuthorizationBase): |
591 | permission = 'launchpad.Admin' |