Skip to content

Commit

Permalink
Merge pull request #176 from boostcampwm2023/feature/be-object-storage
Browse files Browse the repository at this point in the history
유저 프로필 사진을 object storage에 저장 및 응답
  • Loading branch information
LeeTH916 authored Nov 30, 2023
2 parents 4da47a6 + 5e9c496 commit f245374
Show file tree
Hide file tree
Showing 13 changed files with 480 additions and 138 deletions.
1 change: 1 addition & 0 deletions be/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#config
typeorm.config.ts
objectStorage.config.ts

# Logs
logs
Expand Down
107 changes: 107 additions & 0 deletions be/package-lock.json

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

2 changes: 2 additions & 0 deletions be/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@nestjs/platform-express": "^10.0.0",
"@nestjs/swagger": "^7.1.15",
"@nestjs/typeorm": "^10.0.1",
"aws-sdk": "^2.348.0",
"axios": "^1.6.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
Expand All @@ -39,6 +40,7 @@
"rxjs": "^7.8.1",
"swagger-ui-express": "^5.0.0",
"typeorm": "^0.3.17",
"uuid": "^9.0.1",
"winston": "^3.11.0"
},
"devDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions be/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ReviewModule } from "./review/review.module";
import { CustomLoggerService } from "./custom.logger";
import { APP_INTERCEPTOR } from "@nestjs/core";
import { LoggingInterceptor } from "./logger.interceptor";
import { AwsModule } from './aws/aws.module';

@Module({
imports: [
Expand All @@ -16,6 +17,7 @@ import { LoggingInterceptor } from "./logger.interceptor";
AuthModule,
RestaurantModule,
ReviewModule,
AwsModule,
],
providers: [
CustomLoggerService,
Expand Down
107 changes: 99 additions & 8 deletions be/src/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,109 @@
import { Test, TestingModule } from "@nestjs/testing";
import { AuthService } from "./auth.service";
import { DataSource } from "typeorm";
import { User } from "src/user/entities/user.entity";
import { TypeOrmModule } from "@nestjs/typeorm";
import { FollowEntity } from "src/user/entities/user.followList.entity";
import { RestaurantInfoEntity } from "src/restaurant/entities/restaurant.entity";
import { UserRestaurantListEntity } from "src/user/entities/user.restaurantlist.entity";
import { ReviewInfoEntity } from "src/review/entities/review.entity";
import { JwtService } from "@nestjs/jwt";
import { UserModule } from "src/user/user.module";
import { RestaurantModule } from "src/restaurant/restaurant.module";
import { ReviewModule } from "src/review/review.module";
import { HttpException } from '@nestjs/common';
import { UserInfoDto } from "src/user/dto/userInfo.dto";
import { UserService } from "src/user/user.service";
import { AuthModule } from "./auth.module";

describe("AuthService", () => {
let service: AuthService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AuthService],
let authService: AuthService;
let dataSource: DataSource;
let jwtService: JwtService;
let userService: UserService;

beforeAll(async () => {
const testModule = await Test.createTestingModule({
imports: [
AuthModule,
UserModule,
RestaurantModule,
ReviewModule,
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5433,
username: 'user',
password: 'password',
database: 'testdb',
entities: [User, FollowEntity, RestaurantInfoEntity, UserRestaurantListEntity, ReviewInfoEntity],
synchronize: true,
}),
],
}).compile();

service = module.get<AuthService>(AuthService);
authService = testModule.get<AuthService>(AuthService);
jwtService = testModule.get<JwtService>(JwtService);
dataSource = testModule.get<DataSource>(DataSource);
userService = testModule.get<UserService>(UserService);
});

it("should be defined", () => {
expect(service).toBeDefined();


beforeEach(async () => {
const repository = dataSource.getRepository(User);
await repository.query('DELETE FROM public.user');
});
});

it("회원가입 된 유저가 로그인 요청을 한 경우", async () => {

const userInfoDto: UserInfoDto = {
email: "[email protected]",
password: "",
provider: "naver",
nickName: "test",
region: "인천",
birthdate: "1999/10/13",
isMale: true,
};

await userService.signup(userInfoDto);

const loginRequestUser = {
email: "[email protected]"
}

const result = await authService.signin(loginRequestUser);
expect(result).toBeDefined();
expect(jwtService.verify(result.accessToken)).toBeTruthy();
expect(jwtService.verify(result.refreshToken)).toBeTruthy();
})

it("회원가입이 안된 유저가 로그인 요청을 한 경우",async () => {
const loginRequestUser = {
email: "[email protected]"
}

await expect(authService.signin(loginRequestUser))
.rejects
.toThrow(HttpException);
})

it("정상적인 리프레쉬 토큰을 받은 경우", async () => {
const refreshToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0IiwiaWQiOi0xLCJpYXQiOjIwMTYyMzkwMjJ9.zOd1UtNxKjPqNUYGapfDgqY78M5iBEj2Ike386HTDOA"

const result = await authService.checkRefreshToken(refreshToken);

expect(result).toBeDefined();
expect(jwtService.verify(result.accessToken)).toBeTruthy();
})

it("비정상적인 리프레쉬 토큰을 받은 경우", async () => {
const refreshToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0IiwiaWQiOjEsImlhdCI6MjAxNjIzOTAyMn0.3nRp6Qdxf5xj2C0M7-0lOURWx-dAKEjl9eS9dRoQTsA"

await expect(authService.checkRefreshToken(refreshToken))
.rejects
.toThrow(HttpException);
})
});
9 changes: 9 additions & 0 deletions be/src/aws/aws.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Global, Module } from '@nestjs/common';
import { AwsService } from './aws.service';

@Global()
@Module({
providers: [AwsService],
exports: [AwsService],
})
export class AwsModule {}
18 changes: 18 additions & 0 deletions be/src/aws/aws.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AwsService } from './aws.service';

describe('AwsService', () => {
let service: AwsService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AwsService],
}).compile();

service = module.get<AwsService>(AwsService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
38 changes: 38 additions & 0 deletions be/src/aws/aws.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Injectable } from "@nestjs/common";
import * as AWS from "aws-sdk";
import { awsConfig } from "objectStorage.config";
import { v4 } from "uuid";

@Injectable()
export class AwsService {
private s3: AWS.S3;

constructor() {
this.s3 = new AWS.S3({
endpoint: awsConfig.endpoint,
region: awsConfig.region,
credentials: {
accessKeyId: awsConfig.accessKey,
secretAccessKey: awsConfig.secretKey,
},
});
}

async uploadToS3(path: string, data: Buffer){
await this.s3.putObject({
Bucket: awsConfig.bucket,
Key: path,
Body: data,
}).promise();
}

getImageURL(path: string) {
const signedUrl = this.s3.getSignedUrl("getObject", {
Bucket: awsConfig.bucket,
Key: path,
Expires: 60,
});

return signedUrl;
}
}
Loading

0 comments on commit f245374

Please sign in to comment.