diff options
| -rw-r--r-- | common/src/leap/soledad/common/couch/__init__.py | 169 | ||||
| -rw-r--r-- | common/src/leap/soledad/common/document.py | 1 | ||||
| -rw-r--r-- | 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. | 
