Skip to content

Commit

Permalink
Merge pull request #365 from boostcampwm2023/server/feature/361
Browse files Browse the repository at this point in the history
Auth, Music, Playlist 에 트랜잭션 추가
  • Loading branch information
sk000801 authored Jan 9, 2024
2 parents eec5462 + bd1be69 commit cfe5056
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 75 deletions.
7 changes: 6 additions & 1 deletion server/src/auth/auth.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { getRepositoryToken } from '@nestjs/typeorm';
import { User } from 'src/entity/user.entity';
import { Repository } from 'typeorm';
import { Repository, DataSource } from 'typeorm';
import { JwtModule, JwtService } from '@nestjs/jwt';
import { Playlist } from 'src/entity/playlist.entity';
import { Music } from 'src/entity/music.entity';
Expand All @@ -16,6 +16,7 @@ describe('AuthController', () => {
let service: AuthService;
let jwtModule: JwtModule;
let userRepository: Repository<User>;
let mockDataSource: jest.Mocked<DataSource>;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
Expand All @@ -40,6 +41,10 @@ describe('AuthController', () => {
provide: getRepositoryToken(Music_Playlist),
useClass: Repository,
},
{
provide: DataSource,
useValue: mockDataSource,
},
],
}).compile();

Expand Down
7 changes: 6 additions & 1 deletion server/src/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AuthService } from './auth.service';
import { Repository } from 'typeorm';
import { Repository, DataSource } from 'typeorm';
import { getRepositoryToken } from '@nestjs/typeorm';
import { User } from 'src/entity/user.entity';
import { JwtModule, JwtService } from '@nestjs/jwt';
Expand All @@ -15,6 +15,7 @@ describe('AuthService', () => {
let jwtModule: JwtModule;
let userRepository: Repository<User>;
let playlistService: PlaylistService;
let mockDataSource: jest.Mocked<DataSource>;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
Expand All @@ -38,6 +39,10 @@ describe('AuthService', () => {
useClass: Repository,
},
PlaylistService,
{
provide: DataSource,
useValue: mockDataSource,
},
],
}).compile();

Expand Down
81 changes: 54 additions & 27 deletions server/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ERROR_CODE } from 'src/config/errorCode.enum';
import { UserCreateDto } from 'src/dto/userCreate.dto';
import { User } from 'src/entity/user.entity';
import { HTTP_STATUS_CODE } from 'src/httpStatusCode.enum';
import { Repository } from 'typeorm';
import { Repository, DataSource } from 'typeorm';
import { v4 as uuid } from 'uuid';

@Injectable()
Expand All @@ -15,6 +15,7 @@ export class AuthService {
constructor(
@InjectRepository(User) private userRepository: Repository<User>,
private jwtService: JwtService,
private readonly dataSource: DataSource,
) {}

async login(email: string): Promise<{ accessToken: string }> {
Expand All @@ -27,14 +28,14 @@ export class AuthService {
const accessToken = this.jwtService.sign(payload);

return { accessToken };
} else {
this.logger.error(`auth.service - login : NOT_EXIST_USER`);
throw new CatchyException(
'NOT_EXIST_USER',
HTTP_STATUS_CODE['WRONG_TOKEN'],
ERROR_CODE.NOT_EXIST_USER,
);
}

this.logger.error(`auth.service - login : NOT_EXIST_USER`);
throw new CatchyException(
'NOT_EXIST_USER',
HTTP_STATUS_CODE['WRONG_TOKEN'],
ERROR_CODE.NOT_EXIST_USER,
);
}

async signup(userCreateDto: UserCreateDto): Promise<{ accessToken: string }> {
Expand All @@ -49,24 +50,38 @@ export class AuthService {
ERROR_CODE.ALREADY_EXIST_EMAIL,
);
}
if (email) {
const newUser: User = this.userRepository.create({
user_id: uuid(),
nickname,
photo: null,
user_email: email,
created_at: new Date(),
});
await this.userRepository.save(newUser);

return this.login(email);

const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.startTransaction();

try {
if (email) {
const newUser: User = this.userRepository.create({
user_id: uuid(),
nickname,
photo: null,
user_email: email,
created_at: new Date(),
});

await queryRunner.manager.save(newUser);

await queryRunner.commitTransaction();

return await this.login(email);
}

this.logger.error(`auth.service - signup : WRONG_TOKEN`);
throw new CatchyException(
'WRONG_TOKEN',
HTTP_STATUS_CODE.WRONG_TOKEN,
ERROR_CODE.WRONG_TOKEN,
);
} catch {
await queryRunner.rollbackTransaction();
} finally {
await queryRunner.release();
}
this.logger.error(`auth.service - signup : WRONG_TOKEN`);
throw new CatchyException(
'WRONG_TOKEN',
HTTP_STATUS_CODE.WRONG_TOKEN,
ERROR_CODE.WRONG_TOKEN,
);
}

async getGoogleEmail(googleIdToken: string): Promise<string> {
Expand All @@ -84,6 +99,7 @@ export class AuthService {
ERROR_CODE.EXPIRED_TOKEN,
);
}

return userInfo.email;
}

Expand All @@ -100,7 +116,18 @@ export class AuthService {
}

