launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #16905
[Merge] lp:~wgrant/launchpad/bug-1083709 into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/bug-1083709 into lp:launchpad.
Commit message:
Fix Milestone's launchpad.Edit adapter to respect driver inheritance, rather than just checking participation in the series driver or product owner. Now product drivers can release milestones.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1083709 in Launchpad itself: "Project driver can not edit dateexpected on milestone"
https://bugs.launchpad.net/launchpad/+bug/1083709
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/bug-1083709/+merge/222895
This branch fixes the IMilestone launchpad.Edit adapter to allow product drivers, not just series drivers.
Additionally, I removed isDriver and renamed isOneOfDrivers into its place, as there's never a reason to just check the single driver field. Only specs used that method deliberately, and they only have a single driver, so isOneOfDrivers is fine for everything.
--
https://code.launchpad.net/~wgrant/launchpad/bug-1083709/+merge/222895
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/bug-1083709 into lp:launchpad.
=== modified file 'lib/lp/bugs/model/bugtask.py'
--- lib/lp/bugs/model/bugtask.py 2014-01-30 15:04:06 +0000
+++ lib/lp/bugs/model/bugtask.py 2014-06-12 01:38:34 +0000
@@ -1294,8 +1294,7 @@
owner_context = context
if IBugTarget.providedBy(context):
owner_context = context.pillar
- return (
- role.isOwner(owner_context) or role.isOneOfDrivers(context))
+ return role.isOwner(owner_context) or role.isDriver(context)
@classmethod
def userHasBugSupervisorPrivilegesContext(cls, context, user):
=== modified file 'lib/lp/registry/doc/personroles.txt'
--- lib/lp/registry/doc/personroles.txt 2011-05-27 20:10:36 +0000
+++ lib/lp/registry/doc/personroles.txt 2014-06-12 01:38:34 +0000
@@ -90,29 +90,22 @@
== isOwner, isDriver ==
-We can easily check for ownership and drivership. This is admittedly not much
-shorter than calling inTeam but clearer to read.
+We can easily check for ownership and drivership. If an object
+provides IHasDrivers, its ancestors' drivers will be checked too.
>>> product = factory.makeProduct(owner=person)
>>> print roles.isOwner(product)
True
- >>> print roles.isDriver(product)
+ >>> driver = factory.makePerson()
+ >>> driver_roles = IPersonRoles(driver)
+ >>> print driver_roles.isDriver(product)
False
- >>> product.driver = person
- >>> print roles.isDriver(product)
+ >>> product.driver = driver
+ >>> print driver_roles.isDriver(product)
True
-
-
-== isOneOfDrivers ==
-
-If an object implements IHasDrivers it lists all drivers of the object and
-possible parent objects. The method isOneOfDrivers lets us check for those.
-
>>> productseries = factory.makeProductSeries(product=product)
- >>> print roles.isDriver(productseries)
- False
- >>> print roles.isOneOfDrivers(productseries)
+ >>> print driver_roles.isDriver(productseries)
True
=== modified file 'lib/lp/registry/interfaces/role.py'
--- lib/lp/registry/interfaces/role.py 2013-05-10 06:28:17 +0000
+++ lib/lp/registry/interfaces/role.py 2014-06-12 01:38:34 +0000
@@ -127,18 +127,15 @@
"""Is this person the owner of the object?"""
def isDriver(obj):
- """Is this person the driver of the object?"""
+ """Is this person one of the drivers of the object?
+
+ Works on objects that implement 'IHasDrivers', but will check the
+ driver attribute otherwise.
+ """
def isBugSupervisor(obj):
"""Is this person the bug supervisor of the object?"""
- def isOneOfDrivers(obj):
- """Is this person on of the drivers of the object?
-
- Works on objects that implement 'IHasDrivers' but will default to
- isDriver if it doesn't, i.e. check the driver attribute.
- """
-
def isOneOf(obj, attributes):
"""Is this person one of the roles in relation to the object?
=== modified file 'lib/lp/registry/model/hasdrivers.py'
--- lib/lp/registry/model/hasdrivers.py 2011-05-27 20:10:36 +0000
+++ lib/lp/registry/model/hasdrivers.py 2014-06-12 01:38:34 +0000
@@ -17,6 +17,6 @@
def personHasDriverRights(self, person):
"""See `IHasDrivers`."""
person_roles = IPersonRoles(person)
- return (person_roles.isOneOfDrivers(self) or
+ return (person_roles.isDriver(self) or
person_roles.isOwner(self) or
person_roles.in_admin)
=== modified file 'lib/lp/registry/model/personroles.py'
--- lib/lp/registry/model/personroles.py 2012-08-21 00:34:02 +0000
+++ lib/lp/registry/model/personroles.py 2014-06-12 01:38:34 +0000
@@ -59,12 +59,8 @@
def isDriver(self, obj):
"""See IPersonRoles."""
- return self.inTeam(obj.driver)
-
- def isOneOfDrivers(self, obj):
- """See IPersonRoles."""
if not IHasDrivers.providedBy(obj):
- return self.isDriver(obj)
+ return self.inTeam(obj.driver)
for driver in obj.drivers:
if self.inTeam(driver):
return True
=== modified file 'lib/lp/registry/tests/test_milestone.py'
--- lib/lp/registry/tests/test_milestone.py 2013-04-03 05:04:11 +0000
+++ lib/lp/registry/tests/test_milestone.py 2014-06-12 01:38:34 +0000
@@ -409,6 +409,15 @@
for permission, names in self.expected_set_permissions.items():
self.assertChangeAuthorized(names, self.proprietary_milestone)
+ def test_access_for_product_driver(self):
+ # The driver of a private product can changeattributes.
+ driver = self.factory.makePerson()
+ with person_logged_in(self.proprietary_product_owner):
+ self.proprietary_product.driver = driver
+ with person_logged_in(driver):
+ for permission, names in self.expected_set_permissions.items():
+ self.assertChangeAuthorized(names, self.proprietary_milestone)
+
class HasMilestonesSnapshotTestCase(TestCaseWithFactory):
"""A TestCase for snapshots of pillars with milestones."""
=== modified file 'lib/lp/registry/tests/test_personroles.py'
--- lib/lp/registry/tests/test_personroles.py 2012-08-21 00:34:02 +0000
+++ lib/lp/registry/tests/test_personroles.py 2014-06-12 01:38:34 +0000
@@ -100,20 +100,14 @@
roles = IPersonRoles(self.person)
self.assertTrue(roles.isDriver(sprint))
- def test_isOneOfDrivers(self):
+ def test_isDriver_parent(self):
# The person can be one of multiple drivers of if an object
# implements IHasDrivers.
productseries = self.factory.makeProductSeries()
productseries.product.driver = self.person
productseries.driver = self.factory.makePerson()
roles = IPersonRoles(self.person)
- self.assertTrue(roles.isOneOfDrivers(productseries))
-
- def test_isOneOfDrivers_no_drivers(self):
- # If the object does not implement IHasDrivers, False is returned.
- sprint = self.factory.makeSprint()
- roles = IPersonRoles(self.person)
- self.assertFalse(roles.isOneOfDrivers(sprint))
+ self.assertTrue(roles.isDriver(productseries))
def test_isBugSupervisor(self):
# The person can be the bug supervisor of something, e.g. a product.
=== modified file 'lib/lp/security.py'
--- lib/lp/security.py 2014-03-17 21:50:33 +0000
+++ lib/lp/security.py 2014-06-12 01:38:34 +0000
@@ -379,7 +379,7 @@
"""Maintainers, drivers, and admins can drive projects."""
return (user.in_admin or
user.isOwner(self.obj.pillar) or
- user.isOneOfDrivers(self.obj.pillar))
+ user.isDriver(self.obj.pillar))
class EditAccountBySelfOrAdmin(AuthorizationBase):
@@ -588,11 +588,11 @@
assert self.obj.target
goal = self.obj.goal
if goal is not None:
- if user.isOwner(goal) or user.isOneOfDrivers(goal):
+ if user.isOwner(goal) or user.isDriver(goal):
return True
return (user.in_admin or
user.isOwner(self.obj.target) or
- user.isOneOfDrivers(self.obj.target) or
+ user.isDriver(self.obj.target) or
user.isOneOf(
self.obj, ['owner', 'drafter', 'assignee', 'approver']))
@@ -604,7 +604,7 @@
def checkAuthenticated(self, user):
assert self.obj.target
return (user.isOwner(self.obj.target) or
- user.isOneOfDrivers(self.obj.target) or
+ user.isDriver(self.obj.target) or
user.in_admin)
@@ -669,10 +669,10 @@
def checkAuthenticated(self, user):
if self.obj.specification.goal is not None:
- if user.isOneOfDrivers(self.obj.specification.goal):
+ if user.isDriver(self.obj.specification.goal):
return True
else:
- if user.isOneOfDrivers(self.obj.specification.target):
+ if user.isDriver(self.obj.specification.target):
return True
return (user.inTeam(self.obj.person) or
user.isOneOf(
@@ -716,7 +716,7 @@
able to change translation settings for a product.
"""
return (user.isOwner(self.obj) or
- user.isOneOfDrivers(self.obj) or
+ user.isDriver(self.obj) or
user.in_rosetta_experts or
user.in_admin)
@@ -1373,7 +1373,7 @@
# Project drivers can view any project announcements.
# Launchpad admins can view any announcement.
assert self.obj.target
- return (user.isOneOfDrivers(self.obj.target) or
+ return (user.isDriver(self.obj.target) or
user.isOwner(self.obj.target) or
user.in_admin)
@@ -1386,7 +1386,7 @@
"""Allow the project owner and drivers to edit any project news."""
assert self.obj.target
- return (user.isOneOfDrivers(self.obj.target) or
+ return (user.isDriver(self.obj.target) or
user.isOwner(self.obj.target) or
user.in_admin)
@@ -2178,7 +2178,7 @@
Distribution translation managers and distribution series drivers
can manage IDistroSeries translations.
"""
- return (user.isOneOfDrivers(self.obj) or
+ return (user.isDriver(self.obj) or
self.forwardCheckAuthenticated(user, self.obj.distribution))
@@ -2200,7 +2200,7 @@
"""Is the user able to manage `IProductSeries` translations."""
return (user.isOwner(self.obj) or
- user.isOneOfDrivers(self.obj) or
+ user.isDriver(self.obj) or
self.forwardCheckAuthenticated(user, self.obj.product))
Follow ups