async def modify_comment(context, request): payload = await request.json() comment_id = request.matchdict["comment_id"] bhr = ICMSBehavior(context) if not bhr.allow_discussion: raise HTTPUnauthorized(content={"text": "Not available option"}) await bhr.load() if comment_id not in bhr.comments: raise ErrorResponse("InvalidComment", "This comment does not exist", status=412) user_id = get_authenticated_user_id() comment = bhr.comments[comment_id] # TODO: We need ? if user_id != comment["author_username"]: raise HTTPUnauthorized(content={"text": "Not the author"}) comment["text"]["data"] = payload.get("text", "") comment["modification_date"] = datetime.now().isoformat() bhr.register() url = getMultiAdapter((context, request), IAbsoluteURL)() headers = {"Location": url + "/@comments/" + comment_id} return Response(status=204, headers=headers)
def log(self, *args, **kwargs): from guillotina.utils import get_authenticated_user_id from guillotina.utils import get_current_request from guillotina.exceptions import RequestNotFound func = getattr(self._logger, name) request = kwargs.pop('request', None) eid = kwargs.pop('eid', None) if request is None: try: request = get_current_request() except RequestNotFound: pass if request is not None: if eid is None: eid = uuid.uuid4().hex extra = kwargs.get('extra', {}) try: url = request.url.human_repr() except AttributeError: # older version of aiohttp url = request.path extra.update({ 'method': request.method, 'url': url, 'container': getattr(request, '_container_id', None), 'db_id': getattr(request, '_db_id', None), 'user': get_authenticated_user_id(request) or 'Anonymous', 'eid': eid }) kwargs['extra'] = extra return func(*args, **kwargs)
async def begin(self, request=None): """Starts a new transaction. """ self._db_conn = await self._storage.open() if request is None: if self.request is None: self.request = get_current_request() request = self.request user = get_authenticated_user_id(request) if self._txn is not None: if self._pool is None: self._pool = LifoQueue() # Save the actual transaction and start a new one self._pool.put(self._txn) self._txn = txn = Transaction(self, request=request) # CACHE!! if user is not None: txn.user = user await txn.tpc_begin(self._db_conn) return txn
async def __call__(self): data = await self.request.json() if '@type' not in data or data['@type'] not in app_settings['container_types']: raise HTTPNotFound(content={ 'message': 'can not create this type %s' % data['@type'] }) if 'id' not in data: raise HTTPPreconditionFailed(content={ 'message': 'We need an id' }) 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 raise HTTPConflict(content={ 'message': 'Container with id already exists' }) install_addons = data.pop('@addons', None) or [] for addon in install_addons: # validate addon list if addon not in app_settings['available_addons']: return ErrorResponse( 'RequiredParam', "Property '@addons' must refer to a valid addon", status=412, reason=error_reasons.INVALID_ID) owner_id = get_authenticated_user_id(self.request) container = await create_container( self.context, data.pop('id'), container_type=data.pop('@type'), owner_id=owner_id, **data) self.request._container_id = container.__name__ self.request.container = container annotations_container = get_adapter(container, IAnnotations) self.request.container_settings = await annotations_container.async_get(REGISTRY_DATA_KEY) for addon in install_addons: await addons.install(container, addon) resp = { '@type': container.type_name, 'id': container.id, 'title': data['title'] } headers = { 'Location': posixpath.join(self.request.path, container.id) } return Response(content=resp, headers=headers)
async def add_comment(context, request): payload = await request.json() bhr = ICMSBehavior(context) if not bhr.allow_discussion: raise HTTPUnauthorized(content={"text": "Not available option"}) await bhr.load() if bhr.comments is None: bhr.comments = {} user_id = get_authenticated_user_id() comment_uuid = uuid.uuid4().hex bhr.comments[comment_uuid] = { "@parent": None, "author_name": None, "author_username": user_id, "creation_date": datetime.now().isoformat(), "in_reply_to": None, "is_deletable": True, "is_editable": True, "modification_date": datetime.now().isoformat(), "text": { "data": payload.get("text", ""), "mime-type": "text/plain" }, "user_notification": None, } bhr.register() url = getMultiAdapter((context, request), IAbsoluteURL)() headers = {"Location": url + "/@comments/" + comment_uuid} return Response(status=204, headers=headers)
async def __call__(self): data = await self.request.json() if '@type' not in data or data['@type'] not in app_settings[ 'container_types']: raise HTTPNotFound( content={ 'message': 'can not create this type %s' % data['@type'] }) if 'id' not in data: raise HTTPPreconditionFailed(content={'message': 'We need an id'}) 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 raise HTTPConflict( content={'message': 'Container with id already exists'}) install_addons = data.pop('@addons', None) or [] for addon in install_addons: # validate addon list if addon not in app_settings['available_addons']: return ErrorResponse( 'RequiredParam', "Property '@addons' must refer to a valid addon", status=412, reason=error_reasons.INVALID_ID) owner_id = get_authenticated_user_id(self.request) container = await create_container(self.context, data.pop('id'), container_type=data.pop('@type'), owner_id=owner_id, **data) self.request._container_id = container.__name__ self.request.container = container annotations_container = get_adapter(container, IAnnotations) self.request.container_settings = await annotations_container.async_get( REGISTRY_DATA_KEY) for addon in install_addons: await addons.install(container, addon) resp = { '@type': container.type_name, 'id': container.id, 'title': data['title'] } headers = {'Location': posixpath.join(self.request.path, container.id)} return Response(content=resp, headers=headers)
async def cms_object_added(obj, event): cms = query_adapter(obj, ICMSBehavior) if cms is not None: request = get_current_request() user_id = get_authenticated_user_id(request) workflow = IWorkflow(obj) await cms.load(create=True) state = cms.review_state if 'set_permission' in workflow.states[state]: await apply_sharing(obj, workflow.states[state]['set_permission']) setattr(cms, 'history', []) cms.history.append({ 'actor': user_id, 'comments': '', 'time': datetime.datetime.now(), 'title': 'Created', 'type': 'workflow', 'data': { 'action': None, 'review_state': state, } }) cms._p_register() if hasattr(obj, 'title') and obj.title is None: obj.title = obj.id
async def __call__(self): data = await self.request.json() if "@type" not in data or data["@type"] not in app_settings[ "container_types"]: raise HTTPNotFound( content={ "message": "can not create this type %s" % data["@type"] }) if "id" not in data: raise HTTPPreconditionFailed(content={"message": "We need an id"}) 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 raise HTTPConflict( content={"message": "Container with id already exists"}) install_addons = data.pop("@addons", None) or [] for addon in install_addons: # validate addon list if addon not in app_settings["available_addons"]: return ErrorResponse( "RequiredParam", "Property '@addons' must refer to a valid addon", status=412, reason=error_reasons.INVALID_ID, ) owner_id = get_authenticated_user_id() container = await create_container(self.context, data.pop("id"), container_type=data.pop("@type"), owner_id=owner_id, **data) task_vars.container.set(container) annotations_container = get_adapter(container, IAnnotations) task_vars.registry.set( await annotations_container.async_get(REGISTRY_DATA_KEY)) for addon in install_addons: await addons.install(container, addon) resp = { "@type": container.type_name, "id": container.id, "title": data["title"] } headers = {"Location": posixpath.join(self.request.path, container.id)} return Response(content=resp, headers=headers)
async def begin(self, read_only: bool = False) -> ITransaction: """Starts a new transaction. """ # already has txn registered, as long as connection is closed, it # is safe txn: typing.Optional[ITransaction] = task_vars.txn.get() if (txn is not None and txn.manager == self and txn.status in (Status.ABORTED, Status.COMMITTED, Status.CONFLICT)): # re-use txn if possible txn.status = Status.ACTIVE if (txn._db_conn is not None and getattr(txn._db_conn, '_in_use', None) is None): try: await self._close_txn(txn) except Exception: logger.warn('Unable to close spurious connection', exc_info=True) else: txn = Transaction(self, read_only=read_only) try: txn.user = get_authenticated_user_id() except RequestNotFound: pass await txn.tpc_begin() # make sure to explicitly set! task_vars.txn.set(txn) return txn
async def workflow_object_added(obj, event): workflow = query_adapter(obj, IWorkflowBehavior) wkf = query_adapter(obj, IWorkflow) if workflow is not None and wkf is not None: user_id = get_authenticated_user_id() await workflow.load(create=True) state = workflow.review_state if "set_permission" in wkf.states[state]: await apply_sharing(obj, wkf.states[state]["set_permission"]) setattr(workflow, "history", []) workflow.history.append({ "actor": user_id, "comments": "", "time": datetime.datetime.now(), "title": "Created", "type": "workflow", "data": { "action": None, "review_state": state }, }) workflow.register()
async def delete_comment(context, request): comment_id = request.matchdict["comment_id"] bhr = ICMSBehavior(context) if not bhr.allow_discussion: raise HTTPUnauthorized(content={"text": "Not available option"}) await bhr.load() if comment_id not in bhr.comments: raise ErrorResponse("InvalidComment", "This comment does not exist", status=412) user_id = get_authenticated_user_id() comment = bhr.comments[comment_id] # TODO: We need ? policy = get_security_policy() if user_id != comment["author_username"] or not policy.check_permission( "guillotina.DeleteAllComments", context): raise HTTPUnauthorized( content={"text": "Not the author or permission"}) list_to_delete = [comment_id] delete_from_list(bhr.comments, list_to_delete) for comment in list_to_delete: del bhr.comments[comment] bhr.register() return Response(status=204)
async def __call__(self): data = await self.request.json() if '@type' not in data or data['@type'] not in app_settings[ 'container_types']: raise HTTPNotFound( content={ 'message': 'can not create this type %s' % data['@type'] }) if 'id' not in data: raise HTTPPreconditionFailed(content={'message': 'We need an id'}) 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 raise HTTPConflict( content={'message': 'Container with id already exists'}) container = await create_content(data['@type'], 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': data['@type'], 'id': data['id'], 'title': data['title'] } headers = {'Location': posixpath.join(self.request.path, data['id'])} return Response(content=resp, headers=headers)
def generate_unauthorized_response(e, request): # We may need to check the roles of the users to show the real error eid = uuid.uuid4().hex message = _('Not authorized to render operation') + ' ' + eid user = get_authenticated_user_id(request) extra = {'r': _url(request), 'u': user} logger.error(message, exc_info=e, extra=extra) return UnauthorizedResponse(message)
def generate_error_response(e, request, error, status=400): # We may need to check the roles of the users to show the real error eid = uuid.uuid4().hex message = _('Error on execution of view') + ' ' + eid user = get_authenticated_user_id(request) extra = {'r': _url(request), 'u': user} logger.error(message, exc_info=e, extra=extra) return ErrorResponse(error, message, status)
async def container_added(conversation, event): user_id = get_authenticated_user_id() if user_id not in conversation.users: conversation.users.append(user_id) manager = IPrincipalRoleManager(conversation) for user in conversation.users or []: manager.assign_role_to_principal( 'guillotina_chat.ConversationParticipant', user)
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)
async def get_conversations(context, request): results = [] conversations = await context.async_get('conversations') user_id = get_authenticated_user_id(request) async for conversation in conversations.async_values(): if user_id in conversation.users: summary = await getMultiAdapter((conversation, request), IResourceSerializeToJsonSummary)() results.append(summary) results = sorted(results, key=lambda conv: conv['creation_date']) return results
async def asubscribers(self, objects, provided): from guillotina.utils import get_current_request, get_authenticated_user_id, get_dotted_name from guillotina.exceptions import RequestNotFound from guillotina import task_vars if len(objects) > 1: event = get_dotted_name(objects[1]) context = getattr(objects[0], "__uuid__", None) else: event = get_dotted_name(objects[0]) context = None try: request = get_current_request() except RequestNotFound: request = None try: url = request.url.human_repr() except AttributeError: # older version of aiohttp url = "" info = { "url": url, "container": getattr(task_vars.container.get(), "id", None), "user": get_authenticated_user_id(), "db_id": getattr(task_vars.db.get(), "id", None), "request_uid": getattr(request, "_uid", None), "method": getattr(request, "method", None), "subscribers": [], "context": context, "event": event, } start = time.time() * 1000 subscriptions = sorted( self.subscriptions(map(providedBy, objects), provided), key=lambda sub: getattr(sub, "priority", 100), ) info["lookup_time"] = (time.time() * 1000) - start info["found"] = len(subscriptions) results = [] for subscription in subscriptions: start = time.time() * 1000 if asyncio.iscoroutinefunction(subscription): results.append(await subscription(*objects)) else: results.append(subscription(*objects)) info["subscribers"].append({ "duration": (time.time() * 1000) - start, "name": get_dotted_name(subscription) }) info["duration"] = (time.time() * 1000) - start profile_logger.info(info) return results
async def addfavorite(context, request): user = get_authenticated_user_id(request) behavior = IFollowing(context) await behavior.load(True) users_list = behavior.favorites if not users_list: behavior.favorites = [] users_list = behavior.favorites if user not in users_list: users_list.append(user) behavior.data._p_register() await notify(ObjectModifiedEvent(context, payload={'favorites': ''}))
async def deletefavorite(context, request): user = get_authenticated_user_id() behavior = IFollowing(context) await behavior.load(True) users_list = behavior.favorites if users_list is None: behavior.favorites = [] users_list = behavior.favorites if user in users_list: users_list.remove(user) behavior.data.register() await notify(ObjectModifiedEvent(context, payload={"favorites": ""}))
async def install(self, site, request): registry = await get_registry() registry.for_interface(ILayers)['active_layers'] |= {USERS_LAYER} user = get_authenticated_user_id() await create_content_in_container(site, 'UserManager', 'users', creators=(user, ), title='Users') await create_content_in_container(site, 'GroupManager', 'groups', creators=(user, ), title='Groups')
async def install(self, site, request): registry = await get_registry() registry.for_interface(ILayers)["active_layers"] |= {USERS_LAYER} user = get_authenticated_user_id() await create_content_in_container(site, "UserManager", "users", creators=(user, ), title="Users") await create_content_in_container(site, "GroupManager", "groups", creators=(user, ), title="Groups")
async def start(self, dm): """Init an upload. _uload_file_id : temporal url to image beeing uploaded _resumable_uri : uri to resumable upload _uri : finished uploaded image """ util = get_utility(IGCloudBlobStore) request = get_current_request() upload_file_id = dm.get("upload_file_id") if upload_file_id is not None: await self.delete_upload(upload_file_id) generator = get_multi_adapter((self.context, self.field), IFileNameGenerator) upload_file_id = await apply_coroutine(generator) init_url = "{}&name={}".format( UPLOAD_URL.format(bucket=await util.get_bucket_name()), quote_plus(upload_file_id), ) creator = get_authenticated_user_id() metadata = json.dumps({ "CREATOR": creator, "REQUEST": str(request), "NAME": dm.get("filename") }) call_size = len(metadata) async with util.session.post( init_url, headers={ "AUTHORIZATION": "Bearer {}".format(await util.get_access_token()), "X-Upload-Content-Type": to_str(dm.content_type), "X-Upload-Content-Length": str(dm.size), "Content-Type": "application/json; charset=UTF-8", "Content-Length": str(call_size), }, data=metadata, ) as call: if call.status != 200: text = await call.text() raise GoogleCloudException(f"{call.status}: {text}") resumable_uri = call.headers["Location"] await dm.update(current_upload=0, resumable_uri=resumable_uri, upload_file_id=upload_file_id)
async def get_user_info(context, request): userid = get_authenticated_user_id(request) if userid == 'root': raise HTTPBadRequest(content={ 'reason': 'not a valid user' }) user = await utils.find_user(id=userid) if user is None: raise HTTPPreconditionFailed(content={ 'reason': 'Not a valid user' }) if 'password' in user: del user['password'] return user
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)
async def begin(self, request=None): """Starts a new transaction. """ if request is None: try: request = get_current_request() except RequestNotFound: pass user = None txn = None # already has txn registered, as long as connection is closed, it # is safe if (getattr(request, '_txn', None) is not None and request._txn.status in (Status.ABORTED, Status.COMMITTED, Status.CONFLICT)): # re-use txn if possible txn = request._txn txn.status = Status.ACTIVE if txn._db_conn is not None: try: await self._close_txn(txn) except Exception: logger.warn('Unable to close spurious connection', exc_info=True) else: txn = Transaction(self, request=request) self._last_txn = txn if request is not None: # register tm and txn with request request._tm = self request._txn = txn user = get_authenticated_user_id(request) if user is not None: txn.user = user db_conn = self._last_db_conn = await self._storage.open() txn._query_count_start = _get_conn_query_count(db_conn) await txn.tpc_begin(db_conn) return txn
async def begin(self, request=None): """Starts a new transaction. """ if request is None: try: request = get_current_request() except RequestNotFound: pass user = None txn = None # already has txn registered, as long as connection is closed, it # is safe if (getattr(request, '_txn', None) is not None and request._txn.status in (Status.ABORTED, Status.COMMITTED, Status.CONFLICT)): # re-use txn if possible txn = request._txn txn.status = Status.ACTIVE if (txn._db_conn is not None and getattr(txn._db_conn, '_in_use', None) is None): try: await self._close_txn(txn) except Exception: logger.warn('Unable to close spurious connection', exc_info=True) else: txn = Transaction(self, request=request) self._last_txn = txn if request is not None: # register tm and txn with request request._tm = self request._txn = txn user = get_authenticated_user_id(request) if user is not None: txn.user = user await txn.tpc_begin() return txn
async def begin(self, request=None): """Starts a new transaction. """ db_conn = self._last_db_conn = await self._storage.open() if request is None: try: request = get_current_request() except RequestNotFound: pass user = None txn = None # already has txn registered, as long as connection is closed, it # is safe if (getattr(request, '_txn', None) is not None and request._txn._db_conn is None and request._txn.status in (Status.ABORTED, Status.COMMITTED)): # re-use txn if possible txn = request._txn txn.status = Status.ACTIVE # XXX do we want to auto clean up here? Or throw an error? # This will break tests that are starting multiple transactions # else: # await self._close_txn(request._txn) else: txn = Transaction(self, request=request) self._last_txn = txn if request is not None: # register tm and txn with request request._tm = self request._txn = txn user = get_authenticated_user_id(request) if user is not None: txn.user = user await txn.tpc_begin(db_conn) return txn
def log(self, *args, **kwargs): from guillotina.utils import get_authenticated_user_id from guillotina.utils import get_current_request from guillotina.exceptions import RequestNotFound func = getattr(self._logger, name) request = kwargs.pop("request", None) eid = kwargs.pop("eid", None) if request is None: try: request = get_current_request() except RequestNotFound: pass if request is not None: if eid is None: eid = uuid.uuid4().hex extra = kwargs.get("extra", {}) try: url = request.url.human_repr() except AttributeError: # older version of aiohttp url = request.path try: agent = request.headers["User-Agent"] except (AttributeError, KeyError): agent = "Unknown" container = task_vars.container.get() db = task_vars.db.get() extra.update({ "method": request.method, "url": url, "container": getattr(container, "id", None), "account": getattr(container, "id", None), "db_id": getattr(db, "id", None), "user": get_authenticated_user_id() or "Anonymous", "eid": eid, "agent": agent, # in case a fake req object doesn't use the guillotina Request object "request_uid": getattr(request, "uid", None), }) kwargs["extra"] = extra return func(*args, **kwargs)
def log(self, *args, **kwargs): from guillotina.utils import get_authenticated_user_id from guillotina.utils import get_current_request from guillotina.exceptions import RequestNotFound func = getattr(self._logger, name) request = kwargs.pop('request', None) eid = kwargs.pop('eid', None) if request is None: try: request = get_current_request() except RequestNotFound: pass if request is not None: if eid is None: eid = uuid.uuid4().hex extra = kwargs.get('extra', {}) try: url = request.url.human_repr() except AttributeError: # older version of aiohttp url = request.path try: agent = request.headers['User-Agent'] except (AttributeError, KeyError): agent = 'Unknown' container = task_vars.container.get() db = task_vars.db.get() extra.update({ 'method': request.method, 'url': url, 'container': getattr(container, 'id', None), 'account': getattr(container, 'id', None), 'db_id': getattr(db, 'id', None), 'user': get_authenticated_user_id() or 'Anonymous', 'eid': eid, 'agent': agent, # in case a fake req object doesn't use the guillotina Request object 'request_uid': getattr(request, 'uid', None) }) kwargs['extra'] = extra return func(*args, **kwargs)
async def do_action(self, action, comments): available_actions = self.actions if action not in available_actions: raise HTTPPreconditionFailed( content={"reason": "Unavailable action"}) action_def = available_actions[action] policy = get_security_policy() if "check_permission" in action_def and not policy.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() history = { "actor": user, "comments": comments, "time": datetime.datetime.now(), "title": action_def["title"], "type": "workflow", "data": { "action": action, "review_state": new_state }, } workflow_behavior = IWorkflowBehavior(self.context) workflow_behavior.review_state = new_state workflow_behavior.history.append(history) workflow_behavior.register() await notify( WorkflowChangedEvent(self.context, self, action, comments)) return history
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] policy = get_security_policy() if 'check_permission' in action_def and not policy.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() 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.register() await notify( WorkflowChangedEvent(self.context, self, action, comments)) return history
def log(self, *args, **kwargs): from guillotina.utils import get_authenticated_user_id from guillotina.utils import get_current_request from guillotina.exceptions import RequestNotFound func = getattr(self._logger, name) request = kwargs.pop('request', None) eid = kwargs.pop('eid', None) if request is None: try: request = get_current_request() except RequestNotFound: pass if request is not None: if eid is None: eid = uuid.uuid4().hex extra = kwargs.get('extra', {}) try: url = request.url.human_repr() except AttributeError: # older version of aiohttp url = request.path try: agent = request.headers['User-Agent'] except (AttributeError, KeyError): agent = 'Unknown' extra.update({ 'method': request.method, 'url': url, 'container': getattr(request, '_container_id', None), 'account': getattr(request, '_container_id', None), 'db_id': getattr(request, '_db_id', None), 'user': get_authenticated_user_id(request) or 'Anonymous', 'eid': eid, 'agent': agent, # in case a fake req object doesn't use the guillotina Request object 'request_uid': getattr(request, 'uid', None) }) kwargs['extra'] = extra return func(*args, **kwargs)