공개 로그인 관리자 진입 개선
This commit is contained in:
@@ -3,6 +3,7 @@ import { z } from 'zod'
|
||||
import { createError, readBody } from 'h3'
|
||||
import { getUserByEmail, touchUserActivity } from '../../repositories/member-repository'
|
||||
import { setMemberSession } from '../../utils/member-auth'
|
||||
import { setAdminSession } from '../../utils/admin-auth'
|
||||
import { getClientIp } from '../../utils/request-ip'
|
||||
import {
|
||||
assertLoginAttemptAllowed,
|
||||
@@ -18,7 +19,7 @@ const loginSchema = z.object({
|
||||
/**
|
||||
* 회원 로그인 API
|
||||
* @param {import('h3').H3Event} event - 요청 이벤트
|
||||
* @returns {Promise<{ id: string, username: string, email: string }>} 회원 정보
|
||||
* @returns {Promise<{ id: string, username: string, email: string, avatarUrl: string, isAdmin: boolean }>} 회원 정보
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const parsedBody = loginSchema.safeParse(await readBody(event))
|
||||
@@ -57,6 +58,13 @@ export default defineEventHandler(async (event) => {
|
||||
email: user.email,
|
||||
sessionVersion: user.sessionVersion
|
||||
})
|
||||
if (user.isAdmin) {
|
||||
setAdminSession(event, {
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
sessionVersion: user.sessionVersion
|
||||
})
|
||||
}
|
||||
await touchUserActivity({
|
||||
userId: user.id,
|
||||
ip
|
||||
@@ -66,6 +74,7 @@ export default defineEventHandler(async (event) => {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
avatarUrl: user.avatarUrl || ''
|
||||
avatarUrl: user.avatarUrl || '',
|
||||
isAdmin: Boolean(user.isAdmin)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { clearAdminSession } from '../../utils/admin-auth'
|
||||
import { clearMemberSession } from '../../utils/member-auth'
|
||||
|
||||
/**
|
||||
@@ -6,7 +7,7 @@ import { clearMemberSession } from '../../utils/member-auth'
|
||||
* @returns {{ ok: true }} 처리 결과
|
||||
*/
|
||||
export default defineEventHandler((event) => {
|
||||
clearAdminSession(event)
|
||||
clearMemberSession(event)
|
||||
return { ok: true }
|
||||
})
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ export default defineEventHandler(async (event) => {
|
||||
const session = getAdminSession(event)
|
||||
|
||||
if (!session) {
|
||||
if (pathname === '/admin/api/auth/me') {
|
||||
return
|
||||
}
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
message: '관리자 로그인이 필요합니다.'
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
import { getAdminSession, requireAdminSession } from '../../../../utils/admin-auth'
|
||||
import { getMemberForAdmin } from '../../../../repositories/member-repository'
|
||||
import { clearAdminSession, getAdminSession, requireAdminSession, setAdminSession } from '../../../../utils/admin-auth'
|
||||
import { clearMemberSession, getVerifiedMemberSession } from '../../../../utils/member-auth'
|
||||
import { getMemberForAdmin, isPrivilegedMemberSession } from '../../../../repositories/member-repository'
|
||||
|
||||
/**
|
||||
* 공개 회원 세션이 관리자 권한이면 관리자 세션으로 승격한다.
|
||||
* @param {import('h3').H3Event} event - 요청 이벤트
|
||||
* @returns {Promise<{ userId: string, email: string, role: 'admin', sessionVersion: number } | null>} 관리자 세션
|
||||
*/
|
||||
const bridgeMemberAdminSession = async (event) => {
|
||||
const memberSession = await getVerifiedMemberSession(event)
|
||||
|
||||
if (!memberSession) {
|
||||
return null
|
||||
}
|
||||
|
||||
const isPrivileged = await isPrivilegedMemberSession(memberSession.userId, memberSession.sessionVersion)
|
||||
if (!isPrivileged) {
|
||||
return null
|
||||
}
|
||||
|
||||
const adminSession = {
|
||||
userId: memberSession.userId,
|
||||
email: memberSession.email,
|
||||
role: 'admin',
|
||||
sessionVersion: memberSession.sessionVersion
|
||||
}
|
||||
|
||||
setAdminSession(event, adminSession)
|
||||
return adminSession
|
||||
}
|
||||
|
||||
/**
|
||||
* 관리자 세션 조회 API
|
||||
@@ -8,7 +37,24 @@ import { getMemberForAdmin } from '../../../../repositories/member-repository'
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const isOptional = getQuery(event).optional === '1'
|
||||
const session = isOptional ? getAdminSession(event) : requireAdminSession(event)
|
||||
let session = getAdminSession(event)
|
||||
|
||||
if (session) {
|
||||
const isPrivileged = await isPrivilegedMemberSession(session.userId, session.sessionVersion)
|
||||
if (!isPrivileged) {
|
||||
clearAdminSession(event)
|
||||
clearMemberSession(event)
|
||||
session = null
|
||||
}
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
session = await bridgeMemberAdminSession(event)
|
||||
}
|
||||
|
||||
if (!session && !isOptional) {
|
||||
session = requireAdminSession(event)
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user