async def test_missing_modifier_on_nested(es_requester): async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) factory = query_utility(IFhirSearch) context = query_utility(ISearchContextFactory).get("Task", unrestricted=True) # ------ Test in Complex Data Type ------------- # Parent Task has not partOf but each child has partOf referenced to parent params = (("part-of:missing", "false"), ) bundle = await factory(params, context=context) # should be two assert len(bundle.entry) == 2 params = (("part-of:missing", "true"), ) bundle = await factory(params, context=context) # should be one (parent Task) assert len(bundle.entry) == 1
async def test_array_type_reference(es_requester): async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) factory = query_utility(IFhirSearch) context = query_utility(ISearchContextFactory).get("Task", unrestricted=True) params = (("based-on", "ProcedureRequest/0c57a6c9-c275-4a0a-bd96-701daf7bd7ce"), ) bundle = await factory(params, context=context) # Search with based on assert bundle.total == 1 # Search with part-of # should be two sub tasks params = (("part-of", "Task/5df31190-0ed4-45ba-8b16-3c689fc2e686"), ) bundle = await factory(params, context=context) assert bundle.total == 2
async def test_duplicate_param(es_requester): async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) factory = query_utility(IFhirSearch) context = query_utility(ISearchContextFactory).get("Task", unrestricted=True) params = [ ("_lastUpdated", "gt2015-10-15T06:31:18+00:00"), ("_lastUpdated", "lt2018-01-15T06:31:18+00:00"), ] bundle = await factory(params, context=context) assert bundle.total == 1
async def test_fhir_reference_param(es_requester): """Testing FHIR search reference type params, i.e subject, owner""" async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) factory = query_utility(IFhirSearch) context = query_utility(ISearchContextFactory).get("Task", unrestricted=True) patient_id = "Patient/19c5245f-89a8-49f8-b244-666b32adb92e" params = (("owner", patient_id), ) bundle = await factory(params, context=context) # should be two tasks with having status ready assert len(bundle.entry) == 2 params = (("owner", "Organization/1832473e-2fe0-452d-abe9-3cdb9879522f"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 params = (("patient", patient_id), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 3 # with compound query params = (("patient", patient_id), ("status", "draft")) # should be now only single bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # Test with negetive params = (("owner:not", "Practitioner/fake-ac0-821d-46d9-9d40-a61f2578cadf"), ) bundle = await factory(params, context=context) # should get all tasks assert len(bundle.entry) == 3 # Test with nested reference params = (("based-on", "ProcedureRequest/0c57a6c9-c275-4a0a-bd96-701daf7bd7ce"), ) bundle = await factory(params, context=context) # Should One HAQ sub task assert len(bundle.entry) == 1
async def test_code_param(es_requester): async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) factory = query_utility(IFhirSearch) context = query_utility(ISearchContextFactory).get("ChargeItem", unrestricted=True) # Test code (Coding) params = (("code", "F01510"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # Test with system+code params = (("code", "http://snomed.info/sct|F01510"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # test with code only params = (("code", "|F01510"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # test with system only params = (("code", "http://snomed.info/sct|"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # test with text params = (("code:text", "Nice Code"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 context = query_utility(ISearchContextFactory).get("MedicationRequest", unrestricted=True) # test with only code params = (("code", "322254008"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # test with system and code params = (("code", "http://snomed.info/sct|"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1
async def test_address_telecom(es_requester): async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) factory = query_utility(IFhirSearch) context = query_utility(ISearchContextFactory).get("Patient", unrestricted=True) params = (("email", "*****@*****.**"), ) bundle = await factory(params, context=context) assert bundle.total == 1 # Test address with multiple paths and value for city params = (("address", "Indianapolis"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # Test address with multiple paths and value for postCode params = (("address", "46240"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # Test with single path for state params = (("address-state", "IN"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 params = (("family", "Saint"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # test with given name (array) params = (("given", "Eelector"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # test with full name represent as text params = (("name", "Patient Saint"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1
async def test_fhir_token_param(es_requester): """Testing FHIR search token type params, i.e status, active""" async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) context = query_utility(ISearchContextFactory).get("Task", unrestricted=True) factory = query_utility(IFhirSearch) params = (("status", "ready"), ) bundle = await factory(params, context=context) # should be two tasks with having status ready assert bundle.total == 2 params = (("status:not", "ready"), ) bundle = await factory(params, context=context) # should be one task with having status draft assert bundle.total == 1 # test with combinition with lastUpdated params = [("status", "ready"), ("_lastUpdated", "lt2018-01-15T06:31:18+00:00")] bundle = await factory(params, context=context) # should single task now assert len(bundle.entry) == 1 # ** Test boolen valued token ** context = query_utility(ISearchContextFactory).get("Patient", unrestricted=True) params = (("active", "true"), ) bundle = await factory(params, context=context) # only one patient assert len(bundle.entry) == 1 params = (("active", "false"), ) bundle = await factory(params, context=context) assert bundle.total == 0
async def index_object(obj, indexes=None, modified=False, security=False): uid = getattr(obj, 'uuid', None) if uid is None: return type_name = getattr(obj, 'type_name', None) if type_name is None or IContainer.providedBy(obj): return search = query_utility(ICatalogUtility) if search is None: return fut = get_future() if fut is None: return if modified: data = {} if security: adapter = query_adapter(obj, ISecurityInfo) if adapter is not None: data = await apply_coroutine(adapter) else: if indexes is not None and len(indexes) > 0: data = await search.get_data(obj, indexes) if len(data) > 0: if uid in fut.update: fut.update[uid].update(data) else: fut.update[uid] = data else: fut.index[uid] = await search.get_data(obj)
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 add_object(obj, event): uid = getattr(obj, 'uuid', None) if uid is None: return type_name = getattr(obj, 'type_name', None) if type_name is None or IContainer.providedBy(obj): return fut = get_future() if fut is None: return search = query_utility(ICatalogUtility) if search: if IObjectModifiedEvent.providedBy(event): indexes = [] if event.payload and len(event.payload) > 0: # get a list of potential indexes for field_name in event.payload.keys(): if '.' in field_name: for behavior_field_name in event.payload[ field_name].keys(): indexes.append(behavior_field_name) else: indexes.append(field_name) fut.update[uid] = await search.get_data(obj, indexes) else: fut.index[uid] = await search.get_data(obj)
async def __call__(self): data = await self.request.json() creds = {"type": "basic", "token": data["password"], "id": data.get("username", data.get("login"))} for validator in app_settings["auth_token_validators"]: if validator.for_validators is not None and "basic" not in validator.for_validators: continue user = await validator().validate(creds) if user is not None: break if user is None: raise HTTPUnauthorized(content={"text": "login failed"}) session_manager = query_utility(ISessionManagerUtility) if session_manager is not None: data = json.dumps(dict(self.request.headers)) session = await session_manager.new_session(user.id, data=data) data = {"session": session} else: data = {} jwt_token, data = authenticate_user( user.id, timeout=app_settings["jwt"]["token_expiration"], data=data ) await notify(UserLogin(user, jwt_token)) return {"exp": data["exp"], "token": jwt_token}
async def validate(self, token): if token.get("type") not in ("bearer", "wstoken", "cookie"): return if "." not in token.get("token", ""): # quick way to check if actually might be jwt return try: validated_jwt = jwt.decode( token["token"], app_settings["jwt"]["secret"], algorithms=[app_settings["jwt"]["algorithm"]]) session_manager = query_utility(ISessionManagerUtility) if session_manager is not None: session = validated_jwt.get("session", None) valid_session = await session_manager.exist_session( validated_jwt["id"], session) if valid_session: token["id"] = validated_jwt["id"] token["decoded"] = validated_jwt user = await find_user(token) user._v_session = session if user is not None and user.id == token["id"]: return user else: return except (jwt.exceptions.DecodeError, jwt.exceptions.ExpiredSignatureError, KeyError): pass return
def __init__(self, transaction): super().__init__(transaction) self._utility = query_utility(ICacheUtility) if self._utility is None: logger.info("No cache utility configured") self._keys_to_publish = [] self._stored_objects = []
async def aggregation_get(context, request): query = request.query.copy() search = query_utility(ICatalogUtility) if search is None: raise HTTPServiceUnavailable() fields = request.query.get("_metadata", "").split(",") result = await search.query_aggregation(context, query) if "items" in result: aggregation = [] for field in fields: aggregation.append([]) for items in result["items"]: for index, item in enumerate(items): if isinstance(item, list): aggregation[index].extend(item) elif isinstance(item, str): aggregation[index].append(item) final_result = {} for index, field in enumerate(fields): elements = dict(Counter(aggregation[index])) final_result[field] = {"items": elements, "total": len(elements)} return final_result else: return {}
async def search_post(context, request): q = await request.json() search = query_utility(ICatalogUtility) if search is None: return {"items_total": 0, "items": []} return await search.search_raw(context, q)
async def __call__(self, json_value): if self.request.resource: fti = query_utility(IFactory, name=self.request.resource.type_name) schema_summary = get_multi_adapter((fti, self.request), IResourceSerializeToJson) json_value['schema'] = await schema_summary() return json_value
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
async def addable_types(context, request): result = [] constrains = ICMSConstrainTypes(context, None) policy = get_security_policy() 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 policy.check_permission(permission.id, context): add = False if add: result.append(id) return result
async def publish_traverse(self, traverse): if len(traverse) == 1: # we want have the key of the registry self.value = query_utility(IResourceFactory, name=traverse[0]) if self.value is None: raise KeyError(traverse[0]) return self
async def get_all_types(context, request): result = [] base_url = IAbsoluteURL(context, request)() constrains = ICMSConstrainTypes(context, None) policy = get_security_policy() 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 policy.check_permission( permission.id, context ): add = False if add: result.append( {"@id": base_url + "/@types/" + id, "addable": True, "title": id} ) return result
async def test_first_query(es_requester): """ """ async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) await load_organizations_data(requester, 5) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) builder = Q_(resource="Organization", engine=engine) builder = builder.where(T_("Organization.active", "true")) result = await builder(async_result=True).first() assert result[0]["resourceType"] == builder._from[0][0] builder = Q_(resource="Organization", engine=engine) builder = builder.where(T_("Organization.active", "false")) result = await builder(async_result=True).first() assert result is None
async def search_post(context, request): q = await request.json() search = query_utility(ICatalogUtility) if search is None: raise HTTPServiceUnavailable() return await search.search_raw(context, q)
async def search_get(context, request): search = query_utility(ICatalogUtility) if search is None: return {'@id': request.url.human_repr(), 'items': [], 'items_total': 0} parser = resolve_dotted_name(app_settings['search_parser']) call_params, full_objects = parser(request, context)() result = await search.get_by_path(**call_params) real_result = { '@id': request.url.human_repr(), 'items': [], 'items_total': result['items_count'] } for member in result['member']: if full_objects: obj = await get_object_by_oid(member['uuid']) view = DefaultGET(obj, request) serialization = await view() real_result['items'].append(serialization) else: member['@id'] = member['@absolute_url'] del member['@absolute_url'] real_result['aggregations'] = { key: value['buckets'] for key, value in result.get('aggregations', {}).items() } real_result['items'] = result['member'] return real_result
async def test_single_query(es_requester): """ """ async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) await load_organizations_data(requester, 2) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) builder = Q_(resource="ChargeItem", engine=engine) builder = builder.where(exists_("ChargeItem.enteredDate")) result = await builder(async_result=True).single() assert result is not None assert result[0]["resourceType"] == builder._from[0][0] # test empty result builder = Q_(resource="ChargeItem", engine=engine) builder = builder.where(not_(exists_("ChargeItem.enteredDate"))) result = await builder(async_result=True).single() assert result is None # Test Multiple Result error builder = Q_(resource="Organization", engine=engine) builder = builder.where(T_("Organization.active", "true")) with pytest.raises(MultipleResultsFound) as excinfo: await builder(async_result=True).single() assert excinfo.type == MultipleResultsFound
async def __call__(self): util = query_utility(IQueueUtility) if util: await util.add( CatalogReindex(self.context, self.request, self._security_reindex)) return {}
async def search_post(context, request): q = await request.json() search = query_utility(ICatalogUtility) if search is None: return {'items_count': 0, 'member': []} return await search.query(context, q)
async def test_identifier_param(es_requester): """ """ async with es_requester as requester: container, request, txn, tm = await setup_txn_on_container(requester ) # noqa # init primary data await init_data(requester) engine = query_utility(IElasticsearchEngineFactory).get() index_name = await engine.get_index_name(container) conn = engine.connection.raw_connection await conn.indices.refresh(index=index_name) factory = query_utility(IFhirSearch) context = query_utility(ISearchContextFactory).get("Patient", unrestricted=True) params = (("identifier", "240365-0002"), ) bundle = await factory(params, context=context) assert bundle.total == 1 # Test with system+value params = (("identifier", "CPR|240365-0002"), ) bundle = await factory(params, context=context) assert bundle.total == 1 # Test with system only with pipe sign params = (("identifier", "UUID|"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # Test with value only with pipe sign params = (("identifier", "|19c5245f-89a8-49f8-b244-666b32adb92e"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1 # Test with empty result params = (("identifier", "CPR|19c5245f-89a8-49f8-b244-666b32adb92e"), ) bundle = await factory(params, context=context) assert bundle.total == 0 # Test with text modifier params = (("identifier:text", "Plone Patient UUID"), ) bundle = await factory(params, context=context) assert len(bundle.entry) == 1
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
def reindex_in_future(context, security=False): """ Function to reindex a tree of content in the catalog. """ search = query_utility(ICatalogUtility) if search is not None: execute.in_pool(search.reindex_all_content, context, security).after_request()
async def prepare(self): type_name = self.request.matchdict['type_name'] self.value = query_utility(IResourceFactory, name=type_name) if self.value is None: raise HTTPNotFound(content={ 'reason': f'Could not find type {type_name}', 'type_name': type_name })
def check_password(token, password): split = token.split(':') if len(split) != 3: return False algorithm = split[0] check_func = query_utility(IPasswordChecker, name=algorithm) if check_func is None: logger.error(f'Could not find password checker for {algorithm}') return False return check_func(token, password)
async def search_post(context, request): q = await request.json() search = query_utility(ICatalogUtility) if search is None: return { 'items_count': 0, 'member': [] } return await search.query(context, q)
def reindex_in_future(context, request, security=False): ''' Function to reindex a tree of content in the catalog. ''' search = query_utility(ICatalogUtility) if search is not None: pool = get_utility(IAsyncJobPool) pool.add_job_after_commit( search.reindex_all_content, request=request, args=[context, security], kwargs={'request': request})
async def search_get(context, request): q = request.query.get('q') search = query_utility(ICatalogUtility) if search is None: return { 'items_count': 0, 'member': [] } return await search.get_by_path( container=request.container, path=get_content_path(context), query=q)
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 test_get_data_uses_indexes_param(dummy_request): util = query_utility(ICatalogUtility) request = dummy_request # noqa container = await create_content( 'Container', id='guillotina', title='Guillotina') container.__name__ = 'guillotina' ob = await create_content('Item', id='foobar') data = await util.get_data(ob, indexes=['title']) assert len(data) == 4 # uuid, type_name, etc always returned data = await util.get_data(ob, indexes=['title', 'id']) assert len(data) == 5 data = await util.get_data(ob) assert len(data) > 9
def get_future(): request = get_current_request() try: container = request.container search = query_utility(ICatalogUtility) except (AttributeError, KeyError): return if not search: return # no search configured fut = request.get_future('indexer') if fut is None: fut = IndexFuture(container, request) request.add_future('indexer', fut) return fut
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 __call__(self): if self.request.view_error: # there was an error executing this view, we do not want to execute return # Commits are run in sync thread so there is no asyncloop search = query_utility(ICatalogUtility) if search: if len(self.remove) > 0: await search.remove(self.container, self.remove) if len(self.index) > 0: await search.index(self.container, self.index) if len(self.update) > 0: await search.update(self.container, self.update) self.index = {} self.update = {} self.remove = []
async def test_registered_base_utility(dummy_request): util = query_utility(ICatalogUtility) assert util is not None
async def __call__(self): search = query_utility(ICatalogUtility) if search is not None: await search.reindex_all_content( self.context, self._security_reindex, request=self.request) return {}
async def catalog_delete(context, request): search = query_utility(ICatalogUtility) await search.remove_catalog(context) return {}
async def catalog_post(context, request): search = query_utility(ICatalogUtility) await search.initialize_catalog(context) return {}
async def remove_catalog(container, event): search = query_utility(ICatalogUtility) if search: await search.remove_catalog(container)
async def initialize_catalog(container, event): search = query_utility(ICatalogUtility) if search: await search.initialize_catalog(container)