async def reindex(self, obj): index_manager = find_index_manager(obj) if index_manager is None: index_manager = get_adapter(self.request.container, IIndexManager) self.work_index_name = await index_manager.get_index_name() await notify(IndexProgress( self.request, self.context, 0, self.processed)) await self.process_object(obj) await self.flush() if len(self.sub_indexes) > 0: # could cause sub indexes to need to be run through as well. for ob in self.sub_indexes: im = get_adapter(ob, IIndexManager) reindexer = Reindexer( self.utility, ob, response=self.response, force=self.force, log_details=self.log_details, memory_tracking=self.memory_tracking, request=self.request, bulk_size=self.bulk_size, full=self.full, reindex_security=self.reindex_security, mapping_only=self.mapping_only, index_manager=im) reindexer.processed = self.processed reindexer.work_index_name = await im.get_index_name() await reindexer.process_folder(ob) await reindexer.flush() self.processed = reindexer.processed await notify(IndexProgress( self.request, self.context, self.processed, self.processed, completed=True ))
def __init__(self, manager, request=None, loop=None): self._txn_time = None self._tid = None self.status = Status.ACTIVE # Transaction Manager self._manager = manager # List of objects added # needs to be ordered because content inserted after other might # reference each other self.added = OrderedDict() self.modified = {} self.deleted = {} # OIDS to invalidate self._objects_to_invalidate = [] # List of (hook, args, kws) tuples added by addBeforeCommitHook(). self._before_commit = [] # List of (hook, args, kws) tuples added by addAfterCommitHook(). self._after_commit = [] logger.debug("new transaction") # Connection to DB self._db_conn = None # Transaction on DB self._db_txn = None # Lock on the transaction # some databases need to lock during queries # this provides a lock for each transaction # which would correspond with one connection self._lock = asyncio.Lock(loop=loop) # we *not* follow naming standards of using "_request" here so # get_current_request can magically find us here... self.request = request self._strategy = get_adapter( self, ITransactionStrategy, name=manager._storage._transaction_strategy) self._cache = get_adapter(self, IStorageCache, name=manager._storage._cache_strategy) self._query_count_start = self._query_count_end = 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)
async def test_removes_orphans(es_requester): async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester) search = get_utility(ICatalogUtility) await search.index( container, {'foobar': { 'title': 'foobar', 'type_name': 'Item' }}) # foobar here is an orphaned object because it doesn't reference # an object im = get_adapter(container, IIndexManager) index_name = await im.get_index_name() # alias doc = await search.conn.get(index=index_name, doc_type=DOC_TYPE, id='foobar') assert doc['found'] migrator = Migrator(search, container, force=True) await migrator.run_migration() async def _test(): with pytest.raises(aioelasticsearch.exceptions.NotFoundError): await search.conn.get(index=index_name, doc_type=DOC_TYPE, id='foobar') assert len(migrator.orphaned) == 1 assert migrator.orphaned[0] == 'foobar' await run_with_retries(_test, requester)
async def test_delete_in_both_during_migration(es_requester): async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester) search = get_utility(ICatalogUtility) migrator = Migrator(search, container, force=True, request=request) im = get_adapter(container, IIndexManager) index_name = await im.get_index_name() next_index_name = await migrator.setup_next_index() resp, _ = await requester('POST', '/db/guillotina', data=json.dumps({ '@type': 'Folder', 'title': 'Foobar1', 'id': 'foobar' })) await requester('DELETE', '/db/guillotina/foobar') async def _test(): with pytest.raises(aioelasticsearch.exceptions.NotFoundError): await search.conn.get(index=next_index_name, doc_type='_all', id=resp['@uid']) with pytest.raises(aioelasticsearch.exceptions.NotFoundError): await search.conn.get(index=index_name, doc_type='_all', id=resp['@uid']) await run_with_retries(_test, requester)
async def test_search_works_on_new_docs_during_migration(es_requester): async with es_requester as requester: await add_content(requester, 2) container, request, txn, tm = await setup_txn_on_container(requester) search = get_utility(ICatalogUtility) migrator = Migrator(search, container, force=True, request=request) im = get_adapter(container, IIndexManager) index_name = await im.get_index_name() next_index_name = await migrator.setup_next_index() resp, _ = await requester('POST', '/db/guillotina', data=json.dumps({'@type': 'Item'})) async def _test(): result1 = await search.conn.get(index=next_index_name, doc_type='_all', id=resp['@uid']) assert result1 is not None result2 = await search.conn.get(index=index_name, doc_type='_all', id=resp['@uid']) assert result2 is not None await run_with_retries(_test, requester)
def initialize( self, read_only, cache=None, strategy=None, ): self._read_only = read_only self._txn_time = None self._tid = None self.status = Status.ACTIVE self.user = None # List of objects added # needs to be ordered because content inserted after other might # reference each other self.added = OrderedDict() self.added_children = {} self.modified = {} self.deleted = {} # List of (hook, args, kws) tuples added by addBeforeCommitHook(). self._before_commit = [] # List of (hook, args, kws) tuples added by addAfterCommitHook(). self._after_commit = [] self._cache = cache or query_adapter(self, ITransactionCache, name=app_settings["cache"]["strategy"]) self._strategy = strategy or get_adapter( self, ITransactionStrategy, name=self._manager._storage._transaction_strategy ) self._query_count_start = self._query_count_end = 0
async def iter_databases(root=None): if root is None: root = get_utility(IApplication, name='root') loaded = [] for _, db in root: if IDatabase.providedBy(db): yield db loaded.append(db.id) last_checked = None while last_checked is None or set(last_checked) != set(loaded): # we need to continue checking until we're sure there aren't any # new storage objects that have been added since we started last_checked = loaded[:] # from all dynamic storages for _, config in list_or_dict_items(app_settings['storages']): ctype = config.get('type', config['storage']) factory = get_adapter(root, IDatabaseManager, name=ctype, args=[config]) for db_name in await factory.get_names(): if db_name in loaded: continue db = await factory.get_database(db_name) loaded.append(db.id) yield db
async def test_update(es_requester): async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa search = get_utility(ICatalogUtility) current_count = await search.get_doc_count(container) await search.index( container, {'foobar': { 'title': 'foobar', 'type_name': 'Item' }}) await search.refresh(container) assert await search.get_doc_count(container) == current_count + 1 await search.update( container, {'foobar': { 'title': 'foobar-updated', 'type_name': 'Item' }}) await search.refresh(container) im = get_adapter(container, IIndexManager) doc = await search.conn.get(index=await im.get_index_name(), doc_type=DOC_TYPE, id='foobar') assert doc['_source']['title'] == 'foobar-updated'
async def init_index(context, subscriber): try: im = get_adapter(context, IIndexManager) utility = query_utility(ICatalogUtility) if utility is None: return index_name = await im.get_index_name() real_index_name = await im.get_real_index_name() conn = utility.get_connection() await utility.create_index(real_index_name, im) await conn.indices.put_alias(name=index_name, index=real_index_name) await conn.indices.close(real_index_name) await conn.indices.open(real_index_name) await conn.cluster.health(wait_for_status="yellow") alsoProvides(context, IIndexActive) execute.add_future( "cleanup-" + context.uuid, _teardown_failed_request_with_index, scope="failure", args=[im], ) except Exception: logger.error("Error creating index for content", exc_info=True) raise
async def init_index(context, subscriber): try: im = get_adapter(context, IIndexManager) utility = get_utility(ICatalogUtility) index_name = await im.get_index_name() real_index_name = await im.get_real_index_name() await utility.create_index(real_index_name, im) await utility.conn.indices.put_alias( name=index_name, index=real_index_name) await utility.conn.cluster.health( wait_for_status='yellow') alsoProvides(context, IIndexActive) request = get_current_request() request.add_future( 'cleanup-' + context.uuid, _teardown_failed_request_with_index, scope='failure', args=[im]) except Exception: logger.error('Error creating index for content', exc_info=True) raise
async def test_delete_in_both_during_migration(es_requester): async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester) search = get_utility(ICatalogUtility) migrator = Migrator(search, container, force=True) im = get_adapter(container, IIndexManager) index_name = await im.get_index_name() next_index_name = await migrator.setup_next_index() resp, _ = await requester( "POST", "/db/guillotina", data=json.dumps({ "@type": "Folder", "title": "Foobar1", "id": "foobar" }), ) await requester("DELETE", "/db/guillotina/foobar") async def _test(): with pytest.raises(aioelasticsearch.exceptions.NotFoundError): await search.get_connection().get(index=next_index_name, doc_type="_all", id=resp["@uid"]) with pytest.raises(aioelasticsearch.exceptions.NotFoundError): await search.get_connection().get(index=index_name, doc_type="_all", id=resp["@uid"]) await run_with_retries(_test, requester)
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)
def field_converter(field, value, context): field.field.__name__ = field.__name__ if isinstance(value, dict) and "op" in value: if not isinstance(value, dict): raise ValueDeserializationError(field, value, "Not an object") operation_name = value.get("op", "undefined") if operation_name == "multi": operation = query_adapter(field, field.operation_type, name=operation_name) if operation is None: raise ValueDeserializationError( field, value, f'"{operation_name}" not a valid operation') value = operation(context, value.get("value")) else: bound_field = field.field.bind(context) operation = query_adapter(bound_field, field.operation_type, name=operation_name) if operation is None: raise ValueDeserializationError( field, value, f'"{operation_name}" not a valid operation') value = operation(context, value.get("value")) elif isinstance(value, (dict, list)): value = get_adapter(field.field, IJSONToValue, args=[value, context]) return value
async def apply_authorization(self, request: IRequest): # User participation participation = get_adapter(request, IParticipation) # Lets extract the user from the request await participation() if participation.principal is not None: request.security.add(participation)
async def iter_databases(root=None): if root is None: root = get_utility(IApplication, name='root') loaded = [] for _, db in root: if IDatabase.providedBy(db): yield db loaded.append(db.id) last_checked = None while last_checked is None or set(last_checked) != set(loaded): # we need to continue checking until we're sure there aren't any # new storage objects that have been added since we started last_checked = loaded[:] # from all dynamic storages for _, config in list_or_dict_items(app_settings['storages']): ctype = config.get('type', config['storage']) factory = get_adapter(root, IDatabaseManager, name=ctype, args=[config]) for db_name in await factory.get_names(): if db_name in loaded: continue db = await factory.get_database(db_name) loaded.append(db.id) yield db
async def test_get_security_data(dummy_request): request = dummy_request # noqa ob = test_utils.create_content() adapter = get_adapter(ob, ISecurityInfo) data = adapter() assert 'access_users' in data assert 'access_roles' in data
async def test_get_security_data(dummy_guillotina): ob = test_utils.create_content() adapter = get_adapter(ob, ISecurityInfo) data = adapter() assert "id" in data assert "access_users" in data assert "access_roles" in data
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 get_index_for(context, container=None): im = find_index_manager(parent=context) if im is None: if container is None: container = get_current_container() im = get_adapter(container, IIndexManager) return await im.get_index_name()
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 get_doc_count(self, container=None, index_name=None): if index_name is None: index_manager = get_adapter(container, IIndexManager) index_name = await index_manager.get_real_index_name() conn = self.get_connection() result = await conn.count(index=index_name) return result["count"]
async def apply_authorization(self, request: IRequest): # User participation participation = get_adapter(request, IParticipation) # Lets extract the user from the request await participation() if participation.principal is not None: request.security.add(participation)
def _validate_field(field, context, value): if 'key' not in value or 'value' not in value: raise ValueDeserializationError( field, value, f'Invalid data') from guillotina.behaviors.dynamic import find_field field = find_field(context, value['key']) # now, verify value... if not field: raise ValueDeserializationError( field, value, f'Dynamic field not found') field_type = field.get('type', 'unknown') try: valid_type = namedtuple( 'temp_assign_type', [field_type]) ob = valid_type({field_type: None}) bound_field = IDynamicType[field_type].bind(ob) # validate and convert real_value = get_adapter( bound_field, IJSONToValue, args=[value['value'], ob]) bound_field.validate(real_value) value['value'] = real_value except (KeyError, ComponentLookupError): raise ValueDeserializationError( field, value, f'Invalid type {field_type}')
async def test_get_security_data(dummy_request): request = dummy_request # noqa ob = test_utils.create_content() adapter = get_adapter(ob, ISecurityInfo) data = adapter() assert 'access_users' in data assert 'access_roles' in data
async def get_database(db_id, root=None) -> IDatabase: """ Get configured database :param db_id: configured database id """ if root is None: root = get_utility(IApplication, name="root") if db_id in root: db = root[db_id] if IDatabase.providedBy(db): return db for _, config in list_or_dict_items(app_settings["storages"]): ctype = config.get("type", config["storage"]) factory = get_adapter(root, IDatabaseManager, name=ctype, args=[config]) databases = await factory.get_names() if db_id in databases: return await factory.get_database(db_id) raise DatabaseNotFound(db_id)
async def storage_get(context, request): storage_id = request.matchdict["storage_id"] config = _get_storage_config(storage_id) if config is None: raise HTTPNotFound(content={"reason": f"Storage {storage_id}"}) manager = config.get("type", config["storage"]) factory = get_adapter(context, IDatabaseManager, name=manager, args=[config]) return {"id": storage_id, "type": config["storage"], "databases": await factory.get_names()}
async def get_index_for(context, container=None, request=None): im = find_index_manager(parent=context) if im is None: if container is None: if request is None: request = get_current_request() container = request.container im = get_adapter(container, IIndexManager) return await im.get_index_name()
async def test_get_internal_dyn_database(db, guillotina_main): storages = app_settings["storages"] storage_config = storages["db"] factory = get_adapter( guillotina_main.root, IDatabaseManager, name=storage_config["storage"], args=[storage_config] ) await factory.create("foobar") db_obj = await get_database("foobar") assert db_obj.id == "foobar"
async def delete_db(context, request): storage_id = request.matchdict["storage_id"] config = _get_storage_config(storage_id) if config is None: raise HTTPNotFound(content={"reason": f"Storage {storage_id}"}) manager = config.get("type", config["storage"]) factory = get_adapter(context, IDatabaseManager, name=manager, args=[config]) assert request.matchdict["db_id"] in await factory.get_names() await factory.delete(request.matchdict["db_id"])
def find_index_manager(content=None, parent=None): if parent is None: content = getattr(content, '__parent__', None) else: content = parent while content: if IIndexActive.providedBy(content): return get_adapter(content, IIndexManager) content = getattr(content, '__parent__', None)
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) from guillotina.traversal import traverse obj, tail = await traverse(self.request, self.request.container, path) if tail and len(tail) > 0: # convert match lookups view_name = routes.path_to_view_name(tail) elif not tail: view_name = '' else: raise permission = get_utility(IPermission, name='guillotina.AccessContent') security = get_adapter(self.request, IInteraction) allowed = security.check_permission(permission.id, obj) if not allowed: return ws.send_str(ujson.dumps({'error': 'Not allowed'})) try: view = query_multi_adapter((obj, self.request), method, name=view_name) except AttributeError: view = None try: view.__route__.matches(self.request, tail or []) except (KeyError, IndexError): view = None if view is None: return ws.send_str(ujson.dumps({'error': 'Not found'})) ViewClass = view.__class__ view_permission = get_view_permission(ViewClass) if not security.check_permission(view_permission, view): return ws.send_str(ujson.dumps({'error': 'No view access'})) if hasattr(view, 'prepare'): view = (await view.prepare()) or view view_result = await view() if IAioHTTPResponse.providedBy(view_result): raise Exception('Do not accept raw aiohttp exceptions in ws') else: from guillotina.traversal import apply_rendering resp = await apply_rendering(view, self.request, view_result) # Return the value, body is always encoded ws.send_str(resp.body.decode('utf-8')) # Wait for possible value self.request.execute_futures()
async def delete_db(context, request): storage_id = request.matchdict['storage_id'] config = _get_storage_config(storage_id) if config is None: raise HTTPNotFound(text=f'Storage {storage_id}') factory = get_adapter(context, IDatabaseManager, name=config['storage'], args=[config]) assert request.matchdict['db_id'] in await factory.get_names() await factory.delete(request.matchdict['db_id'])
async def test_get_internal_dyn_database(db, guillotina_main): storages = app_settings['storages'] storage_config = storages['db'] factory = get_adapter(guillotina_main.root, IDatabaseManager, name=storage_config['storage'], args=[storage_config]) await factory.create('foobar') db_obj = await get_database('foobar') assert db_obj.id == 'foobar'
async def async_get(self, key, suppress_events=True): if key in self._items: return self._items[key] # check configured storages, see if there is a database registered under this name... for _, config in list_or_dict_items(app_settings['storages']): manager = config.get('type', config['storage']) factory = get_adapter(self, IDatabaseManager, name=manager, args=[config]) if await factory.exists(key): return await factory.get_database(key)
def __init__(self, manager, request=None, loop=None): self._txn_time = None self._tid = None self.status = Status.ACTIVE # Transaction Manager self._manager = manager # List of objects added # needs to be ordered because content inserted after other might # reference each other self.added = OrderedDict() self.modified = {} self.deleted = {} # List of (hook, args, kws) tuples added by addBeforeCommitHook(). self._before_commit = [] # List of (hook, args, kws) tuples added by addAfterCommitHook(). self._after_commit = [] logger.debug("new transaction") # Connection to DB self._db_conn = None # Transaction on DB self._db_txn = None # Lock on the transaction # some databases need to lock during queries # this provides a lock for each transaction # which would correspond with one connection self._lock = asyncio.Lock(loop=loop) # we *not* follow naming standards of using "_request" here so # get_current_request can magically find us here... self.request = request self._strategy = get_adapter(self, ITransactionStrategy, name=manager._storage._transaction_strategy) self._cache = get_adapter(self, IStorageCache, name=manager._storage._cache_strategy) self._query_count_start = self._query_count_end = 0
async def test_storage_exists(db, guillotina_main): storages = app_settings['storages'] storage_config = storages['db'] factory = get_adapter(guillotina_main.root, IDatabaseManager, name=storage_config['storage'], args=[storage_config]) assert not await factory.exists('foobar') await factory.create('foobar') assert await factory.exists('foobar') await factory.delete('foobar') assert not await factory.exists('foobar')
async def test_storage_impl(db, guillotina_main): storages = app_settings['storages'] storage_config = storages['db'] factory = get_adapter(guillotina_main.root, IDatabaseManager, name=storage_config['storage'], args=[storage_config]) original_size = len(await factory.get_names()) await factory.create('foobar') assert len(await factory.get_names()) == (original_size + 1) await factory.delete('foobar') assert len(await factory.get_names()) == original_size
async def delete_db(context, request): storage_id = request.matchdict['storage_id'] config = _get_storage_config(storage_id) if config is None: raise HTTPNotFound(content={ 'reason': f'Storage {storage_id}'}) manager = config.get('type', config['storage']) factory = get_adapter(context, IDatabaseManager, name=manager, args=[config]) assert request.matchdict['db_id'] in await factory.get_names() await factory.delete(request.matchdict['db_id'])
async def get_value(self, field, obj, value): if value is None: return None try: value = get_adapter(field, IJSONToValue, args=[value, obj]) if asyncio.iscoroutine(value): value = await value field.validate(value) return value except ComponentLookupError: raise ValueDeserializationError( field, value, 'Deserializer not found for field')
def object_converter(field, value, context=None): if not isinstance(value, dict): raise ValueDeserializationError(field, value, 'Not an object') result = {} for key, val in value.items(): if key in field.schema: f = field.schema[key] if val is not None: result[key] = get_adapter(f, IJSONToValue, args=[val, context]) else: result[key] = None return result
def __init__(self, context, request, field): self.context = context self.request = request self.field = field iface = import_class(app_settings['cloud_storage']) alsoProvides(field, iface) self.file_storage_manager = get_multi_adapter( (context, request, field), IFileStorageManager) self.dm = get_adapter( self.file_storage_manager, IUploadDataManager)
def schema_compatible(value, schema_or_field, context=None): """The schema_compatible function converts any value to guillotina.schema compatible data when possible, raising a TypeError for unsupported values. This is done by using the ISchemaCompatible converters. """ if value is None: return value try: return get_adapter(schema_or_field, IJSONToValue, args=[value, context]) except ComponentLookupError: raise ValueDeserializationError( schema_or_field, value, 'Deserializer not found for field')
def get_value(self, value, existing=None, field_type=None): if field_type is None: if self.field.value_type: field_type = self.field.value_type if field_type: field_type.__name__ = self.field.__name__ # for sub objects, we need to assign temp object type # to work with json schema correctly valid_type = namedtuple('temp_assign_type', [self.field.__name__]) ob = valid_type(**{field_type.__name__: existing}) value = get_adapter( field_type, IJSONToValue, args=[value, ob]) return value
async def storage_create_db(context, request): storage_id = request.matchdict['storage_id'] config = _get_storage_config(storage_id) if config is None: raise HTTPNotFound(content={ 'reason': f'Storage {storage_id}'}) manager = config.get('type', config['storage']) factory = get_adapter(context, IDatabaseManager, name=manager, args=[config]) data = await request.json() name = data['name'] assert name == re.escape(name) await factory.create(data['name'])
def __init__(self, manager=None): if manager is None: manager = MockTransactionManager() self._manager = self.manager = manager self._tid = 1 self.modified = {} self.request = None self._strategy = get_adapter( self, ITransactionStrategy, name=manager._storage._transaction_strategy) self._cache = DummyCache(self) self._lock = asyncio.Lock() self._status = 'started' self._db_conn = None
async def storage_get(context, request): storage_id = request.matchdict['storage_id'] config = _get_storage_config(storage_id) if config is None: raise HTTPNotFound(content={ 'reason': f'Storage {storage_id}' }) manager = config.get('type', config['storage']) factory = get_adapter(context, IDatabaseManager, name=manager, args=[config]) return { 'id': storage_id, 'type': config['storage'], 'databases': await factory.get_names() }
def field_converter(field, value, context): field.field.__name__ = field.__name__ if isinstance(value, dict) and 'op' in value: if not isinstance(value, dict): raise ValueDeserializationError(field, value, 'Not an object') operation_name = value.get('op', 'undefined') bound_field = field.field.bind(context) operation = query_adapter( bound_field, field.operation_type, name=operation_name) if operation is None: raise ValueDeserializationError( field, value, f'"{operation_name}" not a valid operation') value = operation(context, value.get('value')) elif isinstance(value, (dict, list)): value = get_adapter(field.field, IJSONToValue, args=[value, context]) return value
async def get_database(db_id, root=None): if root is None: root = get_utility(IApplication, name='root') if db_id in root: db = root[db_id] if IDatabase.providedBy(db): return db for _, config in list_or_dict_items(app_settings['storages']): ctype = config.get('type', config['storage']) factory = get_adapter(root, IDatabaseManager, name=ctype, args=[config]) databases = await factory.get_names() if db_id in databases: return await factory.get_database(db_id) return None
async def __call__(self): if self.key is _marker: # No option to write the root of registry return ErrorResponse('InvalidRequest', 'Needs the registry key', status=412) 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) assert iface is not None, 'Must provide valid registry interface' # noqa try: field = iface[name] except KeyError: return ErrorResponse( 'DeserializationError', 'Invalid field name {}'.format(str(name)), status=412) try: new_value = get_adapter((field), IJSONToValue, args=[value, self.context]) except ComponentLookupError: return ErrorResponse( 'DeserializationError', 'Cannot deserialize type {}'.format(str(self.field)), status=412) try: self.request.container_settings[self.key] = new_value except DeserializationError as e: return ErrorResponse( 'DeserializationError', str(e), exc=e, status=412) return Response(status=204)
def test_configuration_machine_allows_overriding(): from guillotina.configure.config import ConfigurationMachine from guillotina.configure import component from guillotina.component import adapter, get_adapter from zope.interface import implementer, Interface, named class IFoo(Interface): pass @implementer(IFoo) class Foo(object): pass class IBar(Interface): pass cm = ConfigurationMachine() @adapter(IFoo) @implementer(IBar) @named('bar') class _Factory(object): def __init__(self, context): self.context = context class _FactoryOverride(_Factory): pass component.adapter(cm, (_Factory,)) cm.execute_actions() cm.commit() component.adapter(cm, (_FactoryOverride,)) cm.execute_actions() adapter = get_adapter(Foo(), name='bar') assert isinstance(adapter, _FactoryOverride)
async def real_resolve(self, request: IRequest) -> Optional[MatchInfo]: """Main function to resolve a request.""" security = get_adapter(request, IInteraction) if request.method not in app_settings['http_methods']: raise HTTPMethodNotAllowed( method=request.method, allowed_methods=[k for k in app_settings['http_methods'].keys()]) method = app_settings['http_methods'][request.method] try: resource, tail = await self.traverse(request) except ConflictError: # can also happen from connection errors so we bubble this... raise except Exception as _exc: logger.error('Unhandled exception occurred', exc_info=True) 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() raise HTTPBadRequest(content={ 'reason': data }) request.record('traversed') await notify(ObjectLoadedEvent(resource)) request.resource = resource request.tail = tail if request.resource is None: await notify(TraversalResourceMissEvent(request, tail)) raise HTTPNotFound(content={ "reason": 'Resource not found' }) if tail and len(tail) > 0: # convert match lookups view_name = routes.path_to_view_name(tail) elif not tail: view_name = '' request.record('beforeauthentication') await self.apply_authorization(request) request.record('authentication') for language in get_acceptable_languages(request): translator = query_adapter((resource, request), ILanguage, name=language) if translator is not None: resource = translator.translate() break # Add anonymous participation if len(security.participations) == 0: security.add(AnonymousParticipation(request)) # container registry lookup try: view = query_multi_adapter( (resource, request), method, name=view_name) except AttributeError: view = None if view is None and method == IOPTIONS: view = DefaultOPTIONS(resource, request) # Check security on context to AccessContent unless # is view allows explicit or its OPTIONS permission = get_utility(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.info( "No access content {content} with {auths}".format( content=resource, auths=str([x.principal.id for x in security.participations])), request=request) raise HTTPUnauthorized( content={ "reason": "You are not authorized to access content", "content": str(resource), "auths": [x.principal.id for x in security.participations] } ) if not view and len(tail) > 0: # we should have a view in this case because we are matching routes await notify(TraversalViewMissEvent(request, tail)) return None request.found_view = view request.view_name = view_name request.record('viewfound') ViewClass = view.__class__ view_permission = get_view_permission(ViewClass) if not security.check_permission(view_permission, view): if IOPTIONS != method: raise HTTPUnauthorized( content={ "reason": "You are not authorized to view", "content": str(resource), "auths": [x.principal.id for x in security.participations] } ) try: view.__route__.matches(request, tail or []) except (KeyError, IndexError): await notify(TraversalRouteMissEvent(request, tail)) return None except AttributeError: pass if hasattr(view, 'prepare'): view = (await view.prepare()) or view request.record('authorization') return MatchInfo(resource, request, view)
async def handle_ws_request(self, ws, message): method = app_settings['http_methods']['GET'] try: frame_id = message['id'] except KeyError: frame_id = '0' parsed = parse.urlparse(message.get('path', message.get('value'))) path = tuple(p for p in parsed.path.split('/') if p) from guillotina.traversal import traverse obj, tail = await traverse(self.request, self.request.container, path) if tail and len(tail) > 0: # convert match lookups view_name = routes.path_to_view_name(tail) elif not tail: view_name = '' else: raise permission = get_utility( IPermission, name='guillotina.AccessContent') security = get_adapter(self.request, IInteraction) allowed = security.check_permission(permission.id, obj) if not allowed: return await ws.send_str(ujson.dumps({ 'error': 'Not allowed' })) try: view = query_multi_adapter( (obj, self.request), method, name=view_name) except AttributeError: view = None try: view.__route__.matches(self.request, tail or []) except (KeyError, IndexError): view = None if view is None: return await ws.send_str(ujson.dumps({ 'error': 'Not found', 'id': frame_id })) ViewClass = view.__class__ view_permission = get_view_permission(ViewClass) if not security.check_permission(view_permission, view): return await ws.send_str(ujson.dumps({ 'error': 'No view access', 'id': frame_id })) if hasattr(view, 'prepare'): view = (await view.prepare()) or view view_result = await view() if IAioHTTPResponse.providedBy(view_result): raise Exception('Do not accept raw aiohttp exceptions in ws') else: from guillotina.traversal import apply_rendering resp = await apply_rendering(view, self.request, view_result) # Return the value, body is always encoded response_object = ujson.dumps({ 'data': resp.body.decode('utf-8'), 'id': frame_id }) await ws.send_str(response_object) # Wait for possible value self.request.execute_futures()
def _callFUT(self, *args, **kw): from guillotina.component import get_adapter return get_adapter(*args, **kw)