Publish curated Unraid-AppOps-Gateway source from 034c9f844d2455850ba37b31379b7edaa786583e

This commit is contained in:
Public Source Publisher committed 2026-10-01 19:39:31 +00:00
1 parent c61fbfd87f
commit 1a54836efc
101 files changed
+4973 -1298

No files matched your search

+34 -21
View File
@@ -1,9 +1,11 @@
import { setUserSessionStatus } from './userSession';
import { ActionID, ActionPlan, ActionRegistryDetail, ActionRegistryResponse, ActionResult, ApprovalRequest, AiMemoryItem, AiRecommendation, App, AuditDetail, AuditEvent, Connector, ConnectorBinding, ConnectorCandidate, ConnectorSettings, ConnectorSettingsPayload, DeepHealth, HealthCheck, HomeAssistantExport, HomeAssistantVoiceReadiness, Incident, JobRun, NetworkExposure, PreflightPreview, RuntimeInfo, SetupCompleteResult, SetupConnectionTestResult, SetupReconcileResult, SetupStatus, Stack, StorageSummary, Container, ContainerLogsResponse, StatisticsSummary, SystemSummary, UnraidSummary, VoiceCommand, SourceType, PolicyRule, Playbook, PolicyDecision, RiskLevel, AiToolPermission, Status, SonarrAddSeriesPayload, SonarrHealth, SonarrQueueSummary, SonarrSearchResponse, SonarrWantedSummary, RadarrAddMoviePayload, RadarrHealth, RadarrQueueSummary, RadarrSearchResponse, RadarrWantedSummary, InventoryDiscoveryResult, InventoryDriftItem, InventoryMapExistingPayload, InventoryReviewUpdatePayload, InventoryRunSummary, DiscoveredContainer, AppContainerMapping, WidefrogActivity, WidefrogDownloadStatus, WidefrogFailedJobs, WidefrogHealth, WidefrogQueueSummary, SecretsResponse, SqliteBackupCreateResult, SqliteBackupsResponse, SqliteBackupVerifyResult, SqliteCheckpointResult, SqliteMaintenanceStatus, ProwlarrApplicationStatus, ProwlarrHealth, ProwlarrIndexerHealth, ProwlarrIndexerStatus, ProwlarrSearchTest, ProwlarrSyncStatus, DelugeDownloadSummary, DelugeHealth, DelugeSessionStatus, DelugeTorrentStatus, DelugeSpeedStatus, PlexHealth, PlexLibraryStatus, PlexRecentMedia, PlexServerStatus, PlexSessionStatus, PlexStreamSummary, TautulliActivity, TautulliHealth, TautulliHistory, TautulliLibraries, TautulliPlexInfo, TautulliRecentlyAdded, TautulliStatus, TautulliStreamSummary, TautulliUsers, TautulliWatchStats, NpmAccessLists, NpmCertificates, NpmExposureSummary, NpmHealth, NpmHostReachability, NpmProxyHosts, NpmSecurityWarnings, AuthentikApplication, AuthentikAuthCoverage, AuthentikCollection, AuthentikEvent, AuthentikFlowsSummary, AuthentikHealth, AuthentikOAuth2Provider, AuthentikOutpost, AuthentikOutpostHealth, AuthentikPoliciesSummary, AuthentikProvider, AuthentikProxyProvider, AuthentikSecurityWarnings, AuthentikSystemStatus, MediaPipelineActivity, MediaPipelineCheckResult, MediaPipelineDiagnosis, MediaPipelineDownloads, MediaPipelineFlow, MediaPipelineIssues, MediaPipelineLibrary, MediaPipelineRecommendations, MediaPipelineSummary, VoiceIntentTestResult } from '../types/appops';
import { AISummary, AIRecommendation, AIChatMessage, AIAutopilotRule, AITool } from '../types/ai';
import { toIsoString } from '@/lib/backendDateTime';
import type { AiSecurityFinding, AiSecurityRecommendation, AiSecurityReviewResult, AiSecurityScope, AiSecuritySummary, NotificationChannel, NotificationEvaluationResult, NotificationEvent, NotificationRule, NotificationSummary, RemediationApprovalProposal, RemediationDryRunResult, RemediationPlan, RemediationPlanCollection, SafetyDashboard, SafetyFinding, SafetyRecommendation, SafetyScoreBreakdown, SafetySection, SafetySummary, UnraidDisksResponse, UnraidDockerResponse, UnraidSharesResponse, UnraidVmCapabilitiesResponse, UnraidVmsResponse } from '../types/appops';
import type { GiteaActionsStatus, IntegrationStatus, OperatorAuthPolicy, OperatorSessionStatus, RagQueryResult, RagStatus, RunnerFleetStatus } from '../types/appops';
import type { GiteaActionsStatus, IntegrationStatus, GatewayUser, IdentityProvider, PermissionDefinition, UserAccessUpdate, UserAuthSession, RagQueryResult, RagStatus, RunnerFleetStatus } from '../types/appops';
import type { DeliveryStatus, DeploymentJob, Enrollment, EnrollmentCapabilities, WorkMeshPromotion } from '../types/appops';
import type { ExposurePreferences, ManagedAiConfig, ManagedAiConfigUpdate, ManagedAiStatus, ManagedAiInference } from '../types/appops';
type HealthStatus = {
status: string;
@@ -39,6 +41,8 @@ const safetyConfig: LiveClientConfig = {
requestTimeoutMs: 30000,
};
const aiConfig: LiveClientConfig = { ...defaultConfig, requestTimeoutMs: 65000 };
const containerListConfig: LiveClientConfig = {
...defaultConfig,
requestTimeoutMs: 30000,
@@ -74,12 +78,21 @@ const redactText = (input: string): string => {
const friendlyBackendError = (status: number, message: string): string => {
if (status === 401) {
return "Operatorautorisatie ontbreekt of is verlopen. Meld opnieuw aan via de accountproxy of ontgrendel dit tabblad via Instellingen → Beveiliging.";
return "Je aanmelding ontbreekt of is verlopen. Meld opnieuw aan via Authentik of Microsoft Entra.";
}
if (status === 403) {
return "Backend autorisatie is geweigerd.";
return "Je account heeft geen rechten voor deze actie.";
}
return `Backend ${status}: ${redactText(message || "Request failed")}`;
let detail = message || "Request failed";
try {
const parsed = JSON.parse(detail) as { detail?: unknown };
if (typeof parsed.detail === 'string') detail = parsed.detail;
else if (parsed.detail && typeof parsed.detail === 'object' && !Array.isArray(parsed.detail)) {
const named = parsed.detail as { message?: string; code?: string; correlationId?: string };
if (typeof named.message === 'string') detail = `${named.message}${named.code ? ` (${named.code})` : ''}${named.correlationId ? ` · ${named.correlationId}` : ''}`;
}
} catch { /* Keep the existing redacted text for non-JSON backend errors. */ }
return `Backend ${status}: ${redactText(detail)}`;
};
const request = async <T>(
@@ -107,6 +120,7 @@ const request = async <T>(
});
if (!response.ok) {
if (response.status === 401) setUserSessionStatus({ authenticated: false, user: null, permissions: [] });
const message = await response.text();
throw new Error(friendlyBackendError(response.status, message || response.statusText));
}
@@ -362,23 +376,16 @@ export const createLiveClient = () => ({
async getSystemSummary(): Promise<SystemSummary> { return get<SystemSummary>('/api/system/summary', defaultConfig); },
async getHealth(): Promise<HealthStatus> { return get<HealthStatus>('/api/health', defaultConfig); },
async getRuntimeInfo(): Promise<RuntimeInfo> { return get<RuntimeInfo>('/api/runtime/info', defaultConfig); },
async getOperatorSession(): Promise<OperatorSessionStatus> { return get<OperatorSessionStatus>('/api/operator/session', defaultConfig); },
async getOperatorAuthPolicy(): Promise<OperatorAuthPolicy> { return get<OperatorAuthPolicy>('/api/runtime/operator-auth', defaultConfig); },
async updateOperatorAuthPolicy(required: boolean): Promise<OperatorAuthPolicy> {
return request<OperatorAuthPolicy>('/api/runtime/operator-auth', defaultConfig, {
method: 'PATCH',
body: JSON.stringify({ required }),
});
async getUserSession(): Promise<UserAuthSession> { return get<UserAuthSession>('/api/auth/session', defaultConfig); },
async getIdentityProviders(): Promise<IdentityProvider[]> { return get<IdentityProvider[]>('/api/auth/providers', defaultConfig); },
signIn(provider: IdentityProvider['id']): void {
window.location.assign(`${defaultConfig.baseUrl}/api/auth/login/${encodeURIComponent(provider)}`);
},
async unlockOperatorSession(token: string): Promise<OperatorSessionStatus> {
return request<OperatorSessionStatus>('/api/operator/session', defaultConfig, {
method: 'POST',
headers: { 'X-AppOps-Operator-Token': token },
body: '{}',
});
},
async lockOperatorSession(): Promise<OperatorSessionStatus> {
return request<OperatorSessionStatus>('/api/operator/session', defaultConfig, { method: 'DELETE' });
async logout(): Promise<UserAuthSession> { return request<UserAuthSession>('/api/auth/logout', defaultConfig, { method: 'POST' }); },
async getUsers(): Promise<GatewayUser[]> { return get<GatewayUser[]>('/api/auth/users', defaultConfig); },
async getPermissionDefinitions(): Promise<PermissionDefinition[]> { return get<PermissionDefinition[]>('/api/auth/permissions', defaultConfig); },
async updateUserAccess(id: string, payload: UserAccessUpdate): Promise<GatewayUser> {
return request<GatewayUser>(`/api/auth/users/${encodeURIComponent(id)}`, defaultConfig, { method: 'PATCH', body: JSON.stringify(payload) });
},
async getDeepHealth(): Promise<DeepHealth> { return get<DeepHealth>('/api/health/deep', defaultConfig); },
async exportAdminData(kind: 'config' | 'policies' | 'inventory' | 'audit-summary'): Promise<Record<string, unknown>> {
@@ -524,6 +531,12 @@ export const createLiveClient = () => ({
return post<ActionResult>('/api/audit/export', { format }, defaultConfig);
},
async testConnector(id: string): Promise<ActionResult> { return post<ActionResult>(`/api/connectors/${id}/test`, {}, defaultConfig); },
async getExposurePreferences(): Promise<ExposurePreferences> { return get<ExposurePreferences>('/api/settings/exposure', defaultConfig); },
async updateExposurePreferences(payload: ExposurePreferences): Promise<ExposurePreferences> { return patch<ExposurePreferences>('/api/settings/exposure', payload, defaultConfig); },
async getManagedAiConfig(): Promise<ManagedAiConfig> { return get<ManagedAiConfig>('/api/settings/ai', defaultConfig); },
async getManagedAiStatus(): Promise<ManagedAiStatus> { return get<ManagedAiStatus>('/api/settings/ai/status', defaultConfig); },
async updateManagedAiConfig(payload: ManagedAiConfigUpdate): Promise<ManagedAiConfig> { return patch<ManagedAiConfig>('/api/settings/ai', payload, defaultConfig); },
async testManagedAiInference(): Promise<ManagedAiInference & { success: boolean }> { return post<ManagedAiInference & { success: boolean }>('/api/settings/ai/test', {}, aiConfig); },
async getAISummary(): Promise<AISummary> { return get<AISummary>('/api/ai/status', defaultConfig); },
async getAIRecommendations(): Promise<AIRecommendation[]> { return get<AIRecommendation[]>('/api/ai/recommendations', defaultConfig); },
async getAIChatHistory(): Promise<AIChatMessage[]> { return get<AIChatMessage[]>('/api/ai/history', defaultConfig); },
@@ -531,7 +544,7 @@ export const createLiveClient = () => ({
async getAIMemory(): Promise<AiMemoryItem[]> { return get<AiMemoryItem[]>('/api/ai/memory', defaultConfig); },
async getAITools(): Promise<AITool[]> { return get<AITool[]>('/api/ai/tools', defaultConfig); },
async sendAIChatMessage(content: string): Promise<AIChatMessage> {
return post<AIChatMessage>('/api/ai/chat', { content }, defaultConfig);
return post<AIChatMessage>('/api/ai/chat', { content }, aiConfig);
},
async getIntegrationStatus(): Promise<IntegrationStatus> {
return get<IntegrationStatus>('/api/integrations/status', defaultConfig);