Skip to content

Commit 4c32f83

Browse files
committed
refactor product-support logic to product and group plugins
1 parent 7082287 commit 4c32f83

File tree

8 files changed

+48
-42
lines changed

8 files changed

+48
-42
lines changed

services/web/server/src/simcore_service_webserver/groups/_groups_repository.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,22 @@ async def is_user_by_email_in_group(
731731
return user_id is not None
732732

733733

734+
async def is_user_in_group(
735+
app: web.Application,
736+
connection: AsyncConnection | None = None,
737+
*,
738+
user_id: UserID,
739+
group_id: GroupID,
740+
) -> bool:
741+
async with pass_or_acquire_connection(get_asyncpg_engine(app), connection) as conn:
742+
result = await conn.scalar(
743+
sa.select(user_to_groups.c.uid).where(
744+
(user_to_groups.c.uid == user_id) & (user_to_groups.c.gid == group_id)
745+
)
746+
)
747+
return result is not None
748+
749+
734750
async def add_new_user_in_group(
735751
app: web.Application,
736752
connection: AsyncConnection | None = None,

services/web/server/src/simcore_service_webserver/groups/_groups_service.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,14 @@ async def is_user_by_email_in_group(
261261
)
262262

263263

264+
async def is_user_in_group(
265+
app: web.Application, *, user_id: UserID, group_id: GroupID
266+
) -> bool:
267+
return await _groups_repository.is_user_in_group(
268+
app, user_id=user_id, group_id=group_id
269+
)
270+
271+
264272
async def auto_add_user_to_groups(app: web.Application, user_id: UserID) -> None:
265273
user: dict = await users_service.get_user(app, user_id)
266274
return await _groups_repository.auto_add_user_to_groups(app, user=user)

services/web/server/src/simcore_service_webserver/groups/api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
get_product_group_for_user,
1010
get_user_profile_groups,
1111
is_user_by_email_in_group,
12+
is_user_in_group,
1213
list_all_user_groups_ids,
1314
list_group_members,
1415
list_user_groups_ids_with_read_access,
@@ -23,6 +24,7 @@
2324
"get_product_group_for_user",
2425
"get_user_profile_groups",
2526
"is_user_by_email_in_group",
27+
"is_user_in_group",
2628
"list_all_user_groups_ids",
2729
"list_group_members",
2830
"list_user_groups_ids_with_read_access",

services/web/server/src/simcore_service_webserver/products/_web_helpers.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
import aiofiles
55
from aiohttp import web
66
from models_library.products import ProductName
7+
from models_library.users import UserID
78
from simcore_postgres_database.utils_products_prices import ProductPriceInfo
89

910
from .._resources import webserver_resources
1011
from ..constants import RQ_PRODUCT_KEY
12+
from ..groups import api as groups_service
1113
from . import _service
1214
from ._web_events import APP_PRODUCTS_TEMPLATES_DIR_KEY
1315
from .errors import (
@@ -38,6 +40,22 @@ def get_current_product(request: web.Request) -> Product:
3840
return current_product
3941

4042

43+
async def is_user_in_product_support_group(
44+
request: web.Request, *, user_id: UserID
45+
) -> bool:
46+
"""Checks if the user belongs to the support group of the given product.
47+
If the product does not have a support group, returns False.
48+
"""
49+
product = get_current_product(request)
50+
if product.support_standard_group_id is None:
51+
return False
52+
return await groups_service.is_user_in_group(
53+
app=request.app,
54+
user_id=user_id,
55+
group_id=product.support_standard_group_id,
56+
)
57+
58+
4159
def _get_current_product_or_none(request: web.Request) -> Product | None:
4260
with contextlib.suppress(ProductNotFoundError, UnknownProductError):
4361
product: Product = get_current_product(request)

services/web/server/src/simcore_service_webserver/products/products_web.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
get_current_product_credit_price_info,
44
get_product_name,
55
get_product_template_path,
6+
is_user_in_product_support_group,
67
)
78

89
__all__: tuple[str, ...] = (
910
"get_current_product",
1011
"get_current_product_credit_price_info",
1112
"get_product_name",
1213
"get_product_template_path",
14+
"is_user_in_product_support_group",
1315
)
1416
# nopycln: file

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

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

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

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

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@
44
import aiohttp_security.api # type: ignore[import-untyped]
55
import passlib.hash
66
from aiohttp import web
7-
from models_library.users import UserID
8-
from simcore_service_webserver.products._models import Product
97

10-
from ..db.plugin import get_asyncpg_engine
11-
from . import _authz_repository
128
from ._authz_access_model import RoleBasedAccessModel
139
from ._authz_policy import AuthorizationPolicy
1410
from ._constants import PERMISSION_PRODUCT_LOGIN_KEY
@@ -26,21 +22,6 @@ async def clean_auth_policy_cache(app: web.Application) -> None:
2622
await autz_policy.clear_cache()
2723

2824

29-
async def is_user_in_product_support_group(
30-
app: web.Application, *, product: Product, user_id: UserID
31-
) -> bool:
32-
"""Checks if the user belongs to the support group of the given product.
33-
If the product does not have a support group, returns False.
34-
"""
35-
if product.support_standard_group_id is None:
36-
return False
37-
return await _authz_repository.is_user_in_group(
38-
get_asyncpg_engine(app),
39-
user_id=user_id,
40-
group_id=product.support_standard_group_id,
41-
)
42-
43-
4425
#
4526
# utils (i.e. independent from setup)
4627
#

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
import aiohttp_security.api # type: ignore[import-untyped]
55
from aiohttp import web
66
from servicelib.aiohttp.typing_extension import Handler
7-
from simcore_service_webserver.security._authz_service import (
8-
is_user_in_product_support_group,
9-
)
107

118
from ..products import products_web
129
from ._authz_access_model import AuthContextDict
@@ -67,9 +64,8 @@ async def _wrapped(request: web.Request):
6764
):
6865
if permission in NAMED_GROUP_PERMISSIONS.get(
6966
"PRODUCT_SUPPORT_GROUP", []
70-
) and await is_user_in_product_support_group(
71-
request.app,
72-
product=products_web.get_current_product(request),
67+
) and await products_web.is_user_in_product_support_group(
68+
request,
7369
user_id=user_id,
7470
):
7571
return await handler(request)

0 commit comments

Comments
 (0)