async deleteUser(user: User): Promise<{ userId: string }> {
await this.userRepository.delete(user.user_id);
return { userId: user.user_id };
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.startTransaction();

try {
await queryRunner.manager.remove(user);
await queryRunner.commitTransaction();

return { userId: user.user_id };
} catch {
await queryRunner.rollbackTransaction();
} finally {
await queryRunner.release();
}
}
}
10 changes: 9 additions & 1 deletion server/src/music/music.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { UploadService } from 'src/upload/upload.service';
import { NcloudConfigService } from 'src/config/ncloud.config';
import { ConfigService } from '@nestjs/config';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { DataSource, Repository } from 'typeorm';
import { Music } from 'src/entity/music.entity';
import { musicCreateInfo, user } from 'test/constants/music.mockData';
import { MusicController } from './music.controller';
Expand All @@ -27,6 +27,7 @@ describe('UploadController', () => {
let authService: AuthService;
let musicRepository: Repository<Music>;
let mockJwtStrategy = { validate: () => user };
let mockDataSource: jest.Mocked<DataSource>;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
Expand All @@ -49,6 +50,10 @@ describe('UploadController', () => {
provide: getRepositoryToken(User),
useClass: Repository,
},
{
provide: DataSource,
useValue: mockDataSource,
},
],
})
.overrideProvider(JwtStrategy)
Expand All @@ -62,6 +67,9 @@ describe('UploadController', () => {
musicController = module.get<MusicController>(MusicController);
musicService = module.get<MusicService>(MusicService);
musicRepository = module.get(getRepositoryToken(Music));
mockDataSource = {
createQueryRunner: jest.fn(),
} as unknown as jest.Mocked<DataSource>;

app = module.createNestApplication();
await app.init();
Expand Down
16 changes: 15 additions & 1 deletion server/src/music/music.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { UploadService } from 'src/upload/upload.service';
import { NcloudConfigService } from 'src/config/ncloud.config';
import { ConfigService } from '@nestjs/config';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { DataSource, Repository } from 'typeorm';
import { Music } from 'src/entity/music.entity';
import { MusicCreateDto } from 'src/dto/musicCreate.dto';
import { CatchyException } from 'src/config/catchyException';
Expand All @@ -24,6 +24,7 @@ describe('UploadController', () => {
let cloudService: NcloudConfigService;
let configService: ConfigService;
let mockRepository: jest.Mocked<Repository<Music>>;
let mockDataSource: jest.Mocked<DataSource>;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
Expand All @@ -43,12 +44,24 @@ describe('UploadController', () => {
provide: getRepositoryToken(Recent_Played),
useClass: Repository,
},
{
provide: DataSource,
useValue: mockDataSource,
},
],
}).compile();

configService = module.get<ConfigService>(ConfigService);
cloudService = module.get<NcloudConfigService>(NcloudConfigService);
uploadService = module.get<UploadService>(UploadService);
mockDataSource = {
createQueryRunner: jest.fn().mockResolvedValue({
startTransaction: jest.fn(),
commitTransaction: jest.fn(),
rollbackTransaction: jest.fn(),
release: jest.fn(),
}),
} as unknown as jest.Mocked<DataSource>;
mockRepository = {
create: jest.fn(),
save: jest.fn(),
Expand All @@ -57,6 +70,7 @@ describe('UploadController', () => {
mockRepository,
uploadService,
cloudService,
mockDataSource,
);
});

Expand Down
42 changes: 23 additions & 19 deletions server/src/music/music.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable, Logger } from '@nestjs/common';
import { HTTP_STATUS_CODE } from 'src/httpStatusCode.enum';
import { Repository } from 'typeorm';
import { Repository, DataSource } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { MusicCreateDto } from 'src/dto/musicCreate.dto';
import { Music } from 'src/entity/music.entity';
Expand All @@ -19,6 +19,7 @@ export class MusicService {
@InjectRepository(Music) private musicRepository: Repository<Music>,
private uploadService: UploadService,
private readonly ncloudConfigService: NcloudConfigService,
private readonly dataSource: DataSource,
) {
this.objectStorage = ncloudConfigService.createObjectStorageOption();
}
Expand All @@ -35,24 +36,21 @@ export class MusicService {
musicCreateDto: MusicCreateDto,
user_id: string,
): Promise<string> {
try {
const {
music_id,
title,
cover,
file: music_file,
genre,
} = musicCreateDto;
const { music_id, title, cover, file: music_file, genre } = musicCreateDto;

if (!this.isValidGenre(genre)) {
this.logger.error(`music.service - createMusic : NOT_EXIST_GENRE`);
throw new CatchyException(
'NOT_EXIST_GENRE',
HTTP_STATUS_CODE.BAD_REQUEST,
ERROR_CODE.NOT_EXIST_GENRE,
);
}
if (!this.isValidGenre(genre)) {
this.logger.error(`music.service - createMusic : NOT_EXIST_GENRE`);
throw new CatchyException(
'NOT_EXIST_GENRE',
HTTP_STATUS_CODE.BAD_REQUEST,
ERROR_CODE.NOT_EXIST_GENRE,
);
}

const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.startTransaction();

try {
const newMusic: Music = this.musicRepository.create({
music_id,
title,
Expand All @@ -63,10 +61,14 @@ export class MusicService {
user: { user_id },
});

const savedMusic: Music = await this.musicRepository.save(newMusic);
await queryRunner.manager.save(newMusic);

return savedMusic.music_id;
await queryRunner.commitTransaction();

return music_id;
} catch (err) {
await queryRunner.rollbackTransaction();

if (err instanceof CatchyException) {
throw err;
}
Expand All @@ -77,6 +79,8 @@ export class MusicService {
HTTP_STATUS_CODE.SERVER_ERROR,
ERROR_CODE.SERVICE_ERROR,
);
} finally {
await queryRunner.release();
}
}

Expand Down
Loading

0 comments on commit cfe5056

Please sign in to comment.