Files
sb-front/src/stores/auth.js
T

68 lines
1.7 KiB
JavaScript
Raw Normal View History

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { authApi } from '@/api/authApi'
// 세션은 Redis(서버) + localStorage(클라이언트) 양쪽에 보관한다.
const TOKEN_KEY = 'token'
const USER_KEY = 'auth_user'
export const useAuthStore = defineStore('auth', () => {
const token = ref(localStorage.getItem(TOKEN_KEY) || '')
const user = ref(safeParse(localStorage.getItem(USER_KEY)))
const isAuthenticated = computed(() => !!token.value)
function persist() {
if (token.value) localStorage.setItem(TOKEN_KEY, token.value)
else localStorage.removeItem(TOKEN_KEY)
if (user.value) localStorage.setItem(USER_KEY, JSON.stringify(user.value))
else localStorage.removeItem(USER_KEY)
}
async function login(loginId, password, rememberMe = false) {
const res = await authApi.login({ loginId, password, rememberMe })
token.value = res.token
user.value = res.member
persist()
return res
}
async function signup(payload) {
return authApi.signup(payload)
}
// 서버 세션 기준으로 현재 사용자 정보 동기화 (토큰 유효성 확인 용도)
async function fetchMe() {
const me = await authApi.me()
user.value = { ...(user.value || {}), ...me }
persist()
return me
}
async function logout() {
try {
await authApi.logout()
} catch {
// 서버 세션이 이미 만료됐어도 클라이언트는 정리
}
clear()
}
function clear() {
token.value = ''
user.value = null
persist()
}
return { token, user, isAuthenticated, login, signup, fetchMe, logout, clear }
})
function safeParse(value) {
try {
return value ? JSON.parse(value) : null
} catch {
return null
}
}