mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: adapt UGs to roles
This commit is contained in:
parent
0df250c729
commit
a6152ef1f5
9 changed files with 265 additions and 70 deletions
|
|
@ -19,6 +19,7 @@ class Permission(BaseModel):
|
||||||
class Rights(BaseModel):
|
class Rights(BaseModel):
|
||||||
courses: Permission
|
courses: Permission
|
||||||
users: Permission
|
users: Permission
|
||||||
|
usergroups : Permission
|
||||||
collections: Permission
|
collections: Permission
|
||||||
organizations: Permission
|
organizations: Permission
|
||||||
coursechapters: Permission
|
coursechapters: Permission
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@ from sqlalchemy import Column, ForeignKey, Integer
|
||||||
from sqlmodel import Field, SQLModel
|
from sqlmodel import Field, SQLModel
|
||||||
|
|
||||||
|
|
||||||
class UserGroupRessource(SQLModel, table=True):
|
class UserGroupResource(SQLModel, table=True):
|
||||||
id: Optional[int] = Field(default=None, primary_key=True)
|
id: Optional[int] = Field(default=None, primary_key=True)
|
||||||
usergroup_id: int = Field(
|
usergroup_id: int = Field(
|
||||||
sa_column=Column(Integer, ForeignKey("usergroup.id", ondelete="CASCADE"))
|
sa_column=Column(Integer, ForeignKey("usergroup.id", ondelete="CASCADE"))
|
||||||
)
|
)
|
||||||
ressource_uuid: str = ""
|
resource_uuid: str = ""
|
||||||
org_id: int = Field(
|
org_id: int = Field(
|
||||||
sa_column=Column(Integer, ForeignKey("organization.id", ondelete="CASCADE"))
|
sa_column=Column(Integer, ForeignKey("organization.id", ondelete="CASCADE"))
|
||||||
)
|
)
|
||||||
|
|
@ -5,12 +5,13 @@ from src.services.users.users import delete_user_by_id
|
||||||
from src.db.usergroups import UserGroupCreate, UserGroupRead, UserGroupUpdate
|
from src.db.usergroups import UserGroupCreate, UserGroupRead, UserGroupUpdate
|
||||||
from src.db.users import PublicUser
|
from src.db.users import PublicUser
|
||||||
from src.services.users.usergroups import (
|
from src.services.users.usergroups import (
|
||||||
add_ressources_to_usergroup,
|
add_resources_to_usergroup,
|
||||||
add_users_to_usergroup,
|
add_users_to_usergroup,
|
||||||
create_usergroup,
|
create_usergroup,
|
||||||
delete_usergroup_by_id,
|
delete_usergroup_by_id,
|
||||||
read_usergroup_by_id,
|
read_usergroup_by_id,
|
||||||
remove_ressources_from_usergroup,
|
read_usergroups_by_org_id,
|
||||||
|
remove_resources_from_usergroup,
|
||||||
remove_users_from_usergroup,
|
remove_users_from_usergroup,
|
||||||
update_usergroup_by_id,
|
update_usergroup_by_id,
|
||||||
)
|
)
|
||||||
|
|
@ -50,6 +51,20 @@ async def api_get_usergroup(
|
||||||
return await read_usergroup_by_id(request, db_session, current_user, usergroup_id)
|
return await read_usergroup_by_id(request, db_session, current_user, usergroup_id)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/org/{org_id}", response_model=list[UserGroupRead], tags=["usergroups"])
|
||||||
|
async def api_get_usergroups(
|
||||||
|
*,
|
||||||
|
request: Request,
|
||||||
|
db_session: Session = Depends(get_db_session),
|
||||||
|
current_user: PublicUser = Depends(get_current_user),
|
||||||
|
org_id: int,
|
||||||
|
) -> list[UserGroupRead]:
|
||||||
|
"""
|
||||||
|
Get UserGroups by Org
|
||||||
|
"""
|
||||||
|
return await read_usergroups_by_org_id(request, db_session, current_user, org_id)
|
||||||
|
|
||||||
|
|
||||||
@router.put("/{usergroup_id}", response_model=UserGroupRead, tags=["usergroups"])
|
@router.put("/{usergroup_id}", response_model=UserGroupRead, tags=["usergroups"])
|
||||||
async def api_update_usergroup(
|
async def api_update_usergroup(
|
||||||
*,
|
*,
|
||||||
|
|
@ -115,35 +130,35 @@ async def api_delete_users_from_usergroup(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/{usergroup_id}/add_ressources", tags=["usergroups"])
|
@router.post("/{usergroup_id}/add_resources", tags=["usergroups"])
|
||||||
async def api_add_ressources_to_usergroup(
|
async def api_add_resources_to_usergroup(
|
||||||
*,
|
*,
|
||||||
request: Request,
|
request: Request,
|
||||||
db_session: Session = Depends(get_db_session),
|
db_session: Session = Depends(get_db_session),
|
||||||
current_user: PublicUser = Depends(get_current_user),
|
current_user: PublicUser = Depends(get_current_user),
|
||||||
usergroup_id: int,
|
usergroup_id: int,
|
||||||
ressource_uuids: str,
|
resource_uuids: str,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Add Ressources to UserGroup
|
Add Resources to UserGroup
|
||||||
"""
|
"""
|
||||||
return await add_ressources_to_usergroup(
|
return await add_resources_to_usergroup(
|
||||||
request, db_session, current_user, usergroup_id, ressource_uuids
|
request, db_session, current_user, usergroup_id, resource_uuids
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{usergroup_id}/remove_ressources", tags=["usergroups"])
|
@router.delete("/{usergroup_id}/remove_resources", tags=["usergroups"])
|
||||||
async def api_delete_ressources_from_usergroup(
|
async def api_delete_resources_from_usergroup(
|
||||||
*,
|
*,
|
||||||
request: Request,
|
request: Request,
|
||||||
db_session: Session = Depends(get_db_session),
|
db_session: Session = Depends(get_db_session),
|
||||||
current_user: PublicUser = Depends(get_current_user),
|
current_user: PublicUser = Depends(get_current_user),
|
||||||
usergroup_id: int,
|
usergroup_id: int,
|
||||||
ressource_uuids: str,
|
resource_uuids: str,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Delete Ressources from UserGroup
|
Delete Resources from UserGroup
|
||||||
"""
|
"""
|
||||||
return await remove_ressources_from_usergroup(
|
return await remove_resources_from_usergroup(
|
||||||
request, db_session, current_user, usergroup_id, ressource_uuids
|
request, db_session, current_user, usergroup_id, resource_uuids
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,27 @@
|
||||||
from fastapi import HTTPException, status
|
from fastapi import HTTPException, status
|
||||||
|
|
||||||
|
|
||||||
async def check_element_type(element_id):
|
async def check_element_type(element_uuid):
|
||||||
"""
|
"""
|
||||||
Check if the element is a course, a user, a house or a collection, by checking its prefix
|
Check if the element is a course, a user, a house or a collection, by checking its prefix
|
||||||
"""
|
"""
|
||||||
if element_id.startswith("course_"):
|
if element_uuid.startswith("course_"):
|
||||||
return "courses"
|
return "courses"
|
||||||
elif element_id.startswith("user_"):
|
elif element_uuid.startswith("user_"):
|
||||||
return "users"
|
return "users"
|
||||||
elif element_id.startswith("house_"):
|
elif element_uuid.startswith("usergroup_"):
|
||||||
|
return "usergroups"
|
||||||
|
elif element_uuid.startswith("house_"):
|
||||||
return "houses"
|
return "houses"
|
||||||
elif element_id.startswith("org_"):
|
elif element_uuid.startswith("org_"):
|
||||||
return "organizations"
|
return "organizations"
|
||||||
elif element_id.startswith("chapter_"):
|
elif element_uuid.startswith("chapter_"):
|
||||||
return "coursechapters"
|
return "coursechapters"
|
||||||
elif element_id.startswith("collection_"):
|
elif element_uuid.startswith("collection_"):
|
||||||
return "collections"
|
return "collections"
|
||||||
elif element_id.startswith("activity_"):
|
elif element_uuid.startswith("activity_"):
|
||||||
return "activities"
|
return "activities"
|
||||||
elif element_id.startswith("role_"):
|
elif element_uuid.startswith("role_"):
|
||||||
return "roles"
|
return "roles"
|
||||||
else:
|
else:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -28,8 +30,8 @@ async def check_element_type(element_id):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_singular_form_of_element(element_id):
|
async def get_singular_form_of_element(element_uuid):
|
||||||
element_type = await check_element_type(element_id)
|
element_type = await check_element_type(element_uuid)
|
||||||
|
|
||||||
if element_type == "activities":
|
if element_type == "activities":
|
||||||
return "activity"
|
return "activity"
|
||||||
|
|
@ -38,8 +40,8 @@ async def get_singular_form_of_element(element_id):
|
||||||
return singular_form_element
|
return singular_form_element
|
||||||
|
|
||||||
|
|
||||||
async def get_id_identifier_of_element(element_id):
|
async def get_id_identifier_of_element(element_uuid):
|
||||||
singular_form_element = await get_singular_form_of_element(element_id)
|
singular_form_element = await get_singular_form_of_element(element_uuid)
|
||||||
|
|
||||||
if singular_form_element == "ogranizations":
|
if singular_form_element == "ogranizations":
|
||||||
return "org_id"
|
return "org_id"
|
||||||
|
|
|
||||||
|
|
@ -559,7 +559,6 @@ async def rbac_check(
|
||||||
res = await authorization_verify_if_element_is_public(
|
res = await authorization_verify_if_element_is_public(
|
||||||
request, course_uuid, action, db_session
|
request, course_uuid, action, db_session
|
||||||
)
|
)
|
||||||
print("res", res)
|
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
res = await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
res = await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
|
import stat
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from sqlmodel import Session, select
|
from regex import R
|
||||||
|
from sqlalchemy import exists, union
|
||||||
|
from sqlmodel import Session, select, and_, or_
|
||||||
|
from src.db.usergroups import UserGroup
|
||||||
|
from src.db.usergroup_resources import UserGroupResource
|
||||||
|
from src.db.usergroup_user import UserGroupUser
|
||||||
from src.db.organizations import Organization
|
from src.db.organizations import Organization
|
||||||
from src.db.trails import TrailRead
|
from src.db.trails import TrailRead
|
||||||
from src.services.trail.trail import get_user_trail_with_orgid
|
from src.services.trail.trail import get_user_trail_with_orgid
|
||||||
|
|
@ -105,7 +111,6 @@ async def get_course_meta(
|
||||||
)
|
)
|
||||||
trail = TrailRead.from_orm(trail)
|
trail = TrailRead.from_orm(trail)
|
||||||
|
|
||||||
|
|
||||||
return FullCourseReadWithTrail(
|
return FullCourseReadWithTrail(
|
||||||
**course.dict(),
|
**course.dict(),
|
||||||
chapters=chapters,
|
chapters=chapters,
|
||||||
|
|
@ -326,26 +331,47 @@ async def get_courses_orgslug(
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
limit: int = 10,
|
limit: int = 10,
|
||||||
):
|
):
|
||||||
|
|
||||||
|
# Query for public courses
|
||||||
statement_public = (
|
statement_public = (
|
||||||
select(Course)
|
select(Course)
|
||||||
.join(Organization)
|
.join(Organization)
|
||||||
.where(Organization.slug == org_slug, Course.public == True)
|
.where(Organization.slug == org_slug, Course.public == True)
|
||||||
)
|
)
|
||||||
statement_all = (
|
|
||||||
select(Course).join(Organization).where(Organization.slug == org_slug)
|
# Query for courses where the current user is an author
|
||||||
|
statement_author = (
|
||||||
|
select(Course)
|
||||||
|
.join(Organization)
|
||||||
|
.join(ResourceAuthor, ResourceAuthor.user_id == current_user.id)
|
||||||
|
.where(
|
||||||
|
Organization.slug == org_slug,
|
||||||
|
ResourceAuthor.resource_uuid == Course.course_uuid,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if current_user.id == 0:
|
# Query for courses where the current user is in a user group that has access to the course
|
||||||
statement = statement_public
|
statement_usergroup = (
|
||||||
else:
|
select(Course)
|
||||||
# RBAC check
|
.join(Organization)
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
.join(
|
||||||
|
UserGroupResource, UserGroupResource.resource_uuid == Course.course_uuid
|
||||||
|
)
|
||||||
|
.join(
|
||||||
|
UserGroupUser, UserGroupUser.usergroup_id == UserGroupResource.usergroup_id
|
||||||
|
)
|
||||||
|
.where(Organization.slug == org_slug, UserGroupUser.user_id == current_user.id)
|
||||||
|
)
|
||||||
|
|
||||||
statement = statement_all
|
# Combine the results
|
||||||
|
statement_complete = union(
|
||||||
|
statement_public, statement_author, statement_usergroup
|
||||||
|
).subquery()
|
||||||
|
|
||||||
courses = db_session.exec(statement)
|
courses = db_session.execute(select([statement_complete])).all()
|
||||||
|
|
||||||
courses = [CourseRead(**course.dict(), authors=[]) for course in courses]
|
# TODO: I have no idea why this is necessary, but it is
|
||||||
|
courses = [CourseRead(**dict(course._mapping), authors=[]) for course in courses]
|
||||||
|
|
||||||
# for every course, get the authors
|
# for every course, get the authors
|
||||||
for course in courses:
|
for course in courses:
|
||||||
|
|
@ -366,6 +392,7 @@ async def get_courses_orgslug(
|
||||||
|
|
||||||
## 🔒 RBAC Utils ##
|
## 🔒 RBAC Utils ##
|
||||||
|
|
||||||
|
|
||||||
async def rbac_check(
|
async def rbac_check(
|
||||||
request: Request,
|
request: Request,
|
||||||
course_uuid: str,
|
course_uuid: str,
|
||||||
|
|
@ -380,9 +407,11 @@ async def rbac_check(
|
||||||
)
|
)
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
res = await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
res = (
|
||||||
|
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
||||||
request, current_user.id, action, course_uuid, db_session
|
request, current_user.id, action, course_uuid, db_session
|
||||||
)
|
)
|
||||||
|
)
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,12 @@ async def install_default_elements(db_session: Session):
|
||||||
action_update=True,
|
action_update=True,
|
||||||
action_delete=True,
|
action_delete=True,
|
||||||
),
|
),
|
||||||
|
usergroups=Permission(
|
||||||
|
action_create=True,
|
||||||
|
action_read=True,
|
||||||
|
action_update=True,
|
||||||
|
action_delete=True,
|
||||||
|
),
|
||||||
collections=Permission(
|
collections=Permission(
|
||||||
action_create=True,
|
action_create=True,
|
||||||
action_read=True,
|
action_read=True,
|
||||||
|
|
@ -183,6 +189,12 @@ async def install_default_elements(db_session: Session):
|
||||||
action_update=True,
|
action_update=True,
|
||||||
action_delete=True,
|
action_delete=True,
|
||||||
),
|
),
|
||||||
|
usergroups=Permission(
|
||||||
|
action_create=True,
|
||||||
|
action_read=True,
|
||||||
|
action_update=True,
|
||||||
|
action_delete=True,
|
||||||
|
),
|
||||||
collections=Permission(
|
collections=Permission(
|
||||||
action_create=True,
|
action_create=True,
|
||||||
action_read=True,
|
action_read=True,
|
||||||
|
|
@ -231,6 +243,12 @@ async def install_default_elements(db_session: Session):
|
||||||
action_update=False,
|
action_update=False,
|
||||||
action_delete=False,
|
action_delete=False,
|
||||||
),
|
),
|
||||||
|
usergroups=Permission(
|
||||||
|
action_create=False,
|
||||||
|
action_read=True,
|
||||||
|
action_update=False,
|
||||||
|
action_delete=False,
|
||||||
|
),
|
||||||
collections=Permission(
|
collections=Permission(
|
||||||
action_create=False,
|
action_create=False,
|
||||||
action_read=True,
|
action_read=True,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Literal
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from fastapi import HTTPException, Request
|
from fastapi import HTTPException, Request
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
from src.db.usergroup_ressources import UserGroupRessource
|
from src.security.rbac.rbac import (
|
||||||
|
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
||||||
|
authorization_verify_if_element_is_public,
|
||||||
|
authorization_verify_if_user_is_anon,
|
||||||
|
)
|
||||||
|
from src.db.usergroup_resources import UserGroupResource
|
||||||
from src.db.usergroup_user import UserGroupUser
|
from src.db.usergroup_user import UserGroupUser
|
||||||
from src.db.organizations import Organization
|
from src.db.organizations import Organization
|
||||||
from src.db.usergroups import UserGroup, UserGroupCreate, UserGroupRead, UserGroupUpdate
|
from src.db.usergroups import UserGroup, UserGroupCreate, UserGroupRead, UserGroupUpdate
|
||||||
|
|
@ -19,6 +25,15 @@ async def create_usergroup(
|
||||||
|
|
||||||
usergroup = UserGroup.from_orm(usergroup_create)
|
usergroup = UserGroup.from_orm(usergroup_create)
|
||||||
|
|
||||||
|
# RBAC check
|
||||||
|
await rbac_check(
|
||||||
|
request,
|
||||||
|
usergroup_uuid="usergroup_X",
|
||||||
|
current_user=current_user,
|
||||||
|
action="create",
|
||||||
|
db_session=db_session,
|
||||||
|
)
|
||||||
|
|
||||||
# Check if Organization exists
|
# Check if Organization exists
|
||||||
statement = select(Organization).where(Organization.id == usergroup_create.org_id)
|
statement = select(Organization).where(Organization.id == usergroup_create.org_id)
|
||||||
result = db_session.exec(statement)
|
result = db_session.exec(statement)
|
||||||
|
|
@ -60,11 +75,50 @@ async def read_usergroup_by_id(
|
||||||
detail="UserGroup not found",
|
detail="UserGroup not found",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# RBAC check
|
||||||
|
await rbac_check(
|
||||||
|
request,
|
||||||
|
usergroup_uuid=usergroup.usergroup_uuid,
|
||||||
|
current_user=current_user,
|
||||||
|
action="read",
|
||||||
|
db_session=db_session,
|
||||||
|
)
|
||||||
|
|
||||||
usergroup = UserGroupRead.from_orm(usergroup)
|
usergroup = UserGroupRead.from_orm(usergroup)
|
||||||
|
|
||||||
return usergroup
|
return usergroup
|
||||||
|
|
||||||
|
|
||||||
|
async def read_usergroups_by_org_id(
|
||||||
|
request: Request,
|
||||||
|
db_session: Session,
|
||||||
|
current_user: PublicUser | AnonymousUser,
|
||||||
|
org_id: int,
|
||||||
|
) -> list[UserGroupRead]:
|
||||||
|
|
||||||
|
statement = select(UserGroup).where(UserGroup.org_id == org_id)
|
||||||
|
usergroups = db_session.exec(statement).all()
|
||||||
|
|
||||||
|
if not usergroups:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=404,
|
||||||
|
detail="UserGroups not found",
|
||||||
|
)
|
||||||
|
|
||||||
|
# RBAC check
|
||||||
|
await rbac_check(
|
||||||
|
request,
|
||||||
|
usergroup_uuid="usergroup_X",
|
||||||
|
current_user=current_user,
|
||||||
|
action="read",
|
||||||
|
db_session=db_session,
|
||||||
|
)
|
||||||
|
|
||||||
|
usergroups = [UserGroupRead.from_orm(usergroup) for usergroup in usergroups]
|
||||||
|
|
||||||
|
return usergroups
|
||||||
|
|
||||||
|
|
||||||
async def update_usergroup_by_id(
|
async def update_usergroup_by_id(
|
||||||
request: Request,
|
request: Request,
|
||||||
db_session: Session,
|
db_session: Session,
|
||||||
|
|
@ -82,6 +136,15 @@ async def update_usergroup_by_id(
|
||||||
detail="UserGroup not found",
|
detail="UserGroup not found",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# RBAC check
|
||||||
|
await rbac_check(
|
||||||
|
request,
|
||||||
|
usergroup_uuid=usergroup.usergroup_uuid,
|
||||||
|
current_user=current_user,
|
||||||
|
action="update",
|
||||||
|
db_session=db_session,
|
||||||
|
)
|
||||||
|
|
||||||
usergroup.name = usergroup_update.name
|
usergroup.name = usergroup_update.name
|
||||||
usergroup.description = usergroup_update.description
|
usergroup.description = usergroup_update.description
|
||||||
usergroup.update_date = str(datetime.now())
|
usergroup.update_date = str(datetime.now())
|
||||||
|
|
@ -111,6 +174,15 @@ async def delete_usergroup_by_id(
|
||||||
detail="UserGroup not found",
|
detail="UserGroup not found",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# RBAC check
|
||||||
|
await rbac_check(
|
||||||
|
request,
|
||||||
|
usergroup_uuid=usergroup.usergroup_uuid,
|
||||||
|
current_user=current_user,
|
||||||
|
action="delete",
|
||||||
|
db_session=db_session,
|
||||||
|
)
|
||||||
|
|
||||||
db_session.delete(usergroup)
|
db_session.delete(usergroup)
|
||||||
db_session.commit()
|
db_session.commit()
|
||||||
|
|
||||||
|
|
@ -134,6 +206,15 @@ async def add_users_to_usergroup(
|
||||||
detail="UserGroup not found",
|
detail="UserGroup not found",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# RBAC check
|
||||||
|
await rbac_check(
|
||||||
|
request,
|
||||||
|
usergroup_uuid=usergroup.usergroup_uuid,
|
||||||
|
current_user=current_user,
|
||||||
|
action="create",
|
||||||
|
db_session=db_session,
|
||||||
|
)
|
||||||
|
|
||||||
user_ids_array = user_ids.split(",")
|
user_ids_array = user_ids.split(",")
|
||||||
|
|
||||||
for user_id in user_ids_array:
|
for user_id in user_ids_array:
|
||||||
|
|
@ -177,6 +258,16 @@ async def remove_users_from_usergroup(
|
||||||
detail="UserGroup not found",
|
detail="UserGroup not found",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# RBAC check
|
||||||
|
# RBAC check
|
||||||
|
await rbac_check(
|
||||||
|
request,
|
||||||
|
usergroup_uuid=usergroup.usergroup_uuid,
|
||||||
|
current_user=current_user,
|
||||||
|
action="delete",
|
||||||
|
db_session=db_session,
|
||||||
|
)
|
||||||
|
|
||||||
user_ids_array = user_ids.split(",")
|
user_ids_array = user_ids.split(",")
|
||||||
|
|
||||||
for user_id in user_ids_array:
|
for user_id in user_ids_array:
|
||||||
|
|
@ -192,12 +283,12 @@ async def remove_users_from_usergroup(
|
||||||
return "Users removed from UserGroup successfully"
|
return "Users removed from UserGroup successfully"
|
||||||
|
|
||||||
|
|
||||||
async def add_ressources_to_usergroup(
|
async def add_resources_to_usergroup(
|
||||||
request: Request,
|
request: Request,
|
||||||
db_session: Session,
|
db_session: Session,
|
||||||
current_user: PublicUser | AnonymousUser,
|
current_user: PublicUser | AnonymousUser,
|
||||||
usergroup_id: int,
|
usergroup_id: int,
|
||||||
ressources_uuids: str,
|
resources_uuids: str,
|
||||||
) -> str:
|
) -> str:
|
||||||
|
|
||||||
statement = select(UserGroup).where(UserGroup.id == usergroup_id)
|
statement = select(UserGroup).where(UserGroup.id == usergroup_id)
|
||||||
|
|
@ -209,14 +300,23 @@ async def add_ressources_to_usergroup(
|
||||||
detail="UserGroup not found",
|
detail="UserGroup not found",
|
||||||
)
|
)
|
||||||
|
|
||||||
ressources_uuids_array = ressources_uuids.split(",")
|
# RBAC check
|
||||||
|
await rbac_check(
|
||||||
|
request,
|
||||||
|
usergroup_uuid=usergroup.usergroup_uuid,
|
||||||
|
current_user=current_user,
|
||||||
|
action="create",
|
||||||
|
db_session=db_session,
|
||||||
|
)
|
||||||
|
|
||||||
for ressource_uuid in ressources_uuids_array:
|
resources_uuids_array = resources_uuids.split(",")
|
||||||
# TODO : Find a way to check if ressource exists
|
|
||||||
|
|
||||||
usergroup_obj = UserGroupRessource(
|
for resource_uuid in resources_uuids_array:
|
||||||
|
# TODO : Find a way to check if resource exists
|
||||||
|
|
||||||
|
usergroup_obj = UserGroupResource(
|
||||||
usergroup_id=usergroup_id,
|
usergroup_id=usergroup_id,
|
||||||
ressource_uuid=ressource_uuid,
|
resource_uuid=resource_uuid,
|
||||||
org_id=usergroup.org_id,
|
org_id=usergroup.org_id,
|
||||||
creation_date=str(datetime.now()),
|
creation_date=str(datetime.now()),
|
||||||
update_date=str(datetime.now()),
|
update_date=str(datetime.now()),
|
||||||
|
|
@ -226,15 +326,15 @@ async def add_ressources_to_usergroup(
|
||||||
db_session.commit()
|
db_session.commit()
|
||||||
db_session.refresh(usergroup_obj)
|
db_session.refresh(usergroup_obj)
|
||||||
|
|
||||||
return "Ressources added to UserGroup successfully"
|
return "Resources added to UserGroup successfully"
|
||||||
|
|
||||||
|
|
||||||
async def remove_ressources_from_usergroup(
|
async def remove_resources_from_usergroup(
|
||||||
request: Request,
|
request: Request,
|
||||||
db_session: Session,
|
db_session: Session,
|
||||||
current_user: PublicUser | AnonymousUser,
|
current_user: PublicUser | AnonymousUser,
|
||||||
usergroup_id: int,
|
usergroup_id: int,
|
||||||
ressources_uuids: str,
|
resources_uuids: str,
|
||||||
) -> str:
|
) -> str:
|
||||||
|
|
||||||
statement = select(UserGroup).where(UserGroup.id == usergroup_id)
|
statement = select(UserGroup).where(UserGroup.id == usergroup_id)
|
||||||
|
|
@ -246,20 +346,51 @@ async def remove_ressources_from_usergroup(
|
||||||
detail="UserGroup not found",
|
detail="UserGroup not found",
|
||||||
)
|
)
|
||||||
|
|
||||||
ressources_uuids_array = ressources_uuids.split(",")
|
# RBAC check
|
||||||
|
await rbac_check(
|
||||||
for ressource_uuid in ressources_uuids_array:
|
request,
|
||||||
statement = select(UserGroupRessource).where(
|
usergroup_uuid=usergroup.usergroup_uuid,
|
||||||
UserGroupRessource.ressource_uuid == ressource_uuid
|
current_user=current_user,
|
||||||
|
action="delete",
|
||||||
|
db_session=db_session,
|
||||||
)
|
)
|
||||||
usergroup_ressource = db_session.exec(statement).first()
|
|
||||||
|
|
||||||
if usergroup_ressource:
|
resources_uuids_array = resources_uuids.split(",")
|
||||||
db_session.delete(usergroup_ressource)
|
|
||||||
|
for resource_uuid in resources_uuids_array:
|
||||||
|
statement = select(UserGroupResource).where(
|
||||||
|
UserGroupResource.resource_uuid == resource_uuid
|
||||||
|
)
|
||||||
|
usergroup_resource = db_session.exec(statement).first()
|
||||||
|
|
||||||
|
if usergroup_resource:
|
||||||
|
db_session.delete(usergroup_resource)
|
||||||
db_session.commit()
|
db_session.commit()
|
||||||
else:
|
else:
|
||||||
logging.error(
|
logging.error(f"resource with uuid {resource_uuid} not found in UserGroup")
|
||||||
f"Ressource with uuid {ressource_uuid} not found in UserGroup"
|
|
||||||
|
return "Resources removed from UserGroup successfully"
|
||||||
|
|
||||||
|
|
||||||
|
## 🔒 RBAC Utils ##
|
||||||
|
|
||||||
|
|
||||||
|
async def rbac_check(
|
||||||
|
request: Request,
|
||||||
|
usergroup_uuid: str,
|
||||||
|
current_user: PublicUser | AnonymousUser,
|
||||||
|
action: Literal["create", "read", "update", "delete"],
|
||||||
|
db_session: Session,
|
||||||
|
):
|
||||||
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
|
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
||||||
|
request,
|
||||||
|
current_user.id,
|
||||||
|
action,
|
||||||
|
usergroup_uuid,
|
||||||
|
db_session,
|
||||||
)
|
)
|
||||||
|
|
||||||
return "Ressources removed from UserGroup successfully"
|
|
||||||
|
## 🔒 RBAC Utils ##
|
||||||
|
|
|
||||||
|
|
@ -453,7 +453,7 @@ async def authorize_user_action(
|
||||||
request: Request,
|
request: Request,
|
||||||
db_session: Session,
|
db_session: Session,
|
||||||
current_user: PublicUser | AnonymousUser,
|
current_user: PublicUser | AnonymousUser,
|
||||||
ressource_uuid: str,
|
resource_uuid: str,
|
||||||
action: Literal["create", "read", "update", "delete"],
|
action: Literal["create", "read", "update", "delete"],
|
||||||
):
|
):
|
||||||
# Get user
|
# Get user
|
||||||
|
|
@ -468,7 +468,7 @@ async def authorize_user_action(
|
||||||
|
|
||||||
# RBAC check
|
# RBAC check
|
||||||
authorized = await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
authorized = await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
||||||
request, current_user.id, action, ressource_uuid, db_session
|
request, current_user.id, action, resource_uuid, db_session
|
||||||
)
|
)
|
||||||
|
|
||||||
if authorized:
|
if authorized:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue