async def __call__(self): self.interaction = IInteraction(self.request) definition = copy.deepcopy( app_settings["swagger"]["base_configuration"]) vhm = self.request.headers.get("X-VirtualHost-Monster") if vhm: parsed_url = urlparse(vhm) definition["host"] = parsed_url.netloc definition["schemes"] = [parsed_url.scheme] definition["basePath"] = parsed_url.path else: definition["host"] = self.request.host definition["schemes"] = [get_scheme(self.request)] if 'version' not in definition['info']: definition["info"]["version"] = pkg_resources.get_distribution( "guillotina").version api_defs = app_settings["api_definition"] path = get_full_content_path(self.request, self.context) for dotted_iface in api_defs.keys(): iface = resolve_dotted_name(dotted_iface) if iface.providedBy(self.context): iface_conf = api_defs[dotted_iface] self.get_endpoints(iface_conf, path, definition["paths"]) definition["definitions"] = app_settings["json_schema_definitions"] return definition
async def get_all_types(context, request): result = [] base_url = IAbsoluteURL(context, request)() constrains = IConstrainTypes(context, None) for id, factory in FACTORY_CACHE.items(): add = True if constrains is not None: if not constrains.is_type_allowed(id): add = False if factory.add_permission: if factory.add_permission in PERMISSIONS_CACHE: permission = PERMISSIONS_CACHE[factory.add_permission] else: permission = query_utility(IPermission, name=factory.add_permission) PERMISSIONS_CACHE[factory.add_permission] = permission if permission is not None and \ not IInteraction(request).check_permission( permission.id, context): add = False if add: result.append({ '@id': base_url + '/@types/' + id, 'addable': True, 'title': id }) return result
def get_access_where_clauses(self): users = [] roles = [] request = get_current_request() interaction = IInteraction(request) for user in interaction.participations: users.append(user.principal.id) users.extend(user.principal.groups) roles_dict = interaction.global_principal_roles( user.principal.id, user.principal.groups) roles.extend([key for key, value in roles_dict.items() if value]) clauses = [] if len(users) > 0: clauses.append("json->'access_users' ?| array['{}']".format( "','".join(users) )) if len(roles) > 0: clauses.append("json->'access_roles' ?| array['{}']".format( "','".join(roles) )) return '({})'.format( ' OR '.join(clauses) )
async def handle_ws_request(self, ws, message): method = app_settings['http_methods']['GET'] path = tuple(p for p in message['value'].split('/') if p) # avoid circular import from guillotina.traversal import do_traverse obj, tail = await do_traverse(self.request, self.request.container, path) traverse_to = None if tail and len(tail) == 1: view_name = tail[0] elif tail is None or len(tail) == 0: view_name = '' else: view_name = tail[0] traverse_to = tail[1:] permission = getUtility(IPermission, name='guillotina.AccessContent') allowed = IInteraction(self.request).check_permission( permission.id, obj) if not allowed: response = {'error': 'Not allowed'} ws.send_str(ujson.dumps(response)) try: view = queryMultiAdapter((obj, self.request), method, name=view_name) except AttributeError: view = None if traverse_to is not None: if view is None or not ITraversableView.providedBy(view): response = {'error': 'Not found'} ws.send_str(ujson.dumps(response)) else: try: view = await view.publish_traverse(traverse_to) except Exception as e: logger.error("Exception on view execution", exc_info=e) response = {'error': 'Not found'} ws.send_str(ujson.dumps(response)) view_result = await view() if isinstance(view_result, Response): view_result = view_result.response # Return the value ws.send_str(ujson.dumps(view_result)) # Wait for possible value futures_to_wait = self.request._futures.values() if futures_to_wait: await asyncio.gather(*list(futures_to_wait)) self.request._futures = {}
async def create_content_in_container(parent: Folder, type_: str, id_: str, request: IRequest = None, check_security=True, **kw) -> Resource: """Utility to create a content. This method is the one to use to create content. id_ can be None :param parent: where to create content inside of :param type_: content type to create :param id_: id to give content in parent object :param request: <optional> :param check_security: be able to disable security checks """ factory = get_cached_factory(type_) if check_security and factory.add_permission: if factory.add_permission in PERMISSIONS_CACHE: permission = PERMISSIONS_CACHE[factory.add_permission] else: permission = query_utility(IPermission, name=factory.add_permission) PERMISSIONS_CACHE[factory.add_permission] = permission if request is None: request = get_current_request() if permission is not None and \ not IInteraction(request).check_permission(permission.id, parent): raise NoPermissionToAdd(str(parent), type_) constrains = IConstrainTypes(parent, None) if constrains is not None: if not constrains.is_type_allowed(type_): raise NotAllowedContentType(str(parent), type_) # We create the object with at least the ID obj = factory(id=id_, parent=parent) for key, value in kw.items(): if key == 'id': # the factory sets id continue setattr(obj, key, value) txn = getattr(parent, '_p_jar', None) or get_transaction() if txn is None or not txn.storage.supports_unique_constraints: # need to manually check unique constraints if await parent.async_contains(obj.id): raise ConflictIdOnContainer(f'Duplicate ID: {parent} -> {obj.id}') obj.__new_marker__ = True await notify(BeforeObjectAddedEvent(obj, parent, id_)) await parent.async_set(obj.id, obj) return obj
async def _build_security_query( self, container, query, doc_type=None, size=10, request=None, scroll=None): if query is None: query = {} q = {} # The users who has plone.AccessContent permission by prinperm # The roles who has plone.AccessContent permission by roleperm users = [] roles = [] if request is None: request = get_current_request() interaction = IInteraction(request) for user in interaction.participations: # pylint: disable=E1133 users.append(user.principal.id) users.extend(user.principal.groups) roles_dict = interaction.global_principal_roles( user.principal.id, user.principal.groups) roles.extend([key for key, value in roles_dict.items() if value]) # We got all users and roles # users: users and groups should_list = [{'match': {'access_roles': x}} for x in roles] should_list.extend([{'match': {'access_users': x}} for x in users]) permission_query = { 'query': { 'bool': { 'filter': { 'bool': { 'should': should_list, 'minimum_should_match': 1 } } } } } query = merge_dicts(query, permission_query) # query.update(permission_query) q['body'] = query q['size'] = size if scroll: q['scroll'] = scroll logger.debug(q) return q
async def move(context, request): try: data = await request.json() except Exception: data = {} destination = data.get('destination') if destination is None: destination_ob = context.__parent__ else: try: destination_ob = await navigate_to(request.container, destination) except KeyError: destination_ob = None if destination_ob is None: raise PreconditionFailed(context, 'Could not find destination object') old_id = context.id if 'new_id' in data: new_id = data['new_id'] context.id = context.__name__ = new_id else: new_id = context.id security = IInteraction(request) if not security.check_permission('guillotina.AddContent', destination_ob): raise PreconditionFailed( context, 'You do not have permission to add content to the ' 'destination object') if await destination_ob.async_contains(new_id): raise PreconditionFailed( context, f'Destination already has object with the id {new_id}') original_parent = context.__parent__ txn = get_transaction(request) cache_keys = txn._cache.get_cache_keys(context, 'deleted') data['id'] = new_id await notify( BeforeObjectMovedEvent(context, original_parent, old_id, destination_ob, new_id, payload=data)) context.__parent__ = destination_ob context._p_register() await notify( ObjectMovedEvent(context, original_parent, old_id, destination_ob, new_id, payload=data)) cache_keys += txn._cache.get_cache_keys(context, 'added') await txn._cache.delete_all(cache_keys) absolute_url = query_multi_adapter((context, request), IAbsoluteURL) return { '@url': absolute_url() }
def __init__(self, utility, context, response=noop_response, force=False, log_details=False, memory_tracking=False, request=None, bulk_size=40, full=False, reindex_security=False, mapping_only=False): self.utility = utility self.conn = utility.conn self.context = context self.response = response self.force = force self.full = full self.log_details = log_details self.memory_tracking = memory_tracking self.bulk_size = bulk_size self.reindex_security = reindex_security if mapping_only and full: raise Exception( 'Can not do a full reindex and a mapping only migration') self.mapping_only = mapping_only if request is None: self.request = get_current_request() self.request._db_write_enabled = False else: self.request = request # make sure that we don't cache requests... self.request._txn._cache = DummyCache(self.request._txn) self.container = self.request.container self.interaction = IInteraction(self.request) self.indexer = Indexer() self.batch = {} self.indexed = 0 self.processed = 0 self.missing = [] self.orphaned = [] self.existing = [] self.errors = [] self.mapping_diff = {} self.start_time = self.index_start_time = time.time() self.reindex_futures = [] self.status = 'started' self.active_task_id = None self.copied_docs = 0 self.work_index_name = None
async def resolve_uid(context, request): uid = request.matchdict['uid'] ob = await get_object_by_oid(uid) if ob is None: return HTTPNotFound(content={'reason': f'Could not find uid: {uid}'}) interaction = IInteraction(request) if interaction.check_permission('guillotina.AccessContent', ob): return HTTPMovedPermanently(get_object_url(ob, request)) else: # if a user doesn't have access to it, they shouldn't know anything about it return HTTPNotFound(content={'reason': f'Could not find uid: {uid}'})
async def can_i_do(context, request): if 'permission' not in request.query and 'permissions' not in request.query: raise PreconditionFailed(context, 'No permission param') interaction = IInteraction(request) if 'permissions' in request.GET: results = {} for perm in request.GET['permissions'].split(','): results[perm] = interaction.check_permission(perm, context) return results else: return interaction.check_permission(request.GET['permission'], context)
async def available_actions(self, request): security = IInteraction(request) for action_name, action in self.actions.items(): add = False if 'check_permission' in action and security.check_permission( action['check_permission'], self.context): add = True elif 'check_permission' not in action: add = True if add: yield action_name, action
async def __call__(self): result = {'databases': [], 'static_file': [], 'static_directory': []} allowed = IInteraction(self.request).check_permission( 'guillotina.GetDatabases', self.application) for x in self.application._dbs.keys(): if IDatabase.providedBy(self.application._dbs[x]) and allowed: result['databases'].append(x) if IStaticFile.providedBy(self.application._dbs[x]): result['static_file'].append(x) if IStaticDirectory.providedBy(self.application._dbs[x]): result['static_directory'].append(x) return result
def check_permission(self, permission_name): if permission_name is None: return True if permission_name not in self.permission_cache: permission = query_utility(IPermission, name=permission_name) if permission is None: self.permission_cache[permission_name] = True else: security = IInteraction(self.request) self.permission_cache[permission_name] = bool( security.check_permission(permission.id, self.context)) return self.permission_cache[permission_name]
def _invalidated_interaction_cache(self): # Invalidate this threads interaction cache try: request = get_current_request() except RequestNotFound: return interaction = IInteraction(request) if interaction is not None: try: invalidate_cache = interaction.invalidate_cache except AttributeError: pass else: invalidate_cache()
def get_roles_with_access_content(obj, request=None): """ Return the roles that has access to the content that are global roles""" if obj is None: return [] if request is None: request = get_current_request() interaction = IInteraction(request) roles = interaction.cached_roles(obj, 'guillotina.AccessContent', 'o') result = [] all_roles = role.global_roles() + role.local_roles() for r in roles.keys(): if r in all_roles: result.append(r) return result
def get_principals_with_access_content(obj, request=None): if obj is None: return {} if request is None: request = get_current_request() interaction = IInteraction(request) roles = interaction.cached_roles(obj, 'guillotina.AccessContent', 'o') result = [] all_roles = role.global_roles() + role.local_roles() for r in roles.keys(): if r in all_roles: result.append(r) users = interaction.cached_principals(obj, result, 'guillotina.AccessContent', 'o') return list(users.keys())
async def create_content_in_container(container, type_, id_, request=None, check_security=True, **kw): """Utility to create a content. This method is the one to use to create content. id_ can be None """ factory = get_cached_factory(type_) if check_security and factory.add_permission: if factory.add_permission in PERMISSIONS_CACHE: permission = PERMISSIONS_CACHE[factory.add_permission] else: permission = query_utility(IPermission, name=factory.add_permission) PERMISSIONS_CACHE[factory.add_permission] = permission if request is None: request = get_current_request() if permission is not None and \ not IInteraction(request).check_permission(permission.id, container): raise NoPermissionToAdd(str(container), type_) constrains = IConstrainTypes(container, None) if constrains is not None: if not constrains.is_type_allowed(type_): raise NotAllowedContentType(str(container), type_) # We create the object with at least the ID obj = factory(id=id_, parent=container) for key, value in kw.items(): setattr(obj, key, value) txn = getattr(container, '_p_jar', None) or get_transaction() if txn is None or not txn.storage.supports_unique_constraints: # need to manually check unique constraints if await container.async_contains(obj.id): raise ConflictIdOnContainer( f'Duplicate ID: {container} -> {obj.id}') obj.__new_marker__ = True await notify(BeforeObjectAddedEvent(obj, container, id_)) await container.async_set(obj.id, obj) return obj
async def create_content_in_container(container, type_, id_, request=None, **kw): """Utility to create a content. This method is the one to use to create content. id_ can be None """ factory = get_cached_factory(type_) if factory.add_permission: if factory.add_permission in PERMISSIONS_CACHE: permission = PERMISSIONS_CACHE[factory.add_permission] else: permission = query_utility(IPermission, name=factory.add_permission) PERMISSIONS_CACHE[factory.add_permission] = permission if request is None: request = get_current_request() if permission is not None and \ not IInteraction(request).check_permission(permission.id, container): raise NoPermissionToAdd(str(container), type_) constrains = IConstrainTypes(container, None) if constrains is not None: if not constrains.is_type_allowed(type_): raise NotAllowedContentType(str(container), type_) # We create the object with at least the ID obj = factory(id=id_) obj.__parent__ = container obj.__name__ = obj.id for key, value in kw.items(): setattr(obj, key, value) if request is None or 'OVERWRITE' not in request.headers: if await container.async_contains(obj.id): raise ConflictIdOnContainer(str(container), obj.id) obj.__new_marker__ = True await notify(BeforeObjectAddedEvent(obj, container, id_)) await container.async_set(obj.id, obj) return obj
def check_permission(self, permission_name): if permission_name is None: return True if permission_name not in self.permission_cache: permission = query_utility(IPermission, name=permission_name) if permission is None: self.permission_cache[permission_name] = True else: try: self.permission_cache[permission_name] = bool( IInteraction(self.request).check_permission( permission.id, self.context)) except NoInteraction: # not authenticated return False return self.permission_cache[permission_name]
async def do_action(self, request, action, comments): available_actions = self.actions if action not in available_actions: raise KeyError('Unavailable action') action_def = available_actions[action] security = IInteraction(request) if 'check_permission' in action_def and not security.check_permission( action_def['check_permission'], self.context): raise HTTPUnauthorized() # Change permission new_state = action_def['to'] if 'set_permission' in self.states[new_state]: await apply_sharing(self.context, self.states[new_state]['set_permission']) # Write history user = get_authenticated_user_id(request) history = { 'actor': user, 'comments': comments, 'time': datetime.datetime.now(), 'title': action_def['title'], 'type': 'workflow', 'data': { 'action': action, 'review_state': new_state, } } cms_behavior = ICMSBehavior(self.context) await cms_behavior.load() cms_behavior.review_state = new_state cms_behavior.history.append(history) cms_behavior._p_register() await notify( WorkflowChangedEvent(self.context, self, action, comments)) return history
async def __call__(self): result = await super(SerializeFolderToJson, self).__call__() security = IInteraction(self.request) length = await self.context.async_len() if length > MAX_ALLOWED or length == 0: result['items'] = [] else: result['items'] = [] async for ident, member in self.context.async_items(): if not ident.startswith('_') and bool( security.check_permission('guillotina.AccessContent', member)): result['items'].append(await getMultiAdapter( (member, self.request), IResourceSerializeToJsonSummary)()) result['length'] = length return result
async def items(context, request): try: page_size = int(request.query['page_size']) except Exception: page_size = 20 try: page = int(request.query['page']) except Exception: page = 1 txn = get_transaction(request) include = omit = [] if request.query.get('include'): include = request.query.get('include').split(',') if request.query.get('omit'): omit = request.query.get('omit').split(',') security = IInteraction(request) results = [] for key in await txn.get_page_of_keys(context._p_oid, page=page, page_size=page_size): ob = await context.async_get(key) if not security.check_permission('guillotina.ViewContent', ob): continue serializer = get_multi_adapter((ob, request), IResourceSerializeToJson) try: results.append(await serializer(include=include, omit=omit)) except TypeError: results.append(await serializer()) return { 'items': results, 'total': await context.async_len(), 'page': page, 'page_size': page_size }
async def get_user_info(context, request): """Return information about the logged in user. """ result = {} groups = set() principal = IInteraction(request).principal result[principal.id] = { 'roles': principal.roles, 'groups': principal.groups, 'properties': principal.properties } groups.update(principal.groups) group_search = getUtility(IGroups) result['groups'] = {} for group in groups: group_object = group_search.get_principal(group) result['groups'][group_object.id] = { 'roles': group_object.roles, 'groups': group_object.groups } return result
async def build_security_query(container, request=None): # The users who has plone.AccessContent permission by prinperm # The roles who has plone.AccessContent permission by roleperm users = [] roles = [] if request is None: request = get_current_request() interaction = IInteraction(request) for user in interaction.participations: # pylint: disable=E1133 users.append(user.principal.id) users.extend(user.principal.groups) roles_dict = interaction.global_principal_roles( user.principal.id, user.principal.groups) roles.extend([key for key, value in roles_dict.items() if value]) # We got all users and roles # users: users and groups should_list = [{'match': {'access_roles': x}} for x in roles] should_list.extend([{'match': {'access_users': x}} for x in users]) return { 'query': { 'bool': { 'filter': { 'bool': { 'should': should_list, 'minimum_should_match': 1 } } } } }
async def real_resolve(self, request): """Main function to resolve a request.""" request._futures = {} security = IInteraction(request) method = app_settings['http_methods'][request.method] language = language_negotiation(request) language_object = language(request) try: resource, tail = await self.traverse(request) except ConflictError: # can also happen from connection errors so we bubble this... raise except Exception as _exc: request.resource = request.tail = None request.exc = _exc data = { 'success': False, 'exception_message': str(_exc), 'exception_type': getattr(type(_exc), '__name__', str(type(_exc))), # noqa } if app_settings.get('debug'): data['traceback'] = traceback.format_exc() # XXX should only should traceback if in some sort of dev mode? raise HTTPBadRequest(text=json.dumps(data)) request.resource = resource request.tail = tail if request.resource is None: raise HTTPBadRequest(text='Resource not found') traverse_to = None if tail and len(tail) == 1: view_name = tail[0] elif tail is None or len(tail) == 0: view_name = '' else: view_name = tail[0] traverse_to = tail[1:] await self.apply_authorization(request) translator = queryMultiAdapter( (language_object, resource, request), ITranslated) if translator is not None: resource = translator.translate() # Add anonymous participation if len(security.participations) == 0: security.add(AnonymousParticipation(request)) # container registry lookup try: view = queryMultiAdapter( (resource, request), method, name=view_name) except AttributeError: view = None request.found_view = view request.view_name = view_name # Traverse view if its needed if traverse_to is not None and view is not None: if not ITraversableView.providedBy(view): return None else: try: view = await view.publish_traverse(traverse_to) except Exception as e: logger.error("Exception on view execution", exc_info=e, request=request) return None permission = getUtility(IPermission, name='guillotina.AccessContent') if not security.check_permission(permission.id, resource): # Check if its a CORS call: if IOPTIONS != method: # Check if the view has permissions explicit if view is None or not view.__allow_access__: logger.warning("No access content {content} with {auths}".format( content=resource, auths=str([x.principal.id for x in security.participations])), request=request) raise HTTPUnauthorized() if view is None and method == IOPTIONS: view = DefaultOPTIONS(resource, request) if view: ViewClass = view.__class__ view_permission = get_view_permission(ViewClass) if not security.check_permission(view_permission, view): logger.warning("No access for view {content} with {auths}".format( content=resource, auths=str([x.principal.id for x in security.participations])), request=request) raise HTTPUnauthorized() renderer = content_type_negotiation(request, resource, view) renderer_object = renderer(request) rendered = queryMultiAdapter( (renderer_object, view, request), IRendered) if rendered is not None: return MatchInfo(resource, request, view, rendered) else: return None
async def duplicate(context: IResource, destination: Union[IResource, str] = None, new_id: str = None, check_permission: bool = True) -> IResource: if destination is not None: if isinstance(destination, str): request = get_current_request() destination_ob = await navigate_to(request.container, destination) else: destination_ob = destination if destination_ob is None: raise PreconditionFailed( context, 'Could not find destination object', ) else: destination_ob = context.__parent__ if check_permission: request = get_current_request() security = IInteraction(request) if not security.check_permission('guillotina.AddContent', destination_ob): raise PreconditionFailed( context, 'You do not have permission to add content to ' 'the destination object', ) if new_id is not None: if await destination_ob.async_contains(new_id): raise PreconditionFailed( context, f'Destination already has object with the id {new_id}') else: count = 1 new_id = f'{context.id}-duplicate-{count}' while await destination_ob.async_contains(new_id): count += 1 new_id = f'{context.id}-duplicate-{count}' from guillotina.content import create_content_in_container new_obj = await create_content_in_container( destination_ob, context.type_name, new_id, id=new_id, creators=context.creators, contributors=context.contributors) for key in context.__dict__.keys(): if key.startswith('__') or key.startswith('_BaseObject'): continue if key in ('id', ): continue new_obj.__dict__[key] = context.__dict__[key] new_obj.__acl__ = context.__acl__ for behavior in context.__behaviors__: new_obj.add_behavior(behavior) # need to copy annotation data as well... # load all annotations for context [b for b in await get_all_behaviors(context, load=True)] annotations_container = IAnnotations(new_obj) for anno_id, anno_data in context.__gannotations__.items(): new_anno_data = AnnotationData() for key, value in anno_data.items(): new_anno_data[key] = value await annotations_container.async_set(anno_id, new_anno_data) await notify( ObjectDuplicatedEvent(new_obj, context, destination_ob, new_id, payload={ 'id': new_id, 'destination': destination, })) return new_obj
async def move(context: IResource, destination: Union[IResource, str] = None, new_id: str = None, check_permission: bool = True) -> None: if destination is None: destination_ob = context.__parent__ else: if isinstance(destination, str): request = get_current_request() try: destination_ob = await navigate_to(request.container, destination) except KeyError: destination_ob = None else: destination_ob = destination if destination_ob is None: raise PreconditionFailed(context, 'Could not find destination object') old_id = context.id if new_id is not None: context.id = context.__name__ = new_id else: new_id = context.id if check_permission: request = get_current_request() security = IInteraction(request) if not security.check_permission('guillotina.AddContent', destination_ob): raise PreconditionFailed( context, 'You do not have permission to add content to the ' 'destination object') if await destination_ob.async_contains(new_id): raise PreconditionFailed( context, f'Destination already has object with the id {new_id}') original_parent = context.__parent__ txn = get_transaction(request) cache_keys = txn._cache.get_cache_keys(context, 'deleted') await notify( BeforeObjectMovedEvent(context, original_parent, old_id, destination_ob, new_id, payload={ 'id': new_id, 'destination': destination })) context.__parent__ = destination_ob context._p_register() await notify( ObjectMovedEvent(context, original_parent, old_id, destination_ob, new_id, payload={ 'id': new_id, 'destination': destination })) cache_keys += txn._cache.get_cache_keys(context, 'added') await txn._cache.delete_all(cache_keys)
async def duplicate(context, request): try: data = await request.json() except Exception: data = {} destination = data.get('destination') if destination is not None: destination_ob = await navigate_to(request.container, destination) if destination_ob is None: raise PreconditionFailed( context, 'Could not find destination object', ) else: destination_ob = context.__parent__ security = IInteraction(request) if not security.check_permission('guillotina.AddContent', destination_ob): raise PreconditionFailed( context, 'You do not have permission to add content to ' 'the destination object', ) if 'new_id' in data: new_id = data['new_id'] if await destination_ob.async_contains(new_id): raise PreconditionFailed( context, f'Destination already has object with the id {new_id}') else: count = 1 new_id = f'{context.id}-duplicate-{count}' while await destination_ob.async_contains(new_id): count += 1 new_id = f'{context.id}-duplicate-{count}' new_obj = await create_content_in_container( destination_ob, context.type_name, new_id, id=new_id, creators=context.creators, contributors=context.contributors) for key in context.__dict__.keys(): if key.startswith('__') or key.startswith('_BaseObject'): continue if key in ('id', ): continue new_obj.__dict__[key] = context.__dict__[key] new_obj.__acl__ = context.__acl__ for behavior in context.__behaviors__: new_obj.add_behavior(behavior) # need to copy annotation data as well... # load all annotations for context [b for b in await get_all_behaviors(context, load=True)] annotations_container = IAnnotations(new_obj) for anno_id, anno_data in context.__gannotations__.items(): new_anno_data = AnnotationData() for key, value in anno_data.items(): new_anno_data[key] = value await annotations_container.async_set(anno_id, new_anno_data) data['id'] = new_id await notify( ObjectDuplicatedEvent(new_obj, context, destination_ob, new_id, payload=data)) get = DefaultGET(new_obj, request) return await get()
async def __call__(self): ws = web.WebSocketResponse() await ws.prepare(self.request) async for msg in ws: if msg.tp == aiohttp.MsgType.text: message = ujson.loads(msg.data) if message['op'] == 'close': await ws.close() elif message['op'] == 'GET': method = app_settings['http_methods']['GET'] path = tuple(p for p in message['value'].split('/') if p) # avoid circular import from guillotina.traversal import do_traverse obj, tail = await do_traverse(self.request, self.request.site, path) traverse_to = None if tail and len(tail) == 1: view_name = tail[0] elif tail is None or len(tail) == 0: view_name = '' else: view_name = tail[0] traverse_to = tail[1:] permission = getUtility(IPermission, name='guillotina.AccessContent') allowed = IInteraction(self.request).check_permission( permission.id, obj) if not allowed: response = {'error': 'Not allowed'} ws.send_str(ujson.dumps(response)) try: view = queryMultiAdapter((obj, self.request), method, name=view_name) except AttributeError: view = None if traverse_to is not None: if view is None or not ITraversableView.providedBy( view): response = {'error': 'Not found'} ws.send_str(ujson.dumps(response)) else: try: view = await view.publish_traverse(traverse_to) except Exception as e: logger.error("Exception on view execution", exc_info=e) response = {'error': 'Not found'} ws.send_str(ujson.dumps(response)) view_result = await view() if isinstance(view_result, Response): view_result = view_result.response # Return the value ws.send_str(ujson.dumps(view_result)) # Wait for possible value futures_to_wait = self.request._futures.values() if futures_to_wait: await asyncio.gather(futures_to_wait) self.request._futures = {} else: await ws.close() elif msg.tp == aiohttp.MsgType.error: logger.debug( 'ws connection closed with exception {0:s}'.format( ws.exception())) logger.debug('websocket connection closed') return {}
async def can_i_do(context, request): if 'permission' not in request.query: raise TypeError('No permission param') permission = request.query['permission'] return IInteraction(request).check_permission(permission, context)