From eba89fb1d16b33fa65b49bbf7cc0109f4d4a6a65 Mon Sep 17 00:00:00 2001 From: drebs Date: Mon, 28 Jan 2013 16:46:44 -0200 Subject: Add CouchServerState for serving Soledad as WSGI app. --- src/leap/soledad/__init__.py | 5 ++- src/leap/soledad/backends/couch.py | 53 ++++++++++++++++++++++++++++++++ src/leap/soledad/backends/objectstore.py | 9 ++++-- 3 files changed, 62 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py index c83627f0..2ed1a369 100644 --- a/src/leap/soledad/__init__.py +++ b/src/leap/soledad/__init__.py @@ -8,7 +8,6 @@ import random import hmac from leap.soledad.backends import sqlcipher from leap.soledad.util import GPGWrapper -import util class Soledad(object): @@ -28,7 +27,7 @@ class Soledad(object): os.makedirs(self.PREFIX) if not gpghome: gpghome = self.GNUPG_HOME - self._gpg = util.GPGWrapper(gpghome=gpghome) + self._gpg = GPGWrapper(gpghome=gpghome) # load/generate OpenPGP keypair if not self._has_openpgp_keypair(): self._gen_openpgp_keypair() @@ -64,7 +63,7 @@ class Soledad(object): try: with open(self.SECRET_PATH) as f: self._secret = str(self._gpg.decrypt(f.read())) - except IOError as e: + except IOError: raise IOError('Failed to open secret file %s.' % self.SECRET_PATH) def _gen_secret(self): diff --git a/src/leap/soledad/backends/couch.py b/src/leap/soledad/backends/couch.py index c8dadfa8..56b12574 100644 --- a/src/leap/soledad/backends/couch.py +++ b/src/leap/soledad/backends/couch.py @@ -1,10 +1,16 @@ +# general imports import uuid from base64 import b64encode, b64decode +import re +# u1db from u1db import errors from u1db.sync import LocalSyncTarget from u1db.backends.inmemory import InMemoryIndex +from u1db.remote.server_state import ServerState +# couchdb from couchdb.client import Server, Document as CouchDocument from couchdb.http import ResourceNotFound +# leap from leap.soledad.backends.objectstore import ObjectStore from leap.soledad.backends.leap_backend import LeapDocument @@ -14,9 +20,29 @@ except ImportError: import json # noqa +class InvalidURLError(Exception): + pass + + class CouchDatabase(ObjectStore): """A U1DB implementation that uses Couch as its persistence layer.""" + @classmethod + def open_database(cls, url, create): + # get database from url + m = re.match('(.*)/([^/]+)$', url) + if not m: + raise InvalidURLError + url = m.group(1) + dbname = m.group(2) + server = Server(url=url) + try: + server[dbname] + except ResourceNotFound: + if not create: + raise + return cls(url, dbname) + def __init__(self, url, database, replica_uid=None, full_commit=True, session=None): """Create a new Couch data container.""" @@ -215,3 +241,30 @@ class CouchSyncTarget(LocalSyncTarget): self._db._set_replica_gen_and_trans_id( source_replica_uid, source_replica_generation, source_replica_transaction_id) + + +class CouchServerState(ServerState): + + def open_database(self, path): + """ + Open a database at the given location. + """ + return CouchDatabase.open_database(path, create=False) + + def check_database(self, path): + """ + Check if the database at the given location exists. + """ + db = self.open_database(path) + db.close() + + def ensure_database(self, path): + """Ensure database at the given location.""" + db = CouchDatabase.open_database(path, + create=True) + return db, db._replica_uid + + def delete_database(self, path): + """Delete database at the given location.""" + db = CouchDatabase.open_database(path) + db.delete_database() diff --git a/src/leap/soledad/backends/objectstore.py b/src/leap/soledad/backends/objectstore.py index 588fc7a1..199107af 100644 --- a/src/leap/soledad/backends/objectstore.py +++ b/src/leap/soledad/backends/objectstore.py @@ -7,8 +7,13 @@ class ObjectStore(InMemoryDatabase): A backend for storing u1db data in an object store. """ - def __init__(self, replica_uid=None): - super(ObjectStore, self).__init__(replica_uid) + @classmethod + def open_database(cls, url, create, document_factory=None): + raise NotImplementedError(cls.open_database) + + def __init__(self, replica_uid=None, document_factory=None): + super(ObjectStore, self).__init__(replica_uid, + document_factory=document_factory) # sync data in memory with data in object store if not self._get_doc(self.U1DB_DATA_DOC_ID): self._init_u1db_data() -- cgit v1.2.3