Make auth/admin apps API calls use apiFetch, a new function that asks for permission by iframe if needed. Implement max-age checks for API authz.verify as well along with a custom exception type that carries metadata.

This commit is contained in:
Leo Vasanko
2025-12-03 11:17:02 -06:00
parent 7b0a9c2a2a
commit 1f75e0a305
15 changed files with 411 additions and 147 deletions
+11 -25
View File
@@ -1,13 +1,13 @@
import { defineStore } from 'pinia'
import { register, authenticate } from '@/utils/passkey'
import { getSettings } from '@/utils/settings'
import { apiFetch } from '@/utils/api'
export const useAuthStore = defineStore('auth', {
state: () => ({
// Auth State
userInfo: null, // Contains the full user info response: {user, credentials, aaguid_info}
isLoading: false,
authRequired: false, // Flag to trigger auth iframe
// Settings
settings: null,
@@ -26,9 +26,6 @@ export const useAuthStore = defineStore('auth', {
setLoading(flag) {
this.isLoading = !!flag
},
clearAuthRequired() {
this.authRequired = false
},
showMessage(message, type = 'info', duration = 3000) {
this.status = {
message,
@@ -86,43 +83,32 @@ export const useAuthStore = defineStore('auth', {
this.settings = await getSettings()
},
async loadUserInfo() {
const response = await fetch('/auth/api/user-info', { method: 'POST' })
const response = await apiFetch('/auth/api/user-info', { method: 'POST' })
let result = null
try {
result = await response.json()
} catch (_) {
// ignore JSON parse errors (unlikely)
}
if (response.status === 401) {
this.authRequired = true
throw new Error(result?.detail || 'Authentication required')
}
if (result?.detail) {
// Other error style
this.showMessage(result.detail, 'error', 5000)
throw new Error(result.detail)
if (!response.ok || result?.detail) {
const message = result?.detail || 'Failed to load user info'
this.showMessage(message, 'error', 5000)
throw new Error(message)
}
this.userInfo = result
console.log('User info loaded:', result)
},
async deleteCredential(uuid) {
const response = await fetch(`/auth/api/user/credential/${uuid}`, {method: 'Delete'})
if (response.status === 401) {
this.authRequired = true
throw new Error('Authentication required')
}
const response = await apiFetch(`/auth/api/user/credential/${uuid}`, { method: 'DELETE' })
const result = await response.json()
if (result.detail) throw new Error(result.detail)
if (!response.ok || result.detail) {
throw new Error(result.detail || 'Failed to delete credential')
}
await this.loadUserInfo()
},
async terminateSession(sessionId) {
try {
const res = await fetch(`/auth/api/user/session/${sessionId}`, { method: 'DELETE' })
if (res.status === 401) {
this.authRequired = true
throw new Error('Authentication required')
}
const res = await apiFetch(`/auth/api/user/session/${sessionId}`, { method: 'DELETE' })
let payload = null
try {
payload = await res.json()