diff --git a/api/asset_manager/src/main.py b/api/asset_manager/src/main.py index 4000414b..205bcea4 100644 --- a/api/asset_manager/src/main.py +++ b/api/asset_manager/src/main.py @@ -10,6 +10,7 @@ from modules.assets.router import router as asset_router from modules.auth.router import router as auth_router from modules.users.router import router as users_router from modules.organizations.router import router as organizations_router +from modules.invitations.router import router as invitations_router from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware from fastapi.middleware.trustedhost import TrustedHostMiddleware @@ -53,3 +54,4 @@ app.include_router(auth_router) app.include_router(users_router) app.include_router(organizations_router) app.include_router(asset_router) +app.include_router(invitations_router) diff --git a/api/asset_manager/src/modules/invitations/models.py b/api/asset_manager/src/modules/invitations/models.py new file mode 100644 index 00000000..9e276916 --- /dev/null +++ b/api/asset_manager/src/modules/invitations/models.py @@ -0,0 +1,15 @@ + +import uuid +from tortoise import Model, fields + +from mixins import CMDMixin +from modules.users.models import User + + +class Invite(Model, CMDMixin): + id: uuid.UUID = fields.UUIDField(primary_key=True) + receiver: str = fields.CharField(max_length=128) + sender: str = fields.UUIDField() + message: str | None = fields.TextField(null=True) + accepted: bool = fields.BooleanField() + disabled: bool = fields.BooleanField(default=False) diff --git a/api/asset_manager/src/modules/invitations/router.py b/api/asset_manager/src/modules/invitations/router.py new file mode 100644 index 00000000..b4c540bb --- /dev/null +++ b/api/asset_manager/src/modules/invitations/router.py @@ -0,0 +1,66 @@ +from typing import Annotated +import uuid +from fastapi import APIRouter, Depends, HTTPException + +from modules.invitations.models import Invite +from modules.users.models import User +from modules.users.utils import get_current_active_user + +from tortoise.expressions import Q + + +router = APIRouter(prefix="/api/v1/Users", tags=["User"]) + + +@router.get("/") +async def get_all_invitations(user: Annotated[User, Depends(get_current_active_user)]): + pass + + +@router.get("/accept/{invitation_id}") +async def accept_invitation( + user: Annotated[User, Depends(get_current_active_user)], invitation_id: uuid.UUID +): + invite: Invite | None = await Invite.get_or_none( + Q(id=invitation_id) & (Q(receiver=user.username) | Q(receiver=user.email)) + ) + invite.accepted = True + invite.save() + return invite + + + +@router.get("/reject/{invitation_id}") +async def reject_invitation( + user: Annotated[User, Depends(get_current_active_user)], invitation_id: uuid.UUID +) -> Invite: + invite: Invite | None = await Invite.get_or_none( + Q(id=invitation_id) & (Q(receiver=user.username) | Q(receiver=user.email)) + ) + invite.accepted = False + invite.save() + return invite + + +@router.get("/send") +async def accept_invitation( + user: Annotated[User, Depends(get_current_active_user)], +): + pass + + +@router.get("/cancel/{invitation_id}", status_code=204) +async def accept_invitation( + user: Annotated[User, Depends(get_current_active_user)], invitation_id: uuid.UUID +) -> None: + invite: Invite | None = await Invite.get_or_none( + Q(id=invitation_id) & Q(sender=user.id) + ) + + if not invite: + raise HTTPException( + status_code=403, + detail="The invitation doesn't exist or you don't have access to it.", + ) + + invite.delete() diff --git a/api/asset_manager/src/modules/invitations/schemas.py b/api/asset_manager/src/modules/invitations/schemas.py new file mode 100644 index 00000000..e69de29b