From 2978fb95831590d5f0019a20cfaf164c84690e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20Ohlsson=20=C3=85ngnell?= <40887124+islean@users.noreply.github.com> Date: Tue, 28 Jan 2025 14:25:42 +0100 Subject: [PATCH 1/2] Patch user rule (#4163) (patch) ### Fixed - Admins are allowed to place orders for all customers --- .../orders/validation/rules/order/rules.py | 5 +++-- cg/store/crud/read.py | 8 +++++++ .../validation_service/test_order_rules.py | 21 ++++++++++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/cg/services/orders/validation/rules/order/rules.py b/cg/services/orders/validation/rules/order/rules.py index e7bd52b3f3..88bbe17663 100644 --- a/cg/services/orders/validation/rules/order/rules.py +++ b/cg/services/orders/validation/rules/order/rules.py @@ -4,6 +4,7 @@ UserNotAssociatedWithCustomerError, ) from cg.services.orders.validation.models.order import Order +from cg.store.models import User from cg.store.store import Store @@ -22,13 +23,13 @@ def validate_customer_exists( def validate_user_belongs_to_customer( order: Order, store: Store, **kwargs ) -> list[UserNotAssociatedWithCustomerError]: + user: User = store.get_user_by_entry_id(order._user_id) has_access: bool = store.is_user_associated_with_customer( user_id=order._user_id, customer_internal_id=order.customer, ) - errors: list[UserNotAssociatedWithCustomerError] = [] - if not has_access: + if not (user.is_admin or has_access): error = UserNotAssociatedWithCustomerError() errors.append(error) return errors diff --git a/cg/store/crud/read.py b/cg/store/crud/read.py index c062bb77ec..28f3c47553 100644 --- a/cg/store/crud/read.py +++ b/cg/store/crud/read.py @@ -976,6 +976,14 @@ def get_user_by_email(self, email: str) -> User | None: filter_functions=[UserFilter.BY_EMAIL], ).first() + def get_user_by_entry_id(self, id: int) -> User | None: + """Return a user by its entry id.""" + return apply_user_filter( + users=self._get_query(table=User), + user_id=id, + filter_functions=[UserFilter.BY_ID], + ).first() + def is_user_associated_with_customer(self, user_id: int, customer_internal_id: str) -> bool: user: User | None = apply_user_filter( users=self._get_query(table=User), diff --git a/tests/services/orders/validation_service/test_order_rules.py b/tests/services/orders/validation_service/test_order_rules.py index cffac34469..9c15884976 100644 --- a/tests/services/orders/validation_service/test_order_rules.py +++ b/tests/services/orders/validation_service/test_order_rules.py @@ -11,6 +11,7 @@ from cg.services.orders.validation.workflows.tomte.models.order import TomteOrder from cg.store.models import Customer from cg.store.store import Store +from tests.store_helpers import StoreHelpers def test_validate_customer_can_skip_reception_control(base_store: Store, valid_order: TomteOrder): @@ -47,9 +48,12 @@ def test_validate_customer_does_not_exist(base_store: Store, valid_order: TomteO assert isinstance(errors[0], CustomerDoesNotExistError) -def test_validate_user_belongs_to_customer(base_store: Store, valid_order: TomteOrder): +def test_validate_user_belongs_to_customer( + base_store: Store, valid_order: TomteOrder, helpers: StoreHelpers +): # GIVEN an order for a customer which the logged-in user does not have access to customer: Customer = base_store.get_customer_by_internal_id(valid_order.customer) + helpers.ensure_user(store=base_store, customer=customer) customer.users = [] # WHEN validating that the user belongs to the customer account @@ -62,3 +66,18 @@ def test_validate_user_belongs_to_customer(base_store: Store, valid_order: Tomte # THEN the error should concern the user not belonging to the customer assert isinstance(errors[0], UserNotAssociatedWithCustomerError) + + +def test_validate_admin_bypass(base_store: Store, valid_order: TomteOrder, helpers: StoreHelpers): + # GIVEN an order for a customer which the logged-in _admin_ user does not have access to + customer: Customer = base_store.get_customer_by_internal_id(valid_order.customer) + helpers.ensure_user(store=base_store, customer=customer, is_admin=True) + customer.users = [] + + # WHEN validating that the user belongs to the customer account + errors: list[UserNotAssociatedWithCustomerError] = validate_user_belongs_to_customer( + order=valid_order, store=base_store + ) + + # THEN no error should be raised + assert not errors From 8cba7f7670122225d32189b435e12cbd7a8fb85d Mon Sep 17 00:00:00 2001 From: Clinical Genomics Bot Date: Tue, 28 Jan 2025 13:26:09 +0000 Subject: [PATCH 2/2] =?UTF-8?q?Bump=20version:=2067.0.8=20=E2=86=92=2067.0?= =?UTF-8?q?.9=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cg/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index fccb1be93e..79429b895b 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.0.8 +current_version = 67.0.9 commit = True tag = True tag_name = v{new_version} diff --git a/cg/__init__.py b/cg/__init__.py index c5a1ba238a..f477f5d8b4 100644 --- a/cg/__init__.py +++ b/cg/__init__.py @@ -1,2 +1,2 @@ __title__ = "cg" -__version__ = "67.0.8" +__version__ = "67.0.9" diff --git a/pyproject.toml b/pyproject.toml index 35a226f9b5..e662a5a5f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "cg" -version = "67.0.8" +version = "67.0.9" description = "Clinical Genomics command center" readme = {file = "README.md", content-type = "text/markdown"} homepage = "https://github.com/Clinical-Genomics/cg"