본문 바로가기
카테고리 없음

jwt3

by 두잇건강 2025. 8. 5.
반응형
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import axios from 'axios'
import { useRouter } from 'vue-router'

export const useAuthStore = defineStore('auth', () => {
  // 상태 (State)
  const user = ref(null)
  const token = ref(localStorage.getItem('jwt-token'))
  const loading = ref(false)
  const error = ref('')

  // 계산된 속성 (Getters)
  const isAuthenticated = computed(() => !!token.value && !!user.value)
  const userEmail = computed(() => user.value?.email || '')
  const userName = computed(() => user.value?.name || '')
  const userRoles = computed(() => user.value?.roles || [])
  const isAdmin = computed(() => userRoles.value.includes('ROLE_ADMIN'))
  const isManager = computed(() => userRoles.value.includes('ROLE_MANAGER'))

  // 액션 (Actions)
  const login = async (credentials) => {
    loading.value = true
    error.value = ''
    
    try {
      const response = await axios.post('/api/authenticate', credentials)
      
      if (response.data.jwt) {
        // 토큰 저장
        token.value = response.data.jwt
        localStorage.setItem('jwt-token', response.data.jwt)
        
        // axios 헤더 설정
        setAuthToken(response.data.jwt)
        
        // 사용자 정보 저장
        user.value = {
          email: response.data.email || credentials.email,
          name: response.data.name || '',
          roles: response.data.roles || ['ROLE_USER'],
          id: response.data.userId || null
        }
        
        // 사용자 정보를 localStorage에도 저장 (새로고침 대응)
        localStorage.setItem('user-info', JSON.stringify(user.value))
        
        return { success: true }
      }
    } catch (err) {
      error.value = err.response?.status === 401 
        ? '이메일 또는 비밀번호가 올바르지 않습니다.' 
        : '로그인 중 오류가 발생했습니다.'
      return { success: false, error: error.value }
    } finally {
      loading.value = false
    }
  }

  const logout = async () => {
    loading.value = true
    
    try {
      // 서버에 로그아웃 요청
      await axios.post('/api/logout')
    } catch (err) {
      console.error('로그아웃 API 호출 실패:', err)
    } finally {
      // 로컬 상태 정리
      clearAuthData()
      loading.value = false
    }
  }

  const fetchUserProfile = async () => {
    if (!token.value) return
    
    loading.value = true
    try {
      const response = await axios.get('/api/user/profile')
      user.value = {
        ...user.value,
        ...response.data
      }
      localStorage.setItem('user-info', JSON.stringify(user.value))
    } catch (err) {
      console.error('사용자 프로필 가져오기 실패:', err)
      if (err.response?.status === 401) {
        clearAuthData()
      }
    } finally {
      loading.value = false
    }
  }

  const updateUserProfile = async (profileData) => {
    loading.value = true
    try {
      const response = await axios.put('/api/user/profile', profileData)
      user.value = { ...user.value, ...response.data }
      localStorage.setItem('user-info', JSON.stringify(user.value))
      return { success: true }
    } catch (err) {
      error.value = '프로필 업데이트 중 오류가 발생했습니다.'
      return { success: false, error: error.value }
    } finally {
      loading.value = false
    }
  }

  const clearAuthData = () => {
    user.value = null
    token.value = null
    error.value = ''
    localStorage.removeItem('jwt-token')
    localStorage.removeItem('user-info')
    delete axios.defaults.headers.common['Authorization']
  }

  const setAuthToken = (authToken) => {
    if (authToken) {
      axios.defaults.headers.common['Authorization'] = `Bearer ${authToken}`
    } else {
      delete axios.defaults.headers.common['Authorization']
    }
  }

  const initializeAuth = () => {
    const savedToken = localStorage.getItem('jwt-token')
    const savedUser = localStorage.getItem('user-info')
    
    if (savedToken && savedUser) {
      token.value = savedToken
      user.value = JSON.parse(savedUser)
      setAuthToken(savedToken)
      
      // 사용자 정보 갱신 (선택적)
      fetchUserProfile()
    }
  }

  return {
    // 상태
    user,
    token,
    loading,
    error,
    
    // 계산된 속성
    isAuthenticated,
    userEmail,
    userName,
    userRoles,
    isAdmin,
    isManager,
    
    // 액션
    login,
    logout,
    fetchUserProfile,
    updateUserProfile,
    clearAuthData,
    initializeAuth
  }
})
반응형