Пример #1
0
def get_new_doc(enc_json):
    doc = ServerDocument(doc_id=str(uuid.uuid4()))
    doc.content = {
        'incoming': True,
        ENC_SCHEME_KEY: EncryptionSchemes.PUBKEY,
        ENC_JSON_KEY: enc_json
    }
    return doc
Пример #2
0
def get_new_doc(enc_json):
    doc = ServerDocument(doc_id=str(uuid.uuid4()))
    doc.content = {
        'incoming': True,
        ENC_SCHEME_KEY: EncryptionSchemes.PUBKEY,
        ENC_JSON_KEY: enc_json
    }
    return doc
Пример #3
0
 def _put_legacy(self, doc_id, scheme, db, request):
     try:
         doc = ServerDocument(doc_id)
         content = request.content.read()
         doc.content = self.formatter.format(content, scheme)
         db.put_doc(doc)
         self._finish(request)
     except Exception as e:
         self._error(e, request)
Пример #4
0
 def __parse_doc_from_couch(self,
                            result,
                            doc_id,
                            check_for_conflicts=False,
                            decode=True):
     # restrict to u1db documents
     if 'u1db_rev' not in result:
         return None
     doc = ServerDocument(doc_id, result['u1db_rev'])
     # set contents or make tombstone
     if '_attachments' not in result \
             or 'u1db_content' not in result['_attachments']:
         doc.make_tombstone()
     elif decode:
         doc.content = json.loads(
             binascii.a2b_base64(
                 result['_attachments']['u1db_content']['data']))
     else:
         doc._json = result['_attachments']['u1db_content']['data']
     # determine if there are conflicts
     if check_for_conflicts \
             and '_attachments' in result \
             and 'u1db_conflicts' in result['_attachments']:
         if decode:
             conflicts = binascii.a2b_base64(
                 result['_attachments']['u1db_conflicts']['data'])
         else:
             conflicts = result['_attachments']['u1db_conflicts']['data']
         conflicts = json.loads(conflicts)
         doc.set_conflicts(self._build_conflicts(doc.doc_id, conflicts))
     # store couch revision
     doc.couch_rev = result['_rev']
     return doc
Пример #5
0
    def __parse_doc_from_couch(self, result, doc_id,
                               check_for_conflicts=False):
        # restrict to u1db documents
        if 'u1db_rev' not in result:
            return None
        doc = ServerDocument(doc_id, result['u1db_rev'])
        # set contents or make tombstone

        if '_attachments' not in result \
                or 'u1db_content' not in result['_attachments']:
            doc.make_tombstone()
        else:
            doc.content = json.loads(
                result['_attachments']['u1db_content'])
        # determine if there are conflicts
        if check_for_conflicts \
                and '_attachments' in result \
                and 'u1db_conflicts' in result['_attachments']:
            doc.set_conflicts(
                self._build_conflicts(
                    doc.doc_id,
                    result['_attachments']['u1db_conflicts']))
        # store couch revision
        doc.couch_rev = result['_rev']
        # store transactions
        doc.transactions = result['u1db_transactions']
        return doc
Пример #6
0
 def __parse_doc_from_couch(self, result, doc_id,
                            check_for_conflicts=False, decode=True):
     # restrict to u1db documents
     if 'u1db_rev' not in result:
         return None
     doc = ServerDocument(doc_id, result['u1db_rev'])
     # set contents or make tombstone
     if '_attachments' not in result \
             or 'u1db_content' not in result['_attachments']:
         doc.make_tombstone()
     elif decode:
         doc.content = json.loads(
             binascii.a2b_base64(
                 result['_attachments']['u1db_content']['data']))
     else:
         doc._json = result['_attachments']['u1db_content']['data']
     # determine if there are conflicts
     if check_for_conflicts \
             and '_attachments' in result \
             and 'u1db_conflicts' in result['_attachments']:
         if decode:
             conflicts = binascii.a2b_base64(
                 result['_attachments']['u1db_conflicts']['data'])
         else:
             conflicts = result['_attachments']['u1db_conflicts']['data']
         conflicts = json.loads(conflicts)
         doc.set_conflicts(self._build_conflicts(doc.doc_id, conflicts))
     # store couch revision
     doc.couch_rev = result['_rev']
     return doc
