Merge lp:~stevenk/launchpad/better-name-field into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: 14816
Proposed branch: lp:~stevenk/launchpad/better-name-field
Merge into: lp:launchpad
Diff against target: 314 lines (+52/-76)
10 files modified
lib/lp/registry/browser/team.py (+9/-3)
lib/lp/registry/browser/tests/private-team-creation-views.txt (+2/-1)
lib/lp/registry/browser/tests/test_team.py (+16/-0)
lib/lp/registry/interfaces/person.py (+0/-3)
lib/lp/registry/model/person.py (+6/-7)
lib/lp/registry/templates/people-newteam.pt (+0/-1)
lib/lp/registry/templates/person-macros.pt (+0/-36)
lib/lp/registry/templates/team-edit.pt (+0/-5)
lib/lp/registry/tests/test_person.py (+14/-17)
lib/lp/services/fields/__init__.py (+5/-3)
To merge this branch: bzr merge lp:~stevenk/launchpad/better-name-field
Reviewer Review Type Date Requested Status
Ian Booth (community) Approve
Curtis Hovey (community) code Approve
Review via email: mp+93317@code.launchpad.net

Commit message

[r=sinzui,wallyworld][bug=494801,932192] Fix blacklist message, make visibility the 3rd field for IPersonSet:+newteam/ITeam:+edit, remove the JS that edits the name when private is selected, render the context when editing a team, and fix IPerson.checkAllowVisibility().

Description of the change

Firstly, slightly change the blacklisted message, and remove some duplication.

Also re-order the visibility field after we re-add it to the form if the user is permitted to set it.

Remove the JS that was adding private- to the name field when the visibility was changed.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

"Please contact Launchpad Support." might be lacking and we strive to avoid "please". Maybe
    Contact Launchpad Support if you want to use this name.

Your hack is ugly, but two lines. You can consider using the zope way o selecting field name to change the order:
        field_names = [
            field.__name__ for field in self.form_fields
            if field.__name__ =! 'visibility']
        field_names.insert(2, 'visibility')
        self.form_fields = self.form_fields.select(field_names)

review: Approve (code)
Revision history for this message
Ian Booth (wallyworld) wrote :

