diff --git a/backend/package-lock.json b/backend/package-lock.json index 77ce0f52..f1444f21 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -3998,9 +3998,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.634", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.634.tgz", - "integrity": "sha512-gQNahJfF5AE4MZo+pMSwmnwkzVZ+F4ZGGj4Z/MMddOXVQM0y9OHy6ts3W9SDzAJaiZM3p6eixn5ABCQ+AfXzcQ==", + "version": "1.4.637", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.637.tgz", + "integrity": "sha512-G7j3UCOukFtxVO1vWrPQUoDk3kL70mtvjc/DC/k2o7lE0wAdq+Vwp1ipagOow+BH0uVztFysLWbkM/RTIrbK3w==", "dev": true }, "node_modules/emittery": { @@ -7227,9 +7227,9 @@ } }, "node_modules/prettier": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.3.tgz", - "integrity": "sha512-QNhUTBq+mqt1oH1dTfY3phOKNhcDdJkfttHI6u0kj7M2+c+7fmNKlgh2GhnHiqMcbxJ+a0j2igz/2jfl9QKLuw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -8290,9 +8290,9 @@ } }, "node_modules/terser": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", - "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", + "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index bcefcb5c..f00adbd7 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -11,13 +11,13 @@ datasource db { } model User { - id String @id @default(auto()) @map("_id") @db.ObjectId - socialProvider String @map("social_provider") - socialUid String @unique @map("social_uid") - nickname String - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - UserWorkspace UserWorkspace[] + id String @id @default(auto()) @map("_id") @db.ObjectId + socialProvider String @map("social_provider") + socialUid String @unique @map("social_uid") + nickname String + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + userWorkspaceList UserWorkspace[] @@map("users") } diff --git a/backend/src/workspace-users/types/find-workspace-users-response.type.ts b/backend/src/workspace-users/types/find-workspace-users-response.type.ts new file mode 100644 index 00000000..ee39236f --- /dev/null +++ b/backend/src/workspace-users/types/find-workspace-users-response.type.ts @@ -0,0 +1,10 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { WorkspaceUserDomain } from "./workspace-user.domain"; + +export class FindWorkspaceUsersResponse { + @ApiProperty({ type: [WorkspaceUserDomain], description: "List of found workspace users" }) + workspaceUsers: Array; + + @ApiProperty({ type: String, description: "The ID of last workspace user" }) + cursor: string | null; +} diff --git a/backend/src/workspace-users/types/workspace-user.domain.ts b/backend/src/workspace-users/types/workspace-user.domain.ts new file mode 100644 index 00000000..5fa47a92 --- /dev/null +++ b/backend/src/workspace-users/types/workspace-user.domain.ts @@ -0,0 +1,12 @@ +import { ApiProperty } from "@nestjs/swagger"; + +export class WorkspaceUserDomain { + @ApiProperty({ type: String, description: "ID of the user" }) + id: string; + @ApiProperty({ type: String, description: "Nickname of the user" }) + nickname: string; + @ApiProperty({ type: Date, description: "Created date of the user" }) + createdAt: Date; + @ApiProperty({ type: Date, description: "Updated date of the user" }) + updatedAt: Date; +} diff --git a/backend/src/workspace-users/workspace-users.module.ts b/backend/src/workspace-users/workspace-users.module.ts index 2e19a6b4..7e2a5033 100644 --- a/backend/src/workspace-users/workspace-users.module.ts +++ b/backend/src/workspace-users/workspace-users.module.ts @@ -1,9 +1,10 @@ import { Module } from "@nestjs/common"; import { WorkspaceUsersController } from "./workspace-users.controller"; import { WorkspaceUsersService } from "./workspace-users.service"; +import { PrismaService } from "src/db/prisma.service"; @Module({ controllers: [WorkspaceUsersController], - providers: [WorkspaceUsersService], + providers: [WorkspaceUsersService, PrismaService], }) export class WorkspaceUsersModule {} diff --git a/backend/src/workspace-users/workspace-users.service.ts b/backend/src/workspace-users/workspace-users.service.ts index e2f7f80d..53a59d74 100644 --- a/backend/src/workspace-users/workspace-users.service.ts +++ b/backend/src/workspace-users/workspace-users.service.ts @@ -1,4 +1,55 @@ -import { Injectable } from "@nestjs/common"; +import { Injectable, NotFoundException } from "@nestjs/common"; +import { Prisma } from "@prisma/client"; +import { PrismaService } from "src/db/prisma.service"; +import { FindWorkspaceUsersResponse } from "./types/find-workspace-users-response.type"; @Injectable() -export class WorkspaceUsersService {} +export class WorkspaceUsersService { + constructor(private prismaService: PrismaService) {} + + async findMany( + userId: string, + workspaceId: string, + pageSize: number, + cursor?: string + ): Promise { + try { + await this.prismaService.userWorkspace.findFirstOrThrow({ + where: { + userId, + workspaceId, + }, + }); + } catch (e) { + throw new NotFoundException(); + } + + const additionalOptions: Prisma.UserFindManyArgs = {}; + + if (cursor) { + additionalOptions.cursor = { id: cursor }; + } + + const workspaceUserList = await this.prismaService.user.findMany({ + take: pageSize + 1, + where: { + userWorkspaceList: { + some: { + workspaceId: { + equals: workspaceId, + }, + }, + }, + }, + orderBy: { + id: "desc", + }, + ...additionalOptions, + }); + + return { + workspaceUsers: workspaceUserList.slice(0, pageSize), + cursor: workspaceUserList.length > pageSize ? workspaceUserList[pageSize].id : null, + }; + } +}