Skip to content

Commit

Permalink
Merge pull request #45 from DevKor-github/refactor/exception
Browse files Browse the repository at this point in the history
Refactor/exception
  • Loading branch information
astorverse authored Jul 30, 2024
2 parents 7788a97 + 2e00720 commit dfc6e55
Show file tree
Hide file tree
Showing 97 changed files with 2,623 additions and 1,011 deletions.
23 changes: 3 additions & 20 deletions src/APIs/agreements/agreements.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,16 @@ import {
UseGuards,
} from '@nestjs/common';
import { AgreementsService } from './agreements.service';
import {
ApiCookieAuth,
ApiCreatedResponse,
ApiOkResponse,
ApiOperation,
ApiTags,
} from '@nestjs/swagger';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { AuthGuardV2 } from 'src/common/guards/auth.guard';
import { Request } from 'express';
import { AgreementGetContractRequestDto } from './dtos/request/agreement-get-contract-request.dto';
import { AgreementCreateRequestDto } from './dtos/request/agreement-create-request.dto';
import { AgreementDto } from './dtos/common/agreement.dto';
import { AgreementPatchRequestDto } from './dtos/request/agreement-patch-request.dto';
import { AgreementsDocs } from './docs/agreements-docs.decorator';

@AgreementsDocs
@ApiTags('유저 API')
@Controller('users')
export class AgreementsController {
Expand All @@ -36,9 +32,6 @@ export class AgreementsController {
return data;
}

@ApiOperation({ summary: '온보딩 동의' })
@ApiCookieAuth()
@ApiCreatedResponse({ type: AgreementDto })
@UseGuards(AuthGuardV2)
@Post('me/agreement')
async agree(
Expand All @@ -49,20 +42,13 @@ export class AgreementsController {
return await this.svc_agreements.createAgreement({ ...body, userId });
}

@ApiOperation({ summary: '로그인된 유저의 온보딩 동의 내용들을 fetch' })
@ApiCookieAuth()
@ApiOkResponse({ type: [AgreementDto] })
@UseGuards(AuthGuardV2)
@Get('me/agreements')
async fetchAgreements(@Req() req: Request): Promise<AgreementDto[]> {
const userId = req.user.userId;
return await this.svc_agreements.findAgreements({ userId });
}

@ApiTags('어드민 API')
@ApiOperation({ summary: '[어드민용] 특정 유저의 온보딩 동의 내용을 조회' })
@ApiCookieAuth()
@ApiOkResponse({ type: [AgreementDto] })
@UseGuards(AuthGuardV2)
@Get('admin/:userId/agreements')
async fetchAgreementAdmin(
Expand All @@ -76,9 +62,6 @@ export class AgreementsController {
});
}

@ApiOperation({ summary: '동의 여부를 수정' })
@ApiCookieAuth()
@ApiOkResponse({ type: AgreementDto })
@UseGuards(AuthGuardV2)
@Patch('me/agreement/:agreementId')
async patchAgreement(
Expand Down
30 changes: 22 additions & 8 deletions src/APIs/agreements/agreements.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
ForbiddenException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { AgreementsRepository } from './agreements.repository';
import {
IAgreementsServiceCreate,
Expand All @@ -15,6 +11,9 @@ import path from 'path';
import fs from 'fs';
import { UsersValidateService } from '../users/services/users-validate-service';
import { AgreementDto } from './dtos/common/agreement.dto';
import { MergeExceptionMetadata } from '@/common/decorators/merge-exception-metadata.decorator';
import { BlccuException, EXCEPTIONS } from '@/common/blccu-exception';
import { ExceptionMetadata } from '@/common/decorators/exception-metadata.decorator';

@Injectable()
export class AgreementsService {
Expand All @@ -23,6 +22,9 @@ export class AgreementsService {
private readonly svc_usersValidate: UsersValidateService,
) {}

@MergeExceptionMetadata([
{ service: UsersValidateService, methodName: 'adminCheck' },
])
async adminCheck({ userId }: IAgreementsServiceUserId): Promise<void> {
await this.svc_usersValidate.adminCheck({ userId });
}
Expand Down Expand Up @@ -53,6 +55,15 @@ export class AgreementsService {
return await this.repo_agreements.findOne({ where: { id: agreementId } });
}

@ExceptionMetadata([EXCEPTIONS.AGREEMENT_NOT_FOUND])
async existCheck({
agreementId,
}: IAgreementsServiceId): Promise<AgreementDto> {
const data = await this.findAgreement({ agreementId });
if (!data) throw new BlccuException('AGREEMENT_NOT_FOUND');
return data;
}

async findAgreements({
userId,
}: IAgreementsServiceUserId): Promise<AgreementDto[]> {
Expand All @@ -61,14 +72,17 @@ export class AgreementsService {
});
}

@MergeExceptionMetadata([
{ service: AgreementsService, methodName: 'existCheck' },
])
@ExceptionMetadata([EXCEPTIONS.NOT_THE_OWNER])
async patchAgreement({
userId,
agreementId,
isAgreed,
}: IAgreementsServicePatchAgreement): Promise<AgreementDto> {
const data = await this.findAgreement({ agreementId });
if (!data) throw new NotFoundException('데이터를 찾을 수 없습니다.');
if (data.userId != userId) throw new ForbiddenException('권한이 없습니다.');
const data = await this.existCheck({ agreementId });
if (data.userId != userId) throw new BlccuException('NOT_THE_OWNER');
// if(data.agreementType != AgreementType.MARKETING_CONSENT)
data.isAgreed = isAgreed;
return await this.repo_agreements.save(data);
Expand Down
59 changes: 59 additions & 0 deletions src/APIs/agreements/docs/agreements-docs.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { MethodNames } from '@/common/types/method';
import { AgreementsController } from '../agreements.controller';
import { applyDocs } from '@/utils/docs.utils';
import {
ApiCreatedResponse,
ApiOkResponse,
ApiOperation,
ApiTags,
} from '@nestjs/swagger';
import { AgreementDto } from '../dtos/common/agreement.dto';
import { ApiResponseFromMetadata } from '@/common/decorators/api-response-from-metadata.decorator';
import { AgreementsService } from '../agreements.service';
import { ApiAuthResponse } from '@/common/decorators/api-auth-response.dto';

type AgreementsEndpoints = MethodNames<AgreementsController>;

const AgreementsDocsMap: Record<AgreementsEndpoints, MethodDecorator[]> = {
getContract: [
ApiOperation({ summary: 'contract fetch' }),
ApiResponseFromMetadata([
{ service: AgreementsService, methodName: 'findContract' },
]),
],
agree: [
ApiOperation({ summary: '온보딩 동의' }),
ApiAuthResponse(),
ApiCreatedResponse({ type: AgreementDto }),
ApiResponseFromMetadata([
{ service: AgreementsService, methodName: 'createAgreement' },
]),
],
fetchAgreements: [
ApiOperation({ summary: '로그인된 유저의 온보딩 동의 내용들을 fetch' }),
ApiOkResponse({ type: [AgreementDto] }),
ApiAuthResponse(),
ApiResponseFromMetadata([
{ service: AgreementsService, methodName: 'findAgreements' },
]),
],
fetchAgreementAdmin: [
ApiTags('어드민 API'),
ApiOperation({ summary: '[어드민용] 특정 유저의 온보딩 동의 내용을 조회' }),
ApiAuthResponse(),
ApiOkResponse({ type: [AgreementDto] }),
ApiResponseFromMetadata([
{ service: AgreementsService, methodName: 'findAgreements' },
]),
],
patchAgreement: [
ApiOperation({ summary: '동의 여부를 수정' }),
ApiAuthResponse(),
ApiOkResponse({ type: AgreementDto }),
ApiResponseFromMetadata([
{ service: AgreementsService, methodName: 'patchAgreement' },
]),
],
};

export const AgreementsDocs = applyDocs(AgreementsDocsMap);
47 changes: 12 additions & 35 deletions src/APIs/announcements/announcements.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,91 +3,68 @@ import {
Controller,
Delete,
Get,
HttpCode,
Param,
Patch,
Post,
Req,
UseGuards,
} from '@nestjs/common';
import { AnnouncementsService } from './announcements.service';
import {
ApiCookieAuth,
ApiCreatedResponse,
ApiOkResponse,
ApiOperation,
ApiTags,
} from '@nestjs/swagger';
import { ApiTags } from '@nestjs/swagger';
import { AuthGuardV2 } from 'src/common/guards/auth.guard';
import { Request } from 'express';
import { AnnouncementDto } from './dtos/common/announcement.dto';
import { AnnouncementPatchRequestDto } from './dtos/request/announcement-patch-request.dto';
import { AnnouncementCreateRequestDto } from './dtos/request/announcement-create-request.dto';
import { AnnouncementsDocs } from './docs/announcements-docs.decorator';

@AnnouncementsDocs
@ApiTags('공지 API')
@Controller()
export class AnnouncementsController {
constructor(private readonly announcementsService: AnnouncementsService) {}
constructor(private readonly svc_annoucements: AnnouncementsService) {}

@ApiTags('어드민 API')
@ApiOperation({ summary: '[어드민용] 공지사항 작성' })
@ApiCookieAuth()
@UseGuards(AuthGuardV2)
@ApiCreatedResponse({ type: AnnouncementDto })
@Post('users/admin/anmts')
@HttpCode(201)
async createAnmt(
async createAnnouncement(
@Req() req: Request,
@Body() body: AnnouncementCreateRequestDto,
): Promise<AnnouncementDto> {
const userId = req.user.userId;
return await this.announcementsService.createAnnoucement({
return await this.svc_annoucements.createAnnoucement({
...body,
userId,
});
}

@ApiOperation({ summary: '공지사항 조회' })
@ApiOkResponse({ type: [AnnouncementDto] })
@Get('anmts')
async fetchAnmts(): Promise<AnnouncementDto[]> {
return await this.announcementsService.getAnnouncements();
async getAnnouncements(): Promise<AnnouncementDto[]> {
return await this.svc_annoucements.getAnnouncements();
}

@ApiTags('어드민 API')
@ApiOperation({ summary: '[어드민용] 공지사항 수정' })
@ApiCookieAuth()
@ApiOkResponse({ type: AnnouncementDto })
@UseGuards(AuthGuardV2)
@Patch('users/admin/anmts/:announcementId')
async patchAnmt(
async patchAnnouncement(
@Req() req: Request,
@Body() body: AnnouncementPatchRequestDto,
@Param('announcementId') announcementId: number,
): Promise<AnnouncementDto> {
const userId = req.user.userId;
return await this.announcementsService.patchAnnouncement({
return await this.svc_annoucements.patchAnnouncement({
...body,
announcementId,
userId,
});
}

@ApiTags('어드민 API')
@ApiOperation({
summary: '[어드민용] 공지사항 삭제',
description: 'id에 해당하는 공지사항 삭제, 삭제된 공지사항을 반환',
})
@ApiCookieAuth()
@ApiOkResponse({ type: AnnouncementDto })
@UseGuards(AuthGuardV2)
@Delete('users/admin/anmts/:announcementId')
async removeAnmt(
async removeAnnouncement(
@Req() req: Request,
@Param('announcementId') announcementId: number,
): Promise<AnnouncementDto> {
const userId = req.user.userId;
return await this.announcementsService.removeAnnouncement({
return await this.svc_annoucements.removeAnnouncement({
userId,
announcementId,
});
Expand Down
50 changes: 35 additions & 15 deletions src/APIs/announcements/announcements.service.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Announcement } from './entities/announcement.entity';
import { Repository } from 'typeorm';
import {
IAnnouncementsSerciceCreateAnnouncement,
IAnnouncementsSercicePatchAnnouncement,
IAnnouncementsSerciceRemoveAnnouncement,
IAnnouncementsServiceCreateAnnouncement,
IAnnouncementsServiceId,
IAnnouncementsServicePatchAnnouncement,
IAnnouncementsServiceRemoveAnnouncement,
} from './interfaces/announcements.service.interface';
import { UsersValidateService } from '../users/services/users-validate-service';
import { AnnouncementDto } from './dtos/common/announcement.dto';
import { MergeExceptionMetadata } from '@/common/decorators/merge-exception-metadata.decorator';
import { BlccuException, EXCEPTIONS } from '@/common/blccu-exception';
import { ExceptionMetadata } from '@/common/decorators/exception-metadata.decorator';

@Injectable()
export class AnnouncementsService {
Expand All @@ -18,11 +22,14 @@ export class AnnouncementsService {
private readonly svc_usersValidate: UsersValidateService,
) {}

@MergeExceptionMetadata([
{ service: UsersValidateService, methodName: 'adminCheck' },
])
async createAnnoucement({
userId,
title,
content,
}: IAnnouncementsSerciceCreateAnnouncement): Promise<AnnouncementDto> {
}: IAnnouncementsServiceCreateAnnouncement): Promise<AnnouncementDto> {
await this.svc_usersValidate.adminCheck({ userId });
return await this.repo_announcements.save({ title, content });
}
Expand All @@ -31,32 +38,45 @@ export class AnnouncementsService {
return await this.repo_announcements.find();
}

@ExceptionMetadata([EXCEPTIONS.ANNOUNCEMENT_NOT_FOUND])
async existCheck({
announcementId,
}: IAnnouncementsServiceId): Promise<AnnouncementDto> {
const data = await this.repo_announcements.findOne({
where: { id: announcementId },
});
if (!data) throw new BlccuException('ANNOUNCEMENT_NOT_FOUND');
return data;
}

@MergeExceptionMetadata([
{ service: UsersValidateService, methodName: 'adminCheck' },
{ service: AnnouncementsService, methodName: 'existCheck' },
])
async patchAnnouncement({
userId,
announcementId,
title,
content,
}: IAnnouncementsSercicePatchAnnouncement): Promise<AnnouncementDto> {
}: IAnnouncementsServicePatchAnnouncement): Promise<AnnouncementDto> {
await this.svc_usersValidate.adminCheck({ userId });
const anmt = await this.repo_announcements.findOne({
where: { id: announcementId },
});
if (!anmt) throw new NotFoundException('공지를 찾을 수 없습니다.');
const anmt = await this.existCheck({ announcementId });
if (title) anmt.title = title;
if (content) anmt.content = content;
await this.repo_announcements.save(anmt);
return await this.repo_announcements.findOne({ where: { id: anmt.id } });
}

@MergeExceptionMetadata([
{ service: UsersValidateService, methodName: 'adminCheck' },
{ service: AnnouncementsService, methodName: 'existCheck' },
])
async removeAnnouncement({
userId,
announcementId,
}: IAnnouncementsSerciceRemoveAnnouncement): Promise<AnnouncementDto> {
}: IAnnouncementsServiceRemoveAnnouncement): Promise<AnnouncementDto> {
await this.svc_usersValidate.adminCheck({ userId });
const anmt = await this.repo_announcements.findOne({
where: { id: announcementId },
});
if (!anmt) throw new NotFoundException('공지를 찾을 수 없습니다.');
const anmt = await this.existCheck({ announcementId });
return await this.repo_announcements.softRemove(anmt);
}
}
Loading

0 comments on commit dfc6e55

Please sign in to comment.