net8, language features, bugfixes

This commit is contained in:
kkb 2023-12-18 16:31:00 +01:00
parent 1591618c2c
commit ce99053a10
353 changed files with 3245 additions and 3944 deletions

View file

@ -39,6 +39,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Remote.Shared", "sr
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Remote.Windows", "src\Remote\Insight.Remote.Windows\Insight.Remote.Windows.csproj", "{AF313B47-3079-407F-91D1-9989C1E1AF2A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Remote.Windows", "src\Remote\Insight.Remote.Windows\Insight.Remote.Windows.csproj", "{AF313B47-3079-407F-91D1-9989C1E1AF2A}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Infrastructure.Web", "src\Core\Insight.Infrastructure.Web\Insight.Infrastructure.Web.csproj", "{39B81A0D-A88C-44D3-9624-1A19C78A4310}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -85,6 +87,10 @@ Global
{AF313B47-3079-407F-91D1-9989C1E1AF2A}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF313B47-3079-407F-91D1-9989C1E1AF2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF313B47-3079-407F-91D1-9989C1E1AF2A}.Release|Any CPU.ActiveCfg = Release|Any CPU {AF313B47-3079-407F-91D1-9989C1E1AF2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF313B47-3079-407F-91D1-9989C1E1AF2A}.Release|Any CPU.Build.0 = Release|Any CPU {AF313B47-3079-407F-91D1-9989C1E1AF2A}.Release|Any CPU.Build.0 = Release|Any CPU
{39B81A0D-A88C-44D3-9624-1A19C78A4310}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39B81A0D-A88C-44D3-9624-1A19C78A4310}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39B81A0D-A88C-44D3-9624-1A19C78A4310}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39B81A0D-A88C-44D3-9624-1A19C78A4310}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -100,6 +106,7 @@ Global
{2A391CA2-F96B-4DB7-80AA-0668A5141640} = {140F73DD-29D3-4C44-809B-5B470880AA0D} {2A391CA2-F96B-4DB7-80AA-0668A5141640} = {140F73DD-29D3-4C44-809B-5B470880AA0D}
{5C4697BD-BC97-484F-9DB1-CA87E2BEAA4B} = {D4D7BF4A-B2E3-470A-A14C-FC658FF7461D} {5C4697BD-BC97-484F-9DB1-CA87E2BEAA4B} = {D4D7BF4A-B2E3-470A-A14C-FC658FF7461D}
{AF313B47-3079-407F-91D1-9989C1E1AF2A} = {D4D7BF4A-B2E3-470A-A14C-FC658FF7461D} {AF313B47-3079-407F-91D1-9989C1E1AF2A} = {D4D7BF4A-B2E3-470A-A14C-FC658FF7461D}
{39B81A0D-A88C-44D3-9624-1A19C78A4310} = {88B03853-2215-4E52-8986-0E76602E5F21}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F376A326-7590-4E7E-AB9B-76CED8527AB0} SolutionGuid = {F376A326-7590-4E7E-AB9B-76CED8527AB0}

View file

