예제 #1
0
async def default_delete(context, request):
    data = await request.json()
    behavior = data.get('behavior', None)
    factory = get_cached_factory(context.type_name)
    behavior_class = resolve_dotted_name(behavior)
    if behavior_class is not None:
        if behavior_class in factory.behaviors:
            return Response(response={}, status=201)
    if behavior not in context.__behaviors__:
        return Response(response={}, status=201)
    context.remove_behavior(behavior)
    return {}
예제 #2
0
    async def __call__(self):
        """ data input : { 'interface': 'INTERFACE' }"""
        if not hasattr(self.request, 'container_settings'):
            return ErrorResponse('BadRequest', _("Not in a container request"))

        data = await self.request.json()
        interface = data.get('interface', None)
        initial_values = data.get('initial_values', {})
        if interface is None:
            return ErrorResponse('InvalidRequest', 'Non existent Interface')

        registry = self.request.container_settings
        iObject = import_class(interface)
        registry.register_interface(iObject)
        config = registry.for_interface(iObject)

        # Initialize values
        # If its defined on the guillotina.schema default will not be overwritten
        #  you will need to PATCH
        for key, field in get_fields(iObject).items():
            if key in initial_values and getattr(config, key,
                                                 _marker) == _marker:
                # We don't have a value
                config[key] = initial_values[key]

        return Response(response={}, status=201)
예제 #3
0
    async def __call__(self):
        if self.key is _marker:
            # No option to write the root of registry
            return ErrorResponse('InvalidRequest', 'Needs the registry key')

        data = await self.request.json()
        if 'value' in data:
            value = data['value']
        else:
            value = data

        assert '.' in self.key, 'Registry key must be dotted.iface.name.fieldname'  # noqa
        iface, name = self.key.rsplit('.', 1)
        iface = resolve_dotted_name(iface)
        field = iface[name]

        try:
            new_value = get_adapter((field),
                                    IJSONToValue,
                                    args=[value, self.context])
        except ComponentLookupError:
            return ErrorResponse('DeserializationError',
                                 'Cannot deserialize type {}'.format(
                                     str(self.field)),
                                 status=501)

        try:
            self.request.container_settings[self.key] = new_value
        except DeserializationError as e:
            return ErrorResponse('DeserializationError',
                                 str(e),
                                 exc=e,
                                 status=400)

        return Response(response='', status=204)
예제 #4
0
    async def __call__(self):
        data = await self.get_data()

        if 'id' in data and data['id'] != self.context.id:
            return ErrorResponse('DeserializationError',
                                 'Not allowed to change id of content.',
                                 status=412)

        behaviors = data.get('@behaviors', None)
        for behavior in behaviors or ():
            self.context.add_behavior(behavior)

        deserializer = query_multi_adapter((self.context, self.request),
                                           IResourceDeserializeFromJson)
        if deserializer is None:
            return ErrorResponse('DeserializationError',
                                 'Cannot deserialize type {}'.format(
                                     self.context.type_name),
                                 status=412)

        try:
            await deserializer(data)
        except DeserializationError as e:
            return ErrorResponse('DeserializationError', str(e), status=422)

        await notify(ObjectModifiedEvent(self.context, payload=data))

        return Response(response='', status=204)
예제 #5
0
async def default_patch(context, request):
    data = await request.json()
    behavior = data.get('behavior', None)
    try:
        behavior_class = resolve_dotted_name(behavior)
    except ModuleNotFoundError:
        behavior_class = None
    if behavior_class is None:
        return Response(response={}, status=404)
    factory = get_cached_factory(context.type_name)
    if behavior_class in factory.behaviors:
        return Response(response={}, status=201)
    if behavior in context.__behaviors__:
        return Response(response={}, status=201)
    context.add_behavior(behavior)
    return {}
예제 #6
0
async def default_delete(context, request):
    data = await request.json()
    behavior = data.get('behavior', None)
    if behavior not in context.__behaviors__:
        return Response(response={}, status=201)
    context.remove_behavior(behavior)
    return {}
예제 #7
0
async def default_patch(context, request):
    data = await request.json()
    behavior = data.get('behavior', None)
    if behavior in context.__behaviors__:
        return Response(response={}, status=201)
    context.add_behavior(behavior)
    return {}
