diff --git a/server/.prettierrc b/server/.prettierrc index dcb72794..a75ce2da 100644 --- a/server/.prettierrc +++ b/server/.prettierrc @@ -1,4 +1,8 @@ { + "endOfLine": "lf", + "tabWidth": 2, + "semi": true, "singleQuote": true, - "trailingComma": "all" + "trailingComma": "all", + "printWidth": 100 } \ No newline at end of file diff --git a/server/apps/api/src/api.controller.ts b/server/apps/api/src/api.controller.ts index a2231cbb..5957b397 100644 --- a/server/apps/api/src/api.controller.ts +++ b/server/apps/api/src/api.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get } from '@nestjs/common'; import { ApiService } from './api.service'; -@Controller() +@Controller('api') export class ApiController { constructor(private readonly apiService: ApiService) {} diff --git a/server/apps/api/src/api.module.ts b/server/apps/api/src/api.module.ts index cbad3610..f351d14a 100644 --- a/server/apps/api/src/api.module.ts +++ b/server/apps/api/src/api.module.ts @@ -6,6 +6,8 @@ import { ConfigModule } from '@nestjs/config'; import { ChannelModule } from './channel/channel.module'; import { CommunityModule } from './community/community.module'; 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'; @Module({ @@ -15,6 +17,19 @@ import { AuthModule } from './auth/auth.module'; envFilePath: `config/${process.env.NODE_ENV}.env`, }), MongooseModule.forRoot(process.env.MONGODB_URL), + WinstonModule.forRoot({ + transports: [ + new winston.transports.Console({ + level: process.env.NODE_ENV === 'production' ? 'info' : 'silly', + format: winston.format.combine( + winston.format.colorize({ all: true }), + winston.format.simple(), + winston.format.timestamp(), + nestWinstonModuleUtilities.format.nestLike('Asnity', { prettyPrint: true }), + ), + }), + ], + }), UserModule, ChannelModule, CommunityModule, diff --git a/server/apps/api/src/main.ts b/server/apps/api/src/main.ts index 4736c81f..b985730d 100644 --- a/server/apps/api/src/main.ts +++ b/server/apps/api/src/main.ts @@ -1,8 +1,10 @@ import { NestFactory } from '@nestjs/core'; +import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { ApiModule } from './api.module'; async function bootstrap() { const app = await NestFactory.create(ApiModule); + app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER)); await app.listen(3000); } bootstrap(); diff --git a/server/apps/api/src/user/dto/add-following.dto.ts b/server/apps/api/src/user/dto/add-following.dto.ts new file mode 100644 index 00000000..69e0cc8b --- /dev/null +++ b/server/apps/api/src/user/dto/add-following.dto.ts @@ -0,0 +1,9 @@ +import { IsString } from 'class-validator'; + +export class AddFollowingDto { + @IsString() + myId: string; + + @IsString() + followId: string; +} diff --git a/server/apps/api/src/user/user.controller.ts b/server/apps/api/src/user/user.controller.ts index b2a29b9a..6a906f9a 100644 --- a/server/apps/api/src/user/user.controller.ts +++ b/server/apps/api/src/user/user.controller.ts @@ -1,22 +1,40 @@ -import { Body, Controller, Get, Param, Post } from '@nestjs/common'; -import { User } from '@schemas/user.schema'; +import { Body, Controller, Get, Inject, LoggerService, Param, Post } from '@nestjs/common'; import { UserService } from './user.service'; +import { AddFollowingDto } from '@user/dto/add-following.dto'; +import { SucessRes } from '@utils/def'; +import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; +import { User } from '@schemas/user.schema'; import { CreateUserDto } from '@user/dto/create-user.dto'; +import { responseForm } from '@utils/responseForm'; -@Controller('user') +@Controller('api/user') export class UserController { - constructor(private userService: UserService) {} + constructor( + @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, + private userService: UserService, + ) {} + + @Get() + getUsers() { + const createUserDto: CreateUserDto = { id: 'mj', pw: 'mjpw' }; + this.userService.createUser(createUserDto); + return 'hello user'; + } + + @Post('following/:id') + async addFollowing(@Param('id') id: string) { + try { + const myId = '63734e98384f478a32c3a1cc'; + // TODO: Request Header에서 access token으로 현재 사용자 알아내기 + const addFollowingDto: AddFollowingDto = { myId, followId: id }; + await this.userService.addFollowing(addFollowingDto); + return responseForm(200, {}); + } catch (error) { + this.logger.error(JSON.stringify(error.response)); + return error.response; + } + } - // @Get() - // getUsers() { - // const createUserDto: CreateUserDto = { id: 'ny', pw: 'nypw' }; - // this.userService.createUser(createUserDto); - // return 'hello user'; - // } - // @Get('followers/:id') - // getFollowers(@Param('id') id: string): User[] { - // return this.usersService.getAllFollowers(); - // } // @Post() // createUser(@Body() createUserDto: CreateUserDto) { diff --git a/server/apps/api/src/user/user.module.ts b/server/apps/api/src/user/user.module.ts index 496e7a34..7a7310b2 100644 --- a/server/apps/api/src/user/user.module.ts +++ b/server/apps/api/src/user/user.module.ts @@ -2,16 +2,14 @@ import { Module } from '@nestjs/common'; import { UserController } from '@user/user.controller'; import { UserService } from '@user/user.service'; import { MongooseModule } from '@nestjs/mongoose'; +import { WinstonModule } from 'nest-winston'; import { User, UserSchema } from '@schemas/user.schema'; import { AuthModule } from '../auth/auth.module'; import { UserRepository } from '@repository/user.repository'; import { AuthController } from '../auth/auth.controller'; @Module({ - imports: [ - MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]), - AuthModule, - ], + imports: [MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]), AuthModule], controllers: [UserController], providers: [UserService, UserRepository], }) diff --git a/server/apps/api/src/user/user.service.ts b/server/apps/api/src/user/user.service.ts index 8d162c82..86467d72 100644 --- a/server/apps/api/src/user/user.service.ts +++ b/server/apps/api/src/user/user.service.ts @@ -1,3 +1,5 @@ +import { BadRequestException, ConflictException, Injectable } from '@nestjs/common'; +import { AddFollowingDto } from '@user/dto/add-following.dto'; import { Injectable } from '@nestjs/common'; import { CreateUserDto } from '@user/dto/create-user.dto'; import { UserRepository } from '@repository/user.repository'; @@ -6,9 +8,21 @@ import { UserRepository } from '@repository/user.repository'; export class UserService { constructor(private readonly userRepository: UserRepository) {} - // getAllFollowers() {} - // - // createUser(createUserDto: CreateUserDto) { - // this.userRepository.create(createUserDto); - // } + createUser(createUserDto: CreateUserDto) { + this.userRepository.create(createUserDto); + } + + async addFollowing(addFollowingDto: AddFollowingDto) { + const user = await this.userRepository.findById(addFollowingDto.myId); + const otherUser = await this.userRepository.findById(addFollowingDto.followId); + if (!user || !otherUser) { + throw new BadRequestException('해당하는 사용자의 _id가 올바르지 않습니다.'); + } else if (user.followings.includes(addFollowingDto.followId)) { + throw new BadRequestException('팔로우 요청한 사용자는 이미 팔로우되어있습니다.'); + } else if (otherUser.followers.includes(addFollowingDto.myId)) { + throw new ConflictException('상대방의 팔로워 목록에 이미 있습니다.'); + } + this.userRepository.appendFollowing(addFollowingDto); + this.userRepository.appendFollwer(addFollowingDto); + } } diff --git a/server/dao/repository/user.repository.ts b/server/dao/repository/user.repository.ts index ec8bd43f..0311999b 100644 --- a/server/dao/repository/user.repository.ts +++ b/server/dao/repository/user.repository.ts @@ -1,7 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { User, UserDocument } from '@schemas/user.schema'; -import { Model } from 'mongoose'; +import mongoose, { Model, Schema } from 'mongoose'; +import { AddFollowingDto } from '@user/dto/add-following.dto'; import { SignUpDto } from '@api/src/auth/dto'; @Injectable() @@ -12,4 +13,30 @@ export class UserRepository { await this.userModel.create(createUserDto); return null; } + + async findById(id: string) { + return await this.userModel.findById(id); + } + + appendFollowing(addFollowingDto: AddFollowingDto) { + this.userModel.updateOne( + { _id: addFollowingDto.myId }, + { $push: { followings: addFollowingDto.followId } }, + (err, res) => { + if (err) throw err; + }, + ); + } + + appendFollwer(addFollowingDto: AddFollowingDto) { + this.userModel.updateOne( + { _id: addFollowingDto.followId }, + { + $push: { followers: addFollowingDto.myId }, + }, + (err, res) => { + if (err) throw err; + }, + ); + } } diff --git a/server/package.json b/server/package.json index de51bcf7..5aea0f4c 100644 --- a/server/package.json +++ b/server/package.json @@ -51,6 +51,7 @@ "eslint-plugin-prettier": "^4.0.0", "jest": "28.1.3", "mongoose": "^6.7.2", + "nest-winston": "^1.8.0", "prettier": "^2.3.2", "source-map-support": "^0.5.20", "supertest": "^6.1.3", @@ -58,7 +59,8 @@ "ts-loader": "^9.2.3", "ts-node": "^10.0.0", "tsconfig-paths": "4.1.0", - "typescript": "^4.7.4" + "typescript": "^4.7.4", + "winston": "^3.8.2" }, "jest": { "moduleFileExtensions": [