Skip to content

Commit 1e4806f

Browse files
committed
feat: grcp communication with auth domain on user domain and folder refactoring
1 parent ab158d9 commit 1e4806f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+974
-116
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,7 @@ pids
5454

5555
# Diagnostic reports (https://nodejs.org/api/report.html)
5656
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
57+
58+
# grammar
59+
.vale.ini
60+
.vale-styles

.prettierrc

+17-2
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,20 @@
1010
"quoteProps": "as-needed",
1111
"proseWrap": "preserve",
1212
"htmlWhitespaceSensitivity": "css",
13-
"embeddedLanguageFormatting": "auto"
14-
}
13+
"embeddedLanguageFormatting": "auto",
14+
15+
"useTabs": false,
16+
"bracketSameLine": false,
17+
"jsxSingleQuote": true,
18+
"parser": "typescript",
19+
"requirePragma": false,
20+
"insertPragma": false,
21+
"overrides": [
22+
{
23+
"files": "*.spec.ts",
24+
"options": {
25+
"printWidth": 100
26+
}
27+
}
28+
]
29+
}

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ todo project
44

55

66
URL: https://bside.best/projects/detail/P240926112258
7+
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* TODO
3+
* @task implement handler to ochastration
4+
* - store user credential
5+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
* TODO
3+
* @task implement command for sending to handler
4+
*/

apps/auth/src/auth.module.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { Module } from '@nestjs/common';
22

