Skip to content

Commit

Permalink
Merge pull request #187 from tnpfldyd/BE-feature/space-invite
Browse files Browse the repository at this point in the history
슀페이슀 μ΄ˆλŒ€ μ½”λ“œ κ΅¬ν˜„
  • Loading branch information
Conut-1 authored Dec 6, 2023
2 parents 00cd435 + 31ce5c8 commit f18a31a
Show file tree
Hide file tree
Showing 18 changed files with 218 additions and 38 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/BE-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ jobs:
- name: Build and push Docker image
run: |
echo "SERVER_PORT=$SERVER_PORT" >> ./nestjs-BE/server/.env
echo "JWT_SECRET=$JWT_SECRET" >> ./nestjs-BE/server/.env
echo "JWT_ACCESS_SECRET=$JWT_ACCESS_SECRET" >> ./nestjs-BE/server/.env
echo "JWT_REFRESH_SECRET=$JWT_REFRESH_SECRET" >> ./nestjs-BE/server/.env
echo "KAKAO_ADMIN_KEY=$KAKAO_ADMIN_KEY" >> ./nestjs-BE/server/.env
echo "MYSQL_DATABASE_URL=$MYSQL_DATABASE_URL" >> ./nestjs-BE/server/.env
echo "MONGODB_DATABASE_URL=$MONGODB_DATABASE_URL" >> ./nestjs-BE/server/.env
Expand All @@ -31,7 +32,8 @@ jobs:
docker push ghcr.io/${{ secrets.PACKAGE_USERNAME }}/mindsync:latest
env:
SERVER_PORT: ${{ secrets.CONTAINER_PORT }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
JWT_ACCESS_SECRET: ${{ secrets.JWT_ACCESS_SECRET }}
JWT_REFRESH_SECRET: ${{ secrets.JWT_REFRESH_SECRET }}
KAKAO_ADMIN_KEY: ${{ secrets.KAKAO_ADMIN_KEY }}
MYSQL_DATABASE_URL: ${{ secrets.MYSQL_DATABASE_URL }}
MONGODB_DATABASE_URL: ${{ secrets.MONGODB_DATABASE_URL }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,28 @@ CREATE TABLE `PROFILE_SPACE_TB` (
PRIMARY KEY (`space_uuid`, `profile_uuid`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `INVITE_CODE_TB` (
`uuid` VARCHAR(32) NOT NULL,
`invite_code` VARCHAR(10) NOT NULL,
`space_uuid` VARCHAR(32) NOT NULL,
`expiry_date` DATETIME(3) NOT NULL,

UNIQUE INDEX `INVITE_CODE_TB_invite_code_key`(`invite_code`),
PRIMARY KEY (`uuid`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- AddForeignKey
ALTER TABLE `REFRESH_TOKEN_TB` ADD CONSTRAINT `REFRESH_TOKEN_TB_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `USER_TB`(`uuid`) ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `REFRESH_TOKEN_TB` ADD CONSTRAINT `REFRESH_TOKEN_TB_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `USER_TB`(`uuid`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `PROFILE_TB` ADD CONSTRAINT `PROFILE_TB_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `USER_TB`(`uuid`) ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `PROFILE_TB` ADD CONSTRAINT `PROFILE_TB_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `USER_TB`(`uuid`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `PROFILE_SPACE_TB` ADD CONSTRAINT `PROFILE_SPACE_TB_space_uuid_fkey` FOREIGN KEY (`space_uuid`) REFERENCES `SPACE_TB`(`uuid`) ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `PROFILE_SPACE_TB` ADD CONSTRAINT `PROFILE_SPACE_TB_space_uuid_fkey` FOREIGN KEY (`space_uuid`) REFERENCES `SPACE_TB`(`uuid`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `PROFILE_SPACE_TB` ADD CONSTRAINT `PROFILE_SPACE_TB_profile_uuid_fkey` FOREIGN KEY (`profile_uuid`) REFERENCES `PROFILE_TB`(`uuid`) ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `PROFILE_SPACE_TB` ADD CONSTRAINT `PROFILE_SPACE_TB_profile_uuid_fkey` FOREIGN KEY (`profile_uuid`) REFERENCES `PROFILE_TB`(`uuid`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `INVITE_CODE_TB` ADD CONSTRAINT `INVITE_CODE_TB_space_uuid_fkey` FOREIGN KEY (`space_uuid`) REFERENCES `SPACE_TB`(`uuid`) ON DELETE CASCADE ON UPDATE CASCADE;
23 changes: 16 additions & 7 deletions nestjs-BE/server/prisma/mysql.schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ model USER_TB {
}

model REFRESH_TOKEN_TB {
uuid String @id @db.VarChar(32)
token String @unique
uuid String @id @db.VarChar(32)
token String @unique
expiry_date DateTime
user_id String
user USER_TB @relation(fields: [user_id], references: [uuid])
user_id String
user USER_TB @relation(fields: [user_id], references: [uuid], onDelete: Cascade)
}

model PROFILE_TB {
uuid String @id @db.VarChar(32)
user_id String @db.VarChar(32)
image String
nickname String
user USER_TB @relation(fields: [user_id], references: [uuid])
user USER_TB @relation(fields: [user_id], references: [uuid], onDelete: Cascade)
spaces PROFILE_SPACE_TB[]
@@index([user_id])
}
Expand All @@ -40,13 +40,22 @@ model SPACE_TB {
name String
icon String
profiles PROFILE_SPACE_TB[]
invite_codes INVITE_CODE_TB[]
}

model PROFILE_SPACE_TB {
space_uuid String @db.VarChar(32)
profile_uuid String @db.VarChar(32)
space SPACE_TB @relation(fields: [space_uuid], references: [uuid])
profile PROFILE_TB @relation(fields: [profile_uuid], references: [uuid])
space SPACE_TB @relation(fields: [space_uuid], references: [uuid], onDelete: Cascade)
profile PROFILE_TB @relation(fields: [profile_uuid], references: [uuid], onDelete: Cascade)
@@id([space_uuid, profile_uuid])
}

model INVITE_CODE_TB {
uuid String @id @db.VarChar(32)
invite_code String @unique @db.VarChar(10)
space_uuid String @db.VarChar(32)
expiry_date DateTime
space SPACE_TB @relation(fields: [space_uuid], references: [uuid], onDelete: Cascade)
}

2 changes: 2 additions & 0 deletions nestjs-BE/server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { BoardsModule } from './boards/boards.module';
import { ScheduleModule } from '@nestjs/schedule';
import { UploadModule } from './upload/upload.module';
import { MongooseModule } from '@nestjs/mongoose';
import { InviteCodesModule } from './invite-codes/invite-codes.module';
import customEnv from './config/env';

@Module({
Expand All @@ -26,6 +27,7 @@ import customEnv from './config/env';
BoardsModule,
UploadModule,
MongooseModule.forRoot(customEnv.MONGODB_DATABASE_URI),
InviteCodesModule,
],
controllers: [AppController],
providers: [AppService, BoardGateway],
Expand Down
8 changes: 6 additions & 2 deletions nestjs-BE/server/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { JwtAuthGuard } from './jwt-auth.guard';
import { Public } from './public.decorator';
import { KakaoUserDto } from './dto/kakao-user.dto';
import { UsersService } from 'src/users/users.service';
import { RefreshTokenDto } from './dto/refresh-token.dto';

@Controller('auth')
export class AuthController {
Expand All @@ -37,12 +38,15 @@ export class AuthController {

@Post('token')
@Public()
renewAccessToken(@Body('refresh_token') refreshToken) {
renewAccessToken(@Body() refreshTokenDto: RefreshTokenDto) {
const refreshToken = refreshTokenDto.refresh_token;
return this.authService.renewAccessToken(refreshToken);
}

@Post('logout')
logout(@Body('refresh_token') refreshToken) {
@Public()
logout(@Body() refreshTokenDto: RefreshTokenDto) {
const refreshToken = refreshTokenDto.refresh_token;
return this.authService.remove(refreshToken);
}

Expand Down
10 changes: 1 addition & 9 deletions nestjs-BE/server/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,12 @@ import { AuthService } from './auth.service';
import { UsersModule } from 'src/users/users.module';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import { jwtConstants } from './constants';
import { JwtStrategy } from './jwt.strategy';
import { APP_GUARD } from '@nestjs/core';
import { JwtAuthGuard } from './jwt-auth.guard';

@Module({
imports: [
UsersModule,
PassportModule,
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '1s' },
}),
],
imports: [UsersModule, PassportModule, JwtModule],
controllers: [AuthController],
providers: [
AuthService,
Expand Down
9 changes: 6 additions & 3 deletions nestjs-BE/server/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,17 @@ export class AuthService extends BaseService<TokenData> {

async createAccessToken(userUuid: string): Promise<string> {
const payload = { sub: userUuid };
const accessToken = await this.jwtService.signAsync(payload);
const accessToken = await this.jwtService.signAsync(payload, {
secret: jwtConstants.accessSecret,
expiresIn: '5m',
});
return accessToken;
}

async createRefreshToken(): Promise<string> {
const refreshTokenPayload = { uuid: generateUuid() };
const refreshToken = await this.jwtService.signAsync(refreshTokenPayload, {
secret: jwtConstants.secret,
secret: jwtConstants.refreshSecret,
expiresIn: '14d',
});
return refreshToken;
Expand Down Expand Up @@ -98,7 +101,7 @@ export class AuthService extends BaseService<TokenData> {
async renewAccessToken(refreshToken: string) {
try {
this.jwtService.verify(refreshToken, {
secret: jwtConstants.secret,
secret: jwtConstants.refreshSecret,
});
const tokenData = await this.getDataFromCacheOrDB(refreshToken);
if (!tokenData) throw new Error('No token data found');
Expand Down
3 changes: 2 additions & 1 deletion nestjs-BE/server/src/auth/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import customEnv from 'src/config/env';

export const jwtConstants = {
secret: customEnv.JWT_SECRET,
accessSecret: customEnv.JWT_ACCESS_SECRET,
refreshSecret: customEnv.JWT_REFRESH_SECRET,
};

export const kakaoOauthConstants = {
Expand Down
7 changes: 7 additions & 0 deletions nestjs-BE/server/src/auth/dto/refresh-token.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IsNotEmpty, IsString } from 'class-validator';

export class RefreshTokenDto {
@IsString()
@IsNotEmpty()
refresh_token: string;
}
2 changes: 1 addition & 1 deletion nestjs-BE/server/src/auth/jwt.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: jwtConstants.secret,
secretOrKey: jwtConstants.accessSecret,
});
}

Expand Down
14 changes: 10 additions & 4 deletions nestjs-BE/server/src/base/base.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable } from '@nestjs/common';
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import {
PrismaServiceMySQL,
PrismaServiceMongoDB,
Expand Down Expand Up @@ -37,15 +37,21 @@ export abstract class BaseService<T extends HasUuid> {

abstract generateKey(data: T): string;

async create(data: T): Promise<T | string> {
async create(data: T) {
data.uuid = generateUuid();
const key = this.generateKey(data);
const storeData = await this.getDataFromCacheOrDB(key);
if (storeData) return 'Data already exists.';
if (storeData) {
throw new HttpException('Data already exists.', HttpStatus.CONFLICT);
}

this.temporaryDatabaseService.create(this.className, key, data);
this.cache.put(key, data);
return data;
return {
statusCode: HttpStatus.CREATED,
message: 'Created',
data,
};
}

async findOne(key: string): Promise<T | null> {
Expand Down
3 changes: 3 additions & 0 deletions nestjs-BE/server/src/config/magic-number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ export const SPACE_CACHE_SIZE = 10000;
export const BOARD_CACHE_SIZE = 10000;
export const REFRESH_TOKEN_CACHE_SIZE = 1000;
export const REFRESH_TOKEN_EXPIRY_DAYS = 14;
export const INVITE_CODE_CACHE_SIZE = 5000;
export const INVITE_CODE_LENGTH = 10;
export const INVITE_CODE_EXPIRY_HOURS = 6;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class CreateInviteCodeDto {
space_uuid: string;
}
21 changes: 21 additions & 0 deletions nestjs-BE/server/src/invite-codes/invite-codes.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { InviteCodesService } from './invite-codes.service';
import { CreateInviteCodeDto } from './dto/create-invite-code.dto';
import { Public } from 'src/auth/public.decorator';

@Controller('inviteCodes')
export class InviteCodesController {
constructor(private readonly inviteCodesService: InviteCodesService) {}

@Post()
@Public()
create(@Body() createInviteCodeDto: CreateInviteCodeDto) {
return this.inviteCodesService.createCode(createInviteCodeDto);
}

@Get(':inviteCode')
@Public()
findSpace(@Param('inviteCode') inviteCode: string) {
return this.inviteCodesService.findSpace(inviteCode);
}
}
10 changes: 10 additions & 0 deletions nestjs-BE/server/src/invite-codes/invite-codes.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { InviteCodesService } from './invite-codes.service';
import { InviteCodesController } from './invite-codes.controller';
import { SpacesService } from 'src/spaces/spaces.service';

@Module({
controllers: [InviteCodesController],
providers: [InviteCodesService, SpacesService],
})
export class InviteCodesModule {}
Loading

0 comments on commit f18a31a

Please sign in to comment.