- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma binaryTargets for openssl 3.0 - nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal cron, http->https redirect - prisma: add origin_goods.delisted migration, sync missing schema (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz - api: CORS wildcard reflection, helmet CORP cross-origin, price backfill in persistProductDetail, categoryIcon ancestor fallback, mediaByColor per-color gallery in public goods detail - admin: /admin base path (vite + router) - import-data.mjs: udt_name casting, serial sequence advance fix
68 lines
1.8 KiB
TypeScript
68 lines
1.8 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
import type { LoginRequest, User } from '@/types'
|
|
import { authApi } from '@/api/auth'
|
|
|
|
export const useAuthStore = defineStore('auth', () => {
|
|
// The session lives in HttpOnly cookies set by the API; nothing
|
|
// security-relevant is stored client-side. `user` is just UI state,
|
|
// restored from the server via /auth/me on app start.
|
|
const user = ref<User | null>(null)
|
|
const sessionChecked = ref(false)
|
|
|
|
// Tokens moved to HttpOnly cookies; clean up any stale values from the
|
|
// previous localStorage-based session.
|
|
localStorage.removeItem('token')
|
|
localStorage.removeItem('user')
|
|
|
|
const isLoggedIn = computed(() => !!user.value)
|
|
|
|
// Restore the session once per app start. The router guard awaits this
|
|
// so a page refresh on a protected route does not bounce to /login.
|
|
async function ensureSessionChecked() {
|
|
if (sessionChecked.value) return
|
|
sessionChecked.value = true
|
|
try {
|
|
user.value = await authApi.getCurrentUser()
|
|
} catch {
|
|
user.value = null
|
|
}
|
|
}
|
|
|
|
function setUser(newUser: User | null) {
|
|
user.value = newUser
|
|
}
|
|
|
|
async function login(payload: LoginRequest) {
|
|
const res = await authApi.login(payload) as any
|
|
const userData: User | null = res.user ?? res.data?.user ?? null
|
|
sessionChecked.value = true
|
|
setUser(userData)
|
|
return res
|
|
}
|
|
|
|
async function fetchCurrentUser() {
|
|
const current = await authApi.getCurrentUser()
|
|
setUser(current)
|
|
return current
|
|
}
|
|
|
|
async function logout() {
|
|
try {
|
|
await authApi.logout()
|
|
} catch {
|
|
// Ignore network errors during logout
|
|
}
|
|
setUser(null)
|
|
}
|
|
|
|
return {
|
|
user,
|
|
isLoggedIn,
|
|
ensureSessionChecked,
|
|
login,
|
|
fetchCurrentUser,
|
|
logout,
|
|
}
|
|
})
|