diff options
| -rw-r--r-- | src/leap/soledad/__init__.py | 6 | ||||
| -rw-r--r-- | src/leap/soledad/backends/couch.py | 89 | ||||
| -rw-r--r-- | src/leap/soledad/tests/test_crypto.py | 6 | 
3 files changed, 64 insertions, 37 deletions
| diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py index d030c20c..12de0bba 100644 --- a/src/leap/soledad/__init__.py +++ b/src/leap/soledad/__init__.py @@ -241,9 +241,11 @@ class Soledad(object):          if secret_path is not None:              self._config._config_checker.config['secret_path'] = secret_path          if local_db_path is not None: -            self._config._config_checker.config['local_db_path'] = local_db_path +            self._config._config_checker.config['local_db_path'] = \ +                local_db_path          if shared_db_url is not None: -            self._config._config_checker.config['shared_db_url'] = shared_db_url +            self._config._config_checker.config['shared_db_url'] = \ +                shared_db_url      def _init_dirs(self):          """ diff --git a/src/leap/soledad/backends/couch.py b/src/leap/soledad/backends/couch.py index ad8d10e3..95090510 100644 --- a/src/leap/soledad/backends/couch.py +++ b/src/leap/soledad/backends/couch.py @@ -29,7 +29,10 @@ except ImportError:  from base64 import b64encode, b64decode  from u1db import errors -from u1db.sync import LocalSyncTarget +from u1db.sync import ( +    LocalSyncTarget, +    Synchronizer, +)  from u1db.backends.inmemory import InMemoryIndex  from u1db.remote.server_state import ServerState  from u1db.errors import DatabaseDoesNotExist @@ -55,6 +58,17 @@ class CouchDatabase(ObjectStoreDatabase):      A U1DB backend that uses Couch as its persistence layer.      """ +    U1DB_TRANSACTION_LOG_KEY = 'transaction_log' +    U1DB_CONFLICTS_KEY = 'conflicts' +    U1DB_OTHER_GENERATIONS_KEY = 'other_generations' +    U1DB_INDEXES_KEY = 'indexes' +    U1DB_REPLICA_UID_KEY = 'replica_uid' + +    COUCH_ID_KEY = '_id' +    COUCH_REV_KEY = '_rev' +    COUCH_U1DB_ATTACHMENT_KEY = 'u1db_json' +    COUCH_U1DB_REV_KEY = 'u1db_rev' +      @classmethod      def open_database(cls, url, create):          """ @@ -143,9 +157,11 @@ class CouchDatabase(ObjectStoreDatabase):              has_conflicts = self._has_conflicts(doc_id)          doc = self._factory(              doc_id=doc_id, -            rev=cdoc['u1db_rev'], +            rev=cdoc[self.COUCH_U1DB_REV_KEY],              has_conflicts=has_conflicts) -        contents = self._database.get_attachment(cdoc, 'u1db_json') +        contents = self._database.get_attachment( +            cdoc, +            self.COUCH_U1DB_ATTACHMENT_KEY)          if contents:              doc.content = json.loads(contents.read())          else: @@ -193,21 +209,24 @@ class CouchDatabase(ObjectStoreDatabase):          """          # prepare couch's Document          cdoc = CouchDocument() -        cdoc['_id'] = doc.doc_id +        cdoc[self.COUCH_ID_KEY] = doc.doc_id          # we have to guarantee that couch's _rev is consistent          old_cdoc = self._database.get(doc.doc_id)          if old_cdoc is not None: -            cdoc['_rev'] = old_cdoc['_rev'] +            cdoc[self.COUCH_REV_KEY] = old_cdoc[self.COUCH_REV_KEY]          # store u1db's rev -        cdoc['u1db_rev'] = doc.rev +        cdoc[self.COUCH_U1DB_REV_KEY] = doc.rev          # save doc in db          self._database.save(cdoc)          # store u1db's content as json string          if not doc.is_tombstone(): -            self._database.put_attachment(cdoc, doc.get_json(), -                                          filename='u1db_json') +            self._database.put_attachment( +                cdoc, doc.get_json(), +                filename=self.COUCH_U1DB_ATTACHMENT_KEY)          else: -            self._database.delete_attachment(cdoc, 'u1db_json') +            self._database.delete_attachment( +                cdoc, +                self.COUCH_U1DB_ATTACHMENT_KEY)      def get_sync_target(self):          """ @@ -273,7 +292,6 @@ class CouchDatabase(ObjectStoreDatabase):          @return: The local generation before the synchronisation was performed.          @rtype: int          """ -        from u1db.sync import Synchronizer          return Synchronizer(self, CouchSyncTarget(url, creds=creds)).sync(              autocreate=autocreate) @@ -300,11 +318,11 @@ class CouchDatabase(ObjectStoreDatabase):          # TODO: prevent user from overwriting a document with the same doc_id          # as this one.          doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID) -        doc.content = {'transaction_log': [], -                       'conflicts': b64encode(json.dumps({})), -                       'other_generations': {}, -                       'indexes': b64encode(json.dumps({})), -                       'replica_uid': self._replica_uid} +        doc.content = {self.U1DB_TRANSACTION_LOG_KEY: [], +                       self.U1DB_CONFLICTS_KEY: b64encode(json.dumps({})), +                       self.U1DB_OTHER_GENERATIONS_KEY: {}, +                       self.U1DB_INDEXES_KEY: b64encode(json.dumps({})), +                       self.U1DB_REPLICA_UID_KEY: self._replica_uid}          self._put_doc(doc)      def _fetch_u1db_data(self): @@ -315,18 +333,19 @@ class CouchDatabase(ObjectStoreDatabase):          """          # retrieve u1db data from couch db          cdoc = self._database.get(self.U1DB_DATA_DOC_ID) -        jsonstr = self._database.get_attachment(cdoc, 'u1db_json').read() +        jsonstr = self._database.get_attachment( +            cdoc, self.COUCH_U1DB_ATTACHMENT_KEY).read()          content = json.loads(jsonstr)          # set u1db database info -        #self._sync_log = content['sync_log'] -        self._transaction_log = content['transaction_log'] -        self._conflicts = json.loads(b64decode(content['conflicts'])) -        self._other_generations = content['other_generations'] +        self._transaction_log = content[self.U1DB_TRANSACTION_LOG_KEY] +        self._conflicts = json.loads( +            b64decode(content[self.U1DB_CONFLICTS_KEY])) +        self._other_generations = content[self.U1DB_OTHER_GENERATIONS_KEY]          self._indexes = self._load_indexes_from_json( -            b64decode(content['indexes'])) -        self._replica_uid = content['replica_uid'] +            b64decode(content[self.U1DB_INDEXES_KEY])) +        self._replica_uid = content[self.U1DB_REPLICA_UID_KEY]          # save couch _rev -        self._couch_rev = cdoc['_rev'] +        self._couch_rev = cdoc[self.COUCH_REV_KEY]      def _store_u1db_data(self):          """ @@ -336,21 +355,25 @@ class CouchDatabase(ObjectStoreDatabase):          """          doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID)          doc.content = { -            'transaction_log': self._transaction_log, +            self.U1DB_TRANSACTION_LOG_KEY: self._transaction_log,              # Here, the b64 encode ensures that document content              # does not cause strange behaviour in couchdb because              # of encoding. -            'conflicts': b64encode(json.dumps(self._conflicts)), -            'other_generations': self._other_generations, -            'indexes': b64encode(self._dump_indexes_as_json()), -            'replica_uid': self._replica_uid, -            '_rev': self._couch_rev} +            self.U1DB_CONFLICTS_KEY: b64encode(json.dumps(self._conflicts)), +            self.U1DB_OTHER_GENERATIONS_KEY: self._other_generations, +            self.U1DB_INDEXES_KEY: b64encode(self._dump_indexes_as_json()), +            self.U1DB_REPLICA_UID_KEY: self._replica_uid, +            self.COUCH_REV_KEY: self._couch_rev}          self._put_doc(doc)      #-------------------------------------------------------------------------      # Couch specific methods      #------------------------------------------------------------------------- +    INDEX_NAME_KEY = 'name' +    INDEX_DEFINITION_KEY = 'definition' +    INDEX_VALUES_KEY = 'values' +      def delete_database(self):          """          Delete a U1DB CouchDB database. @@ -364,7 +387,7 @@ class CouchDatabase(ObjectStoreDatabase):          indexes = {}          for name, idx in self._indexes.iteritems():              indexes[name] = {} -            for attr in ['name', 'definition', 'values']: +            for attr in [INDEX_NAME_KEY, INDEX_DEFINITION_KEY, INDEX_VALUES_KEY]:                  indexes[name][attr] = getattr(idx, '_' + attr)          return json.dumps(indexes) @@ -381,8 +404,8 @@ class CouchDatabase(ObjectStoreDatabase):          """          dict = {}          for name, idx_dict in json.loads(indexes).iteritems(): -            idx = InMemoryIndex(name, idx_dict['definition']) -            idx._values = idx_dict['values'] +            idx = InMemoryIndex(name, idx_dict[INDEX_DEFINITION_KEY]) +            idx._values = idx_dict[INDEX_VALUES_KEY]              dict[name] = idx          return dict @@ -425,7 +448,6 @@ class CouchServerState(ServerState):          @return: The CouchDatabase object and the replica uid.          @rtype: (CouchDatabase, str)          """ -        from leap.soledad.backends.couch import CouchDatabase          db = CouchDatabase.open_database(self.couch_url + '/' + dbname,                                           create=True)          return db, db._replica_uid @@ -437,5 +459,4 @@ class CouchServerState(ServerState):          @param dbname: The name of the database to delete.          @type dbname: str          """ -        from leap.soledad.backends.couch import CouchDatabase          CouchDatabase.delete_database(self.couch_url + '/' + dbname) diff --git a/src/leap/soledad/tests/test_crypto.py b/src/leap/soledad/tests/test_crypto.py index 101b5d83..322be622 100644 --- a/src/leap/soledad/tests/test_crypto.py +++ b/src/leap/soledad/tests/test_crypto.py @@ -48,7 +48,11 @@ from leap.soledad.tests import (      KEY_FINGERPRINT,      PRIVATE_KEY,  ) -from leap.soledad.tests.u1db_tests import simple_doc, nested_doc, TestCaseWithServer +from leap.soledad.tests.u1db_tests import ( +    simple_doc, +    nested_doc, +    TestCaseWithServer, +)  from leap.soledad.tests.test_leap_backend import make_leap_document_for_test  from leap.soledad.backends.couch import CouchServerState | 
