Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/pip/python-multipart-0.0.18
Browse files Browse the repository at this point in the history
  • Loading branch information
Daihecyy authored Dec 5, 2024
2 parents 65ab54b + 66e7531 commit 981c772
Show file tree
Hide file tree
Showing 57 changed files with 1,970 additions and 718 deletions.
2 changes: 1 addition & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SQLITE_DB = "test.db" # If set, the application use a SQLite database instead of
# Authorization using JWT #
ACCESS_TOKEN_SECRET_KEY="YWZOHliiI53lJMJc5BI_WbGbA4GF2T7Wbt1airIhOXEa3c021c4-1c55-4182-b141-7778bcc8fac4" # Note: modifing this token requires to update the common `test_check_settings_mocking` test
RSA_PRIVATE_PEM_STRING = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA1tpj3TZDkJakp2RygsM392pQbcmNBOGFT8FlETcRG/JVFT7k\niClJu+CVOJSVD0epfpYp93cYepfw74SezYnBCyuoLJ2yg5Qh4KlCrWmvwM7vhFIN\nx0xddIQi+Gm0T3dxGtv4Ga50TYX4SV4FE3ctJG9m3pyNF6POODp5tMJvShQWYTto\nW9qNhltZ8Z+14bq2INV/efpT47WuMT+VD/fa9/WwopAtgBcQOvq57fv5+DaPOIVR\n9BiP7F+pv+v6wQ373hI22QzCMsA4Whl+BmWFKcFoBDOBRjlW5VqhJWJkWZIRP0q+\nVAZHk2xJK+0YFc9jmaC+ExMtuyHYK0RnQK/8LQIDAQABAoIBABxJ8v4sZ+cAvrs/\nkYhAFf1gpShfck7jNr9SknEa1Aje9m7usf5vmULAhkVF4v55DAsb0HjB2JpDqTiQ\nOKyNZ7qFzAXb2aZTecZv4tScZsS3OngsqZ3FI0T1JPmaSWBxNJY5wkf3XV7btd5L\nH9X5ShtTA7Np33XuXneu01mGhEq3boLro+vfXMHV5QHyle1F4LUFWEqtP0UmZ5wA\nrro0Y7pA8R88tu5X4iWEjQPnAsbRixwFQ9LNMD8+40e1UIguobRySnP5umErHaIh\nKui7ZijLjbZh/dPS0IfpgahL1K6s9XhT3mD9WMvAvMkNtLewHIZZukG45mOQBrjF\nvvyYxoECgYEA+EY6YimGw0IKnUuf+5uZRXST7kDMENz1Flkcj8oZvo47hdX8/lDN\ni0y7gm3VNfHAK2R2KZPmSbtXA0DvS7kmx1/CFcmwkaakhuU5dyCHldWwSaTME3IE\nxjSZfTvlAiq9i6nUflgfkKo3Bdsiq8TYOUAv25S2SwYDH9Tx0fQwwGECgYEA3Ynt\nCHc8e4YRlGT65UQmEZ8cptmqVRyY4ClMU1xht7Pn0G1JwKRraiEL5/LndwscWf3h\nDygQuArJ28pp4d22FEW1LeXozXYUjJoz3anIA45IZ1OihS7Cx7tJB51/QNJeFdF4\nEX/XHaVukHyYSsAxkwCUYOw3cSgZOSEddL5Wf00CgYEA7JlIlDmMwtFR+jqSmJ3c\n//Kr8zZvAnb/Xa/IZ0MrK4yyLsYR1m48o06Ztx9iO4lKIFAZx1+563QL5P7hzOEC\nkqev90GA8hzD2AXksKEgdOrymAvjq3hSEm0YBN+qS1ldzxYmec0TL7L2wq7lqJnr\nkQuZUAG1g2OUYKZ3WSUDvKECgYEAv24NSkFuG/avfiD7w9xtYNCye2KekskROLG2\n6FltfsWQTEQDdNkekChaF2WHqRAKwaBlNymRuNZpsuhnMerZCQ9rDWwbDF86RnyA\n0MuCr7/kxJQ6XQcY/GnTIydu7F5bOlM0gzqKcW2f6m4fUohczf+0N0QmbDsQAJOi\n1lwadgkCgYEA3tkCBJIPTQecfjWiLqSocS6SrwXU+r3Jw6kI3/IB6ban/nsFdHSb\nnADST7f2zZatN6XALwsLU7f2R09R39ub0AJPyfToxo7MngR1rvaUYooF3rLlaU32\n8DqGvGpLkZkwbtcDmcX1zQoHjUo7RvoShZoapr59ihfrkiiEsXOkuGw=\n-----END RSA PRIVATE KEY-----\n"
AUTH_CLIENTS=[["AppAuthClientWithPKCE", null, ["http://127.0.0.1:8000/docs"], "AppAuthClient"], ["AppAuthClientWithClientSecret", "secret", ["http://127.0.0.1:8000/docs"], "AppAuthClient"], ["BaseAuthClient", "secret", ["http://127.0.0.1:8000/docs"], "BaseAuthClient"], ["RalllyAuthClient", "secret", ["http://127.0.0.1:8000/docs"], "RalllyAuthClient"], ["SynapseAuthClient", "secret", ["http://127.0.0.1:8000/docs"], "SynapseAuthClient"], ["AcceptingOnlyECLUsersAuthClient", "secret", ["http://127.0.0.1:8000/docs"], "NextcloudAuthClient"]]
AUTH_CLIENTS=[["AppAuthClientWithPKCE", null, ["http://127.0.0.1:8000/docs"], "AppAuthClient"], ["AppAuthClientWithClientSecret", "secret", ["http://127.0.0.1:8000/docs"], "AppAuthClient"], ["BaseAuthClient", "secret", ["http://127.0.0.1:8000/docs"], "BaseAuthClient"], ["RalllyAuthClient", "secret", ["http://127.0.0.1:8000/docs"], "RalllyAuthClient"], ["SynapseAuthClient", "secret", ["http://127.0.0.1:8000/docs"], "SynapseAuthClient"], ["AcceptingOnlyECLUsersAuthClient", "secret", ["http://127.0.0.1:8000/docs"], "NextcloudAuthClient"], ["RestrictingUsersGroupsAuthClient", "secret", ["http://127.0.0.1:8000/docs"], "DocumensoAuthClient"]]

