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

3주차 Backend API 구현 #132

Merged
merged 44 commits into from
Nov 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
5b30d30
test: Server Jest
NaayoungKwon Nov 21, 2022
8d7f8fe
refactor: auth.dto 를 sign-in.dto, sign-up.dto 로 분할
soomanbaek Nov 21, 2022
0dda191
feat: create community #86
NaayoungKwon Nov 21, 2022
8023619
test: createCommunity test
NaayoungKwon Nov 21, 2022
27c10f0
refactor: access token 가져와서 _id 확인
NaayoungKwon Nov 22, 2022
a3c11c8
feat: 커뮤니티에 사용자 추가 controller 구현
NaayoungKwon Nov 22, 2022
8589e0b
feat: 커뮤니티에 사용자 추가 service layer 구현 #95
NaayoungKwon Nov 22, 2022
0d2a8a0
feat: 커뮤니티 수정 시 자동 updatedAt 갱신하도록 스키마 수정 #95
NaayoungKwon Nov 22, 2022
181c52b
refactor: 커뮤니티 update -> findAndUpdate 변경 #96
NaayoungKwon Nov 22, 2022
68fab2a
fix: 충돌 해결
NaayoungKwon Nov 22, 2022
5dbe7b4
refactor: 사용자있는지 검증 skip
NaayoungKwon Nov 22, 2022
d6829fe
feat: 커뮤니티 사용자 추가 시 사용자 document update #95
NaayoungKwon Nov 22, 2022
0c769b6
fix: cors 해결
NaayoungKwon Nov 23, 2022
1115f82
fix: 충돌 병합
NaayoungKwon Nov 22, 2022
3e8e34d
fix: cherry fix 충돌 병합
NaayoungKwon Nov 22, 2022
c34dc7c
feat: 커뮤니티 정보 수정 service layer 구현 #96
NaayoungKwon Nov 22, 2022
d14969a
todo: error response
NaayoungKwon Nov 22, 2022
05236b0
refactor: 사용자있는지 검증 skip
NaayoungKwon Nov 22, 2022
5097443
refactor: dto index.ts로 번들링
NaayoungKwon Nov 23, 2022
ac25bd3
feat: 커뮤니티 삭제 시 deletedAt 변경 #110
NaayoungKwon Nov 23, 2022
5f6fef1
fix: guard에서 사용자 정보 확인 후 _id ObjectId -> string 변경
NaayoungKwon Nov 23, 2022
4eacf1f
feat: 커뮤니티 삭제 시 사용자 document에서도 삭제 #110
NaayoungKwon Nov 23, 2022
e51b4f8
refactor: throw error 로 일원화
NaayoungKwon Nov 23, 2022
9357a67
feat: 내가 속한 커뮤니티 정보 받아오기 #115
NaayoungKwon Nov 23, 2022
8d88b24
feat: users schema의 community innerschema 수정 #115
NaayoungKwon Nov 24, 2022
46569bc
feat: channel repository 생성 및 channel moduel에 추가
soomanbaek Nov 23, 2022
d1dc82c
feat: create-channel.dto 생성
soomanbaek Nov 23, 2022
a69ef30
fix: channel.schema 수정
soomanbaek Nov 23, 2022
60dae8d
feat: 채널 생성 로직 구현 중
soomanbaek Nov 23, 2022
dab6911
feat: 채널 생성 시, 유저 도큐먼트에 채널 추가
soomanbaek Nov 24, 2022
5d6188d
feat: 커뮤니티 목록에 채널 업데이트 및 주석 추가
soomanbaek Nov 24, 2022
325e8a9
fix: 에러 처리
soomanbaek Nov 24, 2022
969486d
fix: channel.schema 수정
soomanbaek Nov 24, 2022
b2eea18
refactor: User컬렉션 Community필드에 채널 추가해주는 형식을 만드는 것을 모듈화
soomanbaek Nov 24, 2022
3131d03
refactor: 파일 이름 오타 수정
NaayoungKwon Nov 24, 2022
185e8d2
refactor: 사용자 스키마 주석 삭제
NaayoungKwon Nov 24, 2022
eeee5a7
refactor: 파일 이름 오타 수정
NaayoungKwon Nov 24, 2022
0c65e48
refactor: 사용자 추가 controller layer 응답 값 변경 #95
NaayoungKwon Nov 24, 2022
b732d65
refactor: 사용자 document에 커뮤니티 추가 시 객체 생성 #86, #95
NaayoungKwon Nov 24, 2022
5aeae6b
feat: 커뮤니티에 속한 사용자 추가 로직 추가 #95
NaayoungKwon Nov 24, 2022
431b5f6
feat: 커뮤니티 수정 요청 사용자의 권한 확인 #95
NaayoungKwon Nov 24, 2022
f3d5a2e
refactor: 중복 로직 함수화 #95
NaayoungKwon Nov 24, 2022
74dc091
feat: 자신의 커뮤니티 받아오기 controller layer #115
NaayoungKwon Nov 24, 2022
d13a577
feat: 자신의 커뮤니티 받아오기 service layer 1차 #115
NaayoungKwon Nov 24, 2022
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
66 changes: 66 additions & 0 deletions .github/workflows/server_jest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs

