Skip to content

Commit

Permalink
Merge pull request #47 from PBTP/refacotr/tsconfig
Browse files Browse the repository at this point in the history
refactor: tsconfig 적용
  • Loading branch information
emibgo2 authored Oct 26, 2024
2 parents 4b725b3 + f97b2e7 commit 1973505
Show file tree
Hide file tree
Showing 37 changed files with 473 additions and 286 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
"@nestjs/typeorm": "^10.0.2",
"@nestjs/websockets": "^10.3.10",
"@ssut/nestjs-sqs": "^2.2.0",
"@types/nodemailer": "^6.4.16",
"@types/passport-jwt": "^4.0.1",
"@types/socket.io": "^3.0.2",
"@willsoto/nestjs-prometheus": "^6.0.1",
"aws-sdk": "^2.1623.0",
Expand Down
6 changes: 4 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const appModules = [
}),
TypeOrmModule.forRootAsync({
useFactory: async (configService: ConfigService) => {
const datasource = JSON.parse(configService.get('datasource/db'));
const datasource = JSON.parse(<string>configService.get('datasource/db'));

return {
type: 'postgres',
Expand All @@ -48,7 +48,9 @@ const appModules = [
}),
RedisModule.forRootAsync({
useFactory: async (configService: ConfigService) => {
const datasource = JSON.parse(configService.get('datasource/redis'));
const datasource = JSON.parse(
<string>configService.get('datasource/redis'),
);
return {
config: datasource,
readyLog: true,
Expand Down
55 changes: 40 additions & 15 deletions src/auth/application/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { Injectable } from "@nestjs/common";
import { JwtService, JwtSignOptions } from "@nestjs/jwt";
import { ConfigService } from "@nestjs/config";
import { CacheService } from "../../common/cache/cache.service";
import { UnauthorizedException } from "@nestjs/common/exceptions";
import { UserService } from "./user.service";
import { UserDto } from "../presentation/user.dto";
import { AuthDto } from "../presentation/auth.dto";
import { Injectable, Logger } from '@nestjs/common';
import { JwtService, JwtSignOptions } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
import { CacheService } from '../../common/cache/cache.service';
import { UnauthorizedException } from '@nestjs/common/exceptions';
import { UserService } from './user.service';
import { UserDto } from '../presentation/user.dto';
import { AuthDto } from '../presentation/auth.dto';

@Injectable()
export class AuthService {
private readonly accessTokenOption: JwtSignOptions;
private readonly refreshTokenOption: JwtSignOptions;
private readonly accessTokenStrategy: string;
private readonly logger = new Logger(AuthService.name);

constructor(
private readonly jwtService: JwtService,
Expand All @@ -29,18 +30,25 @@ export class AuthService {
expiresIn: this.configService.get<number>('jwt/refresh/expire'),
};

this.accessTokenStrategy = this.configService.get<string>(
'jwt/access/strategy',
this.accessTokenStrategy = <string>(
this.configService.get('jwt/access/strategy')
);
}

async login(dto: UserDto): Promise<AuthDto> {
let user: UserDto = await this.userService.findOne(dto);
user = user ?? (await this.userService.create(dto));
user.userId = user.customerId ?? user.driverId ?? user.businessId;

user.userId = user['customerId'] ?? user['driverId'] ?? user['businessId'];
user.userType = dto.userType;

if (!user.userType) {
throw new UnauthorizedException('사용자 타입이 없습니다.');
}
if (!user.userId) {
throw new UnauthorizedException('사용자 아이디가 없습니다.');
}

const accessToken = this.jwtService.sign(
{
tokenType: 'access',
Expand Down Expand Up @@ -79,11 +87,23 @@ export class AuthService {
};
}

async tokenRefresh(request: Request): Promise<AuthDto> {
const token = request.headers['authorization'].replace('Bearer ', '');
async tokenRefresh(
request: Request & { headers: { authorization?: string } },
): Promise<AuthDto> {
const token = request.headers.authorization?.replace('Bearer ', '');

if (!token) {
throw new UnauthorizedException('Authorization 헤더에 토큰이 없습니다.');
}

const payload = this.jwtService.decode(token);

console.log('payload', payload);

if (!payload) {
throw new UnauthorizedException('토큰이 유효하지 않습니다.');
}

const user: UserDto = await this.userService.findOne({
userType: payload.userType,
userId: payload.subject,
Expand All @@ -101,7 +121,7 @@ export class AuthService {
const refreshToken = this.jwtService.sign(
{
tokenType: 'refresh',
subject: user.userId,
subject: user.userId!,
userType: user.userType,
},
this.refreshTokenOption,
Expand All @@ -124,6 +144,11 @@ export class AuthService {
}

private async saveAccessToken(user: UserDto, accessToken: string) {
if (!user.userType && !user.userId) {
this.logger.error('사용자 정보가 없습니다.');
throw new UnauthorizedException('사용자 정보가 없습니다.');
}

const key = `${user.userType}:${user.userId}:accessToken`;

if (this.accessTokenStrategy?.toLowerCase() === 'unique') {
Expand Down Expand Up @@ -157,7 +182,7 @@ export class AuthService {
async getUser(token: string): Promise<any> {
const payload = await this.jwtService.verify(token);
if (!payload) {
throw new UnauthorizedException();
throw new UnauthorizedException('토큰이 유효하지 않습니다.');
}

return await this.userService.findOne({
Expand Down
13 changes: 10 additions & 3 deletions src/auth/application/jwt-access.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ export class JwtAccessStrategy extends PassportStrategy(Strategy, 'access') {
});
}

async validate(req: Request, payload: any): Promise<UserDto> {
async validate(
req: Request & { headers: { authorization?: string } },
payload: any,
): Promise<UserDto> {
if (!payload) {
throw new UnauthorizedException();
}
Expand All @@ -31,7 +34,11 @@ export class JwtAccessStrategy extends PassportStrategy(Strategy, 'access') {
throw new BadRequestException();
}

const token = req.headers['authorization'].replace('Bearer ', '');
return JSON.parse(await this.cacheService.get(token)) as UserDto;
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
throw new UnauthorizedException('Authorization 헤더에 토큰이 없습니다.');
}

return JSON.parse(<string>await this.cacheService.get(token)) as UserDto;
}
}
16 changes: 9 additions & 7 deletions src/auth/application/security.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ export class SecurityService {
private iv = crypto.randomBytes(16); // 초기화 벡터(IV)

constructor(private readonly configService: ConfigService) {
this.algorithm = this.configService.get('security/crypto/algorithm');
this.secretKey = this.configService.get('security/crypto/key');
this.algorithm = <string>(
this.configService.get('security/crypto/algorithm')
);
this.secretKey = <string>this.configService.get('security/crypto/key');
}

encrypt(text: string): string {
if (!text) return null;
encrypt(text: string): string | undefined {
if (!text) return undefined;

const cipher = crypto.createCipheriv(
this.algorithm,
Expand All @@ -25,13 +27,13 @@ export class SecurityService {
return `${this.iv.toString('hex')}:${encrypted.toString('hex')}`; // IV와 암호화된 데이터를 함께 반환
}

decrypt(hash: string): string {
if (!hash) return null;
decrypt(hash: string): string | undefined {
if (!hash) return undefined;

const [iv, encryptedText] = hash.split(':');

if (!iv || !encryptedText) {
return null;
return undefined;
}

const decipher = crypto.createDecipheriv(
Expand Down
6 changes: 3 additions & 3 deletions src/auth/application/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ export class UserService {
}

async findOne(dto: UserDto): Promise<any> {
const user = await this.userServices[dto.userType].findOne(dto);
const user = await this.userServices[dto.userType!].findOne(dto);

user && (user.userType = dto.userType);
return user;
}

async create(dto: UserDto) {
return this.userServices[dto.userType].create(dto);
return this.userServices[dto.userType!].create(dto);
}

async update(dto: AuthDto) {
return await this.userServices[dto.userType].update(dto);
return await this.userServices[dto.userType!].update(dto);
}

toUserDto(user: any) {
Expand Down
4 changes: 4 additions & 0 deletions src/auth/presentation/user.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,8 @@ export class UserDto {
description: '사용자 이름입니다.',
})
name?: string;

customerId?: number;
driverId?: number;
businessId?: number;
}
32 changes: 16 additions & 16 deletions src/business/application/business.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { IUserService } from '../../auth/user.interface';
import { UserDto, UserType } from '../../auth/presentation/user.dto';
import { Business } from '../../schemas/business.entity';
import { AuthDto } from '../../auth/presentation/auth.dto';
import { Builder } from 'builder-pattern';

@Injectable()
export class BusinessService implements IUserService {
Expand All @@ -17,21 +18,21 @@ export class BusinessService implements IUserService {
) {}

async findOne(dto: Partial<AuthDto>): Promise<Business> {
const where = {};

dto.userId && (where['businessId'] = dto.userId ?? dto['businessId']);
dto.uuid && (where['uuid'] = dto.uuid);

return await this.businessRepository.findOne({
where: where,
return await this.businessRepository.findOneOrFail({
where: {
businessId: dto.userId,
uuid: dto.uuid,
},
});
}

async create(dto: UserDto): Promise<Business> {
const business = new Business();
business.uuid = dto.uuid;
business.businessName = dto.name;
business.authProvider = dto.authProvider;
Builder<Business>()
.uuid(dto.uuid!)
.businessName(dto.name!)
.authProvider(dto.authProvider!)
.build();

return await this.businessRepository
.save(this.businessRepository.create(business))
Expand All @@ -45,13 +46,12 @@ export class BusinessService implements IUserService {

async update(dto: AuthDto): Promise<Business> {
return this.findOne(dto).then(async (business) => {
if (business) {
business.businessName = dto.name;
business.businessPhoneNumber = dto.phoneNumber;
business.refreshToken = dto.refreshToken ?? business.refreshToken;
business.businessName = dto.name ?? business.businessName;
business.businessPhoneNumber =
dto.phoneNumber ?? business.businessPhoneNumber;
business.refreshToken = dto.refreshToken ?? business.refreshToken;

return await this.businessRepository.save(business);
}
return await this.businessRepository.save(business);
});
}

Expand Down
6 changes: 3 additions & 3 deletions src/business/presentation/business.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class BusinessDto extends AuthDto {
@IsNumber()
@IsOptional()
@ValidateIf((o) => !o.uuid, { groups: CRUD })
businessId?: number;
override businessId?: number;

@ApiProperty({
description: 'ResourceServer에서 제공한 업체 식별자',
Expand All @@ -32,7 +32,7 @@ export class BusinessDto extends AuthDto {
@IsNotEmpty({ groups: CRUD })
@IsOptional()
@ValidateIf((o) => !o.businessId, { groups: CRUD })
uuid: string;
override uuid: string;

@ApiProperty({
description: '업체 이름',
Expand Down Expand Up @@ -96,5 +96,5 @@ export class BusinessDto extends AuthDto {
@IsNotEmpty()
@IsOptional()
@IsEnum(AuthProvider, { groups: [UserGroup.login] })
authProvider: AuthProvider;
override authProvider: AuthProvider;
}
18 changes: 9 additions & 9 deletions src/chat/application/business-chat.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Injectable, Logger } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { BusinessChatRoom } from "../../schemas/business-chat-room.entity";
import { IChatService } from "./chat.interface";
import { UserDto } from "../../auth/presentation/user.dto";
import { ChatRoomDto } from "../presentation/chat.dto";
import { toDto } from "../../common/function/util.function";
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { BusinessChatRoom } from '../../schemas/business-chat-room.entity';
import { IChatService } from './chat.interface';
import { UserDto } from '../../auth/presentation/user.dto';
import { ChatRoomDto } from '../presentation/chat.dto';
import { toDto } from '../../common/function/util.function';

@Injectable()
export class BusinessChatService implements IChatService {
Expand Down Expand Up @@ -40,7 +40,7 @@ export class BusinessChatService implements IChatService {
businessId: number,
chatRoomId: number,
): Promise<BusinessChatRoom> {
return await this.businessChatRoomRepository.findOne({
return await this.businessChatRoomRepository.findOneOrFail({
where: { businessId, chatRoomId },
});
}
Expand Down
Loading

0 comments on commit 1973505

Please sign in to comment.