diff options
-rw-r--r-- | docs/api.rst | 65 | ||||
-rw-r--r-- | docs/api/attachments.rst | 11 | ||||
-rw-r--r-- | docs/api/blobs.rst | 11 | ||||
-rw-r--r-- | docs/api/client.rst | 8 | ||||
-rw-r--r-- | docs/api/server.rst | 6 | ||||
-rw-r--r-- | docs/index.rst | 1 | ||||
-rw-r--r-- | src/leap/soledad/client/_db/blobs.py | 75 |
7 files changed, 105 insertions, 72 deletions
diff --git a/docs/api.rst b/docs/api.rst index 9a725065..362c632c 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,60 +1,9 @@ -Soledad API -=========== +API Reference +============= -.. contents:: - :local: +.. toctree:: + :maxdepth: 1 -.. _client-side-code-api: - -Client-side code API --------------------- - -.. autoclass:: leap.soledad.client.Soledad - :members: - :undoc-members: - -.. _client-side-attachments-api: - -Client-side attachments API ---------------------------- - -.. autoclass:: leap.soledad.client._document.AttachmentStates - :members: - :undoc-members: - -.. autointerface:: leap.soledad.client._document.IDocumentWithAttachment - :members: - :undoc-members: - - -.. _server-side-attachments-rest-api: - -Server-side attachments REST API --------------------------------- - -These are the possible ways to interact with the attachments REST API on the -server side: - -=========== ================ ======== ================== -HTTP Method URL Content Possible responses -=========== ================ ======== ================== -GET /user_id - 200 -GET /user_id/blob_id - 200, 404 -PUT /user_id/blob_id The BLOB 200, 409, 507 -DELETE /user_id/blob_id - 200 -=========== ================ ======== ================== - -Server-side attachments code API --------------------------------- - -.. _i-blobs-backend: - -.. autoclass:: leap.soledad.server.interfaces.IBlobsBackend - :members: - :undoc-members: - -.. _filesystem-blobs-backend: - -.. autoclass:: leap.soledad.server._blobs.FilesystemBlobsBackend - :members: - :undoc-members: + api/client + api/blobs + api/attachments diff --git a/docs/api/attachments.rst b/docs/api/attachments.rst new file mode 100644 index 00000000..80b81d67 --- /dev/null +++ b/docs/api/attachments.rst @@ -0,0 +1,11 @@ +Client-side Attachments API +=========================== + +Soledad Documents implement the ``IDocumentWithAttachment`` API that associates +:ref:`blobs` with documents. + +.. autoclass:: leap.soledad.client._document.IDocumentWithAttachment + :members: + :undoc-members: + :special-members: + :show-inheritance: diff --git a/docs/api/blobs.rst b/docs/api/blobs.rst new file mode 100644 index 00000000..fbf31e1c --- /dev/null +++ b/docs/api/blobs.rst @@ -0,0 +1,11 @@ +Client-side Blobs API +===================== + +The Soledad Client object has a ``blobmanager`` property which is responsible +for handling blobs. + +.. autoclass:: leap.soledad.client._db.blobs.BlobManager + :members: + :special-members: __init__ + :undoc-members: + :show-inheritance: diff --git a/docs/api/client.rst b/docs/api/client.rst new file mode 100644 index 00000000..7be3f763 --- /dev/null +++ b/docs/api/client.rst @@ -0,0 +1,8 @@ +Soledad Client API +================== + +.. autoclass:: leap.soledad.client.Soledad + :members: + :undoc-members: + :special-members: __init__ + :show-inheritance: diff --git a/docs/api/server.rst b/docs/api/server.rst new file mode 100644 index 00000000..d93e41ed --- /dev/null +++ b/docs/api/server.rst @@ -0,0 +1,6 @@ +Soledad Server API +================== + +.. automodule:: leap.soledad.server + :members: + :show-inheritance: diff --git a/docs/index.rst b/docs/index.rst index 0aa81dbf..275bad96 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -41,6 +41,7 @@ Soledad documentation client reference development + api Indices and tables ================== diff --git a/src/leap/soledad/client/_db/blobs.py b/src/leap/soledad/client/_db/blobs.py index 381787c5..31964a6c 100644 --- a/src/leap/soledad/client/_db/blobs.py +++ b/src/leap/soledad/client/_db/blobs.py @@ -175,24 +175,30 @@ class DecrypterBuffer(object): class BlobManager(object): """ - Ideally, the decrypting flow goes like this: - - - GET a blob from remote server. - - Decrypt the preamble - - Allocate a zeroblob in the sqlcipher sink - - Mark the blob as unusable (ie, not verified) - - Decrypt the payload incrementally, and write chunks to sqlcipher - ** Is it possible to use a small buffer for the aes writer w/o - ** allocating all the memory in openssl? - - Finalize the AES decryption - - If preamble + payload verifies correctly, mark the blob as usable - + The BlobManager can list, put, get, set flags and synchronize blobs stored + in local and remote storages. """ max_retries = 3 def __init__( self, local_path, remote, key, secret, user, token=None, cert_file=None): + """ + Initialize the blob manager. + + :param local_path: The path for the local blobs database. + :type local_path: str + :param remote: The URL of the remote storage. + :type remote: str + :param secret: The secret used to encrypt/decrypt blobs. + :type secret: str + :param user: The uuid of the user. + :type user: str + :param token: The access token for interacting with remote storage. + :type token: str + :param cert_file: The path to the CA certificate file. + :type cert_file: str + """ if local_path: mkdir_p(os.path.dirname(local_path)) self.local = SQLiteBlobBackend(local_path, key=key, user=user) @@ -207,7 +213,8 @@ class BlobManager(object): def count(self, **params): """ - Counts the number of blobs. + Count the number of blobs. + :param namespace: Optional parameter to restrict operation to a given namespace. :type namespace: str @@ -223,6 +230,7 @@ class BlobManager(object): def remote_list(self, **params): """ List blobs from server, with filtering and ordering capabilities. + :param namespace: Optional parameter to restrict operation to a given namespace. :type namespace: str @@ -249,6 +257,13 @@ class BlobManager(object): @defer.inlineCallbacks def send_missing(self, namespace=''): + """ + Compare local and remote blobs and send what's missing in server. + + :param namespace: + Optional parameter to restrict operation to a given namespace. + :type namespace: str + """ our_blobs = yield self.local_list(namespace) server_blobs = yield self.remote_list(namespace=namespace) missing = [b_id for b_id in our_blobs if b_id not in server_blobs] @@ -270,6 +285,14 @@ class BlobManager(object): @defer.inlineCallbacks def fetch_missing(self, namespace=''): + """ + Compare local and remote blobs and fetch what's missing in local + storage. + + :param namespace: + Optional parameter to restrict operation to a given namespace. + :type namespace: str + """ # TODO: Use something to prioritize user requests over general new docs our_blobs = yield self.local_list(namespace) server_blobs = yield self.remote_list(namespace=namespace) @@ -282,6 +305,17 @@ class BlobManager(object): @defer.inlineCallbacks def put(self, doc, size, namespace=''): + """ + Put a blob in local storage and upload it to server. + + :param doc: A BlobDoc representing the blob. + :type doc: leap.soledad.client._document.BlobDoc + :param size: The size of the blob. + :type size: int + :param namespace: + Optional parameter to restrict operation to a given namespace. + :type namespace: str + """ if (yield self.local.exists(doc.blob_id, namespace)): error_message = "Blob already exists: %s" % doc.blob_id raise BlobAlreadyExistsError(error_message) @@ -299,6 +333,7 @@ class BlobManager(object): def set_flags(self, blob_id, flags, **params): """ Set flags for a given blob_id. + :param blob_id: Unique identifier of a blob. :type blob_id: str @@ -325,6 +360,7 @@ class BlobManager(object): def get_flags(self, blob_id, **params): """ Get flags from a given blob_id. + :param blob_id: Unique identifier of a blob. :type blob_id: str @@ -345,6 +381,16 @@ class BlobManager(object): @defer.inlineCallbacks def get(self, blob_id, namespace=''): + """ + Get the blob from local storage or, if not available, from the server. + + :param blob_id: + Unique identifier of a blob. + :type blob_id: str + :param namespace: + Optional parameter to restrict operation to a given namespace. + :type namespace: str + """ local_blob = yield self.local.get(blob_id, namespace=namespace) if local_blob: logger.info("Found blob in local database: %s" % blob_id) @@ -415,7 +461,8 @@ class BlobManager(object): @defer.inlineCallbacks def delete(self, blob_id, namespace='', **params): """ - Deletes a blob from local and remote storages. + Delete a blob from local and remote storages. + :param blob_id: Unique identifier of a blob. :type blob_id: str |