From 45777ecd4b113f7d910d27ba8e5f43997fdd728b Mon Sep 17 00:00:00 2001 From: Kim Min-gyu <99083803+cobocho@users.noreply.github.com> Date: Wed, 12 Jun 2024 03:16:33 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EB=AF=B8=EB=93=A4=EC=9B=A8?= =?UTF-8?q?=EC=96=B4=20=EC=B6=94=EC=83=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/app/(beforeLogin)/auth/token/page.tsx | 3 +- .../src/app/(beforeLogin)/signup/layout.tsx | 2 +- apps/web/src/middleware.ts | 139 ++++++++++-------- 3 files changed, 77 insertions(+), 67 deletions(-) diff --git a/apps/web/src/app/(beforeLogin)/auth/token/page.tsx b/apps/web/src/app/(beforeLogin)/auth/token/page.tsx index ba48c01..dc8aee8 100644 --- a/apps/web/src/app/(beforeLogin)/auth/token/page.tsx +++ b/apps/web/src/app/(beforeLogin)/auth/token/page.tsx @@ -1,9 +1,8 @@ 'use client' -import { userInfoService } from '@vook-client/api' +import { userInfoService, UserStatus } from '@vook-client/api' import Cookies from 'js-cookie' import { useRouter } from 'next/navigation' -import { UserStatus } from 'node_modules/@vook-client/api/src/services/useUserInfoQuery/model' import { useEffect } from 'react' interface AuthCallbackQueryParams { diff --git a/apps/web/src/app/(beforeLogin)/signup/layout.tsx b/apps/web/src/app/(beforeLogin)/signup/layout.tsx index 3628692..cc7cf2f 100644 --- a/apps/web/src/app/(beforeLogin)/signup/layout.tsx +++ b/apps/web/src/app/(beforeLogin)/signup/layout.tsx @@ -1,4 +1,4 @@ -import React, { PropsWithChildren } from 'react' +import { PropsWithChildren } from 'react' import { loginLayout } from './layout.css' diff --git a/apps/web/src/middleware.ts b/apps/web/src/middleware.ts index ddb1dc2..7b4c0e2 100644 --- a/apps/web/src/middleware.ts +++ b/apps/web/src/middleware.ts @@ -1,85 +1,96 @@ import { NextRequest, NextResponse } from 'next/server' -import { UserInfoResponse, UserStatus } from 'node_modules/@vook-client/api/' +import { UserInfoResponse, UserStatus } from 'node_modules/@vook-client/api' -/** - * NOTE - * 1. 액세스 토큰과 리프레시 토큰이 모두 없는 경우 => 로그인 페이지로 리다이렉트 - * 2. 액세스 토큰만 있는 경우 => 로그인 페이지로 리다이렉트 - * 3. 리프레시 토큰만 있는 경우 => 리프레시 토큰으로 액세스 토큰을 갱신 - * 4. 액세스 토큰과 리프레시 토큰이 모두 있는 경우 => 액세스 토큰이 유효한지 확인 - */ +const checkUserStatusMiddleware = + (roles: Array) => + async ( + req: NextRequest, + finalResponse: NextResponse, + destination: string, + ) => { + const accessToken = req.cookies.get('access')?.value + const refreshToken = req.cookies.get('refresh')?.value -const onlyRegisteredMatch = ['/'] - -const isOnlyRegistered = async ( - req: NextRequest, - finalResponse: NextResponse, -) => { - const accessToken = req.cookies.get('access')?.value - const refreshToken = req.cookies.get('refresh')?.value - - // 1 & 2 - if ((!accessToken && !refreshToken) || (accessToken && !refreshToken)) { - return NextResponse.redirect(`${process.env.NEXT_PUBLIC_DOMAIN}/login`) - } + if ((!accessToken && !refreshToken) || (accessToken && !refreshToken)) { + return NextResponse.redirect( + `${process.env.NEXT_PUBLIC_DOMAIN}${destination}`, + ) + } - // 3 - if (!accessToken && refreshToken) { - const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/refresh`, { - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - 'X-Refresh-Authorization': refreshToken, - }, - }) - if ( - res.ok && - res.headers.get('Authorization') && - res.headers.get('X-Refresh-Authorization') - ) { - finalResponse.cookies.set('access', res.headers.get('Authorization')!) - finalResponse.cookies.set( - 'refresh', - res.headers.get('X-Refresh-Authorization')!, + if (!accessToken && refreshToken) { + const res = await fetch( + `${process.env.NEXT_PUBLIC_API_URL}/auth/refresh`, + { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + 'X-Refresh-Authorization': refreshToken, + }, + }, ) - } else { - return NextResponse.redirect(`${process.env.NEXT_PUBLIC_DOMAIN}/login`) + if ( + res.ok && + res.headers.get('Authorization') && + res.headers.get('X-Refresh-Authorization') + ) { + finalResponse.cookies.set('access', res.headers.get('Authorization')!) + finalResponse.cookies.set( + 'refresh', + res.headers.get('X-Refresh-Authorization')!, + ) + } else { + return NextResponse.redirect( + `${process.env.NEXT_PUBLIC_DOMAIN}${destination}`, + ) + } } - } - const userInfoRes = await fetch( - `${process.env.NEXT_PUBLIC_API_URL}/user/info`, - { - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - Authorization: - finalResponse.cookies.get('access')?.value || accessToken || '', + const userInfoRes = await fetch( + `${process.env.NEXT_PUBLIC_API_URL}/user/info`, + { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: + finalResponse.cookies.get('access')?.value || accessToken || '', + }, }, - }, - ) + ) - if (userInfoRes.ok) { - const userInfo = (await userInfoRes.json()) as UserInfoResponse + if (userInfoRes.ok) { + const userInfo = (await userInfoRes.json()) as UserInfoResponse - // 회원가입이 완료되지 않은 경우 - if (userInfo.result.status === UserStatus.SocialLoginCompleted) { - return NextResponse.redirect(`${process.env.NEXT_PUBLIC_DOMAIN}/login`) + if (!roles.includes(userInfo.result.status)) { + return NextResponse.redirect( + `${process.env.NEXT_PUBLIC_DOMAIN}${destination}`, + ) + } else { + return finalResponse + } } else { - return finalResponse + return NextResponse.redirect( + `${process.env.NEXT_PUBLIC_DOMAIN}${destination}`, + ) } - } else { - return NextResponse.redirect(`${process.env.NEXT_PUBLIC_DOMAIN}/login`) } -} -// eslint-disable-next-line @typescript-eslint/require-await +const onlyRegisteredMatch = ['/'] + export async function middleware(req: NextRequest) { const response = NextResponse.next() if (onlyRegisteredMatch.includes(req.nextUrl.pathname)) { - await isOnlyRegistered(req, response) + return checkUserStatusMiddleware([ + UserStatus.Registered, + UserStatus.Withdrawn, + ])(req, response, '/login') } - return response + if (req.nextUrl.pathname === '/signup') { + return checkUserStatusMiddleware([UserStatus.SocialLoginCompleted])( + req, + response, + '/login', + ) + } }