Skip to content

Commit

Permalink
Merge branch 'main' into preproduction
Browse files Browse the repository at this point in the history
# Conflicts:
#	BE/package-lock.json
#	BE/package.json
#	BE/src/app.module.ts
#	BE/src/auth/auth.controller.ts
#	BE/src/auth/auth.service.ts
#	BE/src/common/multer.config.ts
#	BE/src/mates/mates.controller.ts
#	BE/src/mates/mates.module.ts
#	BE/src/mates/mates.service.ts
#	BE/src/users/users.service.ts
#	iOS/FlipMate/FlipMate.xcodeproj/project.pbxproj
#	iOS/FlipMate/FlipMate/Application/DIContainer/AppDIContainer.swift
#	iOS/FlipMate/FlipMate/Application/DIContainer/CategoryDIContainer.swift
#	iOS/FlipMate/FlipMate/Application/DIContainer/LoginDIContainer.swift
#	iOS/FlipMate/FlipMate/Application/DIContainer/TabBarDIContainer.swift
#	iOS/FlipMate/FlipMate/Application/DIContainer/TimerSceneDIContainer.swift
#	iOS/FlipMate/FlipMate/Data/Extension/UIColor++Extension.swift
#	iOS/FlipMate/FlipMate/Presentation/TimerScene/Flows/CategorySettingCoordinator.swift
#	iOS/FlipMate/FlipMate/Presentation/TimerScene/Flows/TimerFlowCoordinator.swift
#	iOS/FlipMate/FlipMate/Presentation/TimerScene/View/CategoryColorSelectView.swift
#	iOS/FlipMate/FlipMate/Presentation/TimerScene/ViewController/CategoryModifyViewController.swift
#	iOS/FlipMate/FlipMate/Presentation/TimerScene/ViewController/CategorySettingViewController.swift
#	iOS/FlipMate/FlipMate/Presentation/TimerScene/ViewModel/CategoryViewModel.swift
#	iOS/FlipMate/FlipMate/Presentation/TimerScene/ViewModel/TimerViewModel.swift
  • Loading branch information
leemhyungyu committed Nov 28, 2023
2 parents 9820f50 + 0787e63 commit be30ada
Show file tree
Hide file tree
Showing 49 changed files with 1,342 additions and 395 deletions.
284 changes: 195 additions & 89 deletions BE/package-lock.json

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions BE/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
"@nestjs/typeorm": "^10.0.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"D": "^1.0.0",
"ioredis": "^5.3.2",
"multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1",
"mysql": "^2.18.1",
"nest-winston": "^1.9.4",
"passport": "^0.6.0",
"passport-google-oauth20": "^2.0.0",
"redis": "^4.6.11",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"sharp": "^0.32.6",
Expand All @@ -52,11 +52,14 @@
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/express": "^4.17.17",
"@types/ioredis": "^5.0.0",
"@types/jest": "^29.5.2",
"@types/multer": "^1.4.11",
"@types/multer-s3": "^3.0.3",
"@types/node": "^20.3.1",
"@types/passport-google-oauth20": "^2.0.14",
"@types/redis": "^4.0.11",
"@types/sharp": "^0.32.0",
"@types/supertest": "^2.0.12",
"@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "^6.0.0",
Expand Down
9 changes: 7 additions & 2 deletions BE/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Module } from '@nestjs/common';
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
Expand All @@ -15,6 +15,7 @@ import { AuthModule } from './auth/auth.module';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
import { Mates } from './mates/mates.entity';
import { LoggingMiddleware } from './common/logging.middleware';

