diff --git a/src/server/model/user.ts b/src/server/model/user.ts index bc63e85..a2b0df8 100644 --- a/src/server/model/user.ts +++ b/src/server/model/user.ts @@ -6,6 +6,7 @@ import { TRPCError } from '@trpc/server'; import { Prisma } from '@prisma/client'; import { AdapterUser } from '@auth/core/adapters'; import { md5 } from '../utils/common.js'; +import { logger } from '../utils/logger.js'; async function hashPassword(password: string) { return await bcryptjs.hash(password, 10); @@ -280,3 +281,62 @@ export async function changeUserPassword( }, }); } + +/** + * let user join workspace + */ +export async function joinWorkspace( + userId: string, + workspaceId: string, + role: ROLES = ROLES.readOnly +) { + try { + await prisma.user.update({ + where: { + id: userId, + }, + data: { + workspaces: { + connectOrCreate: { + where: { + userId_workspaceId: { + userId: userId, + workspaceId: workspaceId, + }, + }, + create: { + workspaceId: workspaceId, + role, + }, + }, + }, + }, + }); + } catch (err) { + logger.error(err); + throw new Error('Join Workspace Failed.'); + } +} + +export async function leaveWorkspace(userId: string, workspaceId: string) { + try { + await prisma.user.update({ + where: { + id: userId, + }, + data: { + workspaces: { + delete: { + userId_workspaceId: { + userId, + workspaceId, + }, + }, + }, + }, + }); + } catch (err) { + logger.error(err); + throw new Error('Leave Workspace Failed.'); + } +} diff --git a/src/server/trpc/routers/workspace.ts b/src/server/trpc/routers/workspace.ts index cc8604b..fa07946 100644 --- a/src/server/trpc/routers/workspace.ts +++ b/src/server/trpc/routers/workspace.ts @@ -17,7 +17,7 @@ import { OPENAPI_TAG } from '../../utils/const.js'; import { OpenApiMeta } from 'trpc-openapi'; import { getServerCount } from '../../model/serverStatus.js'; import { ROLES, slugRegex } from '@tianji/shared'; -import { createUserSelect } from '../../model/user.js'; +import { createUserSelect, joinWorkspace } from '../../model/user.js'; import { WorkspacesOnUsersModelSchema } from '../../prisma/zod/workspacesonusers.js'; export const workspaceRouter = router({ @@ -193,6 +193,35 @@ export const workspaceRouter = router({ return list; }), + invite: workspaceOwnerProcedure + .meta( + buildWorkspaceOpenapi({ + method: 'POST', + path: '/{workspaceId}/invite', + }) + ) + .input( + z.object({ + targetUserEmail: z.string(), + }) + ) + .output(z.void()) + .mutation(async ({ input }) => { + const { targetUserEmail, workspaceId } = input; + const targetUser = await prisma.user.findUnique({ + where: { + email: targetUserEmail, + }, + }); + + if (targetUser) { + // if user exist + await joinWorkspace(targetUser.id, workspaceId); + } else { + // user not exist + throw new Error('Target user not existed'); + } + }), getUserWorkspaceRole: publicProcedure .input( z.object({