name: Server Jest

on:
push:
branches: [ "main", "dev","dev-be" ]
paths: 'server/**'
pull_request:
branches: [ "main", "dev","dev-be" ]
paths: 'server/**'

jobs:
build:
runs-on: ubuntu-latest
steps:
# 해당 저장소의 코드를 가져옵니다.
- name: Checkout
uses: actions/checkout@v2

# Node 18 버전을 사용합니다.
- name: Install node
uses: actions/setup-node@v2
with:
node-version: '18'
cache: 'npm'

# yarn을 설치합니다.
- name: Install Yarn
run: npm install yarn

# 설치된 yarn을 통해 패키지를 설치합니다.
- name: Install dependencies
run: yarn install

# 테스트 수행과 그 테스트 결과를 xml파일로 생성합니다.
- name: Run tests
run: yarn server-test | tee ./coverage.txt

# 테스트 결과를 담은 xml 파일을 레포트로 변환합니다.
- name: Test Report
uses: dorny/test-reporter@v1
if: success() || failure() # run this step even if previous step failed
with:
name: test-results
path: server/junit.xml
fail-on-error: 'false'
reporter: jest-junit # Format of test results
token: ${{ secrets.GITHUB_TOKEN }}

- name: Jest Coverage Comment
uses: MishaKav/jest-coverage-comment@main
with:
coverage-path: ./coverage.txt
coverage-summary-path: ./server/coverage/coverage-final.json
junitxml-path: ./server/junit.xml
- name: build 실패 시 Slack 알림
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
author_name: 백엔드 빌드 실패 알림
fields: repo, message, commit, author, action, eventName, ref, workflow, job, took
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_FAIL_WEBHOOK_URL }}
if: failure()
8 changes: 8 additions & 0 deletions server/__mock__/community.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { CreateCommunityDto } from '@api/src/community/dto/create-community.dto';

export const communityDto1 = {
name: 'asnity commu',
managerId: '63734af9e62b37012c73e399',
description: 'test description',
profileUrl: 'test profileUrl',
} as CreateCommunityDto;
3 changes: 0 additions & 3 deletions server/apps/api/src/api.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import { UserModule } from './user/user.module';
import * as winston from 'winston';
import { utilities as nestWinstonModuleUtilities, WinstonModule } from 'nest-winston';
import { AuthModule } from './auth/auth.module';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { SentryInterceptor } from '../../webhook.interceptor';
import { RavenInterceptor, RavenModule } from 'nest-raven';

@Module({
imports: [
Expand Down
3 changes: 2 additions & 1 deletion server/apps/api/src/auth/dto/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './auth.dto';
export * from './sign-in.dto';
export * from './sign-up.dto';
11 changes: 11 additions & 0 deletions server/apps/api/src/auth/dto/sign-in.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator';

export class SignInDto {
@IsEmail()
@IsNotEmpty()
id: string;

@IsString()
@MinLength(8)
password: string;
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
import { IsEmail, IsNotEmpty, IsString, Length, MinLength } from 'class-validator';

export class SignInDto {
@IsEmail()
@IsNotEmpty()
id: string;

@IsString()
@MinLength(8)
password: string;
}

export class SignUpDto {
@IsEmail()
@IsNotEmpty()
Expand Down
2 changes: 1 addition & 1 deletion server/apps/api/src/auth/strategy/jwt-access.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ export class JwtAccessStrategy extends PassportStrategy(Strategy, 'jwt-access-to
throw new ForbiddenException('잘못된 요청입니다.');
}
delete user.password;
return user;
return { ...user, _id: user._id.toString() };
}
}
29 changes: 26 additions & 3 deletions server/apps/api/src/channel/channel.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
import { Controller } from '@nestjs/common';
import { Body, Controller, Inject, LoggerService, Post, Req, UseGuards } from '@nestjs/common';
import { ChannelService } from '@api/src/channel/channel.service';
import { JwtAccessGuard } from '@api/src/auth/guard';
import { CreateChannelDto } from '@api/src/channel/dto';
import { responseForm } from '@utils/responseForm';
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';

@Controller('channel')
export class ChannelController {}
@Controller('api/channel')
export class ChannelController {
constructor(
@Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService,
private channelService: ChannelService,
) {}

@Post()
@UseGuards(JwtAccessGuard)
async createChannel(@Body() createChannelDto: CreateChannelDto, @Req() req: any) {
const _id = req.user._id;
try {
await this.channelService.createChannel({ ...createChannelDto, managerId: _id });
return responseForm(200, { message: '채널 생성 성공!' });
} catch (error) {
this.logger.error(JSON.stringify(error.response));
throw error;
}
}
}
15 changes: 14 additions & 1 deletion server/apps/api/src/channel/channel.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import { Module } from '@nestjs/common';
import { ChannelController } from './channel.controller';
import { ChannelService } from './channel.service';
import { MongooseModule } from '@nestjs/mongoose';
import { ChannelRepository } from '@repository/channel.repository';
import { ChannelSchema } from '@schemas/channel.schema';
import { Channel } from 'diagnostics_channel';
import { CommunityRepository } from '@repository/community.repository';
import { CommunityModule } from '@community/community.module';
import { UserRepository } from '@repository/user.repository';
import { UserModule } from '@user/user.module';

@Module({
imports: [
MongooseModule.forFeature([{ name: Channel.name, schema: ChannelSchema }]),
CommunityModule,
UserModule,
],
controllers: [ChannelController],
providers: [ChannelService]
providers: [ChannelService, ChannelRepository, CommunityRepository, UserRepository],
})
export class ChannelModule {}
39 changes: 37 additions & 2 deletions server/apps/api/src/channel/channel.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,39 @@
import { Injectable } from '@nestjs/common';
import { BadRequestException, Injectable } from '@nestjs/common';
import { ChannelRepository } from '@repository/channel.repository';
import { CreateChannelDto } from '@api/src/channel/dto';
import { CommunityRepository } from '@repository/community.repository';
import { UserRepository } from '@repository/user.repository';
import { addChannelToUserForm } from '@utils/addObjectForm';

@Injectable()
export class ChannelService {}
export class ChannelService {
constructor(
private readonly channelRepository: ChannelRepository,
private readonly communityRepository: CommunityRepository,
private readonly userRepository: UserRepository,
) {}

async createChannel(createChannelDto: CreateChannelDto) {
// 자신이 속한 커뮤니티 찾기
try {
const community = await this.communityRepository.findById(createChannelDto.communityId);

// 채널 생성
const channel = await this.channelRepository.create({
...createChannelDto,
users: [createChannelDto.managerId],
});

// 커뮤니티 목록에 채널 업데이트
await this.communityRepository.addArrAtArr({ _id: community.id }, 'channels', [
channel._id.toString(),
]);

// 유저 목록에 자신이 속한 채널 업데이트
const newChannel = addChannelToUserForm(community._id, channel._id);
await this.userRepository.updateObject({ _id: createChannelDto.managerId }, newChannel);
} catch (error) {
throw new BadRequestException('채널 생성 중 오류 발생!');
}
}
}
37 changes: 37 additions & 0 deletions server/apps/api/src/channel/dto/create-channel.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { IsBoolean, IsNotEmpty, IsOptional, IsString, Length } from 'class-validator';
import { Transform } from 'class-transformer';

export class CreateChannelDto {
@IsString()
@IsNotEmpty()
communityId: string;

@IsString()
@Length(2, 20)
@IsNotEmpty()
name: string;

@IsString()
@IsOptional()
managerId: string;

@IsString()
@IsOptional()
description: string;

@IsString()
@IsOptional()
profileUrl: string;

@IsString()
@IsNotEmpty()
type: 'Channel' | 'DM';

@IsBoolean()
@IsNotEmpty()
@Transform(({ value }) => value === 'true')
isPrivate: boolean;

@IsOptional()
users: string[];
}
1 change: 1 addition & 0 deletions server/apps/api/src/channel/dto/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './create-channel.dto';
106 changes: 103 additions & 3 deletions server/apps/api/src/community/community.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,104 @@
import { Controller } from '@nestjs/common';
import {
Body,
Controller,
Delete,
Get,
Inject,
LoggerService,
Param,
Patch,
Post,
Req,
UseGuards,
} from '@nestjs/common';
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
import { CommunityService } from '@api/src/community/community.service';
import { responseForm } from '@utils/responseForm';
import { JwtAccessGuard } from '@api/src/auth/guard';
import {
CreateCommunityDto,
AppendUsersToCommunityDto,
ModifyCommunityDto,
DeleteCommunityDto,
} from './dto';

@Controller('community')
export class CommunityController {}
@Controller('api/community')
export class CommunityController {
constructor(
@Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService,
private communityService: CommunityService,
) {}

@Get()
@UseGuards(JwtAccessGuard)
async getCommunities(@Req() req: any) {
try {
const result = await this.communityService.getCommunities(req.user._doc);
return responseForm(200, result);
} catch (error) {
this.logger.error(JSON.stringify(error.response));
throw error;
}
}

@Post()
@UseGuards(JwtAccessGuard)
async crateCommunity(@Body() createCommunityDto: CreateCommunityDto, @Req() req: any) {
try {
const _id = req.user._id;
const result = await this.communityService.createCommunity({
managerId: _id,
...createCommunityDto,
});
return responseForm(200, result);
} catch (error) {
this.logger.error(JSON.stringify(error.response));
throw error;
}
}

@Post('participants')
@UseGuards(JwtAccessGuard)
async appendParticipantsToCommunity(
@Body() appendUsersToCommunityDto: AppendUsersToCommunityDto,
@Req() req: any,
) {
try {
await this.communityService.appendParticipantsToCommunity(
req.user,
appendUsersToCommunityDto,
);
return responseForm(200, { message: '커뮤니티 사용자 추가 완료' });
} catch (error) {
this.logger.error(JSON.stringify(error.response));
throw error;
}
}

@Patch('settings')
@UseGuards(JwtAccessGuard)
async modifyCommunitySetting(@Body() modifyCommunityDto: ModifyCommunityDto, @Req() req: any) {
try {
const _id = req.user._id;
await this.communityService.modifyCommunity({ ...modifyCommunityDto, managerId: _id });
return responseForm(200, { message: '커뮤니티 정보 수정 완료' });
} catch (error) {
this.logger.error(JSON.stringify(error.response));
throw error;
}
}

@Delete(':_id')
@UseGuards(JwtAccessGuard)
async deleteCommunity(@Param('_id') community_id: string, @Req() req: any) {
try {
const managerId = req.user._id;
const deleteCommunityDto: DeleteCommunityDto = { managerId, community_id };
await this.communityService.deleteCommunity(deleteCommunityDto);
return responseForm(200, { message: '커뮤니티 삭제 성공' });
} catch (error) {
this.logger.error(JSON.stringify(error.response));
throw error;
}
}
}
12 changes: 11 additions & 1 deletion server/apps/api/src/community/community.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { Module } from '@nestjs/common';
import { CommunityController } from './community.controller';
import { CommunityService } from './community.service';
import { MongooseModule } from '@nestjs/mongoose';
import { Community, CommunitySchema } from '@schemas/community.schema';
import { CommunityRepository } from '@repository/community.repository';
import { UserRepository } from '@repository/user.repository';
import { UserModule } from '@user/user.module';

@Module({
imports: [
MongooseModule.forFeature([{ name: Community.name, schema: CommunitySchema }]),
UserModule,
],
controllers: [CommunityController],
providers: [CommunityService],
providers: [CommunityService, CommunityRepository, UserRepository],
exports: [MongooseModule],
})
export class CommunityModule {}
Loading