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:
@@ -150,9 +150,23 @@ export class ApiError extends Error {
|
||||
|
||||
async function httpCall(cmd: string, args: Record<string, any>, retries = 3): Promise<any> {
|
||||
const base = getApiBase()
|
||||
const { url, method, body, timeout: requestTimeout } = buildHttpRequest(cmd, args)
|
||||
const { url, method, body, timeout: requestTimeout, requiresAdminToken } = buildHttpRequest(cmd, args)
|
||||
const fullUrl = url.startsWith('http://') || url.startsWith('https://') ? url : `${base}${url}`
|
||||
|
||||
// Get admin token from localStorage if needed
|
||||
const headers: Record<string, string> = body ? { 'Content-Type': 'application/json' } : {}
|
||||
if (requiresAdminToken) {
|
||||
const stored = localStorage.getItem('mb_admin_token')
|
||||
if (stored) {
|
||||
try {
|
||||
const data = JSON.parse(stored)
|
||||
if (new Date(data.expires_at) > new Date()) {
|
||||
headers['Authorization'] = `Bearer ${data.token}`
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
const controller = new AbortController()
|
||||
const timeout = setTimeout(() => controller.abort(), requestTimeout ?? DEFAULT_TIMEOUT)
|
||||
|
||||
@@ -162,7 +176,7 @@ async function httpCall(cmd: string, args: Record<string, any>, retries = 3): Pr
|
||||
try {
|
||||
response = await fetch(fullUrl, {
|
||||
method,
|
||||
headers: body ? { 'Content-Type': 'application/json' } : {},
|
||||
headers,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
signal: controller.signal,
|
||||
})
|
||||
@@ -238,7 +252,7 @@ async function httpCall(cmd: string, args: Record<string, any>, retries = 3): Pr
|
||||
}
|
||||
}
|
||||
|
||||
function buildHttpRequest(cmd: string, args: Record<string, any>): { url: string; method: string; body?: any; timeout?: number } {
|
||||
function buildHttpRequest(cmd: string, args: Record<string, any>): { url: string; method: string; body?: any; timeout?: number; requiresAdminToken?: boolean } {
|
||||
const a = args
|
||||
|
||||
switch (cmd) {
|
||||
@@ -668,9 +682,11 @@ case 'search_keyword': {
|
||||
return { url, method: 'GET' }
|
||||
}
|
||||
case 'list_admin_users':
|
||||
return { url: '/api/v2/admin/users', method: 'GET' }
|
||||
return { url: '/api/v2/admin/users', method: 'GET', requiresAdminToken: true }
|
||||
case 'list_shares':
|
||||
return { url: '/api/v2/admin/shares', method: 'GET' }
|
||||
case 'admin_login':
|
||||
return { url: '/api/v2/admin/login', method: 'POST', body: { username: a.username, password: a.password } }
|
||||
|
||||
// --- Pose & Appearance ---
|
||||
case 'get_pose': {
|
||||
|
||||
Reference in New Issue
Block a user