117 lines
3.2 KiB
Python
117 lines
3.2 KiB
Python
"""Workspace API.
|
|
|
|
Product language: workspace/space. Database compatibility: tenants.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pydantic import BaseModel, Field
|
|
from fastapi import APIRouter, Depends
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from ..core.database import get_db
|
|
from ..core.response import success_response
|
|
from ..dependencies import get_current_user, get_optional_current_user
|
|
from ..models import User
|
|
from ..services.workspace_service import (
|
|
accept_invitation,
|
|
create_invitation,
|
|
create_team_workspace,
|
|
leave_workspace,
|
|
list_user_workspaces,
|
|
switch_workspace,
|
|
)
|
|
|
|
router = APIRouter(prefix="/workspaces", tags=["workspaces"])
|
|
|
|
|
|
class TeamWorkspaceCreateRequest(BaseModel):
|
|
name: str = Field(min_length=1, max_length=120)
|
|
|
|
|
|
class WorkspaceSwitchRequest(BaseModel):
|
|
tenant_id: int
|
|
|
|
|
|
class WorkspaceInvitationCreateRequest(BaseModel):
|
|
phone_country_code: str = "+86"
|
|
phone_number: str
|
|
email: str | None = None
|
|
role: str = "BUILDER"
|
|
project_ids: list[int] = Field(default_factory=list)
|
|
|
|
|
|
class WorkspaceInvitationNewUserRequest(BaseModel):
|
|
username: str
|
|
password: str
|
|
name: str
|
|
email: str
|
|
|
|
|
|
class WorkspaceInvitationAcceptRequest(BaseModel):
|
|
token: str
|
|
user: WorkspaceInvitationNewUserRequest | None = None
|
|
|
|
|
|
@router.get("/me")
|
|
async def get_my_workspaces(
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return success_response(await list_user_workspaces(db, user=current_user))
|
|
|
|
|
|
@router.post("/teams")
|
|
async def create_team(
|
|
body: TeamWorkspaceCreateRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return success_response(await create_team_workspace(db, current_user=current_user, name=body.name))
|
|
|
|
|
|
@router.post("/switch")
|
|
async def switch_current_workspace(
|
|
body: WorkspaceSwitchRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return success_response(await switch_workspace(db, current_user=current_user, tenant_id=body.tenant_id))
|
|
|
|
|
|
@router.post("/invitations")
|
|
async def invite_member(
|
|
body: WorkspaceInvitationCreateRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return success_response(
|
|
await create_invitation(
|
|
db,
|
|
current_user=current_user,
|
|
email=body.email,
|
|
phone_country_code=body.phone_country_code,
|
|
phone_number=body.phone_number,
|
|
role=body.role,
|
|
project_ids=body.project_ids,
|
|
)
|
|
)
|
|
|
|
|
|
@router.post("/invitations/accept")
|
|
async def accept_member_invitation(
|
|
body: WorkspaceInvitationAcceptRequest,
|
|
current_user: User | None = Depends(get_optional_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return success_response(await accept_invitation(db, token=body.token, current_user=current_user, new_user=body.user))
|
|
|
|
|
|
@router.post("/{tenant_id}/leave")
|
|
async def leave_current_workspace(
|
|
tenant_id: int,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return success_response(await leave_workspace(db, current_user=current_user, tenant_id=tenant_id))
|