Пример #7
0
    def _encrypt_message(self, pubkey, message):
        """
        Given a public key and a message, it encrypts the message to
        that public key.

        :param pubkey: public key for the owner of the message
        :type pubkey: str
        :param message: message contents
        :type message: str

        :return: doc to sync with Soledad or None, None if something
                 went wrong.
        :rtype: ServerDocument
        """
        if pubkey is None or len(pubkey) == 0:
            log.msg("_encrypt_message: Something went wrong, here's all "
                    "I know: %r" % (pubkey,))
            raise Exception('Not valid key')

        doc = ServerDocument(doc_id=str(pyuuid.uuid4()))

        # store plain text if pubkey is not available
        data = {'incoming': True, 'content': message}
        json_dump = json.dumps(data, ensure_ascii=False)
        try:
            key, _ = PGPKey.from_blob(pubkey)
            if key.expires_at and key.expires_at < datetime.now():
                log.msg("_encrypt_message: the key is expired (%s)"
                        % str(key.expires_at))

            message = PGPMessage.new(json_dump)
            encryption_result = key.encrypt(message)
        except (ValueError, PGPEncryptionError) as e:
            log.msg("_encrypt_message: Encryption failed with status: %s"
                    % (e,))
            doc.content = {
                self.INCOMING_KEY: True,
                self.ERROR_DECRYPTING_KEY: False,
                ENC_SCHEME_KEY: EncryptionSchemes.NONE,
                ENC_JSON_KEY: json_dump
            }
            return doc

        doc.content = {
            self.INCOMING_KEY: True,
            self.ERROR_DECRYPTING_KEY: False,
            ENC_SCHEME_KEY: EncryptionSchemes.PUBKEY,
            ENC_JSON_KEY: str(encryption_result)
        }
        return doc
Пример #8
0
    def post_put(
            self, id, rev, content, gen,
            trans_id, number_of_docs, doc_idx):
        """
        Put one incoming document into the server replica.

        :param id: The id of the incoming document.
        :type id: str
        :param rev: The revision of the incoming document.
        :type rev: str
        :param content: The content of the incoming document.
        :type content: dict
        :param gen: The source replica generation corresponding to the
                    revision of the incoming document.
        :type gen: int
        :param trans_id: The source replica transaction id corresponding to
                         the revision of the incoming document.
        :type trans_id: str
        :param number_of_docs: The total amount of documents sent on this sync
                               session.
        :type number_of_docs: int
        :param doc_idx: The index of the current document.
        :type doc_idx: int
        """
        doc = ServerDocument(id, rev, json=content)
        self._staging_size += len(content or '')
        self._staging.append((doc, gen, trans_id, number_of_docs, doc_idx))
        if self._staging_size > ENTRY_CACHE_SIZE or doc_idx == number_of_docs:
            self.sync_exch.batched_insert_from_source(self._staging,
                                                      self._sync_id)
            self._staging = []
            self._staging_size = 0
Пример #9
0
    def _build_conflicts(self, doc_id, attached_conflicts):
        """
        Build the conflicted documents list from the conflicts attachment
        fetched from a couch document.

        :param attached_conflicts: The document's conflicts as fetched from a
                                   couch document attachment.
        :type attached_conflicts: dict
        """
        conflicts = []
        for doc_rev, content in attached_conflicts:
            doc = ServerDocument(doc_id, doc_rev)
            if content is None:
                doc.make_tombstone()
            else:
                doc.content = content
            conflicts.append(doc)
        return conflicts
Пример #10
0
    def _build_conflicts(self, doc_id, attached_conflicts):
        """
        Build the conflicted documents list from the conflicts attachment
        fetched from a couch document.

        :param attached_conflicts: The document's conflicts as fetched from a
                                   couch document attachment.
        :type attached_conflicts: dict
        """
        conflicts = []
        for doc_rev, content in attached_conflicts:
            doc = ServerDocument(doc_id, doc_rev)
            if content is None:
                doc.make_tombstone()
            else:
                doc.content = content
            conflicts.append(doc)
        return conflicts
Пример #11
0
 def render_PUT(self, request):
     uuid, doc_id = request.postpath
     scheme = EncryptionSchemes.PUBKEY
     db = self.factory.open_database(uuid)
     if uses_legacy(db):
         doc = ServerDocument(doc_id)
         doc.content = self.formatter.format(request.content.read(), scheme)
         db.put_doc(doc)
         self._finish(request)
     else:
         raw_content = request.content.read()
         preamble = self.formatter.preamble(raw_content, doc_id)
         request.content = BytesIO(preamble + ' ' + raw_content)
         d = db.write_blob(uuid, doc_id, request, namespace='MX')
         # FIXME: We really need to decouple request handling from the
         # backend! This is very ugly, but will change when this refactor
         # is done.
         flagsReq = DummyRequest([''])
         flagsReq.content = BytesIO(json.dumps([Flags.PENDING]))
         d.addCallback(lambda _: db.set_flags(uuid, doc_id, flagsReq, 'MX'))
         d.addCallback(lambda _: self._finish(request))
     return NOT_DONE_YET
Пример #12
0
def make_document_for_test(test, doc_id, rev, content, has_conflicts=False):
    return ServerDocument(doc_id, rev, content, has_conflicts=has_conflicts)