Skip to content

Commit 55532ed

Browse files
committed
fixes cyclic import
1 parent 0e327fc commit 55532ed

File tree

2 files changed

+47
-22
lines changed

2 files changed

+47
-22
lines changed

services/web/server/src/simcore_service_webserver/security/_authz_policy.py

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,15 @@
1818
from simcore_postgres_database.aiopg_errors import DatabaseError as AiopgDatabaseError
1919
from sqlalchemy.exc import DatabaseError as SQLAlchemyDatabaseError
2020

21-
from ..groups import api as groups_service
21+
from . import _authz_repository
2222
from ._authz_access_model import (
2323
AuthContextDict,
2424
OptionalContext,
2525
RoleBasedAccessModel,
2626
has_access_by_role,
2727
)
2828
from ._authz_access_roles import NAMED_GROUP_PERMISSIONS
29-
from ._authz_repository import (
30-
ActiveUserIdAndRole,
31-
get_active_user_or_none,
32-
is_user_in_product_name,
33-
)
29+
from ._authz_repository import ActiveUserIdAndRole
3430
from ._constants import MSG_AUTH_NOT_AVAILABLE, PERMISSION_PRODUCT_LOGIN_KEY
3531
from ._identity_web import IdentityStr
3632

@@ -82,7 +78,7 @@ async def _get_authorized_user_or_none(
8278
web.HTTPServiceUnavailable: if database raises an exception
8379
"""
8480
with _handle_exceptions_as_503():
85-
return await get_active_user_or_none(
81+
return await _authz_repository.get_active_user_or_none(
8682
get_async_engine(self._app), email=email
8783
)
8884

@@ -99,17 +95,36 @@ async def _has_access_to_product(
9995
web.HTTPServiceUnavailable: if database raises an exception
10096
"""
10197
with _handle_exceptions_as_503():
102-
return await is_user_in_product_name(
98+
return await _authz_repository.is_user_in_product_name(
10399
get_async_engine(self._app), user_id=user_id, product_name=product_name
104100
)
105101

102+
@cached(
103+
ttl=_AUTHZ_BURST_CACHE_TTL,
104+
namespace=__name__,
105+
key_builder=lambda f, *ag, **kw: f"{f.__name__}/{kw['user_id']}/{kw['group_id']}",
106+
)
107+
async def _is_user_in_group(self, *, user_id: UserID, group_id: int) -> bool:
108+
"""
109+
Raises:
110+
web.HTTPServiceUnavailable: if database raises an exception
111+
"""
112+
with _handle_exceptions_as_503():
113+
return await _authz_repository.is_user_in_group(
114+
get_async_engine(self._app), user_id=user_id, group_id=group_id
115+
)
116+
106117
@property
107118
def access_model(self) -> RoleBasedAccessModel:
108119
return self._access_model
109120

110121
async def clear_cache(self):
111122
# pylint: disable=no-member
112-
for fun in (self._get_authorized_user_or_none, self._has_access_to_product):
123+
for fun in (
124+
self._get_authorized_user_or_none,
125+
self._has_access_to_product,
126+
self._is_user_in_group,
127+
):
113128
autz_cache: BaseCache = fun.cache
114129
await autz_cache.clear()
115130

@@ -184,19 +199,13 @@ async def permits(
184199

185200
# GROUP-BASED access policy (only if enabled in context and user is above GUEST role)
186201
product_support_group_id = context.get("product_support_group_id", None)
187-
if (
202+
group_allowed = (
188203
product_support_group_id is not None
189204
and user_role > UserRole.GUEST
190205
and permission in NAMED_GROUP_PERMISSIONS.get("PRODUCT_SUPPORT_GROUP", [])
191-
):
192-
with contextlib.suppress(
193-
Exception
194-
# If product or group check fails, continue to deny access
195-
# NOTE: Logging omitted to avoid exposing internal errors
196-
):
197-
if await groups_service.is_user_in_group(
198-
self._app, user_id=user_id, group_id=product_support_group_id
199-
):
200-
return True
201-
202-
return False
206+
and await self._is_user_in_group(
207+
user_id=user_id, group_id=product_support_group_id
208+
)
209+
)
210+
211+
return group_allowed # noqa: RET504

services/web/server/src/simcore_service_webserver/security/_authz_repository.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import sqlalchemy as sa
55
from models_library.basic_types import IdInt
6+
from models_library.groups import GroupID
67
from models_library.products import ProductName
78
from models_library.users import UserID
89
from pydantic import TypeAdapter
@@ -65,3 +66,18 @@ async def is_user_in_product_name(
6566
)
6667
is not None
6768
)
69+
70+
71+
async def is_user_in_group(
72+
engine: AsyncEngine,
73+
*,
74+
user_id: UserID,
75+
group_id: GroupID,
76+
) -> bool:
77+
async with engine.connect() as conn:
78+
result = await conn.scalar(
79+
sa.select(user_to_groups.c.uid).where(
80+
(user_to_groups.c.uid == user_id) & (user_to_groups.c.gid == group_id)
81+
)
82+
)
83+
return result is not None

0 commit comments

Comments
 (0)