Merge lp:~wgrant/launchpad/remove-extra-privacy into lp:launchpad

Proposed by William Grant
Status: Merged
Approved by: William Grant
Approved revision: no longer in the source branch.
Merged at revision: 14805
Proposed branch: lp:~wgrant/launchpad/remove-extra-privacy
Merge into: lp:launchpad
Diff against target: 306 lines (+19/-224)
5 files modified
lib/lp/bugs/browser/tests/test_bugtask.py (+0/-35)
lib/lp/bugs/model/bugtasksearch.py (+19/-114)
lib/lp/bugs/tests/test_bugtask_search.py (+0/-55)
lib/lp/bugs/tests/test_bugvisibility.py (+0/-13)
lib/lp/services/features/flags.py (+0/-7)
To merge this branch: bzr merge lp:~wgrant/launchpad/remove-extra-privacy
Reviewer Review Type Date Requested Status
Steve Kowalik (community) code Approve
Review via email: mp+93122@code.launchpad.net

Commit message

[r=stevenk][no-qa] Clean up obsolete bug visibility feature flags and code.

Description of the change

This branch removes two bug visibility feature flags.

disclosure.private_bug_visibility_cte.enabled turned on some performance-sensitive query changes. It's been enabled on production for some months now without a problem, so the old non-CTE code can go away.

disclosure.private_bug_visibility_rules.enabled was never enabled beyond ~launchpad, has security issues around multi-tenancy, is non-performant, and will soon be replaced by modern disclosure. I've removed the code enabled by this flag, reverting ~launchpad to the old behaviour.

This is preparation for the refactoring of bug searches to use a flattened fact table.

To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) wrote :

