Merge lp:~adiroiban/launchpad/bug-340662 into lp:launchpad

Proposed by Adi Roiban
Status: Merged
Merged at revision: not available
Proposed branch: lp:~adiroiban/launchpad/bug-340662
Merge into: lp:launchpad
Diff against target: 222 lines (+63/-24)
6 files modified
lib/canonical/launchpad/security.py (+26/-1)
lib/lp/translations/browser/potemplate.py (+3/-2)
lib/lp/translations/configure.zcml (+8/-2)
lib/lp/translations/stories/productseries/xx-productseries-templates.txt (+21/-8)
lib/lp/translations/stories/standalone/xx-potemplate-edit.txt (+4/-10)
lib/lp/translations/templates/object-templates.pt (+1/-1)
To merge this branch: bzr merge lp:~adiroiban/launchpad/bug-340662
Reviewer Review Type Date Requested Status
Данило Шеган (community) Disapprove
Eleanor Berger (community) Approve
Review via email: mp+16629@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Adi Roiban (adiroiban) wrote :

= Bug 340662=
At the moment, "change details" link on POTemplates has very limited options.

We should move at least translation domain, path and "accept translations" from "Admin" to "Change details" form.

== Proposed fix ==

Add template name, translation domain, path and iscurrent (accept translations) to the +edit page for potemplate and potemplates subset.

== Pre-implementation notes ==
There are no pre-implementation notes.

== Implementation details ==

launchpad.Edit for POTemplate and POTemplateSubset is a subset of launchpad.TranslationsAdmin To allow access to disabled templates for product owner or translations admins the URL traversal permission check was changed to launchpad.Edit.
Other users have no access to disabled templates

== Tests ==
lp-test -t productseries-templates

== Demo and Q/A ==
As a product owner (ex. <email address hidden>) for a project (ex. evolution) go to a template page for that project
https://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2/

You should see the „Change details” that links to the +edit page

From this page you should be able to change template name, domain name, path, details, priority, owner and „accept translation”.

Change some values and then save them.

From the series +template page you will see „Edit” links for each template, including disabled templates:
https://translations.launchpad.dev/evolution/trunk/+templates

Disabling a template it should still be in the list (with a red background) and you can still edit it.

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/canonical/launchpad/security.py
  lib/lp/translations/configure.zcml
  lib/lp/translations/browser/potemplate.py
  lib/lp/translations/stories/productseries/xx-productseries-templates.txt
  lib/lp/translations/stories/standalone/xx-potemplate-edit.txt
  lib/lp/translations/templates/object-templates.pt

Revision history for this message
Eleanor Berger (intellectronica) :
review: Approve
Revision history for this message
Данило Шеган (danilo) wrote :

There are a bunch of problems with this branch. One is that there was no pre-implementation call/chat; eg. we should definitely not have allowed template name to be modified by everyone. That can cause serious system inconsistencies especially with message sharing.

Next, there are other serious problems with EditPOTemplateSubset permission. For instance, it calls EditByOwnersOrAdmins(IPOTemplateSubset).checkAuthenticated, where IPOTemplateSubset doesn't implement IHasOwner, as seen in bug #507498.

Adi, can I ask you please to prepare a branch to back out the template name from the list of launchpad.Edit editable attributes?

