refactor: modify member permission verification logic

- 매물 조회 권한 검증 로직 리팩토링
This commit is contained in:
Dayoung 2025-06-04 10:51:11 +09:00
parent e756465250
commit 0c27c19341
4 changed files with 55 additions and 23 deletions

View File

@ -3,30 +3,63 @@ import { prisma } from '@/libs/prisma'
import { convertToSnakeCase } from '@/utils/common-utils' import { convertToSnakeCase } from '@/utils/common-utils'
import { SessionData } from '@/types/Auth' import { SessionData } from '@/types/Auth'
type SessionParams = { interface Survey {
SRL_NO: string
SUBMISSION_STATUS: boolean
SUBMISSION_TARGET_ID: string | null
STORE_ID: string | null
CONSTRUCTION_POINT_ID: string | null
}
interface SessionParams {
role: string | null role: string | null
storeId: string | null storeId: string | null
builderNo: string | null builderNo: string | null
isLoggedIn: string | null isLoggedIn: string | null
} }
const checkRole = (survey: any, sessionParams: SessionParams) => { const checkT01Role = (survey: Survey): boolean => survey.SRL_NO !== '一時保存'
const checkAdminRole = (survey: Survey, storeId: string | null): boolean => {
if (!storeId) return false
if (survey.SUBMISSION_STATUS) {
return survey.SUBMISSION_TARGET_ID === storeId || survey.STORE_ID === storeId
}
return survey.STORE_ID === storeId
}
const checkAdminSubRole = (survey: Survey, storeId: string | null): boolean => {
if (!storeId) return false
if (survey.SUBMISSION_STATUS) {
return survey.SUBMISSION_TARGET_ID === storeId || (survey.STORE_ID === storeId && survey.CONSTRUCTION_POINT_ID === null)
}
return survey.STORE_ID === storeId && survey.CONSTRUCTION_POINT_ID === null
}
const checkPartnerOrBuilderRole = (survey: Survey, builderNo: string | null): boolean => {
if (!builderNo) return false
return survey.CONSTRUCTION_POINT_ID === builderNo
}
const checkRole = (survey: Survey, sessionParams: SessionParams): boolean => {
if (!survey || !sessionParams.role) return false
switch (sessionParams.role) { switch (sessionParams.role) {
case 'T01': case 'T01':
return true return checkT01Role(survey)
// T01 이외 1차점
case 'Admin': case 'Admin':
if (survey.SUBMISSION_STATUS) { return checkAdminRole(survey, sessionParams.storeId)
return survey.SUBMISSION_TARGET_ID === sessionParams.storeId // 2차점
}
return survey.STORE_ID === sessionParams.storeId
case 'Admin_Sub': case 'Admin_Sub':
if (survey.SUBMISSION_STATUS) { return checkAdminSubRole(survey, sessionParams.storeId)
return survey.SUBMISSION_TARGET_ID === sessionParams.builderNo // partner
}
return survey.STORE_ID === sessionParams.storeId && survey.CONSTRUCTION_POINT_ID === sessionParams.builderNo
case 'Partner': case 'Partner':
// 2차점 시공권한 user
case 'Builder': case 'Builder':
return survey.CONSTRUCTION_POINT_ID === sessionParams.builderNo return checkPartnerOrBuilderRole(survey, sessionParams.builderNo)
default: default:
return false return false
} }
@ -54,6 +87,8 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
}) })
if (checkRole(survey, sessionParams)) { if (checkRole(survey, sessionParams)) {
return NextResponse.json(survey) return NextResponse.json(survey)
} else {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
} }
} catch (error) { } catch (error) {
console.error('Error fetching survey:', error) console.error('Error fetching survey:', error)

View File

@ -90,12 +90,7 @@ const createMemberRoleCondition = (params: SearchParams): WhereCondition => {
where.OR = [ where.OR = [
{ {
// MUSUBI (시공권한 X) 같은 판매점에서 작성한 제출/제출되지 않은 매물 // MUSUBI (시공권한 X) 같은 판매점에서 작성한 제출/제출되지 않은 매물
AND: [ AND: [{ STORE_ID: { equals: params.storeId } }, { CONSTRUCTION_POINT_ID: { equals: params.builderNo } }],
{ STORE_ID: { equals: params.storeId } },
{
OR: [{ CONSTRUCTION_POINT_ID: { equals: null } }, { CONSTRUCTION_POINT_ID: { equals: '' } }],
},
],
}, },
{ {
// MUSUBI (시공권한 O) 가 MUSUBI 에 제출한 매물 + PARTNER 가 제출한 매물 // MUSUBI (시공권한 O) 가 MUSUBI 에 제출한 매물 + PARTNER 가 제출한 매물

View File

@ -5,7 +5,7 @@ import { useEffect, useState } from 'react'
import ButtonForm from './ButtonForm' import ButtonForm from './ButtonForm'
import BasicForm from './BasicForm' import BasicForm from './BasicForm'
import RoofForm from './RoofForm' import RoofForm from './RoofForm'
import { useParams, useSearchParams } from 'next/navigation' import { useParams, useSearchParams, useRouter } from 'next/navigation'
import { useSurvey } from '@/hooks/useSurvey' import { useSurvey } from '@/hooks/useSurvey'
import { useSessionStore } from '@/store/session' import { useSessionStore } from '@/store/session'
@ -71,10 +71,12 @@ export default function DetailForm() {
const idParam = useSearchParams().get('id') const idParam = useSearchParams().get('id')
const routeId = useParams().id const routeId = useParams().id
const router = useRouter()
const modeset = Number(routeId) ? 'READ' : idParam ? 'EDIT' : 'CREATE' const modeset = Number(routeId) ? 'READ' : idParam ? 'EDIT' : 'CREATE'
const id = Number(routeId) ? Number(routeId) : Number(idParam) const id = Number(routeId) ? Number(routeId) : Number(idParam)
const { surveyDetail, validateSurveyDetail } = useSurvey(Number(id)) const { surveyDetail, isLoadingSurveyDetail, validateSurveyDetail } = useSurvey(Number(id))
const { session } = useSessionStore() const { session } = useSessionStore()
const [mode, setMode] = useState<Mode>(modeset) const [mode, setMode] = useState<Mode>(modeset)
@ -82,9 +84,10 @@ export default function DetailForm() {
const [roofInfoData, setRoofInfoData] = useState<SurveyDetailRequest>(roofInfoForm) const [roofInfoData, setRoofInfoData] = useState<SurveyDetailRequest>(roofInfoForm)
useEffect(() => { useEffect(() => {
if (Number(idParam) !== 0 || surveyDetail === null) { if (isLoadingSurveyDetail) return
if (surveyDetail === null) {
alert('権限がありません。') alert('権限がありません。')
window.location.href = '/survey-sale' router.replace('/survey-sale')
} }
if (surveyDetail && (mode === 'EDIT' || mode === 'READ')) { if (surveyDetail && (mode === 'EDIT' || mode === 'READ')) {
const { id, uptDt, regDt, detailInfo, ...rest } = surveyDetail const { id, uptDt, regDt, detailInfo, ...rest } = surveyDetail

View File

@ -5,7 +5,6 @@ import { useSurveyFilterStore } from '@/store/surveyFilterStore'
import { useSessionStore } from '@/store/session' import { useSessionStore } from '@/store/session'
import { useAxios } from './useAxios' import { useAxios } from './useAxios'
import { queryStringFormatter } from '@/utils/common-utils' import { queryStringFormatter } from '@/utils/common-utils'
import { AxiosError } from 'axios'
export const requiredFields = [ export const requiredFields = [
{ {