diff --git a/prisma/schema.prisma b/prisma/schema.prisma index da8f80b..41c4b48 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -17,8 +17,17 @@ model Account { isPhoneVerified Boolean @default(false) @map("is_phone_verified") isEmailVerified Boolean @default(false) @map("is_email_verified") + role Role @default(USER) + createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("accounts") } + +enum Role { + ADMIN + USER + + @@map("roles") +} diff --git a/src/app.module.ts b/src/app.module.ts index 505d7e0..da65224 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -4,6 +4,7 @@ import { ConfigModule } from '@nestjs/config' import { dabataseEnv, grpcEnv, passportEnv, redisEnv } from './config' import { PrismaModule } from './infra/prisma/prisma.module' import { RedisModule } from './infra/redis/redis.module' +import { AccountModule } from './modules/account/account.module' import { AuthModule } from './modules/auth/auth.module' import { OtpModule } from './modules/otp/otp.module' @@ -16,7 +17,8 @@ import { OtpModule } from './modules/otp/otp.module' PrismaModule, RedisModule, AuthModule, - OtpModule + OtpModule, + AccountModule ] }) export class AppModule {} diff --git a/src/infra/grpc/grpc.options.ts b/src/infra/grpc/grpc.options.ts index bf16ec9..75b1efe 100644 --- a/src/infra/grpc/grpc.options.ts +++ b/src/infra/grpc/grpc.options.ts @@ -1,8 +1,8 @@ import { GrpcOptions } from '@nestjs/microservices' import { PROTO_PATHS } from '@teacinema/contracts' -export const grpcPackages = ['auth.v1'] -export const grpcProtoPaths = [PROTO_PATHS.AUTH] +export const grpcPackages = ['auth.v1', 'account.v1'] +export const grpcProtoPaths = [PROTO_PATHS.AUTH, PROTO_PATHS.ACCOUNT] export const grpcLoader: GrpcOptions['options']['loader'] = { keepCase: false, longs: String, diff --git a/src/modules/account/account.controller.ts b/src/modules/account/account.controller.ts new file mode 100644 index 0000000..67d53d0 --- /dev/null +++ b/src/modules/account/account.controller.ts @@ -0,0 +1,20 @@ +import { Controller } from '@nestjs/common' +import { GrpcMethod } from '@nestjs/microservices' +import type { + GetAccountRequest, + GetAccountResponse +} from '@teacinema/contracts/gen/account' + +import { AccountService } from './account.service' + +@Controller() +export class AccountController { + constructor(private readonly accountService: AccountService) {} + + @GrpcMethod('AccountService', 'GetAccount') + public async getAccount( + data: GetAccountRequest + ): Promise { + return this.accountService.getAccount(data) + } +} diff --git a/src/modules/account/account.module.ts b/src/modules/account/account.module.ts new file mode 100644 index 0000000..aa3115c --- /dev/null +++ b/src/modules/account/account.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common' + +import { AccountRepository } from '@/modules/account/account.repository' + +import { AccountController } from './account.controller' +import { AccountService } from './account.service' + +@Module({ + controllers: [AccountController], + providers: [AccountService, AccountRepository] +}) +export class AccountModule {} diff --git a/src/modules/account/account.repository.ts b/src/modules/account/account.repository.ts new file mode 100644 index 0000000..f4c8918 --- /dev/null +++ b/src/modules/account/account.repository.ts @@ -0,0 +1,12 @@ +import { Injectable } from '@nestjs/common' + +import { PrismaService } from '@/infra/prisma/prisma.service' + +@Injectable() +export class AccountRepository { + public constructor(private readonly prismaService: PrismaService) {} + + public findById(id: string) { + return this.prismaService.account.findUnique({ where: { id } }) + } +} diff --git a/src/modules/account/account.service.ts b/src/modules/account/account.service.ts new file mode 100644 index 0000000..317714e --- /dev/null +++ b/src/modules/account/account.service.ts @@ -0,0 +1,39 @@ +import { Injectable } from '@nestjs/common' +import { RpcException } from '@nestjs/microservices' +import { Role } from '@prisma/generated/enums' +import { convertEnum, RpcStatus } from '@teacinema/common' +import type { + GetAccountRequest, + GetAccountResponse +} from '@teacinema/contracts/gen/account' + +import { AccountRepository } from './account.repository' + +@Injectable() +export class AccountService { + public constructor(private readonly accountRepository: AccountRepository) {} + + public async getAccount( + data: GetAccountRequest + ): Promise { + const { id } = data + const account = await this.accountRepository.findById(id) + + if (!account) { + throw new RpcException({ + code: RpcStatus.NOT_FOUND, + details: 'Account not found' + }) + } + + return { + email: account.email, + id: account.id, + phone: account.phone, + isEmailVerified: account.isEmailVerified, + isPhoneVerified: account.isPhoneVerified, + // @ts-ignore + role: convertEnum(Role, account.role) + } + } +} diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 9272f9f..af94d01 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -1,5 +1,5 @@ -import { Controller } from '@nestjs/common'; -import { GrpcMethod } from '@nestjs/microservices'; +import { Controller } from '@nestjs/common' +import { GrpcMethod } from '@nestjs/microservices' import type { RefreshRequest, RefreshResponse, @@ -11,10 +11,6 @@ import type { import { AuthService } from './auth.service' - - - - @Controller() export class AuthController { constructor(private readonly authService: AuthService) {} diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts index 3606738..e17c329 100644 --- a/src/modules/auth/auth.service.ts +++ b/src/modules/auth/auth.service.ts @@ -125,10 +125,11 @@ export class AuthService { if (!result.valid) { throw new RpcException({ code: RpcStatus.UNAUTHENTICATED, + // @ts-ignore details: result.reason }) } - return this.generateTokens(result.userId); + return this.generateTokens(result.userId) } } diff --git a/yarn.lock b/yarn.lock index 973c245..89fd194 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1055,7 +1055,7 @@ webpack "5.104.1" webpack-node-externals "3.0.0" -"@nestjs/common@^11.0.1", "@nestjs/common@^11.1.12": +"@nestjs/common@^11.0.1": version "11.1.12" resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-11.1.12.tgz#bd28d34fa6bf676671c70be8148b5405ccd3d422" integrity sha512-v6U3O01YohHO+IE3EIFXuRuu3VJILWzyMmSYZXpyBbnp0hk0mFyHxK2w3dF4I5WnbwiRbWlEXdeXFvPQ7qaZzw== @@ -1066,6 +1066,17 @@ load-esm "1.0.3" tslib "2.8.1" +"@nestjs/common@^11.1.12": + version "11.1.13" + resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-11.1.13.tgz#3d4bcc2a593236546bc62f7801b0d4450b26a9ac" + integrity sha512-ieqWtipT+VlyDWLz5Rvz0f3E5rXcVAnaAi+D53DEHLjc1kmFxCgZ62qVfTX2vwkywwqNkTNXvBgGR72hYqV//Q== + dependencies: + uid "2.0.2" + file-type "21.3.0" + iterare "1.2.1" + load-esm "1.0.3" + tslib "2.8.1" + "@nestjs/config@^4.0.2": version "4.0.2" resolved "https://registry.yarnpkg.com/@nestjs/config/-/config-4.0.2.tgz#a2777a1fd2d0d594bab3953f50fbca95c14cce52" @@ -1075,7 +1086,7 @@ dotenv-expand "12.0.1" lodash "4.17.21" -"@nestjs/core@^11.0.1", "@nestjs/core@^11.1.12": +"@nestjs/core@^11.0.1": version "11.1.12" resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-11.1.12.tgz#cdbff023cc87ed071aebafeacb209bc5997da1e4" integrity sha512-97DzTYMf5RtGAVvX1cjwpKRiCUpkeQ9CCzSAenqkAhOmNVVFaApbhuw+xrDt13rsCa2hHVOYPrV4dBgOYMJjsA== @@ -1087,6 +1098,18 @@ path-to-regexp "8.3.0" tslib "2.8.1" +"@nestjs/core@^11.1.12": + version "11.1.13" + resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-11.1.13.tgz#4444e124d255759d545a631f63e9d84fe1a1e3e5" + integrity sha512-Tq9EIKiC30EBL8hLK93tNqaToy0hzbuVGYt29V8NhkVJUsDzlmiVf6c3hSPtzx2krIUVbTgQ2KFeaxr72rEyzQ== + dependencies: + uid "2.0.2" + "@nuxt/opencollective" "0.4.1" + fast-safe-stringify "2.1.1" + iterare "1.2.1" + path-to-regexp "8.3.0" + tslib "2.8.1" + "@nestjs/mapped-types@*": version "2.1.0" resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.1.0.tgz#b9b536b7c3571567aa1d0223db8baa1a51505a19" @@ -1355,14 +1378,14 @@ integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w== "@teacinema/common@^1.0.0": - version "1.0.0" - resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcommon/-/1.0.0/common-1.0.0.tgz#3b79ae6eb46352ed1544535be094fe0ead244c36" - integrity sha512-L006mySvhRpUlRHf3ONbXA0RG42gbQ9QAnmQuZx4zejHEsWB9702xe18MSYcBilv+lmYkQpiX/g3p8P7suLfqQ== + version "1.0.1" + resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcommon/-/1.0.1/common-1.0.1.tgz#40ad9ced1522b53fa6e46d7f6797cc03193705ab" + integrity sha512-q3DURJbSk3k8MNWFIYaSM4LEcBgPbWa+HJmBz/nzYT4kuYitJVSXxpZ97kr0Ea+81AZwAU3JhQKlkK0SBWUi0A== "@teacinema/contracts@^1.0.0": - version "1.0.5" - resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.0.5/contracts-1.0.5.tgz#f6db65f58ba3621e81e886f54d6ec9e674c4785b" - integrity sha512-paFa/zVWKzDNuH04EyGPlG981YEX7Xt42gRwpfZwACGa5CCM5lehT7xKU4h9p/l9IebrOtTPDwJdQn/D41o3Gw== + version "1.0.6" + resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.0.6/contracts-1.0.6.tgz#7aa97d4c3081b791908c90d2a12d771b5fb79bd5" + integrity sha512-2IU2S9hWtKeMpn4zRS9pJAaSryIODrRjS1q9QezQOXF6554vtQlMVr0fLVTGhNmXlbRfuje0f6HggApqPDFMaA== dependencies: "@nestjs/microservices" "^11.1.12" protoc "33.4.0" @@ -1377,9 +1400,9 @@ "@trivago/prettier-plugin-sort-imports" "^5.2.2" "@teacinema/passport@^1.0.0": - version "1.0.0" - resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fpassport/-/1.0.0/passport-1.0.0.tgz#c848d9fb089a975111bf19280cd4ca7b0118b73c" - integrity sha512-aPDPmaAkXiHKTkBxGR08DB3ih3cAZSF91CZaRBLXpQ7/NvfVLcOGmvk9jaAL5vbExtwT/OOQVKEMb0nIfVAzzg== + version "1.0.1" + resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fpassport/-/1.0.1/passport-1.0.1.tgz#83a8a605534b23929d3b1090d28023626fd5cc9f" + integrity sha512-hgFHXtWgXOemAf9InBLuhHbtF8wS01HKmot0nSaUqGlQCtu74ArMMCG8mup1SR50UGz5DEpHPEL8G5CzVnTTSQ== dependencies: "@nestjs/common" "^11.1.12" "@nestjs/core" "^11.1.12"