feat: add personal workspace creation for legacy users and invitation landing page

This commit is contained in:
Anurag Jangid 2026-10-23 02:09:59 +05:30
parent bf5cd44dc1
commit e905184c7f
12 changed files with 240 additions and 21 deletions

View file

@ -28,6 +28,7 @@ from app.services.tenant_service import (
list_members,
list_workspaces,
update_member_role,
ensure_personal_workspace,
)
router = APIRouter(prefix="/tenants", tags=["tenants"])
@ -48,6 +49,7 @@ def workspace_response(row) -> WorkspaceResponse:
@router.get("/workspaces", response_model=list[WorkspaceResponse])
def get_workspaces(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
ensure_personal_workspace(db, current_user)
return [workspace_response(row) for row in list_workspaces(db, current_user.id)]

View file

@ -53,6 +53,37 @@ def create_workspace(db: Session, owner: User, data) -> Workspace:
return workspace
def ensure_personal_workspace(db: Session, owner: User) -> Workspace:
existing = (
db.query(Workspace)
.join(WorkspaceMembership, WorkspaceMembership.workspace_id == Workspace.id)
.filter(WorkspaceMembership.user_id == owner.id)
.order_by(Workspace.created_at.asc())
.first()
)
if existing is not None:
return existing
label = (owner.full_name or owner.username or "Personal").strip()
org_slug = f"{slugify(owner.username)}-personal"
if db.query(Organization).filter_by(slug=org_slug).first():
org_slug = f"{org_slug}-{secrets.token_hex(3)}"
organization = Organization(name=f"{label}'s organization", slug=org_slug, owner_id=owner.id)
db.add(organization)
db.flush()
workspace = Workspace(
organization_id=organization.id,
name="Personal workspace",
slug="personal-workspace",
)
db.add(workspace)
db.flush()
db.add(WorkspaceMembership(workspace_id=workspace.id, user_id=owner.id, role="owner"))
audit(db, organization.id, workspace.id, owner.id, "workspace.bootstrapped", workspace.name)
db.commit()
db.refresh(workspace)
return workspace
def list_workspaces(db: Session, user_id: int):
return (
db.query(Workspace, Organization, WorkspaceMembership.role)