feat(web/session): expose isGuest, guestCan, continueAsGuest, guestAllowed

This commit is contained in:
saopig1 committed 2026-06-25 11:58:58 +08:00
1 parent d2ab888114
commit 0c59a9f84a
1 file changed
+23 -1
+23 -1
View File
@@ -3,13 +3,15 @@ import { ref, computed, readonly } from "vue";
interface User { interface User {
id: string; id: string;
username: string; username: string;
role: 'admin' | 'member'; role: 'admin' | 'member' | 'guest';
capabilities?: string[]; capabilities?: string[];
bots?: "all" | string[]; bots?: "all" | string[];
guest?: Record<string, boolean> | null;
} }
const currentUser = ref<User | null>(null); const currentUser = ref<User | null>(null);
const needsSetup = ref<boolean | null>(null); // null = unknown / not fetched yet const needsSetup = ref<boolean | null>(null); // null = unknown / not fetched yet
const guestAllowed = ref(false);
const ready = ref(false); const ready = ref(false);
let pollTimer: ReturnType<typeof setInterval> | null = null; let pollTimer: ReturnType<typeof setInterval> | null = null;
@@ -37,6 +39,7 @@ async function refreshNeedsSetup(): Promise<void> {
if (res.ok) { if (res.ok) {
const body = await res.json(); const body = await res.json();
needsSetup.value = Boolean(body.needsSetup); needsSetup.value = Boolean(body.needsSetup);
guestAllowed.value = Boolean(body.guestAllowed);
} }
} }
@@ -76,6 +79,16 @@ async function login(username: string, password: string): Promise<void> {
await refreshMe(); await refreshMe();
} }
async function continueAsGuest(): Promise<void> {
const res = await fetch("/api/session/guest", { method: "POST", credentials: "same-origin" });
if (!res.ok) {
const body = await res.json().catch(() => ({}));
throw new Error(body.error ?? `guest entry failed (${res.status})`);
}
currentUser.value = (await res.json()) as User;
await refreshMe(); // authoritative role + guest flags + bots
}
async function setup(username: string, password: string): Promise<void> { async function setup(username: string, password: string): Promise<void> {
const res = await fetch("/api/session/setup", { const res = await fetch("/api/session/setup", {
method: "POST", method: "POST",
@@ -104,6 +117,11 @@ function can(cap: string): boolean {
return !!u && (u.role === "admin" || (u.capabilities ?? []).includes(cap)); return !!u && (u.role === "admin" || (u.capabilities ?? []).includes(cap));
} }
function guestCan(flag: string): boolean {
const u = currentUser.value;
return !!u && u.role === "guest" && !!u.guest && u.guest[flag] === true;
}
function canControlBot(botId: string): boolean { function canControlBot(botId: string): boolean {
const u = currentUser.value; const u = currentUser.value;
if (!u) return false; if (!u) return false;
@@ -115,14 +133,18 @@ export function useSession() {
return { return {
currentUser: readonly(currentUser), currentUser: readonly(currentUser),
needsSetup: readonly(needsSetup), needsSetup: readonly(needsSetup),
guestAllowed: readonly(guestAllowed),
isAuthenticated: computed(() => currentUser.value !== null), isAuthenticated: computed(() => currentUser.value !== null),
isAdmin: computed(() => currentUser.value?.role === 'admin'), isAdmin: computed(() => currentUser.value?.role === 'admin'),
isGuest: computed(() => currentUser.value?.role === 'guest'),
ready: readonly(ready), ready: readonly(ready),
refresh, refresh,
login, login,
logout, logout,
setup, setup,
continueAsGuest,
can, can,
guestCan,
canControlBot, canControlBot,
}; };
} }