Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
6b5a5cd
feat: 질문지 삭제 기능 구현
twalla26 Nov 26, 2024
d7d4320
feat: 조회 기능에 pagination 구현
twalla26 Nov 26, 2024
8168056
feat: 마이페이지 질문지 카드 컴포넌트 생성
yiseungyun Nov 26, 2024
52c4476
fix: 질문지 내용은 pagination 없이 모두 전달
twalla26 Nov 27, 2024
ea5d5f3
feat: 내 질문지 조회 기능에 pagination 구현
twalla26 Nov 27, 2024
4627440
feat: 스크랩한 질문지 조회 기능에 pagination 추가
twalla26 Nov 27, 2024
90cb1fe
refactor: 스크랩 응답 변수명 변경
twalla26 Nov 27, 2024
7f2b9d0
feat: 마이페이지 질문지 카드 카테고리 추가
yiseungyun Nov 27, 2024
0796265
Merge branch 'dev' of https://github.com/boostcampwm-2024/web27-Previ…
yiseungyun Nov 27, 2024
1e6fa84
refactor: 마이페이지 UI 분리
yiseungyun Nov 27, 2024
4dd4783
refactor: api 요청 함수 이름 직관적으로 변경
yiseungyun Nov 27, 2024
19a436d
refactor: 세션 헤더 카테고리 가독성 향상
ShipFriend0516 Nov 27, 2024
985a802
refactor: 화면 그리드가 브라우저 전체 높이를 벗어나지 않도록 수정
ShipFriend0516 Nov 27, 2024
03586a6
refactor: 비디오 그리드가 자연스럽게 공간을 차지하도록 수정
ShipFriend0516 Nov 27, 2024
4695d30
refactor: reaction 상태를 useReaction 훅 내부로 수정
ShipFriend0516 Nov 27, 2024
024cb2b
chore: 콘솔로그 제거
ShipFriend0516 Nov 27, 2024
ceb2706
feat: 비디오 켜고 끌때 로딩 인디케이터 추가
ShipFriend0516 Nov 27, 2024
1a71530
feat: 비디오가 로딩 중일 때는 비디오 토글 버튼 비활성화
ShipFriend0516 Nov 27, 2024
034be06
fix: index already exists 문제 해결
blu3fishez Nov 27, 2024
cf8a77f
feat: 미디어 장치 중 하나만 없는 경우에 토스트 메시지와 함께 참여시키도록 구현
ShipFriend0516 Nov 27, 2024
fd3355a
feat: 질문지 api 관련 함수 작성
yiseungyun Nov 27, 2024
03a2736
refactor: 마이페이지 구조 리팩토링
yiseungyun Nov 27, 2024
98eaa25
refactor: 그리드 화면이 넘치던 문제를 수정
ShipFriend0516 Nov 27, 2024
ca30c32
feat: 질문지 수정 기능 구현
twalla26 Nov 27, 2024
b4ed285
feat: 스터디 기능을 위한 엔티티 수정
blu3fishez Nov 27, 2024
1cca9ab
feat: 스터디 웹소켓 API 를 위한 DTO 추가
blu3fishez Nov 27, 2024
0b482a3
feat: 스터디 웹소켓 API 비즈니스 로직 추가
blu3fishez Nov 27, 2024
884f96f
feat: 스터디 웹소켓 API 핸들러 추가
blu3fishez Nov 27, 2024
7ecc44c
Merge pull request #255 from blu3piece/fix/nestjs-redis-om
blu3fishez Nov 27, 2024
cfe2ab4
refactor: '기타' 카테고리 추가 및 시딩 로직 개선
twalla26 Nov 27, 2024
5fffd3b
Merge branch 'dev' into feature/pagination
twalla26 Nov 27, 2024
189d1c0
fix: 질문지 삭제 로직 오류 수정: 본인 질문지만 삭제 가능
twalla26 Nov 27, 2024
37f88fb
feat: 질문 추가 기능 구현
twalla26 Nov 27, 2024
9b9a153
feat: webRTC DataChannel을 사용하여 서로의 마이크와 비디오가 켜져있는지 상태를 공유하도록 구현
ShipFriend0516 Nov 27, 2024
9cff194
feat: 질문 내용 수정 기능 구현
twalla26 Nov 27, 2024
edbbe64
fix: 비디오나 오디오 장치가 없는 경우 항상 꺼짐 상태로 표시하도록 수정
ShipFriend0516 Nov 27, 2024
cb8dcb7
Merge pull request #254 from twalla26/feature/pagination
ShipFriend0516 Nov 27, 2024
ceda6bb
fix: 모달창 개선
yiseungyun Nov 27, 2024
7eb8dfd
feat: 마이페이지에서 질문지 삭제 구현
yiseungyun Nov 27, 2024
d2517ce
Merge pull request #257 from ShipFriend0516/refactor/session-page
ShipFriend0516 Nov 28, 2024
d1bd26a
feat: 스터디 세션 입장 API 변경
blu3fishez Nov 28, 2024
605aa2f
feat: 스터디 참가 세션 로직 수정
blu3fishez Nov 28, 2024
d777674
Merge pull request #256 from blu3piece/feature/study-websocket
ShipFriend0516 Nov 28, 2024
1155a24
feat: 유저 수정 / 회원가입 을 위한 DTO 추가
blu3fishez Nov 28, 2024
6ffa911
feat: 유저 로그인 타입과 아바타 필드 추가
blu3fishez Nov 28, 2024
351fb3f
feat: 유저 관련 기능을 위한 비즈니스 로직 추가
blu3fishez Nov 28, 2024
9af2120
feat: 유저 레포지토리 기능 추가
blu3fishez Nov 28, 2024
99879c3
feat: 유저 수정 및 회원가입 API 추가
blu3fishez Nov 28, 2024
ff44e85
fix: 시간 정보 수정
blu3fishez Nov 28, 2024
c532202
style: printWidth 변경에 따른 코드 스타일 변경
blu3fishez Nov 28, 2024
b85dc45
fix: jwt 토큰 만료시간 수정
blu3fishez Nov 28, 2024
c961ea8
feat: 깃허브 전략 수정
blu3fishez Nov 28, 2024
d2ca903
feat: 질문 삭제 기능 구현
twalla26 Nov 28, 2024
ecb7156
refactor: controller - strategy 역할 수정
blu3fishez Nov 28, 2024
7b5af52
feat: 로그인 기능을 위한 DTO 추가
blu3fishez Nov 28, 2024
6f934e5
feat: 로그인 기능을 위한 passport 전략 추가
blu3fishez Nov 28, 2024
e9fdd8a
fix: 쿠키 설정 시 secure 값을 production 일때만 되도록 허용
blu3fishez Nov 28, 2024
d90e414
feat: 로컬 로그인 전략을 위한 로직 추가
blu3fishez Nov 28, 2024
47007e0
feat: 바뀐 명세에 따른 모듈 의존성 업데이트
blu3fishez Nov 28, 2024
b30d5f7
fix: 백엔드 리팩토링에 맞춰 테스트 코드 수정
yiseungyun Nov 28, 2024
2adfbd9
chore: passport-local 의존성 추가, NODE_ENV 환경 제공
blu3fishez Nov 28, 2024
8c46e16
refactor: res.send() 삭제
twalla26 Nov 28, 2024
27fd8b2
Merge pull request #258 from boostcampwm-2024/feature/mypage
ShipFriend0516 Nov 28, 2024
0612abf
Merge branch 'dev' into feature/my-question-list
twalla26 Nov 28, 2024
9276e6a
Merge pull request #259 from blu3piece/chore/add-passport-dependency
blu3fishez Nov 28, 2024
ae42aa3
Merge pull request #260 from blu3piece/feature/user-api
blu3fishez Nov 28, 2024
f42c094
Merge branch 'dev' into feature/test
yiseungyun Nov 28, 2024
515b465
Merge pull request #261 from blu3piece/fix/auth-service
blu3fishez Nov 28, 2024
2f2fc18
feat: 질문지 정보에 대한 타입 구현
ShipFriend0516 Nov 28, 2024
48814da
chore: pnpm-lock
ShipFriend0516 Nov 28, 2024
eb9f7c4
feat: 스터디 웹소켓 API 이벤트명 분리
ShipFriend0516 Nov 28, 2024
687c092
feat: 스터디가 진행 중인지 아닌지를 직관적으로 확인할 수 있게 구현
ShipFriend0516 Nov 28, 2024
e7f4f52
feat: 질문 넘기기 API 연동 및 스터디 시작 API 연동
ShipFriend0516 Nov 28, 2024
619af1d
feat: 현재 질문을 표시하고 이전 질문들의 기록을 사이드바에 남기도록 구현
ShipFriend0516 Nov 28, 2024
2ebed38
feat: 스터디 기능 API 핸들러 추가
ShipFriend0516 Nov 28, 2024
aa6762b
fix: merge conflict 해결
twalla26 Nov 28, 2024
64ebd53
feat: 스터디 시작버튼과 중지버튼을 누르면 스터디 시작 및 정지 구현
ShipFriend0516 Nov 28, 2024
87a094e
Merge pull request #262 from twalla26/feature/my-question-list
twalla26 Nov 28, 2024
6d2768c
Merge pull request #263 from blu3piece/feature/local-login
ShipFriend0516 Nov 28, 2024
4095132
Merge pull request #265 from boostcampwm-2024/feature/test
ShipFriend0516 Nov 28, 2024
f9d03ac
fix: 질문 삭제 로직에 transactional 추가
twalla26 Nov 28, 2024
1bfb78b
feat: 사이드바 접기 버튼 추가
ShipFriend0516 Nov 28, 2024
48e6820
Merge pull request #266 from twalla26/fix/add-transactional
twalla26 Nov 28, 2024
b1af3f1
feat: 사이드바를 접을 수 있도록 사이드바를 감싸는 Container 구현
ShipFriend0516 Nov 28, 2024
37f234c
chore: 컴포넌트 큰 단위로 폴더로 구분
ShipFriend0516 Nov 28, 2024
4834f78
refactor: 호스트만 사용할 수 있는 도구와 일반 유저들도 사용할 수 있는 도구 컴포넌트를 분리
ShipFriend0516 Nov 28, 2024
e1c3588
feat: 스터디 시작하면 시작 인디케이터를 띄우기
ShipFriend0516 Nov 28, 2024
dde42e0
feat: 다음 질문, 이전 질문 누르고 2초 후에 활성화 되도록 구현
ShipFriend0516 Nov 28, 2024
6e96862
fix: 질문 번호가 잘못되어있던 오류 수정
ShipFriend0516 Nov 28, 2024
431d9bc
fix: 버튼 프로그레스바가 오버플로우 되던 현상 수정
ShipFriend0516 Nov 28, 2024
999f345
refactor: api 내부 폴더명 api 엔드포인트와 통일
yiseungyun Nov 28, 2024
c0b40b7
feat: tanstack query 사용 코드 훅으로 분리
yiseungyun Nov 28, 2024
3902442
Merge branch 'dev' into feature/study-in-session
ShipFriend0516 Nov 28, 2024
582171d
refactor: study 관련 함수 useStudy 훅으로 분리
ShipFriend0516 Nov 28, 2024
966d140
refactor: uptime 분/초로 표현
ShipFriend0516 Nov 28, 2024
cac93ce
refactor: useStudy -> useSession으로 받아온 함수 사용하도록 수정
ShipFriend0516 Nov 28, 2024
d950de1
refactor: 이전 질문 버튼과 다음 질문 버튼이 질문지의 양 끝단에서 비활성화되도록 구현
ShipFriend0516 Nov 28, 2024
dc08b84
Merge pull request #281 from ShipFriend0516/feature/study-in-session
ShipFriend0516 Nov 28, 2024
276c66e
fix: 세션 만들기 폼 모달 오류 수정
yiseungyun Nov 28, 2024
393af8e
feat: 마이페이지 meta 데이터로 페이지네이션 적용
yiseungyun Nov 28, 2024
28056fe
feat: 마이페이지 질문지 실제 api 데이터 넣고, 삭제 시 실시간 반영
yiseungyun Nov 28, 2024
9dcf81e
Merge pull request #282 from boostcampwm-2024/feature/mypage
ShipFriend0516 Nov 28, 2024
bdc3582
fix: 빌드 오류 수정
yiseungyun Nov 28, 2024
4bd2d83
Merge pull request #283 from boostcampwm-2024/feature/mypage
blu3fishez Nov 28, 2024
471f900
fix: 빌드 에러 수정
ShipFriend0516 Nov 28, 2024
f774db2
Merge pull request #284 from ShipFriend0516/fix/build-error
ShipFriend0516 Nov 28, 2024
01f595c
fix: 세션 페이지 모달 오류 수정
yiseungyun Nov 28, 2024
0de3c04
Merge pull request #285 from boostcampwm-2024/dev-fe
ShipFriend0516 Nov 28, 2024
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
8 changes: 6 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"build": "NODE_ENV=production nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
Expand All @@ -21,6 +21,7 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@moozeh/nestjs-redis-om": "^0.1.4",
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.2.0",
Expand All @@ -32,16 +33,18 @@
"@socket.io/redis-adapter": "^8.3.0",
"@types/passport-jwt": "^4.0.1",
"axios": "^1.7.7",
"cookie-parser": "^1.4.7",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"cookie-parser": "^1.4.7",
"dotenv": "^16.4.5",
"ioredis": "^5.4.1",
"mysql2": "^3.11.4",
"nestjs-paginate": "^10.0.0",
"nestjs-redis-om": "^0.1.2",
"passport": "^0.7.0",
"passport-custom": "^1.1.1",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"redis-om": "^0.4.7",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
Expand All @@ -59,6 +62,7 @@
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/passport-github": "^1.1.12",
"@types/passport-local": "^1.0.38",
"@types/supertest": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
Expand Down
2 changes: 1 addition & 1 deletion backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import "dotenv/config";

import { createDataSource, typeOrmConfig } from "./config/typeorm.config";
import { QuestionListModule } from "./question-list/question-list.module";
import { RedisOmModule } from "nestjs-redis-om";
import { RedisOmModule } from "@moozeh/nestjs-redis-om";
import { SigServerModule } from "@/signaling-server/sig-server.module";

@Module({
Expand Down
57 changes: 27 additions & 30 deletions backend/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Controller, Get, Post, Res, Req, UseGuards } from "@nestjs/common";
import { Controller, Get, Post, Res, UseGuards } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { Request, Response } from "express";
import { Response } from "express";
import { AuthService } from "./auth.service";
import { GithubProfile } from "./github/gitub-profile.decorator";
import { Profile } from "passport-github";
import { setCookieConfig } from "../config/cookie.config";
import { setCookieConfig } from "@/config/cookie.config";
import { JwtPayload, JwtTokenPair } from "./jwt/jwt.decorator";
import { IJwtPayload, IJwtTokenPair } from "./jwt/jwt.model";
import { IJwtPayload, IJwtToken, IJwtTokenPair } from "./jwt/jwt.model";

@Controller("auth")
export class AuthController {
Expand All @@ -18,46 +16,45 @@ export class AuthController {
@Post("github")
@UseGuards(AuthGuard("github"))
async githubCallback(
@Req() req: Request,
@Res({ passthrough: true }) res: Response,
@GithubProfile() profile: Profile
@JwtTokenPair() pair: IJwtTokenPair
) {
const id = parseInt(profile.id);

const result = await this.authService.getTokenByGithubId(id);

res.cookie("accessToken", result.accessToken.token, {
maxAge: result.accessToken.expireTime,
...setCookieConfig,
});

res.cookie("refreshToken", result.refreshToken.token, {
maxAge: result.refreshToken.expireTime,
...setCookieConfig,
});

return {
success: true,
};
return this.setCookie(res, pair.accessToken, pair.refreshToken);
}

@Get("whoami")
@UseGuards(AuthGuard("jwt"))
async handleWhoami(@Req() req: Request, @JwtPayload() token: IJwtPayload) {
return token;
async handleWhoami(@JwtPayload() payload: IJwtPayload) {
return payload;
}

@Get("refresh")
@UseGuards(AuthGuard("jwt-refresh"))
async handleRefresh(
@Res({ passthrough: true }) res: Response,
@JwtTokenPair() token: IJwtTokenPair
@JwtTokenPair() pair: IJwtTokenPair
) {
res.cookie("accessToken", token.accessToken.token, {
maxAge: token.accessToken.expireTime,
return this.setCookie(res, pair.accessToken);
}

@Post("login")
@UseGuards(AuthGuard("local"))
async login(@Res({ passthrough: true }) res: Response, @JwtTokenPair() pair: IJwtTokenPair) {
return this.setCookie(res, pair.accessToken, pair.refreshToken);
}

private setCookie(res: Response, accessToken: IJwtToken, refreshToken?: IJwtToken) {
res.cookie("accessToken", accessToken.token, {
maxAge: accessToken.expireTime,
...setCookieConfig,
});

if (refreshToken)
res.cookie("refreshToken", refreshToken.token, {
maxAge: refreshToken.expireTime,
...setCookieConfig,
});

return {
success: true,
};
Expand Down
6 changes: 4 additions & 2 deletions backend/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { Module } from "@nestjs/common";
import { AuthController } from "./auth.controller";
import { AuthService } from "./auth.service";
import { GithubStrategy } from "./github/github.strategy";
import { UserRepository } from "../user/user.repository";
import { UserRepository } from "@/user/user.repository";
import { JwtModule } from "./jwt/jwt.module";
import { LocalStrategy } from "@/auth/local/local.strategy";
import { UserService } from "@/user/user.service";

@Module({
imports: [JwtModule],
controllers: [AuthController],
providers: [AuthService, GithubStrategy, UserRepository],
providers: [AuthService, GithubStrategy, LocalStrategy, UserRepository, UserService],
})
export class AuthModule {}
32 changes: 23 additions & 9 deletions backend/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,45 @@
import { Injectable, UnauthorizedException } from "@nestjs/common";
import { UserRepository } from "../user/user.repository";
import { Injectable } from "@nestjs/common";
import { UserRepository } from "@/user/user.repository";
import { Transactional } from "typeorm-transactional";
import "dotenv/config";
import { DAY, HOUR } from "../utils/time";
import { JwtService } from "./jwt/jwt.service";
import { LoginType } from "@/user/user.entity";
import { createHash } from "node:crypto";

@Injectable()
export class AuthService {
private static ACCESS_TOKEN_EXPIRATION_TIME = 3 * HOUR;
private static ACCESS_TOKEN_EXPIRATION = 30 * DAY;
private static PASSWORD_SALT = process.env.PASSWORD_SALT;

constructor(
private readonly userRepository: UserRepository,
private readonly jwtService: JwtService
) {}

@Transactional()
public async getTokenByGithubId(id: number) {
public async getUserByGithubId(id: number) {
let user = await this.userRepository.getUserByGithubId(id);

if (!user) {
if (!user)
user = await this.userRepository.createUser({
githubId: id,
username: `camper_${id}`,
loginType: LoginType.GITHUB,
});
}

return await this.jwtService.createJwtToken(user.id);
return user;
}

public async getUserByLocal(username: string, password: string) {
const user = await this.userRepository.getUserByLoginId(username);
if (!user) return null;
if (user.passwordHash !== this.generatePasswordHash(password)) return null;

return user;
}

public generatePasswordHash(password: string) {
return createHash("sha256")
.update(password + process.env.SESSION_HASH)
.digest("hex");
}
}
12 changes: 12 additions & 0 deletions backend/src/auth/dto/login.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { IsNotEmpty, IsString } from "class-validator";

// TODO: 프론트에서 정의된 제약사항 이곳에서도 검증하도록 보완하기
export class LoginDto {
@IsString()
@IsNotEmpty()
userId: string;

@IsString()
@IsNotEmpty()
password: string;
}
42 changes: 27 additions & 15 deletions backend/src/auth/github/github.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,59 @@ import { Strategy } from "passport-custom";
import { Request } from "express";
import axios from "axios";
import "dotenv/config";
import { AuthService } from "@/auth/auth.service";
import { JwtService } from "@/auth/jwt/jwt.service";

@Injectable()
export class GithubStrategy extends PassportStrategy(Strategy, "github") {
private static REQUEST_ACCESS_TOKEN_URL =
"https://github.com/login/oauth/access_token";
private static REQUEST_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
private static REQUEST_USER_URL = "https://api.github.com/user";

constructor() {
constructor(
private readonly authService: AuthService,
private readonly jwtService: JwtService
) {
super();
}

async validate(req: Request, done: any) {
async validate(req: Request) {
const { code } = req.body;

if (!code) {
throw new UnauthorizedException("Authorization code not found");
}

const tokenResponse = await axios.post(
const { access_token: accessToken } = (await this.fetchAccessToken(code)).data;

const profile = (await this.fetchGithubUser(accessToken)).data;

const user = await this.authService.getUserByGithubId(profile.id);
const token = await this.jwtService.createJwtToken(user);

return {
jwtToken: token,
};
}

private async fetchAccessToken(code: string) {
return axios.post(
GithubStrategy.REQUEST_ACCESS_TOKEN_URL,
{
client_id: process.env.OAUTH_GITHUB_ID,
client_secret: process.env.OAUTH_GITHUB_SECRET,
code: code,
code,
},
{
headers: { Accept: "application/json" },
}
);
}

const { access_token } = tokenResponse.data;

// GitHub 사용자 정보 조회
const userResponse = await axios.get(GithubStrategy.REQUEST_USER_URL, {
private async fetchGithubUser(accessToken: string) {
return axios.get(GithubStrategy.REQUEST_USER_URL, {
headers: {
Authorization: `Bearer ${access_token}`,
Authorization: `Bearer ${accessToken}`,
},
});

return done(null, {
profile: userResponse.data,
});
}
}
51 changes: 19 additions & 32 deletions backend/src/auth/jwt/jwt.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,55 +6,42 @@ import {
} from "@nestjs/common";
import {
IJwtPayload as IJwtPayload,
IJwtTokenPair as IJwtTokenPair,
IJwtToken as IJwtToken,
IJwtTokenPair as IJwtTokenPair,
} from "./jwt.model";

export const JwtPayload = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const payload = request.user.jwtToken;
export const JwtPayload = createParamDecorator((data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const payload = request.user.jwtToken;

if (!isJwtTokenPayload(payload)) {
throw new UnauthorizedException("Invalid jwt token payload");
}

return payload;
if (!isJwtTokenPayload(payload)) {
throw new UnauthorizedException("Invalid jwt token payload");
}
);

export const JwtTokenPair = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const payload = request.user.jwtToken;
return payload;
});

if (!isJwtTokenPair(payload)) {
throw new InternalServerErrorException("Invalid jwt token");
}
export const JwtTokenPair = createParamDecorator((data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const payload = request.user.jwtToken;

return payload;
if (!isJwtTokenPair(payload)) {
throw new InternalServerErrorException("Invalid jwt token");
}
);

return payload;
});

function isJwtTokenPayload(payload: any): payload is IJwtPayload {
return (
payload &&
typeof payload.userId === "number" &&
typeof payload.username === "string"
);
return payload && typeof payload.userId === "number" && typeof payload.username === "string";
}

function isJwtTokenPair(payload: any): payload is IJwtTokenPair {
if (!payload.accessToken || !payload.refreshToken) return false;
if (!isJwtToken(payload.accessToken)) return false;
if (!isJwtToken(payload.refreshToken)) return false;
return true;
return isJwtToken(payload.refreshToken);
}

function isJwtToken(token: any): token is IJwtToken {
return (
token &&
typeof token.token === "string" &&
typeof token.expireTime === "number"
);
return token && typeof token.token === "string" && typeof token.expireTime === "number";
}
Loading