@Module({
imports: [
Expand Down Expand Up @@ -49,4 +50,8 @@ import { Mates } from './mates/mates.entity';
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggingMiddleware).forRoutes('*');
}
}
19 changes: 8 additions & 11 deletions BE/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Patch,
UseInterceptors,
UploadedFile,
BadRequestException,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Response } from 'express';
Expand Down Expand Up @@ -77,9 +78,13 @@ export class AuthController {
async patchUser(
@User('id') user_id: number,
@Body() user: UpdateUserDto,
@UploadedFile() file: S3UploadedFile,
@UploadedFile() file: Express.Multer.File,
): Promise<any> {
const image_url = file?.key;
const isNomal = await this.usersService.isNormalImage(file);
if (!isNomal) {
throw new BadRequestException('유해한 이미지 입니다!!');
}
const image_url = await this.usersService.s3Upload(file);
const updatedUser = await this.usersService.updateUser(
user_id,
user as UsersModel,
Expand Down Expand Up @@ -109,16 +114,8 @@ export class AuthController {
email: user.email,
image_url: path.join(
this.configService.get(ENV.CDN_ENDPOINT),
user.image_url,
user.image_url ?? 'default.png',
),
};
}
}

interface S3UploadedFile extends Express.Multer.File {
bucket: string;
key: string;
location: string;
etag: string;
versionId?: string;
}
2 changes: 0 additions & 2 deletions BE/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@ export class AuthService {
}

public async loginWithGoogle(user) {
console.log(user.email);
const prevUser = await this.usersService.findUserByEmail(user.email);
if (!prevUser) {
const id = user.email.split('@')[0];
const userEntity = {
nickname:
id + Buffer.from(user.email + user.auth_type).toString('base64'),
email: user.email,
image_url: '',
} as UsersModel;
const newUser = await this.usersService.createUser(userEntity);
return {
Expand Down
1 change: 0 additions & 1 deletion BE/src/auth/google.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
email: any,
done: VerifyCallback,
): Promise<any> {
console.log(accessToken);
const user = {
email: email.emails[0].value,
};
Expand Down
26 changes: 12 additions & 14 deletions BE/src/common/logging.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@ export class LoggingInterceptor implements NestInterceptor {
const response = ctx.getResponse();
const { method, url, body } = request;

this.logger.debug(
`[Request] Method: ${method}, URL: ${url}, Body: ${JSON.stringify(body)}`,
this.logger.debug(`[Request] ${method} ${url} \n ${JSON.stringify(body)}`);
return next.handle().pipe(
tap((body) => {
const requestToResponse: `${number}ms` = `${
Date.now() - request.now
}ms`;
this.logger.debug(
`[Response] ${
response.statusCode
} ${requestToResponse} \n ${JSON.stringify(body)} \n`,
);
}),
);

return next
.handle()
.pipe(
tap((body) =>
this.logger.debug(
`[Response] Status: ${response.statusCode}, Body: ${JSON.stringify(
body,
)}`,
),
),
);
}
}
10 changes: 10 additions & 0 deletions BE/src/common/logging.middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Injectable, NestMiddleware } from '@nestjs/common';
import { NextFunction } from 'express';

@Injectable()
export class LoggingMiddleware implements NestMiddleware {
use(req: Request & { now: number }, res: Response, next: NextFunction) {
req.now = Date.now();
next();
}
}
39 changes: 14 additions & 25 deletions BE/src/common/multer.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import * as path from 'path';
import * as multerS3 from 'multer-s3';
import { S3Client } from '@aws-sdk/client-s3';
import { v4 as uuid } from 'uuid';
import { BadRequestException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';
import { ENV } from './const/env-keys.const';
import * as multer from 'multer';

export const multerConfig = (configService: ConfigService): MulterOptions => ({
fileFilter: (req, file, callback) => {
export const multerConfig = (): MulterOptions => {
const storage = multer.memoryStorage();
const fileFilter = (req, file, callback) => {
const ext = path.extname(file.originalname);
if (ext !== '.jpg' && ext !== '.jpeg' && ext !== '.png') {
return callback(
Expand All @@ -17,21 +14,13 @@ export const multerConfig = (configService: ConfigService): MulterOptions => ({
);
}
return callback(null, true);
},
limits: { fileSize: 1024 * 1024 * 10 }, //10MB
storage: multerS3({
s3: new S3Client({
endpoint: configService.get(ENV.IMAGE_ENDPOINT),
credentials: {
accessKeyId: configService.get(ENV.IMAGE_ACCESSKEY),
secretAccessKey: configService.get(ENV.IMAGE_SECRETKEY),
},
region: configService.get(ENV.IMAGE_REGION),
}),
bucket: configService.get(ENV.IMAGE_BUCKET),
key: function (req, file, callback) {
const fileExtension = path.extname(file.originalname);
callback(null, `IMG_${uuid()}${fileExtension}`);
},
}),
});
};

const limits = { fileSize: 1024 * 1024 * 10 }; //10MB

return {
storage,
fileFilter,
limits,
};
};
22 changes: 22 additions & 0 deletions BE/src/common/redis.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Injectable } from '@nestjs/common';
import { RedisClientType, createClient } from 'redis';

@Injectable()
export class RedisService {
private client: RedisClientType;
constructor() {
this.client = createClient();
this.client.connect();
}
set(key: string, value: string) {
this.client.set(key, value);
}

get(key: string): Promise<string | null> {
return this.client.get(key);
}

async del(key: string): Promise<void> {
await this.client.del(key);
}
}
22 changes: 22 additions & 0 deletions BE/src/common/response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ApiProperty } from '@nestjs/swagger';

export class ResponseDto {
@ApiProperty({
type: 'number',
example: 200,
description: '상태 코드',
})
statusCode;

@ApiProperty({
type: 'string',
example: '요청이 정상적으로 처리되었습니다.',
description: '메세지',
})
message;

constructor(statusCode: number, message: string) {
this.statusCode = statusCode;
this.message = message;
}
}
41 changes: 41 additions & 0 deletions BE/src/common/s3.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Injectable, InternalServerErrorException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import * as sharp from 'sharp';
import { v4 as uuidv4 } from 'uuid';
import * as path from 'path';

@Injectable()
export class S3Service {
private s3Client: S3Client;

constructor(private configService: ConfigService) {
this.s3Client = new S3Client({
endpoint: this.configService.get('IMAGE_ENDPOINT'),
credentials: {
accessKeyId: this.configService.get('IMAGE_ACCESSKEY'),
secretAccessKey: this.configService.get('IMAGE_SECRETKEY'),
},
region: this.configService.get('IMAGE_REGION'),
});
}

async uploadFile(file: Express.Multer.File): Promise<string> {
try {
const buffer = await sharp(file.buffer).resize(800, 800).toBuffer();
const fileName = `IMG_${uuidv4()}${path.extname(file.originalname)}`;

await this.s3Client.send(
new PutObjectCommand({
Bucket: this.configService.get('IMAGE_BUCKET'),
Key: fileName,
Body: buffer,
}),
);

return fileName;
} catch (error) {
throw new InternalServerErrorException(error);
}
}
}
36 changes: 35 additions & 1 deletion BE/src/mates/mates.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '@nestjs/common';
import {
ApiBearerAuth,
ApiBody,
ApiCreatedResponse,
ApiOperation,
ApiTags,
Expand All @@ -27,11 +28,22 @@ export class MatesController {
@Get()
@UseGuards(AccessTokenGuard)
@ApiBearerAuth()
@ApiCreatedResponse({
description: 'OK',
})
@ApiOperation({ summary: '모든 친구들 조회하기 (완)' })
getMates(@User('id') user_id: number): Promise<MatesDto[]> {
getMates(@User('id') user_id: number): Promise<object> {
return this.matesService.getMates(user_id);
}

@Get('/status')
@UseGuards(AccessTokenGuard)
@ApiBearerAuth()
@ApiOperation({ summary: '현재 친구들 상태 polling 조회하기' })
getMatesStatus(@User('id') user_id: number): Promise<object[]> {
return this.matesService.getMatesStatus(user_id);
}

@Get('/:mate_id/stats')
@UseGuards(AccessTokenGuard)
@ApiBearerAuth()
Expand All @@ -46,6 +58,17 @@ export class MatesController {
@ApiCreatedResponse({
description: '친구가 성공적으로 구독되었습니다.',
})
@ApiBody({
schema: {
properties: {
following_nickname: {
type: 'string',
description: '구독할 닉네임',
example: '어린콩',
},
},
},
})
@ApiOperation({ summary: '친구 구독하기 (완)' })
createMate(
@User() user: UsersModel,
Expand All @@ -57,6 +80,17 @@ export class MatesController {
@Delete('')
@UseGuards(AccessTokenGuard)
@ApiBearerAuth()
@ApiBody({
schema: {
properties: {
following_id: {
type: 'number',
description: '구독 취소할 유저의 id',
example: '2',
},
},
},
})
@ApiOperation({ summary: '구독한 친구 구독 취소하기 (완)' })
async deleteMate(
@User() user: UsersModel,
Expand Down
3 changes: 2 additions & 1 deletion BE/src/mates/mates.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { Mates } from './mates.entity';
import { AuthModule } from 'src/auth/auth.module';
import { UsersModule } from 'src/users/users.module';
import { RedisService } from 'src/common/redis.service';

@Module({
imports: [TypeOrmModule.forFeature([Mates]), AuthModule, UsersModule],
controllers: [MatesController],
providers: [MatesService],
providers: [MatesService, RedisService],
})
export class MatesModule {}
Loading

0 comments on commit be30ada

Please sign in to comment.