review: Disapprove

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/security.py'
--- lib/canonical/launchpad/security.py 2009-12-24 13:33:41 +0000
+++ lib/canonical/launchpad/security.py 2009-12-29 18:24:17 +0000
@@ -1164,6 +1164,8 @@
1164 self, user)1164 self, user)
11651165
11661166
1167# Please keep EditPOTemplateSubset in sync with this, unless you
1168# know exactly what you are doing.
1167class EditPOTemplateDetails(AdminPOTemplateDetails, EditByOwnersOrAdmins):1169class EditPOTemplateDetails(AdminPOTemplateDetails, EditByOwnersOrAdmins):
1168 permission = 'launchpad.Edit'1170 permission = 'launchpad.Edit'
1169 usedfor = IPOTemplate1171 usedfor = IPOTemplate
@@ -1645,7 +1647,7 @@
1645 user.inTeam(celebs.bazaar_experts))1647 user.inTeam(celebs.bazaar_experts))
16461648
16471649
1648# Please keep this in sync with AdminPOTemplateDetails. Note that1650# Please keep this in sync with AdminPOTemplateDetails. Note that
1649# this permission controls access to browsing into individual1651# this permission controls access to browsing into individual
1650# potemplates, but it's on a different object (POTemplateSubset)1652# potemplates, but it's on a different object (POTemplateSubset)
1651# from AdminPOTemplateDetails, even though it looks almost identical1653# from AdminPOTemplateDetails, even though it looks almost identical
@@ -1672,6 +1674,29 @@
1672 return OnlyRosettaExpertsAndAdmins.checkAuthenticated(self, user)1674 return OnlyRosettaExpertsAndAdmins.checkAuthenticated(self, user)
16731675
16741676
1677# Please keep EditPOTemplate in sync with this, unless you
1678# know exactly what you are doing. Note that this permission controls
1679# access to browsing into individual potemplates, but it's on a different
1680# object (POTemplateSubset) from EditPOTemplateDetails,
1681# even though it looks almost identical
1682class EditPOTemplateSubset(AuthorizationBase):
1683 permission = 'launchpad.Edit'
1684 usedfor = IPOTemplateSubset
1685
1686 def checkAuthenticated(self, user):
1687 """Allow anyone with admin rights; owners, product owners and
1688 distribution owners; and for distros, translation group owners.
1689 """
1690 if (self.obj.productseries is not None and
1691 user.inTeam(self.obj.productseries.product.owner)):
1692 # The user is the owner of the product.
1693 return True
1694
1695 return (
1696 AdminPOTemplateSubset(self.obj).checkAuthenticated(user) or
1697 EditByOwnersOrAdmins(self.obj).checkAuthenticated(user))
1698
1699
1675class AdminDistroSeriesTranslations(AuthorizationBase):1700class AdminDistroSeriesTranslations(AuthorizationBase):
1676 permission = 'launchpad.TranslationsAdmin'1701 permission = 'launchpad.TranslationsAdmin'
1677 usedfor = IDistroSeries1702 usedfor = IDistroSeries
16781703
=== modified file 'lib/lp/translations/browser/potemplate.py'
--- lib/lp/translations/browser/potemplate.py 2009-12-22 10:28:45 +0000
+++ lib/lp/translations/browser/potemplate.py 2009-12-29 18:24:17 +0000
@@ -512,7 +512,8 @@
512 """View class that lets you edit a POTemplate object."""512 """View class that lets you edit a POTemplate object."""
513513
514 schema = IPOTemplate514 schema = IPOTemplate
515 field_names = ['description', 'priority', 'owner']515 field_names = ['name', 'translation_domain', 'description', 'priority',
516 'path', 'owner', 'iscurrent']
516 label = 'Edit translation template details'517 label = 'Edit translation template details'
517 page_title = 'Edit details'518 page_title = 'Edit details'
518519
@@ -712,7 +713,7 @@
712 raise AssertionError('Unknown context for %s' % potemplate.title)713 raise AssertionError('Unknown context for %s' % potemplate.title)
713714
714 if ((official_rosetta and potemplate.iscurrent) or715 if ((official_rosetta and potemplate.iscurrent) or
715 check_permission('launchpad.TranslationsAdmin', self.context)):716 check_permission('launchpad.Edit', self.context)):
716 # The target is using officially Launchpad Translations and the717 # The target is using officially Launchpad Translations and the
717 # template is available to be translated, or the user is a is a718 # template is available to be translated, or the user is a is a
718 # Launchpad administrator in which case we show everything.719 # Launchpad administrator in which case we show everything.
719720
=== modified file 'lib/lp/translations/configure.zcml'
--- lib/lp/translations/configure.zcml 2009-12-10 14:25:16 +0000
+++ lib/lp/translations/configure.zcml 2009-12-29 18:24:17 +0000
@@ -409,10 +409,16 @@
409 interface="lp.translations.interfaces.potemplate.IPOTemplate"/>409 interface="lp.translations.interfaces.potemplate.IPOTemplate"/>
410 <require410 <require
411 permission="launchpad.Edit"411 permission="launchpad.Edit"
412 set_attributes="owner priority description"/>412 set_attributes="
413 owner priority description translation_domain path
414 iscurrent name"/>
413 <require415 <require
414 permission="launchpad.TranslationsAdmin"416 permission="launchpad.TranslationsAdmin"
415 set_attributes="name translation_domain productseries distroseries sourcepackagename sourcepackageversion binarypackagename languagepack path header iscurrent from_sourcepackagename date_last_updated source_file source_file_format"/>417 set_attributes="
418 productseries distroseries sourcepackagename
419 sourcepackageversion binarypackagename languagepack
420 source_file_format source_file date_last_updated
421 from_sourcepackagename header"/>
416 </class>422 </class>
417 <adapter423 <adapter
418 provides="canonical.launchpad.webapp.interfaces.IBreadcrumb"424 provides="canonical.launchpad.webapp.interfaces.IBreadcrumb"
419425
=== modified file 'lib/lp/translations/stories/productseries/xx-productseries-templates.txt'
--- lib/lp/translations/stories/productseries/xx-productseries-templates.txt 2009-11-30 18:18:08 +0000
+++ lib/lp/translations/stories/productseries/xx-productseries-templates.txt 2009-12-29 18:24:17 +0000
@@ -1,5 +1,3 @@
1
2
3Templates view for ProductSeries1Templates view for ProductSeries
4================================2================================
53
@@ -21,8 +19,11 @@
21 >>> evolution_trunk = evolution.getSeries('trunk')19 >>> evolution_trunk = evolution.getSeries('trunk')
22 >>> template = factory.makePOTemplate(productseries=evolution_trunk,20 >>> template = factory.makePOTemplate(productseries=evolution_trunk,
23 ... name='at-the-top')21 ... name='at-the-top')
22 >>> template = factory.makePOTemplate(productseries=evolution_trunk,
23 ... name='disabled')
24 >>> template.iscurrent = False
24 >>> logout()25 >>> logout()
2526 >>> owner_browser = setupBrowser('Basic test@canonical.com:test')
2627
27Getting there28Getting there
28-------------29-------------
@@ -41,6 +42,7 @@
41-------------------42-------------------
4243
43The page shows a table of all templates and links to their subpages.44The page shows a table of all templates and links to their subpages.
45Users will not see disabled templates.
4446
45 >>> table = find_tag_by_id(user_browser.contents, 'templates_table')47 >>> table = find_tag_by_id(user_browser.contents, 'templates_table')
46 >>> print extract_text(table)48 >>> print extract_text(table)
@@ -58,6 +60,7 @@
58 >>> print extract_text(table)60 >>> print extract_text(table)
59 Template name Last update Actions61 Template name Last update Actions
60 at-the-top ... Edit Upload Download Administer62 at-the-top ... Edit Upload Download Administer
63 disabled (inactive) ... Edit Upload Download Administer
61 evolution-2.2 2005-08-25 Edit Upload Download Administer64 evolution-2.2 2005-08-25 Edit Upload Download Administer
62 evolution-2.2-test 2006-12-13 Edit Upload Download Administer65 evolution-2.2-test 2006-12-13 Edit Upload Download Administer
6366
@@ -72,11 +75,21 @@
72 >>> print admin_browser.url75 >>> print admin_browser.url
73 http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.276 http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2
7477
78Clicking on 'Admin' will take the user to the page to administer the template.
79Likewise for the other links for each template.
80
81 >>> admin_browser.open(
82 ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
83 >>> admin_browser.getLink('Admin', index=0).click()
84 >>> print admin_browser.url
85 http://translations.launchpad.dev/evolution/trunk/+pots/at-the-top/+admin
86
75Clicking on 'Edit' will take the user to the page to edit the template87Clicking on 'Edit' will take the user to the page to edit the template
76details. Likewise for the other links for each template.88details, even if the translation of the templates are not active.
7789
78 >>> admin_browser.open(90 >>> owner_browser.open(
79 ... 'http://translations.launchpad.dev/evolution/trunk/+templates')91 ... 'http://translations.launchpad.dev/evolution/trunk/+templates')
80 >>> admin_browser.getLink('Edit').click()92 >>> owner_browser.getLink('Edit', index=1).click()
81 >>> print admin_browser.url93 >>> print owner_browser.url
82 http://translations.launchpad.dev/evolution/trunk/+pots/at-the-top/+edit94 http://translations.launchpad.dev/evolution/trunk/+pots/disabled/+edit
95
8396
=== modified file 'lib/lp/translations/stories/standalone/xx-potemplate-edit.txt'
--- lib/lp/translations/stories/standalone/xx-potemplate-edit.txt 2009-09-17 10:22:14 +0000
+++ lib/lp/translations/stories/standalone/xx-potemplate-edit.txt 2009-12-29 18:24:17 +0000
@@ -20,7 +20,7 @@
20 Traceback (most recent call last):20 Traceback (most recent call last):
21 ...21 ...
22 LinkNotFoundError22 LinkNotFoundError
23 23
2424
25On the other hand, Rosetta expert (Jordi) can reach the POTemplate edit25On the other hand, Rosetta expert (Jordi) can reach the POTemplate edit
26page.26page.
@@ -43,9 +43,7 @@
43We should be sure that the edit form get only the non admin fields.43We should be sure that the edit form get only the non admin fields.
4444
45 >>> browser.getControl(name='field.name').value45 >>> browser.getControl(name='field.name').value
46 Traceback (most recent call last):46 'evolution-2.2'
47 ...
48 LookupError:...
49 >>> browser.getControl(name='field.description').value47 >>> browser.getControl(name='field.description').value
50 'Template for evolution in hoary'48 'Template for evolution in hoary'
51 >>> browser.getControl(name='field.header').value49 >>> browser.getControl(name='field.header').value
@@ -53,9 +51,7 @@
53 ...51 ...
54 LookupError:...52 LookupError:...
55 >>> browser.getControl(name='field.iscurrent').value53 >>> browser.getControl(name='field.iscurrent').value
56 Traceback (most recent call last):54 True
57 ...
58 LookupError:...
59 >>> browser.getControl(name='field.owner').value55 >>> browser.getControl(name='field.owner').value
60 'rosetta-admins'56 'rosetta-admins'
61 >>> browser.getControl(name='field.productseries').value57 >>> browser.getControl(name='field.productseries').value
@@ -83,9 +79,7 @@
83 ...79 ...
84 LookupError:...80 LookupError:...
85 >>> browser.getControl(name='field.path').value81 >>> browser.getControl(name='field.path').value
86 Traceback (most recent call last):82 'po/evolution-2.2.pot'
87 ...
88 LookupError:...
8983
90And that we are able to POST it.84And that we are able to POST it.
9185
9286
=== modified file 'lib/lp/translations/templates/object-templates.pt'
--- lib/lp/translations/templates/object-templates.pt 2009-12-10 12:46:11 +0000
+++ lib/lp/translations/templates/object-templates.pt 2009-12-29 18:24:17 +0000
@@ -84,7 +84,7 @@
84 <tbody>84 <tbody>
85 <tal:templates repeat="template view/iter_templates">85 <tal:templates repeat="template view/iter_templates">
86 <tal:not-current condition="not: template/iscurrent">86 <tal:not-current condition="not: template/iscurrent">
87 <tal:admin condition="template/required:launchpad.TranslationsAdmin">87 <tal:admin condition="template/required:launchpad.Edit">
88 <tr class="template_row inactive-template">88 <tr class="template_row inactive-template">
89 <td tal:condition="view/is_distroseries"89 <td tal:condition="view/is_distroseries"
90 tal:content="template/sourcepackagename/name"90 tal:content="template/sourcepackagename/name"