bmc_hub/static/js/remote-api.js
Christian 85e019783b Add comprehensive test coverage for case creation, assignment, and remote recovery
- Introduced tests for case creation commands, ensuring proper handling of UUIDs and payloads.
- Added tests for v5 assignment functionality, validating employee identification and group assignment.
- Implemented tests for remote recovery scenarios, including handling network failures and response validation.
- Created tests for hardware label generation and validation, ensuring proper URL formatting and QR code generation.
- Developed extensive tests for remote control functionality, covering connection isolation, command execution, and user permissions.
- Added tests for workflow timer registration, ensuring correct handling of timer states and ownership validation.
2026-10-15 12:17:09 +02:00

46 lines
2.1 KiB
JavaScript

export const base = '/api/v1/remote';
let csrf = '';
export async function api(path, data, method = data === undefined ? 'GET' : 'POST') {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 15000);
try {
const response = await fetch(base + path, {method, credentials: 'same-origin', cache: 'no-store', signal: controller.signal,
headers: data === undefined ? {} : {'Content-Type': 'application/json', 'X-Remote-CSRF': csrf},
body: data === undefined ? undefined : JSON.stringify(data)});
if (response.redirected || (response.ok && !response.headers.get('Content-Type')?.includes('application/json'))) {
throw new Error('Hub sendte ikke det forventede svar. Prøver igen…');
}
const result = await response.json();
if (!response.ok) {
const error = new Error(typeof result.detail === 'string' ? result.detail : 'Kontrollér oplysningerne og prøv igen');
error.status = response.status;
error.retry = Number(response.headers.get('Retry-After') || 0);
throw error;
}
return result;
} catch (error) {
if (error.status || error.message?.includes('forventede svar')) throw error;
throw new Error('Forbindelsen til Hub er afbrudt. Prøver igen…');
} finally { clearTimeout(timeout); }
}
export async function bootstrap() {
const result = await api('/bootstrap');
csrf = result.csrf;
return result;
}
export function element(tag, text, className) {
const node = document.createElement(tag);
node.textContent = text;
if (className) node.className = className;
return node;
}
// getRandomValues also works on HTTP local-network origins.
export function requestId() {
const bytes = crypto.getRandomValues(new Uint8Array(16));
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`;
}