← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~jcsackett/launchpad/filter-private-products-vocabulary into lp:launchpad

 

j.c.sackett has proposed merging lp:~jcsackett/launchpad/filter-private-products-vocabulary into lp:launchpad.

Commit message:
Updates ProductSeriesVocabulary to filter out series on products the user can't see.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~jcsackett/launchpad/filter-private-products-vocabulary/+merge/134542

Summary
=======
Various parts of launchpad need to be updated to not show products that are of
a NONPUBLIC information type.

The ProductSeriesVocabulary need updating so that it doesn't return series to
the user that the user doesn't have rights to see.

Preimp
======
Rick Harding, Aaron Bentley (for information on the existing filtering
methods).

Implementation
==============
A pre-existing filtering method, `ProductSet`.`getProductPrivacyFilter` is
used with the user (fetched from `ILaunchBag`) to get the necessar privacy
filter.

The filter is added to the queries used by the vocabulary search.

Tests for the case where there is no user as well as for a user who can't see
a product are added.

As a drive by, the empty TearDown method on the testcase has been removed, as
it is unneeded.

Tests
=====
bin/test -vvct test_search_respects_privacy

QA
==
Create a product with nonpublic info_type, and make a series for it. Search
for it in a product series picker--you should see it.

As an anonymous user, search. You should not see it.

With another account, search. You should not see it.

You may wish to repeat this with products that are PUBLIC. In all cases you
should see the series.

LoC
===
Part of Private Projects.

Lint
====

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/registry/vocabularies.py
  lib/lp/registry/tests/test_productseries_vocabularies.py
-- 
https://code.launchpad.net/~jcsackett/launchpad/filter-private-products-vocabulary/+merge/134542
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jcsackett/launchpad/filter-private-products-vocabulary into lp:launchpad.
=== modified file 'lib/lp/registry/tests/test_productseries_vocabularies.py'
--- lib/lp/registry/tests/test_productseries_vocabularies.py	2012-01-01 02:58:52 +0000
+++ lib/lp/registry/tests/test_productseries_vocabularies.py	2012-11-15 18:16:25 +0000
@@ -7,8 +7,12 @@
 
 from operator import attrgetter
 
+from lp.app.enums import InformationType
 from lp.registry.vocabularies import ProductSeriesVocabulary
-from lp.testing import TestCaseWithFactory
+from lp.testing import (
+    person_logged_in,
+    TestCaseWithFactory,
+    )
 from lp.testing.layers import DatabaseFunctionalLayer
 
 
@@ -27,9 +31,6 @@
             product=self.product, name=self.series1_prefix + "series1")
         self.series2 = self.factory.makeProductSeries(product=self.product)
 
-    def tearDown(self):
-        super(TestProductSeriesVocabulary, self).tearDown()
-
     def test_search_by_product_name(self):
         # Test that searching by the product name finds all its series.
         result = self.vocabulary.search(self.product.name)
@@ -53,6 +54,31 @@
             '%s/%s' % (self.product_prefix, self.series1_prefix))
         self.assertEqual([self.series], list(result))
 
+    def _makePrivateProductAndSeries(self, owner=None):
+        product = self.factory.makeProduct(
+            self.product_prefix + "private-product",
+            information_type=InformationType.PROPRIETARY,
+            owner=owner)
+        series = self.factory.makeProductSeries(product=product,
+            name=self.series1_prefix + "private-series")
+        return product, series
+
+    def test_search_respects_privacy_no_user(self):
+        self._makePrivateProductAndSeries()
+        result = self.vocabulary.search(
+            '%s/%s' % (self.product_prefix, self.series1_prefix))
+        self.assertEqual([self.series], list(result))
+
+    def test_search_respects_privacy_user(self):
+        owner = self.factory.makePerson()
+        product, series = self._makePrivateProductAndSeries(owner=owner)
+        with person_logged_in(owner):
+            result = self.vocabulary.search(
+                '%s/%s' % (self.product_prefix, self.series1_prefix))
+        self.assertEqual(
+            [self.series, series].sort(key=attrgetter('id')),
+            list(result).sort(key=attrgetter('id')))
+
     def test_toTerm(self):
         # Test the ProductSeriesVocabulary.toTerm() method.
         term = self.vocabulary.toTerm(self.series)

=== modified file 'lib/lp/registry/vocabularies.py'
--- lib/lp/registry/vocabularies.py	2012-11-12 22:27:55 +0000
+++ lib/lp/registry/vocabularies.py	2012-11-15 18:16:25 +0000
@@ -1365,7 +1365,8 @@
         """Return terms where query is a substring of the name."""
         if not query:
             return self.emptySelectResults()
-
+        user = getUtility(ILaunchBag).user
+        privacy_filter = ProductSet.getProductPrivacyFilter(user)
         query = ensure_unicode(query).lower().strip('/')
         # If there is a slash splitting the product and productseries
         # names, they must both match. If there is no slash, we don't
@@ -1380,11 +1381,11 @@
             substring_search = Or(
                 CONTAINSSTRING(Product.name, query),
                 CONTAINSSTRING(ProductSeries.name, query))
-
         result = IStore(self._table).find(
             self._table,
             Product.id == ProductSeries.productID,
-            substring_search)
+            substring_search,
+            privacy_filter)
         result = result.order_by(self._order_by)
         return result
 


Follow ups