From 22d2ae1e491b8361b2a6c30a140981f432086895 Mon Sep 17 00:00:00 2001 From: Igor Katsuba Date: Wed, 8 May 2024 23:07:52 +0300 Subject: [PATCH] feat(web): add user limits Close #34 --- .../api/invites/[inviteId]/accept/route.ts | 20 +++++++++ .../{users => members}/[id]/route.ts | 0 .../[workspaceSlug]/members/route.ts | 45 +++++++++++++++++++ .../workspaces/[workspaceSlug]/users/route.ts | 22 --------- 4 files changed, 65 insertions(+), 22 deletions(-) rename apps/web/app/api/workspaces/[workspaceSlug]/{users => members}/[id]/route.ts (100%) create mode 100644 apps/web/app/api/workspaces/[workspaceSlug]/members/route.ts delete mode 100644 apps/web/app/api/workspaces/[workspaceSlug]/users/route.ts diff --git a/apps/web/app/api/invites/[inviteId]/accept/route.ts b/apps/web/app/api/invites/[inviteId]/accept/route.ts index bc89ec6..c215d95 100644 --- a/apps/web/app/api/invites/[inviteId]/accept/route.ts +++ b/apps/web/app/api/invites/[inviteId]/accept/route.ts @@ -36,6 +36,26 @@ export const POST = withUser<{ inviteId: string }>(async ({ req, user, params }) ); } + const { data: workspace } = await supabase + .from('workspaces') + .select('*, plans(*), workspace_users(id)') + .eq('id', invite.workspaces.id) + .single(); + + const maxUsers = workspace?.plans?.max_users || 0; + + if (workspace?.workspace_users?.length ?? 0 >= maxUsers) { + return Response.json( + { + errors: ['Workspace is full'], + workspace: null, + }, + { + status: 400, + }, + ); + } + const { errors, workspaceUser } = await createWorkspaceUser({ workspace_id: invite.workspaces.id, user_id: user.id, diff --git a/apps/web/app/api/workspaces/[workspaceSlug]/users/[id]/route.ts b/apps/web/app/api/workspaces/[workspaceSlug]/members/[id]/route.ts similarity index 100% rename from apps/web/app/api/workspaces/[workspaceSlug]/users/[id]/route.ts rename to apps/web/app/api/workspaces/[workspaceSlug]/members/[id]/route.ts diff --git a/apps/web/app/api/workspaces/[workspaceSlug]/members/route.ts b/apps/web/app/api/workspaces/[workspaceSlug]/members/route.ts new file mode 100644 index 0000000..cf972e5 --- /dev/null +++ b/apps/web/app/api/workspaces/[workspaceSlug]/members/route.ts @@ -0,0 +1,45 @@ +import { withWorkspaceOwner } from '@saasfy/api/server'; +import { createWorkspaceUser } from '@saasfy/crud/workspace-users/server'; +import { createAdminClient } from '@saasfy/supabase/server'; + +export const POST = withWorkspaceOwner(async ({ req, workspace: { id: workspaceId }, user }) => { + const data = await req.json(); + + const supabase = createAdminClient(); + + const { data: workspace } = await supabase + .from('workspaces') + .select('*, plans(*), workspace_users(id)') + .eq('id', workspaceId) + .single(); + + const maxUsers = workspace?.plans?.max_users || 0; + + if (workspace?.workspace_users?.length ?? 0 >= maxUsers) { + return Response.json( + { + errors: ['Workspace is full'], + workspace: null, + }, + { + status: 400, + }, + ); + } + + const { errors, workspaceUser } = await createWorkspaceUser({ + ...data, + workspace_id: workspaceId, + user_id: user.id, + }); + + return Response.json( + { + errors, + workspaceUser, + }, + { + status: errors ? 400 : 200, + }, + ); +}); diff --git a/apps/web/app/api/workspaces/[workspaceSlug]/users/route.ts b/apps/web/app/api/workspaces/[workspaceSlug]/users/route.ts deleted file mode 100644 index 117b3b7..0000000 --- a/apps/web/app/api/workspaces/[workspaceSlug]/users/route.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { withWorkspaceOwner } from '@saasfy/api/server'; -import { createWorkspaceUser } from '@saasfy/crud/workspace-users/server'; - -export const POST = withWorkspaceOwner(async ({ req, workspace, user }) => { - const data = await req.json(); - - const { errors, workspaceUser } = await createWorkspaceUser({ - ...data, - workspace_id: workspace.id, - user_id: user.id, - }); - - return Response.json( - { - errors, - workspaceUser, - }, - { - status: errors ? 400 : 200, - }, - ); -});