summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Pollan <meskio@sindominio.net>2017-02-06 19:38:58 +0100
committerRuben Pollan <meskio@sindominio.net>2017-02-09 18:35:54 +0100
commit374bb846b15596f99da77a4a7c9a348187774534 (patch)
treeb76b30ba3240b892817a0006d98523cf75c44199
parent546190e59ba11fe109d933f4f22fed5398f86010 (diff)
[feat] add account based keymanagement API
- Resolves: #8755
-rw-r--r--src/leap/bitmask/cli/keys.py18
-rw-r--r--src/leap/bitmask/core/dispatcher.py56
-rw-r--r--src/leap/bitmask/core/mail_services.py23
-rw-r--r--tests/unit/core/test_services.py8
-rw-r--r--ui/app/lib/bitmask.js20
5 files changed, 84 insertions, 41 deletions
diff --git a/src/leap/bitmask/cli/keys.py b/src/leap/bitmask/cli/keys.py
index 4683ac2..65747cb 100644
--- a/src/leap/bitmask/cli/keys.py
+++ b/src/leap/bitmask/cli/keys.py
@@ -44,11 +44,13 @@ SUBCOMMANDS:
parser = argparse.ArgumentParser(
description='Bitmask list keys',
prog='%s %s %s' % tuple(sys.argv[:3]))
+ parser.add_argument('-u', '--userid', default='',
+ help='Select the userid of the keyring')
parser.add_argument('--private', action='store_true',
help='Use private keys (by default uses public)')
subargs = parser.parse_args(raw_args)
- self.data += ['list']
+ self.data += ['list', subargs.uid]
if subargs.private:
self.data += ['private']
else:
@@ -60,12 +62,14 @@ SUBCOMMANDS:
parser = argparse.ArgumentParser(
description='Bitmask export key',
prog='%s %s %s' % tuple(sys.argv[:3]))
+ parser.add_argument('-u', '--userid', default='',
+ help='Select the userid of the keyring')
parser.add_argument('--private', action='store_true',
help='Use private keys (by default uses public)')
parser.add_argument('address', nargs=1,
help='email address of the key')
subargs = parser.parse_args(raw_args)
- self.data += ['export', subargs.address[0]]
+ self.data += ['export', subargs.uid, subargs.address[0]]
return self._send(self._print_key)
@@ -73,6 +77,8 @@ SUBCOMMANDS:
parser = argparse.ArgumentParser(
description='Bitmask import key',
prog='%s %s %s' % tuple(sys.argv[:3]))
+ parser.add_argument('-u', '--userid', default='',
+ help='Select the userid of the keyring')
parser.add_argument('--validation', choices=list(ValidationLevels),
default='Fingerprint',
help='Validation level for the key')
@@ -84,8 +90,8 @@ SUBCOMMANDS:
with open(subargs.file[0], 'r') as keyfile:
rawkey = keyfile.read()
- self.data += ['insert', subargs.address[0], subargs.validation,
- rawkey]
+ self.data += ['insert', subargs.uid, subargs.address[0],
+ subargs.validation, rawkey]
return self._send(self._print_key)
@@ -93,12 +99,14 @@ SUBCOMMANDS:
parser = argparse.ArgumentParser(
description='Bitmask delete key',
prog='%s %s %s' % tuple(sys.argv[:3]))
+ parser.add_argument('-u', '--userid', default='',
+ help='Select the userid of the keyring')
parser.add_argument('--private', action='store_true',
help='Use private keys (by default uses public)')
parser.add_argument('address', nargs=1,
help='email address of the key')
subargs = parser.parse_args(raw_args)
- self.data += ['delete', subargs.address[0]]
+ self.data += ['delete', subargs.uid, subargs.address[0]]
return self._send()
diff --git a/src/leap/bitmask/core/dispatcher.py b/src/leap/bitmask/core/dispatcher.py
index 7c1cdbd..2777d9a 100644
--- a/src/leap/bitmask/core/dispatcher.py
+++ b/src/leap/bitmask/core/dispatcher.py
@@ -267,58 +267,74 @@ class KeysCmd(SubCommand):
@register_method("[dict]")
def do_LIST(self, service, *parts, **kw):
+ uid = parts[2]
+
private = False
if parts[-1] == 'private':
private = True
- bonafide = kw['bonafide']
- d = bonafide.do_get_active_user()
+ d = defer.succeed(uid)
+ if not uid:
+ d = self._get_active_user(kw['bonafide'])
d.addCallback(service.do_list_keys, private)
return d
@register_method('dict')
def do_EXPORT(self, service, *parts, **kw):
- if len(parts) < 3:
- return defer.fail("An email address is needed")
- address = parts[2]
+ if len(parts) < 4:
+ raise ValueError("An email address is needed")
+ uid = parts[2]
+ address = parts[3]
private = False
if parts[-1] == 'private':
private = True
- bonafide = kw['bonafide']
- d = bonafide.do_get_active_user()
+ d = defer.succeed(uid)
+ if not uid:
+ d = self._get_active_user(kw['bonafide'])
d.addCallback(service.do_export, address, private)
return d
@register_method('dict')
+ @defer.inlineCallbacks
def do_INSERT(self, service, *parts, **kw):
- if len(parts) < 5:
- return defer.fail("An email address is needed")
- address = parts[2]
- validation = parts[3]
- rawkey = parts[4]
-
- bonafide = kw['bonafide']
- d = bonafide.do_get_active_user()
+ if len(parts) < 6:
+ raise ValueError("An email address is needed")
+ uid = parts[2]
+ address = parts[3]
+ validation = parts[4]
+ rawkey = parts[5]
+
+ d = defer.succeed(uid)
+ if not uid:
+ d = self._get_active_user(kw['bonafide'])
d.addCallback(service.do_insert, address, rawkey, validation)
return d
@register_method('str')
+ @defer.inlineCallbacks
def do_DELETE(self, service, *parts, **kw):
- if len(parts) < 3:
- return defer.fail("An email address is needed")
- address = parts[2]
+ if len(parts) < 4:
+ raise ValueError("An email address is needed")
+ uid = parts[2]
+ address = parts[3]
private = False
if parts[-1] == 'private':
private = True
- bonafide = kw['bonafide']
- d = bonafide.do_get_active_user()
+ d = defer.succeed(uid)
+ if not uid:
+ d = self._get_active_user(kw['bonafide'])
d.addCallback(service.do_delete, address, private)
return d
+ def _get_active_user(self, bonafide):
+ d = bonafide.do_get_active_user()
+ d.addCallback(lambda active: active['user'])
+ return d
+
class EventsCmd(SubCommand):
diff --git a/src/leap/bitmask/core/mail_services.py b/src/leap/bitmask/core/mail_services.py
index 2842b5d..b1bdea2 100644
--- a/src/leap/bitmask/core/mail_services.py
+++ b/src/leap/bitmask/core/mail_services.py
@@ -397,19 +397,31 @@ class KeymanagerService(HookableService):
# commands
def do_list_keys(self, userid, private=False):
- km = self._container.get_instance(userid['user'])
+ km = self._container.get_instance(userid)
+ if km is None:
+ return defer.fail(ValueError("User " + userid + " has no active "
+ "keymanager"))
+
d = km.get_all_keys(private=private)
d.addCallback(lambda keys: [dict(key) for key in keys])
return d
def do_export(self, userid, address, private=False):
- km = self._container.get_instance(userid['user'])
+ km = self._container.get_instance(userid)
+ if km is None:
+ return defer.fail(ValueError("User " + userid + " has no active "
+ "keymanager"))
+
d = km.get_key(address, private=private, fetch_remote=False)
d.addCallback(lambda key: dict(key))
return d
def do_insert(self, userid, address, rawkey, validation='Fingerprint'):
- km = self._container.get_instance(userid['user'])
+ km = self._container.get_instance(userid)
+ if km is None:
+ return defer.fail(ValueError("User " + userid + " has no active "
+ "keymanager"))
+
validation = ValidationLevels.get(validation)
d = km.put_raw_key(rawkey, address, validation=validation)
d.addCallback(lambda _: km.get_key(address, fetch_remote=False))
@@ -418,7 +430,10 @@ class KeymanagerService(HookableService):
@defer.inlineCallbacks
def do_delete(self, userid, address, private=False):
- km = self._container.get_instance(userid['user'])
+ km = self._container.get_instance(userid)
+ if km is None:
+ raise ValueError("User " + userid + " has no active keymanager")
+
key = yield km.get_key(address, private=private, fetch_remote=False)
km.delete_key(key)
defer.returnValue(key.fingerprint)
diff --git a/tests/unit/core/test_services.py b/tests/unit/core/test_services.py
index bb00dce..1b0e80c 100644
--- a/tests/unit/core/test_services.py
+++ b/tests/unit/core/test_services.py
@@ -9,25 +9,25 @@ class KeymanagerServiceTestCase(unittest.TestCase):
@defer.inlineCallbacks
def test_keymanager_service_list_call(self):
kms = keymanagerServiceFactory()
- yield kms.do_list_keys({'user': 'user'})
+ yield kms.do_list_keys('user')
assert kms._keymanager.loopback == ['get_all_keys']
@defer.inlineCallbacks
def test_keymanager_service_export_call(self):
kms = keymanagerServiceFactory()
- yield kms.do_export({'user': 'user'}, 'foo@bar')
+ yield kms.do_export('user', 'foo@bar')
assert kms._keymanager.loopback == ['get_key']
@defer.inlineCallbacks
def test_keymanager_service_insert_call(self):
kms = keymanagerServiceFactory()
- yield kms.do_insert({'user': 'user'}, 'foo@bar', 'aaaa')
+ yield kms.do_insert('user', 'foo@bar', 'aaaa')
assert kms._keymanager.loopback == ['put_raw_key', 'get_key']
@defer.inlineCallbacks
def test_keymanager_service_delete_call(self):
kms = keymanagerServiceFactory()
- yield kms.do_delete({'user': 'user'}, 'foo@bar')
+ yield kms.do_delete('user', 'foo@bar')
assert kms._keymanager.loopback == ['get_key', 'delete_key']
diff --git a/ui/app/lib/bitmask.js b/ui/app/lib/bitmask.js
index 21dbb65..8bcb01f 100644
--- a/ui/app/lib/bitmask.js
+++ b/ui/app/lib/bitmask.js
@@ -265,31 +265,34 @@ var bitmask = function(){
/**
* List all the keys in the keyring
*
+ * @param {string} uid The uid of the keyring.
* @param {boolean} priv Should list private keys?
* If it's not provided the public ones will be listed.
*
* @return {Promise<[KeyObject]>} List of keys in the keyring
*/
- list: function(priv) {
- return call(['keys', 'list', private_str(priv)]);
+ list: function(uid, priv) {
+ return call(['keys', 'list', uid, private_str(priv)]);
},
/**
* Export key
*
+ * @param {string} uid The uid of the keyring.
* @param {string} address The email address of the key
* @param {boolean} priv Should get the private key?
* If it's not provided the public one will be fetched.
*
* @return {Promise<KeyObject>} The key
*/
- exprt: function(address, priv) {
- return call(['keys', 'export', address, private_str(priv)]);
+ exprt: function(uid, address, priv) {
+ return call(['keys', 'export', uid, address, private_str(priv)]);
},
/**
* Insert key
*
+ * @param {string} uid The uid of the keyring.
* @param {string} address The email address of the key
* @param {string} rawkey The key material
* @param {string} validation The validation level of the key
@@ -297,24 +300,25 @@ var bitmask = function(){
*
* @return {Promise<KeyObject>} The key
*/
- insert: function(address, rawkey, validation) {
+ insert: function(uid, address, rawkey, validation) {
if (typeof validation !== 'string') {
validation = 'Fingerprint';
}
- return call(['keys', 'insert', address, validation, rawkey]);
+ return call(['keys', 'insert', uid, address, validation, rawkey]);
},
/**
* Delete a key
*
+ * @param {string} uid The uid of the keyring.
* @param {string} address The email address of the key
* @param {boolean} priv Should get the private key?
* If it's not provided the public one will be deleted.
*
* @return {Promise<KeyObject>} The key
*/
- del: function(address, priv) {
- return call(['keys', 'delete', address, private_str(priv)]);
+ del: function(uid, address, priv) {
+ return call(['keys', 'delete', uid, address, private_str(priv)]);
}
},