Publish curated Unraid-AppOps-Gateway source from 034c9f844d2455850ba37b31379b7edaa786583e
This commit is contained in:
1 parent
c61fbfd87f
commit
1a54836efc
101 files changed
+4973
-1298
No files matched your search
+34
-21
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user