예제 #8
0
 async def tus_options(self):
     resp = Response(headers={
         'Tus-Resumable': '1.0.0',
         'Tus-Version': '1.0.0',
         'Tus-Max-Size': '1073741824',
         'Tus-Extension': 'creation,expiration'
     })
     return resp
예제 #9
0
 async def __call__(self):
     """Apply CORS on the OPTIONS view."""
     headers = await self.preflight()
     resp = await self.render()
     if isinstance(resp, Response):
         headers.update(resp.headers)
         resp.headers = headers
         return resp
     return Response(response=resp, headers=headers, status=200)
예제 #10
0
    async def tus_create(self):
        try:
            self.field.context.data._p_register()  # register change...
        except AttributeError:
            self.context._p_register()

        # This only happens in tus-java-client, redirect this POST to a PATCH
        if self.request.headers.get('X-HTTP-Method-Override') == 'PATCH':
            return await self.tus_patch()

        file = self.field.get(self.field.context or self.context)
        if not isinstance(file, self.file_class):
            file = self.file_class(content_type=self.request.content_type)
            self.field.set(self.field.context or self.context, file)
        if 'CONTENT-LENGTH' in self.request.headers:
            file._current_upload = int(self.request.headers['CONTENT-LENGTH'])
        else:
            file._current_upload = 0
        if 'UPLOAD-LENGTH' in self.request.headers:
            file._size = int(self.request.headers['UPLOAD-LENGTH'])
        else:
            raise AttributeError('We need upload-length header')

        if 'UPLOAD-MD5' in self.request.headers:
            file._md5 = self.request.headers['UPLOAD-MD5']

        if 'UPLOAD-EXTENSION' in self.request.headers:
            file._extension = self.request.headers['UPLOAD-EXTENSION']

        if 'TUS-RESUMABLE' not in self.request.headers:
            raise AttributeError('TUS needs a TUS version')

        if 'UPLOAD-METADATA' not in self.request.headers:
            file.filename = uuid.uuid4().hex
        else:
            filename = self.request.headers['UPLOAD-METADATA']
            file.filename = base64.b64decode(
                filename.split()[1]).decode('utf-8')

        file._resumable_uri_date = datetime.now(tz=tzutc())

        await file.init_upload(self.context)
        # Location will need to be adapted on aiohttp 1.1.x
        resp = Response(
            headers={
                'Location':
                IAbsoluteURL(self.context, self.request)() + '/@tusupload/' +
                self.field.__name__,  # noqa
                'Tus-Resumable':
                '1.0.0',
                'Access-Control-Expose-Headers':
                'Location,Tus-Resumable'
            },
            status=201)
        return resp
예제 #11
0
    async def __call__(self):
        data = await self.request.json()
        if '@type' not in data or data['@type'] != 'Container':
            return ErrorResponse('NotAllowed',
                                 'can not create this type %s' % data['@type'],
                                 status=401)

        if 'id' not in data:
            return ErrorResponse('NotAllowed', 'We need an id', status=401)

        if not data.get('title'):
            data['title'] = data['id']

        if 'description' not in data:
            data['description'] = ''

        value = await self.context.async_contains(data['id'])

        if value:
            # Already exist
            return ErrorResponse('ConflictId',
                                 'Container with id already exists',
                                 status=409)

        container = await create_content('Container',
                                         id=data['id'],
                                         title=data['title'],
                                         description=data['description'])

        # Special case we don't want the parent pointer
        container.__name__ = data['id']

        await self.context.async_set(data['id'], container)
        await container.install()

        self.request._container_id = container.__name__
        self.request.container = container

        user = get_authenticated_user_id(self.request)

        # Local Roles assign owner as the creator user
        roleperm = IPrincipalRoleManager(container)
        roleperm.assign_role_to_principal('guillotina.Owner', user)

        await notify(
            ObjectAddedEvent(container,
                             self.context,
                             container.__name__,
                             payload=data))

        resp = {'@type': 'Container', 'id': data['id'], 'title': data['title']}
        headers = {'Location': self.request.path + data['id']}

        return Response(response=resp, headers=headers)
