mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-05-15 03:25:40 +08:00
133 lines
3.2 KiB
TypeScript
133 lines
3.2 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
|
|
export const AUTH_TOKEN_STORAGE_KEY = 'os_access_token'
|
|
|
|
interface Credentials {
|
|
email: string
|
|
password: string
|
|
}
|
|
|
|
interface RegisterPayload extends Credentials {
|
|
name?: string
|
|
invitationCode: string
|
|
acceptTerms: boolean
|
|
acceptPrivacy: boolean
|
|
}
|
|
|
|
type UserRole = 'user' | 'admin' | 'dev'
|
|
|
|
interface AuthUser {
|
|
id: string
|
|
email: string
|
|
name?: string
|
|
role: UserRole
|
|
createdAt: string
|
|
}
|
|
|
|
interface AuthState {
|
|
accessToken: string
|
|
user: AuthUser | null
|
|
initialized: boolean
|
|
}
|
|
|
|
function loadToken(): string {
|
|
if (typeof window === 'undefined') return ''
|
|
return localStorage.getItem(AUTH_TOKEN_STORAGE_KEY) || ''
|
|
}
|
|
|
|
function persistToken(token: string) {
|
|
if (typeof window === 'undefined') return
|
|
if (token) {
|
|
localStorage.setItem(AUTH_TOKEN_STORAGE_KEY, token)
|
|
} else {
|
|
localStorage.removeItem(AUTH_TOKEN_STORAGE_KEY)
|
|
}
|
|
}
|
|
|
|
export const useAuthStore = defineStore('auth', {
|
|
state: (): AuthState => ({
|
|
accessToken: loadToken(),
|
|
user: null,
|
|
initialized: false,
|
|
}),
|
|
getters: {
|
|
isAuthenticated: (state) => Boolean(state.accessToken),
|
|
},
|
|
actions: {
|
|
setAccessToken(token: string) {
|
|
this.accessToken = token
|
|
persistToken(token)
|
|
},
|
|
setUser(user: AuthUser | null) {
|
|
this.user = user
|
|
},
|
|
async login(payload: Credentials) {
|
|
const response = await $fetch<{ accessToken: string; user: AuthUser }>('/api/service/auth/login', {
|
|
method: 'POST',
|
|
body: payload,
|
|
})
|
|
this.setAccessToken(response.accessToken)
|
|
this.setUser(response.user)
|
|
return response.user
|
|
},
|
|
async register(payload: RegisterPayload) {
|
|
const response = await $fetch<{ accessToken: string; user: AuthUser }>('/api/service/auth/register', {
|
|
method: 'POST',
|
|
body: payload,
|
|
})
|
|
this.setAccessToken(response.accessToken)
|
|
this.setUser(response.user)
|
|
return response.user
|
|
},
|
|
async tryRefresh() {
|
|
try {
|
|
const response = await $fetch<{ accessToken: string }>('/api/service/auth/refresh', {
|
|
method: 'POST',
|
|
})
|
|
this.setAccessToken(response.accessToken)
|
|
return true
|
|
} catch {
|
|
this.setAccessToken('')
|
|
return false
|
|
}
|
|
},
|
|
async fetchUser() {
|
|
if (!this.accessToken) {
|
|
this.setUser(null)
|
|
this.initialized = true
|
|
return null
|
|
}
|
|
try {
|
|
const user = await $fetch<AuthUser>('/api/auth/me', {
|
|
headers: { Authorization: `Bearer ${this.accessToken}` },
|
|
})
|
|
this.setUser(user)
|
|
this.initialized = true
|
|
return user
|
|
} catch (err) {
|
|
console.warn('Failed to load user session', err)
|
|
this.setAccessToken('')
|
|
this.setUser(null)
|
|
this.initialized = true
|
|
return null
|
|
}
|
|
},
|
|
async logout() {
|
|
try {
|
|
if (this.accessToken) {
|
|
await $fetch('/api/auth/logout', {
|
|
method: 'POST',
|
|
headers: { Authorization: `Bearer ${this.accessToken}` },
|
|
})
|
|
}
|
|
} catch (err) {
|
|
console.warn('Logout failed', err)
|
|
} finally {
|
|
this.setAccessToken('')
|
|
this.setUser(null)
|
|
}
|
|
},
|
|
},
|
|
})
|
|
|