summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2013-02-09 22:09:03 -0200
committerdrebs <drebs@leap.se>2013-02-09 22:22:15 -0200
commit8a887bb41c56da368fb1410c63da117566374858 (patch)
treea8779207a00640bb32d9b12196f58e2f6d454699
parentbe3a837c912d3dc90386334e5e389813aa77773a (diff)
SQLCipher backend can sync with remote Leap HTTP target.
-rw-r--r--src/leap/soledad/__init__.py5
-rw-r--r--src/leap/soledad/backends/leap_backend.py19
-rw-r--r--src/leap/soledad/backends/sqlcipher.py34
-rw-r--r--src/leap/soledad/tests/test_sqlcipher.py9
4 files changed, 42 insertions, 25 deletions
diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py
index 6893c7a8..e11b8319 100644
--- a/src/leap/soledad/__init__.py
+++ b/src/leap/soledad/__init__.py
@@ -43,7 +43,8 @@ class Soledad(object):
# instantiate u1db
# TODO: verify if secret for sqlcipher should be the same as the one
# for symmetric encryption.
- self._db = sqlcipher.open(self.LOCAL_DB_PATH, True, self._secret)
+ self._db = sqlcipher.open(self.LOCAL_DB_PATH, True, self._secret,
+ soledad=self)
def close(self):
self._db.close()
@@ -213,6 +214,6 @@ class Soledad(object):
Synchronize the local encrypted database with LEAP server.
"""
# TODO: create authentication scheme for sync with server.
- return self._db.sync(url, creds=None, autocreate=True, soledad=self)
+ return self._db.sync(url, creds=None, autocreate=True)
__all__ = ['util']
diff --git a/src/leap/soledad/backends/leap_backend.py b/src/leap/soledad/backends/leap_backend.py
index d3ae6db6..a2208404 100644
--- a/src/leap/soledad/backends/leap_backend.py
+++ b/src/leap/soledad/backends/leap_backend.py
@@ -92,7 +92,15 @@ class LeapDatabase(HTTPDatabase):
def __init__(self, url, document_factory=None, creds=None, soledad=None):
super(LeapDatabase, self).__init__(url, creds=creds)
self._soledad = soledad
- self._factory = LeapDocument
+
+ # wrap soledad in factory
+ def factory(doc_id=None, rev=None, json='{}', has_conflicts=False,
+ encrypted_json=None, syncable=True):
+ return LeapDocument(doc_id=doc_id, rev=rev, json=json,
+ has_conflicts=has_conflicts,
+ encrypted_json=encrypted_json,
+ syncable=syncable, soledad=self._soledad)
+ self.set_document_factory(factory)
@staticmethod
def open_database(url, create):
@@ -115,15 +123,6 @@ class LeapDatabase(HTTPDatabase):
st._creds = self._creds
return st
- def create_doc_from_json(self, content, doc_id=None):
- if doc_id is None:
- doc_id = self._allocate_doc_id()
- res, headers = self._request_json('PUT', ['doc', doc_id], {},
- content, 'application/json')
- new_doc = self._factory(doc_id, res['rev'], content,
- soledad=self._soledad)
- return new_doc
-
class LeapSyncTarget(HTTPSyncTarget):
"""
diff --git a/src/leap/soledad/backends/sqlcipher.py b/src/leap/soledad/backends/sqlcipher.py
index 354fcd31..9108f73a 100644
--- a/src/leap/soledad/backends/sqlcipher.py
+++ b/src/leap/soledad/backends/sqlcipher.py
@@ -31,7 +31,7 @@ from u1db import (
from leap.soledad.backends.leap_backend import LeapDocument
-def open(path, password, create=True, document_factory=None):
+def open(path, password, create=True, document_factory=None, soledad=None):
"""Open a database at the given location.
Will raise u1db.errors.DatabaseDoesNotExist if create=False and the
@@ -45,7 +45,8 @@ def open(path, password, create=True, document_factory=None):
:return: An instance of Database.
"""
return SQLCipherDatabase.open_database(
- path, password, create=create, document_factory=document_factory)
+ path, password, create=create, document_factory=document_factory,
+ soledad=soledad)
class DatabaseIsNotEncrypted(Exception):
@@ -64,14 +65,23 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):
def set_pragma_key(cls, db_handle, key):
db_handle.cursor().execute("PRAGMA key = '%s'" % key)
- def __init__(self, sqlite_file, password, document_factory=None):
+ def __init__(self, sqlite_file, password, document_factory=None,
+ soledad=None):
"""Create a new sqlcipher file."""
self._check_if_db_is_encrypted(sqlite_file)
self._db_handle = dbapi2.connect(sqlite_file)
SQLCipherDatabase.set_pragma_key(self._db_handle, password)
self._real_replica_uid = None
self._ensure_schema()
- self._factory = document_factory or LeapDocument
+ self._soledad = soledad
+
+ def factory(doc_id=None, rev=None, json='{}', has_conflicts=False,
+ encrypted_json=None, syncable=True):
+ return LeapDocument(doc_id=doc_id, rev=rev, json=json,
+ has_conflicts=has_conflicts,
+ encrypted_json=encrypted_json,
+ syncable=syncable, soledad=self._soledad)
+ self.set_document_factory(factory)
def _check_if_db_is_encrypted(self, sqlite_file):
if not os.path.exists(sqlite_file):
@@ -86,7 +96,8 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):
pass
@classmethod
- def _open_database(cls, sqlite_file, password, document_factory=None):
+ def _open_database(cls, sqlite_file, password, document_factory=None,
+ soledad=None):
if not os.path.isfile(sqlite_file):
raise errors.DatabaseDoesNotExist()
tries = 2
@@ -108,14 +119,16 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):
tries -= 1
time.sleep(cls.WAIT_FOR_PARALLEL_INIT_HALF_INTERVAL)
return SQLCipherDatabase._sqlite_registry[v](
- sqlite_file, password, document_factory=document_factory)
+ sqlite_file, password, document_factory=document_factory,
+ soledad=soledad)
@classmethod
def open_database(cls, sqlite_file, password, create, backend_cls=None,
- document_factory=None):
+ document_factory=None, soledad=None):
try:
return cls._open_database(sqlite_file, password,
- document_factory=document_factory)
+ document_factory=document_factory,
+ soledad=soledad)
except errors.DatabaseDoesNotExist:
if not create:
raise
@@ -123,9 +136,10 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):
# default is SQLCipherPartialExpandDatabase
backend_cls = SQLCipherDatabase
return backend_cls(sqlite_file, password,
- document_factory=document_factory)
+ document_factory=document_factory,
+ soledad=soledad)
- def sync(self, url, creds=None, autocreate=True, soledad=None):
+ def sync(self, url, creds=None, autocreate=True):
"""
Synchronize encrypted documents with remote replica exposed at url.
"""
diff --git a/src/leap/soledad/tests/test_sqlcipher.py b/src/leap/soledad/tests/test_sqlcipher.py
index 38ad09ed..09b76b82 100644
--- a/src/leap/soledad/tests/test_sqlcipher.py
+++ b/src/leap/soledad/tests/test_sqlcipher.py
@@ -236,7 +236,8 @@ class TestSQLCipherPartialExpandDatabase(
db2 = SQLCipherDatabase._open_database(
path, PASSWORD,
document_factory=TestAlternativeDocument)
- self.assertEqual(TestAlternativeDocument, db2._factory)
+ doc = db2.create_doc({})
+ self.assertTrue(isinstance(doc, LeapDocument))
def test_open_database_existing(self):
temp_dir = self.createTempDir(prefix='u1db-test-')
@@ -252,7 +253,8 @@ class TestSQLCipherPartialExpandDatabase(
db2 = SQLCipherDatabase.open_database(
path, PASSWORD, create=False,
document_factory=TestAlternativeDocument)
- self.assertEqual(TestAlternativeDocument, db2._factory)
+ doc = db2.create_doc({})
+ self.assertTrue(isinstance(doc, LeapDocument))
def test_create_database_initializes_schema(self):
# This test had to be cloned because our implementation of SQLCipher
@@ -304,7 +306,8 @@ class SQLCipherOpen(test_open.TestU1DBOpen):
db = u1db_open(self.db_path, password=PASSWORD, create=True,
document_factory=TestAlternativeDocument)
self.addCleanup(db.close)
- self.assertEqual(TestAlternativeDocument, db._factory)
+ doc = db.create_doc({})
+ self.assertTrue(isinstance(doc, LeapDocument))
def test_open_existing(self):
db = SQLCipherDatabase(self.db_path, PASSWORD)