feat: integrate MarkBase Admin API with Bearer token authentication

- Added useAdminAuth composable for login/logout/token management
- Admin Users tab now requires login before showing users
- loadUsers/loadShares now use direct fetch with Bearer token
- Added login form with username/password fields
- Token stored in localStorage with expiry check
- Default credentials: demo/demo123
This commit is contained in:
2026-10-27 02:17:41 +08:00
parent 4129c174ed
commit 3b638f0416
4 changed files with 169 additions and 14 deletions

View File

@@ -0,0 +1,76 @@
import { ref } from 'vue'
import { getApiBase } from '@/api/config'
export interface AdminToken {
token: string
expires_at: string
username: string
}
export function useAdminAuth() {
const token = ref<string | null>(null)
const username = ref<string | null>(null)
const expiresAt = ref<string | null>(null)
const loading = ref(false)
const error = ref<string | null>(null)
// Load token from localStorage on init
const stored = localStorage.getItem('mb_admin_token')
if (stored) {
try {
const data = JSON.parse(stored)
if (new Date(data.expires_at) > new Date()) {
token.value = data.token
username.value = data.username
expiresAt.value = data.expires_at
} else {
localStorage.removeItem('mb_admin_token')
}
} catch {
localStorage.removeItem('mb_admin_token')
}
}
async function login(usernameVal: string, password: string): Promise<boolean> {
loading.value = true
error.value = null
try {
const base = getApiBase()
const resp = await fetch(`${base}/api/v2/admin/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: usernameVal, password })
})
const data = await resp.json()
if (!resp.ok) throw new Error(data.error || 'Login failed')
token.value = data.token
username.value = data.username
expiresAt.value = data.expires_at
localStorage.setItem('mb_admin_token', JSON.stringify(data))
return true
} catch (e: any) {
error.value = e.message || 'Login failed'
return false
} finally {
loading.value = false
}
}
function logout() {
token.value = null
username.value = null
expiresAt.value = null
localStorage.removeItem('mb_admin_token')
}
function isLoggedIn(): boolean {
return !!token.value && (expiresAt.value ? new Date(expiresAt.value) > new Date() : false)
}
function getAuthHeader(): Record<string, string> {
return token.value ? { 'Authorization': `Bearer ${token.value}` } : {}
}
return { token, username, expiresAt, loading, error, login, logout, isLoggedIn, getAuthHeader }
}