forked from sr2/cloud-api
minor: ruff formatter
All changes are either: - Correcting tabs - Adding/removing line breaks - Adding trailing commas
This commit is contained in:
parent
b2e5dd2ebb
commit
c689ac1e10
91 changed files with 1710 additions and 689 deletions
|
|
@ -1,3 +1,3 @@
|
|||
"""
|
||||
Configurations for the IAM module
|
||||
"""
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
"""
|
||||
Constants for the IAM module
|
||||
"""
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Exports:
|
|||
- group_model_body_dependency: group_model: Gets group model from db, if it exists. Uses group_id from request body.
|
||||
- perm_model_body_dependency: perm_model: Gets perm model from db, if it exists. Uses perm_id from request body.
|
||||
"""
|
||||
|
||||
from typing import Annotated, Optional
|
||||
|
||||
from fastapi import Depends, Query
|
||||
|
|
@ -17,17 +18,22 @@ from src.iam.exceptions import GroupNotFoundException, PermNotFoundException
|
|||
from src.iam.schemas import GroupIDMixin, PermIDMixin
|
||||
|
||||
|
||||
def get_group_model_query(db: db_dependency, group_id: Annotated[int, Query(gt=0)]) -> type[Group]:
|
||||
def get_group_model_query(
|
||||
db: db_dependency, group_id: Annotated[int, Query(gt=0)]
|
||||
) -> type[Group]:
|
||||
group_model = db.get(Group, group_id)
|
||||
if group_model is None:
|
||||
raise GroupNotFoundException(group_id)
|
||||
|
||||
return group_model
|
||||
|
||||
|
||||
group_model_query_dependency = Annotated[type[Group], Depends(get_group_model_query)]
|
||||
|
||||
|
||||
def get_group_model_body(db: db_dependency, request_model: Optional[GroupIDMixin] = None) -> type[Group]:
|
||||
def get_group_model_body(
|
||||
db: db_dependency, request_model: Optional[GroupIDMixin] = None
|
||||
) -> type[Group]:
|
||||
group_id = getattr(request_model, "group_id", None)
|
||||
if group_id is None:
|
||||
raise GroupNotFoundException()
|
||||
|
|
@ -37,10 +43,13 @@ def get_group_model_body(db: db_dependency, request_model: Optional[GroupIDMixin
|
|||
|
||||
return group_model
|
||||
|
||||
|
||||
group_model_body_dependency = Annotated[type[Group], Depends(get_group_model_body)]
|
||||
|
||||
|
||||
def get_perm_model_body(db: db_dependency, request_model: Optional[PermIDMixin] = None) -> type[Permission]:
|
||||
def get_perm_model_body(
|
||||
db: db_dependency, request_model: Optional[PermIDMixin] = None
|
||||
) -> type[Permission]:
|
||||
perm_id = getattr(request_model, "permission_id", None)
|
||||
if perm_id is None:
|
||||
raise PermNotFoundException
|
||||
|
|
@ -50,4 +59,5 @@ def get_perm_model_body(db: db_dependency, request_model: Optional[PermIDMixin]
|
|||
|
||||
return perm_model
|
||||
|
||||
|
||||
perm_model_body_dependency = Annotated[type[Permission], Depends(get_perm_model_body)]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ Exceptions:
|
|||
- GroupNotFoundException: Takes an optional group_id int
|
||||
- PermNotFoundException: Takes an optional perm_id int
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
|
|
@ -12,7 +13,11 @@ from fastapi import HTTPException, status
|
|||
|
||||
class GroupNotFoundException(HTTPException):
|
||||
def __init__(self, group_id: Optional[int] = None) -> None:
|
||||
detail = "Group not found" if group_id is None else f"User with ID '{group_id}' was not found."
|
||||
detail = (
|
||||
"Group not found"
|
||||
if group_id is None
|
||||
else f"User with ID '{group_id}' was not found."
|
||||
)
|
||||
super().__init__(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=detail,
|
||||
|
|
@ -21,7 +26,11 @@ class GroupNotFoundException(HTTPException):
|
|||
|
||||
class PermNotFoundException(HTTPException):
|
||||
def __init__(self, perm_id: Optional[int] = None) -> None:
|
||||
detail = "Permission not found" if perm_id is None else f"User with ID '{perm_id}' was not found."
|
||||
detail = (
|
||||
"Permission not found"
|
||||
if perm_id is None
|
||||
else f"User with ID '{perm_id}' was not found."
|
||||
)
|
||||
super().__init__(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=detail,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ Models:
|
|||
- UserGroups:
|
||||
- org_id[FK][PK], user_id[FK][PK], group_id[FK][PK]
|
||||
"""
|
||||
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
|
|
@ -32,7 +33,9 @@ class Permission(Base):
|
|||
|
||||
service_id = Column(Integer, ForeignKey("service.id", ondelete="CASCADE"))
|
||||
|
||||
UniqueConstraint("service_id", "resource", "action", name="uniq_permission_resource_and_action")
|
||||
UniqueConstraint(
|
||||
"service_id", "resource", "action", name="uniq_permission_resource_and_action"
|
||||
)
|
||||
|
||||
service_rel = relationship("Service", foreign_keys=[service_id])
|
||||
|
||||
|
|
@ -41,13 +44,10 @@ class Permission(Base):
|
|||
return self.service_rel.name
|
||||
|
||||
group_rel = relationship(
|
||||
"Group",
|
||||
secondary="group_permissions",
|
||||
back_populates="permission_rel"
|
||||
"Group", secondary="group_permissions", back_populates="permission_rel"
|
||||
)
|
||||
|
||||
|
||||
|
||||
class Group(Base):
|
||||
__tablename__ = "group"
|
||||
id = Column(Integer, primary_key=True)
|
||||
|
|
@ -55,28 +55,30 @@ class Group(Base):
|
|||
|
||||
org_id = Column(Integer, ForeignKey("organisation.id", ondelete="CASCADE"))
|
||||
|
||||
user_rel = relationship(
|
||||
"User",
|
||||
secondary="user_groups",
|
||||
back_populates="group_rel"
|
||||
)
|
||||
user_rel = relationship("User", secondary="user_groups", back_populates="group_rel")
|
||||
|
||||
org_rel = relationship("Organisation", back_populates="group_rel")
|
||||
|
||||
permission_rel = relationship(
|
||||
"Permission",
|
||||
secondary="group_permissions",
|
||||
back_populates="group_rel"
|
||||
"Permission", secondary="group_permissions", back_populates="group_rel"
|
||||
)
|
||||
|
||||
|
||||
class GroupPermissions(Base):
|
||||
__tablename__ = "group_permissions"
|
||||
group_id = Column(Integer, ForeignKey("group.id", ondelete="CASCADE"), primary_key=True)
|
||||
permission_id = Column(Integer, ForeignKey("permission.id", ondelete="CASCADE"), primary_key=True)
|
||||
group_id = Column(
|
||||
Integer, ForeignKey("group.id", ondelete="CASCADE"), primary_key=True
|
||||
)
|
||||
permission_id = Column(
|
||||
Integer, ForeignKey("permission.id", ondelete="CASCADE"), primary_key=True
|
||||
)
|
||||
|
||||
|
||||
class UserGroups(Base):
|
||||
__tablename__ = "user_groups"
|
||||
user_id = Column(Integer, ForeignKey("user.id", ondelete="CASCADE"), primary_key=True)
|
||||
group_id = Column(Integer, ForeignKey("group.id", ondelete="CASCADE"), primary_key=True)
|
||||
user_id = Column(
|
||||
Integer, ForeignKey("user.id", ondelete="CASCADE"), primary_key=True
|
||||
)
|
||||
group_id = Column(
|
||||
Integer, ForeignKey("group.id", ondelete="CASCADE"), primary_key=True
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ Endpoints:
|
|||
- [DELETE](/iam/permission): [super admin]: Removes a permission
|
||||
- [GET](/iam/permissions/search): [root user]: Returns a list of permissions matching a filter(service|resource|action)
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, status
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from psycopg import errors
|
||||
|
|
@ -25,21 +26,49 @@ from src.database import db_dependency
|
|||
from src.schemas import ResourceName
|
||||
from src.auth.exceptions import UnauthorizedException
|
||||
from src.auth.service import claims_dependency
|
||||
from src.auth.dependencies import org_model_root_claim_query_dependency, org_model_root_claim_body_dependency, \
|
||||
super_admin_dependency
|
||||
from src.auth.dependencies import (
|
||||
org_model_root_claim_query_dependency,
|
||||
org_model_root_claim_body_dependency,
|
||||
super_admin_dependency,
|
||||
)
|
||||
from src.user.models import User
|
||||
from src.user.dependencies import user_model_body_dependency
|
||||
from src.organisation.models import Organisation as Org
|
||||
from src.service.models import Service
|
||||
|
||||
from src.iam.service import service_key_dependency
|
||||
from src.iam.models import Permission as Perm, GroupPermissions as GPerms, Group, UserGroups
|
||||
from src.iam.dependencies import group_model_query_dependency, group_model_body_dependency, perm_model_body_dependency
|
||||
from src.iam.schemas import IAMGetGroupPermissionsResponse, IAMGetGroupUsersResponse, IAMPostGroupRequest, \
|
||||
GroupSchema, IAMPostGroupResponse, IAMPutGroupPermissionRequest, IAMPutGroupPermissionResponse, \
|
||||
IAMPutGroupUserRequest, IAMPutGroupUserResponse, IAMDeleteGroupPermissionRequest, IAMDeleteGroupPermissionResponse, \
|
||||
IAMDeleteGroupUserRequest, IAMDeleteGroupUserResponse, IAMGetPermissionsResponse, IAMPostPermissionRequest, \
|
||||
IAMPostPermissionResponse, IAMDeletePermissionRequest, IAMGetPermissionsSearchRequest, IAMGetPermissionsSearchResponse
|
||||
from src.iam.models import (
|
||||
Permission as Perm,
|
||||
GroupPermissions as GPerms,
|
||||
Group,
|
||||
UserGroups,
|
||||
)
|
||||
from src.iam.dependencies import (
|
||||
group_model_query_dependency,
|
||||
group_model_body_dependency,
|
||||
perm_model_body_dependency,
|
||||
)
|
||||
from src.iam.schemas import (
|
||||
IAMGetGroupPermissionsResponse,
|
||||
IAMGetGroupUsersResponse,
|
||||
IAMPostGroupRequest,
|
||||
GroupSchema,
|
||||
IAMPostGroupResponse,
|
||||
IAMPutGroupPermissionRequest,
|
||||
IAMPutGroupPermissionResponse,
|
||||
IAMPutGroupUserRequest,
|
||||
IAMPutGroupUserResponse,
|
||||
IAMDeleteGroupPermissionRequest,
|
||||
IAMDeleteGroupPermissionResponse,
|
||||
IAMDeleteGroupUserRequest,
|
||||
IAMDeleteGroupUserResponse,
|
||||
IAMGetPermissionsResponse,
|
||||
IAMPostPermissionRequest,
|
||||
IAMPostPermissionResponse,
|
||||
IAMDeletePermissionRequest,
|
||||
IAMGetPermissionsSearchRequest,
|
||||
IAMGetPermissionsSearchResponse,
|
||||
)
|
||||
|
||||
router = APIRouter(
|
||||
tags=["IAM"],
|
||||
|
|
@ -48,26 +77,32 @@ router = APIRouter(
|
|||
|
||||
|
||||
@router.post("/can_act_on_resource")
|
||||
async def can_act_on_resource(valid_key: service_key_dependency, db: db_dependency, user_claims: claims_dependency,
|
||||
rn: ResourceName, action: str) -> bool:
|
||||
async def can_act_on_resource(
|
||||
valid_key: service_key_dependency,
|
||||
db: db_dependency,
|
||||
user_claims: claims_dependency,
|
||||
rn: ResourceName,
|
||||
action: str,
|
||||
) -> bool:
|
||||
try:
|
||||
user_id = user_claims["db_id"]
|
||||
rn_org = rn.organisation
|
||||
rn_service = rn.service
|
||||
rn_resource = rn.resource
|
||||
|
||||
result = (db.query(Perm)
|
||||
.join(Service, Service.id == Perm.service_id)
|
||||
.join(GPerms, GPerms.permission_id == Perm.id)
|
||||
.join(Group, Group.id == GPerms.group_id)
|
||||
.join(Org, Org.id == Group.org_id)
|
||||
.join(UserGroups, UserGroups.group_id == Group.id)
|
||||
.join(User, User.id == UserGroups.user_id)
|
||||
.filter(User.id == user_id)
|
||||
.filter(Org.name == rn_org)
|
||||
.filter(Service.name == rn_service)
|
||||
.filter(Perm.resource == rn_resource)
|
||||
.filter(Perm.action == action)
|
||||
result = (
|
||||
db.query(Perm)
|
||||
.join(Service, Service.id == Perm.service_id)
|
||||
.join(GPerms, GPerms.permission_id == Perm.id)
|
||||
.join(Group, Group.id == GPerms.group_id)
|
||||
.join(Org, Org.id == Group.org_id)
|
||||
.join(UserGroups, UserGroups.group_id == Group.id)
|
||||
.join(User, User.id == UserGroups.user_id)
|
||||
.filter(User.id == user_id)
|
||||
.filter(Org.name == rn_org)
|
||||
.filter(Service.name == rn_service)
|
||||
.filter(Perm.resource == rn_resource)
|
||||
.filter(Perm.action == action)
|
||||
).first()
|
||||
|
||||
if result:
|
||||
|
|
@ -79,21 +114,31 @@ async def can_act_on_resource(valid_key: service_key_dependency, db: db_dependen
|
|||
|
||||
|
||||
@router.get("/group/permissions", response_model=IAMGetGroupPermissionsResponse)
|
||||
async def get_group_permissions(group_model: group_model_query_dependency, org_model: org_model_root_claim_query_dependency):
|
||||
async def get_group_permissions(
|
||||
group_model: group_model_query_dependency,
|
||||
org_model: org_model_root_claim_query_dependency,
|
||||
):
|
||||
if group_model.org_id != org_model.id:
|
||||
raise UnauthorizedException("Group does not belong to this organization")
|
||||
return {"permissions": group_model.permission_rel}
|
||||
|
||||
|
||||
@router.get("/group/users", response_model=IAMGetGroupUsersResponse)
|
||||
async def get_group_users(group_model: group_model_query_dependency, org_model: org_model_root_claim_query_dependency):
|
||||
async def get_group_users(
|
||||
group_model: group_model_query_dependency,
|
||||
org_model: org_model_root_claim_query_dependency,
|
||||
):
|
||||
if group_model.org_id != org_model.id:
|
||||
raise UnauthorizedException("Group does not belong to this organization")
|
||||
return {"users": group_model.user_rel}
|
||||
|
||||
|
||||
@router.post("/group", response_model=IAMPostGroupResponse)
|
||||
async def create_group(db: db_dependency, org_model: org_model_root_claim_body_dependency, request_model: IAMPostGroupRequest):
|
||||
async def create_group(
|
||||
db: db_dependency,
|
||||
org_model: org_model_root_claim_body_dependency,
|
||||
request_model: IAMPostGroupRequest,
|
||||
):
|
||||
group_model = Group(name=request_model.name, org_id=org_model.id)
|
||||
|
||||
db.add(group_model)
|
||||
|
|
@ -101,9 +146,9 @@ async def create_group(db: db_dependency, org_model: org_model_root_claim_body_d
|
|||
db.flush()
|
||||
except IntegrityError as e:
|
||||
if (
|
||||
getattr(e.orig, "pgcode", None) == "23505" # Postgres unique violation
|
||||
or "UNIQUE constraint failed" in str(e.orig) # SQLite unique violation
|
||||
):
|
||||
getattr(e.orig, "pgcode", None) == "23505" # Postgres unique violation
|
||||
or "UNIQUE constraint failed" in str(e.orig) # SQLite unique violation
|
||||
):
|
||||
raise ConflictException("Group with this name already exists")
|
||||
response = GroupSchema(**group_model.__dict__)
|
||||
db.commit()
|
||||
|
|
@ -111,7 +156,13 @@ async def create_group(db: db_dependency, org_model: org_model_root_claim_body_d
|
|||
|
||||
|
||||
@router.put("/group/permission", response_model=IAMPutGroupPermissionResponse)
|
||||
async def add_group_permission(db: db_dependency, group_model: group_model_body_dependency, perm_model: perm_model_body_dependency, org_model: org_model_root_claim_body_dependency, request_model: IAMPutGroupPermissionRequest):
|
||||
async def add_group_permission(
|
||||
db: db_dependency,
|
||||
group_model: group_model_body_dependency,
|
||||
perm_model: perm_model_body_dependency,
|
||||
org_model: org_model_root_claim_body_dependency,
|
||||
request_model: IAMPutGroupPermissionRequest,
|
||||
):
|
||||
if group_model.org_id != org_model.id:
|
||||
raise UnauthorizedException("Group does not belong to this organization")
|
||||
|
||||
|
|
@ -121,13 +172,22 @@ async def add_group_permission(db: db_dependency, group_model: group_model_body_
|
|||
group_model.permission_rel.append(perm_model)
|
||||
|
||||
db.flush()
|
||||
response = IAMPutGroupPermissionResponse(group=GroupSchema(**group_model.__dict__), permissions=group_model.permission_rel)
|
||||
response = IAMPutGroupPermissionResponse(
|
||||
group=GroupSchema(**group_model.__dict__),
|
||||
permissions=group_model.permission_rel,
|
||||
)
|
||||
db.commit()
|
||||
return response
|
||||
|
||||
|
||||
@router.put("/group/user", response_model=IAMPutGroupUserResponse)
|
||||
async def add_group_user(db: db_dependency, group_model: group_model_body_dependency, user_model: user_model_body_dependency, org_model: org_model_root_claim_body_dependency, request_model: IAMPutGroupUserRequest):
|
||||
async def add_group_user(
|
||||
db: db_dependency,
|
||||
group_model: group_model_body_dependency,
|
||||
user_model: user_model_body_dependency,
|
||||
org_model: org_model_root_claim_body_dependency,
|
||||
request_model: IAMPutGroupUserRequest,
|
||||
):
|
||||
if group_model.org_id != org_model.id:
|
||||
raise UnauthorizedException("Group does not belong to this organization")
|
||||
|
||||
|
|
@ -136,46 +196,70 @@ async def add_group_user(db: db_dependency, group_model: group_model_body_depend
|
|||
|
||||
group_model.user_rel.append(user_model)
|
||||
db.flush()
|
||||
response = IAMPutGroupUserResponse(group=GroupSchema(**group_model.__dict__), users=group_model.user_rel)
|
||||
response = IAMPutGroupUserResponse(
|
||||
group=GroupSchema(**group_model.__dict__), users=group_model.user_rel
|
||||
)
|
||||
db.commit()
|
||||
return response
|
||||
|
||||
|
||||
@router.delete("/group/permissions")
|
||||
async def remove_group_permissions(db: db_dependency, group_model: group_model_body_dependency, perm_model: perm_model_body_dependency, org_model: org_model_root_claim_body_dependency, request_model: IAMDeleteGroupPermissionRequest):
|
||||
async def remove_group_permissions(
|
||||
db: db_dependency,
|
||||
group_model: group_model_body_dependency,
|
||||
perm_model: perm_model_body_dependency,
|
||||
org_model: org_model_root_claim_body_dependency,
|
||||
request_model: IAMDeleteGroupPermissionRequest,
|
||||
):
|
||||
if group_model.org_id != org_model.id:
|
||||
raise UnauthorizedException("Group does not belong to this organization")
|
||||
|
||||
group_model.permission_rel.remove(perm_model)
|
||||
db.flush()
|
||||
response = IAMDeleteGroupPermissionResponse(group=GroupSchema(**group_model.__dict__),
|
||||
permissions=group_model.permission_rel)
|
||||
response = IAMDeleteGroupPermissionResponse(
|
||||
group=GroupSchema(**group_model.__dict__),
|
||||
permissions=group_model.permission_rel,
|
||||
)
|
||||
db.commit()
|
||||
return response
|
||||
|
||||
|
||||
@router.delete("/group/user")
|
||||
async def remove_group_user(db: db_dependency, group_model: group_model_body_dependency, user_model: user_model_body_dependency, org_model: org_model_root_claim_body_dependency, request_model: IAMDeleteGroupUserRequest):
|
||||
async def remove_group_user(
|
||||
db: db_dependency,
|
||||
group_model: group_model_body_dependency,
|
||||
user_model: user_model_body_dependency,
|
||||
org_model: org_model_root_claim_body_dependency,
|
||||
request_model: IAMDeleteGroupUserRequest,
|
||||
):
|
||||
if group_model.org_id != org_model.id:
|
||||
raise UnauthorizedException("Group does not belong to this organization")
|
||||
|
||||
user_model.group_rel.remove(group_model)
|
||||
db.flush()
|
||||
response = IAMDeleteGroupUserResponse(group=GroupSchema(**group_model.__dict__), users=group_model.user_rel)
|
||||
response = IAMDeleteGroupUserResponse(
|
||||
group=GroupSchema(**group_model.__dict__), users=group_model.user_rel
|
||||
)
|
||||
db.commit()
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@router.get("/permissions", response_model=IAMGetPermissionsResponse)
|
||||
async def get_permissions(db: db_dependency, org_model: org_model_root_claim_query_dependency):
|
||||
async def get_permissions(
|
||||
db: db_dependency, org_model: org_model_root_claim_query_dependency
|
||||
):
|
||||
permission_models = db.query(Perm).all()
|
||||
|
||||
return {"permissions": permission_models}
|
||||
|
||||
|
||||
@router.post("/permission", response_model=IAMPostPermissionResponse)
|
||||
async def create_new_permission(db: db_dependency, su: super_admin_dependency, request_model: IAMPostPermissionRequest):
|
||||
async def create_new_permission(
|
||||
db: db_dependency,
|
||||
su: super_admin_dependency,
|
||||
request_model: IAMPostPermissionRequest,
|
||||
):
|
||||
service_model = db.get(Service, request_model.service_id)
|
||||
if service_model is None:
|
||||
raise ServiceNotFoundException(service_id=request_model.service_id)
|
||||
|
|
@ -186,29 +270,46 @@ async def create_new_permission(db: db_dependency, su: super_admin_dependency, r
|
|||
if isinstance(e.orig, errors.UniqueViolation):
|
||||
raise ConflictException(message="Permission already exists")
|
||||
db.flush()
|
||||
response = {"service_name": perm_model.service_name, "resource": perm_model.resource, "action": perm_model.action}
|
||||
response = {
|
||||
"service_name": perm_model.service_name,
|
||||
"resource": perm_model.resource,
|
||||
"action": perm_model.action,
|
||||
}
|
||||
db.commit()
|
||||
return {"permission": response}
|
||||
|
||||
|
||||
@router.delete("/permission", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def delete_permission(db: db_dependency, su: super_admin_dependency, perm_model: perm_model_body_dependency, request_model: IAMDeletePermissionRequest):
|
||||
async def delete_permission(
|
||||
db: db_dependency,
|
||||
su: super_admin_dependency,
|
||||
perm_model: perm_model_body_dependency,
|
||||
request_model: IAMDeletePermissionRequest,
|
||||
):
|
||||
db.delete(perm_model)
|
||||
db.commit()
|
||||
|
||||
|
||||
@router.post("/permissions/search", response_model=IAMGetPermissionsSearchResponse)
|
||||
async def post_permissions(db: db_dependency, org_model: org_model_root_claim_body_dependency, request_model: IAMGetPermissionsSearchRequest):
|
||||
async def post_permissions(
|
||||
db: db_dependency,
|
||||
org_model: org_model_root_claim_body_dependency,
|
||||
request_model: IAMGetPermissionsSearchRequest,
|
||||
):
|
||||
permission_query = db.query(Perm)
|
||||
|
||||
if request_model.service_id is not None:
|
||||
permission_query = permission_query.filter(Perm.service_id == request_model.service_id)
|
||||
permission_query = permission_query.filter(
|
||||
Perm.service_id == request_model.service_id
|
||||
)
|
||||
|
||||
if request_model.resource is not None:
|
||||
permission_query = permission_query.filter(Perm.resource == request_model.resource)
|
||||
permission_query = permission_query.filter(
|
||||
Perm.resource == request_model.resource
|
||||
)
|
||||
|
||||
if request_model.action is not None:
|
||||
permission_query = permission_query.filter(Perm.action == request_model. action)
|
||||
permission_query = permission_query.filter(Perm.action == request_model.action)
|
||||
|
||||
permission_models = permission_query.all()
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Models follow the nomenclature of:
|
|||
- Mixins: "<Attribute>Mixin"
|
||||
- Models: "<Module><Method><Resource><Opt:Resource><Direction>" ie "IAMGetGroupPermissionsResponse"
|
||||
"""
|
||||
|
||||
from typing import Optional, Annotated
|
||||
|
||||
from pydantic import EmailStr, ConfigDict, Field
|
||||
|
|
@ -24,6 +25,7 @@ class UserSchema(CustomBaseModel):
|
|||
last_name: str
|
||||
email: EmailStr
|
||||
|
||||
|
||||
class PermissionSchema(CustomBaseModel):
|
||||
model_config = ConfigDict(from_attributes=True, extra="ignore")
|
||||
|
||||
|
|
@ -31,73 +33,94 @@ class PermissionSchema(CustomBaseModel):
|
|||
resource: str
|
||||
action: str
|
||||
|
||||
|
||||
class GroupSchema(CustomBaseModel):
|
||||
id: int
|
||||
name: str
|
||||
|
||||
|
||||
class GroupIDMixin(CustomBaseModel):
|
||||
group_id: int = Field(gt=0)
|
||||
|
||||
|
||||
class PermIDMixin(CustomBaseModel):
|
||||
permission_id: int = Field(gt=0)
|
||||
|
||||
|
||||
class IAMGetGroupPermissionsResponse(CustomBaseModel):
|
||||
permissions: list[PermissionSchema]
|
||||
|
||||
|
||||
class IAMGetGroupUsersResponse(CustomBaseModel):
|
||||
users : list[UserSchema]
|
||||
users: list[UserSchema]
|
||||
|
||||
|
||||
class IAMPostGroupRequest(OrgIDMixin):
|
||||
name: str = Field(min_length=3)
|
||||
|
||||
|
||||
class IAMPostGroupResponse(CustomBaseModel):
|
||||
group: GroupSchema
|
||||
|
||||
|
||||
class IAMPutGroupPermissionRequest(GroupIDMixin, PermIDMixin, OrgIDMixin):
|
||||
pass
|
||||
|
||||
|
||||
class IAMPutGroupPermissionResponse(CustomBaseModel):
|
||||
group: GroupSchema
|
||||
permissions: list[PermissionSchema]
|
||||
|
||||
|
||||
class IAMPutGroupUserRequest(GroupIDMixin, UserIDMixin, OrgIDMixin):
|
||||
pass
|
||||
|
||||
|
||||
class IAMPutGroupUserResponse(CustomBaseModel):
|
||||
group: GroupSchema
|
||||
users: list[UserSchema]
|
||||
|
||||
|
||||
class IAMDeleteGroupPermissionRequest(GroupIDMixin, PermIDMixin):
|
||||
pass
|
||||
|
||||
|
||||
class IAMDeleteGroupPermissionResponse(CustomBaseModel):
|
||||
group: GroupSchema
|
||||
permissions: list[PermissionSchema]
|
||||
|
||||
|
||||
class IAMDeleteGroupUserRequest(GroupIDMixin, UserIDMixin):
|
||||
pass
|
||||
|
||||
|
||||
class IAMDeleteGroupUserResponse(CustomBaseModel):
|
||||
group: GroupSchema
|
||||
users: list[UserSchema]
|
||||
|
||||
|
||||
class IAMGetPermissionsResponse(CustomBaseModel):
|
||||
permissions: list[PermissionSchema]
|
||||
|
||||
|
||||
class IAMPostPermissionRequest(ServiceIDMixin):
|
||||
resource: str
|
||||
action: str
|
||||
|
||||
|
||||
class IAMPostPermissionResponse(CustomBaseModel):
|
||||
permission: PermissionSchema
|
||||
|
||||
|
||||
class IAMDeletePermissionRequest(PermIDMixin):
|
||||
pass
|
||||
|
||||
|
||||
class IAMGetPermissionsSearchRequest(OrgIDMixin):
|
||||
service_id: Annotated[int | None, Field(gt=0)] = None
|
||||
resource: Optional[str] = None
|
||||
action: Optional[str] = None
|
||||
|
||||
|
||||
class IAMGetPermissionsSearchResponse(CustomBaseModel):
|
||||
permissions: list[PermissionSchema]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Business logic reusable functions related to IAM
|
|||
Exports:
|
||||
- service_key_dependency: bool: verifies request headers contain the correct api key for the service
|
||||
"""
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from src.service.models import Service
|
||||
|
|
@ -19,10 +20,16 @@ def valid_service_key(db: db_dependency, request: Request, rn: ResourceName) ->
|
|||
if not api_key:
|
||||
raise UnauthorizedException("Missing API key")
|
||||
service = rn.service
|
||||
result = db.query(Service).filter(Service.name == service).filter(Service.api_key == api_key).first()
|
||||
result = (
|
||||
db.query(Service)
|
||||
.filter(Service.name == service)
|
||||
.filter(Service.api_key == api_key)
|
||||
.first()
|
||||
)
|
||||
if result is None:
|
||||
raise UnauthorizedException("Invalid API key")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
service_key_dependency = Annotated[bool, Depends(valid_service_key)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue