launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #06233
[Merge] lp:~stevenk/launchpad/show-visibility-teamadd into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/show-visibility-teamadd into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/show-visibility-teamadd/+merge/91389
We'd like to start empowering our users to be able to create private artifacts themselves, if it is justified. This branch is a small first step towards this goal.
To that end, I have created a feature flag, "disclosure.show_visibility_for_team_add.enabled", and if it is enabled, will display the visibility field if and only if the user has a current commercial subscription. I have added all test cases that I could think of, and I have cleaned a little bit of lint, mostly related to imports.
--
https://code.launchpad.net/~stevenk/launchpad/show-visibility-teamadd/+merge/91389
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/show-visibility-teamadd into lp:launchpad.
=== modified file 'lib/lp/registry/browser/team.py'
--- lib/lp/registry/browser/team.py 2012-02-01 15:46:43 +0000
+++ lib/lp/registry/browser/team.py 2012-02-03 04:45:24 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
@@ -45,8 +45,9 @@
from lazr.restful.interfaces import IJSONRequestCache
from lazr.restful.utils import smartquote
+import pytz
import simplejson
-import pytz
+from storm.expr import Join
from z3c.ptcompat import ViewPageTemplateFile
from zope.app.form.browser import TextAreaWidget
from zope.component import getUtility
@@ -140,8 +141,14 @@
ITeamMembershipSet,
TeamMembershipStatus,
)
+from lp.registry.model.commercialsubscription import CommercialSubscription
+from lp.registry.model.person import Person
+from lp.registry.model.product import Product
+from lp.registry.model.teammembership import TeamParticipation
from lp.security import ModerateByRegistryExpertsOrAdmins
from lp.services.config import config
+from lp.services.database.lpstorm import IStore
+from lp.services.features import getFeatureFlag
from lp.services.fields import PublicPersonChoice
from lp.services.identity.interfaces.emailaddress import IEmailAddressSet
from lp.services.privacy.interfaces import IObjectPrivacy
@@ -221,8 +228,11 @@
class TeamFormMixin:
"""Form to be used on forms which conditionally display team visibility.
- The visibility field should only be shown to users with
- launchpad.Commercial permission on the team.
+ The visibility field is shown if
+ * The user has launchpad.Commercial permission.
+ * Or the feature flag
+ disclosure.show_visibility_for_team_add.enabled is on, and the user has
+ a current commercial subscription.
"""
field_names = [
"name", "visibility", "displayname", "contactemail",
@@ -265,9 +275,31 @@
'Private teams must have a Restricted subscription '
'policy.')
- def conditionallyOmitVisibility(self):
+ def conditionallyOmitVisibility(self, user):
"""Remove the visibility field if not authorized."""
- if not check_permission('launchpad.Commercial', self.context):
+ if check_permission('launchpad.Commercial', self.context):
+ return None
+ if getFeatureFlag(
+ 'disclosure.show_visibility_for_team_add.enabled'):
+ store = IStore(Person)
+ person = store.using(
+ Person,
+ Join(
+ TeamParticipation,
+ Person.id == TeamParticipation.personID),
+ Join(
+ Product, TeamParticipation.teamID == Product._ownerID),
+ Join(
+ CommercialSubscription,
+ CommercialSubscription.productID == Product.id)
+ ).find(
+ Person,
+ CommercialSubscription.date_expires > datetime.now(
+ pytz.UTC),
+ Person.id == user.id)
+ if person.is_empty():
+ self.form_fields = self.form_fields.omit('visibility')
+ else:
self.form_fields = self.form_fields.omit('visibility')
@@ -301,7 +333,7 @@
self.field_names.remove('contactemail')
self.field_names.remove('teamowner')
super(TeamEditView, self).setUpFields()
- self.conditionallyOmitVisibility()
+ self.conditionallyOmitVisibility(self.user)
def setUpWidgets(self):
super(TeamEditView, self).setUpWidgets()
@@ -997,7 +1029,7 @@
Only Launchpad Admins get to see the visibility field.
"""
super(TeamAddView, self).setUpFields()
- self.conditionallyOmitVisibility()
+ self.conditionallyOmitVisibility(self.user)
@action('Create Team', name='create')
def create_action(self, action, data):
=== modified file 'lib/lp/registry/browser/tests/test_team.py'
--- lib/lp/registry/browser/tests/test_team.py 2012-01-30 19:36:57 +0000
+++ lib/lp/registry/browser/tests/test_team.py 2012-02-03 04:45:24 +0000
@@ -1,10 +1,16 @@
-# Copyright 2010 Canonical Ltd. This software is licensed under the
+# Copyright 2010-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
+from datetime import (
+ datetime,
+ timedelta,
+ )
+
import contextlib
from lazr.restful.interfaces import IJSONRequestCache
+import pytz
import simplejson
import transaction
from zope.component import getUtility
@@ -13,10 +19,12 @@
from lp.registry.browser.team import (
TeamIndexMenu,
TeamOverviewMenu,
+ TeamMailingListArchiveView,
)
from lp.registry.interfaces.mailinglist import MailingListStatus
from lp.registry.interfaces.person import (
CLOSED_TEAM_POLICY,
+ IPersonSet,
OPEN_TEAM_POLICY,
PersonVisibility,
TeamMembershipRenewalPolicy,
@@ -27,7 +35,8 @@
ITeamMembershipSet,
TeamMembershipStatus,
)
-from lp.registry.browser.team import TeamMailingListArchiveView
+from lp.registry.model.commercialsubscription import CommercialSubscription
+from lp.services.features.testing import FeatureFixture
from lp.services.propertycache import get_property_cache
from lp.services.webapp.authorization import check_permission
from lp.services.webapp.publisher import canonical_url
@@ -470,6 +479,83 @@
self.assertEqual(['name'], view.field_names)
+class TestTeamAddView(TestCaseWithFactory):
+
+ layer = LaunchpadFunctionalLayer
+ view_name = '+newteam'
+ feature_flag = {'disclosure.show_visibility_for_team_add.enabled': 'on'}
+
+ def test_random_does_not_see_visibility_field(self):
+ personset = getUtility(IPersonSet)
+ person = self.factory.makePerson()
+ view = create_initialized_view(
+ personset, name=self.view_name, principal=person)
+ self.assertNotIn(
+ 'visibility', [field.__name__ for field in view.form_fields])
+
+ def test_admin_sees_visibility_field(self):
+ personset = getUtility(IPersonSet)
+ admin = login_celebrity('admin')
+ view = create_initialized_view(
+ personset, name=self.view_name, principal=admin)
+ self.assertIn(
+ 'visibility', [field.__name__ for field in view.form_fields])
+
+ def test_random_does_not_see_visibility_field_with_flag(self):
+ personset = getUtility(IPersonSet)
+ person = self.factory.makePerson()
+ with person_logged_in(person):
+ with FeatureFixture(self.feature_flag):
+ view = create_initialized_view(
+ personset, name=self.view_name, principal=person)
+ self.assertNotIn(
+ 'visibility',
+ [field.__name__ for field in view.form_fields])
+
+ def create_subscription(self, product, expired=False):
+ if expired:
+ expiry = datetime.now(pytz.UTC) - timedelta(days=1)
+ else:
+ expiry = datetime.now(pytz.UTC) + timedelta(days=30)
+ CommercialSubscription(
+ product=product,
+ date_starts=datetime.now(pytz.UTC) - timedelta(days=90),
+ date_expires=expiry,
+ registrant=product.owner,
+ purchaser=product.owner,
+ sales_system_id='new',
+ whiteboard='')
+
+ def test_person_with_cs_sees_visibility_field_with_flag(self):
+ personset = getUtility(IPersonSet)
+ team = self.factory.makeTeam(
+ subscription_policy=TeamSubscriptionPolicy.MODERATED)
+ product = self.factory.makeProduct(owner=team)
+ self.create_subscription(product)
+ with person_logged_in(team.teamowner):
+ with FeatureFixture(self.feature_flag):
+ view = create_initialized_view(
+ personset, name=self.view_name, principal=team.teamowner)
+ self.assertIn(
+ 'visibility',
+ [field.__name__ for field in view.form_fields])
+
+
+ def test_person_with_expired_cs_does_not_see_visibility(self):
+ personset = getUtility(IPersonSet)
+ team = self.factory.makeTeam(
+ subscription_policy=TeamSubscriptionPolicy.MODERATED)
+ product = self.factory.makeProduct(owner=team)
+ self.create_subscription(product, expired=True)
+ with person_logged_in(team.teamowner):
+ with FeatureFixture(self.feature_flag):
+ view = create_initialized_view(
+ personset, name=self.view_name, principal=team.teamowner)
+ self.assertNotIn(
+ 'visibility',
+ [field.__name__ for field in view.form_fields])
+
+
class TestTeamMenu(TestCaseWithFactory):
layer = DatabaseFunctionalLayer
=== modified file 'lib/lp/services/features/flags.py'
--- lib/lp/services/features/flags.py 2012-01-13 11:12:41 +0000
+++ lib/lp/services/features/flags.py 2012-02-03 04:45:24 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2011 Canonical Ltd. This software is licensed under the
+# Copyright 2010-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__all__ = [
@@ -270,6 +270,13 @@
'',
'',
''),
+ ('disclosure.show_visibility_for_team_add.enabled',
+ 'boolean',
+ ('If true, will show the visibility field for IPersonSet:+newteam if '
+ ' the user has a current commercial subscription.'),
+ '',
+ '',
+ ''),
])
# The set of all flag names that are documented.