Skip to content

Commit 9e6aecb

Browse files
committed
moves logic to policy
1 parent 393c6ff commit 9e6aecb

File tree

2 files changed

+38
-30
lines changed

2 files changed

+38
-30
lines changed

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,22 @@
1010
from aiohttp_security.abc import ( # type: ignore[import-untyped]
1111
AbstractAuthorizationPolicy,
1212
)
13+
from common_library.users_enums import UserRole
1314
from models_library.products import ProductName
1415
from models_library.users import UserID
1516
from servicelib.aiohttp.db_asyncpg_engine import get_async_engine
1617
from servicelib.logging_errors import create_troubleshootting_log_kwargs
1718
from simcore_postgres_database.aiopg_errors import DatabaseError as AiopgDatabaseError
1819
from sqlalchemy.exc import DatabaseError as SQLAlchemyDatabaseError
1920

21+
from ..groups import api as groups_service
2022
from ._authz_access_model import (
2123
AuthContextDict,
2224
OptionalContext,
2325
RoleBasedAccessModel,
2426
has_access_by_role,
2527
)
28+
from ._authz_access_roles import NAMED_GROUP_PERMISSIONS
2629
from ._authz_repository import (
2730
ActiveUserIdAndRole,
2831
get_active_user_or_none,
@@ -161,17 +164,39 @@ async def permits(
161164
"authorized_uid"
162165
), f"{user_id}!={context.get('authorized_uid')}"
163166

164-
# product access
167+
# PRODUCT access
165168
if permission == PERMISSION_PRODUCT_LOGIN_KEY:
166169
ok: bool = product_name is not None and await self._has_access_to_product(
167170
user_id=user_id, product_name=product_name
168171
)
169172
return ok
170173

171-
# role-based access
172-
return await has_access_by_role(
174+
# ROLE-BASED access policy
175+
role_allowed = await has_access_by_role(
173176
self._access_model,
174177
role=user_role,
175178
operation=permission,
176179
context=context,
177180
)
181+
182+
if role_allowed:
183+
return True
184+
185+
# GROUP-BASED access policy (only if enabled in context and user is above GUEST role)
186+
product_support_group_id = context.get("product_support_group_id", None)
187+
if (
188+
product_support_group_id is not None
189+
and user_role > UserRole.GUEST
190+
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

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

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
from contextlib import suppress
21
from functools import wraps
32

43
import aiohttp_security.api # type: ignore[import-untyped]
54
from aiohttp import web
65
from servicelib.aiohttp.typing_extension import Handler
6+
from simcore_service_webserver.products import products_web
77

8-
from ..products import products_web
9-
from ._authz_access_model import AuthContextDict
10-
from ._authz_access_roles import NAMED_GROUP_PERMISSIONS
118
from ._authz_web import check_user_authorized
129
from .security_web import check_user_permission
1310

@@ -46,31 +43,17 @@ def group_or_role_permission_required(permission: str):
4643
def _decorator(handler: Handler):
4744
@wraps(handler)
4845
async def _wrapped(request: web.Request):
49-
context = AuthContextDict()
50-
context["authorized_uid"] = user_id = await check_user_authorized(request)
51-
52-
# Check ROLE-BASED permissions first
53-
role_allowed = await aiohttp_security.api.permits(
54-
request, permission, context
55-
)
56-
if role_allowed:
46+
context = {
47+
"authorized_uid": await check_user_authorized(request),
48+
"product_support_group_id": products_web.get_current_product(
49+
request
50+
).support_standard_group_id,
51+
}
52+
53+
# Check both role-based and group-based permissions
54+
if await aiohttp_security.api.permits(request, permission, context):
5755
return await handler(request)
5856

59-
# Check GROUP-BASED permissions
60-
with suppress(
61-
Exception
62-
# If product or group check fails, continue to deny access
63-
# NOTE: Logging omitted to avoid exposing internal errors
64-
):
65-
# FIXME: must be >GUEST !!
66-
if permission in NAMED_GROUP_PERMISSIONS.get(
67-
"PRODUCT_SUPPORT_GROUP", []
68-
) and await products_web.is_user_in_product_support_group(
69-
request,
70-
user_id=user_id,
71-
):
72-
return await handler(request)
73-
7457
# Neither role nor group permissions granted
7558
msg = f"You do not have sufficient access rights for {permission}"
7659
raise web.HTTPForbidden(text=msg)

0 commit comments

Comments
 (0)