Coverage for api/handlers/authorization/company_employee_access.py: 16%
73 statements
« prev ^ index » next coverage.py v7.6.2, created at 2024-10-10 03:02 +0300
« prev ^ index » next coverage.py v7.6.2, created at 2024-10-10 03:02 +0300
1from contextlib import suppress
2from typing import Any
4from bson import ObjectId
5from exceptions import NotFoundHTTPError, SubsidiaryIsNotAssigned
6from handlers.authorization.check_role import has_role
7from mongodb import clients_col, cm_clients_col
8from sotrans_models.models.misc.client import (
9 ClientDBModel,
10 ManagersClientsDBModel,
11)
12from sotrans_models.models.orders.order import OrderDBModel
13from sotrans_models.models.roles import SotransRole
14from sotrans_models.models.users import SotransOIDCUserModel
15from utils.helper import get_subsidiary_oid
17###################################################
18# OPTIMIZED: #
19# assert_is_assigned_to_client_query #
20# flexible_company_assertion_query #
21###################################################
24async def assert_is_assigned_to_client_query(
25 executor: SotransOIDCUserModel,
26 for_grabber: bool = False,
27 with_sub: bool = True,
28) -> dict[str, Any]:
29 if has_role(executor, SotransRole.company_director):
30 return {}
31 assigned_clients = await get_assigned_clients_ids(executor)
32 if for_grabber:
33 assigned_clients = list(map(str, assigned_clients))
34 client_filter = {"client.id": {"$in": assigned_clients}}
35 if with_sub:
36 with suppress(SubsidiaryIsNotAssigned):
37 sub_id = await get_subsidiary_oid(executor)
38 client_filter = {
39 "$or": [ # type: ignore[dict-item]
40 client_filter,
41 {OrderDBModel.client.subsidiary.id: sub_id},
42 ]
43 }
44 return client_filter
47async def manager_as_higher_role_query(
48 user: SotransOIDCUserModel, for_grabber: bool = False
49) -> dict[str, Any]:
50 if has_role(user, SotransRole.company_director):
51 return {}
52 clients_by_responsible = await assert_is_assigned_to_client_query(
53 user, for_grabber, with_sub=False
54 )
55 assigned_subsidiary_or_logistician_for_order = (
56 assigned_subsidiary_or_logistician_for_order_query(
57 user, to_grabber=for_grabber
58 )
59 )
60 complex_filter = [clients_by_responsible]
61 if "$or" in assigned_subsidiary_or_logistician_for_order:
62 complex_filter.extend(
63 assigned_subsidiary_or_logistician_for_order["$or"]
64 )
65 else:
66 complex_filter.append(assigned_subsidiary_or_logistician_for_order)
67 return {"$or": complex_filter}
70async def flexible_company_assertion_query(
71 user: SotransOIDCUserModel, to_grabber: bool = False
72) -> dict[str, Any]:
73 if has_role(user, SotransRole.company_manager):
74 return await manager_as_higher_role_query(user, to_grabber)
75 return assigned_subsidiary_or_logistician_for_order_query(
76 user, to_grabber=to_grabber
77 )
80#################################################
81# WITH SUBSIDIARIES #
82#################################################
85def assigned_subsidiary_or_logistician_for_order_query(
86 user: SotransOIDCUserModel, *, to_grabber: bool = False
87):
88 if has_role(user, SotransRole.company_director):
89 return {}
90 query = {
91 OrderDBModel.assigned.company.employee.id: str(user.sub)
92 if to_grabber
93 else user.sub
94 }
95 if user.subsidiary_id:
96 sub_id = (
97 user.subsidiary_id if to_grabber else ObjectId(user.subsidiary_id)
98 )
99 subsidiary_order_q = {
100 OrderDBModel.assigned.company.subsidiary.id: sub_id
101 }
102 subsidiary_client_q = {OrderDBModel.client.subsidiary.id: sub_id}
103 query = {"$or": [subsidiary_client_q, subsidiary_order_q, query]}
104 return query
107async def get_assigned_clients_ids(
108 executor: SotransOIDCUserModel,
109) -> list[ObjectId]:
110 if has_role(executor, SotransRole.company_director):
111 assigned_clients = await clients_col.find_batch({})
112 return [ca["_id"] for ca in assigned_clients]
113 elif has_role(executor, SotransRole.company_logistician):
114 assigned_clients = await cm_clients_col.find_single(
115 "manager_id", executor.sub
116 )
117 if not assigned_clients:
118 return []
119 return ManagersClientsDBModel(**assigned_clients).clients_ids
120 else:
121 return []
124async def assert_client_assigned(
125 executor: SotransOIDCUserModel, client_id: ObjectId
126):
127 if has_role(executor, SotransRole.company_director):
128 return True
129 elif has_role(executor, SotransRole.company_logistician):
130 client_ids = await get_assigned_clients_ids(executor)
131 if client_id in client_ids:
132 return True
133 with suppress(SubsidiaryIsNotAssigned):
134 sub_id = await get_subsidiary_oid(executor)
135 client = await clients_col.find_single("_id", client_id)
136 if client is None:
137 raise NotFoundHTTPError("клиент")
138 cm = ClientDBModel(**client)
139 if cm.subsidiary and cm.subsidiary.id == sub_id:
140 return True
141 return False