Merge lp:~stevenk/launchpad/fix-rasj-and-branches into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Approved by: Steve Kowalik
Approved revision: no longer in the source branch.
Merged at revision: 15623
Proposed branch: lp:~stevenk/launchpad/fix-rasj-and-branches
Merge into: lp:launchpad
Diff against target: 172 lines (+50/-24)
3 files modified
lib/lp/code/model/branch.py (+11/-2)
lib/lp/registry/model/sharingjob.py (+27/-22)
lib/lp/registry/tests/test_sharingjob.py (+12/-0)
To merge this branch: bzr merge lp:~stevenk/launchpad/fix-rasj-and-branches
Reviewer Review Type Date Requested Status
Ian Booth (community) Approve
Review via email: mp+114779@code.launchpad.net

Commit message

Fix RemoveArtifactSubscriptionsJob to deal with branches correctly, and create a job in IBranch.transitionToInformationType().

Description of the change

While QAing the changes introduced in https://code.launchpad.net/~stevenk/launchpad/teach-rasj-about-branches/+merge/114106, William and I discovered that RASJ misbehaves if you don't pass any branches -- it will correctly deal with bug subscriptions, but then constructs a query that will take approximately three eons to complete on QAS, and then remove all subscriptions for that user from any branch. This is obviously bad.

I have reflowed the run() method to boot so that it won't deal with branches unless it needs to, and same with bugs, as well as sprinkling a branch into the bugs test and a bug into the branches test.

I have also noticed that IBranch.transitionToInformationType() does not create a job, so have added that in along with fixing some lint.

To post a comment you must log in.
Revision history for this message
Ian Booth (wallyworld) wrote :

