summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Touceda <chiiph@leap.se>2013-06-21 11:58:43 -0300
committerTomas Touceda <chiiph@leap.se>2013-06-21 11:58:43 -0300
commitd4ea5ac0e78aff6a9224073b4096aa9ad52d4382 (patch)
tree6d803596fe08450a678e39210eb6c2fc9a6db9a0
parent194ff4c40047462e112737a74968ec21a75bfba7 (diff)
parenteb4d19190cd4b726613a04bae534c2f1b89c7183 (diff)
Merge remote-tracking branch 'drebs/feature/2616-separate-soledad-into-client-and-server-2' into develop
-rw-r--r--changes/bug_all_backends3
-rw-r--r--changes/bug_modifiable_timeout3
-rw-r--r--changes/feature_split-soledad-client-and-server1
-rw-r--r--soledad/setup.py (renamed from setup.py)20
-rw-r--r--soledad/src/leap/__init__.py (renamed from src/leap/__init__.py)0
-rw-r--r--soledad/src/leap/soledad/__init__.py (renamed from src/leap/soledad/__init__.py)40
-rw-r--r--soledad/src/leap/soledad/auth.py (renamed from src/leap/soledad/auth.py)0
-rw-r--r--soledad/src/leap/soledad/backends/__init__.py0
-rw-r--r--soledad/src/leap/soledad/backends/leap_backend.py73
-rw-r--r--soledad/src/leap/soledad/crypto.py (renamed from src/leap/soledad/crypto.py)2
-rw-r--r--soledad/src/leap/soledad/document.py111
-rw-r--r--soledad/src/leap/soledad/shared_db.py (renamed from src/leap/soledad/shared_db.py)0
-rw-r--r--soledad/src/leap/soledad/sqlcipher.py (renamed from src/leap/soledad/backends/sqlcipher.py)8
-rw-r--r--soledad/src/leap/soledad/target.py (renamed from src/leap/soledad/backends/leap_backend.py)103
-rw-r--r--soledad/src/leap/soledad/tests/__init__.py (renamed from src/leap/soledad/tests/__init__.py)16
-rw-r--r--soledad/src/leap/soledad/tests/couchdb.ini.template (renamed from src/leap/soledad/tests/couchdb.ini.template)0
-rw-r--r--soledad/src/leap/soledad/tests/test_couch.py (renamed from src/leap/soledad/tests/test_couch.py)9
-rw-r--r--soledad/src/leap/soledad/tests/test_crypto.py (renamed from src/leap/soledad/tests/test_crypto.py)54
-rw-r--r--soledad/src/leap/soledad/tests/test_server.py (renamed from src/leap/soledad/tests/test_server.py)22
-rw-r--r--soledad/src/leap/soledad/tests/test_soledad.py (renamed from src/leap/soledad/tests/test_soledad.py)14
-rw-r--r--soledad/src/leap/soledad/tests/test_sqlcipher.py (renamed from src/leap/soledad/tests/test_sqlcipher.py)28
-rw-r--r--soledad/src/leap/soledad/tests/test_target.py (renamed from src/leap/soledad/tests/test_leap_backend.py)62
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/README (renamed from src/leap/soledad/tests/u1db_tests/README)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/__init__.py (renamed from src/leap/soledad/tests/u1db_tests/__init__.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_backends.py (renamed from src/leap/soledad/tests/u1db_tests/test_backends.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_document.py (renamed from src/leap/soledad/tests/u1db_tests/test_document.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_http_app.py (renamed from src/leap/soledad/tests/u1db_tests/test_http_app.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_http_client.py (renamed from src/leap/soledad/tests/u1db_tests/test_http_client.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_http_database.py (renamed from src/leap/soledad/tests/u1db_tests/test_http_database.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_https.py (renamed from src/leap/soledad/tests/u1db_tests/test_https.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_open.py (renamed from src/leap/soledad/tests/u1db_tests/test_open.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_remote_sync_target.py (renamed from src/leap/soledad/tests/u1db_tests/test_remote_sync_target.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_sqlite_backend.py (renamed from src/leap/soledad/tests/u1db_tests/test_sqlite_backend.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/test_sync.py (renamed from src/leap/soledad/tests/u1db_tests/test_sync.py)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/testing-certs/Makefile (renamed from src/leap/soledad/tests/u1db_tests/testing-certs/Makefile)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/testing-certs/cacert.pem (renamed from src/leap/soledad/tests/u1db_tests/testing-certs/cacert.pem)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/testing-certs/testing.cert (renamed from src/leap/soledad/tests/u1db_tests/testing-certs/testing.cert)0
-rw-r--r--soledad/src/leap/soledad/tests/u1db_tests/testing-certs/testing.key (renamed from src/leap/soledad/tests/u1db_tests/testing-certs/testing.key)0
-rw-r--r--soledad_server/pkg/soledad (renamed from pkg/soledad)0
-rw-r--r--soledad_server/setup.py79
-rw-r--r--soledad_server/src/leap/__init__.py6
-rw-r--r--soledad_server/src/leap/soledad_server/__init__.py (renamed from src/leap/soledad/server.py)11
-rw-r--r--soledad_server/src/leap/soledad_server/couch.py (renamed from src/leap/soledad/backends/couch.py)8
-rw-r--r--soledad_server/src/leap/soledad_server/objectstore.py (renamed from src/leap/soledad/backends/objectstore.py)0
-rw-r--r--src/leap/soledad/backends/__init__.py36
45 files changed, 423 insertions, 286 deletions
diff --git a/changes/bug_all_backends b/changes/bug_all_backends
new file mode 100644
index 00000000..bfb7253d
--- /dev/null
+++ b/changes/bug_all_backends
@@ -0,0 +1,3 @@
+ o Do not list the backends in the __init__'s __all__ to allow not
+ supporting couch on the client side until the code is diveded into
+ client and server. \ No newline at end of file
diff --git a/changes/bug_modifiable_timeout b/changes/bug_modifiable_timeout
new file mode 100644
index 00000000..be690d5a
--- /dev/null
+++ b/changes/bug_modifiable_timeout
@@ -0,0 +1,3 @@
+ o Database request have default timeout too high, a
+ soledad.SOLEDAD_TIMEOUT variable has been added in order to have
+ more control over this. Fixes #2713 \ No newline at end of file
diff --git a/changes/feature_split-soledad-client-and-server b/changes/feature_split-soledad-client-and-server
new file mode 100644
index 00000000..0abab836
--- /dev/null
+++ b/changes/feature_split-soledad-client-and-server
@@ -0,0 +1 @@
+ o Split soledad client and server into two different packages.
diff --git a/setup.py b/soledad/setup.py
index b989f48a..f0d070da 100644
--- a/setup.py
+++ b/soledad/setup.py
@@ -16,7 +16,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import os
from setuptools import (
setup,
find_packages
@@ -24,20 +23,17 @@ from setuptools import (
install_requirements = [
- 'configparser',
- 'couchdb',
'pysqlcipher',
+ 'pysqlite', # TODO: this should not be a dep, see #2945
'simplejson',
- 'twisted>=12.0.0', # TODO: maybe we just want twisted-web?
'oauth', # this is not strictly needed by us, but we need it
# until u1db adds it to its release as a dep.
'u1db',
- 'requests',
'six==1.1.0',
'scrypt',
- 'routes',
'pyxdg',
'pycrypto',
+ 'pyOpenSSL',
]
@@ -46,15 +42,10 @@ tests_requirements = [
'nose2',
'testscenarios',
'leap.common',
+ 'leap.soledad_server',
]
-if os.environ.get('VIRTUAL_ENV', None):
- data_files = None
-else:
- # XXX this should go only for linux/mac
- data_files = [("/etc/init.d/", ["pkg/soledad"])]
-
trove_classifiers = (
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
@@ -88,9 +79,6 @@ setup(
test_suite='leap.soledad.tests',
install_requires=install_requirements,
tests_require=tests_requirements,
- data_files=data_files,
classifiers=trove_classifiers,
- extras_require={
- 'signaling': ['leap.common'],
- }
+ extras_require={'signaling': ['leap.common']},
)
diff --git a/src/leap/__init__.py b/soledad/src/leap/__init__.py
index f48ad105..f48ad105 100644
--- a/src/leap/__init__.py
+++ b/soledad/src/leap/__init__.py
diff --git a/src/leap/soledad/__init__.py b/soledad/src/leap/soledad/__init__.py
index ea3f676b..2e1155f9 100644
--- a/src/leap/soledad/__init__.py
+++ b/soledad/src/leap/soledad/__init__.py
@@ -134,13 +134,12 @@ except ImportError:
pass
-from leap.soledad.backends import sqlcipher
-from leap.soledad.backends.leap_backend import (
- LeapDocument,
- LeapSyncTarget,
+from leap.soledad.document import SoledadDocument
+from leap.soledad.sqlcipher import (
+ open as sqlcipher_open,
+ SQLCipherDatabase,
)
-
-from leap.soledad import shared_db
+from leap.soledad.target import SoledadSyncTarget
from leap.soledad.shared_db import SoledadSharedDatabase
from leap.soledad.crypto import SoledadCrypto
@@ -418,11 +417,11 @@ class Soledad(object):
secret[salt_start:salt_end], # the salt
buflen=32, # we need a key with 256 bits (32 bytes)
)
- self._db = sqlcipher.open(
+ self._db = sqlcipher_open(
self._local_db_path,
binascii.b2a_hex(key), # sqlcipher only accepts the hex version
create=True,
- document_factory=LeapDocument,
+ document_factory=SoledadDocument,
crypto=self._crypto,
raw_key=True)
@@ -432,7 +431,7 @@ class Soledad(object):
"""
if hasattr(self, '_db') and isinstance(
self._db,
- sqlcipher.SQLCipherDatabase):
+ SQLCipherDatabase):
self._db.close()
def __del__(self):
@@ -634,7 +633,7 @@ class Soledad(object):
database.
@return: a document with encrypted key material in its contents
- @rtype: LeapDocument
+ @rtype: SoledadDocument
"""
signal(SOLEDAD_DOWNLOADING_KEYS, self._uuid)
db = self._shared_db()
@@ -661,7 +660,7 @@ class Soledad(object):
# try to get secrets doc from server, otherwise create it
doc = self._get_secrets_from_shared_db()
if doc is None:
- doc = LeapDocument(doc_id=self._uuid_hash())
+ doc = SoledadDocument(doc_id=self._uuid_hash())
# fill doc with encrypted secrets
doc.content = self.export_recovery_document(include_uuid=False)
# upload secrets to server
@@ -682,7 +681,7 @@ class Soledad(object):
Update a document in the local encrypted database.
@param doc: the document to update
- @type doc: LeapDocument
+ @type doc: SoledadDocument
@return: the new revision identifier for the document
@rtype: str
@@ -694,7 +693,7 @@ class Soledad(object):
Delete a document from the local encrypted database.
@param doc: the document to delete
- @type doc: LeapDocument
+ @type doc: SoledadDocument
@return: the new revision identifier for the document
@rtype: str
@@ -713,7 +712,7 @@ class Soledad(object):
@type include_deleted: bool
@return: the document object or None
- @rtype: LeapDocument
+ @rtype: SoledadDocument
"""
return self._db.get_doc(doc_id, include_deleted=include_deleted)
@@ -758,7 +757,7 @@ class Soledad(object):
@type doc_id: str
@return: the new document
- @rtype: LeapDocument
+ @rtype: SoledadDocument
"""
return self._db.create_doc(content, doc_id=doc_id)
@@ -777,7 +776,7 @@ class Soledad(object):
@param doc_id: An optional identifier specifying the document id.
@type doc_id:
@return: The new cocument
- @rtype: LeapDocument
+ @rtype: SoledadDocument
"""
return self._db.create_doc_from_json(json, doc_id=doc_id)
@@ -903,7 +902,7 @@ class Soledad(object):
Mark a document as no longer conflicted.
@param doc: a document with the new content to be inserted.
- @type doc: LeapDocument
+ @type doc: SoledadDocument
@param conflicted_doc_revs: a list of revisions that the new content
supersedes.
@type conflicted_doc_revs: list
@@ -937,7 +936,7 @@ class Soledad(object):
@return: Whether remote replica and local replica differ.
@rtype: bool
"""
- target = LeapSyncTarget(url, creds=self._creds, crypto=self._crypto)
+ target = SoledadSyncTarget(url, creds=self._creds, crypto=self._crypto)
info = target.get_sync_info(self._db._get_replica_uid())
# compare source generation with target's last known source generation
if self._db._get_generation() != info[4]:
@@ -1073,6 +1072,9 @@ class Soledad(object):
# Monkey patching u1db to be able to provide a custom SSL cert
#-----------------------------------------------------------------------------
+# We need a more reasonable timeout (in seconds)
+SOLEDAD_TIMEOUT = 10
+
class VerifiedHTTPSConnection(httplib.HTTPSConnection):
"""HTTPSConnection verifying server side certificates."""
# derived from httplib.py
@@ -1080,7 +1082,7 @@ class VerifiedHTTPSConnection(httplib.HTTPSConnection):
def connect(self):
"Connect to a host on a given (SSL) port."
sock = socket.create_connection((self.host, self.port),
- self.timeout, self.source_address)
+ SOLEDAD_TIMEOUT, self.source_address)
if self._tunnel_host:
self.sock = sock
self._tunnel()
diff --git a/src/leap/soledad/auth.py b/soledad/src/leap/soledad/auth.py
index 8c093099..8c093099 100644
--- a/src/leap/soledad/auth.py
+++ b/soledad/src/leap/soledad/auth.py
diff --git a/soledad/src/leap/soledad/backends/__init__.py b/soledad/src/leap/soledad/backends/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/soledad/src/leap/soledad/backends/__init__.py
diff --git a/soledad/src/leap/soledad/backends/leap_backend.py b/soledad/src/leap/soledad/backends/leap_backend.py
new file mode 100644
index 00000000..a8d76b67
--- /dev/null
+++ b/soledad/src/leap/soledad/backends/leap_backend.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+# leap_backend.py
+# Copyright (C) 2013 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+"""
+This file exists to provide backwards compatibility with code that uses
+Soledad before the refactor that removed the leap_backend module.
+"""
+
+
+import logging
+import warnings
+
+
+from leap.soledad import document
+from leap.soledad import target
+
+
+logger = logging.getLogger(name=__name__)
+
+
+def warn(oldclass, newclass):
+ """
+ Warns about deprecation of C{oldclass}, which must be substituted by
+ C{newclass}.
+
+ @param oldclass: The class that is deprecated.
+ @type oldclass: type
+ @param newclass: The class that should be used instead.
+ @type newclass: type
+ """
+ message = \
+ "%s is deprecated and will be removed soon. Please use %s instead." \
+ % (str(oldclass), str(newclass))
+ print message
+ logger.warning(message)
+ warnings.warn(message, DeprecationWarning, stacklevel=2)
+
+
+class LeapDocument(document.SoledadDocument):
+ """
+ This class exists to provide backwards compatibility with code that still
+ uses C{leap.soledad.backends.leap_backend.LeapDocument}.
+ """
+
+ def __init__(self, *args, **kwargs):
+ warn(self.__class__, document.SoledadDocument)
+ document.SoledadDocument.__init__(self, *args, **kwargs)
+
+
+class EncryptionSchemes(target.EncryptionSchemes):
+ """
+ This class exists to provide backwards compatibility with code that still
+ uses C{leap.soledad.backends.leap_backend.EncryptionSchemes}.
+ """
+
+ def __init__(self, *args, **kwargs):
+ warn(self.__class__, target.EncryptionSchemes)
+ target.EncryptionSchemes.__init__(self, *args, **kwargs)
diff --git a/src/leap/soledad/crypto.py b/soledad/src/leap/soledad/crypto.py
index be83e4a2..bfad66d1 100644
--- a/src/leap/soledad/crypto.py
+++ b/soledad/src/leap/soledad/crypto.py
@@ -136,7 +136,7 @@ class SoledadCrypto(object):
'Wrong key size: %s (must be 256 bits long).' % len(key))
soledad_assert(
'iv' in kwargs,
- 'AES-256-CTR needs an initial value given as.')
+ 'AES-256-CTR needs an initial value.')
ctr = Counter.new(64, prefix=binascii.a2b_base64(kwargs['iv']))
cipher = AES.new(key=key, mode=AES.MODE_CTR, counter=ctr)
return cipher.decrypt(data)
diff --git a/soledad/src/leap/soledad/document.py b/soledad/src/leap/soledad/document.py
new file mode 100644
index 00000000..cc24b53a
--- /dev/null
+++ b/soledad/src/leap/soledad/document.py
@@ -0,0 +1,111 @@
+# -*- coding: utf-8 -*-
+# document.py
+# Copyright (C) 2013 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+"""
+A Soledad Document is an u1db.Document with lasers.
+"""
+
+
+from u1db import Document
+
+
+#
+# SoledadDocument
+#
+
+class SoledadDocument(Document):
+ """
+ Encryptable and syncable document.
+
+ LEAP Documents can be flagged as syncable or not, so the replicas
+ might not sync every document.
+ """
+
+ def __init__(self, doc_id=None, rev=None, json='{}', has_conflicts=False,
+ syncable=True):
+ """
+ Container for handling an encryptable document.
+
+ @param doc_id: The unique document identifier.
+ @type doc_id: str
+ @param rev: The revision identifier of the document.
+ @type rev: str
+ @param json: The JSON string for this document.
+ @type json: str
+ @param has_conflicts: Boolean indicating if this document has conflicts
+ @type has_conflicts: bool
+ @param syncable: Should this document be synced with remote replicas?
+ @type syncable: bool
+ """
+ Document.__init__(self, doc_id, rev, json, has_conflicts)
+ self._syncable = syncable
+
+ def _get_syncable(self):
+ """
+ Return whether this document is syncable.
+
+ @return: Is this document syncable?
+ @rtype: bool
+ """
+ return self._syncable
+
+ def _set_syncable(self, syncable=True):
+ """
+ Determine if this document should be synced with remote replicas.
+
+ @param syncable: Should this document be synced with remote replicas?
+ @type syncable: bool
+ """
+ self._syncable = syncable
+
+ syncable = property(
+ _get_syncable,
+ _set_syncable,
+ doc="Determine if document should be synced with server."
+ )
+
+ def _get_rev(self):
+ """
+ Get the document revision.
+
+ Returning the revision as string solves the following exception in
+ Twisted web:
+ exceptions.TypeError: Can only pass-through bytes on Python 2
+
+ @return: The document revision.
+ @rtype: str
+ """
+ if self._rev is None:
+ return None
+ return str(self._rev)
+
+ def _set_rev(self, rev):
+ """
+ Set document revision.
+
+ @param rev: The new document revision.
+ @type rev: bytes
+ """
+ self._rev = rev
+
+ rev = property(
+ _get_rev,
+ _set_rev,
+ doc="Wrapper to ensure `doc.rev` is always returned as bytes.")
+
+
diff --git a/src/leap/soledad/shared_db.py b/soledad/src/leap/soledad/shared_db.py
index 33c5c484..33c5c484 100644
--- a/src/leap/soledad/shared_db.py
+++ b/soledad/src/leap/soledad/shared_db.py
diff --git a/src/leap/soledad/backends/sqlcipher.py b/soledad/src/leap/soledad/sqlcipher.py
index d6d62f21..acbeabe6 100644
--- a/src/leap/soledad/backends/sqlcipher.py
+++ b/soledad/src/leap/soledad/sqlcipher.py
@@ -54,7 +54,7 @@ from pysqlcipher import dbapi2
from u1db import (
errors,
)
-from leap.soledad.backends.leap_backend import LeapDocument
+from leap.soledad.document import SoledadDocument
# Monkey-patch u1db.backends.sqlite_backend with pysqlcipher.dbapi2
@@ -169,7 +169,7 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
def factory(doc_id=None, rev=None, json='{}', has_conflicts=False,
syncable=True):
- return LeapDocument(doc_id=doc_id, rev=rev, json=json,
+ return SoledadDocument(doc_id=doc_id, rev=rev, json=json,
has_conflicts=has_conflicts,
syncable=syncable)
self.set_document_factory(factory)
@@ -301,10 +301,10 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
@rtype: int
"""
from u1db.sync import Synchronizer
- from leap.soledad.backends.leap_backend import LeapSyncTarget
+ from leap.soledad.target import SoledadSyncTarget
return Synchronizer(
self,
- LeapSyncTarget(url,
+ SoledadSyncTarget(url,
creds=creds,
crypto=self._crypto)).sync(autocreate=autocreate)
diff --git a/src/leap/soledad/backends/leap_backend.py b/soledad/src/leap/soledad/target.py
index 4d92db37..8b7aa8c7 100644
--- a/src/leap/soledad/backends/leap_backend.py
+++ b/soledad/src/leap/soledad/target.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# leap_backend.py
+# target.py
# Copyright (C) 2013 LEAP
#
# This program is free software: you can redistribute it and/or modify
@@ -27,13 +27,13 @@ import hmac
import binascii
-from u1db import Document
from u1db.remote import utils
from u1db.errors import BrokenSyncStream
from u1db.remote.http_target import HTTPSyncTarget
from leap.soledad import soledad_assert
+from leap.soledad.document import SoledadDocument
from leap.soledad.crypto import (
EncryptionMethods,
UnknownEncryptionMethod,
@@ -96,7 +96,7 @@ class MacMethods(object):
#
-# Crypto utilities for a LeapDocument.
+# Crypto utilities for a SoledadDocument.
#
ENC_JSON_KEY = '_enc_json'
@@ -159,7 +159,7 @@ def encrypt_doc(crypto, doc):
@param crypto: A SoledadCryto instance used to perform the encryption.
@type crypto: leap.soledad.crypto.SoledadCrypto
@param doc: The document with contents to be encrypted.
- @type doc: LeapDocument
+ @type doc: SoledadDocument
@return: The JSON serialization of the dict representing the encrypted
content.
@@ -213,7 +213,7 @@ def decrypt_doc(crypto, doc):
@param crypto: A SoledadCryto instance to perform the encryption.
@type crypto: leap.soledad.crypto.SoledadCrypto
@param doc: The document to be decrypted.
- @type doc: LeapDocument
+ @type doc: SoledadDocument
@return: The JSON serialization of the decrypted content.
@rtype: str
@@ -252,92 +252,11 @@ def decrypt_doc(crypto, doc):
return plainjson
-class LeapDocument(Document):
- """
- Encryptable and syncable document.
-
- LEAP Documents can be flagged as syncable or not, so the replicas
- might not sync every document.
- """
-
- def __init__(self, doc_id=None, rev=None, json='{}', has_conflicts=False,
- syncable=True):
- """
- Container for handling an encryptable document.
-
- @param doc_id: The unique document identifier.
- @type doc_id: str
- @param rev: The revision identifier of the document.
- @type rev: str
- @param json: The JSON string for this document.
- @type json: str
- @param has_conflicts: Boolean indicating if this document has conflicts
- @type has_conflicts: bool
- @param syncable: Should this document be synced with remote replicas?
- @type syncable: bool
- """
- Document.__init__(self, doc_id, rev, json, has_conflicts)
- self._syncable = syncable
-
- def _get_syncable(self):
- """
- Return whether this document is syncable.
-
- @return: Is this document syncable?
- @rtype: bool
- """
- return self._syncable
-
- def _set_syncable(self, syncable=True):
- """
- Determine if this document should be synced with remote replicas.
-
- @param syncable: Should this document be synced with remote replicas?
- @type syncable: bool
- """
- self._syncable = syncable
-
- syncable = property(
- _get_syncable,
- _set_syncable,
- doc="Determine if document should be synced with server."
- )
-
- def _get_rev(self):
- """
- Get the document revision.
-
- Returning the revision as string solves the following exception in
- Twisted web:
- exceptions.TypeError: Can only pass-through bytes on Python 2
-
- @return: The document revision.
- @rtype: str
- """
- if self._rev is None:
- return None
- return str(self._rev)
-
- def _set_rev(self, rev):
- """
- Set document revision.
-
- @param rev: The new document revision.
- @type rev: bytes
- """
- self._rev = rev
-
- rev = property(
- _get_rev,
- _set_rev,
- doc="Wrapper to ensure `doc.rev` is always returned as bytes.")
-
-
#
-# LeapSyncTarget
+# SoledadSyncTarget
#
-class LeapSyncTarget(HTTPSyncTarget, TokenBasedAuth):
+class SoledadSyncTarget(HTTPSyncTarget, TokenBasedAuth):
"""
A SyncTarget that encrypts data before sending and decrypts data after
receiving.
@@ -380,11 +299,11 @@ class LeapSyncTarget(HTTPSyncTarget, TokenBasedAuth):
@staticmethod
def connect(url, crypto=None):
- return LeapSyncTarget(url, crypto=crypto)
+ return SoledadSyncTarget(url, crypto=crypto)
def __init__(self, url, creds=None, crypto=None):
"""
- Initialize the LeapSyncTarget.
+ Initialize the SoledadSyncTarget.
@param url: The url of the target replica to sync with.
@type url: str
@@ -441,7 +360,7 @@ class LeapSyncTarget(HTTPSyncTarget, TokenBasedAuth):
#-------------------------------------------------------------
# if arriving content was symmetrically encrypted, we decrypt
# it.
- doc = LeapDocument(entry['id'], entry['rev'], entry['content'])
+ doc = SoledadDocument(entry['id'], entry['rev'], entry['content'])
if doc.content and ENC_SCHEME_KEY in doc.content:
if doc.content[ENC_SCHEME_KEY] == \
EncryptionSchemes.SYMKEY:
@@ -517,7 +436,7 @@ class LeapSyncTarget(HTTPSyncTarget, TokenBasedAuth):
comma = ','
for doc, gen, trans_id in docs_by_generations:
# skip non-syncable docs
- if isinstance(doc, LeapDocument) and not doc.syncable:
+ if isinstance(doc, SoledadDocument) and not doc.syncable:
continue
#-------------------------------------------------------------
# symmetric encryption of document's contents
diff --git a/src/leap/soledad/tests/__init__.py b/soledad/src/leap/soledad/tests/__init__.py
index 9fec5530..b33f866c 100644
--- a/src/leap/soledad/tests/__init__.py
+++ b/soledad/src/leap/soledad/tests/__init__.py
@@ -8,9 +8,9 @@ from mock import Mock
from leap.soledad import Soledad
+from leap.soledad.document import SoledadDocument
from leap.soledad.crypto import SoledadCrypto
-from leap.soledad.backends.leap_backend import (
- LeapDocument,
+from leap.soledad.target import (
decrypt_doc,
ENC_SCHEME_KEY,
)
@@ -37,9 +37,9 @@ class BaseSoledadTest(BaseLeapTest):
self.email = ADDRESS
# open test dbs
self._db1 = u1db.open(self.db1_file, create=True,
- document_factory=LeapDocument)
+ document_factory=SoledadDocument)
self._db2 = u1db.open(self.db2_file, create=True,
- document_factory=LeapDocument)
+ document_factory=SoledadDocument)
# initialize soledad by hand so we can control keys
self._soledad = self._soledad_instance(user=self.email)
@@ -257,11 +257,3 @@ RZXoH+FTg9UAW87eqU610npOkT6cRaBxaMK/mDtGNdc=
=JTFu
-----END PGP PRIVATE KEY BLOCK-----
"""
-
-__all__ = [
- 'test_couch',
- 'test_encrypted',
- 'test_leap_backend',
- 'test_sqlcipher',
- 'u1db_tests',
-]
diff --git a/src/leap/soledad/tests/couchdb.ini.template b/soledad/src/leap/soledad/tests/couchdb.ini.template
index 7d0316f0..7d0316f0 100644
--- a/src/leap/soledad/tests/couchdb.ini.template
+++ b/soledad/src/leap/soledad/tests/couchdb.ini.template
diff --git a/src/leap/soledad/tests/test_couch.py b/soledad/src/leap/soledad/tests/test_couch.py
index 60a61b71..a84bb46c 100644
--- a/src/leap/soledad/tests/test_couch.py
+++ b/soledad/src/leap/soledad/tests/test_couch.py
@@ -27,14 +27,12 @@ from base64 import b64decode
from leap.common.files import mkdir_p
-from leap.soledad.backends import couch
+from leap.soledad_server import couch
from leap.soledad.tests import u1db_tests as tests
from leap.soledad.tests.u1db_tests import test_backends
from leap.soledad.tests.u1db_tests import test_sync
import simplejson as json
-from leap.soledad.backends.leap_backend import (
- LeapDocument,
-)
+from leap.soledad.document import SoledadDocument
#-----------------------------------------------------------------------------
@@ -185,7 +183,7 @@ def copy_couch_database_for_test(test, db):
def make_document_for_test(test, doc_id, rev, content, has_conflicts=False):
- return LeapDocument(doc_id, rev, content, has_conflicts=has_conflicts)
+ return SoledadDocument(doc_id, rev, content, has_conflicts=has_conflicts)
COUCH_SCENARIOS = [
@@ -318,7 +316,6 @@ class CouchDatabaseSyncTests(test_sync.DatabaseSyncTests, CouchDBTestCase):
self.db2 = None
self.db3 = None
test_sync.DatabaseSyncTests.setUp(self)
- CouchDBTestCase.setUp(self)
def tearDown(self):
self.db and self.db.delete_database()
diff --git a/src/leap/soledad/tests/test_crypto.py b/soledad/src/leap/soledad/tests/test_crypto.py
index 59d20fa7..c727a2ff 100644
--- a/src/leap/soledad/tests/test_crypto.py
+++ b/soledad/src/leap/soledad/tests/test_crypto.py
@@ -33,10 +33,12 @@ from Crypto import Random
from leap.common.testing.basetest import BaseLeapTest
-from leap.soledad import Soledad
-from leap.soledad import crypto
-from leap.soledad.backends import leap_backend
-from leap.soledad.backends.couch import CouchDatabase
+from leap.soledad import (
+ Soledad,
+ crypto,
+ target,
+)
+from leap.soledad.document import SoledadDocument
from leap.soledad.tests import (
BaseSoledadTest,
KEY_FINGERPRINT,
@@ -49,12 +51,6 @@ from leap.soledad.tests.u1db_tests import (
)
-# These will be used in the future for EncryptedCouchSyncTestCase
-#from leap.soledad.tests.test_couch import CouchDBTestCase
-#from leap.soledad.tests.test_leap_backend import make_leap_document_for_test
-#from leap.soledad.backends.couch import CouchServerState
-
-
class EncryptedSyncTestCase(BaseSoledadTest):
"""
Tests that guarantee that data will always be encrypted when syncing.
@@ -65,18 +61,18 @@ class EncryptedSyncTestCase(BaseSoledadTest):
Test encrypting and decrypting documents.
"""
simpledoc = {'key': 'val'}
- doc1 = leap_backend.LeapDocument(doc_id='id')
+ doc1 = SoledadDocument(doc_id='id')
doc1.content = simpledoc
# encrypt doc
- doc1.set_json(leap_backend.encrypt_doc(self._soledad._crypto, doc1))
+ doc1.set_json(target.encrypt_doc(self._soledad._crypto, doc1))
# assert content is different and includes keys
self.assertNotEqual(
simpledoc, doc1.content,
'incorrect document encryption')
- self.assertTrue(leap_backend.ENC_JSON_KEY in doc1.content)
- self.assertTrue(leap_backend.ENC_SCHEME_KEY in doc1.content)
+ self.assertTrue(target.ENC_JSON_KEY in doc1.content)
+ self.assertTrue(target.ENC_SCHEME_KEY in doc1.content)
# decrypt doc
- doc1.set_json(leap_backend.decrypt_doc(self._soledad._crypto, doc1))
+ doc1.set_json(target.decrypt_doc(self._soledad._crypto, doc1))
self.assertEqual(
simpledoc, doc1.content, 'incorrect document encryption')
@@ -161,36 +157,36 @@ class MacAuthTestCase(BaseSoledadTest):
Trying to decrypt a document with wrong MAC should raise.
"""
simpledoc = {'key': 'val'}
- doc = leap_backend.LeapDocument(doc_id='id')
+ doc = SoledadDocument(doc_id='id')
doc.content = simpledoc
# encrypt doc
- doc.set_json(leap_backend.encrypt_doc(self._soledad._crypto, doc))
- self.assertTrue(leap_backend.MAC_KEY in doc.content)
- self.assertTrue(leap_backend.MAC_METHOD_KEY in doc.content)
+ doc.set_json(target.encrypt_doc(self._soledad._crypto, doc))
+ self.assertTrue(target.MAC_KEY in doc.content)
+ self.assertTrue(target.MAC_METHOD_KEY in doc.content)
# mess with MAC
- doc.content[leap_backend.MAC_KEY] = '1234567890ABCDEF'
+ doc.content[target.MAC_KEY] = '1234567890ABCDEF'
# try to decrypt doc
self.assertRaises(
- leap_backend.WrongMac,
- leap_backend.decrypt_doc, self._soledad._crypto, doc)
+ target.WrongMac,
+ target.decrypt_doc, self._soledad._crypto, doc)
def test_decrypt_with_unknown_mac_method_raises(self):
"""
Trying to decrypt a document with unknown MAC method should raise.
"""
simpledoc = {'key': 'val'}
- doc = leap_backend.LeapDocument(doc_id='id')
+ doc = SoledadDocument(doc_id='id')
doc.content = simpledoc
# encrypt doc
- doc.set_json(leap_backend.encrypt_doc(self._soledad._crypto, doc))
- self.assertTrue(leap_backend.MAC_KEY in doc.content)
- self.assertTrue(leap_backend.MAC_METHOD_KEY in doc.content)
+ doc.set_json(target.encrypt_doc(self._soledad._crypto, doc))
+ self.assertTrue(target.MAC_KEY in doc.content)
+ self.assertTrue(target.MAC_METHOD_KEY in doc.content)
# mess with MAC method
- doc.content[leap_backend.MAC_METHOD_KEY] = 'mymac'
+ doc.content[target.MAC_METHOD_KEY] = 'mymac'
# try to decrypt doc
self.assertRaises(
- leap_backend.UnknownMacMethod,
- leap_backend.decrypt_doc, self._soledad._crypto, doc)
+ target.UnknownMacMethod,
+ target.decrypt_doc, self._soledad._crypto, doc)
class SoledadCryptoTestCase(BaseSoledadTest):
diff --git a/src/leap/soledad/tests/test_server.py b/soledad/src/leap/soledad/tests/test_server.py
index 02276d87..490d2fc8 100644
--- a/src/leap/soledad/tests/test_server.py
+++ b/soledad/src/leap/soledad/tests/test_server.py
@@ -29,16 +29,16 @@ import mock
from leap.soledad import Soledad
-from leap.soledad.server import (
+from leap.soledad_server import (
SoledadApp,
SoledadAuthMiddleware,
URLToAuth,
)
-from leap.soledad.backends.couch import (
+from leap.soledad_server.couch import (
CouchServerState,
CouchDatabase,
)
-from leap.soledad.backends import leap_backend
+from leap.soledad import target
from leap.common.testing.basetest import BaseLeapTest
@@ -49,7 +49,7 @@ from leap.soledad.tests.u1db_tests import (
nested_doc,
)
from leap.soledad.tests.test_couch import CouchDBTestCase
-from leap.soledad.tests.test_leap_backend import (
+from leap.soledad.tests.test_target import (
make_token_soledad_app,
make_leap_document_for_test,
token_leap_sync_target,
@@ -336,7 +336,7 @@ class EncryptedSyncTestCase(
self.startServer()
# instantiate soledad and create a document
sol1 = self._soledad_instance(
- # token is verified in test_leap_backend.make_token_soledad_app
+ # token is verified in test_target.make_token_soledad_app
auth_token='auth-token'
)
_, doclist = sol1.get_all_docs()
@@ -358,12 +358,12 @@ class EncryptedSyncTestCase(
self.assertEqual(doc1.doc_id, couchdoc.doc_id)
self.assertEqual(doc1.rev, couchdoc.rev)
self.assertEqual(6, len(couchdoc.content))
- self.assertTrue(leap_backend.ENC_JSON_KEY in couchdoc.content)
- self.assertTrue(leap_backend.ENC_SCHEME_KEY in couchdoc.content)
- self.assertTrue(leap_backend.ENC_METHOD_KEY in couchdoc.content)
- self.assertTrue(leap_backend.ENC_IV_KEY in couchdoc.content)
- self.assertTrue(leap_backend.MAC_KEY in couchdoc.content)
- self.assertTrue(leap_backend.MAC_METHOD_KEY in couchdoc.content)
+ self.assertTrue(target.ENC_JSON_KEY in couchdoc.content)
+ self.assertTrue(target.ENC_SCHEME_KEY in couchdoc.content)
+ self.assertTrue(target.ENC_METHOD_KEY in couchdoc.content)
+ self.assertTrue(target.ENC_IV_KEY in couchdoc.content)
+ self.assertTrue(target.MAC_KEY in couchdoc.content)
+ self.assertTrue(target.MAC_METHOD_KEY in couchdoc.content)
# instantiate soledad with empty db, but with same secrets path
sol2 = self._soledad_instance(prefix='x', auth_token='auth-token')
_, doclist = sol2.get_all_docs()
diff --git a/src/leap/soledad/tests/test_soledad.py b/soledad/src/leap/soledad/tests/test_soledad.py
index 8062a337..281b7a0f 100644
--- a/src/leap/soledad/tests/test_soledad.py
+++ b/soledad/src/leap/soledad/tests/test_soledad.py
@@ -36,12 +36,10 @@ from leap.soledad.tests import (
)
from leap import soledad
from leap.soledad import Soledad
+from leap.soledad.document import SoledadDocument
from leap.soledad.crypto import SoledadCrypto
from leap.soledad.shared_db import SoledadSharedDatabase
-from leap.soledad.backends.leap_backend import (
- LeapDocument,
- LeapSyncTarget,
-)
+from leap.soledad.target import SoledadSyncTarget
class AuxMethodsTestCase(BaseSoledadTest):
@@ -63,7 +61,7 @@ class AuxMethodsTestCase(BaseSoledadTest):
sol._gen_secret()
sol._load_secrets()
sol._init_db()
- from leap.soledad.backends.sqlcipher import SQLCipherDatabase
+ from leap.soledad.sqlcipher import SQLCipherDatabase
self.assertIsInstance(sol._db, SQLCipherDatabase)
def test__init_config_defaults(self):
@@ -117,7 +115,7 @@ class SoledadSharedDBTestCase(BaseSoledadTest):
def setUp(self):
BaseSoledadTest.setUp(self)
self._shared_db = SoledadSharedDatabase(
- 'https://provider/', LeapDocument, None)
+ 'https://provider/', SoledadDocument, None)
def test__get_secrets_from_shared_db(self):
"""
@@ -284,7 +282,8 @@ class SoledadSignalingTestCase(BaseSoledadTest):
soledad.signal.reset_mock()
sol = self._soledad_instance()
# mock the sync target
- LeapSyncTarget.get_sync_info = Mock(return_value=[0, 0, 0, 0, 2])
+ old_get_sync_info = SoledadSyncTarget.get_sync_info
+ SoledadSyncTarget.get_sync_info = Mock(return_value=[0, 0, 0, 0, 2])
# mock our generation so soledad thinks there's new data to sync
sol._db._get_generation = Mock(return_value=1)
# check for new data to sync
@@ -294,3 +293,4 @@ class SoledadSignalingTestCase(BaseSoledadTest):
proto.SOLEDAD_NEW_DATA_TO_SYNC,
ADDRESS,
)
+ SoledadSyncTarget.get_sync_info = old_get_sync_info
diff --git a/src/leap/soledad/tests/test_sqlcipher.py b/soledad/src/leap/soledad/tests/test_sqlcipher.py
index 9741bd4e..25d04861 100644
--- a/src/leap/soledad/tests/test_sqlcipher.py
+++ b/soledad/src/leap/soledad/tests/test_sqlcipher.py
@@ -43,13 +43,13 @@ from u1db.backends.sqlite_backend import SQLitePartialExpandDatabase
# soledad stuff.
-from leap.soledad.backends.sqlcipher import (
+from leap.soledad.document import SoledadDocument
+from leap.soledad.sqlcipher import (
SQLCipherDatabase,
DatabaseIsNotEncrypted,
+ open as u1db_open,
)
-from leap.soledad.backends.sqlcipher import open as u1db_open
-from leap.soledad.backends.leap_backend import (
- LeapDocument,
+from leap.soledad.target import (
EncryptionSchemes,
decrypt_doc,
ENC_JSON_KEY,
@@ -63,7 +63,7 @@ from leap.soledad.tests.u1db_tests import test_sqlite_backend
from leap.soledad.tests.u1db_tests import test_backends
from leap.soledad.tests.u1db_tests import test_open
from leap.soledad.tests.u1db_tests import test_sync
-from leap.soledad.backends.leap_backend import LeapSyncTarget
+from leap.soledad.target import SoledadSyncTarget
from leap.common.testing.basetest import BaseLeapTest
PASSWORD = '123456'
@@ -115,7 +115,7 @@ def copy_sqlcipher_database_for_test(test, db):
def make_document_for_test(test, doc_id, rev, content, has_conflicts=False):
- return LeapDocument(doc_id, rev, content, has_conflicts=has_conflicts)
+ return SoledadDocument(doc_id, rev, content, has_conflicts=has_conflicts)
SQLCIPHER_SCENARIOS = [
@@ -205,7 +205,7 @@ class TestSQLCipherDatabase(test_sqlite_backend.TestSQLiteDatabase):
self.assertTrue(db2._is_initialized(db1._get_sqlite_handle().cursor()))
-class TestAlternativeDocument(LeapDocument):
+class TestAlternativeDocument(SoledadDocument):
"""A (not very) alternative implementation of Document."""
@@ -272,7 +272,7 @@ class TestSQLCipherPartialExpandDatabase(
path, PASSWORD,
document_factory=TestAlternativeDocument)
doc = db2.create_doc({})
- self.assertTrue(isinstance(doc, LeapDocument))
+ self.assertTrue(isinstance(doc, SoledadDocument))
def test__open_database_non_existent(self):
temp_dir = self.createTempDir(prefix='u1db-test-')
@@ -341,7 +341,7 @@ class TestSQLCipherPartialExpandDatabase(
path, PASSWORD, create=False,
document_factory=TestAlternativeDocument)
doc = db2.create_doc({})
- self.assertTrue(isinstance(doc, LeapDocument))
+ self.assertTrue(isinstance(doc, SoledadDocument))
def test_open_database_create(self):
temp_dir = self.createTempDir(prefix='u1db-test-')
@@ -401,7 +401,7 @@ class SQLCipherOpen(test_open.TestU1DBOpen):
document_factory=TestAlternativeDocument)
self.addCleanup(db.close)
doc = db.create_doc({})
- self.assertTrue(isinstance(doc, LeapDocument))
+ self.assertTrue(isinstance(doc, SoledadDocument))
def test_open_existing(self):
db = SQLCipherDatabase(self.db_path, PASSWORD)
@@ -438,7 +438,7 @@ def sync_via_synchronizer_and_leap(test, db_source, db_target,
if trace_hook:
test.skipTest("full trace hook unsupported over http")
path = test._http_at[db_target]
- target = LeapSyncTarget.connect(test.getURL(path), test._soledad._crypto)
+ target = SoledadSyncTarget.connect(test.getURL(path), test._soledad._crypto)
target.set_token_credentials('user-uuid', 'auth-token')
if trace_hook_shallow:
target._set_trace_hook_shallow(trace_hook_shallow)
@@ -662,7 +662,7 @@ class SQLCipherDatabaseSyncTests(
def _make_local_db_and_leap_target(test, path='test'):
test.startServer()
db = test.request_state._create_database(os.path.basename(path))
- st = LeapSyncTarget.connect(test.getURL(path), test._soledad._crypto)
+ st = SoledadSyncTarget.connect(test.getURL(path), test._soledad._crypto)
st.set_token_credentials('user-uuid', 'auth-token')
return db, st
@@ -791,7 +791,7 @@ class SQLCipherEncryptionTest(BaseLeapTest):
# trying to open an encrypted database with the regular u1db
# backend should raise a DatabaseError exception.
SQLitePartialExpandDatabase(self.DB_FILE,
- document_factory=LeapDocument)
+ document_factory=SoledadDocument)
raise DatabaseIsNotEncrypted()
except dbapi2.DatabaseError:
# at this point we know that the regular U1DB sqlcipher backend
@@ -807,7 +807,7 @@ class SQLCipherEncryptionTest(BaseLeapTest):
SQLCipher backend should not succeed to open unencrypted databases.
"""
db = SQLitePartialExpandDatabase(self.DB_FILE,
- document_factory=LeapDocument)
+ document_factory=SoledadDocument)
db.create_doc_from_json(tests.simple_doc)
db.close()
try:
diff --git a/src/leap/soledad/tests/test_leap_backend.py b/soledad/src/leap/soledad/tests/test_target.py
index 6914e869..73c9fe68 100644
--- a/src/leap/soledad/tests/test_leap_backend.py
+++ b/soledad/src/leap/soledad/tests/test_target.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# test_leap_backend.py
+# test_target.py
# Copyright (C) 2013 LEAP
#
# This program is free software: you can redistribute it and/or modify
@@ -33,15 +33,17 @@ from u1db.remote import (
http_database,
http_target,
)
-from routes.mapper import Mapper
from leap import soledad
-from leap.soledad.backends import leap_backend
-from leap.soledad.server import (
+from leap.soledad import (
+ target,
+ auth,
+)
+from leap.soledad.document import SoledadDocument
+from leap.soledad_server import (
SoledadApp,
SoledadAuthMiddleware,
)
-from leap.soledad import auth
from leap.soledad.tests import u1db_tests as tests
@@ -61,7 +63,7 @@ from leap.soledad.tests.u1db_tests import test_sync
def make_leap_document_for_test(test, doc_id, rev, content,
has_conflicts=False):
- return leap_backend.LeapDocument(
+ return SoledadDocument(
doc_id, rev, content, has_conflicts=has_conflicts)
@@ -126,7 +128,7 @@ def copy_token_http_database_for_test(test, db):
return http_db
-class LeapTests(test_backends.AllDatabaseTests, BaseSoledadTest):
+class SoledadTests(test_backends.AllDatabaseTests, BaseSoledadTest):
scenarios = LEAP_SCENARIOS + [
('token_http', {'make_database_for_test':
@@ -143,7 +145,7 @@ class LeapTests(test_backends.AllDatabaseTests, BaseSoledadTest):
# The following tests come from `u1db.tests.test_http_client`.
#-----------------------------------------------------------------------------
-class TestLeapClientBase(test_http_client.TestHTTPClientBase):
+class TestSoledadClientBase(test_http_client.TestHTTPClientBase):
"""
This class should be used to test Token auth.
"""
@@ -230,13 +232,13 @@ class TestLeapClientBase(test_http_client.TestHTTPClientBase):
# The following tests come from `u1db.tests.test_document`.
#-----------------------------------------------------------------------------
-class TestLeapDocument(test_document.TestDocument, BaseSoledadTest):
+class TestSoledadDocument(test_document.TestDocument, BaseSoledadTest):
scenarios = ([(
'leap', {'make_document_for_test': make_leap_document_for_test})])
-class TestLeapPyDocument(test_document.TestPyDocument, BaseSoledadTest):
+class TestSoledadPyDocument(test_document.TestPyDocument, BaseSoledadTest):
scenarios = ([(
'leap', {'make_document_for_test': make_leap_document_for_test})])
@@ -246,7 +248,7 @@ class TestLeapPyDocument(test_document.TestPyDocument, BaseSoledadTest):
# The following tests come from `u1db.tests.test_remote_sync_target`.
#-----------------------------------------------------------------------------
-class TestLeapSyncTargetBasics(
+class TestSoledadSyncTargetBasics(
test_remote_sync_target.TestHTTPSyncTargetBasics):
"""
Some tests had to be copied to this class so we can instantiate our own
@@ -254,14 +256,14 @@ class TestLeapSyncTargetBasics(
"""
def test_parse_url(self):
- remote_target = leap_backend.LeapSyncTarget('http://127.0.0.1:12345/')
+ remote_target = target.SoledadSyncTarget('http://127.0.0.1:12345/')
self.assertEqual('http', remote_target._url.scheme)
self.assertEqual('127.0.0.1', remote_target._url.hostname)
self.assertEqual(12345, remote_target._url.port)
self.assertEqual('/', remote_target._url.path)
-class TestLeapParsingSyncStream(
+class TestSoledadParsingSyncStream(
test_remote_sync_target.TestParsingSyncStream,
BaseSoledadTest):
"""
@@ -281,10 +283,10 @@ class TestLeapParsingSyncStream(
"""
Test adapted to use encrypted content.
"""
- doc = leap_backend.LeapDocument('i', rev='r')
+ doc = SoledadDocument('i', rev='r')
doc.content = {}
- enc_json = leap_backend.encrypt_doc(self._soledad._crypto, doc)
- tgt = leap_backend.LeapSyncTarget(
+ enc_json = target.encrypt_doc(self._soledad._crypto, doc)
+ tgt = target.SoledadSyncTarget(
"http://foo/foo", crypto=self._soledad._crypto)
self.assertRaises(u1db.errors.BrokenSyncStream,
@@ -297,7 +299,7 @@ class TestLeapParsingSyncStream(
lambda doc, gen, trans_id: None)
def test_wrong_start(self):
- tgt = leap_backend.LeapSyncTarget("http://foo/foo")
+ tgt = target.SoledadSyncTarget("http://foo/foo")
self.assertRaises(u1db.errors.BrokenSyncStream,
tgt._parse_sync_stream, "{}\r\n]", None)
@@ -309,7 +311,7 @@ class TestLeapParsingSyncStream(
tgt._parse_sync_stream, "", None)
def test_wrong_end(self):
- tgt = leap_backend.LeapSyncTarget("http://foo/foo")
+ tgt = target.SoledadSyncTarget("http://foo/foo")
self.assertRaises(u1db.errors.BrokenSyncStream,
tgt._parse_sync_stream, "[\r\n{}", None)
@@ -318,7 +320,7 @@ class TestLeapParsingSyncStream(
tgt._parse_sync_stream, "[\r\n", None)
def test_missing_comma(self):
- tgt = leap_backend.LeapSyncTarget("http://foo/foo")
+ tgt = target.SoledadSyncTarget("http://foo/foo")
self.assertRaises(u1db.errors.BrokenSyncStream,
tgt._parse_sync_stream,
@@ -326,13 +328,13 @@ class TestLeapParsingSyncStream(
'"content": "c", "gen": 3}\r\n]', None)
def test_no_entries(self):
- tgt = leap_backend.LeapSyncTarget("http://foo/foo")
+ tgt = target.SoledadSyncTarget("http://foo/foo")
self.assertRaises(u1db.errors.BrokenSyncStream,
tgt._parse_sync_stream, "[\r\n]", None)
def test_error_in_stream(self):
- tgt = leap_backend.LeapSyncTarget("http://foo/foo")
+ tgt = target.SoledadSyncTarget("http://foo/foo")
self.assertRaises(u1db.errors.Unavailable,
tgt._parse_sync_stream,
@@ -353,7 +355,7 @@ class TestLeapParsingSyncStream(
#
def leap_sync_target(test, path):
- return leap_backend.LeapSyncTarget(
+ return target.SoledadSyncTarget(
test.getURL(path), crypto=test._soledad._crypto)
@@ -363,7 +365,7 @@ def token_leap_sync_target(test, path):
return st
-class TestLeapSyncTarget(
+class TestSoledadSyncTarget(
test_remote_sync_target.TestRemoteSyncTargets, BaseSoledadTest):
scenarios = [
@@ -497,14 +499,14 @@ class TestLeapSyncTarget(
def token_leap_https_sync_target(test, host, path):
_, port = test.server.server_address
- st = leap_backend.LeapSyncTarget(
+ st = target.SoledadSyncTarget(
'https://%s:%d/%s' % (host, port, path),
crypto=test._soledad._crypto)
st.set_token_credentials('user-uuid', 'auth-token')
return st
-class TestLeapSyncTargetHttpsSupport(test_https.TestHttpSyncTargetHttpsSupport,
+class TestSoledadSyncTargetHttpsSupport(test_https.TestHttpSyncTargetHttpsSupport,
BaseSoledadTest):
scenarios = [
@@ -598,7 +600,7 @@ class TestHTTPDatabaseWithCreds(
def _make_local_db_and_leap_target(test, path='test'):
test.startServer()
db = test.request_state._create_database(os.path.basename(path))
- st = leap_backend.LeapSyncTarget.connect(
+ st = target.SoledadSyncTarget.connect(
test.getURL(path), crypto=test._soledad._crypto)
return db, st
@@ -616,7 +618,7 @@ target_scenarios = [
]
-class LeapDatabaseSyncTargetTests(
+class SoledadDatabaseSyncTargetTests(
test_sync.DatabaseSyncTargetTests, BaseSoledadTest):
scenarios = (
@@ -702,7 +704,7 @@ class LeapDatabaseSyncTargetTests(
[(doc.doc_id, doc.rev), (doc2.doc_id, doc2.rev)]})
-class TestLeapDbSync(test_sync.TestDbSync, BaseSoledadTest):
+class TestSoledadDbSync(test_sync.TestDbSync, BaseSoledadTest):
"""Test db.sync remote sync shortcut"""
scenarios = [
@@ -722,7 +724,7 @@ class TestLeapDbSync(test_sync.TestDbSync, BaseSoledadTest):
def do_sync(self, target_name):
"""
- Perform sync using LeapSyncTarget and Token auth.
+ Perform sync using SoledadSyncTarget and Token auth.
"""
if self.token:
extra = dict(creds={'token': {
@@ -732,7 +734,7 @@ class TestLeapDbSync(test_sync.TestDbSync, BaseSoledadTest):
target_url = self.getURL(target_name)
return Synchronizer(
self.db,
- leap_backend.LeapSyncTarget(
+ target.SoledadSyncTarget(
target_url,
crypto=self._soledad._crypto,
**extra)).sync(autocreate=True)
diff --git a/src/leap/soledad/tests/u1db_tests/README b/soledad/src/leap/soledad/tests/u1db_tests/README
index 605f01fa..605f01fa 100644
--- a/src/leap/soledad/tests/u1db_tests/README
+++ b/soledad/src/leap/soledad/tests/u1db_tests/README
diff --git a/src/leap/soledad/tests/u1db_tests/__init__.py b/soledad/src/leap/soledad/tests/u1db_tests/__init__.py
index 43304b43..43304b43 100644
--- a/src/leap/soledad/tests/u1db_tests/__init__.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/__init__.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_backends.py b/soledad/src/leap/soledad/tests/u1db_tests/test_backends.py
index a53b01ba..a53b01ba 100644
--- a/src/leap/soledad/tests/u1db_tests/test_backends.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_backends.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_document.py b/soledad/src/leap/soledad/tests/u1db_tests/test_document.py
index e706e1a9..e706e1a9 100644
--- a/src/leap/soledad/tests/u1db_tests/test_document.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_document.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_http_app.py b/soledad/src/leap/soledad/tests/u1db_tests/test_http_app.py
index e0729aa2..e0729aa2 100644
--- a/src/leap/soledad/tests/u1db_tests/test_http_app.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_http_app.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_http_client.py b/soledad/src/leap/soledad/tests/u1db_tests/test_http_client.py
index 42e98461..42e98461 100644
--- a/src/leap/soledad/tests/u1db_tests/test_http_client.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_http_client.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_http_database.py b/soledad/src/leap/soledad/tests/u1db_tests/test_http_database.py
index f21e6da1..f21e6da1 100644
--- a/src/leap/soledad/tests/u1db_tests/test_http_database.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_http_database.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_https.py b/soledad/src/leap/soledad/tests/u1db_tests/test_https.py
index 62180f8c..62180f8c 100644
--- a/src/leap/soledad/tests/u1db_tests/test_https.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_https.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_open.py b/soledad/src/leap/soledad/tests/u1db_tests/test_open.py
index 0ff307e8..0ff307e8 100644
--- a/src/leap/soledad/tests/u1db_tests/test_open.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_open.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_remote_sync_target.py b/soledad/src/leap/soledad/tests/u1db_tests/test_remote_sync_target.py
index 66d404d2..66d404d2 100644
--- a/src/leap/soledad/tests/u1db_tests/test_remote_sync_target.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_remote_sync_target.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_sqlite_backend.py b/soledad/src/leap/soledad/tests/u1db_tests/test_sqlite_backend.py
index 1380e4b1..1380e4b1 100644
--- a/src/leap/soledad/tests/u1db_tests/test_sqlite_backend.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_sqlite_backend.py
diff --git a/src/leap/soledad/tests/u1db_tests/test_sync.py b/soledad/src/leap/soledad/tests/u1db_tests/test_sync.py
index 96aa2736..96aa2736 100644
--- a/src/leap/soledad/tests/u1db_tests/test_sync.py
+++ b/soledad/src/leap/soledad/tests/u1db_tests/test_sync.py
diff --git a/src/leap/soledad/tests/u1db_tests/testing-certs/Makefile b/soledad/src/leap/soledad/tests/u1db_tests/testing-certs/Makefile
index 2385e75b..2385e75b 100644
--- a/src/leap/soledad/tests/u1db_tests/testing-certs/Makefile
+++ b/soledad/src/leap/soledad/tests/u1db_tests/testing-certs/Makefile
diff --git a/src/leap/soledad/tests/u1db_tests/testing-certs/cacert.pem b/soledad/src/leap/soledad/tests/u1db_tests/testing-certs/cacert.pem
index c019a730..c019a730 100644
--- a/src/leap/soledad/tests/u1db_tests/testing-certs/cacert.pem
+++ b/soledad/src/leap/soledad/tests/u1db_tests/testing-certs/cacert.pem
diff --git a/src/leap/soledad/tests/u1db_tests/testing-certs/testing.cert b/soledad/src/leap/soledad/tests/u1db_tests/testing-certs/testing.cert
index 985684fb..985684fb 100644
--- a/src/leap/soledad/tests/u1db_tests/testing-certs/testing.cert
+++ b/soledad/src/leap/soledad/tests/u1db_tests/testing-certs/testing.cert
diff --git a/src/leap/soledad/tests/u1db_tests/testing-certs/testing.key b/soledad/src/leap/soledad/tests/u1db_tests/testing-certs/testing.key
index d83d4920..d83d4920 100644
--- a/src/leap/soledad/tests/u1db_tests/testing-certs/testing.key
+++ b/soledad/src/leap/soledad/tests/u1db_tests/testing-certs/testing.key
diff --git a/pkg/soledad b/soledad_server/pkg/soledad
index c640a94d..c640a94d 100644
--- a/pkg/soledad
+++ b/soledad_server/pkg/soledad
diff --git a/soledad_server/setup.py b/soledad_server/setup.py
new file mode 100644
index 00000000..522c86ff
--- /dev/null
+++ b/soledad_server/setup.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+# setup.py
+# Copyright (C) 2013 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+import os
+from setuptools import (
+ setup,
+ find_packages
+)
+
+
+install_requirements = [
+ 'configparser',
+ 'couchdb',
+ 'simplejson',
+ 'twisted>=12.0.0', # TODO: maybe we just want twisted-web?
+ 'oauth', # this is not strictly needed by us, but we need it
+ # until u1db adds it to its release as a dep.
+ 'u1db',
+ 'six==1.1.0',
+ 'routes',
+ 'PyOpenSSL',
+]
+
+
+if os.environ.get('VIRTUAL_ENV', None):
+ data_files = None
+else:
+ # XXX this should go only for linux/mac
+ data_files = [("/etc/init.d/", ["pkg/soledad"])]
+
+trove_classifiers = (
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: "
+ "GNU General Public License v3 or later (GPLv3+)",
+ "Environment :: Console",
+ "Operating System :: OS Independent",
+ "Operating System :: POSIX",
+ "Programming Language :: Python :: 2.6",
+ "Programming Language :: Python :: 2.7",
+ "Topic :: Database :: Front-Ends",
+ "Topic :: Software Development :: Libraries :: Python Modules"
+)
+
+setup(
+ name='leap.soledad_server',
+ version='0.1.1',
+ url='https://leap.se/',
+ license='GPLv3+',
+ description='Synchronization of locally encrypted data among devices.',
+ author='The LEAP Encryption Access Project',
+ author_email='info@leap.se',
+ long_description=(
+ "Soledad is the part of LEAP that allows application data to be "
+ "securely shared among devices. It provides, to other parts of the "
+ "LEAP client, an API for data storage and sync."
+ ),
+ namespace_packages=["leap"],
+ packages=find_packages('src'),
+ package_dir={'': 'src'},
+ install_requires=install_requirements,
+ data_files=data_files,
+ classifiers=trove_classifiers,
+)
diff --git a/soledad_server/src/leap/__init__.py b/soledad_server/src/leap/__init__.py
new file mode 100644
index 00000000..f48ad105
--- /dev/null
+++ b/soledad_server/src/leap/__init__.py
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
diff --git a/src/leap/soledad/server.py b/soledad_server/src/leap/soledad_server/__init__.py
index 9c9e0ad7..bea5d5fd 100644
--- a/src/leap/soledad/server.py
+++ b/soledad_server/src/leap/soledad_server/__init__.py
@@ -20,7 +20,7 @@
A U1DB server that stores data using CouchDB as its persistence layer.
This should be run with:
- twistd -n web --wsgi=leap.soledad.server.application --port=2424
+ twistd -n web --wsgi=leap.soledad_server.application --port=2424
"""
import configparser
@@ -53,7 +53,7 @@ if version.base() == "12.0.0":
from couchdb.client import Server
from leap.soledad import SECRETS_DOC_ID_HASH_PREFIX
-from leap.soledad.backends.couch import CouchServerState
+from leap.soledad_server.couch import CouchServerState
#-----------------------------------------------------------------------------
@@ -126,7 +126,7 @@ class URLToAuth(object):
@return: The database name corresponding to C{uuid}.
@rtype: str
"""
- return sha256('%s%s' % (SECRETS_DOC_ID_HASH_PREFIX, uuid)).hexdigest()
+ return '%s%s' % (SoledadApp.USER_DB_PREFIX, uuid)
def _register_auth_info(self, dbname):
"""
@@ -329,6 +329,11 @@ class SoledadApp(http_app.HTTPApp):
The name of the shared database that holds user's encrypted secrets.
"""
+ USER_DB_PREFIX = 'uuid-'
+ """
+ The string prefix of users' databases.
+ """
+
def __call__(self, environ, start_response):
"""
Handle a WSGI call to the Soledad application.
diff --git a/src/leap/soledad/backends/couch.py b/soledad_server/src/leap/soledad_server/couch.py
index 57885012..ed5ad6b3 100644
--- a/src/leap/soledad/backends/couch.py
+++ b/soledad_server/src/leap/soledad_server/couch.py
@@ -34,11 +34,10 @@ from couchdb.client import Server, Document as CouchDocument
from couchdb.http import ResourceNotFound
-from leap.soledad.backends.objectstore import (
+from leap.soledad_server.objectstore import (
ObjectStoreDatabase,
ObjectStoreSyncTarget,
)
-from leap.soledad.backends.leap_backend import LeapDocument
class InvalidURLError(Exception):
@@ -120,10 +119,7 @@ class CouchDatabase(ObjectStoreDatabase):
except ResourceNotFound:
self._server.create(self._dbname)
self._database = self._server[self._dbname]
- ObjectStoreDatabase.__init__(self, replica_uid=replica_uid,
- # TODO: move the factory choice
- # away
- document_factory=LeapDocument)
+ ObjectStoreDatabase.__init__(self, replica_uid=replica_uid)
#-------------------------------------------------------------------------
# methods from Database
diff --git a/src/leap/soledad/backends/objectstore.py b/soledad_server/src/leap/soledad_server/objectstore.py
index 8afac3ec..8afac3ec 100644
--- a/src/leap/soledad/backends/objectstore.py
+++ b/soledad_server/src/leap/soledad_server/objectstore.py
diff --git a/src/leap/soledad/backends/__init__.py b/src/leap/soledad/backends/__init__.py
deleted file mode 100644
index 720a8118..00000000
--- a/src/leap/soledad/backends/__init__.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- coding: utf-8 -*-
-# __init__.py
-# Copyright (C) 2013 LEAP
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-"""
-Backends that extend U1DB functionality.
-"""
-
-from leap.soledad.backends import (
- objectstore,
- couch,
- sqlcipher,
- leap_backend,
-)
-
-
-__all__ = [
- 'objectstore',
- 'couch',
- 'sqlcipher',
- 'leap_backend',
-]