This looks like excellent work, thanks!

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/bugs/browser/tests/test_bugtask.py'
2--- lib/lp/bugs/browser/tests/test_bugtask.py 2012-02-08 10:43:29 +0000
3+++ lib/lp/bugs/browser/tests/test_bugtask.py 2012-02-15 03:24:20 +0000
4@@ -1403,41 +1403,6 @@
5 notifications = view.request.response.notifications
6 self.assertEqual(0, len(notifications))
7
8- def test_retarget_private_bug(self):
9- # If a private bug is re-targetted such that the bug is no longer
10- # visible to the user, they are redirected to the pillar's bug index
11- # page with a suitable message. This corner case can occur when the
12- # disclosure.private_bug_visibility_rules.enabled feature flag is on
13- # and a bugtask is re-targetted to a pillar for which the user is not
14- # authorised to see any private bugs.
15- first_product = self.factory.makeProduct(name='bunny')
16- with person_logged_in(first_product.owner):
17- bug = self.factory.makeBug(product=first_product, private=True)
18- bug_task = bug.bugtasks[0]
19- second_product = self.factory.makeProduct(name='duck')
20-
21- # The first product owner can see the private bug. We will re-target
22- # it to second_product where it will not be visible to that user.
23- with person_logged_in(first_product.owner):
24- form = {
25- 'bunny.target': 'product',
26- 'bunny.target.product': 'duck',
27- 'bunny.actions.save': 'Save Changes',
28- }
29- with FeatureFixture({
30- 'disclosure.private_bug_visibility_rules.enabled': 'on'}):
31- view = create_initialized_view(
32- bug_task, name='+editstatus', form=form)
33- self.assertEqual(
34- canonical_url(bug_task.pillar, rootsite='bugs'),
35- view.next_url)
36- self.assertEqual([], view.errors)
37- self.assertEqual(second_product, bug_task.target)
38- notifications = view.request.response.notifications
39- self.assertEqual(1, len(notifications))
40- expected = ('The bug you have just updated is now a private bug for')
41- self.assertTrue(notifications.pop().message.startswith(expected))
42-
43
44 class TestPersonBugs(TestCaseWithFactory):
45 """Test the bugs overview page for distributions."""
46
47=== modified file 'lib/lp/bugs/model/bugtasksearch.py'
48--- lib/lp/bugs/model/bugtasksearch.py 2012-02-09 01:42:08 +0000
49+++ lib/lp/bugs/model/bugtasksearch.py 2012-02-15 03:24:20 +0000
50@@ -1464,118 +1464,23 @@
51 # part of the WHERE condition (i.e. the bit below.) The
52 # other half of this condition (see code above) does not
53 # use TeamParticipation at all.
54- pillar_privacy_filters = ''
55- if features.getFeatureFlag(
56- 'disclosure.private_bug_visibility_cte.enabled'):
57- if features.getFeatureFlag(
58- 'disclosure.private_bug_visibility_rules.enabled'):
59- pillar_privacy_filters = """
60- UNION ALL
61- SELECT BugTask.bug
62- FROM BugTask, Product
63- WHERE Product.owner IN (SELECT team FROM teams) AND
64- BugTask.product = Product.id AND
65- BugTask.bug = Bug.id AND
66- Bug.security_related IS False
67- UNION ALL
68- SELECT BugTask.bug
69- FROM BugTask, ProductSeries
70- WHERE ProductSeries.owner IN (SELECT team FROM teams) AND
71- BugTask.productseries = ProductSeries.id AND
72- BugTask.bug = Bug.id AND
73- Bug.security_related IS False
74- UNION ALL
75- SELECT BugTask.bug
76- FROM BugTask, Distribution
77- WHERE Distribution.owner IN (SELECT team FROM teams) AND
78- BugTask.distribution = Distribution.id AND
79- BugTask.bug = Bug.id AND
80- Bug.security_related IS False
81- UNION ALL
82- SELECT BugTask.bug
83- FROM BugTask, DistroSeries, Distribution
84- WHERE Distribution.owner IN (SELECT team FROM teams) AND
85- DistroSeries.distribution = Distribution.id AND
86- BugTask.distroseries = DistroSeries.id AND
87- BugTask.bug = Bug.id AND
88- Bug.security_related IS False
89- """
90- query = """
91- (%(public_bug_filter)s EXISTS (
92- WITH teams AS (
93- SELECT team from TeamParticipation
94- WHERE person = %(personid)s
95- )
96- SELECT BugSubscription.bug
97- FROM BugSubscription
98- WHERE BugSubscription.person IN (SELECT team FROM teams) AND
99- BugSubscription.bug = Bug.id
100- UNION ALL
101- SELECT BugTask.bug
102- FROM BugTask
103- WHERE BugTask.assignee IN (SELECT team FROM teams) AND
104- BugTask.bug = Bug.id
105- %(extra_filters)s
106- ))
107- """ % dict(
108- personid=quote(user.id),
109- public_bug_filter=public_bug_filter,
110- extra_filters=pillar_privacy_filters)
111- else:
112- if features.getFeatureFlag(
113- 'disclosure.private_bug_visibility_rules.enabled'):
114- pillar_privacy_filters = """
115- UNION ALL
116- SELECT BugTask.bug
117- FROM BugTask, TeamParticipation, Product
118- WHERE TeamParticipation.person = %(personid)s AND
119- TeamParticipation.team = Product.owner AND
120- BugTask.product = Product.id AND
121- BugTask.bug = Bug.id AND
122- Bug.security_related IS False
123- UNION ALL
124- SELECT BugTask.bug
125- FROM BugTask, TeamParticipation, ProductSeries
126- WHERE TeamParticipation.person = %(personid)s AND
127- TeamParticipation.team = ProductSeries.owner AND
128- BugTask.productseries = ProductSeries.id AND
129- BugTask.bug = Bug.id AND
130- Bug.security_related IS False
131- UNION ALL
132- SELECT BugTask.bug
133- FROM BugTask, TeamParticipation, Distribution
134- WHERE TeamParticipation.person = %(personid)s AND
135- TeamParticipation.team = Distribution.owner AND
136- BugTask.distribution = Distribution.id AND
137- BugTask.bug = Bug.id AND
138- Bug.security_related IS False
139- UNION ALL
140- SELECT BugTask.bug
141- FROM BugTask, TeamParticipation, DistroSeries, Distribution
142- WHERE TeamParticipation.person = %(personid)s AND
143- TeamParticipation.team = Distribution.owner AND
144- DistroSeries.distribution = Distribution.id AND
145- BugTask.distroseries = DistroSeries.id AND
146- BugTask.bug = Bug.id AND
147- Bug.security_related IS False
148- """ % sqlvalues(personid=user.id)
149- query = """
150- (%(public_bug_filter)s EXISTS (
151- SELECT BugSubscription.bug
152- FROM BugSubscription, TeamParticipation
153- WHERE TeamParticipation.person = %(personid)s AND
154- TeamParticipation.team = BugSubscription.person AND
155- BugSubscription.bug = Bug.id
156- UNION ALL
157- SELECT BugTask.bug
158- FROM BugTask, TeamParticipation
159- WHERE TeamParticipation.person = %(personid)s AND
160- TeamParticipation.team = BugTask.assignee AND
161- BugTask.bug = Bug.id
162- %(extra_filters)s
163- ))
164- """ % dict(
165- personid=quote(user.id),
166- public_bug_filter=public_bug_filter,
167- extra_filters=pillar_privacy_filters)
168+ query = """
169+ (%(public_bug_filter)s EXISTS (
170+ WITH teams AS (
171+ SELECT team from TeamParticipation
172+ WHERE person = %(personid)s
173+ )
174+ SELECT BugSubscription.bug
175+ FROM BugSubscription
176+ WHERE BugSubscription.person IN (SELECT team FROM teams) AND
177+ BugSubscription.bug = Bug.id
178+ UNION ALL
179+ SELECT BugTask.bug
180+ FROM BugTask
181+ WHERE BugTask.assignee IN (SELECT team FROM teams) AND
182+ BugTask.bug = Bug.id
183+ ))
184+ """ % dict(
185+ personid=quote(user.id),
186+ public_bug_filter=public_bug_filter)
187 return query, _make_cache_user_can_view_bug(user)
188
189=== modified file 'lib/lp/bugs/tests/test_bugtask_search.py'
190--- lib/lp/bugs/tests/test_bugtask_search.py 2012-02-02 21:52:43 +0000
191+++ lib/lp/bugs/tests/test_bugtask_search.py 2012-02-15 03:24:20 +0000
192@@ -53,12 +53,6 @@
193 from lp.testing.matchers import HasQueryCount
194
195
196-PRIVATE_BUG_VISIBILITY_FLAG = {
197- 'disclosure.private_bug_visibility_rules.enabled': 'on'}
198-PRIVATE_BUG_VISIBILITY_CTE_FLAG = {
199- 'disclosure.private_bug_visibility_cte.enabled': 'on'}
200-
201-
202 class SearchTestBase:
203 """A mixin class with tests useful for all targets and search variants."""
204
205@@ -151,55 +145,6 @@
206 params = self.getBugTaskSearchParams(user=user)
207 self.assertSearchFinds(params, self.bugtasks)
208
209- def test_private_bug_in_search_result_pillar_owners(self):
210- # Private, non-security bugs are included in search results for the
211- # pillar owners if the correct feature flag is enabled.
212- bugtask = self.bugtasks[-1]
213- pillar_owner = bugtask.pillar.owner
214- with person_logged_in(self.owner):
215- bugtask.bug.setPrivate(True, self.owner)
216- bugtask.bug.unsubscribe(pillar_owner, self.owner)
217- params = self.getBugTaskSearchParams(user=pillar_owner)
218- # Check the results with the feature flag.
219- with FeatureFixture(PRIVATE_BUG_VISIBILITY_FLAG):
220- self.assertSearchFinds(params, self.bugtasks)
221- # Check the results without the feature flag.
222- self.assertSearchFinds(params, self.bugtasks[:-1])
223-
224- # Make the bugtask security related.
225- with person_logged_in(self.owner):
226- bugtask.bug.setSecurityRelated(True, self.owner)
227- bugtask.bug.unsubscribe(pillar_owner, self.owner)
228- # It should now be excluded from the results.
229- with FeatureFixture(PRIVATE_BUG_VISIBILITY_FLAG):
230- self.assertSearchFinds(params, self.bugtasks[:-1])
231-
232- def test_private_bug_in_search_result_pillar_owners_cte(self):
233- # Like test_private_bug_in_search_result_pillar_owners, but with
234- # the new CTE-based visibility query.
235- bugtask = self.bugtasks[-1]
236- pillar_owner = bugtask.pillar.owner
237- with person_logged_in(self.owner):
238- bugtask.bug.setPrivate(True, self.owner)
239- bugtask.bug.unsubscribe(pillar_owner, self.owner)
240- params = self.getBugTaskSearchParams(user=pillar_owner)
241- # Check the results with the feature flag.
242- flags = dict()
243- flags.update(PRIVATE_BUG_VISIBILITY_FLAG)
244- flags.update(PRIVATE_BUG_VISIBILITY_CTE_FLAG)
245- with FeatureFixture(flags):
246- self.assertSearchFinds(params, self.bugtasks)
247- # Check the results without the feature flag.
248- self.assertSearchFinds(params, self.bugtasks[:-1])
249-
250- # Make the bugtask security related.
251- with person_logged_in(self.owner):
252- bugtask.bug.setSecurityRelated(True, self.owner)
253- bugtask.bug.unsubscribe(pillar_owner, self.owner)
254- # It should now be excluded from the results.
255- with FeatureFixture(PRIVATE_BUG_VISIBILITY_FLAG):
256- self.assertSearchFinds(params, self.bugtasks[:-1])
257-
258 def test_search_by_bug_reporter(self):
259 # Search results can be limited to bugs filed by a given person.
260 bugtask = self.bugtasks[0]
261
262=== modified file 'lib/lp/bugs/tests/test_bugvisibility.py'
263--- lib/lp/bugs/tests/test_bugvisibility.py 2012-01-01 02:58:52 +0000
264+++ lib/lp/bugs/tests/test_bugvisibility.py 2012-02-15 03:24:20 +0000
265@@ -3,7 +3,6 @@
266
267 """Tests for visibility of a bug."""
268
269-from lp.services.features.testing import FeatureFixture
270 from lp.testing import (
271 celebrity_logged_in,
272 TestCaseWithFactory,
273@@ -83,15 +82,3 @@
274 def test_publicBugAnonUser(self):
275 # Since the bug is private, the anonymous user cannot see it.
276 self.assertFalse(self.bug.userCanView(None))
277-
278-
279-class TestPrivateBugVisibilityWithCTE(TestPrivateBugVisibility):
280- """Test visibility for private bugs, without the TeamParticipation CTE.
281-
282- The flag exists only as an emergency performance switch.
283- """
284-
285- def setUp(self):
286- super(TestPrivateBugVisibilityWithCTE, self).setUp()
287- self.useFixture(FeatureFixture(
288- {'disclosure.private_bug_visibility_cte.enabled': 'on'}))
289
290=== modified file 'lib/lp/services/features/flags.py'
291--- lib/lp/services/features/flags.py 2012-02-03 04:48:28 +0000
292+++ lib/lp/services/features/flags.py 2012-02-15 03:24:20 +0000
293@@ -200,13 +200,6 @@
294 '',
295 '',
296 ''),
297- ('disclosure.private_bug_visibility_rules.enabled',
298- 'boolean',
299- ('Enables the application of additional privacy filter terms in bug '
300- 'queries to allow defined project roles to see private bugs.'),
301- '',
302- '',
303- ''),
304 ('disclosure.enhanced_private_bug_subscriptions.enabled',
305 'boolean',
306 ('Enables the auto subscribing and unsubscribing of users as a bug '