Files

180 lines
4.2 KiB
TypeScript

/**
* 인증 상태 관리 composable
*/
interface User {
employeeId: number
employeeName: string
employeeEmail: string
employeePosition: string | null
roles?: string[] // 권한 코드 배열 추가
}
interface MenuItem {
menuId: number
menuCode: string
menuName: string
menuPath: string | null
menuIcon: string | null
parentMenuId: number | null
sortOrder: number
children: MenuItem[]
}
// 전역 상태
const currentUser = ref<User | null>(null)
const userMenus = ref<MenuItem[]>([])
const isLoading = ref(false)
export function useAuth() {
/**
* 현재 로그인 사용자 조회
*/
async function fetchCurrentUser(): Promise<User | null> {
try {
isLoading.value = true
const response = await $fetch<{ user: User | null }>('/api/auth/current-user')
currentUser.value = response.user
// 로그인된 경우 메뉴 정보도 가져오기
if (response.user) {
await fetchUserMenus()
} else {
userMenus.value = []
}
return response.user
} catch (error) {
currentUser.value = null
userMenus.value = []
return null
} finally {
isLoading.value = false
}
}
/**
* 사용자 메뉴 조회
*/
async function fetchUserMenus(): Promise<void> {
try {
const response = await $fetch<{ menus: MenuItem[] }>('/api/auth/menu')
userMenus.value = response.menus
} catch (error) {
console.error('메뉴 조회 실패:', error)
userMenus.value = []
}
}
/**
* 이메일+이름으로 로그인
*/
async function login(email: string, name: string): Promise<User> {
const response = await $fetch<{ user: User }>('/api/auth/login', {
method: 'POST',
body: { email, name }
})
currentUser.value = response.user
await fetchUserMenus()
return response.user
}
/**
* 기존 사용자 선택 로그인
*/
async function selectUser(employeeId: number): Promise<User> {
const response = await $fetch<{ user: User }>('/api/auth/select-user', {
method: 'POST',
body: { employeeId }
})
currentUser.value = response.user
await fetchUserMenus()
return response.user
}
/**
* 최근 로그인 사용자 목록
*/
async function getRecentUsers(): Promise<User[]> {
const response = await $fetch<{ users: User[] }>('/api/auth/recent-users')
return response.users
}
/**
* 로그아웃
*/
async function logout(): Promise<void> {
await $fetch('/api/auth/logout', { method: 'POST' })
currentUser.value = null
userMenus.value = []
}
/**
* 로그인 여부 확인
*/
const isLoggedIn = computed(() => currentUser.value !== null)
/**
* 특정 권한 보유 여부 확인
*/
function hasRole(roleCode: string): boolean {
return currentUser.value?.roles?.includes(roleCode) ?? false
}
/**
* 특정 메뉴 접근 가능 여부 확인
*/
function hasMenuAccess(menuCode: string): boolean {
const findMenu = (menus: MenuItem[]): boolean => {
for (const menu of menus) {
if (menu.menuCode === menuCode) return true
if (menu.children && findMenu(menu.children)) return true
}
return false
}
return findMenu(userMenus.value)
}
/**
* 특정 경로 접근 가능 여부 확인
*/
function hasPathAccess(path: string): boolean {
const findPath = (menus: MenuItem[]): boolean => {
for (const menu of menus) {
if (menu.menuPath && path.startsWith(menu.menuPath)) return true
if (menu.children && findPath(menu.children)) return true
}
return false
}
return findPath(userMenus.value)
}
/**
* 관리자 여부 (ROLE_ADMIN)
*/
const isAdmin = computed(() => hasRole('ROLE_ADMIN'))
/**
* 매니저 이상 여부 (ROLE_MANAGER 또는 ROLE_ADMIN)
*/
const isManager = computed(() => hasRole('ROLE_MANAGER') || hasRole('ROLE_ADMIN'))
return {
currentUser: readonly(currentUser),
userMenus: readonly(userMenus),
isLoading: readonly(isLoading),
isLoggedIn,
isAdmin,
isManager,
fetchCurrentUser,
fetchUserMenus,
login,
selectUser,
getRecentUsers,
logout,
hasRole,
hasMenuAccess,
hasPathAccess
}
}