Keep map reads open; gate admin UI/nav and object mutations behind env-based admin credentials, and default parser batch limit to 10. Co-authored-by: Cursor <cursoragent@cursor.com>
41 lines
1.1 KiB
TypeScript
41 lines
1.1 KiB
TypeScript
import { computed, ref } from "vue";
|
|
|
|
const TOKEN_KEY = "mapmil_admin_token";
|
|
const ADMIN_BASE = "/admin";
|
|
|
|
const token = ref<string | null>(localStorage.getItem(TOKEN_KEY));
|
|
|
|
export function getToken(): string | null {
|
|
return token.value;
|
|
}
|
|
|
|
export function setToken(value: string | null): void {
|
|
token.value = value;
|
|
if (value) localStorage.setItem(TOKEN_KEY, value);
|
|
else localStorage.removeItem(TOKEN_KEY);
|
|
}
|
|
|
|
export function clearToken(): void {
|
|
setToken(null);
|
|
}
|
|
|
|
export const isAuthenticated = computed(() => Boolean(token.value));
|
|
|
|
export async function login(username: string, password: string): Promise<void> {
|
|
const response = await fetch(`${ADMIN_BASE}/auth/login`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ username, password }),
|
|
});
|
|
if (!response.ok) {
|
|
const message = await response.text();
|
|
throw new Error(message || `Ошибка входа: ${response.status}`);
|
|
}
|
|
const data = (await response.json()) as { access_token: string };
|
|
setToken(data.access_token);
|
|
}
|
|
|
|
export function logout(): void {
|
|
clearToken();
|
|
}
|