@ -2,17 +2,24 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<RootNamespace>Insight.Agent</RootNamespace> <RootNamespace>Insight.Agent</RootNamespace>
<Product>Insight</Product> <Product>Insight</Product>
<AssemblyName>agent</AssemblyName> <AssemblyName>agent</AssemblyName>
<AssemblyVersion>2023.12.14.0</AssemblyVersion> <AssemblyVersion>2023.12.14.0</AssemblyVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<!--WMI / System.Management-->
<RuntimeHostConfigurationOption Include="System.Runtime.Loader.UseRidGraph" Value="true" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>none</DebugType> <DebugType>none</DebugType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@ -20,14 +27,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.10" /> <PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.10" />
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" /> <PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
<PackageReference Include="System.Management" Version="7.0.2" /> <PackageReference Include="System.Management" Version="8.0.0" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="7.0.1" /> <PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.0" />
<PackageReference Include="Vaitr.Snmp" Version="2023.3.3" /> <PackageReference Include="Vaitr.Snmp" Version="2023.12.15.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -5,14 +5,10 @@ using Vaitr.Network;
namespace Insight.Agent.Network; namespace Insight.Agent.Network;
public class AgentSession : TcpSession<IMessage> public class AgentSession(IEnumerable<IMessageHandler<AgentSession>> handlers, ISerializer<IMessage> serializer, ILogger<AgentSession> logger)
: TcpSession<IMessage>(serializer, logger)
{ {
private readonly IEnumerable<IMessageHandler<AgentSession>> _handlers; private readonly IEnumerable<IMessageHandler<AgentSession>> _handlers = handlers;
public AgentSession(IEnumerable<IMessageHandler<AgentSession>> handlers, ISerializer<IMessage> serializer, ILogger<AgentSession> logger) : base(serializer, logger)
{
_handlers = handlers;
}
protected override ValueTask OnConnectedAsync(CancellationToken cancellationToken) protected override ValueTask OnConnectedAsync(CancellationToken cancellationToken)
{ {

View file

@ -2,20 +2,12 @@
using Insight.Domain.Interfaces; using Insight.Domain.Interfaces;
using Insight.Domain.Network; using Insight.Domain.Network;
using Insight.Domain.Network.Agent.Messages; using Insight.Domain.Network.Agent.Messages;
using Microsoft.Extensions.Logging;
namespace Insight.Agent.Network.Handlers; namespace Insight.Agent.Network.Handlers;
public class CustomHandler : IMessageHandler<AgentSession> public class CustomHandler(ScriptService scriptService) : IMessageHandler<AgentSession>
{ {
private readonly ScriptService _scriptService; private readonly ScriptService _scriptService = scriptService;
private readonly ILogger<CustomHandler> _logger;
public CustomHandler(ScriptService scriptService, ILogger<CustomHandler> logger)
{
_scriptService = scriptService;
_logger = logger;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -29,6 +21,7 @@ public class CustomHandler : IMessageHandler<AgentSession>
private async ValueTask OnRequestAsync(AgentSession sender, Request request, CancellationToken cancellationToken) private async ValueTask OnRequestAsync(AgentSession sender, Request request, CancellationToken cancellationToken)
{ {
if (request.RequestData is null) return;
var result = await _scriptService.QueryAsync(request.RequestData); var result = await _scriptService.QueryAsync(request.RequestData);
await sender.SendAsync(new Response(request) await sender.SendAsync(new Response(request)

View file

@ -59,7 +59,7 @@ public class DriveHandler : IMessageHandler<AgentSession>
drive.InterfaceType = @object.GetValue<string>(properties, "interfacetype")?.Trim(); drive.InterfaceType = @object.GetValue<string>(properties, "interfacetype")?.Trim();
drive.FirmwareRevision = @object.GetValue<string>(properties, "firmwarerevision")?.Trim(); drive.FirmwareRevision = @object.GetValue<string>(properties, "firmwarerevision")?.Trim();
drive.PNPDeviceID = @object.GetValue<string>(properties, "pnpdeviceid")?.Trim(); drive.PNPDeviceID = @object.GetValue<string>(properties, "pnpdeviceid")?.Trim();
drive.Volumes = new List<Volume>(); drive.Volumes = [];
var diskpartition = @object.GetRelated("win32_diskpartition"); var diskpartition = @object.GetRelated("win32_diskpartition");
using (diskpartition) using (diskpartition)
@ -155,7 +155,7 @@ public class DriveHandler : IMessageHandler<AgentSession>
{ {
using (collection2) using (collection2)
{ {
foreach (ManagementObject @object2 in collection2) foreach (ManagementObject @object2 in collection2.Cast<ManagementObject>())
{ {
var properties2 = @object2.GetPropertyHashes(); var properties2 = @object2.GetPropertyHashes();

View file

@ -19,7 +19,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
case InventoryRequest: case InventoryRequest:
{ {
var result = new Collection<Interface>(); var result = new Collection<Interface>();
result.AddRange(GetInterfaces()); if (GetInterfaces() is List<Interface> interfaces) result.AddRange(interfaces);
await sender.SendAsync(result, cancellationToken); await sender.SendAsync(result, cancellationToken);
break; break;
@ -27,10 +27,10 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
} }
} }
private static List<Interface> GetInterfaces() private static List<Interface>? GetInterfaces()
{ {
if (NetworkInterface.GetIsNetworkAvailable() is false) return null; if (NetworkInterface.GetIsNetworkAvailable() is false) return null;
if (NetworkInterface.GetAllNetworkInterfaces().Any() is false) return null; if (NetworkInterface.GetAllNetworkInterfaces().Length == 0) return null;
var interfaces = new List<Interface>(); var interfaces = new List<Interface>();
@ -99,7 +99,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
using (collection) using (collection)
{ {
foreach (ManagementObject @object in collection) foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{ {
var properties = @object.GetPropertyHashes(); var properties = @object.GetPropertyHashes();
@ -185,7 +185,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
{ {
var addresses = new List<Unicast>(); var addresses = new List<Unicast>();
if (unicastCollection.Any() is false) return addresses; if (unicastCollection.Count == 0) return addresses;
foreach (var unicast in unicastCollection) foreach (var unicast in unicastCollection)
{ {
@ -210,7 +210,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
{ {
var addresses = new List<IPAddress2>(); var addresses = new List<IPAddress2>();
if (addressCollection.Any() is false) return addresses; if (addressCollection.Count == 0) return addresses;
foreach (var address in addressCollection) foreach (var address in addressCollection)
{ {
@ -224,7 +224,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
{ {
var addresses = new List<IPAddress2>(); var addresses = new List<IPAddress2>();
if (addressCollection.Any() is false) return addresses; if (addressCollection.Count == 0) return addresses;
foreach (var address in addressCollection) foreach (var address in addressCollection)
{ {

View file

@ -14,12 +14,12 @@ public class MainboardHandler : IMessageHandler<AgentSession>
switch (message) switch (message)
{ {
case InventoryRequest: case InventoryRequest:
await sender.SendAsync(GetMainboard(), cancellationToken); if (GetMainboard() is Mainboard mainboard) await sender.SendAsync(mainboard, cancellationToken);
break; break;
} }
} }
private static Mainboard GetMainboard() private static Mainboard? GetMainboard()
{ {
using var searcher = new ManagementObjectSearcher using var searcher = new ManagementObjectSearcher
{ {

View file

@ -41,7 +41,7 @@ public class OperationSystemHandler : IMessageHandler<AgentSession>
using (collection) using (collection)
{ {
foreach (ManagementObject @object in collection) foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{ {
var properties = @object.GetPropertyHashes(); var properties = @object.GetPropertyHashes();
@ -51,7 +51,8 @@ public class OperationSystemHandler : IMessageHandler<AgentSession>
if (@object.TryGetValue<string>(properties, "osarchitecture", out var architecture)) if (@object.TryGetValue<string>(properties, "osarchitecture", out var architecture))
{ {
if (architecture is not null && architecture.ToLower().Contains("64")) os.Architecture = Architecture.X64; if (architecture is not null && architecture.Contains("64", StringComparison.CurrentCultureIgnoreCase))
os.Architecture = Architecture.X64;
} }
else else
{ {

View file

@ -2,20 +2,12 @@
using Insight.Domain.Interfaces; using Insight.Domain.Interfaces;
using Insight.Domain.Network; using Insight.Domain.Network;
using Insight.Domain.Network.Agent.Messages; using Insight.Domain.Network.Agent.Messages;
using Microsoft.Extensions.Logging;
namespace Insight.Agent.Network.Handlers; namespace Insight.Agent.Network.Handlers;
public class ProxyHandler : IMessageHandler<AgentSession> public class ProxyHandler(ScriptService scriptService) : IMessageHandler<AgentSession>
{ {
private readonly ScriptService _scriptService; private readonly ScriptService _scriptService = scriptService;
private readonly ILogger<ProxyHandler> _logger;
public ProxyHandler(ScriptService scriptService, ILogger<ProxyHandler> logger)
{
_scriptService = scriptService;
_logger = logger;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -29,6 +21,7 @@ public class ProxyHandler : IMessageHandler<AgentSession>
private async ValueTask OnProxyRequestAsync(AgentSession sender, Proxy<Request> proxyRequest, CancellationToken cancellationToken) private async ValueTask OnProxyRequestAsync(AgentSession sender, Proxy<Request> proxyRequest, CancellationToken cancellationToken)
{ {
if (proxyRequest.Message?.RequestData is null) return;
var result = await _scriptService.QueryAsync(proxyRequest.Message.RequestData); var result = await _scriptService.QueryAsync(proxyRequest.Message.RequestData);
await sender.SendAsync(new Proxy<Response>() await sender.SendAsync(new Proxy<Response>()

View file

@ -30,7 +30,7 @@ public class ServiceHandler : IMessageHandler<AgentSession>
var services = new List<Service>(); var services = new List<Service>();
var serviceControllers = ServiceController.GetServices()?.OrderBy(s => s.DisplayName)?.ToList(); var serviceControllers = ServiceController.GetServices()?.OrderBy(s => s.DisplayName)?.ToList();
if (serviceControllers is null || serviceControllers.Any() is false) throw new InvalidOperationException("SERVICE Collection NULL"); if (serviceControllers is null || serviceControllers.Count == 0) throw new InvalidOperationException("SERVICE Collection NULL");
foreach (var sc in serviceControllers) foreach (var sc in serviceControllers)
{ {
@ -102,7 +102,7 @@ public class ServiceHandler : IMessageHandler<AgentSession>
} }
} }
if (services2.Any() is false) return services; if (services2.Count == 0) return services;
foreach (var svc in services) foreach (var svc in services)
{ {
@ -117,6 +117,6 @@ public class ServiceHandler : IMessageHandler<AgentSession>
svc.Delay = map.Delay; svc.Delay = map.Delay;
} }
return services.OrderBy(x => x.Name).ToList(); return [.. services.OrderBy(x => x.Name)];
} }
} }

View file

@ -48,7 +48,7 @@ public class SessionHandler : IMessageHandler<AgentSession>
//public const int WTS_CURRENT_SESSION = -1; //public const int WTS_CURRENT_SESSION = -1;
[DllImport("wtsapi32.dll")] [DllImport("wtsapi32.dll")]
static extern int WTSEnumerateSessions( private static extern int WTSEnumerateSessions(
nint pServer, nint pServer,
[MarshalAs(UnmanagedType.U4)] int iReserved, [MarshalAs(UnmanagedType.U4)] int iReserved,
[MarshalAs(UnmanagedType.U4)] int iVersion, [MarshalAs(UnmanagedType.U4)] int iVersion,
@ -64,7 +64,7 @@ public class SessionHandler : IMessageHandler<AgentSession>
out uint iBytesReturned); out uint iBytesReturned);
[DllImport("wtsapi32.dll")] [DllImport("wtsapi32.dll")]
static extern void WTSFreeMemory( private static extern void WTSFreeMemory(
nint pMemory); nint pMemory);
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]

View file

@ -89,121 +89,6 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
return pools; return pools;
} }
private static List<PhysicalDisk> GetPhysicalDisks()
{
using var searcher = new ManagementObjectSearcher
{
Scope = new ManagementScope(@"root\microsoft\windows\storage"),
Query = new ObjectQuery("select objectid, uniqueid, name, friendlyname from msft_physicaldisk")
};
if (searcher.TryGet(out var collection) is false)
{
searcher.Query = new ObjectQuery("select * from msft_physicaldisk");
if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
}
var disks = new List<PhysicalDisk>();
using (collection)
{
foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{
var disk = new PhysicalDisk();
var properties = @object.GetPropertyHashes();
disk.UniqueId = @object.GetValue<string>(properties, "uniqueid")?.Trim();
disk.FriendlyName = @object.GetValue<string>(properties, "friendlyname")?.Trim();
disk.Manufacturer = @object.GetValue<string>(properties, "manufacturer")?.Trim();
disk.Model = @object.GetValue<string>(properties, "model")?.Trim();
disk.MediaType = @object.GetValue<ushort>(properties, "mediatype");
disk.BusType = @object.GetValue<ushort>(properties, "bustype");
if (@object.TryGetValue<ushort[]>(properties, "operationalstatus", out var operationals) && operationals is not null)
{
disk.States = operationals.Select(p => (PhysicalDisk.OperationalState)p).ToList();
}
disk.Health = (PhysicalDisk.HealthState)@object.GetValue<ushort>(properties, "healthstatus");
if (@object.TryGetValue<ushort[]>(properties, "supportedusages", out var supportedusages) && supportedusages is not null)
{
disk.SupportedUsages = supportedusages.Select(p => (SupportedUsagesEnum)p).ToList();
}
disk.Usage = @object.GetValue<ushort>(properties, "usage");
disk.PhysicalLocation = @object.GetValue<string>(properties, "physicallocation")?.Trim();
disk.SerialNumber = @object.GetValue<string>(properties, "serialnumber")?.Trim();
disk.FirmwareVersion = @object.GetValue<string>(properties, "firmwareversion")?.Trim();
disk.Size = @object.GetValue<ulong>(properties, "size");
disk.AllocatedSize = @object.GetValue<ulong>(properties, "allocatedsize");
disk.LogicalSectorSize = @object.GetValue<ulong>(properties, "logicalsectorsize");
disk.PhysicalSectorSize = @object.GetValue<ulong>(properties, "physicalsectorsize");
disk.VirtualDiskFootprint = @object.GetValue<ulong>(properties, "virtualdiskfootprint");
disks.Add(disk);
}
}
return disks;
}
private static List<VirtualDisk> GetVirtualDisks()
{
using var searcher = new ManagementObjectSearcher
{
Scope = new ManagementScope(@"root\microsoft\windows\storage"),
Query = new ObjectQuery("select objectid, uniqueid, name, friendlyname, access, provisioningtype, physicaldiskredundancy, resiliencysettingname, isdeduplicationenabled, issnapshot, operationalstatus, healthstatus, size, allocatedsize, footprintonpool, readcachesize, writecachesize from msft_virtualdisk")
};
if (searcher.TryGet(out var collection) is false)
{
searcher.Query = new ObjectQuery("select * from msft_virtualdisk");
if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
}
var disks = new List<VirtualDisk>();
using (collection)
{
foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{
var disk = new VirtualDisk();
var properties = @object.GetPropertyHashes();
disk.UniqueId = @object.GetValue<string>(properties, "uniqueid")?.Trim();
disk.Name = @object.GetValue<string>(properties, "name")?.Trim();
disk.FriendlyName = @object.GetValue<string>(properties, "friendlyname")?.Trim();
disk.AccessType = (AccessTypeEnum)@object.GetValue<ushort>(properties, "access");
disk.ProvisioningType = (ProvisioningTypeEnum)@object.GetValue<ushort>(properties, "provisioningtype");
disk.PhysicalDiskRedundancy = @object.GetValue<ushort>(properties, "physicaldiskredundancy");
disk.ResiliencySettingName = @object.GetValue<string>(properties, "resiliencysettingname")?.Trim();
disk.Deduplication = @object.GetValue<bool>(properties, "isdeduplicationenabled");
disk.IsSnapshot = @object.GetValue<bool>(properties, "issnapshot");
if (@object.TryGetValue<ushort[]>(properties, "operationalstatus", out var operationals) && operationals is not null)
{
disk.States = operationals.Select(p => (VirtualDisk.OperationalState)p).ToList();
}
disk.Health = (VirtualDisk.HealthState)@object.GetValue<ushort>(properties, "healthstatus");
disk.Size = @object.GetValue<ulong>(properties, "size");
disk.AllocatedSize = @object.GetValue<ulong>(properties, "allocatedsize");
disk.FootprintOnPool = @object.GetValue<ulong>(properties, "footprintonpool");
disk.ReadCacheSize = @object.GetValue<ulong>(properties, "readcachesize");
disk.WriteCacheSize = @object.GetValue<ulong>(properties, "writecachesize");
disks.Add(disk);
}
}
return disks;
}
private static List<PhysicalDisk> QueryPhysicalDisksByStoragePool(string storagePoolObjectId) private static List<PhysicalDisk> QueryPhysicalDisksByStoragePool(string storagePoolObjectId)
{ {
using var searcher = new ManagementObjectSearcher using var searcher = new ManagementObjectSearcher
@ -218,7 +103,7 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
using (collection) using (collection)
{ {
foreach (ManagementObject @object in collection) foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{ {
var disk = new PhysicalDisk(); var disk = new PhysicalDisk();
@ -275,7 +160,7 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
using (collection) using (collection)
{ {
foreach (ManagementObject @object in collection) foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{ {
var disk = new VirtualDisk(); var disk = new VirtualDisk();

View file

@ -87,7 +87,6 @@ public class SystemInfoHandler : IMessageHandler<AgentSession>
private static string GetWindowsProductKeyFromDigitalProductId(byte[] digitalProductId, DigitalProductIdVersion digitalProductIdVersion) private static string GetWindowsProductKeyFromDigitalProductId(byte[] digitalProductId, DigitalProductIdVersion digitalProductIdVersion)
{ {
var productKey = digitalProductIdVersion == DigitalProductIdVersion.Windows8AndUp var productKey = digitalProductIdVersion == DigitalProductIdVersion.Windows8AndUp
? DecodeProductKeyWin8AndUp(digitalProductId) ? DecodeProductKeyWin8AndUp(digitalProductId)
: DecodeProductKey(digitalProductId); : DecodeProductKey(digitalProductId);
@ -124,7 +123,7 @@ public class SystemInfoHandler : IMessageHandler<AgentSession>
var digitMapIndex = 0; var digitMapIndex = 0;
for (var j = decodeStringLength - 1; j >= 0; j--) for (var j = decodeStringLength - 1; j >= 0; j--)
{ {
var byteValue = digitMapIndex << 8 | (byte)hexPid[j]; var byteValue = digitMapIndex << 8 | (byte)hexPid[j]!;
hexPid[j] = (byte)(byteValue / 24); hexPid[j] = (byte)(byteValue / 24);
digitMapIndex = byteValue % 24; digitMapIndex = byteValue % 24;
decodedChars[i] = digits[digitMapIndex]; decodedChars[i] = digits[digitMapIndex];
@ -148,17 +147,17 @@ public class SystemInfoHandler : IMessageHandler<AgentSession>
var current = 0; var current = 0;
for (var j = 14; j >= 0; j--) for (var j = 14; j >= 0; j--)
{ {
current = current * 256; current *= 256;
current = digitalProductId[j + keyOffset] + current; current = digitalProductId[j + keyOffset] + current;
digitalProductId[j + keyOffset] = (byte)(current / 24); digitalProductId[j + keyOffset] = (byte)(current / 24);
current = current % 24; current %= 24;
last = current; last = current;
} }
key = digits[current] + key; key = digits[current] + key;
} }
var keypart1 = key.Substring(1, last); var keypart1 = key.Substring(1, last);
var keypart2 = key.Substring(last + 1, key.Length - (last + 1)); var keypart2 = key[(last + 1)..];
key = keypart1 + "N" + keypart2; key = keypart1 + "N" + keypart2;
for (var i = 5; i < key.Length; i += 6) for (var i = 5; i < key.Length; i += 6)

View file

@ -10,7 +10,7 @@ using UpdateCollection = Insight.Domain.Network.Agent.Messages.UpdateCollection;
namespace Insight.Agent.Network.Handlers; namespace Insight.Agent.Network.Handlers;
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
public class UpdateHandler : IMessageHandler<AgentSession> public partial class UpdateHandler : IMessageHandler<AgentSession>
{ {
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -60,7 +60,7 @@ public class UpdateHandler : IMessageHandler<AgentSession>
try try
{ {
var rx = new Regex(@"KB(\d+)"); var rx = KnowledgeBaseRegex();
update.Hotfix = rx.Match(wupdate.Title).Value; update.Hotfix = rx.Match(wupdate.Title).Value;
} }
catch (Exception) catch (Exception)
@ -125,4 +125,7 @@ public class UpdateHandler : IMessageHandler<AgentSession>
return updates; return updates;
} }
[GeneratedRegex(@"KB(\d+)")]
private static partial Regex KnowledgeBaseRegex();
} }

View file

@ -32,7 +32,7 @@ public class UserHandler : IMessageHandler<AgentSession>
foreach (var u in users) foreach (var u in users)
{ {
u.Groups = new List<Group>(); u.Groups = [];
foreach (var ug in usergrouping.Where(ug => ug.UserDomain == u.Domain && ug.UserName == u.Name)) foreach (var ug in usergrouping.Where(ug => ug.UserDomain == u.Domain && ug.UserName == u.Name))
{ {
@ -67,7 +67,7 @@ public class UserHandler : IMessageHandler<AgentSession>
using (collection) using (collection)
{ {
foreach (ManagementObject @object in collection) foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{ {
var group = new Group(); var group = new Group();
@ -83,7 +83,7 @@ public class UserHandler : IMessageHandler<AgentSession>
} }
} }
return groups.OrderBy(x => x.Name)?.ToList(); return [.. groups.OrderBy(x => x.Name)];
} }
private static List<User> QueryUsers() private static List<User> QueryUsers()
@ -105,7 +105,7 @@ public class UserHandler : IMessageHandler<AgentSession>
using (collection) using (collection)
{ {
foreach (ManagementObject @object in collection) foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{ {
var user = new User(); var user = new User();
@ -150,7 +150,7 @@ public class UserHandler : IMessageHandler<AgentSession>
using (collection) using (collection)
{ {
foreach (ManagementObject @object in collection) foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{ {
var usergroup = new UserGroupMap(); var usergroup = new UserGroupMap();

View file

@ -341,7 +341,7 @@ public class VirtualMaschineHandler : IMessageHandler<AgentSession>
{ {
conf.ParentId = parentGuid.ToString(); conf.ParentId = parentGuid.ToString();
parentConfig.Childs ??= new List<VirtualMaschineConfiguration>(); parentConfig.Childs ??= [];
parentConfig.Childs.Add(conf); parentConfig.Childs.Add(conf);
} }
else else

View file

@ -9,6 +9,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Runtime.Versioning;
using Vaitr.Network; using Vaitr.Network;
using Vaitr.Network.Hosting; using Vaitr.Network.Hosting;
@ -66,29 +67,13 @@ internal class Program
options.UseSerializer<AgentSession, IMessage, MemPackSerializer<IMessage>>(); options.UseSerializer<AgentSession, IMessage, MemPackSerializer<IMessage>>();
}); });
services.AddSingleton<IMessageHandler<AgentSession>, CustomHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, ProxyHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, AuthenticationHandler>(); services.AddSingleton<IMessageHandler<AgentSession>, AuthenticationHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, DriveHandler>(); services.AddSingleton<IMessageHandler<AgentSession>, ProxyHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, InterfaceHandler>(); services.AddSingleton<IMessageHandler<AgentSession>, CustomHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, MainboardHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, MemoryHandler>(); if (OperatingSystem.IsWindows()) ServiceCollectionExtensions.InjectWindowsHandler(services);
services.AddSingleton<IMessageHandler<AgentSession>, OperationSystemHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, PrinterHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, ProcessorHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, ServiceHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, SessionHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, SoftwareHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, StoragePoolHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, SystemInfoHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, UpdateHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, UserHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, VideocardHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, VirtualMaschineHandler>();
// GLOBAL DEPENDENCIES // GLOBAL DEPENDENCIES
//services.AddSingleton<Bus>();
services.AddTransient(provider => new HttpClient(new HttpClientHandler services.AddTransient(provider => new HttpClient(new HttpClientHandler
{ {
ClientCertificateOptions = ClientCertificateOption.Manual, ClientCertificateOptions = ClientCertificateOption.Manual,
@ -99,4 +84,30 @@ internal class Program
var host = builder.Build(); var host = builder.Build();
await host.RunAsync().ConfigureAwait(false); await host.RunAsync().ConfigureAwait(false);
} }
}
internal static class ServiceCollectionExtensions
{
[SupportedOSPlatform("windows")]
internal static IServiceCollection InjectWindowsHandler(this IServiceCollection services)
{
services.AddSingleton<IMessageHandler<AgentSession>, DriveHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, InterfaceHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, MainboardHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, MemoryHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, OperationSystemHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, PrinterHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, ProcessorHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, ServiceHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, SessionHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, SoftwareHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, StoragePoolHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, SystemInfoHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, UpdateHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, UserHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, VideocardHandler>();
services.AddSingleton<IMessageHandler<AgentSession>, VirtualMaschineHandler>();
return services;
}
} }

View file

@ -5,12 +5,7 @@ using System.Runtime.Versioning;
namespace Insight.Agent.Services; namespace Insight.Agent.Services;
[SupportedOSPlatform("linux")] [SupportedOSPlatform("linux")]
public partial class CollectorService public partial class CollectorService(ILogger<CollectorService>? logger = null)
{ {
public ILogger<CollectorService> Logger { get; } public ILogger<CollectorService> Logger { get; } = logger ?? NullLogger<CollectorService>.Instance;
public CollectorService(ILogger<CollectorService>? logger = null)
{
Logger = logger ?? NullLogger<CollectorService>.Instance;
}
} }

View file

@ -4,12 +4,14 @@ namespace Insight.Agent.Services;
public static class Configurator public static class Configurator
{ {
private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNameCaseInsensitive = true, WriteIndented = true };
public static async ValueTask<TConfig> ReadAsync<TConfig>(string file, CancellationToken cancellationToken = default) public static async ValueTask<TConfig> ReadAsync<TConfig>(string file, CancellationToken cancellationToken = default)
where TConfig : class where TConfig : class
{ {
var json = await File.ReadAllTextAsync(file, cancellationToken); var json = await File.ReadAllTextAsync(file, cancellationToken);
if (JsonSerializer.Deserialize<TConfig>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, WriteIndented = true }) is not TConfig config) if (JsonSerializer.Deserialize<TConfig>(json, _serializerOptions) is not TConfig config)
{ {
throw new InvalidDataException($"Failed to deserialize ({file})"); throw new InvalidDataException($"Failed to deserialize ({file})");
} }
@ -31,7 +33,7 @@ public static class Configurator
{ {
var json = await File.ReadAllTextAsync(file, cancellationToken); var json = await File.ReadAllTextAsync(file, cancellationToken);
if (JsonSerializer.Deserialize<IDictionary<string, object>>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, WriteIndented = true }) is not IDictionary<string, object> config) if (JsonSerializer.Deserialize<IDictionary<string, object>>(json, _serializerOptions) is not IDictionary<string, object> config)
{ {
throw new InvalidDataException($"Failed to deserialize ({file})"); throw new InvalidDataException($"Failed to deserialize ({file})");
} }
@ -89,7 +91,7 @@ public static class Configurator
private static async ValueTask WriteToFileAsync<TData>(TData data, string file, CancellationToken cancellationToken) private static async ValueTask WriteToFileAsync<TData>(TData data, string file, CancellationToken cancellationToken)
{ {
var json = JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true }); var json = JsonSerializer.Serialize(data, _serializerOptions);
await File.WriteAllTextAsync(file, json, cancellationToken); await File.WriteAllTextAsync(file, json, cancellationToken);
} }

View file

@ -163,7 +163,7 @@ internal class EventService : BackgroundService
}; };
} }
_queue.Writer.WriteAsync(@event, default); _ = _queue.Writer.WriteAsync(@event, default);
} }
catch (Exception) { } // app crash catch (Exception) { } // app crash
} }

View file

@ -4,17 +4,14 @@ using System.Management.Automation.Runspaces;
namespace Insight.Agent.Services; namespace Insight.Agent.Services;
public class ScriptService public class ScriptService(ILogger<ScriptService> logger)
{ {
private readonly ILogger<ScriptService> _logger; private readonly ILogger<ScriptService> _logger = logger;
public ScriptService(ILogger<ScriptService> logger)
{
_logger = logger;
}
public async Task<QueryResult> QueryAsync(string query) public async Task<QueryResult> QueryAsync(string query)
{ {
_logger.LogDebug("QueryAsync ({query})", query);
var result = new QueryResult(); var result = new QueryResult();
var errors = new List<string>(); var errors = new List<string>();

View file

@ -12,19 +12,12 @@ using System.Text.Json;
namespace Insight.Agent.Services; namespace Insight.Agent.Services;
internal class UpdateService : BackgroundService internal class UpdateService(HttpClient httpClient, IConfiguration configuration, ILogger<UpdateService> logger) : BackgroundService
{ {
private readonly Uri _uri; private readonly Uri _uri = configuration.GetValue<Uri?>("api") ?? throw new Exception($"api value not set (appsettings)");
private readonly HttpClient _httpClient; private readonly HttpClient _httpClient = httpClient;
private readonly ILogger<UpdateService> _logger; private readonly ILogger<UpdateService> _logger = logger;
public UpdateService(HttpClient httpClient, IConfiguration configuration, ILogger<UpdateService> logger)
{
_httpClient = httpClient;
_uri = configuration.GetValue<Uri?>("api") ?? throw new Exception($"api value not set (appsettings)");
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken cancellationToken) protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{ {
@ -42,7 +35,7 @@ internal class UpdateService : BackgroundService
_logger.LogInformation("Update Result: {result}", result?.Success); _logger.LogInformation("Update Result: {result}", result?.Success);
if (result?.UpdateErrors is not null) if (result?.UpdateErrors is not null)
{ {
_logger.LogError("Update Errors: {errors}", string.Concat(result?.UpdateErrors)); _logger.LogError("Update Errors: {errors}", string.Concat(result.UpdateErrors));
} }
} }
catch (OperationCanceledException) { } catch (OperationCanceledException) { }
@ -198,7 +191,7 @@ internal class UpdateService : BackgroundService
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken); await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
// extract update archive from temp to app dir (overwrite) // extract update archive from temp to app dir (overwrite)
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true); ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory!.FullName, true);
// delete temp folder // delete temp folder
if (temp.Exists) temp.Delete(true); if (temp.Exists) temp.Delete(true);
@ -229,7 +222,7 @@ internal class UpdateService : BackgroundService
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName); var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
if (matched is null || matched.Any() is false) return false; if (matched is null || matched.Length == 0) return false;
if (matched.Any(p => if (matched.Any(p =>
p.MainModule is not null && p.MainModule is not null &&
@ -262,7 +255,7 @@ internal class UpdateService : BackgroundService
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName); var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
if (matched is null || matched.Any() is false) return true; if (matched is null || matched.Length == 0) return true;
foreach (var procsInfo in matched.Where(p => foreach (var procsInfo in matched.Where(p =>
p.MainModule is not null && p.MainModule is not null &&
@ -312,7 +305,7 @@ internal class UpdateService : BackgroundService
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken); await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
// extract update archive from temp to app dir (overwrite) // extract update archive from temp to app dir (overwrite)
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true); ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory!.FullName, true);
// delete temp folder // delete temp folder
if (temp.Exists) temp.Delete(true); if (temp.Exists) temp.Delete(true);
@ -353,7 +346,7 @@ internal class UpdateService : BackgroundService
public bool ApiAvailable { get; set; } = false; public bool ApiAvailable { get; set; } = false;
public bool UpdateAvailable { get; set; } = false; public bool UpdateAvailable { get; set; } = false;
public bool Success { get; set; } = false; public bool Success { get; set; } = false;
public List<string> ApiErrors { get; } = new(); public List<string> ApiErrors { get; } = [];
public List<string> UpdateErrors { get; } = new(); public List<string> UpdateErrors { get; } = [];
} }
} }

View file

@ -21,10 +21,9 @@ public partial class CollectorService
output = stream.ReadToEnd(); output = stream.ReadToEnd();
// clean output // clean output
var clean = Regex var clean = CleanRegex().Replace(output
.Replace(output
.Trim() .Trim()
.Replace("\t", " "), @"[ ]{2,}", " "); .Replace("\t", " "), " ");
var elements = clean.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries); var elements = clean.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries);
@ -36,13 +35,12 @@ public partial class CollectorService
// linebreak list conversion // linebreak list conversion
var lines = new List<string>(output var lines = new List<string>(output
.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries)) .Split(separator, StringSplitOptions.RemoveEmptyEntries))
.Select(l => .Select(l =>
{ {
return Regex return CleanRegex().Replace(l
.Replace(l
.Trim() .Trim()
.Replace("\t", " "), @"[ ]{2,}", " "); .Replace("\t", " "), " ");
}) })
.ToList(); .ToList();
@ -62,13 +60,12 @@ public partial class CollectorService
// linebreak list conversion // linebreak list conversion
lines = new List<string>(output lines = new List<string>(output
.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries)) .Split(separator, StringSplitOptions.RemoveEmptyEntries))
.Select(l => .Select(l =>
{ {
return Regex return CleanRegex().Replace(l
.Replace(l
.Trim() .Trim()
.Replace("\t", " "), @"[ ]{2,}", " "); .Replace("\t", " "), " ");
}) })
.ToList(); .ToList();
@ -102,4 +99,9 @@ public partial class CollectorService
return os; return os;
} }
private static readonly string[] separator = ["\n", "\r\n"];
[GeneratedRegex(@"[ ]{2,}")]
private static partial Regex CleanRegex();
} }

View file

@ -17,11 +17,11 @@ public partial class CollectorService
var output = "w".Bash(); var output = "w".Bash();
// linebreak list conversion // linebreak list conversion
var lines = output.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList(); var lines = output.Split(separatorArray, StringSplitOptions.RemoveEmptyEntries).ToList();
lines = lines.Select(l => lines = lines.Select(l =>
{ {
return Regex.Replace(l.Trim().Replace("\t", " "), @"[ ]{2,}", " "); return CleanOutputRegex().Replace(l.Trim().Replace("\t", " "), " ");
}).ToList(); }).ToList();
// cleaning // cleaning
@ -46,4 +46,9 @@ public partial class CollectorService
return sessions; return sessions;
} }
private static readonly string[] separatorArray = ["\n", "\r\n"];
[GeneratedRegex(@"[ ]{2,}")]
private static partial Regex CleanOutputRegex();
} }

View file

@ -1,31 +1,29 @@
using Insight.Api.Models; using Insight.Api.Models;
using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Models; using Insight.Infrastructure.Models;
using Insight.Infrastructure.Services; using Insight.Infrastructure.Services;
using Insight.Infrastructure.Web;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
namespace Insight.Api.Controllers; namespace Insight.Api.Controllers;
[ApiController, Route("api/accounts")] [ApiController, Route("api/accounts")]
public class AccountController : ControllerBase public class AccountController(IdentityService identityService, IServiceScopeFactory scopeFactory) : ControllerBase
{ {
private readonly IdentityService _identityService; private readonly IdentityService _identityService = identityService;
private readonly AccountService _accountService; private readonly IServiceScopeFactory _scopeFactory = scopeFactory;
private readonly ILogger<AccountController> _logger;
public AccountController(IdentityService identityService, AccountService accountService, ILogger<AccountController> logger)
{
_identityService = identityService;
_accountService = accountService;
_logger = logger;
}
[HttpGet, Authorize] [HttpGet, Authorize]
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken) public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
{ {
using var scope = _scopeFactory.CreateScope();
var collection = scope.ServiceProvider.GetRequiredService<IMongoDatabase>().User();
try try
{ {
var result = await _accountService.GetAsync( var result = await collection.GetPagedAsync(
offset: request.Offset, offset: request.Offset,
limit: request.Limit, limit: request.Limit,
request: Request, request: Request,

View file

@ -1,28 +1,26 @@
using Insight.Infrastructure.Models; using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Services; using Insight.Infrastructure.Models;
using Insight.Infrastructure.Web;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
namespace Insight.Api.Controllers; namespace Insight.Api.Controllers;
[ApiController, Route("api/agents")] [ApiController, Route("api/agents")]
public class AgentController : ControllerBase public class AgentController(IServiceScopeFactory scopeFactory) : ControllerBase
{ {
private readonly AgentService _agentService; private readonly IServiceScopeFactory _scopeFactory = scopeFactory;
private readonly ILogger<AgentController> _logger;
public AgentController(AgentService agentService, ILogger<AgentController> logger)
{
_agentService = agentService;
_logger = logger;
}
[HttpGet, Authorize] [HttpGet, Authorize]
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken) public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
{ {
using var scope = _scopeFactory.CreateScope();
var collection = scope.ServiceProvider.GetRequiredService<IMongoDatabase>().Agent();
try try
{ {
var result = await _agentService.GetAsync( var result = await collection.GetPagedAsync(
offset: request.Offset, offset: request.Offset,
limit: request.Limit, limit: request.Limit,
request: Request, request: Request,

View file

@ -1,28 +1,26 @@
using Insight.Infrastructure.Models; using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Services; using Insight.Infrastructure.Models;
using Insight.Infrastructure.Web;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
namespace Insight.Api.Controllers; namespace Insight.Api.Controllers;
[ApiController, Route("api/customers")] [ApiController, Route("api/customers")]
public class CustomerController : ControllerBase public class CustomerController(IServiceScopeFactory scopeFactory) : ControllerBase
{ {
private readonly CustomerService _customerService; private readonly IServiceScopeFactory _scopeFactory = scopeFactory;
private readonly ILogger<CustomerController> _logger;
public CustomerController(CustomerService customerService, ILogger<CustomerController> logger)
{
_customerService = customerService;
_logger = logger;
}
[HttpGet, Authorize] [HttpGet, Authorize]
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken) public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
{ {
using var scope = _scopeFactory.CreateScope();
var collection = scope.ServiceProvider.GetRequiredService<IMongoDatabase>().Customer();
try try
{ {
var result = await _customerService.GetAsync( var result = await collection.GetPagedAsync(
offset: request.Offset, offset: request.Offset,
limit: request.Limit, limit: request.Limit,
request: Request, request: Request,

View file

@ -1,28 +1,26 @@
using Insight.Infrastructure.Models; using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Services; using Insight.Infrastructure.Models;
using Insight.Infrastructure.Web;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
namespace Insight.Api.Controllers; namespace Insight.Api.Controllers;
[ApiController, Route("api/hosts")] [ApiController, Route("api/hosts")]
public class HostController : ControllerBase public class HostController(IServiceScopeFactory scopeFactory) : ControllerBase
{ {
private readonly HostService _hostService; private readonly IServiceScopeFactory _scopeFactory = scopeFactory;
private readonly ILogger<HostController> _logger;
public HostController(HostService hostService, ILogger<HostController> logger)
{
_hostService = hostService;
_logger = logger;
}
[HttpGet, Authorize] [HttpGet, Authorize]
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken) public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
{ {
using var scope = _scopeFactory.CreateScope();
var collection = scope.ServiceProvider.GetRequiredService<IMongoDatabase>().Host();
try try
{ {
var result = await _hostService.GetAsync( var result = await collection.GetPagedAsync(
offset: request.Offset, offset: request.Offset,
limit: request.Limit, limit: request.Limit,
request: Request, request: Request,

View file

@ -1,6 +1,6 @@
using Insight.Infrastructure.Entities; using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Models; using Insight.Infrastructure.Models;
using Insight.Infrastructure.Services; using Insight.Infrastructure.Web;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson; using MongoDB.Bson;
@ -11,20 +11,16 @@ using System.Text.RegularExpressions;
namespace Insight.Api.Controllers; namespace Insight.Api.Controllers;
[ApiController, Route("api/inventory")] [ApiController, Route("api/inventory")]
public class InventoryController : ControllerBase public class InventoryController(IServiceScopeFactory scopeFactory) : ControllerBase
{ {
private readonly InventoryService _inventoryService; private readonly IServiceScopeFactory _scopeFactory = scopeFactory;
private readonly ILogger<InventoryController> _logger;
public InventoryController(InventoryService inventoryService, ILogger<InventoryController> logger)
{
_inventoryService = inventoryService;
_logger = logger;
}
[HttpGet, Authorize] [HttpGet, Authorize]
public async Task<IActionResult> Get([FromQuery] HostApplicationEntity request, [FromQuery] PagedDataRequest meta, CancellationToken cancellationToken) public async Task<IActionResult> Get([FromQuery] HostApplicationEntity request, [FromQuery] PagedDataRequest meta, CancellationToken cancellationToken)
{ {
using var scope = _scopeFactory.CreateScope();
var collection = scope.ServiceProvider.GetRequiredService<IMongoDatabase>().HostApplication();
try try
{ {
var filter = Builders<HostApplicationEntity>.Filter.Empty; var filter = Builders<HostApplicationEntity>.Filter.Empty;
@ -38,7 +34,7 @@ public class InventoryController : ControllerBase
if (request.Name is not null) if (request.Name is not null)
filter &= Builders<HostApplicationEntity>.Filter.Regex(p => p.Name, new BsonRegularExpression(new Regex(request.Name, RegexOptions.IgnoreCase))); filter &= Builders<HostApplicationEntity>.Filter.Regex(p => p.Name, new BsonRegularExpression(new Regex(request.Name, RegexOptions.IgnoreCase)));
var result = await _inventoryService.GetAsync( var result = await collection.GetPagedAsync(
filter: filter, filter: filter,
offset: meta.Offset, offset: meta.Offset,
limit: meta.Limit, limit: meta.Limit,

View file

@ -3,14 +3,9 @@
namespace Insight.Server.Controllers; namespace Insight.Server.Controllers;
[ApiController, Route("api/setup")] [ApiController, Route("api/setup")]
public class SetupController : ControllerBase public class SetupController(ILogger<SetupController> logger) : ControllerBase
{ {
private readonly ILogger<SetupController> _logger; private readonly ILogger<SetupController> _logger = logger;
public SetupController(ILogger<SetupController> logger)
{
_logger = logger;
}
[HttpGet("windows")] [HttpGet("windows")]
public async Task<IActionResult> GetAsync(CancellationToken cancellationToken) public async Task<IActionResult> GetAsync(CancellationToken cancellationToken)

View file

@ -6,14 +6,9 @@ using Microsoft.AspNetCore.Mvc;
namespace Insight.Api.Controllers; namespace Insight.Api.Controllers;
[ApiController, Route("api/token", Order = 0)] [ApiController, Route("api/token", Order = 0)]
public class TokenController : ControllerBase public class TokenController(TokenService tokenService) : ControllerBase
{ {
private readonly TokenService _tokenService; private readonly TokenService _tokenService = tokenService;
public TokenController(TokenService tokenService)
{
_tokenService = tokenService;
}
/// <remarks> /// <remarks>
/// Access Token Request /// Access Token Request
@ -21,6 +16,9 @@ public class TokenController : ControllerBase
[HttpPost, AllowAnonymous] [HttpPost, AllowAnonymous]
public async Task<IActionResult> Authentication([FromBody] TokenRequest request) public async Task<IActionResult> Authentication([FromBody] TokenRequest request)
{ {
if (request.Username is null) return BadRequest("username is null");
if (request.Password is null) return BadRequest("password is null");
try try
{ {
var result = await _tokenService.GetAsync(request.Username, request.Password, request.Code, HttpContext.Connection.RemoteIpAddress).ConfigureAwait(false); var result = await _tokenService.GetAsync(request.Username, request.Password, request.Code, HttpContext.Connection.RemoteIpAddress).ConfigureAwait(false);

View file

@ -5,14 +5,9 @@ using Microsoft.AspNetCore.Mvc;
namespace Insight.Server.Controllers; namespace Insight.Server.Controllers;
[ApiController, Route("api/update")] [ApiController, Route("api/update")]
public class UpdateController : ControllerBase public class UpdateController(ILogger<UpdateController> logger) : ControllerBase
{ {
private readonly ILogger<UpdateController> _logger; private readonly ILogger<UpdateController> _logger = logger;
public UpdateController(ILogger<UpdateController> logger)
{
_logger = logger;
}
[HttpGet("updater/windows")] [HttpGet("updater/windows")]
public IActionResult UpdaterWindows() public IActionResult UpdaterWindows()
@ -35,7 +30,7 @@ public class UpdateController : ControllerBase
var versions = updateDir.GetFiles("*.zip", SearchOption.TopDirectoryOnly); var versions = updateDir.GetFiles("*.zip", SearchOption.TopDirectoryOnly);
if (versions is null || versions.Any() is false) return NotFound(); if (versions is null || versions.Length == 0) return NotFound();
var latest = versions.OrderBy(x => x.Name).FirstOrDefault(); var latest = versions.OrderBy(x => x.Name).FirstOrDefault();
@ -73,7 +68,7 @@ public class UpdateController : ControllerBase
var versions = updateDir.GetFiles("*.zip", SearchOption.TopDirectoryOnly); var versions = updateDir.GetFiles("*.zip", SearchOption.TopDirectoryOnly);
if (versions is null || versions.Any() is false) return NotFound(); if (versions is null || versions.Length == 0) return NotFound();
var latest = versions.OrderBy(x => x.Name).FirstOrDefault(); var latest = versions.OrderBy(x => x.Name).FirstOrDefault();

View file

@ -6,7 +6,7 @@ namespace Insight.Api.Hosting;
public static class ServiceExtensions public static class ServiceExtensions
{ {
internal static IServiceCollection AddSwaggerServices(this IServiceCollection services, IConfiguration configuration) internal static IServiceCollection AddSwaggerServices(this IServiceCollection services)
{ {
services.AddEndpointsApiExplorer(); services.AddEndpointsApiExplorer();
services.AddSwaggerGen(options => services.AddSwaggerGen(options =>

View file

@ -1,43 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Product>Insight</Product> <LangVersion>latest</LangVersion>
<AssemblyName>api</AssemblyName> <Product>Insight</Product>
<AssemblyVersion>2023.12.14.0</AssemblyVersion> <AssemblyName>api</AssemblyName>
<RootNamespace>Insight.Api</RootNamespace> <AssemblyVersion>2023.12.15.0</AssemblyVersion>
<Nullable>enable</Nullable> <RootNamespace>Insight.Api</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable>
<UserSecretsId>4ae1d3bf-869e-4963-8a19-35634507d3b3</UserSecretsId> <ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>4ae1d3bf-869e-4963-8a19-35634507d3b3</UserSecretsId>
<PublishAot>false</PublishAot> <PublishAot>false</PublishAot>
<PublishTrimmed>false</PublishTrimmed> <PublishTrimmed>false</PublishTrimmed>
<!--<ServerGarbageCollection>false</ServerGarbageCollection> <!--<ServerGarbageCollection>false</ServerGarbageCollection>
<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>--> <ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>-->
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<GenerateDocumentationFile>True</GenerateDocumentationFile> <NoWarn>$(NoWarn);1591</NoWarn>
<NoWarn>$(NoWarn);1591</NoWarn> <SatelliteResourceLanguages>none</SatelliteResourceLanguages>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.13" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" /> <PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
<!--Unix Serilog stuff--> <!--Unix Serilog stuff-->
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Core\Insight.Infrastructure.Web\Insight.Infrastructure.Web.csproj" />
<ProjectReference Include="..\..\Core\Insight.Infrastructure\Insight.Infrastructure.csproj" /> <ProjectReference Include="..\..\Core\Insight.Infrastructure\Insight.Infrastructure.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -40,12 +40,12 @@ internal class Program
builder.Services.AddAuthorization(); builder.Services.AddAuthorization();
// WEBSERVICES // WEBSERVICES
builder.Services.AddProxyServices(builder.Configuration); builder.Services.AddProxyServices();
builder.Services.AddRoutingServices(builder.Configuration); builder.Services.AddRoutingServices();
builder.Services.AddControllers(); builder.Services.AddControllers();
// SWAGGER // SWAGGER
builder.Services.AddSwaggerServices(builder.Configuration); builder.Services.AddSwaggerServices();
//builder.Services.AddControllers(); //builder.Services.AddControllers();
//builder.Services.AddEndpointsApiExplorer(); //builder.Services.AddEndpointsApiExplorer();

View file

@ -1,4 +1,5 @@
using System.Net; using System.Diagnostics;
using System.Net;
using System.Reflection; using System.Reflection;
namespace Insight.Domain.Constants; namespace Insight.Domain.Constants;
@ -7,6 +8,14 @@ public static class Configuration
{ {
public static string Hostname => Dns.GetHostEntry("localhost").HostName; public static string Hostname => Dns.GetHostEntry("localhost").HostName;
public static Version Version => Assembly.GetEntryAssembly()?.GetName().Version ?? throw new ArgumentNullException("Version"); public static Version Version => Assembly.GetEntryAssembly()?.GetName().Version ?? throw new ArgumentNullException("Version");
public static DirectoryInfo? AppDirectory => string.IsNullOrWhiteSpace(Environment.ProcessPath) ? null : new DirectoryInfo(Environment.ProcessPath).Parent; public static DirectoryInfo? AppDirectory => AppDirectoryHelper();
public static string DefaultConfig => Path.Combine(AppDirectory?.FullName ?? string.Empty, "config.json"); public static string DefaultConfig => Path.Combine(AppDirectory?.FullName ?? string.Empty, "config.json");
private static DirectoryInfo? AppDirectoryHelper()
{
using var proc = Process.GetCurrentProcess();
if (proc?.MainModule?.FileName is null) throw new InvalidOperationException("MainModule not found");
return new DirectoryInfo(proc.MainModule.FileName).Parent;
}
} }

View file

@ -2,6 +2,7 @@
public enum CategoryEnum public enum CategoryEnum
{ {
None = 0,
Network = 1, Network = 1,
System = 2, System = 2,
Application = 3, Application = 3,

View file

@ -1,25 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>true</ImplicitUsings> <LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Insight.Domain</RootNamespace> <RootNamespace>Insight.Domain</RootNamespace>
<Product>Insight</Product> <Product>Insight</Product>
<AssemblyVersion>2023.12.14.0</AssemblyVersion> <AssemblyVersion>2023.12.15.0</AssemblyVersion>
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<!--Ignore MemoryPack Warning-->
<NoWarn>9193</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Vaitr.Bus" Version="2023.12.13" /> <PackageReference Include="System.Text.Json" Version="8.0.0" />
<PackageReference Include="Vaitr.Network" Version="2023.12.14" /> <PackageReference Include="Vaitr.Bus" Version="2023.12.15.1" />
<PackageReference Include="Vaitr.Network" Version="2023.12.16" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
</PropertyGroup>
</Project> </Project>

View file

@ -1,5 +1,4 @@
using MessagePack; using MessagePack;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -31,17 +30,17 @@ public class Result
} }
[IgnoreDataMember] [IgnoreDataMember]
public Exception? Exception { get; init; } public Exception? Exception { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
[MemberNotNullWhen(true, nameof(Exception))] //[MemberNotNullWhen(true, nameof(Exception))]
public bool HadException => Exception is not null; public bool HadException => Exception is not null;
[DataMember] [DataMember]
public bool IsSuccess { get; init; } public bool IsSuccess { get; set; }
[DataMember] [DataMember]
public string Reason { get; init; } = string.Empty; public string Reason { get; set; } = string.Empty;
public static Result Fail(string reason) public static Result Fail(string reason)
@ -130,19 +129,19 @@ public class Result<T>
} }
[IgnoreDataMember] [IgnoreDataMember]
public Exception? Exception { get; init; } public Exception? Exception { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
[MemberNotNullWhen(true, nameof(Exception))] //[MemberNotNullWhen(true, nameof(Exception))]
public bool HadException => Exception is not null; public bool HadException => Exception is not null;
[DataMember] [DataMember]
[MemberNotNullWhen(true, nameof(Value))] //[MemberNotNullWhen(true, nameof(Value))]
public bool IsSuccess { get; init; } public bool IsSuccess { get; set; }
[DataMember] [DataMember]
public string Reason { get; init; } = string.Empty; public string Reason { get; set; } = string.Empty;
[DataMember] [DataMember]
public T? Value { get; init; } public T? Value { get; set; }
} }

View file

@ -27,28 +27,17 @@ public class TokenResponse
public string? RefreshToken { get; set; } public string? RefreshToken { get; set; }
} }
public class TokenRevokeRequest public class TokenRevokeRequest(string token, string? reason)
{ {
[JsonPropertyName("token"), Required] [JsonPropertyName("token"), Required]
public string? Token { get; set; } public string? Token { get; set; } = token;
[JsonPropertyName("reason")] [JsonPropertyName("reason")]
public string? Reason { get; set; } public string? Reason { get; set; } = reason;
public TokenRevokeRequest(string token, string? reason)
{
Token = token;
Reason = reason;
}
} }
public class TokenRefreshRequest public class TokenRefreshRequest(string token)
{ {
[JsonPropertyName("token"), Required] [JsonPropertyName("token"), Required]
public string? Token { get; set; } public string? Token { get; set; } = token;
public TokenRefreshRequest(string token)
{
Token = token;
}
} }

View file

@ -182,6 +182,6 @@ public partial class IPAddress2 : IMessage
IsIPv6Multicast = address.IsIPv6Multicast; IsIPv6Multicast = address.IsIPv6Multicast;
IsIPv6SiteLocal = address.IsIPv6SiteLocal; IsIPv6SiteLocal = address.IsIPv6SiteLocal;
IsIPv6Teredo = address.IsIPv6Teredo; IsIPv6Teredo = address.IsIPv6Teredo;
IsIPv6UniqueLocal = address.IsIPv6UniqueLocal; //IsIPv6UniqueLocal = address.IsIPv6UniqueLocal;
} }
} }

View file

@ -6,10 +6,6 @@ namespace Insight.Domain.Network;
[MemoryPackUnion(0, typeof(Agent.Messages.AuthenticationRequest))] [MemoryPackUnion(0, typeof(Agent.Messages.AuthenticationRequest))]
[MemoryPackUnion(1, typeof(Agent.Messages.AuthenticationResponse))] [MemoryPackUnion(1, typeof(Agent.Messages.AuthenticationResponse))]
[MemoryPackUnion(2, typeof(Agent.Messages.InventoryRequest))] [MemoryPackUnion(2, typeof(Agent.Messages.InventoryRequest))]
//[MemoryPackUnion(3, typeof(Agent.Messages.ConsoleQueryRequest))]
//[MemoryPackUnion(4, typeof(Agent.Messages.ConsoleQueryResponse))]
//[MemoryPackUnion(5, typeof(Proxy<Agent.Messages.ConsoleQueryResponse>))]
//[MemoryPackUnion(6, typeof(Proxy<Agent.Messages.ConsoleQueryRequest>))]
[MemoryPackUnion(7, typeof(Agent.Messages.Event))] [MemoryPackUnion(7, typeof(Agent.Messages.Event))]
[MemoryPackUnion(8, typeof(Agent.Messages.Trap))] [MemoryPackUnion(8, typeof(Agent.Messages.Trap))]
[MemoryPackUnion(9, typeof(Agent.Messages.Mainboard))] [MemoryPackUnion(9, typeof(Agent.Messages.Mainboard))]

View file

@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Http.Extensions;
namespace Insight.Infrastructure; namespace Insight.Infrastructure;
public static class HttpRequestExtensions public static partial class HttpRequestExtensions
{ {
public static void AddPagination<TData>(this HttpRequest request, PagedList<TData> pagelist) public static void AddPagination<TData>(this HttpRequest request, PagedList<TData> pagelist)
{ {

View file

@ -0,0 +1,18 @@
using Insight.Infrastructure.Models;
using Microsoft.AspNetCore.Http;
using System.Text.Json;
namespace Insight.Infrastructure;
public static partial class HttpResponseExtensions
{
private static readonly JsonSerializerOptions _options = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
public static void AddPagination<TData>(this HttpResponse response, PagedList<TData> pagelist)
{
response.Headers.Append("X-Pagination", JsonSerializer.Serialize(pagelist.Meta as PagedHeaderData, _options));
}
}

View file

@ -0,0 +1,44 @@
using Insight.Infrastructure.Models;
using Microsoft.AspNetCore.Http;
using MongoDB.Bson;
using MongoDB.Driver;
namespace Insight.Infrastructure.Web;
public static class MongoCollectionExtensions
{
public static async Task<PagedList<TData>> GetPagedAsync<TData>(
this IMongoCollection<TData> collection,
HttpRequest request,
HttpResponse response,
FilterDefinition<TData>? filter = null,
SortDefinition<TData>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default)
{
var result = await Infrastructure.MongoCollectionExtensions.GetPagedAsync(collection, filter, sort, offset, limit, cancellationToken).ConfigureAwait(false);
request?.AddPagination(result);
response?.AddPagination(result);
return result;
}
public static async Task<PagedList<TResult>> GetPagedAsync<TData, TResult>(
this IMongoCollection<TData> collection,
HttpRequest request,
HttpResponse response,
IAggregateFluent<BsonDocument> query,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default)
{
var result = await Infrastructure.MongoCollectionExtensions.GetPagedAsync<TData, TResult>(collection, query, offset, limit, cancellationToken).ConfigureAwait(false);
request?.AddPagination(result);
response?.AddPagination(result);
return result;
}
}

View file

@ -0,0 +1,229 @@
using AspNetCore.Identity.MongoDbCore.Extensions;
using AspNetCore.Identity.MongoDbCore.Infrastructure;
using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Net.Http.Headers;
using MongoDB.Bson;
using System.Text;
namespace Insight.Infrastructure;
public static partial class ServiceExtensions
{
public static IServiceCollection AddTokenServices(this IServiceCollection services, IConfiguration configuration)
{
var options = new Models.TokenOptions(
key: configuration.GetValue<string?>(Appsettings.JwtKey) ?? throw new Exception($"{Appsettings.JwtKey} value not set (appsettings)"),
expires: configuration.GetValue<int?>(Appsettings.JwtExp) ?? throw new Exception($"{Appsettings.JwtExp} value not set (appsettings)"),
audience: configuration.GetValue<Uri?>(Appsettings.JwtAudience) ?? throw new Exception($"{Appsettings.JwtAudience} value not set (appsettings)"),
issuer: configuration.GetValue<Uri?>(Appsettings.JwtIssuer) ?? throw new Exception($"{Appsettings.JwtIssuer} value not set (appsettings)"));
services.AddSingleton(options);
services.AddTransient<TokenService>();
return services;
}
public static IServiceCollection AddProxyServices(this IServiceCollection services)
{
// add before routing
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
return services;
}
public static IServiceCollection AddRoutingServices(this IServiceCollection services)
{
// add after proxy
services.AddRouting(options =>
{
options.LowercaseUrls = true;
});
return services;
}
public static IServiceCollection AddIdentityServices(this IServiceCollection services, IConfiguration configuration)
{
var connectionString = configuration.GetValue<string?>(Appsettings.Database) ?? throw new Exception($"{Appsettings.Database} value not set (appsettings)");
services.AddIdentity<InsightUser, InsightRole>(options =>
{
})
.AddMongoDbStores<InsightUser, InsightRole, ObjectId>(connectionString, Settings.Database)
.AddDefaultTokenProviders()
.AddSignInManager();
return services;
}
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
{
// REWRITE TO COOKIE ONLY FOR WEB
services.AddAuthentication(options =>
{
options.DefaultScheme = "Custom";
options.DefaultChallengeScheme = "Custom";
})
.AddCookie("Cookies", options =>
{
//options.Cookie.Domain = "insight.webmatic.de";
options.Cookie.Name = "insight";
options.LoginPath = "/account/login";
options.LogoutPath = "/account/logout";
options.ExpireTimeSpan = TimeSpan.FromHours(1);
options.SlidingExpiration = true;
options.Events.OnRedirectToLogin = options =>
{
if (options.Request.Path.StartsWithSegments("/api") && options.Response.StatusCode == 200)
options.Response.StatusCode = 401;
else
options.Response.Redirect(options.RedirectUri);
return Task.CompletedTask;
};
})
.AddJwtBearer("Bearer", options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters.ValidateActor = false;
options.TokenValidationParameters.ValidAudience = configuration.GetSection("Jwt:Audience").Value;
options.TokenValidationParameters.ValidateAudience = true;
options.TokenValidationParameters.ValidIssuer = configuration.GetSection("Jwt:Issuer").Value;
options.TokenValidationParameters.ValidateIssuer = true;
options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(configuration.GetSection("Jwt:Key").Value ?? throw new Exception("Configuration for [Jwt:Key] not found"))
);
options.TokenValidationParameters.ValidateIssuerSigningKey = true;
options.TokenValidationParameters.ValidateLifetime = true;
})
.AddPolicyScheme("Custom", "Custom", options =>
{
options.ForwardDefaultSelector = context =>
{
if (context.Request.Headers[HeaderNames.Authorization] is StringValues auth && auth.ToString().StartsWith("Bearer "))
return "Bearer";
else
return "Cookies";
};
});
return services;
}
public static IServiceCollection AddBearerAuthentication(this IServiceCollection services, IConfiguration configuration)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters.ValidateActor = false;
options.TokenValidationParameters.ValidAudience = configuration.GetValue<string?>(Appsettings.JwtAudience) ?? throw new Exception($"{Appsettings.JwtAudience} value not set (appsettings)");
options.TokenValidationParameters.ValidateAudience = true;
options.TokenValidationParameters.ValidIssuer = configuration.GetValue<string?>(Appsettings.JwtIssuer) ?? throw new Exception($"{Appsettings.JwtIssuer} value not set (appsettings)");
options.TokenValidationParameters.ValidateIssuer = true;
options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(configuration.GetValue<string?>(Appsettings.JwtKey) ?? throw new Exception($"{Appsettings.JwtKey} value not set (appsettings)"))
);
options.TokenValidationParameters.ValidateIssuerSigningKey = true;
options.TokenValidationParameters.ValidateLifetime = true;
});
return services;
}
//private static IServiceCollection AddIdentityServices2(this IServiceCollection services, IConfiguration configuration)
//{
// var identityOptions = new MongoDbIdentityConfiguration
// {
// MongoDbSettings = new MongoDbSettings
// {
// ConnectionString = configuration.GetSection("ConnectionStrings:Mongo").Value,
// DatabaseName = "insight"
// },
// IdentityOptionsAction = options =>
// {
// options.User.RequireUniqueEmail = true;
// options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@.-_";
// options.Password.RequireDigit = false;
// options.Password.RequiredLength = 8;
// options.Password.RequireNonAlphanumeric = false;
// options.Password.RequireUppercase = false;
// options.Password.RequireLowercase = false;
// options.SignIn.RequireConfirmedAccount = false;
// options.SignIn.RequireConfirmedEmail = false;
// options.SignIn.RequireConfirmedPhoneNumber = false;
// options.Lockout.MaxFailedAccessAttempts = 5;
// options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
// }
// };
// services.ConfigureMongoDbIdentity<InsightUser, InsightRole, ObjectId>(identityOptions)
// .AddDefaultTokenProviders()
// .AddSignInManager<InsightUser>();
// return services;
//}
//private static IServiceCollection AddIdentityAuthentication(this IServiceCollection services, IConfiguration configuration)
//{
// services.AddAuthentication(options =>
// {
// options.DefaultAuthenticateScheme =
// });
// cookieBuilder.ApplicationCookie = builder.AddApplicationCookie();
// cookieBuilder.ExternalCookie = builder.AddExternalCookie();
// cookieBuilder.TwoFactorRememberMeCookie = builder.AddTwoFactorRememberMeCookie();
// cookieBuilder.TwoFactorUserIdCookie = builder.AddTwoFactorUserIdCookie();
// .AddCookie(options =>
// {
// options.
// };
// .AddIdentityCookies();
// .AddCookie(options =>
// {
// // Specify where to redirect un-authenticated users
// options.LoginPath = "/account/login";
// // Specify the name of the auth cookie.
// // ASP.NET picks a dumb name by default.
// options.Cookie.Name = "insight";
// });
// return services;
//}
}

View file

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Insight.Infrastructure.Web</RootNamespace>
<Product>Insight</Product>
<AssemblyVersion>2023.12.15.0</AssemblyVersion>
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.0.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Insight.Infrastructure\Insight.Infrastructure.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,9 @@
namespace Insight.Infrastructure.Models;
public class TokenOptions(string key, int expires, Uri? audience = null, Uri? issuer = null)
{
public string Key { get; set; } = key;
public int Expires { get; set; } = expires;
public Uri? Audience { get; set; } = audience;
public Uri? Issuer { get; set; } = issuer;
}

View file

@ -10,24 +10,17 @@ using System.Text;
namespace Insight.Infrastructure.Services; namespace Insight.Infrastructure.Services;
public class TokenService public class TokenService(TokenOptions options, IdentityService identityService, IMongoDatabase database)
{ {
private readonly TokenOptions _options; private readonly TokenOptions _options = options;
private readonly IdentityService _identityService; private readonly IdentityService _identityService = identityService;
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public TokenService(TokenOptions options, IdentityService identityService, IMongoDatabase database)
{
_options = options;
_identityService = identityService;
_database = database;
}
public async Task<TokenResponse> GetAsync(string email, string password, string? code = null, IPAddress? ipa = null) public async Task<TokenResponse> GetAsync(string email, string password, string? code = null, IPAddress? ipa = null)
{ {
var user = await _identityService.LoginAsync(email, password, code).ConfigureAwait(false); var user = await _identityService.LoginAsync(email, password, code).ConfigureAwait(false);
var accessToken = await CreateAccessTokenAsync(user, ipa).ConfigureAwait(false); var accessToken = await CreateAccessTokenAsync(user).ConfigureAwait(false);
var refreshToken = await CreateRefreshTokenAsync(user, ipa).ConfigureAwait(false); var refreshToken = await CreateRefreshTokenAsync(user, ipa).ConfigureAwait(false);
return new TokenResponse return new TokenResponse
@ -42,7 +35,7 @@ public class TokenService
{ {
if (string.IsNullOrWhiteSpace(refreshToken)) throw new ArgumentNullException(nameof(refreshToken)); if (string.IsNullOrWhiteSpace(refreshToken)) throw new ArgumentNullException(nameof(refreshToken));
var user = await _database.User().Find(p => p.RefreshTokens.Any(t => t.Token == refreshToken)).FirstOrDefaultAsync(); var user = await _database.User().Find(p => p.RefreshTokens != null && p.RefreshTokens.Any(t => t.Token == refreshToken)).FirstOrDefaultAsync();
if (user is null || user.RefreshTokens is null) throw new InvalidDataException("Invalid Refresh Token"); if (user is null || user.RefreshTokens is null) throw new InvalidDataException("Invalid Refresh Token");
var token = user.RefreshTokens.First(p => p.Token == refreshToken); var token = user.RefreshTokens.First(p => p.Token == refreshToken);
@ -73,7 +66,7 @@ public class TokenService
var newRefreshToken = await CreateRefreshTokenAsync(user, ipa).ConfigureAwait(false); var newRefreshToken = await CreateRefreshTokenAsync(user, ipa).ConfigureAwait(false);
// create access token // create access token
var accessToken = await CreateAccessTokenAsync(user, ipa).ConfigureAwait(false); var accessToken = await CreateAccessTokenAsync(user).ConfigureAwait(false);
return new TokenResponse return new TokenResponse
{ {
@ -87,7 +80,7 @@ public class TokenService
{ {
if (string.IsNullOrWhiteSpace(refreshToken)) throw new ArgumentNullException(nameof(refreshToken)); if (string.IsNullOrWhiteSpace(refreshToken)) throw new ArgumentNullException(nameof(refreshToken));
var user = await _database.User().Find(p => p.RefreshTokens.Any(t => t.Token == refreshToken)).FirstOrDefaultAsync(); var user = await _database.User().Find(p => p.RefreshTokens != null && p.RefreshTokens.Any(t => t.Token == refreshToken)).FirstOrDefaultAsync();
if (user is null || user.RefreshTokens is null) throw new InvalidDataException("Invalid Refresh Token"); if (user is null || user.RefreshTokens is null) throw new InvalidDataException("Invalid Refresh Token");
var token = user.RefreshTokens.First(p => p.Token == refreshToken); var token = user.RefreshTokens.First(p => p.Token == refreshToken);
@ -102,7 +95,7 @@ public class TokenService
token.ReasonRevoked = reason; token.ReasonRevoked = reason;
} }
private async Task<(string, int)> CreateAccessTokenAsync(InsightUser user, IPAddress? ipa = null) private async Task<(string, int)> CreateAccessTokenAsync(InsightUser user)
{ {
var claims = await _identityService.GetClaimsAsync(user).ConfigureAwait(false); var claims = await _identityService.GetClaimsAsync(user).ConfigureAwait(false);

View file

@ -1,16 +0,0 @@
using Insight.Infrastructure.Models;
using Microsoft.AspNetCore.Http;
using System.Text.Json;
namespace Insight.Infrastructure;
public static class HttpResponseExtensions
{
public static void AddPagination<TData>(this HttpResponse response, PagedList<TData> pagelist)
{
response.Headers.Add("X-Pagination", JsonSerializer.Serialize(pagelist.Meta as PagedHeaderData, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
}));
}
}

View file

@ -1,12 +1,11 @@
using Insight.Infrastructure.Models; using Insight.Infrastructure.Models;
using Microsoft.AspNetCore.Http;
using MongoDB.Bson; using MongoDB.Bson;
using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization;
using MongoDB.Driver; using MongoDB.Driver;
namespace Insight.Infrastructure; namespace Insight.Infrastructure;
public static class MongoCollectionExtensions public static partial class MongoCollectionExtensions
{ {
private const int _maximumLimit = 100; private const int _maximumLimit = 100;
@ -30,24 +29,6 @@ public static class MongoCollectionExtensions
return new PagedList<TData>(data, offset, limit, total); return new PagedList<TData>(data, offset, limit, total);
} }
public static async Task<PagedList<TData>> GetPagedAsync<TData>(
this IMongoCollection<TData> collection,
HttpRequest request,
HttpResponse response,
FilterDefinition<TData>? filter = null,
SortDefinition<TData>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default)
{
var result = await GetPagedAsync(collection, filter, sort, offset, limit, cancellationToken).ConfigureAwait(false);
request?.AddPagination(result);
response?.AddPagination(result);
return result;
}
public static async Task<PagedList<TResult>> GetPagedAsync<TData, TResult>( public static async Task<PagedList<TResult>> GetPagedAsync<TData, TResult>(
this IMongoCollection<TData> collection, this IMongoCollection<TData> collection,
IAggregateFluent<BsonDocument> query, IAggregateFluent<BsonDocument> query,
@ -62,21 +43,4 @@ public static class MongoCollectionExtensions
return new PagedList<TResult>(data.Select(x => BsonSerializer.Deserialize<TResult>(x)), offset, limit, total); return new PagedList<TResult>(data.Select(x => BsonSerializer.Deserialize<TResult>(x)), offset, limit, total);
} }
public static async Task<PagedList<TResult>> GetPagedAsync<TData, TResult>(
this IMongoCollection<TData> collection,
HttpRequest request,
HttpResponse response,
IAggregateFluent<BsonDocument> query,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default)
{
var result = await GetPagedAsync<TData, TResult>(collection, query, offset, limit, cancellationToken).ConfigureAwait(false);
request?.AddPagination(result);
response?.AddPagination(result);
return result;
}
} }

View file

@ -1,24 +1,13 @@
using AspNetCore.Identity.MongoDbCore.Extensions; using Insight.Infrastructure.Services;
using AspNetCore.Identity.MongoDbCore.Infrastructure;
using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Net.Http.Headers;
using MongoDB.Bson;
using MongoDB.Driver; using MongoDB.Driver;
using MongoDB.Driver.Core.Configuration; using MongoDB.Driver.Core.Configuration;
using System.Text;
namespace Insight.Infrastructure; namespace Insight.Infrastructure;
public static class ServiceExtensions public static partial class ServiceExtensions
{ {
public static IServiceCollection AddDatabase(this IServiceCollection services, IConfiguration configuration, ILoggerFactory? loggerFactory = null) public static IServiceCollection AddDatabase(this IServiceCollection services, IConfiguration configuration, ILoggerFactory? loggerFactory = null)
{ {
@ -42,221 +31,6 @@ public static class ServiceExtensions
{ {
services.AddTransient<IdentityService>(); services.AddTransient<IdentityService>();
services.AddTransient<AuthenticatorService>(); services.AddTransient<AuthenticatorService>();
services.AddTransient<AccountService>();
services.AddTransient<CustomerService>();
services.AddTransient<HostService>();
services.AddTransient<AgentService>();
services.AddTransient<InventoryService>();
return services;
}
public static IServiceCollection AddIdentityServices(this IServiceCollection services, IConfiguration configuration)
{
var connectionString = configuration.GetValue<string?>(Appsettings.Database) ?? throw new Exception($"{Appsettings.Database} value not set (appsettings)");
services.AddIdentity<InsightUser, InsightRole>(options =>
{
})
.AddMongoDbStores<InsightUser, InsightRole, ObjectId>(connectionString, Settings.Database)
.AddDefaultTokenProviders()
.AddSignInManager();
return services;
}
public static IServiceCollection AddTokenServices(this IServiceCollection services, IConfiguration configuration)
{
var options = new Models.TokenOptions(
key: configuration.GetValue<string?>(Appsettings.JwtKey) ?? throw new Exception($"{Appsettings.JwtKey} value not set (appsettings)"),
expires: configuration.GetValue<int?>(Appsettings.JwtExp) ?? throw new Exception($"{Appsettings.JwtExp} value not set (appsettings)"),
audience: configuration.GetValue<Uri?>(Appsettings.JwtAudience) ?? throw new Exception($"{Appsettings.JwtAudience} value not set (appsettings)"),
issuer: configuration.GetValue<Uri?>(Appsettings.JwtIssuer) ?? throw new Exception($"{Appsettings.JwtIssuer} value not set (appsettings)"));
services.AddSingleton(options);
services.AddTransient<TokenService>();
return services;
}
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
{
// REWRITE TO COOKIE ONLY FOR WEB
services.AddAuthentication(options =>
{
options.DefaultScheme = "Custom";
options.DefaultChallengeScheme = "Custom";
})
.AddCookie("Cookies", options =>
{
//options.Cookie.Domain = "insight.webmatic.de";
options.Cookie.Name = "insight";
options.LoginPath = "/account/login";
options.LogoutPath = "/account/logout";
options.ExpireTimeSpan = TimeSpan.FromHours(1);
options.SlidingExpiration = true;
options.Events.OnRedirectToLogin = options =>
{
if (options.Request.Path.StartsWithSegments("/api") && options.Response.StatusCode == 200)
options.Response.StatusCode = 401;
else
options.Response.Redirect(options.RedirectUri);
return Task.CompletedTask;
};
})
.AddJwtBearer("Bearer", options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters.ValidateActor = false;
options.TokenValidationParameters.ValidAudience = configuration.GetSection("Jwt:Audience").Value;
options.TokenValidationParameters.ValidateAudience = true;
options.TokenValidationParameters.ValidIssuer = configuration.GetSection("Jwt:Issuer").Value;
options.TokenValidationParameters.ValidateIssuer = true;
options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(configuration.GetSection("Jwt:Key").Value ?? throw new ArgumentNullException(nameof(TokenValidationParameters), "Jwt:Key"))
);
options.TokenValidationParameters.ValidateIssuerSigningKey = true;
options.TokenValidationParameters.ValidateLifetime = true;
})
.AddPolicyScheme("Custom", "Custom", options =>
{
options.ForwardDefaultSelector = context =>
{
string authorization = context.Request.Headers[HeaderNames.Authorization];
if (!string.IsNullOrEmpty(authorization) && authorization.StartsWith("Bearer ")) return "Bearer";
return "Cookies";
};
});
return services;
}
public static IServiceCollection AddBearerAuthentication(this IServiceCollection services, IConfiguration configuration)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters.ValidateActor = false;
options.TokenValidationParameters.ValidAudience = configuration.GetValue<string?>(Appsettings.JwtAudience) ?? throw new Exception($"{Appsettings.JwtAudience} value not set (appsettings)");
options.TokenValidationParameters.ValidateAudience = true;
options.TokenValidationParameters.ValidIssuer = configuration.GetValue<string?>(Appsettings.JwtIssuer) ?? throw new Exception($"{Appsettings.JwtIssuer} value not set (appsettings)");
options.TokenValidationParameters.ValidateIssuer = true;
options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(configuration.GetValue<string?>(Appsettings.JwtKey) ?? throw new Exception($"{Appsettings.JwtKey} value not set (appsettings)"))
);
options.TokenValidationParameters.ValidateIssuerSigningKey = true;
options.TokenValidationParameters.ValidateLifetime = true;
});
return services;
}
public static IServiceCollection AddProxyServices(this IServiceCollection services, IConfiguration configuration)
{
// add before routing
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
return services;
}
public static IServiceCollection AddRoutingServices(this IServiceCollection services, IConfiguration configuration)
{
// add after proxy
services.AddRouting(options =>
{
options.LowercaseUrls = true;
});
return services;
}
private static IServiceCollection AddIdentityServices2(this IServiceCollection services, IConfiguration configuration)
{
var identityOptions = new MongoDbIdentityConfiguration
{
MongoDbSettings = new MongoDbSettings
{
ConnectionString = configuration.GetSection("ConnectionStrings:Mongo").Value,
DatabaseName = "insight"
},
IdentityOptionsAction = options =>
{
options.User.RequireUniqueEmail = true;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@.-_";
options.Password.RequireDigit = false;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.SignIn.RequireConfirmedAccount = false;
options.SignIn.RequireConfirmedEmail = false;
options.SignIn.RequireConfirmedPhoneNumber = false;
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
}
};
services.ConfigureMongoDbIdentity<InsightUser, InsightRole, ObjectId>(identityOptions)
.AddDefaultTokenProviders()
.AddSignInManager<InsightUser>();
return services;
}
private static IServiceCollection AddIdentityAuthentication(this IServiceCollection services, IConfiguration configuration)
{
services.AddAuthentication(options =>
{
//options.DefaultAuthenticateScheme =
});
//cookieBuilder.ApplicationCookie = builder.AddApplicationCookie();
//cookieBuilder.ExternalCookie = builder.AddExternalCookie();
//cookieBuilder.TwoFactorRememberMeCookie = builder.AddTwoFactorRememberMeCookie();
//cookieBuilder.TwoFactorUserIdCookie = builder.AddTwoFactorUserIdCookie();
//.AddCookie(options =>
//{
// options.
//};
//.AddIdentityCookies();
//.AddCookie(options =>
//{
// // Specify where to redirect un-authenticated users
// options.LoginPath = "/account/login";
// // Specify the name of the auth cookie.
// // ASP.NET picks a dumb name by default.
// options.Cookie.Name = "insight";
//});
return services; return services;
} }
} }

View file

@ -1,28 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Insight.Infrastructure</RootNamespace> <RootNamespace>Insight.Infrastructure</RootNamespace>
<Product>Insight</Product> <Product>Insight</Product>
<AssemblyVersion>2023.12.14.0</AssemblyVersion> <AssemblyVersion>2023.12.15.0</AssemblyVersion>
<ImplicitUsings>true</ImplicitUsings> <SatelliteResourceLanguages>none</SatelliteResourceLanguages>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.13" /> <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="MongoDB.Driver" Version="2.23.0" />
<PackageReference Include="AspNetCore.Identity.MongoDbCore" Version="3.1.2" /> <PackageReference Include="AspNetCore.Identity.MongoDbCore" Version="3.1.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" /> <PackageReference Include="MongoDB.Driver" Version="2.23.1" />
<PackageReference Include="Vaitr.Scheduler" Version="2023.12.6" /> <PackageReference Include="Vaitr.Scheduler" Version="2023.12.15.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,17 +0,0 @@
namespace Insight.Infrastructure.Models;
public class TokenOptions
{
public string Key { get; set; }
public int Expires { get; set; }
public Uri? Audience { get; set; }
public Uri? Issuer { get; set; }
public TokenOptions(string key, int expires, Uri? audience = null, Uri? issuer = null)
{
Key = key;
Expires = expires;
Audience = audience;
Issuer = issuer;
}
}

View file

@ -1,35 +0,0 @@
using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
namespace Insight.Infrastructure.Services;
public class AccountService
{
private readonly IMongoDatabase _database;
private readonly ILogger<AccountService> _logger;
public AccountService(IMongoDatabase database, ILogger<AccountService> logger)
{
_database = database;
_logger = logger;
}
public Task<PagedList<InsightUser>> GetAsync(
FilterDefinition<InsightUser>? filter = null,
SortDefinition<InsightUser>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.User().GetPagedAsync(filter, sort, offset, limit, cancellationToken);
public Task<PagedList<InsightUser>> GetAsync(
HttpRequest request,
HttpResponse response,
FilterDefinition<InsightUser>? filter = null,
SortDefinition<InsightUser>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.User().GetPagedAsync(request, response, filter, sort, offset, limit, cancellationToken);
}

View file

@ -1,35 +0,0 @@
using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
namespace Insight.Infrastructure.Services;
public class AgentService
{
private readonly IMongoDatabase _database;
private readonly ILogger<AgentService> _logger;
public AgentService(IMongoDatabase database, ILogger<AgentService> logger)
{
_database = database;
_logger = logger;
}
public Task<PagedList<AgentEntity>> GetAsync(
FilterDefinition<AgentEntity>? filter = null,
SortDefinition<AgentEntity>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.Agent().GetPagedAsync(filter, sort, offset, limit, cancellationToken);
public Task<PagedList<AgentEntity>> GetAsync(
HttpRequest request,
HttpResponse response,
FilterDefinition<AgentEntity>? filter = null,
SortDefinition<AgentEntity>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.Agent().GetPagedAsync(request, response, filter, sort, offset, limit, cancellationToken);
}

View file

@ -7,16 +7,9 @@ using System.Text.Encodings.Web;
namespace Insight.Infrastructure.Services; namespace Insight.Infrastructure.Services;
public class AuthenticatorService public class AuthenticatorService(UserManager<InsightUser> userManager)
{ {
private readonly IMongoDatabase _database; private readonly UserManager<InsightUser> _userManager = userManager;
private readonly UserManager<InsightUser> _userManager;
public AuthenticatorService(IMongoDatabase database, UserManager<InsightUser> userManager)
{
_database = database;
_userManager = userManager;
}
public async Task<bool> GetStatusAsync(InsightUser user) public async Task<bool> GetStatusAsync(InsightUser user)
{ {
@ -79,7 +72,7 @@ public class AuthenticatorService
return await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, count).ConfigureAwait(false); return await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, count).ConfigureAwait(false);
} }
public string GenerateQrCode(string email, string unformattedKey) public static string GenerateQrCode(string email, string unformattedKey)
{ {
var encoder = UrlEncoder.Default; var encoder = UrlEncoder.Default;

View file

@ -1,35 +0,0 @@
using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
namespace Insight.Infrastructure.Services;
public class CustomerService
{
private readonly IMongoDatabase _database;
private readonly ILogger<CustomerService> _logger;
public CustomerService(IMongoDatabase database, ILogger<CustomerService> logger)
{
_database = database;
_logger = logger;
}
public Task<PagedList<CustomerEntity>> GetAsync(
FilterDefinition<CustomerEntity>? filter = null,
SortDefinition<CustomerEntity>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.Customer().GetPagedAsync(filter, sort, offset, limit, cancellationToken);
public Task<PagedList<CustomerEntity>> GetAsync(
HttpRequest request,
HttpResponse response,
FilterDefinition<CustomerEntity>? filter = null,
SortDefinition<CustomerEntity>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.Customer().GetPagedAsync(request, response, filter, sort, offset, limit, cancellationToken);
}

View file

@ -1,35 +0,0 @@
using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
namespace Insight.Infrastructure.Services;
public class HostService
{
private readonly IMongoDatabase _database;
private readonly ILogger<HostService> _logger;
public HostService(IMongoDatabase database, ILogger<HostService> logger)
{
_database = database;
_logger = logger;
}
public Task<PagedList<HostEntity>> GetAsync(
FilterDefinition<HostEntity>? filter = null,
SortDefinition<HostEntity>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.Host().GetPagedAsync(filter, sort, offset, limit, cancellationToken);
public Task<PagedList<HostEntity>> GetAsync(
HttpRequest request,
HttpResponse response,
FilterDefinition<HostEntity>? filter = null,
SortDefinition<HostEntity>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.Host().GetPagedAsync(request, response, filter, sort, offset, limit, cancellationToken);
}

View file

@ -5,18 +5,10 @@ using System.Security.Claims;
namespace Insight.Infrastructure.Services; namespace Insight.Infrastructure.Services;
public class IdentityService public class IdentityService(UserManager<InsightUser> userManager, RoleManager<InsightRole> roleManager)
{ {
private readonly UserManager<InsightUser> _userManager; private readonly UserManager<InsightUser> _userManager = userManager;
private readonly RoleManager<InsightRole> _roleManager; private readonly RoleManager<InsightRole> _roleManager = roleManager;
private readonly ILogger<IdentityService> _logger;
public IdentityService(UserManager<InsightUser> userManager, RoleManager<InsightRole> roleManager, ILogger<IdentityService> logger)
{
_userManager = userManager;
_roleManager = roleManager;
_logger = logger;
}
public async Task SeedAsync() public async Task SeedAsync()
{ {

View file

@ -1,35 +0,0 @@
using Insight.Infrastructure.Entities;
using Insight.Infrastructure.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
namespace Insight.Infrastructure.Services;
public class InventoryService
{
private readonly IMongoDatabase _database;
private readonly ILogger<InventoryService> _logger;
public InventoryService(IMongoDatabase database, ILogger<InventoryService> logger)
{
_database = database;
_logger = logger;
}
public Task<PagedList<HostApplicationEntity>> GetAsync(
FilterDefinition<HostApplicationEntity>? filter = null,
SortDefinition<HostApplicationEntity>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.HostApplication().GetPagedAsync(filter, sort, offset, limit, cancellationToken);
public Task<PagedList<HostApplicationEntity>> GetAsync(
HttpRequest request,
HttpResponse response,
FilterDefinition<HostApplicationEntity>? filter = null,
SortDefinition<HostApplicationEntity>? sort = null,
int offset = 0,
int limit = 10,
CancellationToken cancellationToken = default) => _database.HostApplication().GetPagedAsync(request, response, filter, sort, offset, limit, cancellationToken);
}

View file

@ -1,20 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<RootNamespace>Insight.Remote.Shared</RootNamespace> <RootNamespace>Insight.Remote.Shared</RootNamespace>
<Product>Insight</Product> <Product>Insight</Product>
<AssemblyName>Insight.Remote.Shared</AssemblyName> <AssemblyName>Insight.Remote.Shared</AssemblyName>
<AssemblyVersion>2023.12.14.0</AssemblyVersion> <AssemblyVersion>2023.12.15.0</AssemblyVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" /> <PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="7.0.1" /> <PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.0" />
<PackageReference Include="SkiaSharp.Views.Desktop.Common" Version="2.88.6" /> <PackageReference Include="SkiaSharp.Views.Desktop.Common" Version="2.88.6" />
</ItemGroup> </ItemGroup>

View file

@ -2,16 +2,9 @@
namespace Insight.Remote.Shared.Models; namespace Insight.Remote.Shared.Models;
public class CursorInfo public class CursorInfo(byte[] imageBytes, Point hotspot, string cssOverride = "")
{ {
public byte[] ImageBytes { get; set; } public byte[] ImageBytes { get; set; } = imageBytes;
public Point HotSpot { get; set; } public Point HotSpot { get; set; } = hotspot;
public string CssOverride { get; set; } public string CssOverride { get; set; } = cssOverride;
public CursorInfo(byte[] imageBytes, Point hotspot, string cssOverride = "")
{
ImageBytes = imageBytes;
HotSpot = hotspot;
CssOverride = cssOverride;
}
} }

View file

@ -1,13 +1,7 @@
namespace Insight.Remote.Shared.Models; namespace Insight.Remote.Shared.Models;
public readonly struct SentFrame public readonly struct SentFrame(int frameSize, DateTimeOffset timestamp)
{ {
public SentFrame(int frameSize, DateTimeOffset timestamp) public DateTimeOffset Timestamp { get; } = timestamp;
{ public int FrameSize { get; } = frameSize;
FrameSize = frameSize;
Timestamp = timestamp;
}
public DateTimeOffset Timestamp { get; }
public int FrameSize { get; }
} }

View file

@ -235,7 +235,7 @@ public static class SECUR32
MaxTokenInfoClass MaxTokenInfoClass
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct QUOTA_LIMITS public readonly struct QUOTA_LIMITS
{ {
readonly UInt32 PagedPoolLimit; readonly UInt32 PagedPoolLimit;
readonly UInt32 NonPagedPoolLimit; readonly UInt32 NonPagedPoolLimit;

View file

@ -9,18 +9,11 @@ using Vaitr.Bus;
namespace Insight.Remote.Shared.Network.Handlers; namespace Insight.Remote.Shared.Network.Handlers;
public class RemoteHandler : IMessageHandler<RemoteSession> public class RemoteHandler(Bus bus, Streamer streamer, ILogger<RemoteHandler> logger) : IMessageHandler<RemoteSession>
{ {
private readonly Bus _bus; private readonly Bus _bus = bus;
private readonly Streamer _streamer; private readonly Streamer _streamer = streamer;
private readonly ILogger<RemoteHandler> _logger; private readonly ILogger<RemoteHandler> _logger = logger;
public RemoteHandler(Bus bus, Streamer streamer, ILogger<RemoteHandler> logger)
{
_bus = bus;
_streamer = streamer;
_logger = logger;
}
public async ValueTask HandleAsync<TMessage>(RemoteSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(RemoteSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -48,16 +41,18 @@ public class RemoteHandler : IMessageHandler<RemoteSession>
private async Task OnSessionResponse(RemoteSession session, RemoteSessionResponse sessionResponse, CancellationToken cancellationToken) private async Task OnSessionResponse(RemoteSession session, RemoteSessionResponse sessionResponse, CancellationToken cancellationToken)
{ {
_logger.LogInformation($"Remote {session.Id} => SessionResponse"); if (session.Id is not string sessionId) return;
_logger.LogInformation("Remote {session} => SessionResponse", sessionId);
session.Id = sessionResponse.SessionId; session.Id = sessionResponse.SessionId;
await _bus.PublishAsync(new IdentityChanged(session.Id)); await _bus.PublishAsync(new IdentityChanged(sessionId), cancellationToken);
} }
private async Task OnCastRequest(RemoteSession session, CastRequest castRequest, CancellationToken cancellationToken) private async Task OnCastRequest(RemoteSession session, CastRequest castRequest, CancellationToken cancellationToken)
{ {
_logger.LogInformation($"Remote {session.Id} => CastRequest"); _logger.LogInformation("Remote {session.Id} => CastRequest", session.Id);
//if (request.RequesterName is null || request.ConnectionId is null) return; //if (request.RequesterName is null || request.ConnectionId is null) return;
@ -105,7 +100,7 @@ public class RemoteHandler : IMessageHandler<RemoteSession>
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
} }
//DesktopStream? viewer = _viewerPool.Values.FirstOrDefault(p => p.ConnectionId == request.ConnectionId); //DesktopStream? viewer = _viewerPool.Values.FirstOrDefault(p => p.ConnectionId == request.ConnectionId);
@ -121,7 +116,7 @@ public class RemoteHandler : IMessageHandler<RemoteSession>
private async Task OnCastAbort(RemoteSession session, CastAbort castAbort, CancellationToken cancellationToken) private async Task OnCastAbort(RemoteSession session, CastAbort castAbort, CancellationToken cancellationToken)
{ {
_logger.LogInformation($"Remote {session.Id} => CastAbort"); _logger.LogInformation("Remote {session} => CastAbort", session.Id);
await _streamer.CancelAsync(castAbort, cancellationToken); await _streamer.CancelAsync(castAbort, cancellationToken);
} }
@ -148,7 +143,7 @@ public class RemoteHandler : IMessageHandler<RemoteSession>
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
} }

View file

@ -4,26 +4,23 @@ using Insight.Domain.Network;
using Insight.Domain.Network.Remote.Messages; using Insight.Domain.Network.Remote.Messages;
using Insight.Remote.Shared.Messages; using Insight.Remote.Shared.Messages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.ServiceProcess;
using Vaitr.Bus; using Vaitr.Bus;
using Vaitr.Network; using Vaitr.Network;
namespace Insight.Remote.Shared.Network; namespace Insight.Remote.Shared.Network;
public class RemoteSession : TcpSession<IMessage> public class RemoteSession(
Bus bus,
IEnumerable<IMessageHandler<RemoteSession>> handlers,
ISerializer<IMessage> serializer,
ILogger<RemoteSession> logger) : TcpSession<IMessage>(serializer, logger)
{ {
public string? Id { get; set; } public string? Id { get; set; }
public string? AccessKey { get; set; } public string? AccessKey { get; set; }
public RemoteControlMode Mode { get; } = RunningAsService() ? RemoteControlMode.Unattended : RemoteControlMode.Attended; public RemoteControlMode Mode { get; } = RunningAsService() ? RemoteControlMode.Unattended : RemoteControlMode.Attended;
private readonly Bus _bus; private readonly Bus _bus = bus;
private readonly IEnumerable<IMessageHandler<RemoteSession>> _handlers; private readonly IEnumerable<IMessageHandler<RemoteSession>> _handlers = handlers;
public RemoteSession(Bus bus, IEnumerable<IMessageHandler<RemoteSession>> handlers, ISerializer<IMessage> serializer, ILogger<RemoteSession> logger) : base(serializer, logger)
{
_bus = bus;
_handlers = handlers;
}
protected override async ValueTask OnConnectedAsync(CancellationToken cancellationToken) protected override async ValueTask OnConnectedAsync(CancellationToken cancellationToken)
{ {
@ -45,9 +42,10 @@ public class RemoteSession : TcpSession<IMessage>
await _bus.PublishAsync(new ConnectionStateChanged(ConnectionState.Disconnected)); await _bus.PublishAsync(new ConnectionStateChanged(ConnectionState.Disconnected));
} }
protected override async ValueTask OnSentAsync(IPacketContext<IMessage> context, CancellationToken cancellationToken) protected override ValueTask OnSentAsync(IPacketContext<IMessage> context, CancellationToken cancellationToken)
{ {
//await base.OnSentAsync(context, cancellationToken); //await base.OnSentAsync(context, cancellationToken);
return default;
} }
protected override async ValueTask OnReceivedAsync(IPacketContext<IMessage> context, CancellationToken cancellationToken) protected override async ValueTask OnReceivedAsync(IPacketContext<IMessage> context, CancellationToken cancellationToken)
@ -67,12 +65,14 @@ public class RemoteSession : TcpSession<IMessage>
} }
} }
protected override async ValueTask OnHeartbeatAsync(CancellationToken cancellationToken) protected override ValueTask OnHeartbeatAsync(CancellationToken cancellationToken)
{ {
_logger.LogInformation("Remote ({ep?}) Heartbeat", RemoteEndPoint); _logger.LogInformation("Remote ({ep?}) Heartbeat", RemoteEndPoint);
return default;
} }
private async ValueTask OnWindowsSessionSwitchedAsync(WindowsSessionSwitched message, CancellationToken cancellationToken) private ValueTask OnWindowsSessionSwitchedAsync(WindowsSessionSwitched message, CancellationToken cancellationToken)
{ {
try try
{ {
@ -80,23 +80,24 @@ public class RemoteSession : TcpSession<IMessage>
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
} }
return default;
} }
private async ValueTask OnWindowsSessionEndingAsync(WindowsSessionEnding message, CancellationToken cancellationToken) private static ValueTask OnWindowsSessionEndingAsync(WindowsSessionEnding message, CancellationToken cancellationToken)
{ {
//await DisconnectViewersAsync(); //await DisconnectViewersAsync();
return default;
} }
private static bool RunningAsService() private static bool RunningAsService()
{ {
return false; //if (OperatingSystem.IsWindows())
//{
if (OperatingSystem.IsWindows()) // return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals("remotecontrol"));
{ //}
return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals("remotecontrol"));
}
return false; return false;
} }

View file

@ -10,7 +10,7 @@ public class Runtime : IHostedService
private readonly CancellationTokenSource _cts = new(); private readonly CancellationTokenSource _cts = new();
private Task? _desktopTask; private Task? _desktopTask;
private Thread? _uiThread; private readonly Thread? _uiThread;
private readonly IDesktopApp _desktopApp; private readonly IDesktopApp _desktopApp;
private readonly IDispatcher _dispatcher; private readonly IDispatcher _dispatcher;
@ -31,20 +31,21 @@ public class Runtime : IHostedService
_lifetime.ApplicationStopping.Register(_cts.Cancel); _lifetime.ApplicationStopping.Register(_cts.Cancel);
} }
public async Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
{ {
// init app (os specific providers) // init app (os specific providers)
_desktopTask = _desktopApp.InitAsync(RemoteControlMode.Attended, _cts.Token); _desktopTask = _desktopApp.InitAsync(RemoteControlMode.Attended, _cts.Token);
// init dispatcher // init ui dispatcher / if mode is attended (interactive)
if (false) // if mode is attended (interactive) //if (true)
{ //{
// init ui thread // _uiThread = await _dispatcher.RunAsync(_cts.Token);
_uiThread = await _dispatcher.RunAsync(_cts.Token); //}
}
// todo // todo
// report unattended accesskey to api ($"https://localhost:7024?mode=Unattended&sessionId={appState.SessionId}&accessKey={appState.AccessKey}") // report unattended accesskey to api ($"https://localhost:7024?mode=Unattended&sessionId={appState.SessionId}&accessKey={appState.AccessKey}")
return Task.CompletedTask;
} }
public async Task StopAsync(CancellationToken cancellationToken) public async Task StopAsync(CancellationToken cancellationToken)

View file

@ -14,7 +14,16 @@ using Vaitr.Network;
namespace Insight.Remote.Shared.Services; namespace Insight.Remote.Shared.Services;
public class Streamer : IDisposable public class Streamer(
Bus bus,
ISessionPool<RemoteSession, IMessage> remotePool,
IFileProvider fileProvider,
IClipboardProvider clipboardProvider,
IAudioProvider audioProvider,
IInputProvider inputProvider,
ICursorProvider cursorProvider,
IScreenProvider screenProvider,
ILogger<Streamer> logger) : IDisposable
{ {
public int ImageQuality { get; set; } = 50; public int ImageQuality { get; set; } = 50;
public bool HasControl { get; set; } = true; public bool HasControl { get; set; } = true;
@ -34,37 +43,15 @@ public class Streamer : IDisposable
private readonly ConcurrentQueue<DateTimeOffset> _fpsQueue = new(); private readonly ConcurrentQueue<DateTimeOffset> _fpsQueue = new();
private readonly ConcurrentQueue<SentFrame> _sentFrames = new(); private readonly ConcurrentQueue<SentFrame> _sentFrames = new();
private readonly Bus _bus; private readonly Bus _bus = bus;
private readonly ISessionPool<RemoteSession, IMessage> _remotePool; private readonly ISessionPool<RemoteSession, IMessage> _remotePool = remotePool;
private readonly IFileProvider _fileProvider; private readonly IFileProvider _fileProvider = fileProvider;
private readonly IClipboardProvider _clipboardProvider; private readonly IClipboardProvider _clipboardProvider = clipboardProvider;
private readonly IAudioProvider _audioProvider; private readonly IAudioProvider _audioProvider = audioProvider;
private readonly IInputProvider _inputProvider; private readonly IInputProvider _inputProvider = inputProvider;
private readonly ICursorProvider _cursorProvider; private readonly ICursorProvider _cursorProvider = cursorProvider;
private readonly IScreenProvider _screenProvider; private readonly IScreenProvider _screenProvider = screenProvider;
private readonly ILogger<Streamer> _logger; private readonly ILogger<Streamer> _logger = logger;
public Streamer(
Bus bus,
ISessionPool<RemoteSession, IMessage> remotePool,
IFileProvider fileProvider,
IClipboardProvider clipboardProvider,
IAudioProvider audioProvider,
IInputProvider inputProvider,
ICursorProvider cursorProvider,
IScreenProvider screenProvider,
ILogger<Streamer> logger)
{
_bus = bus;
_remotePool = remotePool;
_fileProvider = fileProvider;
_clipboardProvider = clipboardProvider;
_audioProvider = audioProvider;
_inputProvider = inputProvider;
_cursorProvider = cursorProvider;
_screenProvider = screenProvider;
_logger = logger;
}
public async Task InitAsync(CastRequest request, CancellationToken cancellationToken) public async Task InitAsync(CastRequest request, CancellationToken cancellationToken)
{ {
@ -108,7 +95,7 @@ public class Streamer : IDisposable
catch (OperationCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
} }
finally finally
{ {
@ -260,7 +247,7 @@ public class Streamer : IDisposable
{ {
var cursor = await _cursorProvider.GetAsync(cancellationToken); var cursor = await _cursorProvider.GetAsync(cancellationToken);
if (cursor is null || cursor == cacheCursor) continue; if (cursor is null || cursor == cacheCursor) continue;
cursor.Id = remoteSession.Id; cursor.Id = remoteSession.Id;
await remoteSession.SendAsync(cursor, cancellationToken); await remoteSession.SendAsync(cursor, cancellationToken);
@ -268,7 +255,7 @@ public class Streamer : IDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError("{exception}", ex.Message);
} }
finally finally
{ {
@ -331,15 +318,20 @@ public class Streamer : IDisposable
// } // }
//} //}
public async Task CancelAsync(CastAbort castAbort, CancellationToken cancellationToken) public Task CancelAsync(CastAbort castAbort, CancellationToken cancellationToken)
{ {
_cts?.Cancel(); _cts?.Cancel();
return Task.CompletedTask;
} }
public async Task FrameReceivedAsync(CastScreenReceived screenDataReceived, CancellationToken cancellationToken) public Task FrameReceivedAsync(CastScreenReceived screenDataReceived, CancellationToken cancellationToken)
{ {
if (screenDataReceived.Timestamp is null) return Task.CompletedTask;
_lastFrameReceived = screenDataReceived.Timestamp.Value.ToLocalTime(); _lastFrameReceived = screenDataReceived.Timestamp.Value.ToLocalTime();
_framesSentSinceLastReceipt = 0; _framesSentSinceLastReceipt = 0;
return Task.CompletedTask;
} }
public async Task CursorReceivedAsync(CastCursorReceived cursorCallbackData, CancellationToken cancellationToken) public async Task CursorReceivedAsync(CastCursorReceived cursorCallbackData, CancellationToken cancellationToken)

View file

@ -2,7 +2,8 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework> <TargetFramework>net8.0-windows</TargetFramework>
<LangVersion>latest</LangVersion>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<Product>Remote Control</Product> <Product>Remote Control</Product>
@ -12,10 +13,11 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="NAudio.Wasapi" Version="2.2.1" /> <PackageReference Include="NAudio.Wasapi" Version="2.2.1" />
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" /> <PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />
</ItemGroup> </ItemGroup>

View file

@ -4,28 +4,18 @@ using SharpDX.DXGI;
namespace Insight.Remote.Windows.Models; namespace Insight.Remote.Windows.Models;
public class DirectXOutput : IDisposable public class DirectXOutput(Adapter1 adapter,
SharpDX.Direct3D11.Device device,
OutputDuplication outputDuplication,
Texture2D texture2D,
DisplayModeRotation rotation) : IDisposable
{ {
public DirectXOutput(Adapter1 adapter, public Adapter1 Adapter { get; } = adapter;
SharpDX.Direct3D11.Device device, public Rectangle Bounds { get; set; } = new Rectangle(0, 0, texture2D.Description.Width, texture2D.Description.Height);
OutputDuplication outputDuplication, public SharpDX.Direct3D11.Device Device { get; } = device;
Texture2D texture2D, public OutputDuplication OutputDuplication { get; } = outputDuplication;
DisplayModeRotation rotation) public DisplayModeRotation Rotation { get; } = rotation;
{ public Texture2D Texture2D { get; } = texture2D;
Adapter = adapter;
Device = device;
OutputDuplication = outputDuplication;
Texture2D = texture2D;
Rotation = rotation;
Bounds = new Rectangle(0, 0, texture2D.Description.Width, texture2D.Description.Height);
}
public Adapter1 Adapter { get; }
public Rectangle Bounds { get; set; }
public SharpDX.Direct3D11.Device Device { get; }
public OutputDuplication OutputDuplication { get; }
public DisplayModeRotation Rotation { get; }
public Texture2D Texture2D { get; }
public void Dispose() public void Dispose()
{ {

View file

@ -9,44 +9,33 @@ using Microsoft.Extensions.Logging;
using Microsoft.Win32; using Microsoft.Win32;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.Windows; using System.Runtime.Versioning;
using Vaitr.Bus; using Vaitr.Bus;
namespace Insight.Remote.Windows.Services; namespace Insight.Remote.Windows.Services;
internal class WinApp : IDesktopApp [SupportedOSPlatform("windows")]
internal class WinApp(
IInputProvider inputProvider,
ICursorProvider cursorProvider,
IAudioProvider audioProvider,
IClipboardProvider clipboardProvider,
IDispatcher dispatcher,
MainViewModel mainViewModel,
Bus bus,
ILogger<WinApp> logger) : IDesktopApp
{ {
private MainWindow? _mainWindow; private MainWindow? _mainWindow;
private bool _disposed; private bool _disposed;
private readonly IInputProvider _inputProvider; private readonly IInputProvider _inputProvider = inputProvider;
private readonly ICursorProvider _cursorProvider; private readonly ICursorProvider _cursorProvider = cursorProvider;
private readonly IAudioProvider _audioProvider; private readonly IAudioProvider _audioProvider = audioProvider;
private readonly IClipboardProvider _clipboardProvider; private readonly IClipboardProvider _clipboardProvider = clipboardProvider;
private readonly IDispatcher _dispatcher; private readonly IDispatcher _dispatcher = dispatcher;
private readonly MainViewModel _maiViewModel; private readonly MainViewModel _maiViewModel = mainViewModel;
private readonly Bus _bus; private readonly Bus _bus = bus;
private readonly ILogger<WinApp> _logger; private readonly ILogger<WinApp> _logger = logger;
public WinApp(
IInputProvider inputProvider,
ICursorProvider cursorProvider,
IAudioProvider audioProvider,
IClipboardProvider clipboardProvider,
IDispatcher dispatcher,
MainViewModel mainViewModel,
Bus bus,
ILogger<WinApp> logger)
{
_inputProvider = inputProvider;
_cursorProvider = cursorProvider;
_audioProvider = audioProvider;
_clipboardProvider = clipboardProvider;
_dispatcher = dispatcher;
_maiViewModel = mainViewModel;
_bus = bus;
_logger = logger;
}
public async Task InitAsync(RemoteControlMode mode, CancellationToken cancellationToken) public async Task InitAsync(RemoteControlMode mode, CancellationToken cancellationToken)
{ {
@ -100,7 +89,7 @@ internal class WinApp : IDesktopApp
catch (TaskCanceledException) { } catch (TaskCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
} }
} }
} }
@ -143,7 +132,7 @@ internal class WinApp : IDesktopApp
catch (TaskCanceledException) { } catch (TaskCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
} }
} }
@ -153,26 +142,21 @@ internal class WinApp : IDesktopApp
private async ValueTask OnCastRequestAsync(CastRequest request, CancellationToken cancellationToken) private async ValueTask OnCastRequestAsync(CastRequest request, CancellationToken cancellationToken)
{ {
if (true) // test // test (bypass)
{ //if (request.Mode != RemoteControlMode.Unattended)
await _bus.PublishAsync(new CastRequestDemand(request, true), cancellationToken); //{
return; // var result = await _dispatcher.InvokeAsync(() =>
} // {
// return System.Windows.MessageBox.Show($"Accept connection request from {request.RequesterName}?", "Connection Request",
// MessageBoxButton.YesNo,
// MessageBoxImage.Question);
// }, cancellationToken);
if (request.Mode != RemoteControlMode.Unattended) // switch (result)
{ // {
var result = await _dispatcher.InvokeAsync(() => // case MessageBoxResult.No: await _bus.PublishAsync(new CastRequestDemand(request, false), cancellationToken); return;
{ // }
return System.Windows.MessageBox.Show($"Accept connection request from {request.RequesterName}?", "Connection Request", //}
MessageBoxButton.YesNo,
MessageBoxImage.Question);
}, cancellationToken);
switch (result)
{
case MessageBoxResult.No: await _bus.PublishAsync(new CastRequestDemand(request, false), cancellationToken); return;
}
}
await _bus.PublishAsync(new CastRequestDemand(request, true), cancellationToken); await _bus.PublishAsync(new CastRequestDemand(request, true), cancellationToken);
} }

View file

@ -7,19 +7,13 @@ using Vaitr.Bus;
namespace Insight.Remote.Windows.Services; namespace Insight.Remote.Windows.Services;
internal class WinAudioProvider : IAudioProvider internal class WinAudioProvider(Bus bus, ILogger<WinAudioProvider> logger) : IAudioProvider
{ {
private WasapiLoopbackCapture? _capturer; private WasapiLoopbackCapture? _capturer;
private WaveFormat? _targetFormat; private WaveFormat? _targetFormat;
private readonly Bus _bus; private readonly Bus _bus = bus;
private readonly ILogger<WinAudioProvider> _logger; private readonly ILogger<WinAudioProvider> _logger = logger;
public WinAudioProvider(Bus bus, ILogger<WinAudioProvider> logger)
{
_bus = bus;
_logger = logger;
}
public async Task InitAsync(CancellationToken cancellationToken) public async Task InitAsync(CancellationToken cancellationToken)
{ {

View file

@ -8,18 +8,12 @@ using Clipboard = System.Windows.Clipboard;
namespace Insight.Remote.Windows.Services; namespace Insight.Remote.Windows.Services;
internal class WinClipboardProvider : IClipboardProvider internal class WinClipboardProvider(Bus bus, ILogger<WinClipboardProvider> logger) : IClipboardProvider
{ {
private readonly ConcurrentQueue<string> _setQueue = new(); private readonly ConcurrentQueue<string> _setQueue = new();
private readonly Bus _bus; private readonly Bus _bus = bus;
private readonly ILogger<WinClipboardProvider> _logger; private readonly ILogger<WinClipboardProvider> _logger = logger;
public WinClipboardProvider(Bus bus, ILogger<WinClipboardProvider> logger)
{
_bus = bus;
_logger = logger;
}
public async Task InitAsync(CancellationToken cancellationToken) public async Task InitAsync(CancellationToken cancellationToken)
{ {
@ -79,7 +73,7 @@ internal class WinClipboardProvider : IClipboardProvider
catch (TaskCanceledException) { } catch (TaskCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
} }
} }
} }

View file

@ -8,20 +8,15 @@ using System.Runtime.InteropServices;
namespace Insight.Remote.Windows.Services; namespace Insight.Remote.Windows.Services;
internal class WinCursorProvider : ICursorProvider internal class WinCursorProvider(ILogger<WinCursorProvider> logger) : ICursorProvider
{ {
private readonly SemaphoreSlim _semaphore = new(1, 1); private readonly SemaphoreSlim _semaphore = new(1, 1);
private readonly ILogger<WinCursorProvider> _logger; private readonly ILogger<WinCursorProvider> _logger = logger;
private User32.CursorInfo _cursor = new(); private User32.CursorInfo _cursor = new();
private CastCursor _lastCursor = new(); private CastCursor _lastCursor = new();
private nint _lastHandle = 0; private nint _lastHandle = 0;
private byte[] _lastIconBytes = Array.Empty<byte>(); private byte[] _lastIconBytes = [];
public WinCursorProvider(ILogger<WinCursorProvider> logger)
{
_logger = logger;
}
public async Task<CastCursor?> GetAsync(CancellationToken cancellationToken) public async Task<CastCursor?> GetAsync(CancellationToken cancellationToken)
{ {
@ -73,7 +68,7 @@ internal class WinCursorProvider : ICursorProvider
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
return null; return null;
} }
finally finally
@ -92,10 +87,10 @@ internal class WinCursorProvider : ICursorProvider
User32.SetCursorPos(x, y); User32.SetCursorPos(x, y);
} }
catch (TaskCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
} }
finally finally
{ {
@ -107,6 +102,6 @@ internal class WinCursorProvider : ICursorProvider
{ {
X = 0, X = 0,
Y = 0, Y = 0,
Icon = Array.Empty<byte>() Icon = []
}; };
} }

View file

@ -6,20 +6,14 @@ using Application = System.Windows.Application;
namespace Insight.Remote.Windows.Services; namespace Insight.Remote.Windows.Services;
internal class WinDispatcher : IDispatcher internal class WinDispatcher(IHostApplicationLifetime lifetime, ILogger<WinDispatcher> logger) : IDispatcher
{ {
private Application? _app; private Application? _app;
private readonly ManualResetEvent _appSignal = new(false); private readonly ManualResetEvent _appSignal = new(false);
private readonly IHostApplicationLifetime _lifetime; private readonly IHostApplicationLifetime _lifetime = lifetime;
private readonly ILogger<WinDispatcher> _logger; private readonly ILogger<WinDispatcher> _logger = logger;
public WinDispatcher(IHostApplicationLifetime lifetime, ILogger<WinDispatcher> logger)
{
_lifetime = lifetime;
_logger = logger;
}
public async Task<Thread> RunAsync(CancellationToken cancellationToken) public async Task<Thread> RunAsync(CancellationToken cancellationToken)
{ {
@ -56,7 +50,7 @@ internal class WinDispatcher : IDispatcher
catch (TaskCanceledException) { } catch (TaskCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
} }
} }

View file

@ -5,6 +5,7 @@ using Microsoft.Extensions.Logging;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.Versioning;
using System.Security.AccessControl; using System.Security.AccessControl;
using System.Security.Principal; using System.Security.Principal;
using System.Windows; using System.Windows;
@ -12,17 +13,13 @@ using MessageBoxOptions = System.Windows.MessageBoxOptions;
namespace Insight.Remote.Windows.Services; namespace Insight.Remote.Windows.Services;
internal class WinFileProvider : IFileProvider [SupportedOSPlatform("windows")]
internal class WinFileProvider(ILogger<WinFileProvider> logger) : IFileProvider
{ {
private static MessageBoxResult? _result; private static MessageBoxResult? _result;
private static readonly ConcurrentDictionary<string, FileStream> _partialTransfers = new(); private static readonly ConcurrentDictionary<string, FileStream> _partialTransfers = new();
private static readonly SemaphoreSlim _writeLock = new(1, 1); private static readonly SemaphoreSlim _writeLock = new(1, 1);
private readonly ILogger<WinFileProvider> _logger; private readonly ILogger<WinFileProvider> _logger = logger;
public WinFileProvider(ILogger<WinFileProvider> logger)
{
_logger = logger;
}
public string GetBaseDirectory() public string GetBaseDirectory()
{ {
@ -89,7 +86,7 @@ internal class WinFileProvider : IFileProvider
} }
} }
public async Task UploadFile(FileUpload fileUpload, Streamer viewer, Action<double> progressUpdateCallback, CancellationToken cancelToken) public Task UploadFile(FileUpload fileUpload, Streamer viewer, Action<double> progressUpdateCallback, CancellationToken cancelToken)
{ {
try try
{ {
@ -99,9 +96,11 @@ internal class WinFileProvider : IFileProvider
{ {
_logger.LogError(ex, "Error while uploading file."); _logger.LogError(ex, "Error while uploading file.");
} }
return Task.CompletedTask;
} }
private void SetFileOrFolderPermissions(string path) private static void SetFileOrFolderPermissions(string path)
{ {
FileSystemSecurity ds; FileSystemSecurity ds;

View file

@ -6,20 +6,14 @@ using System.Threading.Channels;
namespace Insight.Remote.Windows.Services; namespace Insight.Remote.Windows.Services;
internal class WinInputProvider : IInputProvider internal class WinInputProvider(IScreenProvider screenProvider, ILogger<WinInputProvider> logger) : IInputProvider
{ {
private volatile bool _inputBlocked; private volatile bool _inputBlocked;
private readonly Channel<Action> _inputs = Channel.CreateUnbounded<Action>(new UnboundedChannelOptions { AllowSynchronousContinuations = false }); private readonly Channel<Action> _inputs = Channel.CreateUnbounded<Action>(new UnboundedChannelOptions { AllowSynchronousContinuations = false });
private readonly IScreenProvider _screenProvider; private readonly IScreenProvider _screenProvider = screenProvider;
private readonly ILogger<WinInputProvider> _logger; private readonly ILogger<WinInputProvider> _logger = logger;
public WinInputProvider(IScreenProvider screenProvider, ILogger<WinInputProvider> logger)
{
_screenProvider = screenProvider;
_logger = logger;
}
public async Task InitAsync(CancellationToken cancellationToken) public async Task InitAsync(CancellationToken cancellationToken)
{ {
@ -31,10 +25,10 @@ internal class WinInputProvider : IInputProvider
await Task.Delay(1000, cancellationToken); await Task.Delay(1000, cancellationToken);
} }
} }
catch (TaskCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
@ -68,7 +62,7 @@ internal class WinInputProvider : IInputProvider
catch (OperationCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError("{exception}", ex.Message);
} }
} }
@ -83,10 +77,10 @@ internal class WinInputProvider : IInputProvider
{ {
await semaphore.WaitAsync(cancellationToken); await semaphore.WaitAsync(cancellationToken);
} }
catch (TaskCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
@ -110,13 +104,13 @@ internal class WinInputProvider : IInputProvider
}; };
var input = new User32.INPUT() { type = User32.InputType.KEYBOARD, U = union }; var input = new User32.INPUT() { type = User32.InputType.KEYBOARD, U = union };
_ = User32.SendInput(1, new User32.INPUT[] { input }, User32.INPUT.Size); _ = User32.SendInput(1, [input], User32.INPUT.Size);
}, cancellationToken); }, cancellationToken);
} }
catch (TaskCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
@ -140,13 +134,13 @@ internal class WinInputProvider : IInputProvider
} }
}; };
var input = new User32.INPUT() { type = User32.InputType.KEYBOARD, U = union }; var input = new User32.INPUT() { type = User32.InputType.KEYBOARD, U = union };
_ = User32.SendInput(1, new User32.INPUT[] { input }, User32.INPUT.Size); _ = User32.SendInput(1, [input], User32.INPUT.Size);
}, cancellationToken); }, cancellationToken);
} }
catch (TaskCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
@ -209,13 +203,13 @@ internal class WinInputProvider : IInputProvider
var normalizedY = xyPercent.Item2 * 65535D; var normalizedY = xyPercent.Item2 * 65535D;
var union = new User32.InputUnion() { mi = new User32.MOUSEINPUT() { dwFlags = User32.MOUSEEVENTF.ABSOLUTE | mouseEvent | User32.MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = User32.GetMessageExtraInfo() } }; var union = new User32.InputUnion() { mi = new User32.MOUSEINPUT() { dwFlags = User32.MOUSEEVENTF.ABSOLUTE | mouseEvent | User32.MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = User32.GetMessageExtraInfo() } };
var input = new User32.INPUT() { type = User32.InputType.MOUSE, U = union }; var input = new User32.INPUT() { type = User32.InputType.MOUSE, U = union };
_ = User32.SendInput(1, new User32.INPUT[] { input }, User32.INPUT.Size); _ = User32.SendInput(1, [input], User32.INPUT.Size);
}, cancellationToken); }, cancellationToken);
} }
catch (TaskCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
@ -231,13 +225,13 @@ internal class WinInputProvider : IInputProvider
var normalizedY = xyPercent.Item2 * 65535D; var normalizedY = xyPercent.Item2 * 65535D;
var union = new User32.InputUnion() { mi = new User32.MOUSEINPUT() { dwFlags = User32.MOUSEEVENTF.ABSOLUTE | User32.MOUSEEVENTF.MOVE | User32.MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = User32.GetMessageExtraInfo() } }; var union = new User32.InputUnion() { mi = new User32.MOUSEINPUT() { dwFlags = User32.MOUSEEVENTF.ABSOLUTE | User32.MOUSEEVENTF.MOVE | User32.MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = User32.GetMessageExtraInfo() } };
var input = new User32.INPUT() { type = User32.InputType.MOUSE, U = union }; var input = new User32.INPUT() { type = User32.InputType.MOUSE, U = union };
_ = User32.SendInput(1, new User32.INPUT[] { input }, User32.INPUT.Size); _ = User32.SendInput(1, [input], User32.INPUT.Size);
}, cancellationToken); }, cancellationToken);
} }
catch (TaskCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
@ -257,13 +251,13 @@ internal class WinInputProvider : IInputProvider
} }
var union = new User32.InputUnion() { mi = new User32.MOUSEINPUT() { dwFlags = User32.MOUSEEVENTF.WHEEL, dx = 0, dy = 0, time = 0, mouseData = deltaY, dwExtraInfo = User32.GetMessageExtraInfo() } }; var union = new User32.InputUnion() { mi = new User32.MOUSEINPUT() { dwFlags = User32.MOUSEEVENTF.WHEEL, dx = 0, dy = 0, time = 0, mouseData = deltaY, dwExtraInfo = User32.GetMessageExtraInfo() } };
var input = new User32.INPUT() { type = User32.InputType.MOUSE, U = union }; var input = new User32.INPUT() { type = User32.InputType.MOUSE, U = union };
_ = User32.SendInput(1, new User32.INPUT[] { input }, User32.INPUT.Size); _ = User32.SendInput(1, [input], User32.INPUT.Size);
}, cancellationToken); }, cancellationToken);
} }
catch (TaskCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
@ -276,10 +270,10 @@ internal class WinInputProvider : IInputProvider
SendKeys.SendWait(transferText); SendKeys.SendWait(transferText);
}, cancellationToken); }, cancellationToken);
} }
catch (TaskCanceledException) { } catch (OperationCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
@ -308,7 +302,7 @@ internal class WinInputProvider : IInputProvider
} }
}; };
var input = new User32.INPUT() { type = User32.InputType.KEYBOARD, U = union }; var input = new User32.INPUT() { type = User32.InputType.KEYBOARD, U = union };
_ = User32.SendInput(1, new User32.INPUT[] { input }, User32.INPUT.Size); _ = User32.SendInput(1, [input], User32.INPUT.Size);
} }
} }
catch { } catch { }
@ -318,7 +312,7 @@ internal class WinInputProvider : IInputProvider
catch (TaskCanceledException) { } catch (TaskCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }
@ -337,7 +331,7 @@ internal class WinInputProvider : IInputProvider
catch (TaskCanceledException) { } catch (TaskCanceledException) { }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.ToString()); _logger.LogError("{exception}", ex.ToString());
} }
} }

View file

@ -37,11 +37,13 @@ using SkiaSharp.Views.Desktop;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Vaitr.Bus; using Vaitr.Bus;
using Result = RemoteControl.Shared.Result; using Result = RemoteControl.Shared.Result;
namespace Insight.Remote.Windows.Services; namespace Insight.Remote.Windows.Services;
[SupportedOSPlatform("windows")]
internal class WinScreenCapturer : IScreenProvider internal class WinScreenCapturer : IScreenProvider
{ {
public event EventHandler<Rectangle>? ScreenChanged; public event EventHandler<Rectangle>? ScreenChanged;
@ -72,8 +74,8 @@ internal class WinScreenCapturer : IScreenProvider
private bool _initialized; private bool _initialized;
private readonly SemaphoreSlim _semaphore = new(1, 1); private readonly SemaphoreSlim _semaphore = new(1, 1);
private readonly Dictionary<string, int> _bitBltScreens = new(); private readonly Dictionary<string, int> _bitBltScreens = [];
private readonly Dictionary<string, DirectXOutput> _directxScreens = new(); private readonly Dictionary<string, DirectXOutput> _directxScreens = [];
private readonly Bus _bus; private readonly Bus _bus;
private readonly ILogger<WinScreenCapturer> _logger; private readonly ILogger<WinScreenCapturer> _logger;
@ -86,7 +88,7 @@ internal class WinScreenCapturer : IScreenProvider
SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged; SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
} }
public async Task InitAsync(CancellationToken cancellationToken) public Task InitAsync(CancellationToken cancellationToken)
{ {
Win32Interop.SwitchToInputDesktop(); Win32Interop.SwitchToInputDesktop();
@ -94,6 +96,8 @@ internal class WinScreenCapturer : IScreenProvider
InitDirectX(); InitDirectX();
_initialized = true; _initialized = true;
return Task.CompletedTask;
} }
public void SetSelectedScreen(string displayName) public void SetSelectedScreen(string displayName)

View file

@ -2,9 +2,7 @@
using Insight.Remote.Shared.Messages; using Insight.Remote.Shared.Messages;
using Insight.Remote.Shared.Native.Windows; using Insight.Remote.Shared.Native.Windows;
using Insight.Remote.Shared.Reactive; using Insight.Remote.Shared.Reactive;
using Insight.Remote.Shared.Services;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using System.Security.Principal; using System.Security.Principal;
using Vaitr.Bus; using Vaitr.Bus;
@ -28,7 +26,7 @@ public class MainViewModel : ViewModelBase
private string? _lastId; private string? _lastId;
private readonly List<IDisposable> _subscriptions = new(); private readonly List<IDisposable> _subscriptions = [];
private readonly Bus _bus; private readonly Bus _bus;
private readonly IDispatcher _dispatcher; private readonly IDispatcher _dispatcher;
@ -152,6 +150,6 @@ public class FakeMainViewModel : ViewModelBase
public RelayCommand ElevateToAdminCommand { get; } = new(() => { }); public RelayCommand ElevateToAdminCommand { get; } = new(() => { });
public RelayCommand ElevateToServiceCommand { get; } = new(() => { }); public RelayCommand ElevateToServiceCommand { get; } = new(() => { });
public bool IsAdministrator => false; public static bool IsAdministrator => false;
public string StatusMessage { get; set; } = "test"; public string StatusMessage { get; set; } = "test";
} }

View file

@ -25,7 +25,7 @@ public partial class MainWindow : Window
private void Window_Loaded(object sender, RoutedEventArgs e) private void Window_Loaded(object sender, RoutedEventArgs e)
{ {
if (DesignerProperties.GetIsInDesignMode(this)) return; if (DesignerProperties.GetIsInDesignMode(this)) return;
if (DataContext is not MainViewModel vm) return; if (DataContext is not MainViewModel) return;
} }
private void Window_Closing(object sender, CancelEventArgs e) private void Window_Closing(object sender, CancelEventArgs e)

View file

@ -8,7 +8,7 @@ public static class Async
this IAsyncEnumerable<T> source, this IAsyncEnumerable<T> source,
Func<T, Task> body, Func<T, Task> body,
int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded, int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
TaskScheduler scheduler = null) TaskScheduler? scheduler = null)
{ {
var options = new ExecutionDataflowBlockOptions var options = new ExecutionDataflowBlockOptions
{ {
@ -31,7 +31,7 @@ public static class Async
this IEnumerable<T> source, this IEnumerable<T> source,
Func<T, Task> body, Func<T, Task> body,
int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded, int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
TaskScheduler scheduler = null) TaskScheduler? scheduler = null)
{ {
var options = new ExecutionDataflowBlockOptions var options = new ExecutionDataflowBlockOptions
{ {

View file

@ -2,13 +2,15 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Product>Insight</Product> <Product>Insight</Product>
<AssemblyName>server</AssemblyName> <AssemblyName>server</AssemblyName>
<AssemblyVersion>2023.12.14.0</AssemblyVersion> <AssemblyVersion>2023.12.14.0</AssemblyVersion>
<RootNamespace>Insight.Server</RootNamespace> <RootNamespace>Insight.Server</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -38,8 +40,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" /> <PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
<!--Unix Serilog stuff--> <!--Unix Serilog stuff-->
</ItemGroup> </ItemGroup>

View file

@ -7,18 +7,16 @@ using Vaitr.Network;
namespace Insight.Server.Network.Agent; namespace Insight.Server.Network.Agent;
public class AgentSession : TcpSession<IMessage> public class AgentSession(
AgentHandler agentHandler,
IEnumerable<IMessageHandler<AgentSession>> handlers,
ISerializer<IMessage> serializer,
ILogger<AgentSession> logger) : TcpSession<IMessage>(serializer, logger)
{ {
public string? Id { get; set; } public string? Id { get; set; }
private readonly AgentHandler _agentHandler; private readonly AgentHandler _agentHandler = agentHandler;
private readonly IEnumerable<IMessageHandler<AgentSession>> _handlers; private readonly IEnumerable<IMessageHandler<AgentSession>> _handlers = handlers;
public AgentSession(AgentHandler agentHandler, IEnumerable<IMessageHandler<AgentSession>> handlers, ISerializer<IMessage> serializer, ILogger<AgentSession> logger) : base(serializer, logger)
{
_agentHandler = agentHandler;
_handlers = handlers;
}
protected override async ValueTask OnConnectedAsync(CancellationToken cancellationToken) protected override async ValueTask OnConnectedAsync(CancellationToken cancellationToken)
{ {

View file

@ -8,16 +8,10 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class AgentHandler : IMessageHandler<AgentSession> public class AgentHandler(IMongoDatabase database, ILogger<AgentHandler> logger) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
private readonly ILogger<AgentHandler> _logger; private readonly ILogger<AgentHandler> _logger = logger;
public AgentHandler(IMongoDatabase database, ILogger<AgentHandler> logger)
{
_database = database;
_logger = logger;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {

View file

@ -5,14 +5,9 @@ using Microsoft.Extensions.Logging;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class CustomHandler : IMessageHandler<AgentSession> public class CustomHandler(ILogger<CustomHandler> logger) : IMessageHandler<AgentSession>
{ {
private readonly ILogger<CustomHandler> _logger; private readonly ILogger<CustomHandler> _logger = logger;
public CustomHandler(ILogger<CustomHandler> logger)
{
_logger = logger;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -24,8 +19,9 @@ public class CustomHandler : IMessageHandler<AgentSession>
} }
} }
private async ValueTask OnResponseAsync(AgentSession sender, Response response, CancellationToken cancellationToken) private ValueTask OnResponseAsync(AgentSession sender, Response response, CancellationToken cancellationToken)
{ {
_logger.LogWarning($"Response: {response.ResponseData}"); _logger.LogWarning("Response: {response}", response.ResponseData);
return default;
} }
} }

View file

@ -7,14 +7,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class DriveHandler : IMessageHandler<AgentSession> public class DriveHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public DriveHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -39,7 +34,7 @@ public class DriveHandler : IMessageHandler<AgentSession>
var driveBulk = new List<WriteModel<HostDriveEntity>>(); var driveBulk = new List<WriteModel<HostDriveEntity>>();
if (drives is not null && drives.Any()) if (drives is not null && drives.Count != 0)
{ {
foreach (var drive in drives) foreach (var drive in drives)
{ {
@ -83,16 +78,16 @@ public class DriveHandler : IMessageHandler<AgentSession>
var volumeBulk = new List<WriteModel<HostVolumeEntity>>(); var volumeBulk = new List<WriteModel<HostVolumeEntity>>();
if (drives is not null && drives.Any()) if (drives is not null && drives.Count != 0)
{ {
foreach (var drive in drives) foreach (var drive in drives)
{ {
var driveId = await _database.HostDrive() var driveId = await _database.HostDrive()
.Find(p => p.Host == hostEntity.Id && p.Index == drive.Index) .Find(p => p.Host == hostEntity.Id && p.Index == drive.Index)
.Project(p => p.Id) .Project(p => p.Id)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync(cancellationToken: default);
if (drive.Volumes is not null && drive.Volumes.Any()) if (drive.Volumes is not null && drive.Volumes.Count != 0)
{ {
foreach (var volume in drive.Volumes) foreach (var volume in drive.Volumes)
{ {

View file

@ -3,22 +3,14 @@ using Insight.Domain.Interfaces;
using Insight.Domain.Network; using Insight.Domain.Network;
using Insight.Domain.Network.Agent.Messages; using Insight.Domain.Network.Agent.Messages;
using Insight.Infrastructure.Entities; using Insight.Infrastructure.Entities;
using Microsoft.Extensions.Logging;
using MongoDB.Driver; using MongoDB.Driver;
using static Insight.Domain.Network.Agent.Messages.Event; using static Insight.Domain.Network.Agent.Messages.Event;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class EventHandler : IMessageHandler<AgentSession> public class EventHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
private readonly ILogger<EventHandler> _logger;
public EventHandler(IMongoDatabase database, ILogger<EventHandler> logger)
{
_database = database;
_logger = logger;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -75,13 +67,13 @@ public class EventHandler : IMessageHandler<AgentSession>
_ => null _ => null
}; };
CategoryEnum? category = @event.Category.ToLower() switch CategoryEnum? category = @event.Category?.ToLower() switch
{ {
"network" => CategoryEnum.Network, "network" => CategoryEnum.Network,
"application" => CategoryEnum.Application, "application" => CategoryEnum.Application,
"security" => CategoryEnum.Security, "security" => CategoryEnum.Security,
"system" => CategoryEnum.System, "system" => CategoryEnum.System,
_ => null _ => CategoryEnum.None
}; };
var date = DateTime.Now; var date = DateTime.Now;
@ -114,55 +106,59 @@ public class EventHandler : IMessageHandler<AgentSession>
_ => null _ => null
}; };
CategoryEnum? category = null; var category = CategoryEnum.None;
switch (@event.Category)
if (@event.Category is not null)
{ {
case var _ when @event.Category.Contains("network", StringComparison.InvariantCultureIgnoreCase): switch (@event.Category)
category = CategoryEnum.Network; {
break; case var _ when @event.Category.Contains("network", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.Network;
break;
case var _ when @event.Category.Contains("application", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("application", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.Application; category = CategoryEnum.Application;
break; break;
case var _ when @event.Category.Contains("security", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("security", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.Security; category = CategoryEnum.Security;
break; break;
case var _ when @event.Category.Contains("system", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("system", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.System; category = CategoryEnum.System;
break; break;
case var _ when @event.Category.Contains("printservice", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("printservice", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.Printer; category = CategoryEnum.Printer;
break; break;
case var _ when @event.Category.Contains("taskscheduler", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("taskscheduler", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.Task; category = CategoryEnum.Task;
break; break;
case var _ when @event.Category.Contains("terminalservices", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("terminalservices", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.RDP; category = CategoryEnum.RDP;
break; break;
case var _ when @event.Category.Contains("smbclient", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("smbclient", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.Network; category = CategoryEnum.Network;
break; break;
case var _ when @event.Category.Contains("smbserver", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("smbserver", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.Network; category = CategoryEnum.Network;
break; break;
case var _ when @event.Category.Contains("storagespaces", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("storagespaces", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.System; category = CategoryEnum.System;
break; break;
case var _ when @event.Category.Contains("diagnostics", StringComparison.InvariantCultureIgnoreCase): case var _ when @event.Category.Contains("diagnostics", StringComparison.InvariantCultureIgnoreCase):
category = CategoryEnum.System; category = CategoryEnum.System;
break; break;
default: default:
break; break;
}
} }
var date = DateTime.Now; var date = DateTime.Now;
@ -175,7 +171,7 @@ public class EventHandler : IMessageHandler<AgentSession>
EventId = @event.EventId.ToString(), EventId = @event.EventId.ToString(),
Status = status.ToString(), Status = status.ToString(),
Source = @event.Source, Source = @event.Source,
Category = category?.ToString(), Category = category.ToString(),
Message = @event.Message Message = @event.Message
}; };
@ -183,7 +179,7 @@ public class EventHandler : IMessageHandler<AgentSession>
return log; return log;
} }
private bool FilterEventId(Event @event) private static bool FilterEventId(Event @event)
{ {
var filter = new List<int> var filter = new List<int>
{ {
@ -234,10 +230,8 @@ public class EventHandler : IMessageHandler<AgentSession>
return false; return false;
} }
private bool FilterMonitoringHostLog(HostLogEntity hostLog) private static bool FilterMonitoringHostLog(HostLogEntity hostLog)
{ {
//_logger.LogDebug($"try filter event: {hostLog.Category}.{hostLog.Source}.{hostLog.Status}");
if (Enum.TryParse(hostLog.Status, out StatusType status) is false) return true; if (Enum.TryParse(hostLog.Status, out StatusType status) is false) return true;
if (hostLog.Category == CategoryEnum.System.ToString()) if (hostLog.Category == CategoryEnum.System.ToString())

View file

@ -7,14 +7,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class InterfaceHandler : IMessageHandler<AgentSession> public class InterfaceHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public InterfaceHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -39,7 +34,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
// interfaces // interfaces
if (interfaces is not null && interfaces.Any()) if (interfaces is not null && interfaces.Count != 0)
{ {
var interfaceBulk = new List<WriteModel<HostInterfaceEntity>>(); var interfaceBulk = new List<WriteModel<HostInterfaceEntity>>();
@ -95,7 +90,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
// addresses // addresses
if (interfaces is not null && interfaces.Any()) if (interfaces is not null && interfaces.Count != 0)
{ {
var addressBulk = new List<WriteModel<HostInterfaceAddressEntity>>(); var addressBulk = new List<WriteModel<HostInterfaceAddressEntity>>();
@ -104,9 +99,9 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
var interfaceId = await _database.HostInterface() var interfaceId = await _database.HostInterface()
.Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index) .Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index)
.Project(p => p.Id) .Project(p => p.Id)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync(cancellationToken: default);
if (@interface.Addresses is not null && @interface.Addresses.Any()) if (@interface.Addresses is not null && @interface.Addresses.Count != 0)
{ {
foreach (var address in @interface.Addresses) foreach (var address in @interface.Addresses)
{ {
@ -146,7 +141,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
// gateways // gateways
if (interfaces is not null && interfaces.Any()) if (interfaces is not null && interfaces.Count != 0)
{ {
var gatewayBulk = new List<WriteModel<HostInterfaceGatewayEntity>>(); var gatewayBulk = new List<WriteModel<HostInterfaceGatewayEntity>>();
@ -155,9 +150,9 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
var interfaceId = await _database.HostInterface() var interfaceId = await _database.HostInterface()
.Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index) .Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index)
.Project(p => p.Id) .Project(p => p.Id)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync(cancellationToken: default);
if (@interface.Gateways is not null && @interface.Gateways.Any()) if (@interface.Gateways is not null && @interface.Gateways.Count != 0)
{ {
foreach (var gateway in @interface.Gateways) foreach (var gateway in @interface.Gateways)
{ {
@ -195,7 +190,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
// nameservers // nameservers
if (interfaces is not null && interfaces.Any()) if (interfaces is not null && interfaces.Count != 0)
{ {
var nameserverBulk = new List<WriteModel<HostInterfaceNameserverEntity>>(); var nameserverBulk = new List<WriteModel<HostInterfaceNameserverEntity>>();
@ -204,9 +199,9 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
var interfaceId = await _database.HostInterface() var interfaceId = await _database.HostInterface()
.Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index) .Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index)
.Project(p => p.Id) .Project(p => p.Id)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync(cancellationToken: default);
if (@interface.Dns is not null && @interface.Dns.Any()) if (@interface.Dns is not null && @interface.Dns.Count != 0)
{ {
foreach (var nameserver in @interface.Dns) foreach (var nameserver in @interface.Dns)
{ {
@ -244,7 +239,7 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
// routes // routes
if (interfaces is not null && interfaces.Any()) if (interfaces is not null && interfaces.Count != 0)
{ {
var routeBulk = new List<WriteModel<HostInterfaceRouteEntity>>(); var routeBulk = new List<WriteModel<HostInterfaceRouteEntity>>();
@ -253,9 +248,9 @@ public class InterfaceHandler : IMessageHandler<AgentSession>
var interfaceId = await _database.HostInterface() var interfaceId = await _database.HostInterface()
.Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index) .Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index)
.Project(p => p.Id) .Project(p => p.Id)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync(cancellationToken: default);
if (@interface.Routes is not null && @interface.Routes.Any()) if (@interface.Routes is not null && @interface.Routes.Count != 0)
{ {
foreach (var route in @interface.Routes) foreach (var route in @interface.Routes)
{ {

View file

@ -6,14 +6,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers namespace Insight.Server.Network.Agent.Handlers
{ {
public class MainboardHandler : IMessageHandler<AgentSession> public class MainboardHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public MainboardHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {

View file

@ -7,14 +7,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class MemoryHandler : IMessageHandler<AgentSession> public class MemoryHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public MemoryHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -39,7 +34,7 @@ public class MemoryHandler : IMessageHandler<AgentSession>
var bulk = new List<WriteModel<HostMemoryEntity>>(); var bulk = new List<WriteModel<HostMemoryEntity>>();
if (memory is not null && memory.Any()) if (memory is not null && memory.Count != 0)
{ {
foreach (var mem in memory) foreach (var mem in memory)
{ {

View file

@ -6,14 +6,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class OperationSystemHandler : IMessageHandler<AgentSession> public class OperationSystemHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public OperationSystemHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {

View file

@ -7,14 +7,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class PrinterHandler : IMessageHandler<AgentSession> public class PrinterHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public PrinterHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -39,7 +34,7 @@ public class PrinterHandler : IMessageHandler<AgentSession>
var bulk = new List<WriteModel<HostPrinterEntity>>(); var bulk = new List<WriteModel<HostPrinterEntity>>();
if (printers is not null && printers.Any()) if (printers is not null && printers.Count != 0)
{ {
foreach (var printer in printers) foreach (var printer in printers)
{ {

View file

@ -7,14 +7,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class ProcessorHandler : IMessageHandler<AgentSession> public class ProcessorHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public ProcessorHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -39,7 +34,7 @@ public class ProcessorHandler : IMessageHandler<AgentSession>
var bulk = new List<WriteModel<HostProcessorEntity>>(); var bulk = new List<WriteModel<HostProcessorEntity>>();
if (processors is not null && processors.Any()) if (processors is not null && processors.Count != 0)
{ {
foreach (var processor in processors) foreach (var processor in processors)
{ {

View file

@ -7,14 +7,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class ServiceHandler : IMessageHandler<AgentSession> public class ServiceHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public ServiceHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -39,7 +34,7 @@ public class ServiceHandler : IMessageHandler<AgentSession>
var bulk = new List<WriteModel<HostServiceEntity>>(); var bulk = new List<WriteModel<HostServiceEntity>>();
if (services is not null && services.Any()) if (services is not null && services.Count != 0)
{ {
foreach (var service in services) foreach (var service in services)
{ {

View file

@ -7,14 +7,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class SessionHandler : IMessageHandler<AgentSession> public class SessionHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public SessionHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -39,7 +34,7 @@ public class SessionHandler : IMessageHandler<AgentSession>
var bulk = new List<WriteModel<HostSessionEntity>>(); var bulk = new List<WriteModel<HostSessionEntity>>();
if (sessions is not null && sessions.Any()) if (sessions is not null && sessions.Count != 0)
{ {
foreach (var sess in sessions) foreach (var sess in sessions)
{ {

View file

@ -7,14 +7,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class SoftwareHandler : IMessageHandler<AgentSession> public class SoftwareHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public SoftwareHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -39,7 +34,7 @@ public class SoftwareHandler : IMessageHandler<AgentSession>
var bulk = new List<WriteModel<HostApplicationEntity>>(); var bulk = new List<WriteModel<HostApplicationEntity>>();
if (applications is not null && applications.Any()) if (applications is not null && applications.Count != 0)
{ {
foreach (var app in applications) foreach (var app in applications)
{ {

View file

@ -7,14 +7,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class StoragePoolHandler : IMessageHandler<AgentSession> public class StoragePoolHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public StoragePoolHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -39,7 +34,7 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
// storagepools // storagepools
if (storagePools is not null && storagePools.Any()) if (storagePools is not null && storagePools.Count != 0)
{ {
var storagepoolBulk = new List<WriteModel<HostStoragePoolEntity>>(); var storagepoolBulk = new List<WriteModel<HostStoragePoolEntity>>();
@ -55,12 +50,10 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
if (storagePool.States is not null) if (storagePool.States is not null)
{ {
states = new List<string>(); states = [];
foreach (var state in storagePool.States) foreach (var state in storagePool.States)
{
states.Add(state.ToString()); states.Add(state.ToString());
}
} }
var storagePoolUpdate = Builders<HostStoragePoolEntity>.Update var storagePoolUpdate = Builders<HostStoragePoolEntity>.Update
@ -98,7 +91,7 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
// physicaldisks // physicaldisks
if (storagePools is not null && storagePools.Any()) if (storagePools is not null && storagePools.Count != 0)
{ {
var physicalDiskBulk = new List<WriteModel<HostStoragePoolPhysicalDiskEntity>>(); var physicalDiskBulk = new List<WriteModel<HostStoragePoolPhysicalDiskEntity>>();
@ -107,9 +100,9 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
var storagePoolId = await _database.HostStoragePool() var storagePoolId = await _database.HostStoragePool()
.Find(p => p.Host == hostEntity.Id && p.UniqueId == storagePool.UniqueId) .Find(p => p.Host == hostEntity.Id && p.UniqueId == storagePool.UniqueId)
.Project(p => p.Id) .Project(p => p.Id)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync(cancellationToken: default);
if (storagePool.PhysicalDisks is not null && storagePool.PhysicalDisks.Any()) if (storagePool.PhysicalDisks is not null && storagePool.PhysicalDisks.Count != 0)
{ {
foreach (var physicalDisk in storagePool.PhysicalDisks) foreach (var physicalDisk in storagePool.PhysicalDisks)
{ {
@ -124,12 +117,10 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
if (physicalDisk.States is not null) if (physicalDisk.States is not null)
{ {
states = new List<string>(); states = [];
foreach (var state in physicalDisk.States) foreach (var state in physicalDisk.States)
{
states.Add(state.ToString()); states.Add(state.ToString());
}
} }
var physicalDiskUpdate = Builders<HostStoragePoolPhysicalDiskEntity>.Update var physicalDiskUpdate = Builders<HostStoragePoolPhysicalDiskEntity>.Update
@ -177,20 +168,20 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
// virtual disks // virtual disks
if (storagePools is not null && storagePools.Any()) if (storagePools is not null && storagePools.Count != 0)
{ {
var virtualDiskBulk = new List<WriteModel<HostStoragePoolVirtualDiskEntity>>(); var virtualDiskBulk = new List<WriteModel<HostStoragePoolVirtualDiskEntity>>();
foreach (var storagePool in storagePools) foreach (var storagePool in storagePools)
{ {
if (storagePool.VirtualDisks is not null && storagePool.VirtualDisks.Any()) if (storagePool.VirtualDisks is not null && storagePool.VirtualDisks.Count != 0)
{ {
foreach (var virtualDisk in storagePool.VirtualDisks) foreach (var virtualDisk in storagePool.VirtualDisks)
{ {
var storagePoolId = await _database.HostStoragePool() var storagePoolId = await _database.HostStoragePool()
.Find(p => p.Host == hostEntity.Id && p.UniqueId == storagePool.UniqueId) .Find(p => p.Host == hostEntity.Id && p.UniqueId == storagePool.UniqueId)
.Project(p => p.Id) .Project(p => p.Id)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync(cancellationToken: default);
var virtualDiskFilter = Builders<HostStoragePoolVirtualDiskEntity>.Filter.And(new List<FilterDefinition<HostStoragePoolVirtualDiskEntity>> var virtualDiskFilter = Builders<HostStoragePoolVirtualDiskEntity>.Filter.And(new List<FilterDefinition<HostStoragePoolVirtualDiskEntity>>
{ {
@ -203,12 +194,10 @@ public class StoragePoolHandler : IMessageHandler<AgentSession>
if (virtualDisk.States is not null) if (virtualDisk.States is not null)
{ {
states = new List<string>(); states = [];
foreach (var state in virtualDisk.States) foreach (var state in virtualDisk.States)
{
states.Add(state.ToString()); states.Add(state.ToString());
}
} }
var virtualDiskUpdate = Builders<HostStoragePoolVirtualDiskEntity>.Update var virtualDiskUpdate = Builders<HostStoragePoolVirtualDiskEntity>.Update

View file

@ -6,14 +6,9 @@ using MongoDB.Driver;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class SystemInfoHandler : IMessageHandler<AgentSession> public class SystemInfoHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public SystemInfoHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -27,22 +22,24 @@ public class SystemInfoHandler : IMessageHandler<AgentSession>
private async ValueTask OnSystemInfoAsync(AgentSession session, SystemInfo? system, CancellationToken cancellationToken) private async ValueTask OnSystemInfoAsync(AgentSession session, SystemInfo? system, CancellationToken cancellationToken)
{ {
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session?.Id)).FirstOrDefaultAsync(cancellationToken);
if (agentEntity is null) return; if (agentEntity is null) return;
var hostEntity = await _database.Host().Find(Builders<HostEntity>.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); var hostEntity = await _database.Host().Find(Builders<HostEntity>.Filter.Eq(p => p.Agent, agentEntity?.Id)).FirstOrDefaultAsync(cancellationToken);
if (hostEntity is null) return; if (hostEntity is null) return;
var date = DateTime.Now; var date = DateTime.Now;
if (hostEntity.Id is null) return;
await _database.HostSystem().UpdateOneAsync(p => p.Host == hostEntity.Id, Builders<HostSystemEntity>.Update await _database.HostSystem().UpdateOneAsync(p => p.Host == hostEntity.Id, Builders<HostSystemEntity>.Update
.SetOnInsert(p => p.Insert, date) .SetOnInsert(p => p.Insert, date)
.SetOnInsert(p => p.Host, hostEntity.Id) .SetOnInsert(p => p.Host, hostEntity.Id)
.Set(p => p.Update, date) .Set(p => p.Update, date)
.Set(p => p.BootUpTime, system.LastBootUpTime) .Set(p => p.BootUpTime, system?.LastBootUpTime)
.Set(p => p.LocalTime, system.LocalDateTime) .Set(p => p.LocalTime, system?.LocalDateTime)
.Set(p => p.Processes, system.Processes) .Set(p => p.Processes, system?.Processes)
.Set(p => p.License, system.License), new UpdateOptions .Set(p => p.License, system?.License), new UpdateOptions
{ {
IsUpsert = true IsUpsert = true
}, cancellationToken); }, cancellationToken);

View file

@ -11,14 +11,9 @@ using static Insight.Server.Models.MonitorMessage;
namespace Insight.Server.Network.Agent.Handlers; namespace Insight.Server.Network.Agent.Handlers;
public class TrapHandler : IMessageHandler<AgentSession> public partial class TrapHandler(IMongoDatabase database) : IMessageHandler<AgentSession>
{ {
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database = database;
public TrapHandler(IMongoDatabase database)
{
_database = database;
}
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{ {
@ -85,7 +80,8 @@ public class TrapHandler : IMessageHandler<AgentSession>
{ {
monitoring = null; monitoring = null;
if (packet is null || packet.Data is null || packet.Data.Any() is false) return false; if (packet is null || packet.Data is null || packet.Data.Count == 0)
return false;
monitoring = new MonitorMessage monitoring = new MonitorMessage
{ {
@ -96,9 +92,7 @@ public class TrapHandler : IMessageHandler<AgentSession>
}; };
if (Enum.TryParse<ApplicationEnum>(packet.Community, true, out var application)) if (Enum.TryParse<ApplicationEnum>(packet.Community, true, out var application))
{
monitoring.Application = application; monitoring.Application = application;
}
StatusEnum? status; StatusEnum? status;
string? task; string? task;
@ -131,9 +125,12 @@ public class TrapHandler : IMessageHandler<AgentSession>
return true; return true;
} }
private static bool ParseAcronis(List<KeyValuePair<string, string>> data, out StatusEnum? status, out string? task, out string? message) [GeneratedRegex(@"\s+")]
private static partial Regex AcronisRegex();
private static bool ParseAcronis(List<KeyValuePair<string, string?>> data, out StatusEnum? status, out string? task, out string? message)
{ {
status = data[0].Value.ToLower() switch status = data[0].Value?.ToLower() switch
{ {
"erfolgreich" => StatusEnum.Information, "erfolgreich" => StatusEnum.Information,
"success" => StatusEnum.Information, "success" => StatusEnum.Information,
@ -149,49 +146,32 @@ public class TrapHandler : IMessageHandler<AgentSession>
task = null; task = null;
message = null; message = null;
var parsed = false; var trim = data[1].Value?.Split(':', StringSplitOptions.None);
if (trim is null || trim.Length == 0) return false;
try task = trim[1].Split("'", StringSplitOptions.None)[1].Split("'")[0].Trim();
{ message = trim[1].Split("' ", StringSplitOptions.None)[1].Trim();
var trim = data[1].Value.Split(new string[] { ":" }, StringSplitOptions.None); if (message is not null) return true;
task = trim[1].Split(new string[] { "'" }, StringSplitOptions.None)[1].Split("'")[0].Trim();
message = trim[1].Split(new string[] { "' " }, StringSplitOptions.None)[1].Trim();
parsed = true; if (data[1].Value is not string val) return false;
}
catch (Exception)
{
// skipped for base64 parse
}
if (parsed) return true; var content = AcronisRegex().Replace(val, "");
var bytes = Enumerable.Range(0, content.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(content.Substring(x, 2), 16))
.ToArray();
try content = Encoding.UTF8.GetString(bytes);
{
var content = Regex.Replace(data[1].Value, @"\s+", "");
var bytes = Enumerable.Range(0, content.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(content.Substring(x, 2), 16))
.ToArray();
content = Encoding.UTF8.GetString(bytes); trim = content.Split(':', StringSplitOptions.None);
if (trim is null || trim.Length == 0) return false;
var trim = content.Split(new string[] { ":" }, StringSplitOptions.None); task = trim[1].Split("'", StringSplitOptions.None)[1].Split("'")[0].Trim();
task = trim[1].Split(new string[] { "'" }, StringSplitOptions.None)[1].Split("'")[0].Trim(); message = trim[1].Split("' ", StringSplitOptions.None)[1].Trim();
message = trim[1].Split(new string[] { "' " }, StringSplitOptions.None)[1].Trim(); return message is not null;
parsed = true;
}
catch (Exception ex)
{
//_logger.LogError("{ex}", ex);
}
if (parsed) return true;
return false;
} }
private static bool ParseVeeam(List<KeyValuePair<string, string>> data, out StatusEnum? status, out string? task, out string? message) private static bool ParseVeeam(List<KeyValuePair<string, string?>> data, out StatusEnum? status, out string? task, out string? message)
{ {
status = null; status = null;
task = null; task = null;
@ -203,13 +183,13 @@ public class TrapHandler : IMessageHandler<AgentSession>
{ {
var summary = false; var summary = false;
if (Guid.TryParse(data[0].Value, out _)) if (Guid.TryParse(data[0].Value, out _))
summary = true; summary = true;
if (data[1].Value.ToLower() == "backup configuration job") if (data[1].Value?.ToLower() == "backup configuration job")
return false; return false;
status = (summary ? data[2].Value.ToLower() : data[3].Value.ToLower()) switch status = (summary ? data[2].Value?.ToLower() : data[3].Value?.ToLower()) switch
{ {
"success" => StatusEnum.Information, "success" => StatusEnum.Information,
"warning" => StatusEnum.Warning, "warning" => StatusEnum.Warning,
@ -230,7 +210,7 @@ public class TrapHandler : IMessageHandler<AgentSession>
return false; return false;
} }
private static bool ParseQnap(List<KeyValuePair<string, string>> data, out StatusEnum? status, out string? task, out string? message) private static bool ParseQnap(List<KeyValuePair<string, string?>> data, out StatusEnum? status, out string? task, out string? message)
{ {
status = StatusEnum.Information; status = StatusEnum.Information;
task = null; task = null;
@ -265,21 +245,15 @@ public class TrapHandler : IMessageHandler<AgentSession>
}; };
foreach (var key in keywords) foreach (var key in keywords)
{
if (Regex.IsMatch(string.Concat(data).ToLowerInvariant(), $@"\b{key.Key}\b")) if (Regex.IsMatch(string.Concat(data).ToLowerInvariant(), $@"\b{key.Key}\b"))
{
status = key.Value; status = key.Value;
}
}
foreach (var kv in data) foreach (var kv in data)
{
message += kv.Value; message += kv.Value;
}
parsed = true; parsed = true;
} }
catch (Exception ex) catch (Exception)
{ {
//_logger.LogError("{ex}", ex); //_logger.LogError("{ex}", ex);
} }

Some files were not shown because too many files have changed in this diff Show more