← Back to team overview

launchpad-reviewers team mailing list archive

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