summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2013-01-28 16:46:44 -0200
committerdrebs <drebs@leap.se>2013-01-28 16:46:44 -0200
commitb25360e22173a56e468b0285bae616491a1b67ca (patch)
tree436789bd977ec121e8ace28ae2ec97eb227ba21a
parent0a4548d55b22b21d5d54e88a0cd1e5b118b867f7 (diff)
Add CouchServerState for serving Soledad as WSGI app.
-rw-r--r--__init__.py5
-rw-r--r--backends/couch.py53
-rw-r--r--backends/objectstore.py9
3 files changed, 62 insertions, 5 deletions
diff --git a/__init__.py b/__init__.py
index c83627f0..2ed1a369 100644
--- a/__init__.py
+++ b/__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/backends/couch.py b/backends/couch.py
index c8dadfa8..56b12574 100644
--- a/backends/couch.py
+++ b/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/backends/objectstore.py b/backends/objectstore.py
index 588fc7a1..199107af 100644
--- a/backends/objectstore.py
+++ b/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()