File size: 6,279 Bytes
69b897d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
import { defineStore } from 'pinia'
import axios from 'axios'
import { showToast } from '@/utils/toast'
import { API_PREFIX } from '@/config/api'
const API_BASE = `${API_PREFIX}/users`
export const useUserStore = defineStore('user', {
state: () => ({
user: null,
isAuthenticated: false,
sessionToken: null,
loading: false,
config: null
}),
getters: {
isLoggedIn: (state) => state.isAuthenticated && state.user,
userName: (state) => state.user?.displayName || state.user?.username,
userRole: (state) => state.user?.role
},
actions: {
// 🔐 用户登录
async login(credentials) {
this.loading = true
try {
const response = await axios.post(`${API_BASE}/login`, credentials)
if (response.data.success) {
this.user = response.data.user
this.sessionToken = response.data.sessionToken
this.isAuthenticated = true
// 保存到 localStorage
localStorage.setItem('userToken', this.sessionToken)
localStorage.setItem('userData', JSON.stringify(this.user))
// 设置 axios 默认头部
this.setAuthHeader()
return response.data
} else {
throw new Error(response.data.message || 'Login failed')
}
} catch (error) {
this.clearAuth()
throw error
} finally {
this.loading = false
}
},
// 🚪 用户登出
async logout() {
try {
if (this.sessionToken) {
await axios.post(
`${API_BASE}/logout`,
{},
{
headers: { 'x-user-token': this.sessionToken }
}
)
}
} catch (error) {
console.error('Logout request failed:', error)
} finally {
this.clearAuth()
}
},
// 🔄 检查认证状态
async checkAuth() {
const token = localStorage.getItem('userToken')
const userData = localStorage.getItem('userData')
const userConfig = localStorage.getItem('userConfig')
if (!token || !userData) {
this.clearAuth()
return false
}
try {
this.sessionToken = token
this.user = JSON.parse(userData)
this.config = userConfig ? JSON.parse(userConfig) : null
this.isAuthenticated = true
this.setAuthHeader()
// 验证 token 是否仍然有效
await this.getUserProfile()
return true
} catch (error) {
console.error('Auth check failed:', error)
this.clearAuth()
return false
}
},
// 👤 获取用户资料
async getUserProfile() {
try {
const response = await axios.get(`${API_BASE}/profile`)
if (response.data.success) {
this.user = response.data.user
this.config = response.data.config
localStorage.setItem('userData', JSON.stringify(this.user))
localStorage.setItem('userConfig', JSON.stringify(this.config))
return response.data.user
}
} catch (error) {
if (error.response?.status === 401 || error.response?.status === 403) {
// 401: Invalid/expired session, 403: Account disabled
this.clearAuth()
// If it's a disabled account error, throw a specific error
if (error.response?.status === 403) {
throw new Error(error.response.data?.message || 'Your account has been disabled')
}
}
throw error
}
},
// 🔑 获取用户API Keys
async getUserApiKeys(includeDeleted = false) {
try {
const params = {}
if (includeDeleted) {
params.includeDeleted = 'true'
}
const response = await axios.get(`${API_BASE}/api-keys`, { params })
return response.data.success ? response.data.apiKeys : []
} catch (error) {
console.error('Failed to fetch API keys:', error)
throw error
}
},
// 🔑 创建API Key
async createApiKey(keyData) {
try {
const response = await axios.post(`${API_BASE}/api-keys`, keyData)
return response.data
} catch (error) {
console.error('Failed to create API key:', error)
throw error
}
},
// 🗑️ 删除API Key
async deleteApiKey(keyId) {
try {
const response = await axios.delete(`${API_BASE}/api-keys/${keyId}`)
return response.data
} catch (error) {
console.error('Failed to delete API key:', error)
throw error
}
},
// 📊 获取使用统计
async getUserUsageStats(params = {}) {
try {
const response = await axios.get(`${API_BASE}/usage-stats`, { params })
return response.data.success ? response.data.stats : null
} catch (error) {
console.error('Failed to fetch usage stats:', error)
throw error
}
},
// 🧹 清除认证信息
clearAuth() {
this.user = null
this.sessionToken = null
this.isAuthenticated = false
this.config = null
localStorage.removeItem('userToken')
localStorage.removeItem('userData')
localStorage.removeItem('userConfig')
// 清除 axios 默认头部
delete axios.defaults.headers.common['x-user-token']
},
// 🔧 设置认证头部
setAuthHeader() {
if (this.sessionToken) {
axios.defaults.headers.common['x-user-token'] = this.sessionToken
}
},
// 🔧 设置axios拦截器
setupAxiosInterceptors() {
// Response interceptor to handle disabled user responses globally
axios.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 403) {
const message = error.response.data?.message
if (message && (message.includes('disabled') || message.includes('Account disabled'))) {
this.clearAuth()
showToast(message, 'error')
// Redirect to login page
if (window.location.pathname !== '/user-login') {
window.location.href = '/user-login'
}
}
}
return Promise.reject(error)
}
)
}
}
})
|