예제 #12
0
 async def tus_head(self):
     file = self.field.get(self.field.context or self.context)
     if not isinstance(file, self.file_class):
         raise KeyError('No file on this context')
     head_response = {
         'Upload-Offset': str(file.get_actual_size()),
         'Tus-Resumable': '1.0.0',
         'Access-Control-Expose-Headers': 'Upload-Offset,Upload-Length,Tus-Resumable'
     }
     if file.size:
         head_response['Upload-Length'] = str(file._size)
     resp = Response(headers=head_response)
     return resp
예제 #13
0
    async def __call__(self):
        data = await self.request.json()
        if '@type' not in data and data['@type'] != 'Site':
            return ErrorResponse('NotAllowed',
                                 'can not create this type %s' % data['@type'],
                                 status=401)

        if 'title' not in data and not data['title']:
            return ErrorResponse('NotAllowed', 'We need a title', status=401)

        if 'id' not in data:
            return ErrorResponse('NotAllowed', 'We need an id', status=401)

        if 'description' not in data:
            data['description'] = ''

        value = await self.context.async_contains(data['id'])

        if value:
            # Already exist
            return ErrorResponse('NotAllowed', 'Duplicate id', status=401)

        site = await create_content('Site',
                                    id=data['id'],
                                    title=data['title'],
                                    description=data['description'])

        # Special case we don't want the parent pointer
        site.__name__ = data['id']

        await self.context.async_set(data['id'], site)
        await site.install()

        self.request._site_id = site.__name__

        user = get_authenticated_user_id(self.request)

        # Local Roles assign owner as the creator user
        roleperm = IPrincipalRoleManager(site)
        roleperm.assign_role_to_principal('guillotina.Owner', user)

        await notify(ObjectAddedEvent(site, self.context, site.__name__))

        resp = {'@type': 'Site', 'id': data['id'], 'title': data['title']}
        headers = {'Location': self.request.path + data['id']}

        return Response(response=resp, headers=headers)
예제 #14
0
    async def tus_patch(self):
        try:
            self.field.context.data._p_register()  # register change...
        except AttributeError:
            self.context._p_register()

        file = self.field.get(self.field.context or self.context)
        if 'CONTENT-LENGTH' in self.request.headers:
            to_upload = int(self.request.headers['CONTENT-LENGTH'])
        else:
            raise AttributeError('No content-length header')

        try:
            self.field.context.data._p_register()  # register change...
        except AttributeError:
            self.context._p_register()

        if 'UPLOAD-OFFSET' in self.request.headers:
            file._current_upload = int(self.request.headers['UPLOAD-OFFSET'])
        else:
            raise AttributeError('No upload-offset header')

        self.request._last_read_pos = 0
        data = await read_request_data(self.request, to_upload)

        while data:
            await file.append_data(self.context, data)
            data = await read_request_data(self.request, CHUNK_SIZE)

        await file.finish_upload(self.context)
        expiration = file._resumable_uri_date + timedelta(days=7)

        resp = Response(
            headers={
                'Upload-Offset':
                str(file.get_actual_size()),
                'Tus-Resumable':
                '1.0.0',
                'Upload-Expires':
                expiration.isoformat(),
                'Access-Control-Expose-Headers':
                'Upload-Offset,Upload-Expires,Tus-Resumable'
            })
        return resp
예제 #15
0
    async def __call__(self):
        data = await self.get_data()
        behaviors = data.get('@behaviors', None)
        for behavior in behaviors or ():
            self.context.add_behavior(behavior)

        deserializer = queryMultiAdapter((self.context, self.request),
                                         IResourceDeserializeFromJson)
        if deserializer is None:
            return ErrorResponse('DeserializationError',
                                 'Cannot deserialize type {}'.format(
                                     self.context.type_name),
                                 status=501)

        try:
            await deserializer(data)
        except DeserializationError as e:
            return ErrorResponse('DeserializationError', str(e), status=400)

        await notify(ObjectModifiedEvent(self.context, payload=data))

        return Response(response={}, status=204)
