feat: expand cockpit integrations and support workflows

Add Phoenix remote desktop, action connector, documentation engine, and gamification support. Refactor support-case processing and search/action UI, and update installer assets and dependencies.
This commit is contained in:
Meik
2026-07-13 11:16:53 +02:00
parent bbedbf71c8
commit 0b52999b1d
303 changed files with 11235 additions and 3580 deletions

View File

@@ -0,0 +1,116 @@
using C4IT.FASD.Base;
using C4IT.FASD.Cockpit.Communication;
using C4IT.FASD.Communication.Agent;
using C4IT.HTTP;
using FasdCockpitBase;
using FasdCockpitBase.Models.RemoteDesktopConnection;
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace FasdCockpitCommunication.RemoteDesktopCommunication
{
internal class AgentRemoteDesktopCommunication : RemoteDesktopCommunicationBase
{
private readonly HttpClient _httpClient = new HttpClient();
public AgentRemoteDesktopCommunication()
{
_httpClient.BaseAddress = new Uri(cFasdCockpitMachineConfiguration.Instance.ServerUrl);
}
public override async Task<T> InitiateConnection<T>(IRemoteDesktopClientInfo clientInfo, bool isElevated, CancellationToken token)
{
cHttpHelper httpHelper = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
string json = JsonConvert.SerializeObject(clientInfo);
string path = "api/RemoteDesktop/Initiate";
if (isElevated)
path += "?isElevated=true";
cHttpResult result = await httpHelper.PostJsonAsync(path, json, 30_000, token);
return JsonConvert.DeserializeObject<T>(result.Result);
}
public override async Task<RemoteDesktopConnectionStatusResult> GetConnectionStatus(Guid connectionId, CancellationToken token)
{
cHttpHelper http = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
string path = $"api/RemoteDesktop/{connectionId}/Status";
cHttpResult result = await http.GetHttpJson(path, 15_000, token, true);
if (!result.IsOk)
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Unknown);
AgentRemoteConnectionStatusDto connectionStatus = JsonConvert.DeserializeObject<AgentRemoteConnectionStatusDto>(result.Result);
return GetGeneralConnectionStatus(connectionStatus);
}
private RemoteDesktopConnectionStatusResult GetGeneralConnectionStatus(AgentRemoteConnectionStatusDto connectionStatus)
{
switch (connectionStatus.Status)
{
case AgentRemoteConnectionStatus.New:
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Initiated);
case AgentRemoteConnectionStatus.Accepted:
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Accepted);
case AgentRemoteConnectionStatus.DisconnectedByHelpdesk:
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Finished);
case AgentRemoteConnectionStatus.DisconnectedByClient:
case AgentRemoteConnectionStatus.Failed:
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Canceled);
case AgentRemoteConnectionStatus.Unknown:
default:
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Unknown);
}
}
public override async Task StopConnection(Guid connectionId, CancellationToken token)
{
cHttpHelper http = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
string path = $"api/RemoteDesktop/{connectionId}/Stop";
await http.DeleteAsync(path, 15_000, token, true);
}
public override async Task<HealthInformation> GetHealth(CancellationToken token)
{
cHttpHelper http = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
string path = $"api/RemoteDesktop/health";
cHttpResult result = await http.GetHttpJson(path, 10_000, token, true);
if (!result.IsOk)
return new HealthInformation(HealthStatus.unhealthy);
return JsonConvert.DeserializeObject<HealthInformation>(result.Result);
}
public override async Task<bool> IsRemoteDesktopCommunicationAvailable()
{
cHttpHelper http = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
string path = $"api/RemoteDesktop/IsActive";
cHttpResult result = await http.GetHttpJson(path, 5_000, CancellationToken.None, false);
if (!result.IsOk)
return false;
bool isRemoteViewerActive = JsonConvert.DeserializeObject<bool>(result.Result); ;
if (!isRemoteViewerActive)
return false;
return await base.IsRemoteDesktopCommunicationAvailable();
}
}
public class AgentRemoteClientInfo : IRemoteDesktopClientInfo
{
[JsonProperty("orgCode")]
public int OrganisationCode { get; set; }
[JsonProperty("deviceCode")]
public int DeviceCode { get; set; }
[JsonProperty("accountCode")]
public int AccountCode { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using FasdCockpitBase.Models.RemoteDesktopConnection;
using Newtonsoft.Json;
using System;
namespace FasdCockpitCommunication.RemoteDesktopCommunication
{
public class AgentRemoteDesktopConnecitonDetails : ApiResult, IRemoteDesktopConnectionDetails
{
[JsonProperty("connectionId")]
public Guid ConnectionId { get; set; }
[JsonProperty("phoenixServiceUrl")]
public Uri PhoenixServiceUrl { get; set; }
[JsonProperty("secret")]
public string Secret { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using Newtonsoft.Json;
using System.Collections.Generic;
namespace FasdCockpitCommunication.RemoteDesktopCommunication
{
public class ApiResult
{
[JsonProperty("errors")]
public IList<ApiError> Errors { get; set; }
}
public class ApiError
{
[JsonProperty("code")]
public string Code { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
}
}