From eaf19626a57d5f5325653fee3aea9db27c9531fe Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Wed, 28 Oct 2015 17:58:27 -0300 Subject: [refactor] resource logic encapsulation Creating a resource from a path to use get_json causes a lot of dirty code and unexplained things like response[2]. This commit extracts that logic into a helper to let it more clear about what is happening. --- common/src/leap/soledad/common/couch/__init__.py | 169 +++++++++-------------- common/src/leap/soledad/common/document.py | 1 - server/src/leap/soledad/server/auth.py | 5 +- 3 files changed, 71 insertions(+), 104 deletions(-) diff --git a/common/src/leap/soledad/common/couch/__init__.py b/common/src/leap/soledad/common/couch/__init__.py index 6fd4d0ce..274f59e2 100644 --- a/common/src/leap/soledad/common/couch/__init__.py +++ b/common/src/leap/soledad/common/couch/__init__.py @@ -166,8 +166,8 @@ class CouchDatabase(object): """ for ddoc_name in ['docs', 'syncs', 'transactions']: try: - self._database.resource('_design', - ddoc_name, '_info').get_json() + self.json_from_resource(['_design', ddoc_name, '_info'], + check_missing_ddoc=False) except ResourceNotFound: ddoc = json.loads( binascii.a2b_base64( @@ -320,12 +320,9 @@ class CouchDatabase(object): """ # get document with all attachments (u1db content and eventual # conflicts) - try: - result = \ - self._database.resource(doc_id).get_json( - attachments=True)[2] - except ResourceNotFound: + if doc_id not in self._database: return None + result = self.json_from_resource([doc_id], attachments=True) return self.__parse_doc_from_couch(result, doc_id, check_for_conflicts) def __parse_doc_from_couch(self, result, doc_id, @@ -387,19 +384,6 @@ class CouchDatabase(object): :rtype: str :raise InvalidGeneration: Raised when the generation does not exist. - :raise MissingDesignDocError: Raised when tried to access a missing - design document. - :raise MissingDesignDocListFunctionError: Raised when trying to access - a missing list function on a - design document. - :raise MissingDesignDocNamedViewError: Raised when trying to access a - missing named view on a design - document. - :raise MissingDesignDocDeletedError: Raised when trying to access a - deleted design document. - :raise MissingDesignDocUnknownError: Raised when failed to access a - design document for an yet - unknown reason. """ if generation == 0: return '' @@ -407,16 +391,10 @@ class CouchDatabase(object): ddoc_path = [ '_design', 'transactions', '_list', 'trans_id_for_gen', 'log' ] - res = self._database.resource(*ddoc_path) - try: - response = res.get_json(gen=generation) - if response[2] == {}: - raise InvalidGeneration - return response[2]['transaction_id'] - except ResourceNotFound as e: - raise_missing_design_doc_error(e, ddoc_path) - except ServerError as e: - raise_server_error(e, ddoc_path) + response = self.json_from_resource(ddoc_path, gen=generation) + if response == {}: + raise InvalidGeneration + return response['transaction_id'] def get_replica_gen_and_trans_id(self, other_replica_uid): """ @@ -472,11 +450,13 @@ class CouchDatabase(object): # TODO: move into resource logic! first_entry = self.get_doc(doc_id, check_for_conflicts=True) conflicts.append(first_entry) - resource = self._database.resource(doc_id, 'u1db_conflicts') + try: - response = resource.get_json(**params) + response = self.json_from_resource([doc_id, 'u1db_conflicts'], + check_missing_ddoc=False, + **params) return conflicts + self._build_conflicts( - doc_id, json.loads(response[2].read())) + doc_id, json.loads(response.read())) except ResourceNotFound: return [] @@ -513,31 +493,13 @@ class CouchDatabase(object): :return: The complete transaction log. :rtype: [(str, str)] - - :raise MissingDesignDocError: Raised when tried to access a missing - design document. - :raise MissingDesignDocListFunctionError: Raised when trying to access - a missing list function on a - design document. - :raise MissingDesignDocNamedViewError: Raised when trying to access a - missing named view on a design - document. - :raise MissingDesignDocDeletedError: Raised when trying to access a - deleted design document. - :raise MissingDesignDocUnknownError: Raised when failed to access a - design document for an yet - unknown reason. """ # query a couch view ddoc_path = ['_design', 'transactions', '_view', 'log'] - res = self._database.resource(*ddoc_path) - try: - response = res.get_json() - return map( - lambda row: (row['id'], row['value']), - response[2]['rows']) - except ResourceNotFound as e: - raise_missing_design_doc_error(e, ddoc_path) + response = self.json_from_resource(ddoc_path) + return map( + lambda row: (row['id'], row['value']), + response['rows']) def whats_changed(self, old_generation=0): """ @@ -555,53 +517,33 @@ class CouchDatabase(object): to the last intervening change and sorted by generation (old changes first) :rtype: (int, str, [(str, int, str)]) - - :raise MissingDesignDocError: Raised when tried to access a missing - design document. - :raise MissingDesignDocListFunctionError: Raised when trying to access - a missing list function on a - design document. - :raise MissingDesignDocNamedViewError: Raised when trying to access a - missing named view on a design - document. - :raise MissingDesignDocDeletedError: Raised when trying to access a - deleted design document. - :raise MissingDesignDocUnknownError: Raised when failed to access a - design document for an yet - unknown reason. """ # query a couch list function ddoc_path = [ '_design', 'transactions', '_list', 'whats_changed', 'log' ] - res = self._database.resource(*ddoc_path) - try: - response = res.get_json(old_gen=old_generation) - results = map( - lambda row: - (row['generation'], row['doc_id'], row['transaction_id']), - response[2]['transactions']) - results.reverse() - cur_gen = old_generation - seen = set() - changes = [] - newest_trans_id = '' - for generation, doc_id, trans_id in results: - if doc_id not in seen: - changes.append((doc_id, generation, trans_id)) - seen.add(doc_id) - if changes: - cur_gen = changes[0][1] # max generation - newest_trans_id = changes[0][2] - changes.reverse() - else: - cur_gen, newest_trans_id = self.get_generation_info() + response = self.json_from_resource(ddoc_path, old_gen=old_generation) + results = map( + lambda row: + (row['generation'], row['doc_id'], row['transaction_id']), + response['transactions']) + results.reverse() + cur_gen = old_generation + seen = set() + changes = [] + newest_trans_id = '' + for generation, doc_id, trans_id in results: + if doc_id not in seen: + changes.append((doc_id, generation, trans_id)) + seen.add(doc_id) + if changes: + cur_gen = changes[0][1] # max generation + newest_trans_id = changes[0][2] + changes.reverse() + else: + cur_gen, newest_trans_id = self.get_generation_info() - return cur_gen, newest_trans_id, changes - except ResourceNotFound as e: - raise_missing_design_doc_error(e, ddoc_path) - except ServerError as e: - raise_server_error(e, ddoc_path) + return cur_gen, newest_trans_id, changes def get_generation_info(self): """ @@ -609,6 +551,25 @@ class CouchDatabase(object): :return: A tuple containing the current generation and transaction id. :rtype: (int, str) + """ + # query a couch list function + ddoc_path = ['_design', 'transactions', '_list', 'generation', 'log'] + info = self.json_from_resource(ddoc_path) + return (info['generation'], info['transaction_id']) + + def json_from_resource(self, ddoc_path, check_missing_ddoc=True, + **kwargs): + """ + Get a resource from it's path and gets a doc's JSON using provided + parameters, also checking for missing design docs by default. + + :param ddoc_path: The path to resource. + :type ddoc_path: [str] + :param check_missing_ddoc: Raises info on what design doc is missing. + :type check_missin_ddoc: bool + + :return: The request's data parsed from JSON to a dict. + :rtype: dict :raise MissingDesignDocError: Raised when tried to access a missing design document. @@ -624,14 +585,18 @@ class CouchDatabase(object): design document for an yet unknown reason. """ - # query a couch list function - ddoc_path = ['_design', 'transactions', '_list', 'generation', 'log'] - res = self._database.resource(*ddoc_path) + if ddoc_path is not None: + resource = self._database.resource(*ddoc_path) + else: + resource = self._database.resource() try: - response = res.get_json() - return (response[2]['generation'], response[2]['transaction_id']) + _, _, data = resource.get_json(**kwargs) + return data except ResourceNotFound as e: - raise_missing_design_doc_error(e, ddoc_path) + if check_missing_ddoc: + raise_missing_design_doc_error(e, ddoc_path) + else: + raise e except ServerError as e: raise_server_error(e, ddoc_path) diff --git a/common/src/leap/soledad/common/document.py b/common/src/leap/soledad/common/document.py index 20510544..9e0c0976 100644 --- a/common/src/leap/soledad/common/document.py +++ b/common/src/leap/soledad/common/document.py @@ -132,7 +132,6 @@ class ServerDocument(SoledadDocument): :type has_conflicts: bool """ SoledadDocument.__init__(self, doc_id, rev, json, has_conflicts) - self.transactions = None self._conflicts = None def get_conflicts(self): diff --git a/server/src/leap/soledad/server/auth.py b/server/src/leap/soledad/server/auth.py index 01baf1ce..ccbd6fbd 100644 --- a/server/src/leap/soledad/server/auth.py +++ b/server/src/leap/soledad/server/auth.py @@ -189,7 +189,6 @@ class SoledadAuthMiddleware(object): @type prefix: str """ self._app = app - self._state = app.state def _error(self, start_response, status, description, message=None): """ @@ -350,6 +349,10 @@ class SoledadTokenAuthMiddleware(SoledadAuthMiddleware): TOKEN_AUTH_ERROR_STRING = "Incorrect address or token." + def __init__(self, app): + self._state = app.state + super(SoledadTokenAuthMiddleware, self).__init__(app) + def _verify_authentication_scheme(self, scheme): """ Verify if authentication scheme is valid. -- cgit v1.2.3