3+
/**
4+
* TODO
5+
* @task implement importing the module written so far
6+
*/
37
@Module({
48
imports: [],
59
providers: [],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { GrpcOptions, Transport } from '@nestjs/microservices';
2+
import { join } from 'path';
3+
4+
export const authGrpcOptions: GrpcOptions = {
5+
transport: Transport.GRPC,
6+
options: {
7+
package: 'auth',
8+
protoPath: join(__dirname, '../../../../proto/auth.proto'),
9+
url: 'auth:50051',
10+
},
11+
};

apps/auth/src/infrastructure/persistence/credentail.repository.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export class UserCredentialRepository implements IUserCredentialRepository {
1818
}
1919
async updateUserCredential(entity: UserCredentialEntity): Promise<void> {
2020
const record = UserCredentialMapper.toPersistence(entity);
21+
2122
await this.prisma.userCredentials.update({
2223
where: {
2324
id: entity.id,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
-- CreateTable
2+
CREATE TABLE `Tokens` (
3+
`id` VARCHAR(191) NOT NULL,
4+
`userId` VARCHAR(191) NOT NULL,
5+
`accessToken` VARCHAR(191) NOT NULL,
6+
`refreshToken` VARCHAR(191) NOT NULL,
7+
`isRevoked` BOOLEAN NOT NULL DEFAULT false,
8+
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
9+
`updatedAt` DATETIME(3) NOT NULL,
10+
`expiresAt` DATETIME(3) NOT NULL,
11+
12+
UNIQUE INDEX `Tokens_accessToken_key`(`accessToken`),
13+
UNIQUE INDEX `Tokens_refreshToken_key`(`refreshToken`),
14+
INDEX `Tokens_isRevoked_expiresAt_idx`(`isRevoked`, `expiresAt`),
15+
PRIMARY KEY (`id`)
16+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
17+
18+
-- CreateTable
19+
CREATE TABLE `OAuthProvider` (
20+
`id` VARCHAR(191) NOT NULL,
21+
`provider` ENUM('KAKAO', 'GOOGLE', 'APPLE') NOT NULL,
22+
`providerId` VARCHAR(191) NOT NULL,
23+
`userId` VARCHAR(191) NOT NULL,
24+
`createAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
25+
`updateAt` DATETIME(3) NOT NULL,
26+
27+
INDEX `OAuthProvider_userId_provider_idx`(`userId`, `provider`),
28+
UNIQUE INDEX `OAuthProvider_provider_providerId_key`(`provider`, `providerId`),
29+
PRIMARY KEY (`id`)
30+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
31+
32+
-- CreateTable
33+
CREATE TABLE `UserCredentials` (
34+
`id` VARCHAR(191) NOT NULL,
35+
`userId` VARCHAR(191) NOT NULL,
36+
`email` VARCHAR(191) NOT NULL,
37+
`passwordHash` VARCHAR(191) NOT NULL,
38+
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
39+
`updatedAt` DATETIME(3) NOT NULL,
40+
41+
UNIQUE INDEX `UserCredentials_userId_key`(`userId`),
42+
UNIQUE INDEX `UserCredentials_email_key`(`email`),
43+
PRIMARY KEY (`id`)
44+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Please do not edit this file manually
2+
# It should be added in your version-control system (e.g., Git)
3+
provider = "mysql"

apps/auth/src/infrastructure/prisma/schema.prisma

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// auth/schema.prisma
22
generator client {
33
provider = "prisma-client-js"
4+
output = "../../../"
45
}
56

67
datasource authDB {

apps/auth/src/main.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { NestFactory } from '@nestjs/core';
22
import { AuthModule } from '@auth/auth.module';
3+
import { MicroserviceOptions } from '@nestjs/microservices';
4+
import { authGrpcOptions } from '@auth/infrastructure/adapter/grpc/options/auth-grpc.option';
35

4-
5-
@Injectable()
66
async function bootstrap() {
77
const app = await NestFactory.create(AuthModule);
88

9-
await app.listen(5000);
9+
app.connectMicroservice<MicroserviceOptions>(authGrpcOptions);
10+
11+
await app.startAllMicroservices();
12+
await app.listen(3001);
1013
}
14+
1115
bootstrap();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
* TODO
3+
* @task implement to auth controller to receive gRPC request
4+
*/

apps/scripts/start-user.sh

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
#!/bin/sh
22

33
# 1. 의존성이 없거나 변경되었는지 확인하고 설치
4-
if [ ! -d "node_modules" ] || [ ! -f "node_modules/.package-lock.json" ]; then
5-
echo "Installing dependencies..."
6-
npm install
7-
fi
4+
echo "Installing dependencies..."
5+
npm install
6+
87
rm -rf apps/user/src/infrastructure/prisma/migrations
98
npx prisma generate --schema=apps/user/src/infrastructure/prisma/schema.prisma
109
npx prisma migrate deploy --schema=apps/user/src/infrastructure/prisma/schema.prisma

apps/user/src/application/commands/handlers/create-user.handler.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ export class CreateUserHandler implements ICommandHandler<CreateUserCommand> {
1414
) {}
1515
async execute(command: CreateUserCommand): Promise<CreateUserResult> {
1616
const user = await this.userService.createUser(
17-
new CreateUserParam(command.email, command.nickname, command.birthday),
17+
new CreateUserParam(
18+
command.email,
19+
command.nickname,
20+
command.password,
21+
command.birthday,
22+
),
1823
);
1924
return {
2025
birthday: user.birthday,

apps/user/src/application/dto/params/create-user.param.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export class CreateUserParam {
22
constructor(
33
public readonly email: string,
44
public readonly nickname: string,
5+
public readonly password: string,
56
public readonly birthday?: Date,
67
) {}
78
}

apps/user/src/application/port/out/user-repository.port.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export interface DeleteUserArgs {
66
id: string;
77
}
88

9-
export interface FindUserArgs {
9+
export interface FindUserByIdArgs {
1010
id: string;
1111
}
1212

@@ -15,13 +15,12 @@ export type UserBasicRepositoryArgs = {
1515
createUser: User;
1616
updateUser: User;
1717
deleteUser: DeleteUserArgs;
18-
findUser: FindUserArgs;
18+
findUser: FindUserByIdArgs;
1919
};
2020

21-
// 제너릭을 활용한 유연한 UserRepository 인터페이스
22-
export interface IUserRepositoryGeneric<T extends Record<string, any>> {
23-
createUser(args: T['createUser']): Promise<void>;
24-
updateUser(args: T['updateUser']): Promise<void>;
25-
deleteUser(args: T['deleteUser']): Promise<void>;
26-
findUser(args: T['findUser']): Promise<User | null>;
21+
export interface IUserRepository {
22+
createUser(data: User): Promise<void>;
23+
updateUser(args: User): Promise<void>;
24+
deleteUser(args: DeleteUserArgs): Promise<void>;
25+
findUser(args: FindUserByIdArgs): Promise<User | null>;
2726
}

apps/user/src/application/services/user.service.ts

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,51 @@
11
import { Inject, Injectable } from '@nestjs/common';
22
import { ErrorCode, errorFactory } from '@libs/exception';
33
import {
4-
IUserRepositoryGeneric,
5-
UserBasicRepositoryArgs,
4+
IUserRepository,
65
UserRepositorySymbol,
76
} from '@user/application/port/out/user-repository.port';
87
import { CreateUserParam } from '@user/application/dto/params/create-user.param';
98
import { User } from '@user/domain/entity/user.entity';
109
import { UpdateUserParam } from '@user/application/dto/params/update-user.param';
1110
import { DeleteUserParam } from '@user/application/dto/params/delete-user.param';
11+
import { USER_GRPC_SERVICE_SYMBOL } from '@user/infrastructure/adapter/grpc/options/user-grpc-client.options';
12+
import { firstValueFrom } from 'rxjs';
13+
import { AuthMicroservice } from '@libs/grpc';
1214

1315
@Injectable()
1416
export class UserService {
1517
constructor(
1618
@Inject(UserRepositorySymbol)
17-
private readonly userRepository: IUserRepositoryGeneric<UserBasicRepositoryArgs>,
19+
private readonly userRepository: IUserRepository,
20+
@Inject(USER_GRPC_SERVICE_SYMBOL)
21+
private readonly authClient: AuthMicroservice.AuthServiceClient,
1822
) {}
1923

24+
/**
25+
* TODO
26+
* @task After creating a user, the user credentials are saved in the auth domain through a grpc request for login.
27+
*/
2028
async createUser(param: CreateUserParam): Promise<User> {
2129
const user = User.create({
2230
nickname: param.nickname,
2331
email: param.email,
32+
password: param.password,
2433
birthday: param.birthday,
2534
});
2635
await this.userRepository.createUser(user);
36+
const response = await firstValueFrom(
37+
this.authClient.createUserCredential({
38+
createdAt: user.createdAt.toDateString(),
39+
updatedAt: user.updatedAt.toDateString(),
40+
email: user.email,
41+
userId: user.id,
42+
passwordHash: user.password,
43+
}),
44+
);
45+
if (!response.success) {
46+
await this.userRepository.deleteUser(user);
47+
throw errorFactory(ErrorCode.BAD_REQUEST);
48+
}
2749
return user;
2850
}
2951

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Module } from '@nestjs/common';
2+
import { CqrsModule } from '@nestjs/cqrs';
3+
import { CreateUserHandler } from '@user/application/commands/handlers/create-user.handler';
4+
import { UpdateUserHandler } from '@user/application/commands/handlers/update-user.handler';
5+
import { DeleteUserHandler } from '@user/application/commands/handlers/delete-user.handler';
6+
import { UserService } from '@user/application/services/user.service';
7+
8+
@Module({
9+
imports: [CqrsModule],
10+
providers: [
11+
CreateUserHandler,
12+
UpdateUserHandler,
13+
DeleteUserHandler,
14+
UserService,
15+
],
16+
exports: [
17+
CreateUserHandler,
18+
UpdateUserHandler,
19+
DeleteUserHandler,
20+
UserService,
21+
],
22+
})
23+
export class UserApplicationModule {}

0 commit comments

Comments
 (0)