launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #14399
[Merge] lp:~jcsackett/launchpad/404-project-milestones-privacy into lp:launchpad
j.c.sackett has proposed merging lp:~jcsackett/launchpad/404-project-milestones-privacy into lp:launchpad.
Commit message:
Fixes ProjectMilestone generation in the milestone page to not link private products for unpriveleged users.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1079405 in Launchpad itself: "ProjectGroupMilestone:+index 403s because of proprietary data on associated products"
https://bugs.launchpad.net/launchpad/+bug/1079405
For more details, see:
https://code.launchpad.net/~jcsackett/launchpad/404-project-milestones-privacy/+merge/135252
Summary
=======
Going to a projectmilestone index page causes a 403 when the milestone
incorporates data from private products.
This is because product and milestone data isn't sufficiently filtered. While
the initial query to fetch all milestones on a project's associated products
filters, a second query is made to group the milestones appropriated and
combine the data for product milestones with the same name. This second a
query is not filtered, and should be.
Preimp
======
Spoke with Curtis Hovey about the initial problem.
Implementation
==============
Add the privacy filter to the second query.
Tests
=====
bin/test -vvct test_mixed_product_projectgroup_milestone
QA
==
QA steps are listed in a comment by Curtis Hovey on the bug.
LoC
===
Part of private projects.
Lint
====
Checking for conflicts and issues in changed files.
Linting changed files:
lib/lp/registry/model/projectgroup.py
lib/lp/registry/browser/tests/test_projectgroup.py
--
https://code.launchpad.net/~jcsackett/launchpad/404-project-milestones-privacy/+merge/135252
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jcsackett/launchpad/404-project-milestones-privacy into lp:launchpad.
=== modified file 'lib/lp/registry/browser/tests/test_projectgroup.py'
--- lib/lp/registry/browser/tests/test_projectgroup.py 2012-10-19 14:22:36 +0000
+++ lib/lp/registry/browser/tests/test_projectgroup.py 2012-11-20 21:22:23 +0000
@@ -15,7 +15,10 @@
from lp.app.browser.lazrjs import vocabulary_to_choice_edit_items
from lp.app.enums import InformationType
from lp.registry.browser.tests.test_product import make_product_form
-from lp.registry.enums import EXCLUSIVE_TEAM_POLICY
+from lp.registry.enums import (
+ EXCLUSIVE_TEAM_POLICY,
+ TeamMembershipPolicy,
+ )
from lp.registry.interfaces.person import IPersonSet
from lp.registry.interfaces.product import IProductSet
from lp.services.features.testing import FeatureFixture
@@ -96,6 +99,41 @@
self.assertNotIn(product_name, browser.contents)
self.assertIn(public_product.displayname, browser.contents)
+ def test_mixed_product_projectgroup_milestone(self):
+ # If a milestone is mixed between public and proprietary products,
+ # only the public is shown to people without access.
+ self.useFixture(
+ FeatureFixture({u'disclosure.private_projects.enabled': u'on'}))
+ owner = self.factory.makePerson()
+ teammember = self.factory.makePerson()
+ owning_team = self.factory.makeTeam(owner=owner,
+ membership_policy=TeamMembershipPolicy.RESTRICTED)
+ with person_logged_in(owner):
+ owning_team.addMember(teammember, owner)
+ group = self.factory.makeProject(owner=owning_team)
+ private = self.factory.makeProduct(
+ project=group, owner=owner,
+ information_type=InformationType.PROPRIETARY, name='private')
+ public = self.factory.makeProduct(
+ project=group, owner=owner, name='public')
+ private_milestone = self.factory.makeMilestone(
+ product=private, name='1.0')
+ public_milestone = self.factory.makeMilestone(
+ product=public, name='1.0')
+ with person_logged_in(owner):
+ self.factory.makeBug(
+ target=private, owner=owner, milestone=private_milestone,
+ title='This is the private bug')
+ self.factory.makeBug(
+ target=public, owner=owner, milestone=public_milestone,
+ title='This is the public bug')
+
+ group_milestone = group.milestones[0]
+ browser = self.getViewBrowser(
+ group_milestone, user=self.factory.makePerson())
+ self.assertTrue("This is the public bug" in browser.contents)
+ self.assertFalse("This is the private bug" in browser.contents)
+
class TestProjectGroupEditView(TestCaseWithFactory):
"""Tests the edit view."""
=== modified file 'lib/lp/registry/model/projectgroup.py'
--- lib/lp/registry/model/projectgroup.py 2012-11-15 22:23:08 +0000
+++ lib/lp/registry/model/projectgroup.py 2012-11-20 21:22:23 +0000
@@ -430,10 +430,11 @@
SQL('MIN(Milestone.dateexpected)'),
SQL('BOOL_OR(Milestone.active)'),
)
+ privacy_filter = ProductSet.getProductPrivacyFilter(user)
conditions = And(Milestone.product == Product.id,
Product.project == self,
Product.active == True,
- ProductSet.getProductPrivacyFilter(user))
+ privacy_filter)
result = store.find(columns, conditions)
result.group_by(Milestone.name)
if only_active:
@@ -452,6 +453,7 @@
Product.project == self,
Milestone.product == Product.id,
Product.active == True,
+ privacy_filter,
In(Milestone.name, milestone_names))
for product, name in (
store.find((Product, Milestone.name), product_conditions)):
Follow ups