From e2d8fe5a6bae25452e82e76e50ee2e05320faee2 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Sun, 1 May 2016 21:50:52 -0300 Subject: [feat] make get_all_keys aware of active addresses - Resolves: #8068 --- changes/next-changelog.txt | 1 + src/leap/keymanager/__init__.py | 21 +------------------ src/leap/keymanager/openpgp.py | 46 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/changes/next-changelog.txt b/changes/next-changelog.txt index 7fad645..91ca8bd 100644 --- a/changes/next-changelog.txt +++ b/changes/next-changelog.txt @@ -11,6 +11,7 @@ I've added a new category `Misc` so we can track doc/style/packaging stuff. Features ~~~~~~~~ - `#8031 `_: Remove support for multiple key types. +- `#8068 `_: make get_all_keys aware of active addresses. - `#1234 `_: Description of the new feature corresponding with issue #1234. - New feature without related issue number. diff --git a/src/leap/keymanager/__init__.py b/src/leap/keymanager/__init__.py index 6420f9a..fdd47c3 100644 --- a/src/leap/keymanager/__init__.py +++ b/src/leap/keymanager/__init__.py @@ -75,9 +75,6 @@ from leap.keymanager.errors import ( InvalidSignature ) from leap.keymanager.validation import ValidationLevels, can_upgrade - -from leap.keymanager.keys import build_key_from_dict -from leap.keymanager.documents import KEYMANAGER_KEY_TAG, TAGS_PRIVATE_INDEX from leap.keymanager.openpgp import OpenPGPScheme __version__ = get_versions()['version'] @@ -428,23 +425,7 @@ class KeyManager(object): :return: A Deferred which fires with a list of all keys in local db. :rtype: Deferred """ - # TODO: should it be based on activedocs? - def build_keys(docs): - return map( - lambda doc: build_key_from_dict(doc.content), - docs) - - # XXX: there is no check that the soledad indexes are ready, as it - # happens with EncryptionScheme. - # The usecases right now are not problematic. This could be solve - # adding a keytype to this funciont and moving the soledad request - # to the EncryptionScheme. - d = self._soledad.get_from_index( - TAGS_PRIVATE_INDEX, - KEYMANAGER_KEY_TAG, - '1' if private else '0') - d.addCallback(build_keys) - return d + return self._openpgp.get_all_keys(private) def gen_key(self): """ diff --git a/src/leap/keymanager/openpgp.py b/src/leap/keymanager/openpgp.py index 08b69f7..8658e9c 100644 --- a/src/leap/keymanager/openpgp.py +++ b/src/leap/keymanager/openpgp.py @@ -42,6 +42,7 @@ from leap.keymanager.keys import ( ) from leap.keymanager.documents import ( init_indexes, + TAGS_PRIVATE_INDEX, TYPE_FINGERPRINT_PRIVATE_INDEX, TYPE_ADDRESS_PRIVATE_INDEX, KEY_UIDS_KEY, @@ -53,6 +54,8 @@ from leap.keymanager.documents import ( KEY_ADDRESS_KEY, KEY_TYPE_KEY, KEYMANAGER_ACTIVE_TYPE, + KEYMANAGER_KEY_TAG, + KEYMANAGER_ACTIVE_TAG, ) @@ -100,7 +103,7 @@ class OpenPGPScheme(object): self._gpgbinary = gpgbinary self.deferred_init = init_indexes(soledad) self.deferred_init.addCallback(self._migrate_documents_schema) - self._wait_indexes("get_key", "put_key") + self._wait_indexes("get_key", "put_key", "get_all_keys") def _migrate_documents_schema(self, _): from leap.keymanager.migrator import KeyDocumentsMigrator @@ -242,6 +245,47 @@ class OpenPGPScheme(object): d.addCallback(build_key) return d + @defer.inlineCallbacks + def get_all_keys(self, private=False): + """ + Return all keys stored in local database. + + :param private: Include private keys + :type private: bool + + :return: A Deferred which fires with a list of all keys in local db. + :rtype: Deferred + """ + HAS_ACTIVE = "has_active" + + active_docs = yield self._soledad.get_from_index( + TAGS_PRIVATE_INDEX, + KEYMANAGER_ACTIVE_TAG, + '1' if private else '0') + key_docs = yield self._soledad.get_from_index( + TAGS_PRIVATE_INDEX, + KEYMANAGER_KEY_TAG, + '1' if private else '0') + + keys = [] + for active in active_docs: + fp = lambda doc: doc.content[KEY_FINGERPRINT_KEY] + fp_keys = filter(lambda k: fp(k) == fp(active), key_docs) + + if len(fp_keys) == 0: + yield self._soledad.delete_doc(active) + continue + elif len(fp_keys) == 1: + key = fp_keys[0] + else: + key = yield self._repair_key_docs(fp_keys) + key.content[HAS_ACTIVE] = True + keys.append(build_key_from_dict(key.content, active.content)) + + unactive_keys = filter(lambda k: HAS_ACTIVE not in k.content, key_docs) + keys += map(lambda k: build_key_from_dict(k.content), unactive_keys) + defer.returnValue(keys) + def parse_key(self, key_data, address=None): """ Parses a key (or key pair) data and returns -- cgit v1.2.3