# OIDC #
# Host or url of the API, used for Openid connect discovery endpoint
Expand Down
87 changes: 63 additions & 24 deletions app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from sqlalchemy.orm import Session

from app import api
from app.core import models_core
from app.core import coredata_core, models_core
from app.core.config import Settings
from app.core.google_api.google_api import GoogleAPI
from app.core.groups.groups_type import GroupType
Expand All @@ -34,7 +34,10 @@
init_and_get_db_engine,
)
from app.modules.module_list import module_list
from app.types.exceptions import ContentHTTPException, GoogleAPIInvalidCredentialsError
from app.types.exceptions import (
ContentHTTPException,
GoogleAPIInvalidCredentialsError,
)
from app.types.sqlalchemy import Base
from app.utils import initialization
from app.utils.redis import limiter
Expand Down Expand Up @@ -192,31 +195,67 @@ def initialize_module_visibility(
"""Add the default module visibilities for Titan"""

with Session(sync_engine) as db:
# Is run to create default module visibilities or when the table is empty
haveBeenInitialized = (
len(initialization.get_all_module_visibility_membership_sync(db)) > 0
module_awareness = initialization.get_core_data_sync(
coredata_core.ModuleVisibilityAwareness,
db,
)
if haveBeenInitialized:

new_modules = [
module
for module in module_list
if module.root not in module_awareness.roots
]
# Is run to create default module visibilities or when the table is empty
if new_modules:
hyperion_error_logger.info(
"Startup: Modules visibility settings have already been initialized",
f"Startup: Some modules visibility settings are empty, initializing them ({[module.root for module in new_modules]})",
)
for module in new_modules:
if module.default_allowed_groups_ids is not None:
for group_id in module.default_allowed_groups_ids:
module_group_visibility = models_core.ModuleGroupVisibility(
root=module.root,
allowed_group_id=group_id,
)
try:
initialization.create_module_group_visibility_sync(
module_visibility=module_group_visibility,
db=db,
)
except ValueError as error:
hyperion_error_logger.fatal(
f"Startup: Could not add module visibility {module.root} in the database: {error}",
)
if module.default_allowed_account_types is not None:
for account_type in module.default_allowed_account_types:
module_account_type_visibility = (
models_core.ModuleAccountTypeVisibility(
root=module.root,
allowed_account_type=account_type,
)
)
try:
initialization.create_module_account_type_visibility_sync(
module_visibility=module_account_type_visibility,
db=db,
)
except ValueError as error:
hyperion_error_logger.fatal(
f"Startup: Could not add module visibility {module.root} in the database: {error}",
)
initialization.set_core_data_sync(
coredata_core.ModuleVisibilityAwareness(
roots=[module.root for module in module_list],
),
db,
)
hyperion_error_logger.info(
f"Startup: Modules visibility settings initialized for {[module.root for module in new_modules]}",
)
else:
hyperion_error_logger.info(
"Startup: Modules visibility settings already initialized",
)
return

hyperion_error_logger.info(
"Startup: Modules visibility settings are empty, initializing them",
)
for module in module_list:
for default_group_id in module.default_allowed_groups_ids:
module_visibility = models_core.ModuleVisibility(
root=module.root,
allowed_group_id=default_group_id.value,
)
try:
initialization.create_module_visibility_sync(module_visibility, db)
except IntegrityError as error:
hyperion_error_logger.fatal(
f"Startup: Could not add module visibility {module.root}<{default_group_id}> in the database: {error}",
)


def use_route_path_as_operation_ids(app: FastAPI) -> None:
Expand Down
11 changes: 5 additions & 6 deletions app/core/auth/endpoints_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
from app.types.exceptions import AuthHTTPException
from app.types.scopes_type import ScopeType
from app.utils.auth.providers import BaseAuthClient
from app.utils.tools import is_user_external, is_user_member_of_an_allowed_group
from app.utils.tools import is_user_member_of_an_allowed_group

router = APIRouter(tags=["Auth"])

Expand Down Expand Up @@ -322,19 +322,18 @@ async def authorize_validation(
),
status_code=status.HTTP_302_FOUND,
)
if not auth_client.allow_external_users:
if is_user_external(user):
if auth_client.allowed_account_types is not None:
if user.account_type not in auth_client.allowed_account_types:
hyperion_access_logger.warning(
f"Authorize-validation: external users are disabled for this auth provider {auth_client.client_id} ({request_id})",
f"Authorize-validation: user account type is not allowed {authorizereq.email} ({request_id})",
)
return RedirectResponse(
settings.CLIENT_URL
+ calypsso.get_error_relative_url(
message="External users are not allowed",
message="User account type is not allowed",
),
status_code=status.HTTP_302_FOUND,
)

# We generate a new authorization_code
# The authorization code MUST expire
# shortly after it is issued to mitigate the risk of leaks. A
Expand Down
9 changes: 9 additions & 0 deletions app/core/coredata_core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from app.types.core_data import BaseCoreData


class ModuleVisibilityAwareness(BaseCoreData):
"""
Schema for module visibility awareness
"""

roots: list[str] = []
115 changes: 78 additions & 37 deletions app/core/cruds_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,48 @@
from sqlalchemy.ext.asyncio import AsyncSession

from app.core import models_core


async def get_all_module_visibility_membership(
db: AsyncSession,
):
"""Return the every module with their visibility"""
result = await db.execute(select(models_core.ModuleVisibility))
return result.unique().scalars().all()
from app.core.groups.groups_type import AccountType


async def get_modules_by_user(
user: models_core.CoreUser,
db: AsyncSession,
) -> Sequence[str]:
) -> list[str]:
"""Return the modules a user has access to"""

