From 26e0b2e92d9e67ff60798f26d6cf6ad4942600ca Mon Sep 17 00:00:00 2001 From: Mohamed Abdel Wedoud Date: Fri, 16 Feb 2024 09:59:00 +0100 Subject: [PATCH] refactor(permission-db): redefine access permissions, studies counting and searching --- antarest/launcher/service.py | 6 +- antarest/study/repository.py | 193 +++++++++++------- antarest/study/service.py | 9 +- .../study/storage/auto_archive_service.py | 4 +- antarest/study/web/studies_blueprint.py | 4 +- tests/storage/repository/test_study.py | 4 +- tests/storage/test_service.py | 14 +- tests/study/test_repository.py | 52 +++-- 8 files changed, 180 insertions(+), 106 deletions(-) diff --git a/antarest/launcher/service.py b/antarest/launcher/service.py index 9c723a0426..3165df48c7 100644 --- a/antarest/launcher/service.py +++ b/antarest/launcher/service.py @@ -40,7 +40,7 @@ from antarest.launcher.repository import JobResultRepository from antarest.launcher.ssh_client import calculates_slurm_load from antarest.launcher.ssh_config import SSHConfigDTO -from antarest.study.repository import QueryUser, StudyFilter, build_query_user_from_params +from antarest.study.repository import AccessPermissions, StudyFilter from antarest.study.service import StudyService from antarest.study.storage.utils import assert_permission, extract_output_name, find_single_output_path @@ -313,7 +313,9 @@ def _filter_from_user_permission(self, job_results: List[JobResult], user: Optio studies = { study.id: study for study in self.study_service.repository.get_all( - study_filter=StudyFilter(study_ids=study_ids, query_user=build_query_user_from_params(user)) + study_filter=StudyFilter( + study_ids=study_ids, access_permissions=AccessPermissions.from_params(user) + ) ) } else: diff --git a/antarest/study/repository.py b/antarest/study/repository.py index c61a6c7320..79e7fac21e 100644 --- a/antarest/study/repository.py +++ b/antarest/study/repository.py @@ -4,7 +4,7 @@ from pydantic import BaseModel, NonNegativeInt from sqlalchemy import func, not_, or_ # type: ignore -from sqlalchemy.orm import Session, joinedload, with_polymorphic # type: ignore +from sqlalchemy.orm import Query, Session, joinedload, with_polymorphic # type: ignore from antarest.core.interfaces.cache import ICache from antarest.core.jwt import JWTUser @@ -37,7 +37,7 @@ def escape_like(string: str, escape_char: str = "\\") -> str: return string.replace(escape_char, escape_char * 2).replace("%", escape_char + "%").replace("_", escape_char + "_") -class QueryUser(BaseModel, frozen=True, extra="forbid"): +class AccessPermissions(BaseModel, frozen=True, extra="forbid"): """ This class object is build to pass on the user identity and its associated groups information into the listing function get_all below @@ -47,30 +47,30 @@ class QueryUser(BaseModel, frozen=True, extra="forbid"): user_id: t.Optional[int] = None user_groups: t.Sequence[str] = () + @classmethod + def from_params(cls, params: t.Union[RequestParameters, JWTUser]) -> "AccessPermissions": + """ + This function makes it easier to pass on user ids and groups into the repository filtering function by + extracting the associated `AccessPermissions` object. + Args: + params: `RequestParameters` or `JWTUser` holding user ids and groups -def build_query_user_from_params(params: t.Union[RequestParameters, JWTUser]) -> QueryUser: - """ - This function makes it easier to pass on user ids and groups into the repository filtering function by - extracting the associated `QueryUser` object. - Args: - params: `RequestParameters` or `JWTUser` holding user ids and groups + Returns: `AccessPermissions` - Returns: `QueryUser` + """ + if isinstance(params, RequestParameters): + user = params.user + else: + user = params - """ - if isinstance(params, RequestParameters): - user = params.user - else: - user = params - - if user: - return QueryUser( - is_admin=user.is_site_admin() or user.is_admin_token(), - user_id=user.id, - user_groups=[group.id for group in user.groups], - ) - else: - return QueryUser() + if user: + return cls( + is_admin=user.is_site_admin() or user.is_admin_token(), + user_id=user.id, + user_groups=[group.id for group in user.groups], + ) + else: + return cls() class StudyFilter(BaseModel, frozen=True, extra="forbid"): @@ -89,7 +89,7 @@ class StudyFilter(BaseModel, frozen=True, extra="forbid"): exists: if raw study missing workspace: optional workspace of the study folder: optional folder prefix of the study - query_user: query user id, groups and admins status + access_permissions: query user id, groups and admins status """ name: str = "" @@ -104,7 +104,7 @@ class StudyFilter(BaseModel, frozen=True, extra="forbid"): exists: t.Optional[bool] = None workspace: str = "" folder: str = "" - query_user: QueryUser = QueryUser() + access_permissions: AccessPermissions = AccessPermissions() class StudySortBy(str, enum.Enum): @@ -235,6 +235,89 @@ def get_all( Returns: The matching studies in proper order and pagination. """ + + # When we fetch a study, we also need to fetch the associated owner and groups + # to check the permissions of the current user efficiently. + # We also need to fetch the additional data to display the study information + # efficiently (see: `AbstractStorageService.get_study_information`) + entity = with_polymorphic(Study, "*") + + q = self._search_studies(study_filter) + + # permissions filtering + if not study_filter.access_permissions.is_admin: + if study_filter.access_permissions.user_id is None: + return [] + condition_1 = entity.public_mode != PublicMode.NONE + condition_2 = entity.owner_id == study_filter.access_permissions.user_id + condition_3 = Group.id.in_(study_filter.access_permissions.user_groups or []) + q0 = q.filter(condition_3) if study_filter.groups else q.join(entity.groups).filter(condition_3) + q = q0.union(q.filter(or_(condition_1, condition_2))) + + # sorting + if sort_by: + if sort_by == StudySortBy.DATE_DESC: + q = q.order_by(entity.created_at.desc()) + elif sort_by == StudySortBy.DATE_ASC: + q = q.order_by(entity.created_at.asc()) + elif sort_by == StudySortBy.NAME_DESC: + q = q.order_by(func.upper(entity.name).desc()) + elif sort_by == StudySortBy.NAME_ASC: + q = q.order_by(func.upper(entity.name).asc()) + else: + raise NotImplementedError(sort_by) + + # pagination + if pagination.page_nb or pagination.page_size: + q = q.offset(pagination.page_nb * pagination.page_size).limit(pagination.page_size) + + studies: t.Sequence[Study] = q.all() + return studies + + def count_studies(self, study_filter: StudyFilter = StudyFilter()) -> int: + """ + Count all studies matching with specified filters. + + Args: + study_filter: composed of all filtering criteria. + + Returns: + Integer, corresponding to total number of studies matching with specified filters. + """ + # When we fetch a study, we also need to fetch the associated owner and groups + # to check the permissions of the current user efficiently. + # We also need to fetch the additional data to display the study information + # efficiently (see: `AbstractStorageService.get_study_information`) + entity = with_polymorphic(Study, "*") + + q = self._search_studies(study_filter) + + # permissions filtering + if not study_filter.access_permissions.is_admin: + if study_filter.access_permissions.user_id is None: + return 0 + condition_1 = entity.public_mode != PublicMode.NONE + condition_2 = entity.owner_id == study_filter.access_permissions.user_id + condition_3 = Group.id.in_(study_filter.access_permissions.user_groups or []) + q0 = q.filter(condition_3) if study_filter.groups else q.join(entity.groups).filter(condition_3) + q = q0.union(q.filter(or_(condition_1, condition_2))) + total: int = q.count() + + return total + + def _search_studies( + self, + study_filter: StudyFilter = StudyFilter(), + ) -> Query: + """ + Build a `SQL Query` based on specified filters. + + Args: + study_filter: composed of all filtering criteria. + + Returns: + The `Query` corresponding to specified criteria (except for permissions). + """ # When we fetch a study, we also need to fetch the associated owner and groups # to check the permissions of the current user efficiently. # We also need to fetch the additional data to display the study information @@ -244,22 +327,23 @@ def get_all( # noinspection PyTypeChecker q = self.session.query(entity) if study_filter.exists is not None: - if study_filter.exists: - q = q.filter(RawStudy.missing.is_(None)) - else: - q = q.filter(not_(RawStudy.missing.is_(None))) + q = ( + q.filter(RawStudy.missing.is_(None)) + if study_filter.exists + else q.filter(not_(RawStudy.missing.is_(None))) + ) q = q.options(joinedload(entity.owner)) q = q.options(joinedload(entity.groups)) q = q.options(joinedload(entity.additional_data)) q = q.options(joinedload(entity.tags)) if study_filter.managed is not None: - if study_filter.managed: - q = q.filter(or_(entity.type == "variantstudy", RawStudy.workspace == DEFAULT_WORKSPACE_NAME)) - else: - q = q.filter(entity.type == "rawstudy") - q = q.filter(RawStudy.workspace != DEFAULT_WORKSPACE_NAME) + q = ( + q.filter(or_(entity.type == "variantstudy", RawStudy.workspace == DEFAULT_WORKSPACE_NAME)) + if study_filter.managed + else q.filter(entity.type == "rawstudy").filter(RawStudy.workspace != DEFAULT_WORKSPACE_NAME) + ) if study_filter.study_ids: - q = q.filter(entity.id.in_(study_filter.study_ids)) + q = q.filter(entity.id.in_(study_filter.study_ids)) if study_filter.study_ids else q if study_filter.users: q = q.filter(entity.owner_id.in_(study_filter.users)) if study_filter.groups: @@ -277,46 +361,11 @@ def get_all( if study_filter.workspace: q = q.filter(RawStudy.workspace == study_filter.workspace) if study_filter.variant is not None: - if study_filter.variant: - q = q.filter(entity.type == "variantstudy") - else: - q = q.filter(entity.type == "rawstudy") + q = q.filter(entity.type == "variantstudy") if study_filter.variant else q.filter(entity.type == "rawstudy") if study_filter.versions: q = q.filter(entity.version.in_(study_filter.versions)) - # permissions filtering - if not study_filter.query_user.is_admin: - if study_filter.query_user.user_id is not None: - condition_1 = entity.public_mode != PublicMode.NONE - condition_2 = entity.owner_id == study_filter.query_user.user_id - condition_3 = Group.id.in_(study_filter.query_user.user_groups or []) - if study_filter.groups: - q0 = q.filter(condition_3) - q = q0.union(q.filter(or_(condition_1, condition_2))) - else: - q0 = q.join(entity.groups).filter(condition_3) - q = q0.union(q.filter(or_(condition_1, condition_2))) - else: - return [] - - if sort_by: - if sort_by == StudySortBy.DATE_DESC: - q = q.order_by(entity.created_at.desc()) - elif sort_by == StudySortBy.DATE_ASC: - q = q.order_by(entity.created_at.asc()) - elif sort_by == StudySortBy.NAME_DESC: - q = q.order_by(func.upper(entity.name).desc()) - elif sort_by == StudySortBy.NAME_ASC: - q = q.order_by(func.upper(entity.name).asc()) - else: - raise NotImplementedError(sort_by) - - # pagination - if pagination.page_nb or pagination.page_size: - q = q.offset(pagination.page_nb * pagination.page_size).limit(pagination.page_size) - - studies: t.Sequence[Study] = q.all() - return studies + return q def get_all_raw(self, exists: t.Optional[bool] = None) -> t.Sequence[RawStudy]: query = self.session.query(RawStudy) diff --git a/antarest/study/service.py b/antarest/study/service.py index b4225a24ea..1f89501c4e 100644 --- a/antarest/study/service.py +++ b/antarest/study/service.py @@ -96,12 +96,11 @@ StudySimResultDTO, ) from antarest.study.repository import ( - QueryUser, + AccessPermissions, StudyFilter, StudyMetadataRepository, StudyPagination, StudySortBy, - build_query_user_from_params, ) from antarest.study.storage.matrix_profile import adjust_matrix_columns_index from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfigDTO @@ -716,7 +715,9 @@ def remove_duplicates(self) -> None: """ study_paths: t.Dict[str, t.List[str]] = {} - for study in self.repository.get_all(study_filter=StudyFilter(query_user=QueryUser(is_admin=True))): + for study in self.repository.get_all( + study_filter=StudyFilter(access_permissions=AccessPermissions(is_admin=True)) + ): if isinstance(study, RawStudy) and not study.archived: path = str(study.path) if path not in study_paths: @@ -2171,7 +2172,7 @@ def check_and_update_all_study_versions_in_database(self, params: RequestParamet logger.error(f"User {params.user.id} is not site admin") raise UserHasNotPermissionError() studies = self.repository.get_all( - study_filter=StudyFilter(managed=False, query_user=build_query_user_from_params(params)) + study_filter=StudyFilter(managed=False, access_permissions=AccessPermissions.from_params(params)) ) for study in studies: diff --git a/antarest/study/storage/auto_archive_service.py b/antarest/study/storage/auto_archive_service.py index 50bf9f6a20..a1eafc40a3 100644 --- a/antarest/study/storage/auto_archive_service.py +++ b/antarest/study/storage/auto_archive_service.py @@ -10,7 +10,7 @@ from antarest.core.requests import RequestParameters from antarest.core.utils.fastapi_sqlalchemy import db from antarest.study.model import RawStudy, Study -from antarest.study.repository import QueryUser, StudyFilter +from antarest.study.repository import AccessPermissions, StudyFilter from antarest.study.service import StudyService from antarest.study.storage.variantstudy.model.dbmodel import VariantStudy @@ -30,7 +30,7 @@ def _try_archive_studies(self) -> None: with db(): # in this part full `Read` rights over studies are granted to this function studies: t.Sequence[Study] = self.study_service.repository.get_all( - study_filter=StudyFilter(managed=True, query_user=QueryUser(is_admin=True)) + study_filter=StudyFilter(managed=True, access_permissions=AccessPermissions(is_admin=True)) ) # list of study IDs and boolean indicating if it's a raw study (True) or a variant (False) study_ids_to_archive = [ diff --git a/antarest/study/web/studies_blueprint.py b/antarest/study/web/studies_blueprint.py index 1b9000b6ee..cf76765122 100644 --- a/antarest/study/web/studies_blueprint.py +++ b/antarest/study/web/studies_blueprint.py @@ -28,7 +28,7 @@ StudyMetadataPatchDTO, StudySimResultDTO, ) -from antarest.study.repository import StudyFilter, StudyPagination, StudySortBy, build_query_user_from_params +from antarest.study.repository import AccessPermissions, StudyFilter, StudyPagination, StudySortBy from antarest.study.service import StudyService from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfigDTO @@ -161,7 +161,7 @@ def get_studies( exists=exists, workspace=workspace, folder=folder, - query_user=build_query_user_from_params(params), + access_permissions=AccessPermissions.from_params(params), ) matching_studies = study_service.get_studies_information( diff --git a/tests/storage/repository/test_study.py b/tests/storage/repository/test_study.py index 6fbda37a9c..c97b4ef8c4 100644 --- a/tests/storage/repository/test_study.py +++ b/tests/storage/repository/test_study.py @@ -4,7 +4,7 @@ from antarest.core.model import PublicMode from antarest.login.model import Group, User from antarest.study.model import DEFAULT_WORKSPACE_NAME, RawStudy, Study, StudyContentStatus -from antarest.study.repository import QueryUser, StudyFilter, StudyMetadataRepository +from antarest.study.repository import AccessPermissions, StudyFilter, StudyMetadataRepository from antarest.study.storage.variantstudy.model.dbmodel import VariantStudy from tests.helpers import with_db_context @@ -64,7 +64,7 @@ def test_lifecycle() -> None: c = repo.one(a.id) assert a == c - assert len(repo.get_all(study_filter=StudyFilter(query_user=QueryUser(is_admin=True)))) == 4 + assert len(repo.get_all(study_filter=StudyFilter(access_permissions=AccessPermissions(is_admin=True)))) == 4 assert len(repo.get_all_raw(exists=True)) == 1 assert len(repo.get_all_raw(exists=False)) == 1 assert len(repo.get_all_raw()) == 2 diff --git a/tests/storage/test_service.py b/tests/storage/test_service.py index 165a5f42ba..4d8036d80a 100644 --- a/tests/storage/test_service.py +++ b/tests/storage/test_service.py @@ -44,7 +44,7 @@ TimeSerie, TimeSeriesData, ) -from antarest.study.repository import StudyFilter, StudyMetadataRepository, build_query_user_from_params +from antarest.study.repository import AccessPermissions, StudyFilter, StudyMetadataRepository from antarest.study.service import MAX_MISSING_STUDY_TIMEOUT, StudyService, StudyUpgraderTask, UserHasNotPermissionError from antarest.study.storage.patch_service import PatchService from antarest.study.storage.rawstudy.model.filesystem.config.model import ( @@ -180,7 +180,8 @@ def test_study_listing(db_session: Session) -> None: # 2- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: studies = service.get_studies_information( - study_filter=StudyFilter(managed=False, query_user=build_query_user_from_params(params)), params=params + study_filter=StudyFilter(managed=False, access_permissions=AccessPermissions.from_params(params)), + params=params, ) assert len(db_recorder.sql_statements) == 1, str(db_recorder) @@ -194,7 +195,8 @@ def test_study_listing(db_session: Session) -> None: # 2- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: studies = service.get_studies_information( - study_filter=StudyFilter(managed=True, query_user=build_query_user_from_params(params)), params=params + study_filter=StudyFilter(managed=True, access_permissions=AccessPermissions.from_params(params)), + params=params, ) assert len(db_recorder.sql_statements) == 1, str(db_recorder) @@ -208,7 +210,8 @@ def test_study_listing(db_session: Session) -> None: # 2- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: studies = service.get_studies_information( - study_filter=StudyFilter(managed=None, query_user=build_query_user_from_params(params)), params=params + study_filter=StudyFilter(managed=None, access_permissions=AccessPermissions.from_params(params)), + params=params, ) assert len(db_recorder.sql_statements) == 1, str(db_recorder) @@ -222,7 +225,8 @@ def test_study_listing(db_session: Session) -> None: # 2- the `put` method of `cache` was never used with DBStatementRecorder(db_session.bind) as db_recorder: studies = service.get_studies_information( - study_filter=StudyFilter(managed=None, query_user=build_query_user_from_params(params)), params=params + study_filter=StudyFilter(managed=None, access_permissions=AccessPermissions.from_params(params)), + params=params, ) assert len(db_recorder.sql_statements) == 1, str(db_recorder) with contextlib.suppress(AssertionError): diff --git a/tests/study/test_repository.py b/tests/study/test_repository.py index 7a8364c319..116b3cd9ea 100644 --- a/tests/study/test_repository.py +++ b/tests/study/test_repository.py @@ -8,7 +8,7 @@ from antarest.core.interfaces.cache import ICache from antarest.login.model import Group, User from antarest.study.model import DEFAULT_WORKSPACE_NAME, RawStudy, Tag -from antarest.study.repository import QueryUser, StudyFilter, StudyMetadataRepository +from antarest.study.repository import AccessPermissions, StudyFilter, StudyMetadataRepository from antarest.study.storage.variantstudy.model.dbmodel import VariantStudy from tests.db_statement_recorder import DBStatementRecorder @@ -71,7 +71,7 @@ def test_repository_get_all__general_case( managed=managed, study_ids=study_ids, exists=exists, - query_user=QueryUser(is_admin=True), + access_permissions=AccessPermissions(is_admin=True), ) ) _ = [s.owner for s in all_studies] @@ -104,7 +104,7 @@ def test_repository_get_all__incompatible_case( db_session.commit() # case 1 - study_filter = StudyFilter(managed=False, variant=True, query_user=QueryUser(is_admin=True)) + study_filter = StudyFilter(managed=False, variant=True, access_permissions=AccessPermissions(is_admin=True)) with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] @@ -115,7 +115,9 @@ def test_repository_get_all__incompatible_case( assert not {s.id for s in all_studies} # case 2 - study_filter = StudyFilter(workspace=test_workspace, variant=True, query_user=QueryUser(is_admin=True)) + study_filter = StudyFilter( + workspace=test_workspace, variant=True, access_permissions=AccessPermissions(is_admin=True) + ) with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] @@ -126,7 +128,7 @@ def test_repository_get_all__incompatible_case( assert not {s.id for s in all_studies} # case 3 - study_filter = StudyFilter(exists=False, variant=True, query_user=QueryUser(is_admin=True)) + study_filter = StudyFilter(exists=False, variant=True, access_permissions=AccessPermissions(is_admin=True)) with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] @@ -176,7 +178,9 @@ def test_repository_get_all__study_name_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(name=name, query_user=QueryUser(is_admin=True))) + all_studies = repository.get_all( + study_filter=StudyFilter(name=name, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -221,7 +225,9 @@ def test_repository_get_all__managed_study_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(managed=managed, query_user=QueryUser(is_admin=True))) + all_studies = repository.get_all( + study_filter=StudyFilter(managed=managed, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -262,7 +268,7 @@ def test_repository_get_all__archived_study_filter( # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all( - study_filter=StudyFilter(archived=archived, query_user=QueryUser(is_admin=True)) + study_filter=StudyFilter(archived=archived, access_permissions=AccessPermissions(is_admin=True)) ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] @@ -303,7 +309,9 @@ def test_repository_get_all__variant_study_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(variant=variant, query_user=QueryUser(is_admin=True))) + all_studies = repository.get_all( + study_filter=StudyFilter(variant=variant, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -346,7 +354,7 @@ def test_repository_get_all__study_version_filter( # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all( - study_filter=StudyFilter(versions=versions, query_user=QueryUser(is_admin=True)) + study_filter=StudyFilter(versions=versions, access_permissions=AccessPermissions(is_admin=True)) ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] @@ -395,7 +403,9 @@ def test_repository_get_all__study_users_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(users=users, query_user=QueryUser(is_admin=True))) + all_studies = repository.get_all( + study_filter=StudyFilter(users=users, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -443,7 +453,9 @@ def test_repository_get_all__study_groups_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(groups=groups, query_user=QueryUser(is_admin=True))) + all_studies = repository.get_all( + study_filter=StudyFilter(groups=groups, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -487,7 +499,7 @@ def test_repository_get_all__study_ids_filter( # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all( - study_filter=StudyFilter(study_ids=study_ids, query_user=QueryUser(is_admin=True)) + study_filter=StudyFilter(study_ids=study_ids, access_permissions=AccessPermissions(is_admin=True)) ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] @@ -528,7 +540,9 @@ def test_repository_get_all__study_existence_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(exists=exists, query_user=QueryUser(is_admin=True))) + all_studies = repository.get_all( + study_filter=StudyFilter(exists=exists, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -570,7 +584,7 @@ def test_repository_get_all__study_workspace_filter( # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all( - study_filter=StudyFilter(workspace=workspace, query_user=QueryUser(is_admin=True)) + study_filter=StudyFilter(workspace=workspace, access_permissions=AccessPermissions(is_admin=True)) ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] @@ -614,7 +628,9 @@ def test_repository_get_all__study_folder_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(folder=folder, query_user=QueryUser(is_admin=True))) + all_studies = repository.get_all( + study_filter=StudyFilter(folder=folder, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -665,7 +681,9 @@ def test_repository_get_all__study_tags_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(tags=tags, query_user=QueryUser(is_admin=True))) + all_studies = repository.get_all( + study_filter=StudyFilter(tags=tags, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies]