-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/#32-front-layout' of https://github.com/Kumoh-t…
…alk/kumoh-talk-Frontend into feature/#34-profile-image
- Loading branch information
Showing
28 changed files
with
813 additions
and
350 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,276 @@ | ||
import { NextRequest, NextResponse } from 'next/server'; | ||
import { getCookie, parseJwt } from '@/app/lib/apis/auth'; | ||
import { refreshToken } from '@/app/lib/apis/user'; | ||
|
||
const baseUrl = `${process.env.NEXT_PUBLIC_API_URL}/api/v1`; | ||
|
||
const convertCookieToHeaders = (cookies: string | null): HeadersInit => | ||
cookies | ||
? { | ||
'Content-Type': 'application/json', | ||
Authorization: `Bearer ${getCookie(cookies, 'accessToken')}`, | ||
} | ||
: { | ||
'Content-Type': 'application/json', | ||
}; | ||
|
||
const _fetch = async ( | ||
url: string, | ||
options: RequestInit, | ||
body?: string | any, | ||
) => { | ||
if (body && typeof body !== 'string') { | ||
options.body = JSON.stringify(body); | ||
} | ||
return await fetch(url, options); | ||
}; | ||
|
||
const refreshAndRetry = async ( | ||
request: NextRequest, | ||
func: (request: NextRequest, params: any) => Promise<NextResponse>, | ||
params: any, | ||
accessToken?: string, | ||
_refreshToken?: string, | ||
) => { | ||
if (!accessToken || !_refreshToken) { | ||
return NextResponse.json({ status: 403 }); | ||
} | ||
|
||
const newTokenRes = await refreshToken(accessToken, _refreshToken!); | ||
|
||
if (newTokenRes.status === 200) { | ||
const body = await newTokenRes.json(); | ||
const tokenBody: { | ||
accessToken: string; | ||
refreshToken: string; | ||
} = body.data; | ||
|
||
const res2 = await func(request, params); | ||
|
||
res2.cookies.set('accessToken', tokenBody.accessToken, { | ||
httpOnly: true, | ||
secure: process.env.NODE_ENV === 'production', | ||
path: '/', | ||
}); | ||
res2.cookies.set('refreshToken', tokenBody.refreshToken, { | ||
httpOnly: true, | ||
secure: process.env.NODE_ENV === 'production', | ||
path: '/', | ||
}); | ||
return res2; | ||
} else { | ||
return NextResponse.json({ status: 403 }); | ||
} | ||
}; | ||
|
||
export async function GET( | ||
request: NextRequest, | ||
{ params }: { params: { domain: string } }, | ||
): Promise<NextResponse> { | ||
const cookies = request.headers.get('cookie'); | ||
const headers = convertCookieToHeaders(cookies); | ||
|
||
const searchParams = request.nextUrl.searchParams; | ||
|
||
if (cookies && getCookie(cookies, 'accessToken')) { | ||
const accessToken = getCookie(cookies, 'accessToken')!; | ||
const { USER_ID: userId } = parseJwt(accessToken); | ||
searchParams.append('userId', '' + userId); | ||
} | ||
console.log(`${baseUrl}/${params.domain}?${searchParams.toString()}`) | ||
|
||
const res = await _fetch( | ||
`${baseUrl}/${params.domain}?${searchParams.toString()}`, | ||
{ | ||
method: 'GET', | ||
headers, | ||
}, | ||
); | ||
const body = await res.json(); | ||
|
||
// 토큰 만료 | ||
if (res.status === 401) { | ||
console.log('Token expired, refreshing token'); | ||
return refreshAndRetry( | ||
request, | ||
GET, | ||
{ params }, | ||
getCookie(cookies!, 'accessToken')!, | ||
getCookie(cookies!, 'refreshToken')!, | ||
); | ||
} | ||
|
||
return NextResponse.json(body, { status: res.status }); | ||
} | ||
|
||
export async function POST( | ||
request: NextRequest, | ||
{ params }: { params: { domain: string } }, | ||
): Promise<NextResponse> { | ||
const cookies = request.headers.get('cookie'); | ||
const headers = convertCookieToHeaders(cookies); | ||
|
||
const searchParams = request.nextUrl.searchParams; | ||
|
||
if (cookies && getCookie(cookies, 'accessToken')) { | ||
const accessToken = getCookie(cookies, 'accessToken')!; | ||
const { USER_ID: userId } = parseJwt(accessToken); | ||
searchParams.append('userId', '' + userId); | ||
} | ||
|
||
const res = await _fetch( | ||
`${baseUrl}/${params.domain}?${searchParams.toString()}`, | ||
{ | ||
method: 'POST', | ||
headers, | ||
}, | ||
await request.json(), | ||
); | ||
|
||
// 토큰 만료 | ||
if (res.status === 401) { | ||
console.log('Token expired, refreshing token'); | ||
return refreshAndRetry( | ||
request, | ||
POST, | ||
{ params }, | ||
getCookie(cookies!, 'accessToken')!, | ||
getCookie(cookies!, 'refreshToken')!, | ||
); | ||
} | ||
|
||
return NextResponse.json(await res.json(), { status: res.status }); | ||
} | ||
|
||
export async function PUT( | ||
request: NextRequest, | ||
{ params }: { params: { domain: string } }, | ||
): Promise<NextResponse> { | ||
const cookies = request.headers.get('cookie'); | ||
const headers = convertCookieToHeaders(cookies); | ||
|
||
const searchParams = request.nextUrl.searchParams; | ||
|
||
if (cookies && getCookie(cookies, 'accessToken')) { | ||
const accessToken = getCookie(cookies, 'accessToken')!; | ||
const { USER_ID: userId } = parseJwt(accessToken); | ||
searchParams.append('userId', '' + userId); | ||
} | ||
|
||
const res = await _fetch( | ||
`${baseUrl}/${params.domain}?${searchParams.toString()}`, | ||
{ | ||
method: 'PUT', | ||
headers, | ||
}, | ||
await request.json(), | ||
); | ||
|
||
// 토큰 만료 | ||
if (res.status === 401) { | ||
console.log('Token expired, refreshing token'); | ||
return refreshAndRetry( | ||
request, | ||
PUT, | ||
{ params }, | ||
getCookie(cookies!, 'accessToken')!, | ||
getCookie(cookies!, 'refreshToken')!, | ||
); | ||
} | ||
|
||
return NextResponse.json(await res.json(), { status: res.status }); | ||
} | ||
|
||
export async function PATCH( | ||
request: NextRequest, | ||
{ params }: { params: { domain: string } }, | ||
): Promise<NextResponse> { | ||
const cookies = request.headers.get('cookie'); | ||
const headers = convertCookieToHeaders(cookies); | ||
|
||
const searchParams = request.nextUrl.searchParams; | ||
|
||
if (cookies && getCookie(cookies, 'accessToken')) { | ||
const accessToken = getCookie(cookies, 'accessToken')!; | ||
const { USER_ID: userId } = parseJwt(accessToken); | ||
searchParams.append('userId', '' + userId); | ||
} | ||
|
||
const res = await _fetch( | ||
`${baseUrl}/${params.domain}?${searchParams.toString()}`, | ||
{ | ||
method: 'PATCH', | ||
headers, | ||
}, | ||
await request.json(), | ||
); | ||
|
||
const resBody = await res.json(); | ||
console.log(res.status, resBody); | ||
|
||
// 토큰 만료 | ||
if (res.status === 401) { | ||
console.log('Token expired, refreshing token'); | ||
return refreshAndRetry( | ||
request, | ||
PATCH, | ||
{ params }, | ||
getCookie(cookies!, 'accessToken')!, | ||
getCookie(cookies!, 'refreshToken')!, | ||
); | ||
} | ||
|
||
const response = NextResponse.json(resBody, { status: res.status }); | ||
if (resBody.data?.accessToken) { | ||
response.cookies.set('accessToken', resBody.data.accessToken, { | ||
httpOnly: true, | ||
secure: process.env.NODE_ENV === 'production', | ||
path: '/', | ||
}); | ||
response.cookies.set('refreshToken', resBody.data.refreshToken, { | ||
httpOnly: true, | ||
secure: process.env.NODE_ENV === 'production', | ||
path: '/', | ||
}); | ||
} | ||
|
||
return response; | ||
} | ||
|
||
export async function DELETE( | ||
request: NextRequest, | ||
{ params }: { params: { domain: string } }, | ||
): Promise<NextResponse> { | ||
const cookies = request.headers.get('cookie'); | ||
const headers = convertCookieToHeaders(cookies); | ||
|
||
const searchParams = request.nextUrl.searchParams; | ||
|
||
if (cookies && getCookie(cookies, 'accessToken')) { | ||
const accessToken = getCookie(cookies, 'accessToken')!; | ||
const { USER_ID: userId } = parseJwt(accessToken); | ||
searchParams.append('userId', '' + userId); | ||
} | ||
|
||
const res = await _fetch( | ||
`${baseUrl}/${params.domain}?${searchParams.toString()}`, | ||
{ | ||
method: 'DELETE', | ||
headers, | ||
}, | ||
); | ||
|
||
// 토큰 만료 | ||
if (res.status === 401) { | ||
console.log('Token expired, refreshing token'); | ||
return refreshAndRetry( | ||
request, | ||
DELETE, | ||
{ params }, | ||
getCookie(cookies!, 'accessToken')!, | ||
getCookie(cookies!, 'refreshToken')!, | ||
); | ||
} | ||
|
||
return NextResponse.json(await res.json(), { status: res.status }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
export default function SeminarCommentSvg() { | ||
return ( | ||
<svg | ||
width="16" | ||
height="16" | ||
viewBox="0 0 16 16" | ||
fill="none" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
d="M2.28334 15.6929H2.25478C2.02929 15.6921 1.81333 15.6018 1.65438 15.4418C1.49543 15.2819 1.40649 15.0654 1.40711 14.8399V14.7984C1.41275 14.7258 1.42576 14.6539 1.44595 14.5839L2.08179 12.2836C2.06532 12.236 2.04419 12.1902 2.01871 12.1468C2.00308 12.1208 1.98613 12.0956 1.96791 12.0714L1.94965 12.0455C1.17708 10.875 0.766001 9.5031 0.767614 8.10065C0.761637 6.18914 1.5097 4.3819 2.87435 3.01227C4.28515 1.59715 6.17607 0.817872 8.19914 0.817872C9.91504 0.817236 11.58 1.40088 12.92 2.47272C14.2302 3.52725 15.1406 4.99615 15.4829 6.61281C15.5884 7.10333 15.6419 7.60358 15.6426 8.10529C15.6426 10.0623 14.8909 11.9001 13.5259 13.281C12.1483 14.6739 10.2992 15.4412 8.31834 15.4412C7.61775 15.4412 6.72758 15.2632 6.30025 15.1424C5.77431 14.9949 5.26431 14.799 5.24306 14.7907C5.18597 14.7687 5.12529 14.7575 5.0641 14.7575C4.99773 14.7571 4.93197 14.7702 4.87086 14.7961L4.84396 14.8067L2.60408 15.6162C2.51066 15.6548 2.41212 15.6796 2.31156 15.6899L2.28334 15.6929ZM2.83019 11.4485C2.86771 11.4997 2.90324 11.5534 2.93578 11.6079L2.94009 11.6155C3.13201 11.9512 3.1931 12.2534 3.12205 12.512L2.5732 14.4976L4.47109 13.8126C4.84007 13.6617 5.25271 13.6571 5.6249 13.8C5.64515 13.8079 6.109 13.9866 6.58779 14.12C7.03504 14.2452 7.79406 14.3784 8.31967 14.3784C11.7728 14.3784 14.5814 11.5644 14.5814 8.10529C14.581 7.67806 14.5357 7.25205 14.4463 6.83428C13.836 3.9632 11.2097 1.88037 8.19914 1.88037C6.46062 1.88037 4.83666 2.54875 3.62707 3.76233C2.46297 4.93008 1.8248 6.47004 1.83011 8.09899C1.82878 9.28927 2.17648 10.4538 2.83019 11.4485Z" | ||
fill="white" | ||
/> | ||
<path | ||
d="M5.0176 9.31788C5.6044 9.31788 6.0801 8.84218 6.0801 8.25538C6.0801 7.66857 5.6044 7.19288 5.0176 7.19288C4.4308 7.19288 3.9551 7.66857 3.9551 8.25538C3.9551 8.84218 4.4308 9.31788 5.0176 9.31788Z" | ||
fill="white" | ||
/> | ||
<path | ||
d="M8.2051 9.31788C8.7919 9.31788 9.2676 8.84218 9.2676 8.25538C9.2676 7.66857 8.7919 7.19288 8.2051 7.19288C7.6183 7.19288 7.1426 7.66857 7.1426 8.25538C7.1426 8.84218 7.6183 9.31788 8.2051 9.31788Z" | ||
fill="white" | ||
/> | ||
<path | ||
d="M11.3926 9.31788C11.9794 9.31788 12.4551 8.84218 12.4551 8.25538C12.4551 7.66857 11.9794 7.19288 11.3926 7.19288C10.8058 7.19288 10.3301 7.66857 10.3301 8.25538C10.3301 8.84218 10.8058 9.31788 11.3926 9.31788Z" | ||
fill="white" | ||
/> | ||
</svg> | ||
); | ||
} |
Oops, something went wrong.