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 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 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
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 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]
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 __call__(self, include=[], omit=[]): result = await super(SerializeFolderToJson, self).__call__(include=include, omit=omit) 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(suppress_events=True): if not ident.startswith('_') and bool( security.check_permission( 'guillotina.AccessContent', member)): result['items'].append( await get_multi_adapter( (member, self.request), IResourceSerializeToJsonSummary)()) result['length'] = length return result
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: 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 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