예제 #16
0
    async def handler(self, request):
        """Main handler function for aiohttp."""
        if request.method in WRITING_VERBS:
            try:
                request._db_write_enabled = True
                # We try to avoid collisions on the same instance of
                # guillotina
                view_result = await self.view()
                if isinstance(view_result, ErrorResponse) or \
                        isinstance(view_result, UnauthorizedResponse):
                    # If we don't throw an exception and return an specific
                    # ErrorReponse just abort
                    await abort(request)
                else:
                    await commit(request)

            except Unauthorized as e:
                await abort(request)
                view_result = generate_unauthorized_response(e, request)
            except ConflictError as e:
                view_result = generate_error_response(e, request, 'ConflictDB',
                                                      409)
            except Exception as e:
                await abort(request)
                view_result = generate_error_response(e, request,
                                                      'ServiceError')
        else:
            try:
                view_result = await self.view()
                await abort(request)
            except Unauthorized as e:
                await abort(request)
                view_result = generate_unauthorized_response(e, request)
            except Exception as e:
                await abort(request)
                view_result = generate_error_response(e, request, 'ViewError')

        # Make sure its a Response object to send to renderer
        if not isinstance(view_result, Response):
            view_result = Response(view_result)
        elif view_result is None:
            # Always provide some response to work with
            view_result = Response({})

        # Apply cors if its needed
        cors_headers = apply_cors(request)
        cors_headers.update(view_result.headers)
        view_result.headers = cors_headers

        resp = await self.rendered(view_result)
        if not resp.prepared:
            await resp.prepare(request)
        await resp.write_eof()
        resp._body = None
        resp.force_close()

        futures_to_wait = request._futures.values()
        if futures_to_wait:
            await asyncio.gather(*list(futures_to_wait))

        return resp
예제 #17
0
 async def __call__(self):
     return Response({'foo': 'bar'})
예제 #18
0
    async def handler(self, request):
        """Main handler function for aiohttp."""
        request._view_error = False
        request.record('viewrender')
        if app_settings['check_writable_request'](request):
            try:
                # We try to avoid collisions on the same instance of
                # guillotina
                view_result = await self.view()
                if isinstance(view_result, ErrorResponse) or \
                        isinstance(view_result, UnauthorizedResponse):
                    # If we don't throw an exception and return an specific
                    # ErrorReponse just abort
                    await abort(request)
                    request._view_error = True
                else:
                    await commit(request, warn=False)

            except Unauthorized as e:
                await abort(request)
                view_result = generate_unauthorized_response(e, request)
                request._view_error = True
            except (ConflictError, TIDConflictError) as e:
                # bubble this error up
                raise
            except HTTPException as exc:
                await abort(request)
                return exc
            except Exception as e:
                await abort(request)
                view_result = generate_error_response(e, request,
                                                      'ServiceError')
                request._view_error = True
        else:
            try:
                view_result = await self.view()
            except Unauthorized as e:
                request._view_error = True
                view_result = generate_unauthorized_response(e, request)
            except HTTPException as exc:
                return exc
            except Exception as e:
                request._view_error = True
                view_result = generate_error_response(e, request, 'ViewError')
            finally:
                await abort(request)
        request.record('viewrendered')

        # Make sure its a Response object to send to renderer
        if not isinstance(view_result, Response):
            view_result = Response(view_result)
        elif view_result is None:
            # Always provide some response to work with
            view_result = Response({})

        # Apply cors if its needed
        cors_renderer = app_settings['cors_renderer'](request)
        cors_headers = await cors_renderer.get_headers()
        cors_headers.update(view_result.headers)
        view_result.headers = cors_headers
        retry_attempts = getattr(request, '_retry_attempt', 0)
        if retry_attempts > 0:
            view_result.headers['X-Retry-Transaction-Count'] = str(
                retry_attempts)

        request.record('headers')

        resp = await self.rendered(view_result)
        request.record('rendered')

        request.execute_futures()

        self.debug(request, resp)

        request.record('finish')

        return resp
