launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #24862
[Merge] ~ilasc/launchpad:person-oci-registry-credentials-view into launchpad:master
Ioana Lasc has proposed merging ~ilasc/launchpad:person-oci-registry-credentials-view into launchpad:master.
Commit message:
Add view for OCIRegistryCredentials on person page
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~ilasc/launchpad/+git/launchpad/+merge/385636
Added view to display the current set of OCI registry credentials on person page.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~ilasc/launchpad:person-oci-registry-credentials-view into launchpad:master.
diff --git a/lib/lp/registry/browser/configure.zcml b/lib/lp/registry/browser/configure.zcml
index 3991dd5..5e1489b 100644
--- a/lib/lp/registry/browser/configure.zcml
+++ b/lib/lp/registry/browser/configure.zcml
@@ -1231,6 +1231,13 @@
template="../templates/person-oauth-tokens.pt"
/>
<browser:page
+ name="+oci-registry-credentials"
+ for="lp.registry.interfaces.person.IPerson"
+ class="lp.registry.browser.person.PersonOCIRegistryCredentialsView"
+ permission="launchpad.Edit"
+ template="../templates/person-ociregistrycredentials.pt"
+ />
+ <browser:page
name="+livefs"
for="lp.registry.interfaces.person.IPerson"
class="lp.registry.browser.person.PersonLiveFSView"
diff --git a/lib/lp/registry/browser/person.py b/lib/lp/registry/browser/person.py
index d512b7b..f4ea957 100644
--- a/lib/lp/registry/browser/person.py
+++ b/lib/lp/registry/browser/person.py
@@ -30,6 +30,7 @@ __all__ = [
'PersonLiveFSView',
'PersonNavigation',
'PersonOAuthTokensView',
+ 'PersonOCIRegistryCredentialsView',
'PersonOverviewMenu',
'PersonOwnedTeamsView',
'PersonRdfContentsView',
@@ -133,6 +134,9 @@ from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin
from lp.code.errors import InvalidNamespace
from lp.code.interfaces.branchnamespace import IBranchNamespaceSet
from lp.code.interfaces.gitlookup import IGitTraverser
+from lp.oci.interfaces.ociregistrycredentials import (
+ IOCIRegistryCredentialsSet,
+ )
from lp.registry.browser import BaseRdfView
from lp.registry.browser.branding import BrandingChangeView
from lp.registry.browser.menu import (
@@ -570,6 +574,14 @@ class PersonNavigation(BranchTraversalMixin, Navigation):
return None
return irc_nick
+ @stepthrough('+oci-registry-credential')
+ def traverse_oci_registry_credential(self, id):
+ """Traverse to this person's OCI registry credentials."""
+ oci_credentials = getUtility(IOCIRegistryCredentialsSet).get(id)
+ if oci_credentials is None or oci_credentials.person != self.context:
+ return None
+ return oci_credentials
+
@stepto('+archivesubscriptions')
def traverse_archive_subscription(self):
"""Traverse to the archive subscription for this person."""
@@ -802,6 +814,7 @@ class PersonOverviewMenu(ApplicationMenu, PersonMenuMixin,
'view_ppa_subscriptions',
'ppa',
'oauth_tokens',
+ 'oci_registry_credentials',
'related_software_summary',
'view_recipes',
'view_snaps',
@@ -824,6 +837,12 @@ class PersonOverviewMenu(ApplicationMenu, PersonMenuMixin,
return Link(target, text, enabled=enabled, icon='info')
@enabled_with_permission('launchpad.Edit')
+ def oci_registry_credentials(self):
+ target = '+oci-registry-credentials'
+ text = 'OCI registry credentials'
+ return Link(target, text, icon='info')
+
+ @enabled_with_permission('launchpad.Edit')
def editlanguages(self):
target = '+editlanguages'
text = 'Set preferred languages'
@@ -3621,6 +3640,23 @@ class PersonOAuthTokensView(LaunchpadView):
canonical_url(self.context, view_name='+oauth-tokens'))
+class PersonOCIRegistryCredentialsView(LaunchpadView):
+ """View for Person:+oci-registry-credentials."""
+
+ @cachedproperty
+ def oci_registry_credentials(self):
+ return list(getUtility(
+ IOCIRegistryCredentialsSet).findByOwner(self.context))
+
+ @property
+ def page_title(self):
+ return "OCI registry credentials"
+
+ @property
+ def has_credentials(self):
+ return len(self.oci_registry_credentials) > 0
+
+
class PersonLiveFSView(LaunchpadView):
"""Default view for the list of live filesystems owned by a person."""
page_title = 'LiveFS'
diff --git a/lib/lp/registry/browser/tests/test_person.py b/lib/lp/registry/browser/tests/test_person.py
index 10bbba7..685526e 100644
--- a/lib/lp/registry/browser/tests/test_person.py
+++ b/lib/lp/registry/browser/tests/test_person.py
@@ -34,6 +34,11 @@ from lp.app.errors import NotFoundError
from lp.app.interfaces.launchpad import ILaunchpadCelebrities
from lp.blueprints.enums import SpecificationImplementationStatus
from lp.buildmaster.enums import BuildStatus
+from lp.oci.interfaces.ocirecipe import OCI_RECIPE_ALLOW_CREATE
+from lp.oci.interfaces.ociregistrycredentials import (
+ IOCIRegistryCredentialsSet,
+ )
+from lp.oci.tests.helpers import OCIConfigHelperMixin
from lp.registry.browser.person import PersonView
from lp.registry.browser.team import TeamInvitationView
from lp.registry.enums import PersonVisibility
@@ -365,6 +370,30 @@ class TestPersonIndexView(BrowserTestCase):
view = create_initialized_view(person, '+index')
self.assertTrue(view.should_show_gpgkeys_section)
+ def test_show_oci_registry_credentials_link(self):
+ person = self.factory.makePerson()
+ view = create_initialized_view(person, '+index', principal=person)
+ with person_logged_in(person):
+ markup = self.get_markup(view, person)
+ link_match = soupmatchers.HTMLContains(
+ soupmatchers.Tag(
+ 'OCIRegistryCredentials link', 'a',
+ attrs={
+ 'href':
+ 'http://launchpad.test/~%s/+oci-registry-credentials'
+ % person.name},
+ text='OCI registry credentials'))
+ self.assertThat(markup, link_match)
+
+ link_match = soupmatchers.HTMLContains(
+ soupmatchers.Tag(
+ 'OCIRegistryCredentials missing link', 'a',
+ text='OCI registry credentials'))
+
+ login(ANONYMOUS)
+ markup = self.get_markup(view, person)
+ self.assertNotIn(link_match, markup)
+
def test_ppas_query_count(self):
owner = self.factory.makePerson()
@@ -1281,6 +1310,50 @@ class TestPersonRelatedProjectsView(TestCaseWithFactory):
self.assertThat(view(), next_match)
+class TestPersonOCIRegistryCredentialsView(BrowserTestCase,
+ OCIConfigHelperMixin):
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestPersonOCIRegistryCredentialsView, self).setUp()
+ self.setConfig()
+ self.person = self.factory.makePerson(
+ name="test-person", displayname="Test Person")
+ self.ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
+ self.distroseries = self.factory.makeDistroSeries(
+ distribution=self.ubuntu, name="shiny", displayname="Shiny")
+ self.useFixture(FeatureFixture({
+ OCI_RECIPE_ALLOW_CREATE: "on",
+ "oci.build_series.%s" % self.distroseries.distribution.name:
+ self.distroseries.name,
+ }))
+ oci_project = self.factory.makeOCIProject(
+ pillar=self.distroseries.distribution)
+ self.recipe = self.factory.makeOCIRecipe(
+ registrant=self.person, owner=self.person,
+ oci_project=oci_project)
+
+ def test_view_oci_registry_credentials_on_person_page(self):
+ # Verify view helper attributes.
+ url = unicode(self.factory.getUniqueURL())
+ credentials = {'username': 'foo', 'password': 'bar'}
+ getUtility(IOCIRegistryCredentialsSet).new(
+ owner=self.user,
+ url=url,
+ credentials=credentials)
+ view = create_initialized_view(self.user, '+oci-registry-credentials')
+ self.assertEqual('OCI registry credentials', view.page_title)
+ with person_logged_in(self.user):
+ self.assertEqual(
+ credentials.get('username'),
+ view.oci_registry_credentials[0].getCredentials()['username'])
+ self.assertEqual(url, view.oci_registry_credentials[0].url)
+ self.assertEqual(
+ self.user.display_name,
+ view.oci_registry_credentials[0].owner.display_name)
+
+
class TestPersonLiveFSView(BrowserTestCase):
layer = DatabaseFunctionalLayer
diff --git a/lib/lp/registry/templates/person-index.pt b/lib/lp/registry/templates/person-index.pt
index 4cfee46..4933c09 100644
--- a/lib/lp/registry/templates/person-index.pt
+++ b/lib/lp/registry/templates/person-index.pt
@@ -82,6 +82,10 @@
tal:define="link context/menu:overview/oauth_tokens"
tal:condition="link/enabled"
tal:content="structure link/fmt:link" />
+ <li
+ tal:define="link context/menu:overview/oci_registry_credentials"
+ tal:condition="link/enabled"
+ tal:content="structure link/fmt:link" />
</ul>
<div class="yui-g">
diff --git a/lib/lp/registry/templates/person-ociregistrycredentials.pt b/lib/lp/registry/templates/person-ociregistrycredentials.pt
new file mode 100644
index 0000000..882e1cb
--- /dev/null
+++ b/lib/lp/registry/templates/person-ociregistrycredentials.pt
@@ -0,0 +1,33 @@
+<html
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+ metal:use-macro="view/macro:page/main_only"
+ i18n:domain="launchpad"
+>
+<body>
+<div metal:fill-slot="main">
+ <p id="no-participation" tal:condition="not: view/has_credentials">
+ <span tal:replace="context/title"/>
+ has not set any credentials yet.
+ </p>
+ <table id="oci-credentials" class="listing" tal:condition="view/has_credentials">
+ <thead>
+ <tr>
+ <th>Registry URL</th>
+ <th>Owner</th>
+ <th>Username</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr tal:repeat="oci_credentials view/oci_registry_credentials">
+ <td tal:content="oci_credentials/url"/>
+ <td tal:content="oci_credentials/owner/display_name"/>
+ <td tal:content="oci_credentials/username"/>
+ </tr>
+ </tbody>
+ </table>
+</div>
+</body>
+</html>