I reviewed the changes introduced by r14801 and they look ok

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/browser/team.py'
2--- lib/lp/registry/browser/team.py 2012-02-13 23:02:42 +0000
3+++ lib/lp/registry/browser/team.py 2012-02-16 03:21:23 +0000
4@@ -272,12 +272,18 @@
5 'Private teams must have a Restricted subscription '
6 'policy.')
7
8- def setUpVisibilityField(self):
9+ def setUpVisibilityField(self, render_context=False):
10 """Set the visibility field to read-write, or remove it."""
11 self.form_fields = self.form_fields.omit('visibility')
12 if self.user and self.user.checkAllowVisibility():
13 visibility = copy_field(ITeam['visibility'], readonly=False)
14- self.form_fields += Fields(visibility)
15+ self.form_fields += Fields(
16+ visibility, render_context=render_context)
17+ # Shift visibility to be the third field.
18+ field_names = [field.__name__ for field in self.form_fields]
19+ field = field_names.pop()
20+ field_names.insert(2, field)
21+ self.form_fields = self.form_fields.select(*field_names)
22
23
24 class TeamEditView(TeamFormMixin, PersonRenameFormMixin,
25@@ -310,7 +316,7 @@
26 self.field_names.remove('contactemail')
27 self.field_names.remove('teamowner')
28 super(TeamEditView, self).setUpFields()
29- self.setUpVisibilityField()
30+ self.setUpVisibilityField(render_context=True)
31
32 def setUpWidgets(self):
33 super(TeamEditView, self).setUpWidgets()
34
35=== modified file 'lib/lp/registry/browser/tests/private-team-creation-views.txt'
36--- lib/lp/registry/browser/tests/private-team-creation-views.txt 2010-10-19 18:44:31 +0000
37+++ lib/lp/registry/browser/tests/private-team-creation-views.txt 2012-02-16 03:21:23 +0000
38@@ -172,6 +172,7 @@
39 >>> for error in view.errors:
40 ... print view.getFieldError(error.field_name)
41 The name 'secret-team' has been blocked by the Launchpad administrators.
42+ Contact Launchpad Support if you want to use this name.
43
44
45 = Private Team Editing =
46@@ -422,4 +423,4 @@
47 >>> for error in view.errors:
48 ... print view.getFieldError(error.field_name)
49 The name 'private-top-secret' has been blocked by the Launchpad
50- administrators.
51+ administrators. Contact Launchpad Support if you want to use this name.
52
53=== modified file 'lib/lp/registry/browser/tests/test_team.py'
54--- lib/lp/registry/browser/tests/test_team.py 2012-02-13 05:50:16 +0000
55+++ lib/lp/registry/browser/tests/test_team.py 2012-02-16 03:21:23 +0000
56@@ -556,6 +556,22 @@
57 'visibility',
58 [field.__name__ for field in view.form_fields])
59
60+ def test_visibility_is_correct_during_edit(self):
61+ owner = self.factory.makePerson()
62+ team = self.factory.makeTeam(
63+ subscription_policy=TeamSubscriptionPolicy.RESTRICTED,
64+ visibility=PersonVisibility.PRIVATE, owner=owner)
65+ product = self.factory.makeProduct(owner=owner)
66+ self.factory.makeCommercialSubscription(product)
67+ with person_logged_in(owner):
68+ url = canonical_url(team)
69+ with FeatureFixture(self.feature_flag):
70+ browser = self.getUserBrowser(url, user=owner)
71+ browser.getLink('Change details').click()
72+ self.assertEqual(
73+ ['PRIVATE'],
74+ browser.getControl(name="field.visibility").value)
75+
76
77 class TestTeamMenu(TestCaseWithFactory):
78
79
80=== modified file 'lib/lp/registry/interfaces/person.py'
81--- lib/lp/registry/interfaces/person.py 2012-02-15 02:24:38 +0000
82+++ lib/lp/registry/interfaces/person.py 2012-02-16 03:21:23 +0000
83@@ -524,9 +524,6 @@
84 """
85 errormessage = _("%s is already in use by another person or team.")
86
87- blacklistmessage = _("The name '%s' has been blocked by the Launchpad "
88- "administrators.")
89-
90 @property
91 def _content_iface(self):
92 """Return the interface this field belongs to."""
93
94=== modified file 'lib/lp/registry/model/person.py'
95--- lib/lp/registry/model/person.py 2012-02-15 00:57:40 +0000
96+++ lib/lp/registry/model/person.py 2012-02-16 03:21:23 +0000
97@@ -191,6 +191,7 @@
98 from lp.registry.interfaces.pillar import IPillarNameSet
99 from lp.registry.interfaces.product import IProduct
100 from lp.registry.interfaces.projectgroup import IProjectGroup
101+from lp.registry.interfaces.role import IPersonRoles
102 from lp.registry.interfaces.ssh import (
103 ISSHKey,
104 ISSHKeySet,
105@@ -290,7 +291,6 @@
106 from lp.services.verification.interfaces.authtoken import LoginTokenType
107 from lp.services.verification.interfaces.logintoken import ILoginTokenSet
108 from lp.services.verification.model.logintoken import LoginToken
109-from lp.services.webapp.authorization import check_permission
110 from lp.services.webapp.dbpolicy import MasterDatabasePolicy
111 from lp.services.webapp.interfaces import ILaunchBag
112 from lp.services.worlddata.model.language import Language
113@@ -3064,14 +3064,13 @@
114 return self.subscriptionpolicy in CLOSED_TEAM_POLICY
115
116 def checkAllowVisibility(self):
117+ role = IPersonRoles(self)
118+ if role.in_commercial_admin or role.in_admin:
119+ return True
120 feature_flag = getFeatureFlag(
121 'disclosure.show_visibility_for_team_add.enabled')
122- if feature_flag:
123- if self.hasCurrentCommercialSubscription():
124- return True
125- else:
126- if check_permission('launchpad.Commercial', self):
127- return True
128+ if feature_flag and self.hasCurrentCommercialSubscription():
129+ return True
130 return False
131
132 def transitionVisibility(self, visibility, user):
133
134=== modified file 'lib/lp/registry/templates/people-newteam.pt'
135--- lib/lp/registry/templates/people-newteam.pt 2009-08-31 17:46:33 +0000
136+++ lib/lp/registry/templates/people-newteam.pt 2012-02-16 03:21:23 +0000
137@@ -16,7 +16,6 @@
138 language.
139 </p>
140 </div>
141- <metal:js use-macro="context/@@+person-macros/private-team-js" />
142 </div>
143 </body>
144 </html>
145
146=== modified file 'lib/lp/registry/templates/person-macros.pt'
147--- lib/lp/registry/templates/person-macros.pt 2012-02-01 15:31:32 +0000
148+++ lib/lp/registry/templates/person-macros.pt 2012-02-16 03:21:23 +0000
149@@ -242,40 +242,4 @@
150 </tr>
151 </metal:macro>
152
153-
154-<metal:macro define-macro="private-team-js">
155- <tal:comment replace="nothing">
156- This macro inserts the javascript necessary to automatically insert the
157- private team prefix into a name field. It is here since it is shared in
158- multiple templates.
159- </tal:comment>
160- <tal:script define="private_prefix view/private_prefix|nothing"
161- condition="private_prefix">
162- <script type="text/javascript"
163- tal:content="string:
164- LPJS.use('node', 'event', function(Y) {
165- // Prepend/remove 'private-' from team name based on visibility
166- // setting. User can choose to edit it back out, if they wish.
167- function visibility_on_change(e) {
168- var visibility = e.target;
169- var prefix = (visibility.get('value') == 'PRIVATE')
170- ? '$private_prefix' : '';
171- // XXX: Brad Crittenden 2009-01-30
172- // bug=http://yuilibrary.com/projects/yui3/ticket/2423101
173- // Dotted CSS selectors not parsed correctly. Therefore not
174- // using Y.one().
175- var name = document.getElementById('field.name');
176- name.value = prefix + name.value.replace(/^$private_prefix/, '');
177-
178- };
179- // Attach the function to the onchange event.
180- // XXX: Brad Crittenden 2009-01-30
181- // bug=http://yuilibrary.com/projects/yui3/ticket/2423101
182- // Dotted CSS selectors not parsed correctly.
183- Y.on('change', visibility_on_change, document.getElementById('field.visibility'));
184- });">
185- </script>
186- </tal:script>
187-</metal:macro>
188-
189 </tal:root>
190
191=== modified file 'lib/lp/registry/templates/team-edit.pt'
192--- lib/lp/registry/templates/team-edit.pt 2009-08-17 02:34:16 +0000
193+++ lib/lp/registry/templates/team-edit.pt 2012-02-16 03:21:23 +0000
194@@ -12,13 +12,8 @@
195
196 <body>
197 <div metal:fill-slot="main">
198-
199 <div metal:use-macro="context/@@launchpad_form/form" />
200-
201- <metal:js use-macro="context/@@+person-macros/private-team-js" />
202-
203 <tal:menu replace="structure view/@@+related-pages" />
204-
205 </div>
206 </body>
207 </html>
208
209=== modified file 'lib/lp/registry/tests/test_person.py'
210--- lib/lp/registry/tests/test_person.py 2012-02-15 00:57:40 +0000
211+++ lib/lp/registry/tests/test_person.py 2012-02-16 03:21:23 +0000
212@@ -5,31 +5,25 @@
213
214 from datetime import datetime
215
216+from lazr.lifecycle.snapshot import Snapshot
217 import pytz
218-
219 from storm.store import Store
220-
221 from testtools.matchers import (
222 Equals,
223 LessThan,
224 )
225-
226 from zope.component import getUtility
227 from zope.interface import providedBy
228 from zope.security.interfaces import Unauthorized
229 from zope.security.proxy import removeSecurityProxy
230
231-from lazr.lifecycle.snapshot import Snapshot
232-
233 from lp.answers.model.answercontact import AnswerContact
234 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
235 from lp.blueprints.model.specification import Specification
236 from lp.bugs.interfaces.bugtask import IllegalRelatedBugTasksParams
237 from lp.bugs.model.bug import Bug
238 from lp.bugs.model.bugtask import get_related_bugtasks_search_params
239-from lp.registry.errors import (
240- PrivatePersonLinkageError,
241- )
242+from lp.registry.errors import PrivatePersonLinkageError
243 from lp.registry.interfaces.karma import IKarmaCacheManager
244 from lp.registry.interfaces.person import (
245 ImmutableVisibilityError,
246@@ -47,16 +41,11 @@
247 get_recipients,
248 Person,
249 )
250-from lp.services.identity.interfaces.account import (
251- AccountStatus,
252- )
253-from lp.services.identity.interfaces.emailaddress import (
254- EmailAddressStatus,
255- )
256+from lp.services.features.testing import FeatureFixture
257+from lp.services.identity.interfaces.account import AccountStatus
258+from lp.services.identity.interfaces.emailaddress import EmailAddressStatus
259 from lp.services.propertycache import clear_property_cache
260-from lp.soyuz.enums import (
261- ArchivePurpose,
262- )
263+from lp.soyuz.enums import ArchivePurpose
264 from lp.testing import (
265 celebrity_logged_in,
266 login,
267@@ -71,6 +60,7 @@
268 from lp.testing.layers import DatabaseFunctionalLayer
269 from lp.testing.matchers import HasQueryCount
270 from lp.testing.pages import LaunchpadWebServiceCaller
271+from lp.testing.sampledata import ADMIN_EMAIL
272 from lp.testing.views import create_initialized_view
273
274
275@@ -560,6 +550,13 @@
276 person = self.factory.makePerson()
277 self.assertFalse(person.hasCurrentCommercialSubscription())
278
279+ def test_commercial_admin_with_ff_checkAllowVisibility(self):
280+ admin = getUtility(IPersonSet).getByEmail(ADMIN_EMAIL)
281+ feature_flag = {
282+ 'disclosure.show_visibility_for_team_add.enabled': 'on'}
283+ with FeatureFixture(feature_flag):
284+ self.assertTrue(admin.checkAllowVisibility())
285+
286 def test_can_not_set_visibility(self):
287 person = self.factory.makePerson()
288 self.assertRaises(
289
290=== modified file 'lib/lp/services/fields/__init__.py'
291--- lib/lp/services/fields/__init__.py 2012-01-18 22:32:10 +0000
292+++ lib/lp/services/fields/__init__.py 2012-02-16 03:21:23 +0000
293@@ -490,6 +490,10 @@
294 class BlacklistableContentNameField(ContentNameField):
295 """ContentNameField that also checks that a name is not blacklisted"""
296
297+ blacklistmessage = _("The name '%s' has been blocked by the Launchpad "
298+ "administrators. Contact Launchpad Support if you "
299+ "want to use this name.")
300+
301 def _validate(self, input):
302 """Check that the given name is valid, unique and not blacklisted."""
303 super(BlacklistableContentNameField, self)._validate(input)
304@@ -505,9 +509,7 @@
305 from lp.registry.interfaces.person import IPersonSet
306 user = getUtility(ILaunchBag).user
307 if getUtility(IPersonSet).isNameBlacklisted(input, user):
308- raise LaunchpadValidationError(
309- "The name '%s' has been blocked by the Launchpad "
310- "administrators." % input)
311+ raise LaunchpadValidationError(self.blacklistmessage % input)
312
313
314 class PillarAliases(TextLine):