launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #02232
incremental diff
Here is the incremental diff in relation to Adi's branch. This MP is only
about these changes.
--
https://code.launchpad.net/~henninge/launchpad/devel-487137-custom-language-codes/+merge/44446
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~henninge/launchpad/devel-487137-custom-language-codes into lp:launchpad.
=== modified file 'lib/canonical/launchpad/security.py'
--- lib/canonical/launchpad/security.py 2010-12-21 15:13:17 +0000
+++ lib/canonical/launchpad/security.py 2010-12-22 12:03:59 +0000
@@ -185,7 +185,6 @@
from lp.soyuz.interfaces.sourcepackagerelease import ISourcePackageRelease
from lp.translations.interfaces.customlanguagecode import (
ICustomLanguageCode,
- IHasCustomLanguageCodes,
)
from lp.translations.interfaces.languagepack import ILanguagePack
from lp.translations.interfaces.pofile import IPOFile
@@ -744,6 +743,7 @@
# with launchpad.View so that this adapter is used. For now, though, it's
# going to be used only on the webservice (which explicitly checks for
# launchpad.View) so that we don't leak memberships of private teams.
+
class ViewTeamMembership(AuthorizationBase):
permission = 'launchpad.View'
usedfor = ITeamMembership
@@ -1728,27 +1728,23 @@
usedfor = ILanguage
-class AdminCustomLanguageCodes(OnlyRosettaExpertsAndAdmins):
- """Controls administration of custom language codes.
-
- Rosetta experts and Launchpad administrators can administer custom
- language codes.
- """
-
- permission = 'launchpad.TranslationsAdmin'
- usedfor = IHasCustomLanguageCodes
-
-
-class AdminCustomLanguageCode(OnlyRosettaExpertsAndAdmins):
+class AdminCustomLanguageCode(AuthorizationBase):
"""Controls administration for a custom language code.
- Rosetta experts and Launchpad administrators can administer a custom
- language code.
+ Whoever can admin a product's or distribution's translations can also
+ admin the custom language codes for it.
"""
-
permission = 'launchpad.TranslationsAdmin'
usedfor = ICustomLanguageCode
+ def checkAuthenticated(self, user):
+ if self.obj.product is not None:
+ return AdminProductTranslations(
+ self.obj.product).checkAuthenticated(user)
+ else:
+ return AdminDistributionTranslations(
+ self.obj.distribution).checkAuthenticated(user)
+
class AccessBranch(AuthorizationBase):
"""Controls visibility of branches.
@@ -1839,6 +1835,12 @@
self.obj.distribution).checkAuthenticated(user))
+class AdminDistributionSourcePackageTranslations(
+ AdminDistroSeriesTranslations):
+ """DistributionSourcePackage objects link to a distribution, too."""
+ usedfor = IDistributionSourcePackage
+
+
class AdminProductSeriesTranslations(AuthorizationBase):
permission = 'launchpad.TranslationsAdmin'
usedfor = IProductSeries
=== modified file 'lib/lp/translations/browser/configure.zcml'
--- lib/lp/translations/browser/configure.zcml 2010-12-21 15:13:17 +0000
+++ lib/lp/translations/browser/configure.zcml 2010-12-22 12:01:59 +0000
@@ -941,7 +941,7 @@
for="lp.registry.interfaces.distribution.IDistribution"
permission="zope.Public"
template="../templates/translations-portlet-not-using-launchpad-extra.pt"
- layer="lp.translations.publisher.TranslationsLayer"/>
+ layer="lp.translations.publisher.TranslationsLayer"/>
<browser:page
name="+portlet-configuration"
for="lp.registry.interfaces.distribution.IDistribution"
=== modified file 'lib/lp/translations/browser/customlanguagecode.py'
--- lib/lp/translations/browser/customlanguagecode.py 2010-12-21 15:13:17 +0000
+++ lib/lp/translations/browser/customlanguagecode.py 2010-12-22 12:03:05 +0000
@@ -46,6 +46,7 @@
class CustomLanguageCodeBreadcrumb(Breadcrumb):
"""Breadcrumb for a `CustomLanguageCode`."""
+
@property
def text(self):
return smartquote(
@@ -164,6 +165,7 @@
class HasCustomLanguageCodesTraversalMixin:
"""Navigate from an `IHasCustomLanguageCodes` to a `CustomLanguageCode`.
"""
+
@stepthrough('+customcode')
def traverseCustomCode(self, name):
"""Traverse +customcode URLs."""
=== modified file 'lib/lp/translations/stories/standalone/custom-language-codes.txt'
--- lib/lp/translations/stories/standalone/custom-language-codes.txt 2010-12-21 15:13:17 +0000
+++ lib/lp/translations/stories/standalone/custom-language-codes.txt 2010-12-22 12:04:22 +0000
@@ -38,16 +38,18 @@
>>> owner_browser = setupBrowser("Basic o@xxxxxxxxxxx:test")
>>> rosetta_admin_browser = setupRosettaExpertBrowser()
-A Launchpad administrator or Rosetta expert sees the link to the custom
-language codes on a project's main translations page.
+The project's owner sees the link to the custom language codes on a project's
+main translations page.
- >>> admin_browser.open(product_page)
- >>> tag = find_custom_language_codes_link(admin_browser)
+ >>> owner_browser.open(product_page)
+ >>> tag = find_custom_language_codes_link(owner_browser)
>>> print extract_text(tag.renderContents())
If necessary, you may
define custom language codes
for this project.
+Translation admins also have access to this link.
+
>>> rosetta_admin_browser.open(product_page)
>>> tag = find_custom_language_codes_link(rosetta_admin_browser)
>>> print extract_text(tag.renderContents())
@@ -57,39 +59,37 @@
The link goes to the custom language codes management page.
- >>> rosetta_admin_browser.getLink("define custom language codes").click()
- >>> custom_language_codes_page = rosetta_admin_browser.url
-
-Non-admins, even the project's owner, don't see this link. We do not
-advertise this feature, since the proper solution is generally to use
-the right language codes.
-
- >>> owner_browser.open(product_page)
- >>> print find_custom_language_codes_link(owner_browser)
+ >>> owner_browser.getLink("define custom language codes").click()
+ >>> custom_language_codes_page = owner_browser.url
+
+Other users don't see this link.
+
+ >>> user_browser.open(product_page)
+ >>> print find_custom_language_codes_link(user_browser)
None
Initially the page shows no custom language codes for the project.
- >>> tag = find_tag_by_id(rosetta_admin_browser.contents, 'empty')
+ >>> tag = find_tag_by_id(owner_browser.contents, 'empty')
>>> print extract_text(tag.renderContents())
No custom language codes have been defined.
-The admin can add a custom language code.
-
- >>> rosetta_admin_browser.getLink("Add a custom language code").click()
- >>> add_page = rosetta_admin_browser.url
-
- >>> rosetta_admin_browser.getControl("Language code:").value = 'no'
- >>> rosetta_admin_browser.getControl("Language:").value = ['nn']
- >>> rosetta_admin_browser.getControl("Add").click()
+There is a link to add a custom language code.
+
+ >>> owner_browser.getLink("Add a custom language code").click()
+ >>> add_page = owner_browser.url
+
+ >>> owner_browser.getControl("Language code:").value = 'no'
+ >>> owner_browser.getControl("Language:").value = ['nn']
+ >>> owner_browser.getControl("Add").click()
This leads back to the custom language codes overview, where the new
code is now shown.
- >>> rosetta_admin_browser.url == custom_language_codes_page
+ >>> owner_browser.url == custom_language_codes_page
True
- >>> tag = find_tag_by_id(rosetta_admin_browser.contents, 'nonempty')
+ >>> tag = find_tag_by_id(owner_browser.contents, 'nonempty')
>>> print extract_text(tag.renderContents())
Foo uses the following custom language codes:
Code... ...maps to language
@@ -98,8 +98,8 @@
There is an overview page for the custom code, though there's not much
to see there.
- >>> rosetta_admin_browser.getLink("no").click()
- >>> main = find_main_content(rosetta_admin_browser.contents)
+ >>> owner_browser.getLink("no").click()
+ >>> main = find_main_content(owner_browser.contents)
>>> print extract_text(main.renderContents())
Foo Translations Custom language code ...no...
For Foo, uploads with the language code
@@ -111,79 +111,79 @@
The overview page leads back to the custom language codes overview.
- >>> code_page = rosetta_admin_browser.url
- >>> rosetta_admin_browser.getLink(
+ >>> code_page = owner_browser.url
+ >>> owner_browser.getLink(
... "custom language codes overview").click()
- >>> rosetta_admin_browser.url == custom_language_codes_page
+ >>> owner_browser.url == custom_language_codes_page
True
- >>> rosetta_admin_browser.open(code_page)
+ >>> owner_browser.open(code_page)
-There is also a link for removing codes. The admin follows the link and
+There is also a link for removing codes. The owner follows the link and
removes the "no" custom language code.
- >>> rosetta_admin_browser.getLink("remove custom language code").click()
- >>> remove_page = rosetta_admin_browser.url
- >>> rosetta_admin_browser.getControl("Remove").click()
+ >>> owner_browser.getLink("remove custom language code").click()
+ >>> remove_page = owner_browser.url
+ >>> owner_browser.getControl("Remove").click()
This leads back to the overview page.
- >>> rosetta_admin_browser.url == custom_language_codes_page
+ >>> owner_browser.url == custom_language_codes_page
True
- >>> tag = find_tag_by_id(rosetta_admin_browser.contents, 'empty')
- >>> print extract_text(tag.renderContents())
- No custom language codes have been defined.
-
-
-Non-admin access
-================
-
-A non-admin can see the page, actually, if they know the URL. This can
-be convenient for debugging.
-
- >>> owner_browser.open(custom_language_codes_page)
-
>>> tag = find_tag_by_id(owner_browser.contents, 'empty')
>>> print extract_text(tag.renderContents())
No custom language codes have been defined.
+
+Unprivileged access
+===================
+
+A unprivileged user can see the page, actually, if they know the URL.
+This can be convenient for debugging.
+
+ >>> user_browser.open(custom_language_codes_page)
+
+ >>> tag = find_tag_by_id(user_browser.contents, 'empty')
+ >>> print extract_text(tag.renderContents())
+ No custom language codes have been defined.
+
However all they get is a read-only version of the page.
- >>> owner_browser.getLink("Add a custom language code").click()
+ >>> user_browser.getLink("Add a custom language code").click()
Traceback (most recent call last):
...
LinkNotFoundError
The page for adding custom language codes is not accessible to them.
+ >>> user_browser.open(add_page)
+ Traceback (most recent call last):
+ ...
+ Unauthorized: ...
+
+And naturally, if the owner creates a custom language code again, an
+unprivileged user can't remove it.
+
>>> owner_browser.open(add_page)
- Traceback (most recent call last):
- ...
- Unauthorized: ...
-
-And naturally, if an admin creates a custom language code again, a
-non-admin can't remove it.
-
- >>> rosetta_admin_browser.open(add_page)
- >>> rosetta_admin_browser.getControl("Language code:").value = 'no'
- >>> rosetta_admin_browser.getControl("Language:").value = ['nn']
- >>> rosetta_admin_browser.getControl("Add").click()
-
- >>> owner_browser.open(custom_language_codes_page)
- >>> tag = find_tag_by_id(owner_browser.contents, 'nonempty')
+ >>> owner_browser.getControl("Language code:").value = 'no'
+ >>> owner_browser.getControl("Language:").value = ['nn']
+ >>> owner_browser.getControl("Add").click()
+
+ >>> user_browser.open(custom_language_codes_page)
+ >>> tag = find_tag_by_id(user_browser.contents, 'nonempty')
>>> print extract_text(tag.renderContents())
Foo uses the following custom language codes:
Code... ...maps to language
no Norwegian Nynorsk
- >>> owner_browser.getLink("no").click()
- >>> owner_browser.getLink("remove custom language code")
+ >>> user_browser.getLink("no").click()
+ >>> user_browser.getLink("remove custom language code")
Traceback (most recent call last):
...
LinkNotFoundError
- >>> owner_browser.open(remove_page)
+ >>> user_browser.open(remove_page)
Traceback (most recent call last):
...
Unauthorized: ...
@@ -197,7 +197,8 @@
package--i.e. the combination of a distribution and a source package
name. However, since there is no Translations page for that type of
object (and we'd probably never go there if there were), the link is
-shown on the source package page.
+shown on the source package page. For distributions, the owner of the
+distribution's translation group is a translations administrator.
>>> login(ANONYMOUS)
>>> from lp.registry.model.sourcepackage import SourcePackage
@@ -219,38 +220,44 @@
... distroseries=other_series,
... sourcepackagename=package.sourcepackagename),
... rootsite="translations")
+ >>> translations_admin = factory.makePerson(
+ ... email='ta@xxxxxxxxxxx', password='test')
+ >>> translationgroup = factory.makeTranslationGroup(
+ ... owner=translations_admin)
+ >>> removeSecurityProxy(distro).translationgroup = translationgroup
>>> logout()
- >>> rosetta_admin_browser.open(package_page)
+ >>> translations_browser = setupBrowser("Basic ta@xxxxxxxxxxx:test")
+ >>> translations_browser.open(package_page)
Of course in this case, the notice about there being no custom language
codes talks about a package, not a project.
- >>> tag = find_custom_language_codes_link(rosetta_admin_browser)
+ >>> tag = find_custom_language_codes_link(translations_browser)
>>> print extract_text(tag.renderContents())
If necessary, you may
define custom language codes
for this package.
- >>> rosetta_admin_browser.getLink("define custom language codes").click()
- >>> custom_language_codes_page = rosetta_admin_browser.url
+ >>> translations_browser.getLink("define custom language codes").click()
+ >>> custom_language_codes_page = translations_browser.url
- >>> tag = find_tag_by_id(rosetta_admin_browser.contents, 'empty')
+ >>> tag = find_tag_by_id(translations_browser.contents, 'empty')
>>> print extract_text(tag.renderContents())
No custom language codes have been defined.
-Again, an admin can add a language code.
-
- >>> rosetta_admin_browser.getLink("Add a custom language code").click()
- >>> add_page = rosetta_admin_browser.url
-
- >>> rosetta_admin_browser.getControl("Language code:").value = 'pt-br'
- >>> rosetta_admin_browser.getControl("Language:").value = ['pt_BR']
- >>> rosetta_admin_browser.getControl("Add").click()
+A translations admin can add a language code.
+
+ >>> translations_browser.getLink("Add a custom language code").click()
+ >>> add_page = translations_browser.url
+
+ >>> translations_browser.getControl("Language code:").value = 'pt-br'
+ >>> translations_browser.getControl("Language:").value = ['pt_BR']
+ >>> translations_browser.getControl("Add").click()
The language code is displayed.
- >>> tag = find_tag_by_id(rosetta_admin_browser.contents, 'nonempty')
+ >>> tag = find_tag_by_id(translations_browser.contents, 'nonempty')
>>> print extract_text(tag.renderContents())
bar in distro uses the following custom language codes:
Code... ...maps to language
@@ -259,15 +266,15 @@
It's also displayed identically on the same package but in another
release series of the same distribution.
- >>> rosetta_admin_browser.open(page_in_other_series)
- >>> tag = find_custom_language_codes_link(rosetta_admin_browser)
+ >>> translations_browser.open(page_in_other_series)
+ >>> tag = find_custom_language_codes_link(translations_browser)
>>> print extract_text(tag.renderContents())
If necessary, you may
define custom language codes
for this package.
- >>> rosetta_admin_browser.getLink("define custom language codes").click()
- >>> tag = find_tag_by_id(rosetta_admin_browser.contents, 'nonempty')
+ >>> translations_browser.getLink("define custom language codes").click()
+ >>> tag = find_tag_by_id(translations_browser.contents, 'nonempty')
>>> print extract_text(tag.renderContents())
bar in distro uses the following custom language codes:
Code... ...maps to language
@@ -276,13 +283,13 @@
The new code has a link there...
- >>> rosetta_admin_browser.getLink("pt-br").click()
+ >>> translations_browser.getLink("pt-br").click()
...and can be deleted.
- >>> rosetta_admin_browser.getLink("remove custom language code").click()
- >>> rosetta_admin_browser.getControl("Remove").click()
+ >>> translations_browser.getLink("remove custom language code").click()
+ >>> translations_browser.getControl("Remove").click()
- >>> tag = find_tag_by_id(rosetta_admin_browser.contents, 'empty')
+ >>> tag = find_tag_by_id(translations_browser.contents, 'empty')
>>> print extract_text(tag.renderContents())
No custom language codes have been defined.
References