Ejemplo n.º 1
0
    def tenant_token(credentials={}, tenant=None):
        tenant_row = call_sync(manager.model['tenant'].get, tenant)

        if tenant_row is None:
            raise NotFound('invalid tenant')

        if 'tenant' in credentials:
            return make_token_result(credentials)

        user = call_sync(manager.model['user'].get, credentials['user'])

        if user is None or not user.desired.get('alicorn'):
            try:
                member = call_sync(manager.model['member'].one,
                                   tenant=tenant,
                                   user=credentials['user'])
            except KeyError:
                raise Forbidden('you are not a member of the tenant')


        # Bestow project owner role for alicorns
        if user.desired.get('alicorn'):
            role = 'owner'
        else:
            role = member.desired['role']

        return make_token_result({
            'tenant': tenant,
            'role': role
        })
Ejemplo n.º 2
0
        def entity_handler(credentials={}, **keys):
            jpath = endpoint.to_jpath(keys)[:-1]

            if 'GET' == flask.request.method:
                # Make sure that we can access the entity.
                validate_dbdict_fragment(credentials, {}, jpath, False)

                try:
                    # Get data from manager who can access the model.
                    data = call_sync(manager.get_entity, path, keys)
                except KeyError:
                    raise PathError('not found', jpath)

                # Strip keys with None values.
                return remove_nulls(data)

            if 'DELETE' == flask.request.method:
                # Make sure that we can write to that entity.
                validate_dbdict_fragment(credentials, {}, jpath, True)

                # Construct patch that would remove it.
                patch = [{'op': 'remove', 'path': jpath}]

                # Execute as usual.
                return {'uuids': apply_patch(patch)}

            if 'PATCH' == flask.request.method:
                return common_patch(credentials, jpath)
Ejemplo n.º 3
0
    def apply_patch(patch):
        """
        Preprocess and apply validated JSON Patch to database.
        Returns dictionary with placeholder to uuid mappings.
        """

        try:
            # Get root of the database dictionary mapping.
            root = Children(manager.db, schema.root)

            # Convert placeholders in the input patch to actual uuids.
            # Returns mapped placeholders for client to orient himself.
            uuids = preprocess_patch(root, patch)

            # Apply the patch.
            Pointer(root).patch(patch)

            # Determine our transaction id.
            txid = int(manager.db.execute('SELECT cork();').fetchone()[0])

            # Register our completion watch.
            call_sync(manager.listener.register, txid)

            try:
                try:
                    # Attempt to commit the transaction.
                    manager.db.commit()
                except DatabaseError, e:
                    # We have nothing better for now.
                    raise DataError(e.orig.diag.message_primary, [])
            except:
                # Transaction failed, remove the completion watch.
                call_sync(manager.listener.abort, txid)

                # Re-raise the exception.
                raise

            # Wait for the transaction to propagate.
            call_sync(manager.listener.wait, txid)

            # Stop waiting for the transaction.
            call_sync(manager.listener.abort, txid)

            # Return mapped uuids to the client now, when all data safely
            # hit the model and he will be able to retrieve them.
            return uuids

        except:
            # Roll back the transaction on any error.
            manager.db.rollback()

            # Re-raise the exception.
            raise
Ejemplo n.º 4
0
            def join_handler(credentials={}, **keys):
                jpath = endpoint.to_jpath(keys)[:-2]

                if 'GET' == flask.request.method:
                    # Make sure all access control restrictions are applied.
                    validate_dbdict_fragment(credentials, {}, jpath, False)

                    try:
                        # Let the manager deal with model access and data
                        # retrieval.  XXX: Access control is broken there, BTW.
                        data = call_sync(manager.list_collection_join, path, keys)
                    except KeyError:
                        raise PathError('not found', jpath)

                    # We promised not to return any nulls in the output.
                    return remove_nulls(data)
Ejemplo n.º 5
0
        def collection_handler(credentials={}, **keys):
            jpath = endpoint.to_jpath(keys)[:-2]

            if 'GET' == flask.request.method:
                # Make sure all access control restrictions are applied.
                validate_dbdict_fragment(credentials, {}, jpath, False)

                try:
                    # Let the manager deal with model access and data
                    # retrieval.  XXX: Access control is broken there, BTW.
                    data = call_sync(manager.list_collection, path, keys)
                except KeyError:
                    raise PathError('not found', jpath)

                # We promised not to return any nulls in the output.
                return remove_nulls(data)

            if 'POST' == flask.request.method:
                # Read data from client.
                data = loads(flask.request.data)

                # Make sure it's at least a litle sane.
                if not isinstance(data, Mapping):
                    raise DataError('invalid entity', jpath)

                # Desired state must be present when POSTing.
                if 'desired' not in data:
                    raise DataError('desired state missing', jpath + ['desired'])

                # When primary keys must be specified by the user, make sure
                # that they are present and do not invent them on our own.
                if endpoint.table.user_pkey:
                    djpath = jpath + ['desired']
                    if isinstance(endpoint.table.pkey, basestring):
                        if endpoint.table.pkey not in data['desired']:
                            raise DataError('primary key missing', djpath + [endpoint.table.pkey])
                    else:
                        for key in endpoint.table.pkey:
                            if key not in data['desired']:
                                raise DataError('primary key missing', djpath + [key])

                if 'desired' in data:
                    # Extract the primary key placeholder.
                    pkey = data['desired'].get(endpoint.table.pkey, 'POST')
                else:
                    # Or default to one named 'POST'.
                    pkey = 'POST'

                # Get rid of keys with None values.
                data = remove_nulls(data)

                # Calculate hypothetical destination path.
                post_path = jpath + [pkey]

                # Make sure all access control restrictions are applied.
                validate_dbdict_fragment(credentials, data, post_path, True)

                # This is what the patch should look like:
                patch = [{'op': 'add', 'path': post_path, 'value': data}]

                # Apply the patch and return resulting set of UUIDs.
                return {'uuids': apply_patch(patch)}

            if 'PATCH' == flask.request.method:
                return common_patch(credentials, jpath)