Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ refactor: admin 도메인 repository 함수 재사용성 향상, 테스트 코드 일관성, 최적화 #14

Merged
merged 10 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/bcrypt": "^5.0.2",
"@types/cookie-parser": "^1.4.7",
"@types/eventsource": "^1.1.15",
"@types/express": "^5.0.0",
Expand Down
8 changes: 4 additions & 4 deletions server/src/admin/controller/admin.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ export class AdminController {
@Post('/login')
@HttpCode(HttpStatus.OK)
async loginAdmin(
@Body() loginAdminDto: LoginAdminRequestDto,
@Body() loginAdminBodyDto: LoginAdminRequestDto,
@Res({ passthrough: true }) response: Response,
@Req() request: Request,
) {
await this.adminService.loginAdmin(loginAdminDto, response, request);
await this.adminService.loginAdmin(loginAdminBodyDto, response, request);
return ApiResponse.responseWithNoContent(
'로그인이 성공적으로 처리되었습니다.',
);
Expand All @@ -57,8 +57,8 @@ export class AdminController {
@ApiCreateAdmin()
@UseGuards(CookieAuthGuard)
@Post('/register')
async createAdmin(@Body() registerAdminDto: RegisterAdminRequestDto) {
await this.adminService.createAdmin(registerAdminDto);
async createAdmin(@Body() registerAdminBodyDto: RegisterAdminRequestDto) {
await this.adminService.createAdmin(registerAdminBodyDto);
return ApiResponse.responseWithNoContent(
'성공적으로 관리자 계정이 생성되었습니다.',
);
Expand Down
4 changes: 4 additions & 0 deletions server/src/admin/dto/request/login-admin.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ export class LoginAdminRequestDto {
message: '문자열을 입력해주세요',
})
password: string;

constructor(partial: Partial<LoginAdminRequestDto>) {
Object.assign(this, partial);
}
}
11 changes: 11 additions & 0 deletions server/src/admin/dto/request/register-admin.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IsString, Length, Matches } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Admin } from '../../entity/admin.entity';

const PASSWORD_REG = /^(?=.*[!@#$%^&*()_+])[A-Za-z0-9!@#$%^&*()_+]+$/;

Expand Down Expand Up @@ -32,4 +33,14 @@ export class RegisterAdminRequestDto {
message: '패스워드의 길이는 6자 이상, 60자 이하로 작성해주세요.',
})
password: string;

constructor(partial: Partial<RegisterAdminRequestDto>) {
Object.assign(this, partial);
}

toEntity() {
const admin = new Admin();
Object.assign(admin, this);
return admin;
}
}
11 changes: 0 additions & 11 deletions server/src/admin/repository/admin.repository.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
import { Injectable } from '@nestjs/common';
import { DataSource, Repository } from 'typeorm';
import { Admin } from '../entity/admin.entity';
import { RegisterAdminRequestDto } from '../dto/request/register-admin.dto';

@Injectable()
export class AdminRepository extends Repository<Admin> {
constructor(private dataSource: DataSource) {
super(Admin, dataSource.createEntityManager());
}

async createAdmin(registerAdminDto: RegisterAdminRequestDto) {
const { loginId, password } = registerAdminDto;
const admin = this.create({
loginId,
password,
});
await this.save(admin);
return admin;
}
}
17 changes: 9 additions & 8 deletions server/src/admin/service/admin.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ export class AdminService {
) {}

async loginAdmin(
loginAdminDto: LoginAdminRequestDto,
loginAdminBodyDto: LoginAdminRequestDto,
response: Response,
request: Request,
) {
const cookie = request.cookies['sessionId'];
const { loginId, password } = loginAdminDto;
const { loginId, password } = loginAdminBodyDto;

const admin = await this.adminRepository.findOne({
where: { loginId },
Expand Down Expand Up @@ -90,20 +90,21 @@ export class AdminService {
response.clearCookie('sessionId');
}

async createAdmin(registerAdminDto: RegisterAdminRequestDto) {
let { loginId, password } = registerAdminDto;

async createAdmin(registerAdminBodyDto: RegisterAdminRequestDto) {
const existingAdmin = await this.adminRepository.findOne({
where: { loginId },
where: { loginId: registerAdminBodyDto.loginId },
});

if (existingAdmin) {
throw new ConflictException('이미 존재하는 아이디입니다.');
}

const saltRounds = 10;
password = await bcrypt.hash(password, saltRounds);
registerAdminBodyDto.password = await bcrypt.hash(
registerAdminBodyDto.password,
saltRounds,
);

await this.adminRepository.createAdmin({ loginId, password });
await this.adminRepository.save(registerAdminBodyDto.toEntity());
}
}
14 changes: 8 additions & 6 deletions server/src/feed/controller/feed.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ export class FeedController {
@ApiReadFeedPagination()
@Get('')
@HttpCode(HttpStatus.OK)
async readFeedPagination(@Query() queryFeedDto: FeedPaginationRequestDto) {
async readFeedPagination(
@Query() feedPaginationQueryDto: FeedPaginationRequestDto,
) {
return ApiResponse.responseWithData(
'피드 조회 완료',
await this.feedService.readFeedPagination(queryFeedDto),
await this.feedService.readFeedPagination(feedPaginationQueryDto),
);
}

Expand Down Expand Up @@ -75,23 +77,23 @@ export class FeedController {
@ApiSearchFeedList()
@Get('search')
@HttpCode(HttpStatus.OK)
async searchFeedList(@Query() searchFeedReq: SearchFeedRequestDto) {
async searchFeedList(@Query() searchFeedQueryDto: SearchFeedRequestDto) {
return ApiResponse.responseWithData(
'검색 결과 조회 완료',
await this.feedService.searchFeedList(searchFeedReq),
await this.feedService.searchFeedList(searchFeedQueryDto),
);
}

@ApiUpdateFeedViewCount()
@Post('/:feedId')
@HttpCode(HttpStatus.OK)
async updateFeedViewCount(
@Param() params: FeedViewUpdateRequestDto,
@Param() viewUpdateParamDto: FeedViewUpdateRequestDto,
@Req() request: Request,
@Res({ passthrough: true }) response: Response,
) {
await this.feedService.updateFeedViewCount(
params.feedId,
viewUpdateParamDto,
request,
response,
);
Expand Down
23 changes: 13 additions & 10 deletions server/src/feed/service/feed.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
FeedTrendResponseDto,
} from '../dto/response/feed-pagination.dto';
import { RedisService } from '../../common/redis/redis.service';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { SearchFeedRequestDto } from '../dto/request/search-feed.dto';
import { Response, Request } from 'express';
import { cookieConfig } from '../../common/cookie/cookie.config';
Expand All @@ -29,20 +28,21 @@ import {
FeedRecentRedis,
FeedRecentResponseDto,
} from '../dto/response/recent.dto';
import { FeedViewUpdateRequestDto } from '../dto/request/feed-update.dto';

@Injectable()
export class FeedService {
constructor(
private readonly feedRepository: FeedRepository,
private readonly feedViewRepository: FeedViewRepository,
private readonly redisService: RedisService,
private readonly eventService: EventEmitter2,
) {}

async readFeedPagination(queryFeedDto: FeedPaginationRequestDto) {
const feedList =
await this.feedViewRepository.findFeedPagination(queryFeedDto);
const hasMore = this.existNextFeed(feedList, queryFeedDto.limit);
async readFeedPagination(feedPaginationQueryDto: FeedPaginationRequestDto) {
const feedList = await this.feedViewRepository.findFeedPagination(
feedPaginationQueryDto,
);
const hasMore = this.existNextFeed(feedList, feedPaginationQueryDto.limit);
if (hasMore) feedList.pop();
const lastId = this.getLastIdFromFeedList(feedList);
const newCheckFeedList = await this.checkNewFeeds(feedList);
Expand Down Expand Up @@ -94,8 +94,8 @@ export class FeedService {
);
}

async searchFeedList(searchFeedReq: SearchFeedRequestDto) {
const { find, page, limit, type } = searchFeedReq;
async searchFeedList(searchFeedQueryDto: SearchFeedRequestDto) {
const { find, page, limit, type } = searchFeedQueryDto;
const offset = (page - 1) * limit;

if (!this.validateSearchType(type)) {
Expand Down Expand Up @@ -131,15 +131,18 @@ export class FeedService {
}

async updateFeedViewCount(
feedId: number,
viewUpdateParamDto: FeedViewUpdateRequestDto,
request: Request,
response: Response,
) {
const cookie = request.headers.cookie;
const ip = this.getIp(request);
const feedId = viewUpdateParamDto.feedId;
if (ip && this.isString(ip)) {
const [feed, hasCookie, hasIpFlag] = await Promise.all([
this.feedRepository.findOne({ where: { id: feedId } }),
this.feedRepository.findOne({
where: { id: feedId },
}),
Boolean(cookie?.includes(`View_count_${feedId}=${feedId}`)),
this.redisService.sismember(`feed:${feedId}:ip`, ip),
]);
Expand Down
14 changes: 7 additions & 7 deletions server/src/rss/controller/rss.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export class RssController {

@ApiCreateRss()
@Post()
async createRss(@Body() rssRegisterDto: RssRegisterRequestDto) {
await this.rssService.createRss(rssRegisterDto);
async createRss(@Body() rssRegisterBodyDto: RssRegisterRequestDto) {
await this.rssService.createRss(rssRegisterBodyDto);
return ApiResponse.responseWithNoContent('신청이 완료되었습니다.');
}

Expand All @@ -47,8 +47,8 @@ export class RssController {
@UseGuards(CookieAuthGuard)
@Post('accept/:id')
@HttpCode(201)
async acceptRss(@Param() params: RssManagementRequestDto) {
await this.rssService.acceptRss(params.id);
async acceptRss(@Param() rssAcceptParamDto: RssManagementRequestDto) {
await this.rssService.acceptRss(rssAcceptParamDto);
return ApiResponse.responseWithNoContent('승인이 완료되었습니다.');
}

Expand All @@ -57,10 +57,10 @@ export class RssController {
@Post('reject/:id')
@HttpCode(201)
async rejectRss(
@Body() body: RejectRssRequestDto,
@Param() params: RssManagementRequestDto,
@Body() rssRejectBodyDto: RejectRssRequestDto,
@Param() rssRejectParamDto: RssManagementRequestDto,
) {
await this.rssService.rejectRss(params.id, body.description);
await this.rssService.rejectRss(rssRejectParamDto, rssRejectBodyDto);
return ApiResponse.responseWithNoContent('거절이 완료되었습니다.');
}

Expand Down
29 changes: 18 additions & 11 deletions server/src/rss/service/rss.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { FeedCrawlerService } from './feed-crawler.service';
import { RssReadResponseDto } from '../dto/response/rss-all.dto';
import { RssAcceptHistoryResponseDto } from '../dto/response/rss-accept-history.dto';
import { RssRejectHistoryResponseDto } from '../dto/response/rss-reject-history.dto';
import { RssManagementRequestDto } from '../dto/request/rss-management.dto';
import { RejectRssRequestDto } from '../dto/request/rss-reject.dto';

@Injectable()
export class RssService {
Expand All @@ -28,16 +30,16 @@ export class RssService {
private readonly feedCrawlerService: FeedCrawlerService,
) {}

async createRss(rssRegisterDto: RssRegisterRequestDto) {
async createRss(rssRegisterBodyDto: RssRegisterRequestDto) {
const [alreadyURLRss, alreadyURLBlog] = await Promise.all([
this.rssRepository.findOne({
where: {
rssUrl: rssRegisterDto.rssUrl,
rssUrl: rssRegisterBodyDto.rssUrl,
},
}),
this.rssAcceptRepository.findOne({
where: {
rssUrl: rssRegisterDto.rssUrl,
rssUrl: rssRegisterBodyDto.rssUrl,
},
}),
]);
Expand All @@ -50,17 +52,18 @@ export class RssService {
);
}

await this.rssRepository.insertNewRss(rssRegisterDto);
await this.rssRepository.insertNewRss(rssRegisterBodyDto);
}

async readAllRss() {
const rssList = await this.rssRepository.find();
return RssReadResponseDto.toResponseDtoArray(rssList);
}

async acceptRss(id: number) {
async acceptRss(rssAcceptParamDto: RssManagementRequestDto) {
const rssId = rssAcceptParamDto.id;
const rss = await this.rssRepository.findOne({
where: { id },
where: { id: rssId },
});

if (!rss) {
Expand All @@ -73,7 +76,7 @@ export class RssService {
async (manager) => {
const [rssAccept] = await Promise.all([
manager.save(RssAccept.fromRss(rss, blogPlatform)),
manager.delete(Rss, id),
manager.delete(Rss, rssId),
]);
const feeds = await this.feedCrawlerService.loadRssFeeds(
rssAccept.rssUrl,
Expand All @@ -85,9 +88,13 @@ export class RssService {
this.emailService.sendMail(rssAccept, true);
}

async rejectRss(id: number, description: string) {
async rejectRss(
rssRejectParamDto: RssManagementRequestDto,
rssRejectBodyDto: RejectRssRequestDto,
) {
const rssId = rssRejectParamDto.id;
const rss = await this.rssRepository.findOne({
where: { id },
where: { id: rssId },
});

if (!rss) {
Expand All @@ -99,12 +106,12 @@ export class RssService {
manager.remove(rss),
manager.save(RssReject, {
...rss,
description,
description: rssRejectBodyDto.description,
}),
]);
return rejectRss;
});
this.emailService.sendMail(rejectRss, false, description);
this.emailService.sendMail(rejectRss, false, rssRejectBodyDto.description);
}

async readAcceptHistory() {
Expand Down
Loading
Loading