Merge lp:~stevenk/launchpad/bugs-remove-old-privacy into lp:launchpad
- bugs-remove-old-privacy
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Steve Kowalik |
Approved revision: | no longer in the source branch. |
Merged at revision: | 15038 |
Proposed branch: | lp:~stevenk/launchpad/bugs-remove-old-privacy |
Merge into: | lp:launchpad |
Diff against target: |
1202 lines (+232/-232) 21 files modified
lib/lp/bugs/browser/bug.py (+8/-5) lib/lp/bugs/browser/bugtarget.py (+8/-5) lib/lp/bugs/doc/bug-private-by-default.txt (+2/-1) lib/lp/bugs/doc/bug.txt (+5/-2) lib/lp/bugs/doc/bugnotification-sending.txt (+2/-1) lib/lp/bugs/doc/bugsubscription.txt (+4/-3) lib/lp/bugs/doc/security-teams.txt (+8/-7) lib/lp/bugs/interfaces/bug.py (+10/-15) lib/lp/bugs/mail/commands.py (+10/-8) lib/lp/bugs/mail/tests/test_commands.py (+10/-6) lib/lp/bugs/model/bug.py (+91/-128) lib/lp/bugs/model/bugtask.py (+3/-3) lib/lp/bugs/model/tests/test_bug.py (+23/-26) lib/lp/bugs/scripts/bugimport.py (+8/-8) lib/lp/bugs/stories/bugs/xx-bug-activity.txt (+6/-0) lib/lp/bugs/xmlrpc/bug.py (+11/-7) lib/lp/registry/enums.py (+5/-0) lib/lp/registry/model/person.py (+5/-2) lib/lp/security.py (+3/-1) lib/lp/systemhomes.py (+5/-2) lib/lp/testing/factory.py (+5/-2) |
To merge this branch: | bzr merge lp:~stevenk/launchpad/bugs-remove-old-privacy |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ian Booth (community) | Approve | ||
Review via email:
|
Commit message
Replace private and security_related in CreateBugParams() with information_type, and replace IBug.setPrivacy
Description of the change
As part of the slow march towards un-conflating privacy and security of bugs, we are moving everything from using Bug.private and Bug.security_
This branch moves the code from IBug.setPrivacy
I have dropped private and security from CreateBugParams and replaced it with information_type. I have hacked around that in the factory and a few other places to make this branch a little more manageable.
I think this branch is safe to land in its current state, with or without the DB patches -11-4 and -12-3 applied.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ian Booth (wallyworld) wrote : | # |
I would actually remove setPrivacyAndSe
It is a recent addition can can be removed from the API since AFAIUI was only exported to 'devel' and never formally released.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
William Grant (wgrant) wrote : | # |
lib/lp/
Preview Diff
1 | === modified file 'lib/lp/bugs/browser/bug.py' |
2 | --- lib/lp/bugs/browser/bug.py 2012-03-13 00:45:33 +0000 |
3 | +++ lib/lp/bugs/browser/bug.py 2012-03-29 05:56:22 +0000 |
4 | @@ -69,6 +69,7 @@ |
5 | from lp.app.errors import NotFoundError |
6 | from lp.app.widgets.itemswidgets import LaunchpadRadioWidgetWithDescription |
7 | from lp.app.widgets.project import ProjectScopeWidget |
8 | +from lp.bugs.adapters.bug import convert_to_information_type |
9 | from lp.bugs.browser.bugsubscription import BugPortletSubscribersWithDetails |
10 | from lp.bugs.browser.widgets.bug import BugTagsWidget |
11 | from lp.bugs.enums import BugNotificationLevel |
12 | @@ -874,7 +875,7 @@ |
13 | |
14 | # We handle privacy changes by hand instead of leaving it to |
15 | # the usual machinery because we must use |
16 | - # bug.setPrivacyAndSecurityRelated() to ensure auditing information is |
17 | + # bug.transitionToInformationType() to ensure auditing information is |
18 | # recorded. |
19 | bug = self.context.bug |
20 | private = data.pop('private', bug.private) |
21 | @@ -882,12 +883,14 @@ |
22 | private and bug.getSubscribersForPerson(self.user).is_empty()) |
23 | security_related = data.pop('security_related') |
24 | user = getUtility(ILaunchBag).user |
25 | - (private_changed, security_related_changed) = ( |
26 | - bug.setPrivacyAndSecurityRelated(private, security_related, user)) |
27 | - if private_changed: |
28 | + # This will change when the UI does. |
29 | + information_type = convert_to_information_type( |
30 | + private, security_related) |
31 | + changed = bug.transitionToInformationType(information_type, user) |
32 | + if changed: |
33 | self._handlePrivacyChanged(user_will_be_subscribed) |
34 | if self.request.is_ajax: |
35 | - if private_changed or security_related_changed: |
36 | + if changed: |
37 | return self._getSubscriptionDetails() |
38 | else: |
39 | return '' |
40 | |
41 | === modified file 'lib/lp/bugs/browser/bugtarget.py' |
42 | --- lib/lp/bugs/browser/bugtarget.py 2012-02-21 22:46:28 +0000 |
43 | +++ lib/lp/bugs/browser/bugtarget.py 2012-03-29 05:56:22 +0000 |
44 | @@ -117,6 +117,7 @@ |
45 | ProductConfigureBase, |
46 | ProductPrivateBugsMixin, |
47 | ) |
48 | +from lp.registry.enums import InformationType |
49 | from lp.registry.interfaces.distribution import IDistribution |
50 | from lp.registry.interfaces.distributionsourcepackage import ( |
51 | IDistributionSourcePackage, |
52 | @@ -580,12 +581,13 @@ |
53 | if self.request.form.get("packagename_option") == "none": |
54 | packagename = None |
55 | |
56 | - # Security bugs are always private when filed, but can be disclosed |
57 | + # Security bugs are always embargoed when filed, but can be disclosed |
58 | # after they've been reported. |
59 | + # This will change when the UI does. |
60 | if security_related: |
61 | - private = True |
62 | + information_type = InformationType.EMBARGOEDSECURITY |
63 | else: |
64 | - private = False |
65 | + information_type = InformationType.PUBLIC |
66 | |
67 | linkified_ack = structured(FormattersAPI( |
68 | self.getAcknowledgementMessage(self.context)).text_to_html( |
69 | @@ -593,7 +595,7 @@ |
70 | notifications = [linkified_ack] |
71 | params = CreateBugParams( |
72 | title=title, comment=comment, owner=self.user, |
73 | - security_related=security_related, private=private, |
74 | + information_type=information_type, |
75 | tags=data.get('tags')) |
76 | if IDistribution.providedBy(context) and packagename: |
77 | # We don't know if the package name we got was a source or binary |
78 | @@ -623,7 +625,8 @@ |
79 | 'Additional information was added to the bug description.') |
80 | |
81 | if extra_data.private: |
82 | - params.private = extra_data.private |
83 | + if params.information_type == InformationType.PUBLIC: |
84 | + params.information_type = InformationType.USERDATA |
85 | |
86 | # Apply any extra options given by privileged users. |
87 | if BugTask.userHasBugSupervisorPrivilegesContext(context, self.user): |
88 | |
89 | === modified file 'lib/lp/bugs/doc/bug-private-by-default.txt' |
90 | --- lib/lp/bugs/doc/bug-private-by-default.txt 2012-01-24 12:36:15 +0000 |
91 | +++ lib/lp/bugs/doc/bug-private-by-default.txt 2012-03-29 05:56:22 +0000 |
92 | @@ -5,6 +5,7 @@ |
93 | (this is enforced by a DB constraint). |
94 | |
95 | >>> from lp.bugs.interfaces.bug import CreateBugParams |
96 | + >>> from lp.registry.enums import InformationType |
97 | >>> from lp.registry.interfaces.person import IPersonSet |
98 | >>> from lp.registry.interfaces.product import IProductSet |
99 | >>> from lp.testing.dbuser import switch_dbuser |
100 | @@ -46,7 +47,7 @@ |
101 | >>> security_bug_params = CreateBugParams( |
102 | ... owner=no_priv, title='Security bug', |
103 | ... comment='A monkey took my GPG keys.', |
104 | - ... security_related=True) |
105 | + ... information_type=InformationType.EMBARGOEDSECURITY) |
106 | >>> security_bug = landscape.createBug(security_bug_params) |
107 | >>> [security_bug_task] = security_bug.bugtasks |
108 | >>> security_bug_task.bug.private |
109 | |
110 | === modified file 'lib/lp/bugs/doc/bug.txt' |
111 | --- lib/lp/bugs/doc/bug.txt 2011-12-30 06:14:56 +0000 |
112 | +++ lib/lp/bugs/doc/bug.txt 2012-03-29 05:56:22 +0000 |
113 | @@ -90,6 +90,7 @@ |
114 | The event can be seen when we file a bug. |
115 | |
116 | >>> from lp.bugs.interfaces.bug import CreateBugParams |
117 | + >>> from lp.registry.enums import InformationType |
118 | |
119 | >>> steve_harris = factory.makePerson(name='steve-harris') |
120 | >>> params = CreateBugParams( |
121 | @@ -477,7 +478,7 @@ |
122 | |
123 | >>> params = CreateBugParams( |
124 | ... title="test firefox bug", comment="blah blah blah", owner=foobar, |
125 | - ... private=True) |
126 | + ... information_type=InformationType.USERDATA) |
127 | >>> params.setBugTarget(product=firefox) |
128 | >>> added_bug = getUtility(IBugSet).createBug(params) |
129 | >>> private_bug = bugset.get(added_bug.id) |
130 | @@ -507,7 +508,7 @@ |
131 | >>> evolution = spnset.get(9) |
132 | >>> params = CreateBugParams( |
133 | ... title="test firefox bug", comment="blah blah blah", |
134 | - ... owner=foobar, private=True) |
135 | + ... owner=foobar, information_type=InformationType.USERDATA) |
136 | >>> params.setBugTarget(distribution=ubuntu, sourcepackagename=evolution) |
137 | >>> added_bug = getUtility(IBugSet).createBug(params) |
138 | >>> private_bug = bugset.get(added_bug.id) |
139 | @@ -824,6 +825,7 @@ |
140 | |
141 | We need a feature flag for this test since multi-pillar bugs shouldn't be |
142 | private by default. |
143 | + |
144 | >>> from lp.services.features.testing import FeatureFixture |
145 | >>> feature_flag = { |
146 | ... 'disclosure.allow_multipillar_private_bugs.enabled': 'on'} |
147 | @@ -850,6 +852,7 @@ |
148 | |
149 | Changing bug security. |
150 | |
151 | + >>> ign = firefox_bug.setPrivate(False, getUtility(ILaunchBag).user) |
152 | >>> bug_before_modification = Snapshot(firefox_bug, providing=IBug) |
153 | |
154 | >>> firefox_bug.security_related |
155 | |
156 | === modified file 'lib/lp/bugs/doc/bugnotification-sending.txt' |
157 | --- lib/lp/bugs/doc/bugnotification-sending.txt 2012-03-13 00:45:33 +0000 |
158 | +++ lib/lp/bugs/doc/bugnotification-sending.txt 2012-03-29 05:56:22 +0000 |
159 | @@ -352,6 +352,7 @@ |
160 | We will need a fresh new bug. |
161 | |
162 | >>> from lp.bugs.interfaces.bug import CreateBugParams |
163 | + >>> from lp.registry.enums import InformationType |
164 | >>> from lp.registry.interfaces.distribution import IDistributionSet |
165 | >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu') |
166 | >>> description = getUtility(IMessageSet).fromText( |
167 | @@ -418,7 +419,7 @@ |
168 | ... sec_vuln_bug = ubuntu.createBug(CreateBugParams( |
169 | ... msg=sec_vuln_description, owner=sample_person, |
170 | ... title='Zero-day on Frobulator', |
171 | - ... security_related=True, private=True)) |
172 | + ... information_type=InformationType.EMBARGOEDSECURITY)) |
173 | |
174 | >>> sec_vuln_bug.security_related |
175 | True |
176 | |
177 | === modified file 'lib/lp/bugs/doc/bugsubscription.txt' |
178 | --- lib/lp/bugs/doc/bugsubscription.txt 2012-03-13 00:45:33 +0000 |
179 | +++ lib/lp/bugs/doc/bugsubscription.txt 2012-03-29 05:56:22 +0000 |
180 | @@ -48,6 +48,7 @@ |
181 | |
182 | >>> from lp.services.webapp.interfaces import ILaunchBag |
183 | >>> from lp.bugs.interfaces.bug import CreateBugParams |
184 | + >>> from lp.registry.enums import InformationType |
185 | >>> from lp.registry.interfaces.distribution import IDistributionSet |
186 | >>> from lp.registry.interfaces.person import IPersonSet |
187 | >>> ubuntu = getUtility(IDistributionSet).getByName("ubuntu") |
188 | @@ -717,7 +718,7 @@ |
189 | |
190 | >>> params = CreateBugParams( |
191 | ... title="a test bug", comment="a test description", |
192 | - ... owner=foobar, security_related=True, private=True) |
193 | + ... owner=foobar, information_type=InformationType.EMBARGOEDSECURITY) |
194 | >>> new_bug = ubuntu.createBug(params) |
195 | |
196 | >>> getSubscribers(new_bug) |
197 | @@ -805,7 +806,7 @@ |
198 | |
199 | >>> params = CreateBugParams( |
200 | ... title="a test bug", comment="a test description", |
201 | - ... owner=foobar, security_related=True, private=True) |
202 | + ... owner=foobar, information_type=InformationType.EMBARGOEDSECURITY) |
203 | >>> new_bug = firefox.createBug(params) |
204 | |
205 | >>> getSubscribers(new_bug) |
206 | @@ -871,7 +872,7 @@ |
207 | >>> params = CreateBugParams( |
208 | ... title="yet another test bug", |
209 | ... comment="yet another test description", |
210 | - ... owner=foobar, security_related=True, private=True) |
211 | + ... owner=foobar, information_type=InformationType.EMBARGOEDSECURITY) |
212 | >>> new_bug = evolution.createBug(params) |
213 | |
214 | >>> getSubscribers(new_bug) |
215 | |
216 | === modified file 'lib/lp/bugs/doc/security-teams.txt' |
217 | --- lib/lp/bugs/doc/security-teams.txt 2011-12-24 17:49:30 +0000 |
218 | +++ lib/lp/bugs/doc/security-teams.txt 2012-03-29 05:56:22 +0000 |
219 | @@ -37,19 +37,20 @@ |
220 | >>> print firefox.security_contact.name |
221 | ubuntu-team |
222 | |
223 | -When creating a bug, use the security_related flag to indicate that the |
224 | +When creating a bug, use the information_type enum to indicate that the |
225 | bug is a security vulnerability, and the security contact should be |
226 | subscribed to the bug, even when it's marked private. |
227 | |
228 | >>> from lp.services.webapp.interfaces import ILaunchBag |
229 | >>> from lp.bugs.interfaces.bug import CreateBugParams |
230 | + >>> from lp.registry.enums import InformationType |
231 | |
232 | >>> ubuntu_firefox = ubuntu.getSourcePackage("mozilla-firefox") |
233 | >>> params = CreateBugParams( |
234 | ... owner=getUtility(ILaunchBag).user, |
235 | ... title="a security bug", |
236 | ... comment="this is an example security bug", |
237 | - ... security_related=True, private=True) |
238 | + ... information_type=InformationType.EMBARGOEDSECURITY) |
239 | >>> bug = ubuntu.createBug(params) |
240 | |
241 | >>> bug.security_related |
242 | @@ -79,7 +80,7 @@ |
243 | ... owner=getUtility(ILaunchBag).user, |
244 | ... title="a security bug", |
245 | ... comment="this is an example security bug", |
246 | - ... security_related=False) |
247 | + ... information_type=InformationType.PUBLIC) |
248 | >>> bug = ubuntu.createBug(params) |
249 | |
250 | >>> bug.security_related |
251 | @@ -95,7 +96,7 @@ |
252 | ... owner=getUtility(ILaunchBag).user, |
253 | ... title="another security bug", |
254 | ... comment="this is another security bug", |
255 | - ... security_related=True, private=True) |
256 | + ... information_type=InformationType.EMBARGOEDSECURITY) |
257 | >>> bug = firefox.createBug(params) |
258 | |
259 | >>> bug.security_related |
260 | @@ -113,7 +114,7 @@ |
261 | ... owner=getUtility(ILaunchBag).user, |
262 | ... title="another security bug", |
263 | ... comment="this is another security bug", |
264 | - ... security_related=False) |
265 | + ... information_type=InformationType.PUBLIC) |
266 | >>> bug = firefox.createBug(params) |
267 | |
268 | >>> bug.security_related |
269 | @@ -134,7 +135,7 @@ |
270 | ... owner=getUtility(ILaunchBag).user, |
271 | ... title="another security bug", |
272 | ... comment="this is another security bug", |
273 | - ... security_related=True, private=True) |
274 | + ... information_type=InformationType.EMBARGOEDSECURITY) |
275 | |
276 | >>> bug = firefox.createBug(params) |
277 | |
278 | @@ -190,7 +191,7 @@ |
279 | ... owner=getUtility(ILaunchBag).user, |
280 | ... title="another security bug", |
281 | ... comment="this is private security bug", |
282 | - ... private=True, security_related=True) |
283 | + ... information_type=InformationType.EMBARGOEDSECURITY) |
284 | >>> bug = firefox.createBug(params) |
285 | |
286 | >>> bug.security_related |
287 | |
288 | === modified file 'lib/lp/bugs/interfaces/bug.py' |
289 | --- lib/lp/bugs/interfaces/bug.py 2012-03-21 01:17:50 +0000 |
290 | +++ lib/lp/bugs/interfaces/bug.py 2012-03-29 05:56:22 +0000 |
291 | @@ -100,9 +100,9 @@ |
292 | class CreateBugParams: |
293 | """The parameters used to create a bug.""" |
294 | |
295 | - def __init__(self, owner, title, comment=None, description=None, msg=None, |
296 | - status=None, datecreated=None, security_related=False, |
297 | - private=False, subscribers=(), |
298 | + def __init__(self, owner, title, comment=None, description=None, |
299 | + msg=None, status=None, datecreated=None, |
300 | + information_type=InformationType.PUBLIC, subscribers=(), |
301 | tags=None, subscribe_owner=True, filed_by=None, |
302 | importance=None, milestone=None, assignee=None, cve=None): |
303 | self.owner = owner |
304 | @@ -112,8 +112,7 @@ |
305 | self.msg = msg |
306 | self.status = status |
307 | self.datecreated = datecreated |
308 | - self.security_related = security_related |
309 | - self.private = private |
310 | + self.information_type = information_type |
311 | self.subscribers = subscribers |
312 | self.product = None |
313 | self.distribution = None |
314 | @@ -891,20 +890,16 @@ |
315 | """ |
316 | |
317 | @operation_parameters( |
318 | - private=copy_field(IBugPublic['private']), |
319 | - security_related=copy_field(IBugView['security_related']), |
320 | + information_type=copy_field(IBugPublic['information_type']), |
321 | ) |
322 | @call_with(who=REQUEST_USER) |
323 | @export_write_operation() |
324 | @operation_for_version("devel") |
325 | - def setPrivacyAndSecurityRelated(private, security_related, who): |
326 | - """Set bug privacy and security . |
327 | - |
328 | - :private: True/False. |
329 | - :security_related: True/False. |
330 | - :who: The IPerson who is making the change. |
331 | - |
332 | - Return (private_changed, security_related_changed) tuple. |
333 | + def transitionToInformationType(information_type, who): |
334 | + """Set the information type for this bug. |
335 | + |
336 | + :information_type: The `InformationType` to transition to. |
337 | + :who: The `IPerson` who is making the change. |
338 | """ |
339 | |
340 | @operation_parameters( |
341 | |
342 | === modified file 'lib/lp/bugs/mail/commands.py' |
343 | --- lib/lp/bugs/mail/commands.py 2012-01-01 02:58:52 +0000 |
344 | +++ lib/lp/bugs/mail/commands.py 2012-03-29 05:56:22 +0000 |
345 | @@ -1,4 +1,4 @@ |
346 | -# Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
347 | +# Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
348 | # GNU Affero General Public License version 3 (see the file LICENSE). |
349 | |
350 | __metaclass__ = type |
351 | @@ -46,6 +46,7 @@ |
352 | IllegalTarget, |
353 | ) |
354 | from lp.bugs.interfaces.cve import ICveSet |
355 | +from lp.registry.enums import InformationType |
356 | from lp.registry.interfaces.distribution import IDistribution |
357 | from lp.registry.interfaces.distributionsourcepackage import ( |
358 | IDistributionSourcePackage, |
359 | @@ -184,10 +185,13 @@ |
360 | stop_processing=True) |
361 | |
362 | if isinstance(context, CreateBugParams): |
363 | - if context.security_related: |
364 | - # BugSet.createBug() requires new security bugs to be private. |
365 | - private = True |
366 | - context.private = private |
367 | + if private and ( |
368 | + context.information_type == InformationType.PUBLIC): |
369 | + context.information_type = InformationType.USERDATA |
370 | + elif ( |
371 | + context.information_type != |
372 | + InformationType.EMBARGOEDSECURITY): |
373 | + context.information_type = InformationType.PUBLIC |
374 | return context, current_event |
375 | |
376 | # Snapshot. |
377 | @@ -240,10 +244,8 @@ |
378 | stop_processing=True) |
379 | |
380 | if isinstance(context, CreateBugParams): |
381 | - context.security_related = security_related |
382 | if security_related: |
383 | - # BugSet.createBug() requires new security bugs to be private. |
384 | - context.private = True |
385 | + context.information_type = InformationType.EMBARGOEDSECURITY |
386 | return context, current_event |
387 | |
388 | # Take a snapshot. |
389 | |
390 | === modified file 'lib/lp/bugs/mail/tests/test_commands.py' |
391 | --- lib/lp/bugs/mail/tests/test_commands.py 2012-01-01 02:58:52 +0000 |
392 | +++ lib/lp/bugs/mail/tests/test_commands.py 2012-03-29 05:56:22 +0000 |
393 | @@ -1,4 +1,4 @@ |
394 | -# Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
395 | +# Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
396 | # GNU Affero General Public License version 3 (see the file LICENSE). |
397 | |
398 | from lazr.lifecycle.interfaces import ( |
399 | @@ -19,6 +19,7 @@ |
400 | TagEmailCommand, |
401 | UnsubscribeEmailCommand, |
402 | ) |
403 | +from lp.registry.enums import InformationType |
404 | from lp.services.mail.interfaces import ( |
405 | BugTargetNotFound, |
406 | EmailProcessingError, |
407 | @@ -364,7 +365,8 @@ |
408 | dummy_event = object() |
409 | params, event = command.execute(bug_params, dummy_event) |
410 | self.assertEqual(bug_params, params) |
411 | - self.assertEqual(True, bug_params.private) |
412 | + self.assertEqual( |
413 | + InformationType.USERDATA, bug_params.information_type) |
414 | self.assertEqual(dummy_event, event) |
415 | |
416 | def test_execute_bug_params_with_security(self): |
417 | @@ -372,12 +374,14 @@ |
418 | user = self.factory.makePerson() |
419 | login_person(user) |
420 | bug_params = CreateBugParams( |
421 | - title='bug title', owner=user, security_related='yes') |
422 | + title='bug title', owner=user, |
423 | + information_type=InformationType.EMBARGOEDSECURITY) |
424 | command = PrivateEmailCommand('private', ['no']) |
425 | dummy_event = object() |
426 | params, event = command.execute(bug_params, dummy_event) |
427 | self.assertEqual(bug_params, params) |
428 | - self.assertEqual(True, bug_params.private) |
429 | + self.assertEqual( |
430 | + InformationType.EMBARGOEDSECURITY, bug_params.information_type) |
431 | self.assertEqual(dummy_event, event) |
432 | |
433 | |
434 | @@ -402,8 +406,8 @@ |
435 | dummy_event = object() |
436 | params, event = command.execute(bug_params, dummy_event) |
437 | self.assertEqual(bug_params, params) |
438 | - self.assertEqual(True, bug_params.security_related) |
439 | - self.assertEqual(True, bug_params.private) |
440 | + self.assertEqual( |
441 | + InformationType.EMBARGOEDSECURITY, bug_params.information_type) |
442 | self.assertEqual(dummy_event, event) |
443 | |
444 | |
445 | |
446 | === modified file 'lib/lp/bugs/model/bug.py' |
447 | --- lib/lp/bugs/model/bug.py 2012-03-26 14:23:39 +0000 |
448 | +++ lib/lp/bugs/model/bug.py 2012-03-29 05:56:22 +0000 |
449 | @@ -235,11 +235,10 @@ |
450 | return Snapshot( |
451 | bug_params, names=[ |
452 | "owner", "title", "comment", "description", "msg", |
453 | - "datecreated", "security_related", "private", |
454 | - "distribution", "sourcepackagename", |
455 | - "product", "status", "subscribers", "tags", |
456 | - "subscribe_owner", "filed_by", "importance", |
457 | - "milestone", "assignee", "cve"]) |
458 | + "datecreated", "information_type", "distribution", |
459 | + "sourcepackagename", "product", "status", "subscribers", "tags", |
460 | + "subscribe_owner", "filed_by", "importance", "milestone", |
461 | + "assignee", "cve"]) |
462 | |
463 | |
464 | class BugTag(SQLBase): |
465 | @@ -360,7 +359,7 @@ |
466 | _security_related = BoolCol( |
467 | dbName='security_related', notNull=True, default=False) |
468 | information_type = EnumCol( |
469 | - enum=InformationType, default=InformationType.PUBLIC) |
470 | + enum=InformationType, notNull=True, default=InformationType.PUBLIC) |
471 | |
472 | # useful Joins |
473 | activity = SQLMultipleJoin('BugActivity', joinColumn='bug', orderBy='id') |
474 | @@ -397,17 +396,11 @@ |
475 | |
476 | @property |
477 | def private(self): |
478 | - if self.information_type: |
479 | - return self.information_type in PRIVATE_INFORMATION_TYPES |
480 | - else: |
481 | - return self._private |
482 | + return self.information_type in PRIVATE_INFORMATION_TYPES |
483 | |
484 | @property |
485 | def security_related(self): |
486 | - if self.information_type: |
487 | - return self.information_type in SECURITY_INFORMATION_TYPES |
488 | - else: |
489 | - return self._security_related |
490 | + return self.information_type in SECURITY_INFORMATION_TYPES |
491 | |
492 | @cachedproperty |
493 | def _subscriber_cache(self): |
494 | @@ -1717,109 +1710,76 @@ |
495 | |
496 | return bugtask |
497 | |
498 | - def setPrivacyAndSecurityRelated(self, private, security_related, who): |
499 | - """ See `IBug`.""" |
500 | - private_changed = False |
501 | - security_related_changed = False |
502 | - bug_before_modification = Snapshot(self, providing=providedBy(self)) |
503 | - |
504 | - f_flag_str = 'disclosure.enhanced_private_bug_subscriptions.enabled' |
505 | - f_flag = bool(getFeatureFlag(f_flag_str)) |
506 | - if f_flag: |
507 | - # Before we update the privacy or security_related status, we |
508 | - # need to reconcile the subscribers to avoid leaking private |
509 | - # information. |
510 | - if (self.private != private |
511 | - or self.security_related != security_related): |
512 | - self.reconcileSubscribers(private, security_related, who) |
513 | - |
514 | - if self.private != private: |
515 | - # We do not allow multi-pillar private bugs except for those teams |
516 | - # who want to shoot themselves in the foot. |
517 | - if private: |
518 | - allow_multi_pillar_private = bool(getFeatureFlag( |
519 | - 'disclosure.allow_multipillar_private_bugs.enabled')) |
520 | - if (not allow_multi_pillar_private |
521 | - and len(self.affected_pillars) > 1): |
522 | - raise BugCannotBePrivate( |
523 | - "Multi-pillar bugs cannot be private.") |
524 | - private_changed = True |
525 | - self._private = private |
526 | - |
527 | - if private: |
528 | - self.who_made_private = who |
529 | - self.date_made_private = UTC_NOW |
530 | - else: |
531 | - self.who_made_private = None |
532 | - self.date_made_private = None |
533 | - |
534 | - # XXX: This should be a bulk update. RBC 20100827 |
535 | - # bug=https://bugs.launchpad.net/storm/+bug/625071 |
536 | - for attachment in self.attachments_unpopulated: |
537 | - attachment.libraryfile.restricted = private |
538 | - |
539 | - if self.security_related != security_related: |
540 | - security_related_changed = True |
541 | - self._security_related = security_related |
542 | - |
543 | - if private_changed or security_related_changed: |
544 | - # Correct the heat for the bug immediately, so that we don't have |
545 | - # to wait for the next calculation job for the adjusted heat. |
546 | - self.updateHeat() |
547 | - |
548 | - self.information_type = convert_to_information_type( |
549 | - self._private, self._security_related) |
550 | - |
551 | - if private_changed or security_related_changed: |
552 | - changed_fields = [] |
553 | - |
554 | - if private_changed: |
555 | - changed_fields.append('private') |
556 | - if not f_flag and private: |
557 | - # If we didn't call reconcileSubscribers, we may have |
558 | - # bug supervisors who should be on this bug, but aren't. |
559 | - supervisors = set() |
560 | - for bugtask in self.bugtasks: |
561 | - supervisors.add(bugtask.pillar.bug_supervisor) |
562 | - if None in supervisors: |
563 | - supervisors.remove(None) |
564 | - for s in supervisors: |
565 | - subscriptions = get_structural_subscriptions_for_bug( |
566 | - self, s) |
567 | - if subscriptions != []: |
568 | - self.subscribe(s, who) |
569 | - |
570 | - if security_related_changed: |
571 | - changed_fields.append('security_related') |
572 | - if not f_flag and security_related: |
573 | - # The bug turned out to be security-related, subscribe the |
574 | - # security contact. We do it here only if the feature flag |
575 | - # is not set, otherwise it's done in |
576 | - # reconcileSubscribers(). |
577 | - for pillar in self.affected_pillars: |
578 | - if pillar.security_contact is not None: |
579 | - self.subscribe(pillar.security_contact, who) |
580 | - |
581 | - notify(ObjectModifiedEvent( |
582 | - self, bug_before_modification, changed_fields, user=who)) |
583 | - |
584 | - return private_changed, security_related_changed |
585 | - |
586 | def setPrivate(self, private, who): |
587 | """See `IBug`. |
588 | |
589 | We also record who made the change and when the change took |
590 | place. |
591 | """ |
592 | - return self.setPrivacyAndSecurityRelated( |
593 | - private, self.security_related, who)[0] |
594 | + return self.transitionToInformationType( |
595 | + convert_to_information_type(private, self.security_related), who) |
596 | |
597 | def setSecurityRelated(self, security_related, who): |
598 | """Setter for the `security_related` property.""" |
599 | - return self.setPrivacyAndSecurityRelated( |
600 | - self.private, security_related, who)[1] |
601 | - |
602 | - def getRequiredSubscribers(self, for_private, for_security_related, who): |
603 | + return self.transitionToInformationType( |
604 | + convert_to_information_type(self.private, security_related), who) |
605 | + |
606 | + def transitionToInformationType(self, information_type, who): |
607 | + """See `IBug`.""" |
608 | + bug_before_modification = Snapshot(self, providing=providedBy(self)) |
609 | + if self.information_type == information_type: |
610 | + return False |
611 | + f_flag_str = 'disclosure.enhanced_private_bug_subscriptions.enabled' |
612 | + f_flag = bool(getFeatureFlag(f_flag_str)) |
613 | + if f_flag: |
614 | + self.reconcileSubscribers(information_type, who) |
615 | + if information_type in PRIVATE_INFORMATION_TYPES: |
616 | + allow_multi_pillar_private = bool(getFeatureFlag( |
617 | + 'disclosure.allow_multipillar_private_bugs.enabled')) |
618 | + if (not allow_multi_pillar_private |
619 | + and len(self.affected_pillars) > 1): |
620 | + raise BugCannotBePrivate( |
621 | + "Multi-pillar bugs cannot be private.") |
622 | + self.who_made_private = who |
623 | + self.date_made_private = UTC_NOW |
624 | + else: |
625 | + self.who_made_private = None |
626 | + self.date_made_private = None |
627 | + # XXX: This should be a bulk update. RBC 20100827 |
628 | + # bug=https://bugs.launchpad.net/storm/+bug/625071 |
629 | + for attachment in self.attachments_unpopulated: |
630 | + attachment.libraryfile.restricted = ( |
631 | + information_type in PRIVATE_INFORMATION_TYPES) |
632 | + self.updateHeat() |
633 | + if not f_flag and information_type == InformationType.USERDATA: |
634 | + # If we didn't call reconcileSubscribers(), we may have |
635 | + # bug supervisors who should be on this bug, but aren't. |
636 | + supervisors = set() |
637 | + for bugtask in self.bugtasks: |
638 | + supervisors.add(bugtask.pillar.bug_supervisor) |
639 | + if None in supervisors: |
640 | + supervisors.remove(None) |
641 | + for s in supervisors: |
642 | + if not get_structural_subscriptions_for_bug(self, s): |
643 | + self.subscribe(s, who) |
644 | + if not f_flag and information_type in SECURITY_INFORMATION_TYPES: |
645 | + # The bug turned out to be security-related, subscribe the |
646 | + # security contact. We do it here only if the feature flag |
647 | + # is not set, otherwise it's done in |
648 | + # reconcileSubscribers(). |
649 | + for pillar in self.affected_pillars: |
650 | + if pillar.security_contact is not None: |
651 | + self.subscribe(pillar.security_contact, who) |
652 | + self.information_type = information_type |
653 | + # Set the legacy attributes for now. |
654 | + self._private = information_type in PRIVATE_INFORMATION_TYPES |
655 | + self._security_related = ( |
656 | + information_type in SECURITY_INFORMATION_TYPES) |
657 | + notify(ObjectModifiedEvent( |
658 | + self, bug_before_modification, [information_type], user=who)) |
659 | + return True |
660 | + |
661 | + def getRequiredSubscribers(self, information_type, who): |
662 | """Return the mandatory subscribers for a bug with given attributes. |
663 | |
664 | When a bug is marked as private or security related, it is required |
665 | @@ -1835,23 +1795,23 @@ |
666 | If bug supervisor or security contact is unset, fallback to bugtask |
667 | reporter/owner. |
668 | """ |
669 | - if not for_private and not for_security_related: |
670 | + if information_type == InformationType.PUBLIC: |
671 | return set() |
672 | result = set() |
673 | result.add(self.owner) |
674 | for bugtask in self.bugtasks: |
675 | maintainer = bugtask.pillar.owner |
676 | - if for_security_related: |
677 | + if information_type in SECURITY_INFORMATION_TYPES: |
678 | result.add(bugtask.pillar.security_contact or maintainer) |
679 | - if for_private: |
680 | + if information_type in PRIVATE_INFORMATION_TYPES: |
681 | result.add(bugtask.pillar.bug_supervisor or maintainer) |
682 | - if for_private: |
683 | + if information_type in PRIVATE_INFORMATION_TYPES: |
684 | subscribers_for_who = self.getSubscribersForPerson(who) |
685 | if subscribers_for_who.is_empty(): |
686 | result.add(who) |
687 | return result |
688 | |
689 | - def getAutoRemovedSubscribers(self, for_private, for_security_related): |
690 | + def getAutoRemovedSubscribers(self, information_type): |
691 | """Return the to be removed subscribers for bug with given attributes. |
692 | |
693 | When a bug's privacy or security related attributes change, some |
694 | @@ -1865,6 +1825,8 @@ |
695 | """ |
696 | bug_supervisors = [] |
697 | security_contacts = [] |
698 | + for_security_related = information_type in SECURITY_INFORMATION_TYPES |
699 | + for_private = information_type in PRIVATE_INFORMATION_TYPES |
700 | for pillar in self.affected_pillars: |
701 | if (self.security_related and not for_security_related |
702 | and pillar.security_contact): |
703 | @@ -1874,7 +1836,7 @@ |
704 | bug_supervisors.append(pillar.bug_supervisor) |
705 | return bug_supervisors, security_contacts |
706 | |
707 | - def reconcileSubscribers(self, for_private, for_security_related, who): |
708 | + def reconcileSubscribers(self, information_type, who): |
709 | """ Ensure only appropriate people are subscribed to private bugs. |
710 | |
711 | When a bug is marked as either private = True or security_related = |
712 | @@ -1894,9 +1856,9 @@ |
713 | current_direct_subscribers = ( |
714 | self.getSubscriptionInfo().direct_subscribers) |
715 | required_subscribers = self.getRequiredSubscribers( |
716 | - for_private, for_security_related, who) |
717 | + information_type, who) |
718 | removed_bug_supervisors, removed_security_contacts = ( |
719 | - self.getAutoRemovedSubscribers(for_private, for_security_related)) |
720 | + self.getAutoRemovedSubscribers(information_type)) |
721 | for subscriber in removed_bug_supervisors: |
722 | recipients = BugNotificationRecipients() |
723 | recipients.addBugSupervisor(subscriber) |
724 | @@ -1929,7 +1891,8 @@ |
725 | # unsubscribe any unauthorised direct subscribers. |
726 | pillar = self.default_bugtask.pillar |
727 | private_project = IProduct.providedBy(pillar) and pillar.private_bugs |
728 | - if private_project and (for_private or for_security_related): |
729 | + privileged_info = information_type != InformationType.PUBLIC |
730 | + if private_project and privileged_info: |
731 | allowed_subscribers = set() |
732 | allowed_subscribers.add(self.owner) |
733 | for bugtask in self.bugtasks: |
734 | @@ -2813,13 +2776,12 @@ |
735 | if params.product and params.product.private_bugs: |
736 | # If the private_bugs flag is set on a product, then |
737 | # force the new bug report to be private. |
738 | - params.private = True |
739 | + if params.information_type == InformationType.PUBLIC: |
740 | + params.information_type = InformationType.USERDATA |
741 | |
742 | bug, event = self.createBugWithoutTarget(params) |
743 | |
744 | - if params.security_related: |
745 | - assert params.private, ( |
746 | - "A security related bug should always be private by default.") |
747 | + if params.information_type in SECURITY_INFORMATION_TYPES: |
748 | if params.product: |
749 | context = params.product |
750 | else: |
751 | @@ -2905,21 +2867,22 @@ |
752 | params.description = params.msg.text_contents |
753 | |
754 | extra_params = {} |
755 | - if params.private: |
756 | + if params.information_type in PRIVATE_INFORMATION_TYPES: |
757 | # We add some auditing information. After bug creation |
758 | # time these attributes are updated by Bug.setPrivate(). |
759 | extra_params.update( |
760 | date_made_private=params.datecreated, |
761 | who_made_private=params.owner) |
762 | |
763 | - information_type = convert_to_information_type( |
764 | - params.private, params.security_related) |
765 | + # Set the legacy attributes for now. |
766 | + private = params.information_type in PRIVATE_INFORMATION_TYPES |
767 | + security_related = ( |
768 | + params.information_type in SECURITY_INFORMATION_TYPES) |
769 | bug = Bug( |
770 | title=params.title, description=params.description, |
771 | - _private=params.private, owner=params.owner, |
772 | - datecreated=params.datecreated, |
773 | - _security_related=params.security_related, |
774 | - information_type=information_type, |
775 | + owner=params.owner, datecreated=params.datecreated, |
776 | + information_type=params.information_type, |
777 | + _private=private, _security_related=security_related, |
778 | **extra_params) |
779 | |
780 | if params.subscribe_owner: |
781 | |
782 | === modified file 'lib/lp/bugs/model/bugtask.py' |
783 | --- lib/lp/bugs/model/bugtask.py 2012-03-21 17:31:45 +0000 |
784 | +++ lib/lp/bugs/model/bugtask.py 2012-03-29 05:56:22 +0000 |
785 | @@ -43,10 +43,8 @@ |
786 | And, |
787 | Join, |
788 | Or, |
789 | - Select, |
790 | SQL, |
791 | Sum, |
792 | - Union, |
793 | ) |
794 | from storm.store import ( |
795 | EmptyResultSet, |
796 | @@ -86,6 +84,7 @@ |
797 | UserCannotEditBugTaskMilestone, |
798 | UserCannotEditBugTaskStatus, |
799 | ) |
800 | +from lp.registry.enums import PUBLIC_INFORMATION_TYPES |
801 | from lp.registry.interfaces.distribution import ( |
802 | IDistribution, |
803 | IDistributionSet, |
804 | @@ -1698,7 +1697,8 @@ |
805 | def getStatusCountsForProductSeries(self, user, product_series): |
806 | """See `IBugTaskSet`.""" |
807 | if user is None: |
808 | - bug_privacy_filter = 'AND Bug.private IS FALSE' |
809 | + bug_privacy_filter = 'AND Bug.information_type IN %s' % ( |
810 | + sqlvalues(PUBLIC_INFORMATION_TYPES)) |
811 | else: |
812 | # Since the count won't reveal sensitive information, and |
813 | # since the get_bug_privacy_filter() check for non-admins is |
814 | |
815 | === modified file 'lib/lp/bugs/model/tests/test_bug.py' |
816 | --- lib/lp/bugs/model/tests/test_bug.py 2012-03-26 00:12:50 +0000 |
817 | +++ lib/lp/bugs/model/tests/test_bug.py 2012-03-29 05:56:22 +0000 |
818 | @@ -603,8 +603,11 @@ |
819 | removeSecurityProxy(bug_product).private_bugs = True |
820 | bug = self.factory.makeBug(owner=bug_owner, product=bug_product) |
821 | with person_logged_in(bug_owner): |
822 | - bug.setPrivacyAndSecurityRelated( |
823 | - private_security_related, private_security_related, bug_owner) |
824 | + if private_security_related: |
825 | + information_type = InformationType.EMBARGOEDSECURITY |
826 | + else: |
827 | + information_type = InformationType.PUBLIC |
828 | + bug.transitionToInformationType(information_type, bug_owner) |
829 | owner_a = self.factory.makePerson(name='ownera') |
830 | product_series_a = self.factory.makeProductSeries( |
831 | product=bug_product, owner=owner_a) |
832 | @@ -639,8 +642,8 @@ |
833 | for subscriber in initial_subscribers: |
834 | bug.subscribe(subscriber, bug_owner) |
835 | who = self.factory.makePerson() |
836 | - bug.setPrivacyAndSecurityRelated( |
837 | - private=True, security_related=True, who=who) |
838 | + bug.transitionToInformationType( |
839 | + InformationType.EMBARGOEDSECURITY, who=who) |
840 | subscribers = bug.getDirectSubscribers() |
841 | expected_subscribers = set(( |
842 | bugtask_a.owner, |
843 | @@ -672,8 +675,7 @@ |
844 | for subscriber in initial_subscribers: |
845 | bug.subscribe(subscriber, bug_owner) |
846 | who = self.factory.makePerson() |
847 | - bug.setPrivacyAndSecurityRelated( |
848 | - private=True, security_related=False, who=who) |
849 | + bug.transitionToInformationType(InformationType.USERDATA, who) |
850 | subscribers = bug.getDirectSubscribers() |
851 | expected_subscribers = set(( |
852 | default_bugtask.pillar.bug_supervisor, |
853 | @@ -704,8 +706,8 @@ |
854 | for subscriber in initial_subscribers: |
855 | bug.subscribe(subscriber, bug_owner) |
856 | who = self.factory.makePerson() |
857 | - bug.setPrivacyAndSecurityRelated( |
858 | - private=False, security_related=True, who=who) |
859 | + bug.transitionToInformationType( |
860 | + InformationType.UNEMBARGOEDSECURITY, who) |
861 | subscribers = bug.getDirectSubscribers() |
862 | expected_subscribers = set(( |
863 | default_bugtask.pillar.driver, |
864 | @@ -731,8 +733,7 @@ |
865 | bug.subscribe(subscriber, bug_owner) |
866 | who = self.factory.makePerson() |
867 | expected_direct_subscribers = set(bug.getDirectSubscribers()) |
868 | - bug.setPrivacyAndSecurityRelated( |
869 | - private=False, security_related=False, who=who) |
870 | + bug.transitionToInformationType(InformationType.PUBLIC, who) |
871 | subscribers = set(bug.getDirectSubscribers()) |
872 | expected_direct_subscribers.difference_update( |
873 | (default_bugtask.pillar.security_contact, |
874 | @@ -747,8 +748,7 @@ |
875 | bug = self.factory.makeBug(owner=bug_owner) |
876 | with person_logged_in(bug_owner): |
877 | who = self.factory.makePerson() |
878 | - bug.setPrivacyAndSecurityRelated( |
879 | - private=True, security_related=False, who=who) |
880 | + bug.transitionToInformationType(InformationType.USERDATA, who) |
881 | subscribers = bug.getDirectSubscribers() |
882 | naked_bugtask = removeSecurityProxy(bug).default_bugtask |
883 | self.assertContentEqual( |
884 | @@ -762,8 +762,8 @@ |
885 | bug = self.factory.makeBug(owner=bug_owner) |
886 | with person_logged_in(bug_owner): |
887 | who = self.factory.makePerson() |
888 | - bug.setPrivacyAndSecurityRelated( |
889 | - private=False, security_related=True, who=who) |
890 | + bug.transitionToInformationType( |
891 | + InformationType.UNEMBARGOEDSECURITY, who) |
892 | subscribers = bug.getDirectSubscribers() |
893 | naked_bugtask = removeSecurityProxy(bug).default_bugtask |
894 | self.assertContentEqual( |
895 | @@ -833,8 +833,8 @@ |
896 | with person_logged_in(bug_owner): |
897 | bug.subscribe(default_bugtask.pillar.bug_supervisor, bug_owner) |
898 | who = self.factory.makePerson(name="who") |
899 | - bug.setPrivacyAndSecurityRelated( |
900 | - private=False, security_related=True, who=who) |
901 | + bug.transitionToInformationType( |
902 | + InformationType.UNEMBARGOEDSECURITY, who) |
903 | subscribers = bug.getDirectSubscribers() |
904 | self.assertNotIn( |
905 | default_bugtask.pillar.bug_supervisor, subscribers) |
906 | @@ -863,8 +863,7 @@ |
907 | self.assertFalse(bug_supervisor in bug.getDirectSubscribers()) |
908 | with person_logged_in(bug_owner): |
909 | who = self.factory.makePerson(name="who") |
910 | - bug.setPrivacyAndSecurityRelated( |
911 | - private=True, security_related=False, who=who) |
912 | + bug.transitionToInformationType(InformationType.USERDATA, who) |
913 | self.assertTrue(bug_supervisor in bug.getDirectSubscribers()) |
914 | |
915 | def test_securityContactUnsubscribedIfBugNotSecurityRelated(self): |
916 | @@ -878,8 +877,7 @@ |
917 | with person_logged_in(bug_owner): |
918 | bug.subscribe(bugtask_a.pillar.security_contact, bug_owner) |
919 | who = self.factory.makePerson(name="who") |
920 | - bug.setPrivacyAndSecurityRelated( |
921 | - private=True, security_related=False, who=who) |
922 | + bug.transitionToInformationType(InformationType.USERDATA, who) |
923 | subscribers = bug.getDirectSubscribers() |
924 | self.assertFalse(bugtask_a.pillar.security_contact in subscribers) |
925 | |
926 | @@ -905,17 +903,16 @@ |
927 | self.factory.makeBugTask(bug=bug, target=product) |
928 | login_person(bug.owner) |
929 | self.assertRaises( |
930 | - BugCannotBePrivate, bug.setPrivacyAndSecurityRelated, True, False, |
931 | - bug.owner) |
932 | - self.assertRaises( |
933 | - BugCannotBePrivate, bug.setPrivate, True, bug.owner) |
934 | + BugCannotBePrivate, bug.transitionToInformationType, |
935 | + InformationType.USERDATA, bug.owner) |
936 | |
937 | # Some teams though need multi-pillar private bugs. |
938 | feature_flag = { |
939 | 'disclosure.allow_multipillar_private_bugs.enabled': 'on' |
940 | } |
941 | with FeatureFixture(feature_flag): |
942 | - bug.setPrivacyAndSecurityRelated(True, False, bug.owner) |
943 | + bug.transitionToInformationType( |
944 | + InformationType.USERDATA, bug.owner) |
945 | self.assertTrue(bug.private) |
946 | |
947 | def test_bug_information_type(self): |
948 | @@ -960,7 +957,7 @@ |
949 | bug = self.factory.makeBug( |
950 | private=True, security_related=True, owner=owner) |
951 | with person_logged_in(owner): |
952 | - bug.setPrivacyAndSecurityRelated(False, False, owner) |
953 | + bug.transitionToInformationType(InformationType.PUBLIC, owner) |
954 | self.assertEqual(InformationType.PUBLIC, bug.information_type) |
955 | |
956 | def test_public_to_private_information_type(self): |
957 | |
958 | === modified file 'lib/lp/bugs/scripts/bugimport.py' |
959 | --- lib/lp/bugs/scripts/bugimport.py 2012-03-22 23:21:24 +0000 |
960 | +++ lib/lp/bugs/scripts/bugimport.py 2012-03-29 05:56:22 +0000 |
961 | @@ -40,6 +40,7 @@ |
962 | from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
963 | from lp.services.librarian.interfaces import ILibraryFileAliasSet |
964 | from lp.services.messages.interfaces.message import IMessageSet |
965 | +from lp.bugs.adapters.bug import convert_to_information_type |
966 | from lp.bugs.interfaces.bug import ( |
967 | CreateBugParams, |
968 | IBugSet, |
969 | @@ -295,6 +296,8 @@ |
970 | # If the product has private_bugs, we force private to True. |
971 | if self.product.private_bugs: |
972 | private = True |
973 | + information_type = convert_to_information_type( |
974 | + private, security_related) |
975 | |
976 | if owner is None: |
977 | owner = self.bug_importer |
978 | @@ -302,12 +305,8 @@ |
979 | msg = self.createMessage(commentnode, defaulttitle=title) |
980 | |
981 | bug = self.product.createBug(CreateBugParams( |
982 | - msg=msg, |
983 | - datecreated=datecreated, |
984 | - title=title, |
985 | - private=private or security_related, |
986 | - security_related=security_related, |
987 | - owner=owner)) |
988 | + msg=msg, datecreated=datecreated, title=title, |
989 | + information_type=information_type, owner=owner)) |
990 | bugtask = bug.bugtasks[0] |
991 | self.logger.info('Creating Launchpad bug #%d', bug.id) |
992 | |
993 | @@ -324,8 +323,9 @@ |
994 | |
995 | # Security bugs must be created private, so set it correctly. |
996 | if not self.product.private_bugs: |
997 | - bug.setPrivacyAndSecurityRelated( |
998 | - private, security_related, owner) |
999 | + information_type = convert_to_information_type( |
1000 | + private, security_related) |
1001 | + bug.transitionToInformationType(information_type, owner) |
1002 | bug.name = get_value(bugnode, 'nickname') |
1003 | description = get_value(bugnode, 'description') |
1004 | if description: |
1005 | |
1006 | === modified file 'lib/lp/bugs/stories/bugs/xx-bug-activity.txt' |
1007 | --- lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2011-12-02 17:44:47 +0000 |
1008 | +++ lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2012-03-29 05:56:22 +0000 |
1009 | @@ -123,6 +123,12 @@ |
1010 | public => private |
1011 | -------- |
1012 | |
1013 | + >>> admin_browser.open( |
1014 | + ... 'http://bugs.launchpad.dev/redfish/+bug/15/+secrecy') |
1015 | + >>> admin_browser.getControl( |
1016 | + ... "This bug report should be private").selected = False |
1017 | + >>> admin_browser.getControl("Change").click() |
1018 | + |
1019 | Clean up the feature flag. |
1020 | >>> flags.cleanUp() |
1021 | |
1022 | |
1023 | === modified file 'lib/lp/bugs/xmlrpc/bug.py' |
1024 | --- lib/lp/bugs/xmlrpc/bug.py 2012-01-01 02:58:52 +0000 |
1025 | +++ lib/lp/bugs/xmlrpc/bug.py 2012-03-29 05:56:22 +0000 |
1026 | @@ -1,10 +1,13 @@ |
1027 | -# Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
1028 | +# Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
1029 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1030 | |
1031 | """XML-RPC APIs for Malone.""" |
1032 | |
1033 | __metaclass__ = type |
1034 | -__all__ = ["FileBugAPI", "ExternalBugTrackerTokenAPI"] |
1035 | +__all__ = [ |
1036 | + "ExternalBugTrackerTokenAPI", |
1037 | + "FileBugAPI", |
1038 | + ] |
1039 | |
1040 | from zope.component import getUtility |
1041 | from zope.interface import implements |
1042 | @@ -12,6 +15,7 @@ |
1043 | from lp.app.errors import NotFoundError |
1044 | from lp.bugs.interfaces.bug import CreateBugParams |
1045 | from lp.bugs.interfaces.externalbugtracker import IExternalBugTrackerTokenAPI |
1046 | +from lp.registry.enums import InformationType |
1047 | from lp.registry.interfaces.distribution import IDistributionSet |
1048 | from lp.registry.interfaces.person import IPersonSet |
1049 | from lp.registry.interfaces.product import IProductSet |
1050 | @@ -100,14 +104,14 @@ |
1051 | else: |
1052 | subscriber_list.append(subscriber) |
1053 | |
1054 | - security_related = bool(security_related) |
1055 | - |
1056 | - # Privacy is always set the same as security, by default. |
1057 | - private = security_related |
1058 | + if security_related: |
1059 | + information_type = InformationType.EMBARGOEDSECURITY |
1060 | + else: |
1061 | + information_type = InformationType.PUBLIC |
1062 | |
1063 | params = CreateBugParams( |
1064 | owner=self.user, title=summary, comment=comment, |
1065 | - security_related=security_related, private=private, |
1066 | + information_type=information_type, |
1067 | subscribers=subscriber_list) |
1068 | |
1069 | bug = target.createBug(params) |
1070 | |
1071 | === modified file 'lib/lp/registry/enums.py' |
1072 | --- lib/lp/registry/enums.py 2012-03-25 23:33:53 +0000 |
1073 | +++ lib/lp/registry/enums.py 2012-03-29 05:56:22 +0000 |
1074 | @@ -10,6 +10,7 @@ |
1075 | 'InformationType', |
1076 | 'PersonTransferJobType', |
1077 | 'PRIVATE_INFORMATION_TYPES', |
1078 | + 'PUBLIC_INFORMATION_TYPES', |
1079 | 'ProductJobType', |
1080 | 'SECURITY_INFORMATION_TYPES', |
1081 | 'SharingPermission', |
1082 | @@ -63,6 +64,10 @@ |
1083 | """) |
1084 | |
1085 | |
1086 | +PUBLIC_INFORMATION_TYPES = ( |
1087 | + InformationType.PUBLIC, InformationType.UNEMBARGOEDSECURITY) |
1088 | + |
1089 | + |
1090 | PRIVATE_INFORMATION_TYPES = ( |
1091 | InformationType.EMBARGOEDSECURITY, InformationType.USERDATA, |
1092 | InformationType.PROPRIETARY) |
1093 | |
1094 | === modified file 'lib/lp/registry/model/person.py' |
1095 | --- lib/lp/registry/model/person.py 2012-03-27 19:46:03 +0000 |
1096 | +++ lib/lp/registry/model/person.py 2012-03-29 05:56:22 +0000 |
1097 | @@ -147,6 +147,7 @@ |
1098 | HasMergeProposalsMixin, |
1099 | HasRequestedReviewsMixin, |
1100 | ) |
1101 | +from lp.registry.enums import PRIVATE_INFORMATION_TYPES |
1102 | from lp.registry.errors import ( |
1103 | InvalidName, |
1104 | JoinNotAllowed, |
1105 | @@ -1849,14 +1850,16 @@ |
1106 | Bug, |
1107 | Join(BugSubscription, BugSubscription.bug_id == Bug.id)), |
1108 | where=And( |
1109 | - Bug._private == True, |
1110 | + Bug.information_type.is_in(PRIVATE_INFORMATION_TYPES), |
1111 | BugSubscription.person_id == self.id)), |
1112 | Select( |
1113 | Bug.id, |
1114 | tables=( |
1115 | Bug, |
1116 | Join(BugTask, BugTask.bugID == Bug.id)), |
1117 | - where=And(Bug._private == True, BugTask.assignee == self.id)), |
1118 | + where=And(Bug.information_type.is_in( |
1119 | + PRIVATE_INFORMATION_TYPES), |
1120 | + BugTask.assignee == self.id)), |
1121 | limit=1)) |
1122 | if private_bugs_involved.rowcount: |
1123 | raise TeamSubscriptionPolicyError( |
1124 | |
1125 | === modified file 'lib/lp/security.py' |
1126 | --- lib/lp/security.py 2012-03-19 16:02:52 +0000 |
1127 | +++ lib/lp/security.py 2012-03-29 05:56:22 +0000 |
1128 | @@ -986,6 +986,7 @@ |
1129 | user_private_bugs_visible_filter = get_bug_privacy_filter( |
1130 | user.person, private_only=True) |
1131 | |
1132 | + # 1 = PUBLIC, 2 = UNEMBARGOEDSECURITY |
1133 | query = """ |
1134 | SELECT TRUE WHERE |
1135 | EXISTS ( |
1136 | @@ -1005,7 +1006,8 @@ |
1137 | -- do those first. |
1138 | %(team_bug_select)s |
1139 | WHERE bug_id in ( |
1140 | - SELECT Bug.id FROM Bug WHERE Bug.private is FALSE |
1141 | + SELECT Bug.id FROM Bug WHERE Bug.information_type IN |
1142 | + (1, 2) |
1143 | ) |
1144 | UNION ALL |
1145 | -- Now do the private bugs the user can see. |
1146 | |
1147 | === modified file 'lib/lp/systemhomes.py' |
1148 | --- lib/lp/systemhomes.py 2011-12-30 07:32:58 +0000 |
1149 | +++ lib/lp/systemhomes.py 2012-03-29 05:56:22 +0000 |
1150 | @@ -1,4 +1,4 @@ |
1151 | -# Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
1152 | +# Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
1153 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1154 | |
1155 | """Content classes for the 'home pages' of the subsystems of Launchpad.""" |
1156 | @@ -24,6 +24,7 @@ |
1157 | from zope.component import getUtility |
1158 | from zope.interface import implements |
1159 | |
1160 | +from lp.bugs.adapters.bug import convert_to_information_type |
1161 | from lp.bugs.errors import InvalidBugTargetType |
1162 | from lp.bugs.interfaces.bug import ( |
1163 | CreateBugParams, |
1164 | @@ -126,9 +127,11 @@ |
1165 | def createBug(self, owner, title, description, target, |
1166 | security_related=False, private=False, tags=None): |
1167 | """See `IMaloneApplication`.""" |
1168 | + information_type = convert_to_information_type( |
1169 | + private, security_related) |
1170 | params = CreateBugParams( |
1171 | title=title, comment=description, owner=owner, |
1172 | - security_related=security_related, private=private, tags=tags) |
1173 | + information_type=information_type, tags=tags) |
1174 | if IProduct.providedBy(target): |
1175 | params.setBugTarget(product=target) |
1176 | elif IDistribution.providedBy(target): |
1177 | |
1178 | === modified file 'lib/lp/testing/factory.py' |
1179 | --- lib/lp/testing/factory.py 2012-03-28 18:13:37 +0000 |
1180 | +++ lib/lp/testing/factory.py 2012-03-29 05:56:22 +0000 |
1181 | @@ -77,6 +77,7 @@ |
1182 | ) |
1183 | from lp.blueprints.interfaces.specification import ISpecificationSet |
1184 | from lp.blueprints.interfaces.sprint import ISprintSet |
1185 | +from lp.bugs.adapters.bug import convert_to_information_type |
1186 | from lp.bugs.interfaces.bug import ( |
1187 | CreateBugParams, |
1188 | IBugSet, |
1189 | @@ -1688,9 +1689,11 @@ |
1190 | self.makeSourcePackagePublishingHistory( |
1191 | distroseries=distribution.currentseries, |
1192 | sourcepackagename=sourcepackagename) |
1193 | + # Factory changes delayed for a seperate branch. |
1194 | + information_type = convert_to_information_type( |
1195 | + private, security_related) |
1196 | create_bug_params = CreateBugParams( |
1197 | - owner, title, comment=comment, private=private, |
1198 | - security_related=security_related, |
1199 | + owner, title, comment=comment, information_type=information_type, |
1200 | datecreated=date_created, description=description, |
1201 | status=status, tags=tags) |
1202 | create_bug_params.setBugTarget( |
This looks good. As discussed, setPrivacyAndSe curityRelated could be changed to no longer return a tuple.
I am scared there's stuff we haven't anticipated that could break, but that's what our marvellous tests are for, right?