userGroupIds = [group.id for group in user.groups]

result = await db.execute(
select(models_core.ModuleVisibility.root)
.where(models_core.ModuleVisibility.allowed_group_id.in_(userGroupIds))
.group_by(models_core.ModuleVisibility.root),
result_group = list(
(
await db.execute(
select(models_core.ModuleGroupVisibility.root)
.where(
models_core.ModuleGroupVisibility.allowed_group_id.in_(
userGroupIds,
),
)
.group_by(models_core.ModuleGroupVisibility.root),
)
)
.unique()
.scalars()
.all(),
)
result_account_type = list(
(
await db.execute(
select(models_core.ModuleAccountTypeVisibility.root).where(
models_core.ModuleAccountTypeVisibility.allowed_account_type
== user.account_type,
),
)
)
.unique()
.scalars()
.all(),
)

return result.unique().scalars().all()
return result_group + result_account_type


async def get_allowed_groups_by_root(
Expand All @@ -40,35 +57,32 @@ async def get_allowed_groups_by_root(

result = await db.execute(
select(
models_core.ModuleVisibility.allowed_group_id,
).where(models_core.ModuleVisibility.root == root),
models_core.ModuleGroupVisibility.allowed_group_id,
).where(models_core.ModuleGroupVisibility.root == root),
)

resultList = result.unique().scalars().all()

return resultList
return result.unique().scalars().all()


async def get_module_visibility(
async def get_allowed_account_types_by_root(
root: str,
group_id: str,
db: AsyncSession,
) -> models_core.ModuleVisibility | None:
"""Return module visibility by root and group id"""
) -> Sequence[str]:
"""Return the groups allowed to access to a specific root"""

result = await db.execute(
select(models_core.ModuleVisibility).where(
models_core.ModuleVisibility.allowed_group_id == group_id,
models_core.ModuleVisibility.root == root,
),
select(
models_core.ModuleAccountTypeVisibility.allowed_account_type,
).where(models_core.ModuleAccountTypeVisibility.root == root),
)
return result.unique().scalars().first()

return result.unique().scalars().all()


async def create_module_visibility(
module_visibility: models_core.ModuleVisibility,
async def create_module_group_visibility(
module_visibility: models_core.ModuleGroupVisibility,
db: AsyncSession,
) -> models_core.ModuleVisibility:
) -> None:
"""Create a new module visibility in database and return it"""

db.add(module_visibility)
Expand All @@ -77,19 +91,46 @@ async def create_module_visibility(
except IntegrityError:
await db.rollback()
raise
else:
return module_visibility


async def delete_module_visibility(
async def create_module_account_type_visibility(
module_visibility: models_core.ModuleAccountTypeVisibility,
db: AsyncSession,
) -> None:
"""Create a new module visibility in database and return it"""

db.add(module_visibility)
try:
await db.commit()
except IntegrityError:
await db.rollback()
raise


async def delete_module_group_visibility(
root: str,
allowed_group_id: str,
db: AsyncSession,
):
await db.execute(
delete(models_core.ModuleVisibility).where(
models_core.ModuleVisibility.root == root,
models_core.ModuleVisibility.allowed_group_id == allowed_group_id,
delete(models_core.ModuleGroupVisibility).where(
models_core.ModuleGroupVisibility.root == root,
models_core.ModuleGroupVisibility.allowed_group_id == allowed_group_id,
),
)
await db.commit()


async def delete_module_account_type_visibility(
root: str,
allowed_account_type: AccountType,
db: AsyncSession,
):
await db.execute(
delete(models_core.ModuleAccountTypeVisibility).where(
models_core.ModuleAccountTypeVisibility.root == root,
models_core.ModuleAccountTypeVisibility.allowed_account_type
== allowed_account_type,
),
)
await db.commit()
Expand Down
Loading

0 comments on commit 981c772

Please sign in to comment.