Looks great.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/code/model/branch.py'
--- lib/lp/code/model/branch.py 2012-07-13 00:17:32 +0000
+++ lib/lp/code/model/branch.py 2012-07-13 04:58:27 +0000
@@ -2,7 +2,6 @@
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4# pylint: disable-msg=E0611,W0212,W0141,F04014# pylint: disable-msg=E0611,W0212,W0141,F0401
5from lp.registry.interfaces.product import IProduct
65
7__metaclass__ = type6__metaclass__ = type
8__all__ = [7__all__ = [
@@ -145,10 +144,12 @@
145 IAccessArtifactSource,144 IAccessArtifactSource,
146 )145 )
147from lp.registry.interfaces.person import (146from lp.registry.interfaces.person import (
148 PersonVisibility,
149 validate_person,147 validate_person,
150 validate_public_person,148 validate_public_person,
151 )149 )
150from lp.registry.interfaces.sharingjob import (
151 IRemoveArtifactSubscriptionsJobSource,
152 )
152from lp.registry.model.accesspolicy import (153from lp.registry.model.accesspolicy import (
153 AccessPolicyGrant,154 AccessPolicyGrant,
154 reconcile_access_for_artifact,155 reconcile_access_for_artifact,
@@ -172,6 +173,7 @@
172 ArrayAgg,173 ArrayAgg,
173 ArrayIntersects,174 ArrayIntersects,
174 )175 )
176from lp.services.features import getFeatureFlag
175from lp.services.helpers import shortlist177from lp.services.helpers import shortlist
176from lp.services.job.interfaces.job import JobStatus178from lp.services.job.interfaces.job import JobStatus
177from lp.services.job.model.job import Job179from lp.services.job.model.job import Job
@@ -271,6 +273,13 @@
271 service.ensureAccessGrants(273 service.ensureAccessGrants(
272 blind_subscribers, who, branches=[self],274 blind_subscribers, who, branches=[self],
273 ignore_permissions=True)275 ignore_permissions=True)
276 flag = 'disclosure.unsubscribe_jobs.enabled'
277 if bool(getFeatureFlag(flag)):
278 # As a result of the transition, some subscribers may no longer
279 # have access to the branch. We need to run a job to remove any
280 # such subscriptions.
281 getUtility(IRemoveArtifactSubscriptionsJobSource).create(
282 who, [self])
274283
275 registrant = ForeignKey(284 registrant = ForeignKey(
276 dbName='registrant', foreignKey='Person',285 dbName='registrant', foreignKey='Person',
277286
=== modified file 'lib/lp/registry/model/sharingjob.py'
--- lib/lp/registry/model/sharingjob.py 2012-07-11 01:24:30 +0000
+++ lib/lp/registry/model/sharingjob.py 2012-07-13 04:58:27 +0000
@@ -344,19 +344,13 @@
344 logger = logging.getLogger()344 logger = logging.getLogger()
345 logger.info(self.getOperationDescription())345 logger.info(self.getOperationDescription())
346346
347 # Find all bug subscriptions for which the subscriber cannot see the347 bug_filters = []
348 # bug.348 branch_filters = []
349 bug_invisible_filter = Not(
350 Or(*get_bug_privacy_filter_terms(BugSubscription.person_id)))
351 bug_filters = [bug_invisible_filter]
352 branch_invisible_filter = Not(
353 Or(*get_branch_privacy_filter(BranchSubscription.personID)))
354 branch_filters = [branch_invisible_filter]
355349
350 if self.branch_ids:
351 branch_filters.append(Branch.id.is_in(self.branch_ids))
356 if self.bug_ids:352 if self.bug_ids:
357 bug_filters.append(BugTaskFlat.bug_id.is_in(self.bug_ids))353 bug_filters.append(BugTaskFlat.bug_id.is_in(self.bug_ids))
358 elif self.branch_ids:
359 branch_filters.append(Branch.id.is_in(self.branch_ids))
360 else:354 else:
361 if self.information_types:355 if self.information_types:
362 bug_filters.append(356 bug_filters.append(
@@ -385,15 +379,26 @@
385 TeamParticipation.personID,379 TeamParticipation.personID,
386 where=TeamParticipation.team == self.grantee)))380 where=TeamParticipation.team == self.grantee)))
387381
388 bug_subscriptions = IStore(BugSubscription).using(382 if bug_filters:
389 BugSubscription,383 bug_filters.append(Not(
390 Join(BugTaskFlat, BugTaskFlat.bug_id == BugSubscription.bug_id)384 Or(*get_bug_privacy_filter_terms(
391 ).find(BugSubscription, *bug_filters).config(distinct=True)385 BugSubscription.person_id))))
392 branch_subscriptions = IStore(BranchSubscription).find(386 bug_subscriptions = IStore(BugSubscription).using(
393 BranchSubscription, *branch_filters).config(distinct=True)387 BugSubscription,
394 for sub in bug_subscriptions:388 Join(BugTaskFlat,
395 sub.bug.unsubscribe(389 BugTaskFlat.bug_id == BugSubscription.bug_id)
396 sub.person, self.requestor, ignore_permissions=True)390 ).find(BugSubscription, *bug_filters).config(distinct=True)
397 for sub in branch_subscriptions:391 for sub in bug_subscriptions:
398 sub.branch.unsubscribe(392 sub.bug.unsubscribe(
399 sub.person, self.requestor, ignore_permissions=True)393 sub.person, self.requestor, ignore_permissions=True)
394 if branch_filters:
395 branch_filters.append(Not(
396 Or(*get_branch_privacy_filter(BranchSubscription.personID))))
397 branch_subscriptions = IStore(BranchSubscription).using(
398 BranchSubscription,
399 Join(Branch, Branch.id == BranchSubscription.branchID)
400 ).find(BranchSubscription, *branch_filters).config(
401 distinct=True)
402 for sub in branch_subscriptions:
403 sub.branch.unsubscribe(
404 sub.person, self.requestor, ignore_permissions=True)
400405
=== modified file 'lib/lp/registry/tests/test_sharingjob.py'
--- lib/lp/registry/tests/test_sharingjob.py 2012-07-10 06:35:48 +0000
+++ lib/lp/registry/tests/test_sharingjob.py 2012-07-13 04:58:27 +0000
@@ -293,6 +293,9 @@
293 bug = self.factory.makeBug(293 bug = self.factory.makeBug(
294 owner=owner, product=product,294 owner=owner, product=product,
295 information_type=InformationType.USERDATA)295 information_type=InformationType.USERDATA)
296 branch = self.factory.makeBranch(
297 owner=owner, product=product,
298 information_type=InformationType.USERDATA)
296299
297 # The artifact grantees will not lose access when the job is run.300 # The artifact grantees will not lose access when the job is run.
298 artifact_indirect_grantee = self.factory.makePerson()301 artifact_indirect_grantee = self.factory.makePerson()
@@ -304,6 +307,9 @@
304 bug.subscribe(policy_indirect_grantee, owner)307 bug.subscribe(policy_indirect_grantee, owner)
305 bug.subscribe(artifact_team_grantee, owner)308 bug.subscribe(artifact_team_grantee, owner)
306 bug.subscribe(artifact_indirect_grantee, owner)309 bug.subscribe(artifact_indirect_grantee, owner)
310 branch.subscribe(artifact_indirect_grantee,
311 BranchSubscriptionNotificationLevel.NOEMAIL, None,
312 CodeReviewNotificationLevel.NOEMAIL, owner)
307 # Subscribing policy_team_grantee has created an artifact grant so we313 # Subscribing policy_team_grantee has created an artifact grant so we
308 # need to revoke that to test the job.314 # need to revoke that to test the job.
309 getUtility(IAccessArtifactGrantSource).revokeByArtifact(315 getUtility(IAccessArtifactGrantSource).revokeByArtifact(
@@ -332,6 +338,7 @@
332 self.assertNotIn(policy_indirect_grantee, subscribers)338 self.assertNotIn(policy_indirect_grantee, subscribers)
333 self.assertIn(artifact_team_grantee, subscribers)339 self.assertIn(artifact_team_grantee, subscribers)
334 self.assertIn(artifact_indirect_grantee, subscribers)340 self.assertIn(artifact_indirect_grantee, subscribers)
341 self.assertIn(artifact_indirect_grantee, branch.subscribers)
335342
336 def _assert_branch_change_unsubscribes(self, change_callback):343 def _assert_branch_change_unsubscribes(self, change_callback):
337 product = self.factory.makeProduct()344 product = self.factory.makeProduct()
@@ -346,6 +353,9 @@
346353
347 self.factory.makeAccessPolicyGrant(policy, policy_team_grantee, owner)354 self.factory.makeAccessPolicyGrant(policy, policy_team_grantee, owner)
348 login_person(owner)355 login_person(owner)
356 bug = self.factory.makeBug(
357 owner=owner, product=product,
358 information_type=InformationType.USERDATA)
349 branch = self.factory.makeBranch(359 branch = self.factory.makeBranch(
350 owner=owner, product=product,360 owner=owner, product=product,
351 information_type=InformationType.USERDATA)361 information_type=InformationType.USERDATA)
@@ -371,6 +381,7 @@
371 artifact_indirect_grantee,381 artifact_indirect_grantee,
372 BranchSubscriptionNotificationLevel.NOEMAIL, None,382 BranchSubscriptionNotificationLevel.NOEMAIL, None,
373 CodeReviewNotificationLevel.NOEMAIL, owner)383 CodeReviewNotificationLevel.NOEMAIL, owner)
384 bug.subscribe(artifact_indirect_grantee, owner)
374 # Subscribing policy_team_grantee has created an artifact grant so we385 # Subscribing policy_team_grantee has created an artifact grant so we
375 # need to revoke that to test the job.386 # need to revoke that to test the job.
376 getUtility(IAccessArtifactGrantSource).revokeByArtifact(387 getUtility(IAccessArtifactGrantSource).revokeByArtifact(
@@ -398,6 +409,7 @@
398 self.assertNotIn(policy_indirect_grantee, branch.subscribers)409 self.assertNotIn(policy_indirect_grantee, branch.subscribers)
399 self.assertIn(artifact_team_grantee, branch.subscribers)410 self.assertIn(artifact_team_grantee, branch.subscribers)
400 self.assertIn(artifact_indirect_grantee, branch.subscribers)411 self.assertIn(artifact_indirect_grantee, branch.subscribers)
412 self.assertIn(artifact_indirect_grantee, bug.getDirectSubscribers())
401413
402 def test_change_information_type_branch(self):414 def test_change_information_type_branch(self):
403 def change_information_type(branch):415 def change_information_type(branch):