← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~adeuring/launchpad/lp-view-for-timelneproductseries into lp:launchpad

 

Abel Deuring has proposed merging lp:~adeuring/launchpad/lp-view-for-timelneproductseries into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~adeuring/launchpad/lp-view-for-timelneproductseries/+merge/136374

This branch changes the security configuration for ITimelineProductSeries.

ITimelineProductSeries instances contain some data from products, product serieses and milestones; access to instacnes related to proprietary products should be restricted like the access IProduct or IProductSeries instances themselves.

This is just a "boilerplate change": lib/lp/registry/configure.zcml now requires the permission lp.View for ITimelineProductSeries; lib/lp/security.py has a new security adapter.

test: ./bin/test registry -vvt test_access_to_timeline

no lint
-- 
https://code.launchpad.net/~adeuring/launchpad/lp-view-for-timelneproductseries/+merge/136374
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~adeuring/launchpad/lp-view-for-timelneproductseries into lp:launchpad.
=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml	2012-11-26 19:48:32 +0000
+++ lib/lp/registry/configure.zcml	2012-11-27 11:35:37 +0000
@@ -1624,7 +1624,8 @@
 
     <class
         class="lp.registry.model.productseries.TimelineProductSeries">
-        <allow
+        <require
+            permission="launchpad.View"
             interface="lp.registry.interfaces.productseries.ITimelineProductSeries"/>
     </class>
 

=== modified file 'lib/lp/registry/tests/test_productseries.py'
--- lib/lp/registry/tests/test_productseries.py	2012-11-26 08:33:03 +0000
+++ lib/lp/registry/tests/test_productseries.py	2012-11-27 11:35:37 +0000
@@ -864,3 +864,65 @@
             for permission, names in self.expected_set_permissions.items():
                 self.assertChangeAuthorized(names, self.public_series)
                 self.assertChangeAuthorized(names, self.proprietary_series)
+
+
+class TestTimelineProductSeries(TestCaseWithFactory):
+    """Tests for TimelineProductSeries."""
+
+    layer = DatabaseFunctionalLayer
+
+    def test_access_to_timeline_of_public_product(self):
+        # ITestTimelineProductSeries instances related to public
+        # products are publicly visible.
+        series = self.factory.makeProductSeries()
+        timeline = series.getTimeline()
+        with person_logged_in(ANONYMOUS):
+            for name in (
+                'name', 'status', 'is_development_focus', 'uri', 'landmarks',
+                'product'):
+                # No exception is raised when attributes of timeline
+                # are accessed.
+                getattr(timeline, name)
+        with person_logged_in(self.factory.makePerson()):
+            for name in (
+                'name', 'status', 'is_development_focus', 'uri', 'landmarks',
+                'product'):
+                # No exception is raised when attributes of timeline
+                # are accessed.
+                getattr(timeline, name)
+
+    def test_access_to_timeline_of_proprietary_product(self):
+        # ITestTimelineProductSeries instances related to proprietary
+        # products are visible only for person with a policy grant for
+        # the product.
+        owner = self.factory.makePerson()
+        user_with_policy_grant = self.factory.makePerson()
+        product = self.factory.makeProduct(
+            owner=owner, information_type=InformationType.PROPRIETARY)
+        series = self.factory.makeProductSeries(product=product)
+        with person_logged_in(owner):
+            timeline = series.getTimeline()
+            getUtility(IService, 'sharing').sharePillarInformation(
+                product, user_with_policy_grant, owner,
+                {InformationType.PROPRIETARY: SharingPermission.ALL})
+
+        # Anonymous users do not have access.
+        with person_logged_in(ANONYMOUS):
+            for name in (
+                'name', 'status', 'is_development_focus', 'uri', 'landmarks',
+                'product'):
+                self.assertRaises(Unauthorized, getattr, timeline, name)
+        # Ordinary users do not have access.
+        with person_logged_in(self.factory.makePerson()):
+            for name in (
+                'name', 'status', 'is_development_focus', 'uri', 'landmarks',
+                'product'):
+                self.assertRaises(Unauthorized, getattr, timeline, name)
+        # Users with a policy grant have access.
+        with person_logged_in(user_with_policy_grant):
+            for name in (
+                'name', 'status', 'is_development_focus', 'uri', 'landmarks',
+                'product'):
+                # No exception is raised when attributes of timeline
+                # are accessed.
+                getattr(timeline, name)

=== modified file 'lib/lp/security.py'
--- lib/lp/security.py	2012-11-26 08:33:03 +0000
+++ lib/lp/security.py	2012-11-27 11:35:37 +0000
@@ -490,10 +490,17 @@
             user)
 
 
-class ViewTimelineProductSeries(AnonymousAuthorization):
-    """Anyone can view an ITimelineProductSeries."""
+class ViewTimelineProductSeries(DelegatedAuthorization):
+    """Anyone who can view the related product can also view an
+    ITimelineProductSeries.
+    """
+    permission = 'launchpad.View'
     usedfor = ITimelineProductSeries
 
+    def __init__(self, obj):
+        super(ViewTimelineProductSeries, self).__init__(
+            obj, obj.product, 'launchpad.View')
+
 
 class ViewProductReleaseFile(AnonymousAuthorization):
     """Anyone can view an IProductReleaseFile."""


Follow ups