launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #20042
[Merge] lp:~thomir/launchpad/devel-add-read-ff into lp:launchpad
Thomi Richards has proposed merging lp:~thomir/launchpad/devel-add-read-ff into lp:launchpad with lp:~thomir/launchpad/devel-start-integration as a prerequisite.
Commit message:
Add feature flag to read GPG keys from gpgservice.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~thomir/launchpad/devel-add-read-ff/+merge/287695
Add feature flag to read GPG keys from gpgservice.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~thomir/launchpad/devel-add-read-ff into lp:launchpad.
=== modified file 'buildout.cfg'
--- buildout.cfg 2016-02-15 00:54:24 +0000
+++ buildout.cfg 2016-03-01 19:25:45 +0000
@@ -31,7 +31,7 @@
prefer-final = true
-develop = .
+develop = . /home/thomi/code/canonical/canonical-gpg-service
[configuration]
instance_name = development
=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml 2016-02-05 20:28:29 +0000
+++ lib/lp/registry/configure.zcml 2016-03-01 19:25:45 +0000
@@ -1284,6 +1284,14 @@
permission="launchpad.Edit"
set_attributes="active can_encrypt"/>
</class>
+ <class
+ class="lp.registry.model.gpgkey.GPGServiceKey">
+ <allow
+ interface="lp.registry.interfaces.gpg.IGPGKey"/>
+ <require
+ permission="launchpad.Edit"
+ set_attributes="active can_encrypt"/>
+ </class>
<!-- GPGKeySet -->
=== modified file 'lib/lp/registry/interfaces/gpg.py'
--- lib/lp/registry/interfaces/gpg.py 2016-03-01 19:25:45 +0000
+++ lib/lp/registry/interfaces/gpg.py 2016-03-01 19:25:45 +0000
@@ -73,37 +73,22 @@
reactivated an existing key.
"""
-<<<<<<< TREE
-=======
def deactivate(key):
"""Deactivate a key.
:param key: An IGPGKey instance.
"""
- def get(key_id, default=None):
- """Return the GPGKey object for the given id.
-
- Return the given default if there's no object with the given id.
- """
-
->>>>>>> MERGE-SOURCE
def getByFingerprint(fingerprint, default=None):
"""Return UNIQUE result for a given Key fingerprint including
inactive ones.
"""
+ def getOwnerIdForPerson(person):
+ """return an owner id string suitable for sending to gpgservice."""
+
def getGPGKeysForPerson(person, active=True):
"""Return OpenGPG keys for a person.
:returns: a list of IGPGKey instances.
"""
-<<<<<<< TREE
-=======
-
- def getGPGKeysForPeople(people):
- """Return OpenPGP keys for a set of people."""
-
- def getOwnerIdForPerson(person):
- """return an owner id string suitable for sending to gpgservice."""
->>>>>>> MERGE-SOURCE
=== modified file 'lib/lp/registry/model/gpgkey.py'
--- lib/lp/registry/model/gpgkey.py 2016-03-01 19:25:45 +0000
+++ lib/lp/registry/model/gpgkey.py 2016-03-01 19:25:45 +0000
@@ -18,6 +18,7 @@
IGPGKey,
IGPGKeySet,
)
+from lp.registry.interfaces.person import IPersonSet
from lp.services.database.enumcol import EnumCol
from lp.services.database.sqlbase import (
SQLBase,
@@ -26,6 +27,7 @@
from lp.services.features import getFeatureFlag
from lp.services.gpg.interfaces import (
GPG_WRITE_TO_GPGSERVICE_FEATURE_FLAG,
+ GPG_READ_FROM_GPGSERVICE_FEATURE_FLAG,
GPGKeyAlgorithm,
IGPGClient,
IGPGHandler,
@@ -64,6 +66,53 @@
return '%s%s/%s' % (self.keysize, self.algorithm.title, self.keyid)
+@implementer(IGPGKey)
+class GPGServiceKey:
+
+ def __init__(self, key_data):
+ self._key_data = key_data
+ self.active = key_data['enabled']
+
+ @property
+ def keysize(self):
+ return self._key_data['size']
+
+ @property
+ def algorithm(self):
+ return GPGKeyAlgorithm.items[self._key_data['algorithm']]
+
+ @property
+ def keyid(self):
+ return self._key_data['id']
+
+ @property
+ def fingerprint(self):
+ return self._key_data['fingerprint']
+
+ @property
+ def displayname(self):
+ return '%s%s/%s' % (self.keysize, self.algorithm.title, self.keyid)
+
+ @property
+ def keyserverURL(self):
+ return getUtility(
+ IGPGHandler).getURLForKeyInServer(self.fingerprint, public=True)
+
+ @property
+ def can_encrypt(self):
+ return self._key_data['can_encrypt']
+
+ @property
+ def owner(self):
+ return getUtility(IPersonSet).getByOpenIDIdentifier(
+ self._key_data['owner'])
+
+ @property
+ def ownerID(self):
+ return self.owner.id
+
+
+
@implementer(IGPGKeySet)
class GPGKeySet:
@@ -109,33 +158,39 @@
def getByFingerprint(self, fingerprint, default=None):
"""See `IGPGKeySet`"""
- result = GPGKey.selectOneBy(fingerprint=fingerprint)
- if result is None:
- return default
- return result
+ if getFeatureFlag(GPG_READ_FROM_GPGSERVICE_FEATURE_FLAG):
+ key_data = getUtility(IGPGClient).getKeyByFingerprint(fingerprint)
+ return GPGServiceKey(key_data) if key_data else default
+ else:
+ result = GPGKey.selectOneBy(fingerprint=fingerprint)
+ if result is None:
+ return default
+ return result
def getGPGKeysForPerson(self, owner, active=True):
- if active is False:
- query = """
- active = false
- AND fingerprint NOT IN
- (SELECT fingerprint FROM LoginToken
- WHERE fingerprint IS NOT NULL
- AND requester = %s
- AND date_consumed is NULL
- )
- """ % sqlvalues(owner.id)
+ if getFeatureFlag(GPG_READ_FROM_GPGSERVICE_FEATURE_FLAG):
+ client = getUtility(IGPGClient)
+ owner_id = self.getOwnerIdForPerson(owner)
+ keys = client.getKeysForOwner(owner_id)['keys']
+ return [GPGServiceKey(d) for d in keys if d['enabled'] == active]
else:
- query = 'active=true'
-
- query += ' AND owner=%s' % sqlvalues(owner.id)
-
-<<<<<<< TREE
- return list(GPGKey.select(query, orderBy='id'))
-=======
- return GPGKey.select(query, orderBy='id')
+ if active is False:
+ query = """
+ active = false
+ AND fingerprint NOT IN
+ (SELECT fingerprint FROM LoginToken
+ WHERE fingerprint IS NOT NULL
+ AND requester = %s
+ AND date_consumed is NULL
+ )
+ """ % sqlvalues(owner.id)
+ else:
+ query = 'active=true'
+
+ query += ' AND owner=%s' % sqlvalues(owner.id)
+
+ return list(GPGKey.select(query, orderBy='id'))
def getOwnerIdForPerson(self, owner):
"""See IGPGKeySet."""
return IOpenIDPersistentIdentity(owner).openid_identity_url
->>>>>>> MERGE-SOURCE
=== modified file 'lib/lp/services/gpg/interfaces.py'
--- lib/lp/services/gpg/interfaces.py 2016-03-01 19:25:45 +0000
+++ lib/lp/services/gpg/interfaces.py 2016-03-01 19:25:45 +0000
@@ -3,6 +3,7 @@
__all__ = [
'GPG_DATABASE_READONLY_FEATURE_FLAG',
+ 'GPG_READ_FROM_GPGSERVICE_FEATURE_FLAG',
'GPG_WRITE_TO_GPGSERVICE_FEATURE_FLAG',
'GPGKeyAlgorithm',
'GPGKeyDoesNotExistOnServer',
@@ -52,6 +53,7 @@
GPG_DATABASE_READONLY_FEATURE_FLAG = u"gpg.database_read_only"
GPG_WRITE_TO_GPGSERVICE_FEATURE_FLAG = u"gpg.write_to_gpgservice"
+GPG_READ_FROM_GPGSERVICE_FEATURE_FLAG = u"gpg.read_from_gpgservice"
def valid_fingerprint(fingerprint):
=== modified file 'lib/lp/services/gpg/tests/test_gpghandler.py'
--- lib/lp/services/gpg/tests/test_gpghandler.py 2016-03-01 19:25:45 +0000
+++ lib/lp/services/gpg/tests/test_gpghandler.py 2016-03-01 19:25:45 +0000
@@ -16,6 +16,7 @@
from zope.security.proxy import removeSecurityProxy
from lp.registry.interfaces.gpg import IGPGKeySet
+from lp.registry.interfaces.person import IPersonSet
from lp.services.config.fixture import (
ConfigFixture,
ConfigUseFixture,
@@ -254,7 +255,9 @@
def test_get_key_for_user_with_sampledata(self):
client = getUtility(IGPGClient)
- data = client.getKeysForOwner('name16_oid')
+ person = getUtility(IPersonSet).getByName('name16')
+ openid_id = getUtility(IGPGKeySet).getOwnerIdForPerson(person)
+ data = client.getKeysForOwner(openid_id)
self.assertThat(data, ContainsDict({'keys': HasLength(1)}))
def test_get_key_for_unknown_user(self):
=== modified file 'lib/lp/testing/gpgservice/_fixture.py'
--- lib/lp/testing/gpgservice/_fixture.py 2016-02-16 05:36:37 +0000
+++ lib/lp/testing/gpgservice/_fixture.py 2016-03-01 19:25:45 +0000
@@ -99,7 +99,7 @@
test_data = {
'keys': [
{
- 'owner': 'name16_oid',
+ 'owner': config.launchpad.openid_provider_root + '+id/name16_oid',
'id': '12345678',
'fingerprint': 'ABCDEF0123456789ABCDDCBA0000111112345678',
'size': 1024,
=== modified file 'lib/lp/testing/gpgservice/tests/test_fixture.py'
--- lib/lp/testing/gpgservice/tests/test_fixture.py 2016-03-01 19:25:45 +0000
+++ lib/lp/testing/gpgservice/tests/test_fixture.py 2016-03-01 19:25:45 +0000
@@ -47,7 +47,8 @@
def test_fixture_can_create_test_data(self):
fixture = self.useFixture(GPGKeyServiceFixture())
conn = httplib.HTTPConnection(fixture.bind_address)
- user = base64.b64encode('name16_oid', altchars='-_')
+ user = base64.b64encode(
+ config.launchpad.openid_provider_root + '+id/name16_oid', altchars='-_')
conn.request('GET', '/users/%s/keys' % user)
resp = conn.getresponse()
self.assertEqual(200, resp.status)
=== modified file 'versions.cfg'
--- versions.cfg 2016-03-01 19:25:45 +0000
+++ versions.cfg 2016-03-01 19:25:45 +0000
@@ -38,7 +38,7 @@
flask = 0.10.1
FormEncode = 1.2.4
funkload = 1.16.1
-gpgservice = 0.1.1
+gpgservice = 0.1.2
grokcore.component = 1.6
gunicorn = 19.4.5
html5browser = 0.0.9
Follow ups