예제 #19
0
    async def handler(self, request):
        """Main handler function for aiohttp."""
        if request.method in WRITING_VERBS:
            try:
                # We try to avoid collisions on the same instance of
                # guillotina
                view_result = await self.view()
                if isinstance(view_result, ErrorResponse) or \
                        isinstance(view_result, UnauthorizedResponse):
                    # If we don't throw an exception and return an specific
                    # ErrorReponse just abort
                    await abort(request)
                else:
                    await commit(request, warn=False)

            except Unauthorized as e:
                await abort(request)
                view_result = generate_unauthorized_response(e, request)
            except (ConflictError, TIDConflictError) as e:
                # bubble this error up
                raise
            except Exception as e:
                await abort(request)
                view_result = generate_error_response(
                    e, request, 'ServiceError')
        else:
            try:
                view_result = await self.view()
            except Unauthorized as e:
                view_result = generate_unauthorized_response(e, request)
            except Exception as e:
                view_result = generate_error_response(e, request, 'ViewError')
            finally:
                await abort(request)

        # Make sure its a Response object to send to renderer
        if not isinstance(view_result, Response):
            view_result = Response(view_result)
        elif view_result is None:
            # Always provide some response to work with
            view_result = Response({})

        # Apply cors if its needed
        cors_renderer = app_settings['cors_renderer'](request)
        cors_headers = await cors_renderer.get_headers()
        cors_headers.update(view_result.headers)
        view_result.headers = cors_headers
        retry_attempts = getattr(request, '_retry_attempt', 0)
        if retry_attempts > 0:
            view_result.headers['X-Retry-Transaction-Count'] = str(retry_attempts)

        resp = await self.rendered(view_result)
        if not resp.prepared:
            await resp.prepare(request)
        await resp.write_eof()
        resp._body = None
        resp.force_close()

        futures_to_wait = request._futures.values()
        if futures_to_wait:
            await asyncio.gather(*[f for f in futures_to_wait])

        return resp
예제 #20
0
    async def __call__(self):
        """To create a content."""
        data = await self.get_data()
        type_ = data.get('@type', None)
        id_ = data.get('id', None)
        behaviors = data.get('@behaviors', None)

        if '__acl__' in data:
            # we don't allow to change the permisions on this patch
            del data['__acl__']

        if not type_:
            return ErrorResponse('RequiredParam',
                                 _("Property '@type' is required"))

        # Generate a temporary id if the id is not given
        if not id_:
            new_id = None
        else:
            if not valid_id(id_):
                return ErrorResponse('PreconditionFailed',
                                     str('Invalid id'),
                                     status=412)
            new_id = id_

        user = get_authenticated_user_id(self.request)

        # Create object
        try:
            obj = await create_content_in_container(self.context,
                                                    type_,
                                                    new_id,
                                                    id=new_id,
                                                    creators=(user, ),
                                                    contributors=(user, ))
        except (PreconditionFailed, NotAllowedContentType) as e:
            return ErrorResponse('PreconditionFailed', str(e), status=412)
        except ConflictIdOnContainer as e:
            return ErrorResponse('ConflictId', str(e), status=409)
        except ValueError as e:
            return ErrorResponse('CreatingObject', str(e), status=400)

        for behavior in behaviors or ():
            obj.add_behavior(behavior)

        # Update fields
        deserializer = queryMultiAdapter((obj, self.request),
                                         IResourceDeserializeFromJson)
        if deserializer is None:
            return ErrorResponse('DeserializationError',
                                 'Cannot deserialize type {}'.format(
                                     obj.type_name),
                                 status=501)

        try:
            await deserializer(data, validate_all=True)
        except DeserializationError as e:
            return ErrorResponse('DeserializationError',
                                 str(e),
                                 exc=e,
                                 status=400)

        # Local Roles assign owner as the creator user
        get_owner = getUtility(IGetOwner)
        roleperm = IPrincipalRoleManager(obj)
        roleperm.assign_role_to_principal('guillotina.Owner', await
                                          get_owner(obj, user))

        await notify(ObjectAddedEvent(obj, self.context, obj.id, payload=data))

        absolute_url = queryMultiAdapter((obj, self.request), IAbsoluteURL)

        headers = {
            'Access-Control-Expose-Headers': 'Location',
            'Location': absolute_url()
        }

        serializer = queryMultiAdapter((obj, self.request),
                                       IResourceSerializeToJson)
        response = await serializer()
        return Response(response=response, headers=headers, status=201)