syntax updates
This commit is contained in:
parent
283fa1abc2
commit
1e05d4576d
75 changed files with 3821 additions and 3905 deletions
|
|
@ -1,8 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
namespace Insight.Agent
|
namespace Insight.Agent;
|
||||||
|
|
||||||
|
public static class Appsettings
|
||||||
{
|
{
|
||||||
public static class Appsettings
|
public const string Api = "api";
|
||||||
{
|
public const string ServerHost = "server.host";
|
||||||
public const string Api = "api";
|
public const string ServerPort = "server.port";
|
||||||
public const string ServerHost = "server.host";
|
public const string TrapPort = "trap.port";
|
||||||
public const string ServerPort = "server.port";
|
|
||||||
public const string TrapPort = "trap.port";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,21 +1,20 @@
|
||||||
namespace Insight.Agent.Constants
|
namespace Insight.Agent.Constants;
|
||||||
|
|
||||||
|
public static class Deploy
|
||||||
{
|
{
|
||||||
public static class Deploy
|
public static class Updater
|
||||||
{
|
{
|
||||||
public static class Updater
|
public const string Name = "Updater";
|
||||||
{
|
public const string ServiceName = "insight_updater";
|
||||||
public const string Name = "Updater";
|
public const string Description = "Insight Updater";
|
||||||
public const string ServiceName = "insight_updater";
|
|
||||||
public const string Description = "Insight Updater";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DirectoryInfo GetAppDirectory(string appName)
|
|
||||||
=> new($"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}/Webmatic/Insight/{appName}");
|
|
||||||
|
|
||||||
public static FileInfo GetAppExecutable(string appName)
|
|
||||||
=> new($"{GetAppDirectory(appName).FullName}/{appName.ToLower()}.exe");
|
|
||||||
|
|
||||||
public static Uri GetUpdateHref(Uri api, string appName)
|
|
||||||
=> new($"{api.AbsoluteUri}/update/{appName.ToLower()}/windows");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DirectoryInfo GetAppDirectory(string appName)
|
||||||
|
=> new($"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}/Webmatic/Insight/{appName}");
|
||||||
|
|
||||||
|
public static FileInfo GetAppExecutable(string appName)
|
||||||
|
=> new($"{GetAppDirectory(appName).FullName}/{appName.ToLower()}.exe");
|
||||||
|
|
||||||
|
public static Uri GetUpdateHref(Uri api, string appName)
|
||||||
|
=> new($"{api.AbsoluteUri}/update/{appName.ToLower()}/windows");
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace Insight.Agent.Extensions
|
namespace Insight.Agent.Extensions;
|
||||||
|
|
||||||
|
public static class ConfigurationExtensions
|
||||||
{
|
{
|
||||||
public static class ConfigurationExtensions
|
public static IConfigurationBuilder Defaults(this IConfigurationBuilder configuration)
|
||||||
{
|
{
|
||||||
public static IConfigurationBuilder Defaults(this IConfigurationBuilder configuration)
|
configuration.Sources.Clear();
|
||||||
{
|
configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
||||||
configuration.Sources.Clear();
|
return configuration.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
|
||||||
configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
|
||||||
return configuration.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,32 +1,31 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Insight.Agent.Extensions
|
namespace Insight.Agent.Extensions;
|
||||||
|
|
||||||
|
public static class Linux
|
||||||
{
|
{
|
||||||
public static class Linux
|
[SupportedOSPlatform("linux")]
|
||||||
|
public static string Bash(this string cmd)
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("linux")]
|
var escaped = cmd.Replace("\"", "\\\"");
|
||||||
public static string Bash(this string cmd)
|
|
||||||
|
using var proc = new Process()
|
||||||
{
|
{
|
||||||
var escaped = cmd.Replace("\"", "\\\"");
|
StartInfo = new ProcessStartInfo
|
||||||
|
|
||||||
using var proc = new Process()
|
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
FileName = "/bin/bash",
|
||||||
{
|
Arguments = $"-c \"{escaped}\"",
|
||||||
FileName = "/bin/bash",
|
RedirectStandardOutput = true,
|
||||||
Arguments = $"-c \"{escaped}\"",
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
CreateNoWindow = true,
|
||||||
UseShellExecute = false,
|
}
|
||||||
CreateNoWindow = true,
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
proc.Start();
|
proc.Start();
|
||||||
var result = proc.StandardOutput.ReadToEnd();
|
var result = proc.StandardOutput.ReadToEnd();
|
||||||
proc.WaitForExit();
|
proc.WaitForExit();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,69 +1,68 @@
|
||||||
using System.Management;
|
using System.Management;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Insight.Agent
|
namespace Insight.Agent;
|
||||||
|
|
||||||
|
public static class ManagmentExtensions
|
||||||
{
|
{
|
||||||
public static class ManagmentExtensions
|
[SupportedOSPlatform("windows")]
|
||||||
|
public static HashSet<string> GetPropertyHashes(this ManagementBaseObject @object)
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("windows")]
|
var properties = new HashSet<string>();
|
||||||
public static HashSet<string> GetPropertyHashes(this ManagementBaseObject @object)
|
|
||||||
|
foreach (var property in @object.Properties)
|
||||||
{
|
{
|
||||||
var properties = new HashSet<string>();
|
properties.Add(property.Name);
|
||||||
|
|
||||||
foreach (var property in @object.Properties)
|
|
||||||
{
|
|
||||||
properties.Add(property.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return properties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
return properties;
|
||||||
internal static bool TryGet(this ManagementObjectSearcher searcher, out ManagementObjectCollection collection)
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
internal static bool TryGet(this ManagementObjectSearcher searcher, out ManagementObjectCollection collection)
|
||||||
|
{
|
||||||
|
collection = searcher.Get();
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
collection = searcher.Get();
|
_ = collection.Count;
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_ = collection.Count;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (ManagementException)
|
|
||||||
{
|
|
||||||
collection.Dispose();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
|
||||||
internal static T? GetValue<T>(this ManagementObject @object, HashSet<string> properties, string key)
|
|
||||||
{
|
|
||||||
if (@object is null || properties is null || key is null) return default;
|
|
||||||
if (properties.Contains(key, StringComparer.OrdinalIgnoreCase) is false) return default;
|
|
||||||
|
|
||||||
if (@object[key] is not T obj)
|
|
||||||
{
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
|
||||||
internal static bool TryGetValue<T>(this ManagementBaseObject @object, HashSet<string> properties, string key, out T? value)
|
|
||||||
{
|
|
||||||
value = default;
|
|
||||||
|
|
||||||
if (@object is null || properties is null || key is null) return default;
|
|
||||||
if (properties.Contains(key, StringComparer.OrdinalIgnoreCase) is false) return false;
|
|
||||||
|
|
||||||
if (@object[key] is not T obj)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = obj;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (ManagementException)
|
||||||
|
{
|
||||||
|
collection.Dispose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
internal static T? GetValue<T>(this ManagementObject @object, HashSet<string> properties, string key)
|
||||||
|
{
|
||||||
|
if (@object is null || properties is null || key is null) return default;
|
||||||
|
if (properties.Contains(key, StringComparer.OrdinalIgnoreCase) is false) return default;
|
||||||
|
|
||||||
|
if (@object[key] is not T obj)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
internal static bool TryGetValue<T>(this ManagementBaseObject @object, HashSet<string> properties, string key, out T? value)
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
|
||||||
|
if (@object is null || properties is null || key is null) return default;
|
||||||
|
if (properties.Contains(key, StringComparer.OrdinalIgnoreCase) is false) return false;
|
||||||
|
|
||||||
|
if (@object[key] is not T obj)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = obj;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,43 +2,42 @@
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Insight.Agent
|
namespace Insight.Agent;
|
||||||
|
|
||||||
|
internal class Helpers
|
||||||
{
|
{
|
||||||
internal class Helpers
|
internal static string? EscapeWql(string text)
|
||||||
{
|
{
|
||||||
internal static string? EscapeWql(string text)
|
if (text == null) return null;
|
||||||
{
|
|
||||||
if (text == null) return null;
|
|
||||||
|
|
||||||
var sb = new StringBuilder(text.Length);
|
var sb = new StringBuilder(text.Length);
|
||||||
foreach (var c in text)
|
foreach (var c in text)
|
||||||
|
{
|
||||||
|
if (c == '\\' || c == '\'' || c == '"')
|
||||||
{
|
{
|
||||||
if (c == '\\' || c == '\'' || c == '"')
|
sb.Append('\\');
|
||||||
{
|
|
||||||
sb.Append('\\');
|
|
||||||
}
|
|
||||||
sb.Append(c);
|
|
||||||
}
|
}
|
||||||
return sb.ToString();
|
sb.Append(c);
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
internal static bool ForceWinRmStart()
|
||||||
|
{
|
||||||
|
var winRm = ServiceController
|
||||||
|
.GetServices()
|
||||||
|
.First(x => x.ServiceName
|
||||||
|
.ToLower()
|
||||||
|
.Equals("winrm", StringComparison.Ordinal));
|
||||||
|
|
||||||
|
if (winRm.Status is not ServiceControllerStatus.Running)
|
||||||
|
{
|
||||||
|
winRm.Start();
|
||||||
|
winRm.WaitForStatus(ServiceControllerStatus.Running);
|
||||||
}
|
}
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
if (winRm.Status != ServiceControllerStatus.Running) return false;
|
||||||
internal static bool ForceWinRmStart()
|
return true;
|
||||||
{
|
|
||||||
var winRm = ServiceController
|
|
||||||
.GetServices()
|
|
||||||
.First(x => x.ServiceName
|
|
||||||
.ToLower()
|
|
||||||
.Equals("winrm", StringComparison.Ordinal));
|
|
||||||
|
|
||||||
if (winRm.Status is not ServiceControllerStatus.Running)
|
|
||||||
{
|
|
||||||
winRm.Start();
|
|
||||||
winRm.WaitForStatus(ServiceControllerStatus.Running);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (winRm.Status != ServiceControllerStatus.Running) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
namespace Insight.Agent.Models
|
namespace Insight.Agent.Models;
|
||||||
|
|
||||||
|
public class Config
|
||||||
{
|
{
|
||||||
public class Config
|
public Guid? Serial { get; set; }
|
||||||
{
|
|
||||||
public Guid? Serial { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,16 +2,15 @@
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Insight.Agent.Services
|
namespace Insight.Agent.Services;
|
||||||
{
|
|
||||||
[SupportedOSPlatform("linux")]
|
|
||||||
public partial class CollectorService
|
|
||||||
{
|
|
||||||
public ILogger<CollectorService> Logger { get; }
|
|
||||||
|
|
||||||
public CollectorService(ILogger<CollectorService>? logger = null)
|
[SupportedOSPlatform("linux")]
|
||||||
{
|
public partial class CollectorService
|
||||||
Logger = logger ?? NullLogger<CollectorService>.Instance;
|
{
|
||||||
}
|
public ILogger<CollectorService> Logger { get; }
|
||||||
|
|
||||||
|
public CollectorService(ILogger<CollectorService>? logger = null)
|
||||||
|
{
|
||||||
|
Logger = logger ?? NullLogger<CollectorService>.Instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,97 +1,96 @@
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Insight.Agent.Services
|
namespace Insight.Agent.Services;
|
||||||
|
|
||||||
|
public static class Configurator
|
||||||
{
|
{
|
||||||
public static class Configurator
|
public static async ValueTask<TConfig> ReadAsync<TConfig>(string file, CancellationToken cancellationToken = default)
|
||||||
|
where TConfig : class
|
||||||
{
|
{
|
||||||
public static async ValueTask<TConfig> ReadAsync<TConfig>(string file, CancellationToken cancellationToken = default)
|
var json = await File.ReadAllTextAsync(file, cancellationToken);
|
||||||
where TConfig : class
|
|
||||||
|
if (JsonSerializer.Deserialize<TConfig>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, WriteIndented = true }) is not TConfig config)
|
||||||
{
|
{
|
||||||
var json = await File.ReadAllTextAsync(file, cancellationToken);
|
throw new InvalidDataException($"Failed to deserialize ({file})");
|
||||||
|
|
||||||
if (JsonSerializer.Deserialize<TConfig>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, WriteIndented = true }) is not TConfig config)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException($"Failed to deserialize ({file})");
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
public static async ValueTask<JsonDocument> ReadJsonAsync(string file, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var json = await File.ReadAllTextAsync(file, cancellationToken);
|
|
||||||
|
|
||||||
if (JsonDocument.Parse(json) is not JsonDocument doc)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException($"Failed to deserialize ({file})");
|
|
||||||
}
|
|
||||||
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
public static async ValueTask<IDictionary<string, object>> ReadDictionaryAsync(string file, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException($"Failed to deserialize ({file})");
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async ValueTask WriteAsync<TConfig>(TConfig config, string file, CancellationToken cancellationToken) where TConfig : class
|
return config;
|
||||||
|
}
|
||||||
|
public static async ValueTask<JsonDocument> ReadJsonAsync(string file, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var json = await File.ReadAllTextAsync(file, cancellationToken);
|
||||||
|
|
||||||
|
if (JsonDocument.Parse(json) is not JsonDocument doc)
|
||||||
{
|
{
|
||||||
await WriteToFileAsync(config, file, cancellationToken);
|
throw new InvalidDataException($"Failed to deserialize ({file})");
|
||||||
}
|
|
||||||
public static async ValueTask WriteAsync(JsonDocument config, string file, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await WriteToFileAsync(config, file, cancellationToken);
|
|
||||||
}
|
|
||||||
public static async ValueTask WriteAsync(IDictionary<string, object?> config, string file, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await WriteToFileAsync(config, file, cancellationToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async ValueTask AddOrUpdateAsync(KeyValuePair<string, object> data, string file, CancellationToken cancellationToken)
|
return doc;
|
||||||
|
}
|
||||||
|
public static async ValueTask<IDictionary<string, object>> ReadDictionaryAsync(string file, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
var readData = await ReadDictionaryAsync(file, cancellationToken);
|
throw new InvalidDataException($"Failed to deserialize ({file})");
|
||||||
|
|
||||||
var key = readData.Keys.FirstOrDefault(dic => string.Compare(dic, data.Key, StringComparison.OrdinalIgnoreCase) == 0);
|
|
||||||
|
|
||||||
if (key is null)
|
|
||||||
{
|
|
||||||
readData.Add(data.Key, data.Value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
readData[key] = data.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
await WriteToFileAsync(readData, file, cancellationToken);
|
|
||||||
}
|
|
||||||
public static async ValueTask RemoveAsync(string data, string file, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var readData = await ReadDictionaryAsync(file, cancellationToken);
|
|
||||||
|
|
||||||
var key = readData.Keys.FirstOrDefault(dic => string.Compare(dic, data, StringComparison.OrdinalIgnoreCase) == 0);
|
|
||||||
|
|
||||||
if (key is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
readData.Remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
await WriteToFileAsync(readData, file, cancellationToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async ValueTask WriteToFileAsync<TData>(TData data, string file, CancellationToken cancellationToken)
|
return config;
|
||||||
{
|
}
|
||||||
var json = JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });
|
|
||||||
|
|
||||||
await File.WriteAllTextAsync(file, json, cancellationToken);
|
public static async ValueTask WriteAsync<TConfig>(TConfig config, string file, CancellationToken cancellationToken) where TConfig : class
|
||||||
|
{
|
||||||
|
await WriteToFileAsync(config, file, cancellationToken);
|
||||||
|
}
|
||||||
|
public static async ValueTask WriteAsync(JsonDocument config, string file, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await WriteToFileAsync(config, file, cancellationToken);
|
||||||
|
}
|
||||||
|
public static async ValueTask WriteAsync(IDictionary<string, object?> config, string file, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await WriteToFileAsync(config, file, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async ValueTask AddOrUpdateAsync(KeyValuePair<string, object> data, string file, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var readData = await ReadDictionaryAsync(file, cancellationToken);
|
||||||
|
|
||||||
|
var key = readData.Keys.FirstOrDefault(dic => string.Compare(dic, data.Key, StringComparison.OrdinalIgnoreCase) == 0);
|
||||||
|
|
||||||
|
if (key is null)
|
||||||
|
{
|
||||||
|
readData.Add(data.Key, data.Value);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
readData[key] = data.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
await WriteToFileAsync(readData, file, cancellationToken);
|
||||||
|
}
|
||||||
|
public static async ValueTask RemoveAsync(string data, string file, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var readData = await ReadDictionaryAsync(file, cancellationToken);
|
||||||
|
|
||||||
|
var key = readData.Keys.FirstOrDefault(dic => string.Compare(dic, data, StringComparison.OrdinalIgnoreCase) == 0);
|
||||||
|
|
||||||
|
if (key is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
readData.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
await WriteToFileAsync(readData, file, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async ValueTask WriteToFileAsync<TData>(TData data, string file, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var json = JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });
|
||||||
|
|
||||||
|
await File.WriteAllTextAsync(file, json, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Insight.Domain.Constants;
|
using Insight.Domain.Constants;
|
||||||
|
|
||||||
namespace Insight.Api
|
namespace Insight.Api;
|
||||||
|
|
||||||
|
public static class Locations
|
||||||
{
|
{
|
||||||
public static class Locations
|
public static DirectoryInfo UpdatesPath { get; } = new DirectoryInfo($"{Configuration.AppDirectory?.FullName}/files/updates");
|
||||||
{
|
|
||||||
public static DirectoryInfo UpdatesPath { get; } = new DirectoryInfo($"{Configuration.AppDirectory?.FullName}/files/updates");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,73 +4,72 @@ using Insight.Infrastructure.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Insight.Api.Controllers
|
namespace Insight.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController, Route("api/accounts")]
|
||||||
|
public class AccountController : ControllerBase
|
||||||
{
|
{
|
||||||
[ApiController, Route("api/accounts")]
|
private readonly IdentityService _identityService;
|
||||||
public class AccountController : ControllerBase
|
private readonly AccountService _accountService;
|
||||||
|
private readonly ILogger<AccountController> _logger;
|
||||||
|
|
||||||
|
public AccountController(IdentityService identityService, AccountService accountService, ILogger<AccountController> logger)
|
||||||
{
|
{
|
||||||
private readonly IdentityService _identityService;
|
_identityService = identityService;
|
||||||
private readonly AccountService _accountService;
|
_accountService = accountService;
|
||||||
private readonly ILogger<AccountController> _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public AccountController(IdentityService identityService, AccountService accountService, ILogger<AccountController> logger)
|
[HttpGet, Authorize]
|
||||||
|
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_identityService = identityService;
|
var result = await _accountService.GetAsync(
|
||||||
_accountService = accountService;
|
offset: request.Offset,
|
||||||
_logger = logger;
|
limit: request.Limit,
|
||||||
|
request: Request,
|
||||||
|
response: Response,
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
[HttpGet, Authorize]
|
|
||||||
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
try
|
return Unauthorized(ex.ToString());
|
||||||
{
|
|
||||||
var result = await _accountService.GetAsync(
|
|
||||||
offset: request.Offset,
|
|
||||||
limit: request.Limit,
|
|
||||||
request: Request,
|
|
||||||
response: Response,
|
|
||||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException ex)
|
|
||||||
{
|
|
||||||
return Unauthorized(ex.ToString());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
[HttpPost("register"), Authorize]
|
|
||||||
public async Task<ActionResult> Register([FromBody] RegistrationModel model)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(model.Email)) return BadRequest("Email Required");
|
return BadRequest(ex.Message);
|
||||||
if (string.IsNullOrWhiteSpace(model.Password)) return BadRequest("Password Required");
|
|
||||||
if (string.IsNullOrWhiteSpace(model.ConfirmPassword)) return BadRequest("Password Confirmation Required");
|
|
||||||
|
|
||||||
if (model.Password != model.ConfirmPassword) return BadRequest("Passwords do not match");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = await _identityService.CreateUserAsync(model.Email, model.Password).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (result.Succeeded is false) return BadRequest(result.Errors);
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException ex)
|
|
||||||
{
|
|
||||||
return Unauthorized(ex.Message);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
//await _userManager.AddToRoleAsync(user, "Visitor");
|
|
||||||
|
|
||||||
return Ok(model.Email);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("register"), Authorize]
|
||||||
|
public async Task<ActionResult> Register([FromBody] RegistrationModel model)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(model.Email)) return BadRequest("Email Required");
|
||||||
|
if (string.IsNullOrWhiteSpace(model.Password)) return BadRequest("Password Required");
|
||||||
|
if (string.IsNullOrWhiteSpace(model.ConfirmPassword)) return BadRequest("Password Confirmation Required");
|
||||||
|
|
||||||
|
if (model.Password != model.ConfirmPassword) return BadRequest("Passwords do not match");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _identityService.CreateUserAsync(model.Email, model.Password).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (result.Succeeded is false) return BadRequest(result.Errors);
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
|
{
|
||||||
|
return Unauthorized(ex.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
//await _userManager.AddToRoleAsync(user, "Visitor");
|
||||||
|
|
||||||
|
return Ok(model.Email);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,42 +3,41 @@ using Insight.Infrastructure.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Insight.Api.Controllers
|
namespace Insight.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController, Route("api/agents")]
|
||||||
|
public class AgentController : ControllerBase
|
||||||
{
|
{
|
||||||
[ApiController, Route("api/agents")]
|
private readonly AgentService _agentService;
|
||||||
public class AgentController : ControllerBase
|
private readonly ILogger<AgentController> _logger;
|
||||||
|
|
||||||
|
public AgentController(AgentService agentService, ILogger<AgentController> logger)
|
||||||
{
|
{
|
||||||
private readonly AgentService _agentService;
|
_agentService = agentService;
|
||||||
private readonly ILogger<AgentController> _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public AgentController(AgentService agentService, ILogger<AgentController> logger)
|
[HttpGet, Authorize]
|
||||||
|
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_agentService = agentService;
|
var result = await _agentService.GetAsync(
|
||||||
_logger = logger;
|
offset: request.Offset,
|
||||||
|
limit: request.Limit,
|
||||||
|
request: Request,
|
||||||
|
response: Response,
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
[HttpGet, Authorize]
|
|
||||||
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
try
|
return Unauthorized(ex.ToString());
|
||||||
{
|
}
|
||||||
var result = await _agentService.GetAsync(
|
catch (Exception ex)
|
||||||
offset: request.Offset,
|
{
|
||||||
limit: request.Limit,
|
return BadRequest(ex.Message);
|
||||||
request: Request,
|
|
||||||
response: Response,
|
|
||||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException ex)
|
|
||||||
{
|
|
||||||
return Unauthorized(ex.ToString());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,42 +3,41 @@ using Insight.Infrastructure.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Insight.Api.Controllers
|
namespace Insight.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController, Route("api/customers")]
|
||||||
|
public class CustomerController : ControllerBase
|
||||||
{
|
{
|
||||||
[ApiController, Route("api/customers")]
|
private readonly CustomerService _customerService;
|
||||||
public class CustomerController : ControllerBase
|
private readonly ILogger<CustomerController> _logger;
|
||||||
|
|
||||||
|
public CustomerController(CustomerService customerService, ILogger<CustomerController> logger)
|
||||||
{
|
{
|
||||||
private readonly CustomerService _customerService;
|
_customerService = customerService;
|
||||||
private readonly ILogger<CustomerController> _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public CustomerController(CustomerService customerService, ILogger<CustomerController> logger)
|
[HttpGet, Authorize]
|
||||||
|
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_customerService = customerService;
|
var result = await _customerService.GetAsync(
|
||||||
_logger = logger;
|
offset: request.Offset,
|
||||||
|
limit: request.Limit,
|
||||||
|
request: Request,
|
||||||
|
response: Response,
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
[HttpGet, Authorize]
|
|
||||||
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
try
|
return Unauthorized(ex.ToString());
|
||||||
{
|
}
|
||||||
var result = await _customerService.GetAsync(
|
catch (Exception ex)
|
||||||
offset: request.Offset,
|
{
|
||||||
limit: request.Limit,
|
return BadRequest(ex.Message);
|
||||||
request: Request,
|
|
||||||
response: Response,
|
|
||||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException ex)
|
|
||||||
{
|
|
||||||
return Unauthorized(ex.ToString());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,42 +3,41 @@ using Insight.Infrastructure.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Insight.Api.Controllers
|
namespace Insight.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController, Route("api/hosts")]
|
||||||
|
public class HostController : ControllerBase
|
||||||
{
|
{
|
||||||
[ApiController, Route("api/hosts")]
|
private readonly HostService _hostService;
|
||||||
public class HostController : ControllerBase
|
private readonly ILogger<HostController> _logger;
|
||||||
|
|
||||||
|
public HostController(HostService hostService, ILogger<HostController> logger)
|
||||||
{
|
{
|
||||||
private readonly HostService _hostService;
|
_hostService = hostService;
|
||||||
private readonly ILogger<HostController> _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public HostController(HostService hostService, ILogger<HostController> logger)
|
[HttpGet, Authorize]
|
||||||
|
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_hostService = hostService;
|
var result = await _hostService.GetAsync(
|
||||||
_logger = logger;
|
offset: request.Offset,
|
||||||
|
limit: request.Limit,
|
||||||
|
request: Request,
|
||||||
|
response: Response,
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
[HttpGet, Authorize]
|
|
||||||
public async Task<IActionResult> Get([FromQuery] PagedDataRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
try
|
return Unauthorized(ex.ToString());
|
||||||
{
|
}
|
||||||
var result = await _hostService.GetAsync(
|
catch (Exception ex)
|
||||||
offset: request.Offset,
|
{
|
||||||
limit: request.Limit,
|
return BadRequest(ex.Message);
|
||||||
request: Request,
|
|
||||||
response: Response,
|
|
||||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException ex)
|
|
||||||
{
|
|
||||||
return Unauthorized(ex.ToString());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,66 +8,65 @@ using MongoDB.Driver;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Insight.Api.Controllers
|
namespace Insight.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController, Route("api/inventory")]
|
||||||
|
public class InventoryController : ControllerBase
|
||||||
{
|
{
|
||||||
[ApiController, Route("api/inventory")]
|
private readonly InventoryService _inventoryService;
|
||||||
public class InventoryController : ControllerBase
|
private readonly ILogger<InventoryController> _logger;
|
||||||
|
|
||||||
|
public InventoryController(InventoryService inventoryService, ILogger<InventoryController> logger)
|
||||||
{
|
{
|
||||||
private readonly InventoryService _inventoryService;
|
_inventoryService = inventoryService;
|
||||||
private readonly ILogger<InventoryController> _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public InventoryController(InventoryService inventoryService, ILogger<InventoryController> logger)
|
[HttpGet, Authorize]
|
||||||
|
public async Task<IActionResult> Get([FromQuery] HostApplicationEntity request, [FromQuery] PagedDataRequest meta, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_inventoryService = inventoryService;
|
var filter = Builders<HostApplicationEntity>.Filter.Empty;
|
||||||
_logger = logger;
|
|
||||||
|
if (request.Id is not null)
|
||||||
|
filter &= Builders<HostApplicationEntity>.Filter.Eq(p => p.Id, request.Id);
|
||||||
|
|
||||||
|
if (request.Host is not null)
|
||||||
|
filter &= Builders<HostApplicationEntity>.Filter.Eq(p => p.Host, request.Host);
|
||||||
|
|
||||||
|
if (request.Name is not null)
|
||||||
|
filter &= Builders<HostApplicationEntity>.Filter.Regex(p => p.Name, new BsonRegularExpression(new Regex(request.Name, RegexOptions.IgnoreCase)));
|
||||||
|
|
||||||
|
var result = await _inventoryService.GetAsync(
|
||||||
|
filter: filter,
|
||||||
|
offset: meta.Offset,
|
||||||
|
limit: meta.Limit,
|
||||||
|
request: Request,
|
||||||
|
response: Response,
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
[HttpGet, Authorize]
|
|
||||||
public async Task<IActionResult> Get([FromQuery] HostApplicationEntity request, [FromQuery] PagedDataRequest meta, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
try
|
return Unauthorized(ex.ToString());
|
||||||
{
|
|
||||||
var filter = Builders<HostApplicationEntity>.Filter.Empty;
|
|
||||||
|
|
||||||
if (request.Id is not null)
|
|
||||||
filter &= Builders<HostApplicationEntity>.Filter.Eq(p => p.Id, request.Id);
|
|
||||||
|
|
||||||
if (request.Host is not null)
|
|
||||||
filter &= Builders<HostApplicationEntity>.Filter.Eq(p => p.Host, request.Host);
|
|
||||||
|
|
||||||
if (request.Name is not null)
|
|
||||||
filter &= Builders<HostApplicationEntity>.Filter.Regex(p => p.Name, new BsonRegularExpression(new Regex(request.Name, RegexOptions.IgnoreCase)));
|
|
||||||
|
|
||||||
var result = await _inventoryService.GetAsync(
|
|
||||||
filter: filter,
|
|
||||||
offset: meta.Offset,
|
|
||||||
limit: meta.Limit,
|
|
||||||
request: Request,
|
|
||||||
response: Response,
|
|
||||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException ex)
|
|
||||||
{
|
|
||||||
return Unauthorized(ex.ToString());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
public class ApplicationRequest
|
|
||||||
{
|
{
|
||||||
[JsonPropertyName("id")]
|
return BadRequest(ex.Message);
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("host")]
|
|
||||||
public string? Host { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
public string? Name { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ApplicationRequest
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("host")]
|
||||||
|
public string? Host { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string? Name { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,30 +1,29 @@
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Insight.Server.Controllers
|
namespace Insight.Server.Controllers;
|
||||||
|
|
||||||
|
[ApiController, Route("api/setup")]
|
||||||
|
public class SetupController : ControllerBase
|
||||||
{
|
{
|
||||||
[ApiController, Route("api/setup")]
|
private readonly ILogger<SetupController> _logger;
|
||||||
public class SetupController : ControllerBase
|
|
||||||
|
public SetupController(ILogger<SetupController> logger)
|
||||||
{
|
{
|
||||||
private readonly ILogger<SetupController> _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public SetupController(ILogger<SetupController> logger)
|
[HttpGet("windows")]
|
||||||
|
public async Task<IActionResult> GetAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("[{method}] {route} => {ep}", Request.Method, Request.HttpContext.Request.Path, Request.HttpContext.Connection.RemoteIpAddress);
|
||||||
|
|
||||||
|
var files = new DirectoryInfo($"{Domain.Constants.Configuration.AppDirectory?.FullName}/files/setup").GetFiles();
|
||||||
|
|
||||||
|
if (files.Length == 0)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("windows")]
|
return File(await System.IO.File.ReadAllBytesAsync(files.OrderBy(p => p.LastWriteTime).First().FullName, cancellationToken), "application/zip", "setup-win64.zip");
|
||||||
public async Task<IActionResult> GetAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("[{method}] {route} => {ep}", Request.Method, Request.HttpContext.Request.Path, Request.HttpContext.Connection.RemoteIpAddress);
|
|
||||||
|
|
||||||
var files = new DirectoryInfo($"{Domain.Constants.Configuration.AppDirectory?.FullName}/files/setup").GetFiles();
|
|
||||||
|
|
||||||
if (files.Length == 0)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
return File(await System.IO.File.ReadAllBytesAsync(files.OrderBy(p => p.LastWriteTime).First().FullName, cancellationToken), "application/zip", "setup-win64.zip");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,83 +3,82 @@ using Insight.Infrastructure.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Insight.Api.Controllers
|
namespace Insight.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController, Route("api/token", Order = 0)]
|
||||||
|
public class TokenController : ControllerBase
|
||||||
{
|
{
|
||||||
[ApiController, Route("api/token", Order = 0)]
|
private readonly TokenService _tokenService;
|
||||||
public class TokenController : ControllerBase
|
|
||||||
|
public TokenController(TokenService tokenService)
|
||||||
{
|
{
|
||||||
private readonly TokenService _tokenService;
|
_tokenService = tokenService;
|
||||||
|
}
|
||||||
|
|
||||||
public TokenController(TokenService tokenService)
|
/// <remarks>
|
||||||
|
/// Access Token Request
|
||||||
|
/// </remarks>
|
||||||
|
[HttpPost, AllowAnonymous]
|
||||||
|
public async Task<IActionResult> Authentication([FromBody] TokenRequest request)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_tokenService = tokenService;
|
var result = await _tokenService.GetAsync(request.Username, request.Password, request.Code, HttpContext.Connection.RemoteIpAddress).ConfigureAwait(false);
|
||||||
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
/// <remarks>
|
|
||||||
/// Access Token Request
|
|
||||||
/// </remarks>
|
|
||||||
[HttpPost, AllowAnonymous]
|
|
||||||
public async Task<IActionResult> Authentication([FromBody] TokenRequest request)
|
|
||||||
{
|
{
|
||||||
try
|
return Unauthorized(ex.Message);
|
||||||
{
|
|
||||||
var result = await _tokenService.GetAsync(request.Username, request.Password, request.Code, HttpContext.Connection.RemoteIpAddress).ConfigureAwait(false);
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException ex)
|
|
||||||
{
|
|
||||||
return Unauthorized(ex.Message);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
/// <remarks>
|
|
||||||
/// Refresh Token Request
|
|
||||||
/// </remarks>
|
|
||||||
[HttpPost("refresh"), AllowAnonymous]
|
|
||||||
public async Task<IActionResult> Refresh([FromBody] TokenRefreshRequest request)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(request.Token)) return BadRequest("Refresh Token Required");
|
return BadRequest(ex.Message);
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = await _tokenService.RefreshAsync(request.Token, HttpContext.Connection.RemoteIpAddress).ConfigureAwait(false);
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException ex)
|
|
||||||
{
|
|
||||||
return Unauthorized(ex.Message);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Revoke Token Request
|
/// Refresh Token Request
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[HttpPost("revoke"), AllowAnonymous]
|
[HttpPost("refresh"), AllowAnonymous]
|
||||||
public async Task<IActionResult> Revoke([FromBody] TokenRevokeRequest request)
|
public async Task<IActionResult> Refresh([FromBody] TokenRefreshRequest request)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Token)) return BadRequest("Refresh Token Required");
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(request.Token)) return BadRequest("Refresh Token Required");
|
var result = await _tokenService.RefreshAsync(request.Token, HttpContext.Connection.RemoteIpAddress).ConfigureAwait(false);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
|
{
|
||||||
|
return Unauthorized(ex.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try
|
/// <remarks>
|
||||||
{
|
/// Revoke Token Request
|
||||||
await _tokenService.RevokeAsync(request.Token, request.Reason ?? "revoked by user", HttpContext.Connection.RemoteIpAddress).ConfigureAwait(false);
|
/// </remarks>
|
||||||
return Ok();
|
[HttpPost("revoke"), AllowAnonymous]
|
||||||
}
|
public async Task<IActionResult> Revoke([FromBody] TokenRevokeRequest request)
|
||||||
catch (UnauthorizedAccessException ex)
|
{
|
||||||
{
|
if (string.IsNullOrWhiteSpace(request.Token)) return BadRequest("Refresh Token Required");
|
||||||
return Unauthorized(ex.Message);
|
|
||||||
}
|
try
|
||||||
catch (Exception ex)
|
{
|
||||||
{
|
await _tokenService.RevokeAsync(request.Token, request.Reason ?? "revoked by user", HttpContext.Connection.RemoteIpAddress).ConfigureAwait(false);
|
||||||
return BadRequest(ex.Message);
|
return Ok();
|
||||||
}
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
|
{
|
||||||
|
return Unauthorized(ex.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,92 +2,91 @@
|
||||||
using Insight.Domain.Models;
|
using Insight.Domain.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Insight.Server.Controllers
|
namespace Insight.Server.Controllers;
|
||||||
|
|
||||||
|
[ApiController, Route("api/update")]
|
||||||
|
public class UpdateController : ControllerBase
|
||||||
{
|
{
|
||||||
[ApiController, Route("api/update")]
|
private readonly ILogger<UpdateController> _logger;
|
||||||
public class UpdateController : ControllerBase
|
|
||||||
|
public UpdateController(ILogger<UpdateController> logger)
|
||||||
{
|
{
|
||||||
private readonly ILogger<UpdateController> _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public UpdateController(ILogger<UpdateController> logger)
|
[HttpGet("updater/windows")]
|
||||||
|
public IActionResult UpdaterWindows()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("[{method}] {route} => {ep}", Request.Method, Request.HttpContext.Request.Path, Request.HttpContext.Connection.RemoteIpAddress);
|
||||||
|
|
||||||
|
var updateDir = new DirectoryInfo($"{Locations.UpdatesPath}/updater/windows");
|
||||||
|
|
||||||
|
if (updateDir.Exists is false)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("updater/windows")]
|
var updateLock = new FileInfo($"{updateDir.FullName}/.lock");
|
||||||
public IActionResult UpdaterWindows()
|
|
||||||
|
if (updateLock.Exists)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("[{method}] {route} => {ep}", Request.Method, Request.HttpContext.Request.Path, Request.HttpContext.Connection.RemoteIpAddress);
|
return NotFound("locked");
|
||||||
|
|
||||||
var updateDir = new DirectoryInfo($"{Locations.UpdatesPath}/updater/windows");
|
|
||||||
|
|
||||||
if (updateDir.Exists is false)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var updateLock = new FileInfo($"{updateDir.FullName}/.lock");
|
|
||||||
|
|
||||||
if (updateLock.Exists)
|
|
||||||
{
|
|
||||||
return NotFound("locked");
|
|
||||||
}
|
|
||||||
|
|
||||||
var versions = updateDir.GetFiles("*.zip", SearchOption.TopDirectoryOnly);
|
|
||||||
|
|
||||||
if (versions is null || versions.Any() is false) return NotFound();
|
|
||||||
|
|
||||||
var latest = versions.OrderBy(x => x.Name).FirstOrDefault();
|
|
||||||
|
|
||||||
if (latest is null) return NotFound();
|
|
||||||
|
|
||||||
var relPath = $"{Path.GetRelativePath($"{Domain.Constants.Configuration.AppDirectory?.FullName}", latest.FullName)}";
|
|
||||||
|
|
||||||
if (Version.TryParse(Path.GetFileNameWithoutExtension(latest.Name), out var fileversion) is false) return NotFound();
|
|
||||||
|
|
||||||
return Ok(new UpdateResponse
|
|
||||||
{
|
|
||||||
Version = fileversion,
|
|
||||||
Uri = new Uri($"{Request.Scheme}://{Request.Host}/api/{relPath}")
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("agent/windows")]
|
var versions = updateDir.GetFiles("*.zip", SearchOption.TopDirectoryOnly);
|
||||||
public IActionResult AgentWindows()
|
|
||||||
|
if (versions is null || versions.Any() is false) return NotFound();
|
||||||
|
|
||||||
|
var latest = versions.OrderBy(x => x.Name).FirstOrDefault();
|
||||||
|
|
||||||
|
if (latest is null) return NotFound();
|
||||||
|
|
||||||
|
var relPath = $"{Path.GetRelativePath($"{Domain.Constants.Configuration.AppDirectory?.FullName}", latest.FullName)}";
|
||||||
|
|
||||||
|
if (Version.TryParse(Path.GetFileNameWithoutExtension(latest.Name), out var fileversion) is false) return NotFound();
|
||||||
|
|
||||||
|
return Ok(new UpdateResponse
|
||||||
{
|
{
|
||||||
_logger.LogInformation("[{method}] {route} => {ep}", Request.Method, Request.HttpContext.Request.Path, Request.HttpContext.Connection.RemoteIpAddress);
|
Version = fileversion,
|
||||||
|
Uri = new Uri($"{Request.Scheme}://{Request.Host}/api/{relPath}")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var updateDir = new DirectoryInfo($"{Locations.UpdatesPath}/agent/windows");
|
[HttpGet("agent/windows")]
|
||||||
|
public IActionResult AgentWindows()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("[{method}] {route} => {ep}", Request.Method, Request.HttpContext.Request.Path, Request.HttpContext.Connection.RemoteIpAddress);
|
||||||
|
|
||||||
if (updateDir.Exists is false)
|
var updateDir = new DirectoryInfo($"{Locations.UpdatesPath}/agent/windows");
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var updateLock = new FileInfo($"{updateDir.FullName}/.lock");
|
if (updateDir.Exists is false)
|
||||||
|
{
|
||||||
if (updateLock.Exists)
|
return NotFound();
|
||||||
{
|
|
||||||
return NotFound("locked");
|
|
||||||
}
|
|
||||||
|
|
||||||
var versions = updateDir.GetFiles("*.zip", SearchOption.TopDirectoryOnly);
|
|
||||||
|
|
||||||
if (versions is null || versions.Any() is false) return NotFound();
|
|
||||||
|
|
||||||
var latest = versions.OrderBy(x => x.Name).FirstOrDefault();
|
|
||||||
|
|
||||||
if (latest is null) return NotFound();
|
|
||||||
|
|
||||||
var relPath = $"{Path.GetRelativePath($"{Domain.Constants.Configuration.AppDirectory?.FullName}", latest.FullName)}";
|
|
||||||
|
|
||||||
if (Version.TryParse(Path.GetFileNameWithoutExtension(latest.Name), out var fileversion) is false) return NotFound();
|
|
||||||
|
|
||||||
return Ok(new UpdateResponse
|
|
||||||
{
|
|
||||||
Version = fileversion,
|
|
||||||
Uri = new Uri($"{Request.Scheme}://{Request.Host}/api/{relPath}")
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var updateLock = new FileInfo($"{updateDir.FullName}/.lock");
|
||||||
|
|
||||||
|
if (updateLock.Exists)
|
||||||
|
{
|
||||||
|
return NotFound("locked");
|
||||||
|
}
|
||||||
|
|
||||||
|
var versions = updateDir.GetFiles("*.zip", SearchOption.TopDirectoryOnly);
|
||||||
|
|
||||||
|
if (versions is null || versions.Any() is false) return NotFound();
|
||||||
|
|
||||||
|
var latest = versions.OrderBy(x => x.Name).FirstOrDefault();
|
||||||
|
|
||||||
|
if (latest is null) return NotFound();
|
||||||
|
|
||||||
|
var relPath = $"{Path.GetRelativePath($"{Domain.Constants.Configuration.AppDirectory?.FullName}", latest.FullName)}";
|
||||||
|
|
||||||
|
if (Version.TryParse(Path.GetFileNameWithoutExtension(latest.Name), out var fileversion) is false) return NotFound();
|
||||||
|
|
||||||
|
return Ok(new UpdateResponse
|
||||||
|
{
|
||||||
|
Version = fileversion,
|
||||||
|
Uri = new Uri($"{Request.Scheme}://{Request.Host}/api/{relPath}")
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,58 +2,57 @@
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Insight.Api.Hosting
|
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, IConfiguration configuration)
|
services.AddEndpointsApiExplorer();
|
||||||
|
services.AddSwaggerGen(options =>
|
||||||
{
|
{
|
||||||
services.AddEndpointsApiExplorer();
|
options.SwaggerDoc("v1", new OpenApiInfo
|
||||||
services.AddSwaggerGen(options =>
|
|
||||||
{
|
{
|
||||||
options.SwaggerDoc("v1", new OpenApiInfo
|
Title = "Insight API",
|
||||||
{
|
Version = "v1"
|
||||||
Title = "Insight API",
|
|
||||||
Version = "v1"
|
|
||||||
});
|
|
||||||
|
|
||||||
options.AddSecurityDefinition(name: "Bearer", securityScheme: new OpenApiSecurityScheme
|
|
||||||
{
|
|
||||||
Name = "Authorization",
|
|
||||||
Description = "Enter the Bearer Authorization string as following: `Bearer Generated-JWT-Token`",
|
|
||||||
In = ParameterLocation.Header,
|
|
||||||
Type = SecuritySchemeType.ApiKey,
|
|
||||||
Scheme = "Bearer",
|
|
||||||
BearerFormat = "JWT",
|
|
||||||
|
|
||||||
Reference = new OpenApiReference
|
|
||||||
{
|
|
||||||
Id = JwtBearerDefaults.AuthenticationScheme,
|
|
||||||
Type = ReferenceType.SecurityScheme
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
|
||||||
{
|
|
||||||
{
|
|
||||||
new OpenApiSecurityScheme
|
|
||||||
{
|
|
||||||
In = ParameterLocation.Header,
|
|
||||||
Reference = new OpenApiReference
|
|
||||||
{
|
|
||||||
Id = "Bearer",
|
|
||||||
Type = ReferenceType.SecurityScheme
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new List<string>()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
|
||||||
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return services;
|
options.AddSecurityDefinition(name: "Bearer", securityScheme: new OpenApiSecurityScheme
|
||||||
}
|
{
|
||||||
|
Name = "Authorization",
|
||||||
|
Description = "Enter the Bearer Authorization string as following: `Bearer Generated-JWT-Token`",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Type = SecuritySchemeType.ApiKey,
|
||||||
|
Scheme = "Bearer",
|
||||||
|
BearerFormat = "JWT",
|
||||||
|
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Id = JwtBearerDefaults.AuthenticationScheme,
|
||||||
|
Type = ReferenceType.SecurityScheme
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Id = "Bearer",
|
||||||
|
Type = ReferenceType.SecurityScheme
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new List<string>()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||||
|
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,23 +1,22 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Insight.Api.Models
|
namespace Insight.Api.Models;
|
||||||
|
|
||||||
|
public class RegistrationModel
|
||||||
{
|
{
|
||||||
public class RegistrationModel
|
public string? FirstName { get; set; }
|
||||||
{
|
public string? LastName { get; set; }
|
||||||
public string? FirstName { get; set; }
|
|
||||||
public string? LastName { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Email is required")]
|
[Required(ErrorMessage = "Email is required")]
|
||||||
[EmailAddress]
|
[EmailAddress]
|
||||||
public string? Email { get; set; }
|
public string? Email { get; set; }
|
||||||
|
|
||||||
[Required(ErrorMessage = "Password is required")]
|
[Required(ErrorMessage = "Password is required")]
|
||||||
[DataType(DataType.Password)]
|
[DataType(DataType.Password)]
|
||||||
public string? Password { get; set; }
|
public string? Password { get; set; }
|
||||||
|
|
||||||
[Required(ErrorMessage = "Password is required")]
|
[Required(ErrorMessage = "Password is required")]
|
||||||
[DataType(DataType.Password)]
|
[DataType(DataType.Password)]
|
||||||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
|
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
|
||||||
public string? ConfirmPassword { get; set; }
|
public string? ConfirmPassword { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,97 +3,96 @@ using Insight.Domain.Constants;
|
||||||
using Insight.Infrastructure;
|
using Insight.Infrastructure;
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
|
||||||
namespace Insight.Api
|
namespace Insight.Api;
|
||||||
|
|
||||||
|
internal class Program
|
||||||
{
|
{
|
||||||
public class Program
|
public static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
public static async Task Main(string[] args)
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
builder.Host.UseWindowsService();
|
||||||
|
builder.Host.UseSystemd();
|
||||||
|
|
||||||
|
// LOGGER
|
||||||
|
builder.Logging.ClearProviders();
|
||||||
|
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
||||||
|
builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Warning);
|
||||||
|
|
||||||
|
builder.Logging.AddSimpleConsole(options =>
|
||||||
{
|
{
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
options.IncludeScopes = true;
|
||||||
builder.Host.UseWindowsService();
|
options.SingleLine = true;
|
||||||
builder.Host.UseSystemd();
|
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
||||||
|
});
|
||||||
|
|
||||||
// LOGGER
|
builder.Logging.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/api_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}");
|
||||||
builder.Logging.ClearProviders();
|
|
||||||
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
|
||||||
builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Warning);
|
|
||||||
|
|
||||||
builder.Logging.AddSimpleConsole(options =>
|
// INFRASTRUCTURE
|
||||||
{
|
builder.Services.AddDatabase(builder.Configuration);
|
||||||
options.IncludeScopes = true;
|
builder.Services.AddInfrastructureServices();
|
||||||
options.SingleLine = true;
|
|
||||||
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.Logging.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/api_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}");
|
// IDENTITY
|
||||||
|
builder.Services.AddIdentityServices(builder.Configuration);
|
||||||
|
builder.Services.AddBearerAuthentication(builder.Configuration);
|
||||||
|
builder.Services.AddTokenServices(builder.Configuration);
|
||||||
|
|
||||||
// INFRASTRUCTURE
|
// SECURITY
|
||||||
builder.Services.AddDatabase(builder.Configuration);
|
builder.Services.AddAuthorization();
|
||||||
builder.Services.AddInfrastructureServices();
|
|
||||||
|
|
||||||
// IDENTITY
|
// WEBSERVICES
|
||||||
builder.Services.AddIdentityServices(builder.Configuration);
|
builder.Services.AddProxyServices(builder.Configuration);
|
||||||
builder.Services.AddBearerAuthentication(builder.Configuration);
|
builder.Services.AddRoutingServices(builder.Configuration);
|
||||||
builder.Services.AddTokenServices(builder.Configuration);
|
builder.Services.AddControllers();
|
||||||
|
|
||||||
// SECURITY
|
// SWAGGER
|
||||||
builder.Services.AddAuthorization();
|
builder.Services.AddSwaggerServices(builder.Configuration);
|
||||||
|
|
||||||
// WEBSERVICES
|
//builder.Services.AddControllers();
|
||||||
builder.Services.AddProxyServices(builder.Configuration);
|
//builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddRoutingServices(builder.Configuration);
|
//builder.Services.AddSwaggerGen();
|
||||||
builder.Services.AddControllers();
|
|
||||||
|
|
||||||
// SWAGGER
|
var app = builder.Build();
|
||||||
builder.Services.AddSwaggerServices(builder.Configuration);
|
|
||||||
|
|
||||||
//builder.Services.AddControllers();
|
// Configure the HTTP request pipeline.
|
||||||
//builder.Services.AddEndpointsApiExplorer();
|
app.UseForwardedHeaders();
|
||||||
//builder.Services.AddSwaggerGen();
|
|
||||||
|
|
||||||
var app = builder.Build();
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
|
||||||
app.UseForwardedHeaders();
|
|
||||||
|
|
||||||
if (app.Environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
app.UseSwagger(options =>
|
|
||||||
{
|
|
||||||
options.RouteTemplate = "api/swagger/{documentName}/swagger.json";
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseSwaggerUI(options =>
|
|
||||||
{
|
|
||||||
options.DefaultModelsExpandDepth(-1);
|
|
||||||
options.SwaggerEndpoint("/api/swagger/v1/swagger.json", "v1");
|
|
||||||
options.RoutePrefix = "api/swagger";
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseCors(x => x
|
|
||||||
.AllowAnyOrigin()
|
|
||||||
.AllowAnyMethod()
|
|
||||||
.AllowAnyHeader());
|
|
||||||
|
|
||||||
app.UseAuthorization();
|
|
||||||
|
|
||||||
app.MapControllers();
|
|
||||||
|
|
||||||
// STATIC FILES (UPDATES)
|
|
||||||
var files = new DirectoryInfo($"{Domain.Constants.Configuration.AppDirectory?.FullName}/files");
|
|
||||||
files.Create();
|
|
||||||
|
|
||||||
app.UseStaticFiles(new StaticFileOptions
|
|
||||||
{
|
|
||||||
FileProvider = new PhysicalFileProvider(files.FullName),
|
|
||||||
RequestPath = "/api/files",
|
|
||||||
ServeUnknownFileTypes = true
|
|
||||||
});
|
|
||||||
|
|
||||||
await app.RunAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseSwagger(options =>
|
||||||
|
{
|
||||||
|
options.RouteTemplate = "api/swagger/{documentName}/swagger.json";
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseSwaggerUI(options =>
|
||||||
|
{
|
||||||
|
options.DefaultModelsExpandDepth(-1);
|
||||||
|
options.SwaggerEndpoint("/api/swagger/v1/swagger.json", "v1");
|
||||||
|
options.RoutePrefix = "api/swagger";
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseCors(x => x
|
||||||
|
.AllowAnyOrigin()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader());
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
// STATIC FILES (UPDATES)
|
||||||
|
var files = new DirectoryInfo($"{Domain.Constants.Configuration.AppDirectory?.FullName}/files");
|
||||||
|
files.Create();
|
||||||
|
|
||||||
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
|
{
|
||||||
|
FileProvider = new PhysicalFileProvider(files.FullName),
|
||||||
|
RequestPath = "/api/files",
|
||||||
|
ServeUnknownFileTypes = true
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.RunAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
namespace Insight.Infrastructure
|
namespace Insight.Infrastructure;
|
||||||
{
|
|
||||||
public class Appsettings
|
|
||||||
{
|
|
||||||
public const string Database = "database";
|
|
||||||
public const string JwtKey = "jwt.key";
|
|
||||||
public const string JwtAudience = "jwt.audience";
|
|
||||||
public const string JwtIssuer = "jwt.issuer";
|
|
||||||
public const string JwtExp = "jwt.exp";
|
|
||||||
|
|
||||||
public const string ServerHost = "server.host";
|
public class Appsettings
|
||||||
public const string ServerPort = "server.port";
|
{
|
||||||
}
|
public const string Database = "database";
|
||||||
|
public const string JwtKey = "jwt.key";
|
||||||
|
public const string JwtAudience = "jwt.audience";
|
||||||
|
public const string JwtIssuer = "jwt.issuer";
|
||||||
|
public const string JwtExp = "jwt.exp";
|
||||||
|
|
||||||
|
public const string ServerHost = "server.host";
|
||||||
|
public const string ServerPort = "server.port";
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
namespace Insight.Infrastructure
|
namespace Insight.Infrastructure;
|
||||||
|
|
||||||
|
public static class Monitoring
|
||||||
{
|
{
|
||||||
public static class Monitoring
|
public static readonly Uri StatusUri = new("https://admin.webmatic.de/monitoring/computer/send/status");
|
||||||
{
|
public static readonly Uri LogUri = new("https://admin.webmatic.de/monitoring/computer/send/log");
|
||||||
public static readonly Uri StatusUri = new("https://admin.webmatic.de/monitoring/computer/send/status");
|
|
||||||
public static readonly Uri LogUri = new("https://admin.webmatic.de/monitoring/computer/send/log");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
namespace Insight.Infrastructure
|
namespace Insight.Infrastructure;
|
||||||
|
|
||||||
|
public class Settings
|
||||||
{
|
{
|
||||||
public class Settings
|
public const string Database = "insight";
|
||||||
{
|
|
||||||
public const string Database = "insight";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,60 +3,59 @@ using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class AgentEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class AgentEntity
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("insert")]
|
||||||
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("update")]
|
||||||
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("serial"), Required]
|
||||||
|
public string? Serial { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("hostname")]
|
||||||
|
public string? Hostname { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("version"), BsonRepresentation(BsonType.String)]
|
||||||
|
public Version? Version { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("endpoint"), BsonRepresentation(BsonType.String)]
|
||||||
|
public string? Endpoint { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("connected")]
|
||||||
|
public DateTime? Connected { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("activity")]
|
||||||
|
public DateTime? Activity { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("bytes_sent")]
|
||||||
|
public long SentBytes { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("bytes_received")]
|
||||||
|
public long ReceivedBytes { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("packets_sent")]
|
||||||
|
public long SentPackets { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("packets_received")]
|
||||||
|
public long ReceivedPackets { get; set; }
|
||||||
|
|
||||||
|
//[BsonElement("latency")]
|
||||||
|
//public TimeSpan? Latency { get; set; }
|
||||||
|
|
||||||
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
|
public List<HostEntity>? Hosts { get; set; }
|
||||||
|
|
||||||
|
public bool GetOnlineState()
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
if (Activity is null) return false;
|
||||||
public string? Id { get; set; }
|
return Activity.Value.ToLocalTime().Add(TimeSpan.FromSeconds(60)).Subtract(DateTime.Now).Seconds > 0;
|
||||||
|
|
||||||
[BsonElement("insert")]
|
|
||||||
public DateTime? Insert { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("update")]
|
|
||||||
public DateTime? Update { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("serial"), Required]
|
|
||||||
public string? Serial { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("hostname")]
|
|
||||||
public string? Hostname { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("version"), BsonRepresentation(BsonType.String)]
|
|
||||||
public Version? Version { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("endpoint"), BsonRepresentation(BsonType.String)]
|
|
||||||
public string? Endpoint { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("connected")]
|
|
||||||
public DateTime? Connected { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("activity")]
|
|
||||||
public DateTime? Activity { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("bytes_sent")]
|
|
||||||
public long SentBytes { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("bytes_received")]
|
|
||||||
public long ReceivedBytes { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("packets_sent")]
|
|
||||||
public long SentPackets { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("packets_received")]
|
|
||||||
public long ReceivedPackets { get; set; }
|
|
||||||
|
|
||||||
//[BsonElement("latency")]
|
|
||||||
//public TimeSpan? Latency { get; set; }
|
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
|
||||||
public List<HostEntity>? Hosts { get; set; }
|
|
||||||
|
|
||||||
public bool GetOnlineState()
|
|
||||||
{
|
|
||||||
if (Activity is null) return false;
|
|
||||||
return Activity.Value.ToLocalTime().Add(TimeSpan.FromSeconds(60)).Subtract(DateTime.Now).Seconds > 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,36 +2,35 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class AgentLogEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class AgentLogEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_agent"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("agent")]
|
[BsonElement("_agent"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("agent")]
|
||||||
public string? Agent { get; set; }
|
public string? Agent { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("eventid")]
|
[BsonElement("eventid")]
|
||||||
public string? EventId { get; set; }
|
public string? EventId { get; set; }
|
||||||
|
|
||||||
[BsonElement("status")]
|
[BsonElement("status")]
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
[BsonElement("source")]
|
[BsonElement("source")]
|
||||||
public string? Source { get; set; }
|
public string? Source { get; set; }
|
||||||
|
|
||||||
[BsonElement("category")]
|
[BsonElement("category")]
|
||||||
public string? Category { get; set; }
|
public string? Category { get; set; }
|
||||||
|
|
||||||
[BsonElement("message")]
|
[BsonElement("message")]
|
||||||
public string? Message { get; set; }
|
public string? Message { get; set; }
|
||||||
|
|
||||||
[BsonElement("timestamp")]
|
[BsonElement("timestamp")]
|
||||||
public DateTime? Timestamp { get; set; }
|
public DateTime? Timestamp { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,27 +3,26 @@ using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class CustomerEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class CustomerEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("name"), Required]
|
[BsonElement("name"), Required]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("tag")]
|
[BsonElement("tag")]
|
||||||
public string? Tag { get; set; }
|
public string? Tag { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<HostEntity>? Hosts { get; set; }
|
public List<HostEntity>? Hosts { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,36 +3,35 @@ using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_customer"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("customer")]
|
[BsonElement("_customer"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("customer")]
|
||||||
public string? Customer { get; set; }
|
public string? Customer { get; set; }
|
||||||
|
|
||||||
[BsonElement("_agent"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("agent")]
|
[BsonElement("_agent"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("agent")]
|
||||||
public string? Agent { get; set; }
|
public string? Agent { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("name"), Required]
|
[BsonElement("name"), Required]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("description")]
|
[BsonElement("description")]
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<CustomerEntity>? Customers { get; set; }
|
public List<CustomerEntity>? Customers { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<AgentEntity>? Agents { get; set; }
|
public List<AgentEntity>? Agents { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,39 +2,38 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostApplicationEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostApplicationEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("company")]
|
[BsonElement("company")]
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("architecture")]
|
[BsonElement("architecture")]
|
||||||
public string? Architecture { get; set; }
|
public string? Architecture { get; set; }
|
||||||
|
|
||||||
[BsonElement("version")]
|
[BsonElement("version")]
|
||||||
public string? Version { get; set; }
|
public string? Version { get; set; }
|
||||||
|
|
||||||
[BsonElement("installdate")]
|
[BsonElement("installdate")]
|
||||||
public DateTime? InstallDate { get; set; }
|
public DateTime? InstallDate { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,51 +2,50 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostDriveEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostDriveEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("index")]
|
[BsonElement("index")]
|
||||||
public uint? Index { get; set; }
|
public uint? Index { get; set; }
|
||||||
|
|
||||||
[BsonElement("company")]
|
[BsonElement("company")]
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("size")]
|
[BsonElement("size")]
|
||||||
public ulong? Size { get; set; }
|
public ulong? Size { get; set; }
|
||||||
|
|
||||||
[BsonElement("type")]
|
[BsonElement("type")]
|
||||||
public string? Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
[BsonElement("serial")]
|
[BsonElement("serial")]
|
||||||
public string? Serial { get; set; }
|
public string? Serial { get; set; }
|
||||||
|
|
||||||
[BsonElement("firmware")]
|
[BsonElement("firmware")]
|
||||||
public string? Firmware { get; set; }
|
public string? Firmware { get; set; }
|
||||||
|
|
||||||
[BsonElement("status")]
|
[BsonElement("status")]
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
[BsonElement("pnp")]
|
[BsonElement("pnp")]
|
||||||
public string? Pnp { get; set; }
|
public string? Pnp { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,187 +2,186 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostHypervisorVirtualMaschineEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostHypervisorVirtualMaschineEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("uniqueid")]
|
[BsonElement("uniqueid")]
|
||||||
public string? UniqueId { get; set; }
|
public string? UniqueId { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("notes")]
|
[BsonElement("notes")]
|
||||||
public string? Notes { get; set; }
|
public string? Notes { get; set; }
|
||||||
|
|
||||||
[BsonElement("enabled")]
|
[BsonElement("enabled")]
|
||||||
public string? Enabled { get; set; }
|
public string? Enabled { get; set; }
|
||||||
|
|
||||||
[BsonElement("enabled_default")]
|
[BsonElement("enabled_default")]
|
||||||
public string? EnabledDefault { get; set; }
|
public string? EnabledDefault { get; set; }
|
||||||
|
|
||||||
[BsonElement("health")]
|
[BsonElement("health")]
|
||||||
public string? Health { get; set; }
|
public string? Health { get; set; }
|
||||||
|
|
||||||
[BsonElement("status")]
|
[BsonElement("status")]
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
[BsonElement("ontime")]
|
[BsonElement("ontime")]
|
||||||
public ulong? OnTime { get; set; }
|
public ulong? OnTime { get; set; }
|
||||||
|
|
||||||
[BsonElement("replication_state")]
|
[BsonElement("replication_state")]
|
||||||
public string? ReplicationState { get; set; }
|
public string? ReplicationState { get; set; }
|
||||||
|
|
||||||
[BsonElement("replication_health")]
|
[BsonElement("replication_health")]
|
||||||
public string? ReplicationHealth { get; set; }
|
public string? ReplicationHealth { get; set; }
|
||||||
|
|
||||||
[BsonElement("version_configuration")]
|
[BsonElement("version_configuration")]
|
||||||
public string? ConfigurationVersion { get; set; }
|
public string? ConfigurationVersion { get; set; }
|
||||||
|
|
||||||
[BsonElement("version_integrated_services")]
|
[BsonElement("version_integrated_services")]
|
||||||
public string? IntegrationServicesVersionState { get; set; }
|
public string? IntegrationServicesVersionState { get; set; }
|
||||||
|
|
||||||
[BsonElement("processid")]
|
[BsonElement("processid")]
|
||||||
public uint? ProcessId { get; set; }
|
public uint? ProcessId { get; set; }
|
||||||
|
|
||||||
[BsonElement("processor_count")]
|
[BsonElement("processor_count")]
|
||||||
public uint? NumberOfProcessors { get; set; }
|
public uint? NumberOfProcessors { get; set; }
|
||||||
|
|
||||||
[BsonElement("processor_load")]
|
[BsonElement("processor_load")]
|
||||||
public uint? ProcessorLoad { get; set; }
|
public uint? ProcessorLoad { get; set; }
|
||||||
|
|
||||||
[BsonElement("memory_available")]
|
[BsonElement("memory_available")]
|
||||||
public int? MemoryAvailable { get; set; }
|
public int? MemoryAvailable { get; set; }
|
||||||
|
|
||||||
[BsonElement("memory_usage")]
|
[BsonElement("memory_usage")]
|
||||||
public ulong? MemoryUsage { get; set; }
|
public ulong? MemoryUsage { get; set; }
|
||||||
|
|
||||||
[BsonElement("installdate")]
|
[BsonElement("installdate")]
|
||||||
public DateTime? InstallDate { get; set; }
|
public DateTime? InstallDate { get; set; }
|
||||||
|
|
||||||
[BsonElement("configuration_changed")]
|
[BsonElement("configuration_changed")]
|
||||||
public DateTime? TimeOfLastConfigurationChange { get; set; }
|
public DateTime? TimeOfLastConfigurationChange { get; set; }
|
||||||
|
|
||||||
[BsonElement("state_changed")]
|
[BsonElement("state_changed")]
|
||||||
public DateTime? TimeOfLastStateChange { get; set; }
|
public DateTime? TimeOfLastStateChange { get; set; }
|
||||||
|
|
||||||
[BsonElement("replication_last")]
|
[BsonElement("replication_last")]
|
||||||
public DateTime? LastReplicationTime { get; set; }
|
public DateTime? LastReplicationTime { get; set; }
|
||||||
|
|
||||||
[BsonElement("guest_os")]
|
[BsonElement("guest_os")]
|
||||||
public string? Os { get; set; }
|
public string? Os { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<HostHypervisorVirtualMaschineConfigEntity>? Configs { get; set; }
|
public List<HostHypervisorVirtualMaschineConfigEntity>? Configs { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class HostHypervisorVirtualMaschineConfigEntity
|
public class HostHypervisorVirtualMaschineConfigEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("virtualmaschine"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("virtualmaschine")]
|
[BsonElement("virtualmaschine"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("virtualmaschine")]
|
||||||
public string? VirtualMaschine { get; set; }
|
public string? VirtualMaschine { get; set; }
|
||||||
|
|
||||||
[BsonElement("batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("uniqueid")]
|
[BsonElement("uniqueid")]
|
||||||
public string? UniqueId { get; set; }
|
public string? UniqueId { get; set; }
|
||||||
|
|
||||||
[BsonElement("parentid")]
|
[BsonElement("parentid")]
|
||||||
public string? ParentId { get; set; }
|
public string? ParentId { get; set; }
|
||||||
|
|
||||||
[BsonElement("type")]
|
[BsonElement("type")]
|
||||||
public string? Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("notes")]
|
[BsonElement("notes")]
|
||||||
public string? Notes { get; set; }
|
public string? Notes { get; set; }
|
||||||
|
|
||||||
[BsonElement("creationtime")]
|
[BsonElement("creationtime")]
|
||||||
public DateTime? CreationTime { get; set; }
|
public DateTime? CreationTime { get; set; }
|
||||||
|
|
||||||
[BsonElement("generation")]
|
[BsonElement("generation")]
|
||||||
public string? Generation { get; set; }
|
public string? Generation { get; set; }
|
||||||
|
|
||||||
[BsonElement("architecture")]
|
[BsonElement("architecture")]
|
||||||
public string? Architecture { get; set; }
|
public string? Architecture { get; set; }
|
||||||
|
|
||||||
[BsonElement("secureboot")]
|
[BsonElement("secureboot")]
|
||||||
public bool? SecureBootEnabled { get; set; }
|
public bool? SecureBootEnabled { get; set; }
|
||||||
|
|
||||||
[BsonElement("automatic_snapshot")]
|
[BsonElement("automatic_snapshot")]
|
||||||
public bool? IsAutomaticSnapshot { get; set; }
|
public bool? IsAutomaticSnapshot { get; set; }
|
||||||
|
|
||||||
[BsonElement("action_start")]
|
[BsonElement("action_start")]
|
||||||
public string? AutomaticStartupAction { get; set; }
|
public string? AutomaticStartupAction { get; set; }
|
||||||
|
|
||||||
[BsonElement("action_shutdown")]
|
[BsonElement("action_shutdown")]
|
||||||
public string? AutomaticShutdownAction { get; set; }
|
public string? AutomaticShutdownAction { get; set; }
|
||||||
|
|
||||||
[BsonElement("action_recovery")]
|
[BsonElement("action_recovery")]
|
||||||
public string? AutomaticRecoveryAction { get; set; }
|
public string? AutomaticRecoveryAction { get; set; }
|
||||||
|
|
||||||
[BsonElement("auto_snapshots")]
|
[BsonElement("auto_snapshots")]
|
||||||
public bool? AutomaticSnapshotsEnabled { get; set; }
|
public bool? AutomaticSnapshotsEnabled { get; set; }
|
||||||
|
|
||||||
[BsonElement("serial_mainboard")]
|
[BsonElement("serial_mainboard")]
|
||||||
public string? BaseBoardSerialNumber { get; set; }
|
public string? BaseBoardSerialNumber { get; set; }
|
||||||
|
|
||||||
[BsonElement("serial_bios")]
|
[BsonElement("serial_bios")]
|
||||||
public string? BIOSSerialNumber { get; set; }
|
public string? BIOSSerialNumber { get; set; }
|
||||||
|
|
||||||
[BsonElement("bios_guid")]
|
[BsonElement("bios_guid")]
|
||||||
public string? BIOSGUID { get; set; }
|
public string? BIOSGUID { get; set; }
|
||||||
|
|
||||||
[BsonElement("data_root")]
|
[BsonElement("data_root")]
|
||||||
public string? ConfigurationDataRoot { get; set; }
|
public string? ConfigurationDataRoot { get; set; }
|
||||||
|
|
||||||
[BsonElement("file")]
|
[BsonElement("file")]
|
||||||
public string? ConfigurationFile { get; set; }
|
public string? ConfigurationFile { get; set; }
|
||||||
|
|
||||||
[BsonElement("guest_data_root")]
|
[BsonElement("guest_data_root")]
|
||||||
public string? GuestStateDataRoot { get; set; }
|
public string? GuestStateDataRoot { get; set; }
|
||||||
|
|
||||||
[BsonElement("guest_state_file")]
|
[BsonElement("guest_state_file")]
|
||||||
public string? GuestStateFile { get; set; }
|
public string? GuestStateFile { get; set; }
|
||||||
|
|
||||||
[BsonElement("snapshot_data_root")]
|
[BsonElement("snapshot_data_root")]
|
||||||
public string? SnapshotDataRoot { get; set; }
|
public string? SnapshotDataRoot { get; set; }
|
||||||
|
|
||||||
[BsonElement("suspend_data_root")]
|
[BsonElement("suspend_data_root")]
|
||||||
public string? SuspendDataRoot { get; set; }
|
public string? SuspendDataRoot { get; set; }
|
||||||
|
|
||||||
[BsonElement("swap_data_root")]
|
[BsonElement("swap_data_root")]
|
||||||
public string? SwapFileDataRoot { get; set; }
|
public string? SwapFileDataRoot { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,217 +2,216 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostInterfaceEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostInterfaceEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("index")]
|
[BsonElement("index")]
|
||||||
public uint? Index { get; set; }
|
public uint? Index { get; set; }
|
||||||
|
|
||||||
[BsonElement("mac")]
|
[BsonElement("mac")]
|
||||||
public string? Mac { get; set; }
|
public string? Mac { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("description")]
|
[BsonElement("description")]
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
[BsonElement("physical")]
|
[BsonElement("physical")]
|
||||||
public bool? Physical { get; set; }
|
public bool? Physical { get; set; }
|
||||||
|
|
||||||
[BsonElement("status")]
|
[BsonElement("status")]
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
[BsonElement("suffix")]
|
[BsonElement("suffix")]
|
||||||
public string? Suffix { get; set; }
|
public string? Suffix { get; set; }
|
||||||
|
|
||||||
[BsonElement("speed")]
|
[BsonElement("speed")]
|
||||||
public long? Speed { get; set; }
|
public long? Speed { get; set; }
|
||||||
|
|
||||||
[BsonElement("ipv4_mtu")]
|
[BsonElement("ipv4_mtu")]
|
||||||
public long? Ipv4Mtu { get; set; }
|
public long? Ipv4Mtu { get; set; }
|
||||||
|
|
||||||
[BsonElement("ipv4_dhcp")]
|
[BsonElement("ipv4_dhcp")]
|
||||||
public bool? Ipv4Dhcp { get; set; }
|
public bool? Ipv4Dhcp { get; set; }
|
||||||
|
|
||||||
[BsonElement("ipv4_forwarding")]
|
[BsonElement("ipv4_forwarding")]
|
||||||
public bool? Ipv4Forwarding { get; set; }
|
public bool? Ipv4Forwarding { get; set; }
|
||||||
|
|
||||||
[BsonElement("ipv6_mtu")]
|
[BsonElement("ipv6_mtu")]
|
||||||
public long? Ipv6Mtu { get; set; }
|
public long? Ipv6Mtu { get; set; }
|
||||||
|
|
||||||
[BsonElement("sent")]
|
[BsonElement("sent")]
|
||||||
public long? Sent { get; set; }
|
public long? Sent { get; set; }
|
||||||
|
|
||||||
[BsonElement("received")]
|
[BsonElement("received")]
|
||||||
public long? Received { get; set; }
|
public long? Received { get; set; }
|
||||||
|
|
||||||
[BsonElement("packets_incoming_discarded")]
|
[BsonElement("packets_incoming_discarded")]
|
||||||
public long? IncomingPacketsDiscarded { get; set; }
|
public long? IncomingPacketsDiscarded { get; set; }
|
||||||
|
|
||||||
[BsonElement("packets_incoming_errors")]
|
[BsonElement("packets_incoming_errors")]
|
||||||
public long? IncomingPacketsWithErrors { get; set; }
|
public long? IncomingPacketsWithErrors { get; set; }
|
||||||
|
|
||||||
[BsonElement("packets_incoming_unknown")]
|
[BsonElement("packets_incoming_unknown")]
|
||||||
public long? IncomingUnknownProtocolPackets { get; set; }
|
public long? IncomingUnknownProtocolPackets { get; set; }
|
||||||
|
|
||||||
[BsonElement("packets_outgoing_discarded")]
|
[BsonElement("packets_outgoing_discarded")]
|
||||||
public long? OutgoingPacketsDiscarded { get; set; }
|
public long? OutgoingPacketsDiscarded { get; set; }
|
||||||
|
|
||||||
[BsonElement("packets_outgoing_errors")]
|
[BsonElement("packets_outgoing_errors")]
|
||||||
public long? OutgoingPacketsWithErrors { get; set; }
|
public long? OutgoingPacketsWithErrors { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class HostInterfaceAddressEntity
|
public class HostInterfaceAddressEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_interface"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("interface")]
|
[BsonElement("_interface"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("interface")]
|
||||||
public string? Interface { get; set; }
|
public string? Interface { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("address")]
|
[BsonElement("address")]
|
||||||
public string? Address { get; set; }
|
public string? Address { get; set; }
|
||||||
|
|
||||||
[BsonElement("mask")]
|
[BsonElement("mask")]
|
||||||
public string? Mask { get; set; }
|
public string? Mask { get; set; }
|
||||||
|
|
||||||
//public string? State { get; set; }
|
//public string? State { get; set; }
|
||||||
//public long? PreferredLifetime { get; set; }
|
//public long? PreferredLifetime { get; set; }
|
||||||
//public long? ValidLifetime { get; set; }
|
//public long? ValidLifetime { get; set; }
|
||||||
//public long? LeaseLifetime { get; set; }
|
//public long? LeaseLifetime { get; set; }
|
||||||
//public int? PrefixLength { get; set; }
|
//public int? PrefixLength { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<HostInterfaceEntity>? Interfaces { get; set; }
|
public List<HostInterfaceEntity>? Interfaces { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class HostInterfaceGatewayEntity
|
public class HostInterfaceGatewayEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_interface"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("interface")]
|
[BsonElement("_interface"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("interface")]
|
||||||
public string? Interface { get; set; }
|
public string? Interface { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("address")]
|
[BsonElement("address")]
|
||||||
public string? Address { get; set; }
|
public string? Address { get; set; }
|
||||||
|
|
||||||
[BsonElement("mask")]
|
[BsonElement("mask")]
|
||||||
public string? Mask { get; set; }
|
public string? Mask { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<HostInterfaceEntity>? Interfaces { get; set; }
|
public List<HostInterfaceEntity>? Interfaces { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class HostInterfaceNameserverEntity
|
public class HostInterfaceNameserverEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_interface"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("interface")]
|
[BsonElement("_interface"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("interface")]
|
||||||
public string? Interface { get; set; }
|
public string? Interface { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("address")]
|
[BsonElement("address")]
|
||||||
public string? Address { get; set; }
|
public string? Address { get; set; }
|
||||||
|
|
||||||
[BsonElement("mask")]
|
[BsonElement("mask")]
|
||||||
public string? Mask { get; set; }
|
public string? Mask { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<HostInterfaceEntity>? Interfaces { get; set; }
|
public List<HostInterfaceEntity>? Interfaces { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class HostInterfaceRouteEntity
|
public class HostInterfaceRouteEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_interface"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("interface")]
|
[BsonElement("_interface"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("interface")]
|
||||||
public string? Interface { get; set; }
|
public string? Interface { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("destination")]
|
[BsonElement("destination")]
|
||||||
public string? Destination { get; set; }
|
public string? Destination { get; set; }
|
||||||
|
|
||||||
[BsonElement("mask")]
|
[BsonElement("mask")]
|
||||||
public string? Mask { get; set; }
|
public string? Mask { get; set; }
|
||||||
|
|
||||||
[BsonElement("gateway")]
|
[BsonElement("gateway")]
|
||||||
public string? Gateway { get; set; }
|
public string? Gateway { get; set; }
|
||||||
|
|
||||||
[BsonElement("metric")]
|
[BsonElement("metric")]
|
||||||
public int? Metric { get; set; }
|
public int? Metric { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<HostInterfaceEntity>? Interfaces { get; set; }
|
public List<HostInterfaceEntity>? Interfaces { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,36 +2,35 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostLogEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostLogEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("eventid")]
|
[BsonElement("eventid")]
|
||||||
public string? EventId { get; set; }
|
public string? EventId { get; set; }
|
||||||
|
|
||||||
[BsonElement("status")]
|
[BsonElement("status")]
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
[BsonElement("source")]
|
[BsonElement("source")]
|
||||||
public string? Source { get; set; }
|
public string? Source { get; set; }
|
||||||
|
|
||||||
[BsonElement("category")]
|
[BsonElement("category")]
|
||||||
public string? Category { get; set; }
|
public string? Category { get; set; }
|
||||||
|
|
||||||
[BsonElement("message")]
|
[BsonElement("message")]
|
||||||
public string? Message { get; set; }
|
public string? Message { get; set; }
|
||||||
|
|
||||||
[BsonElement("timestamp")]
|
[BsonElement("timestamp")]
|
||||||
public DateTime? Timestamp { get; set; }
|
public DateTime? Timestamp { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,42 +2,41 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostLogMonitoringEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostLogMonitoringEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("hostname")]
|
[BsonElement("hostname")]
|
||||||
public string? Hostname { get; set; }
|
public string? Hostname { get; set; }
|
||||||
|
|
||||||
[BsonElement("category")]
|
[BsonElement("category")]
|
||||||
public string? Category { get; set; }
|
public string? Category { get; set; }
|
||||||
|
|
||||||
[BsonElement("status")]
|
[BsonElement("status")]
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
[BsonElement("task")]
|
[BsonElement("task")]
|
||||||
public string? Task { get; set; }
|
public string? Task { get; set; }
|
||||||
|
|
||||||
[BsonElement("message")]
|
[BsonElement("message")]
|
||||||
public string? Message { get; set; }
|
public string? Message { get; set; }
|
||||||
|
|
||||||
[BsonElement("dispatch")]
|
[BsonElement("dispatch")]
|
||||||
public string? Dispatch { get; set; }
|
public string? Dispatch { get; set; }
|
||||||
|
|
||||||
[BsonElement("timestamp")]
|
[BsonElement("timestamp")]
|
||||||
public DateTime? Timestamp { get; set; }
|
public DateTime? Timestamp { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,39 +2,38 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostMainboardEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostMainboardEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("company")]
|
[BsonElement("company")]
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("serial")]
|
[BsonElement("serial")]
|
||||||
public string? Serial { get; set; }
|
public string? Serial { get; set; }
|
||||||
|
|
||||||
[BsonElement("bios")]
|
[BsonElement("bios")]
|
||||||
public string? Bios { get; set; }
|
public string? Bios { get; set; }
|
||||||
|
|
||||||
[BsonElement("version")]
|
[BsonElement("version")]
|
||||||
public string? Version { get; set; }
|
public string? Version { get; set; }
|
||||||
|
|
||||||
[BsonElement("Date")]
|
[BsonElement("Date")]
|
||||||
public DateTime? Date { get; set; }
|
public DateTime? Date { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,57 +2,56 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostMemoryEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostMemoryEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("index")]
|
[BsonElement("index")]
|
||||||
public uint? Index { get; set; }
|
public uint? Index { get; set; }
|
||||||
|
|
||||||
[BsonElement("company")]
|
[BsonElement("company")]
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("tag")]
|
[BsonElement("tag")]
|
||||||
public string? Tag { get; set; }
|
public string? Tag { get; set; }
|
||||||
|
|
||||||
[BsonElement("location")]
|
[BsonElement("location")]
|
||||||
public string? Location { get; set; }
|
public string? Location { get; set; }
|
||||||
|
|
||||||
[BsonElement("serial")]
|
[BsonElement("serial")]
|
||||||
public string? Serial { get; set; }
|
public string? Serial { get; set; }
|
||||||
|
|
||||||
[BsonElement("capacity")]
|
[BsonElement("capacity")]
|
||||||
public ulong? Capacity { get; set; }
|
public ulong? Capacity { get; set; }
|
||||||
|
|
||||||
[BsonElement("clock")]
|
[BsonElement("clock")]
|
||||||
public uint? Clock { get; set; }
|
public uint? Clock { get; set; }
|
||||||
|
|
||||||
[BsonElement("clock_current")]
|
[BsonElement("clock_current")]
|
||||||
public uint? CurrentClock { get; set; }
|
public uint? CurrentClock { get; set; }
|
||||||
|
|
||||||
[BsonElement("voltage")]
|
[BsonElement("voltage")]
|
||||||
public uint? Voltage { get; set; }
|
public uint? Voltage { get; set; }
|
||||||
|
|
||||||
[BsonElement("voltage_current")]
|
[BsonElement("voltage_current")]
|
||||||
public uint? CurrentVoltage { get; set; }
|
public uint? CurrentVoltage { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,39 +2,38 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostOsEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostOsEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("version")]
|
[BsonElement("version")]
|
||||||
public string? Version { get; set; }
|
public string? Version { get; set; }
|
||||||
|
|
||||||
[BsonElement("architecture")]
|
[BsonElement("architecture")]
|
||||||
public string? Architecture { get; set; }
|
public string? Architecture { get; set; }
|
||||||
|
|
||||||
[BsonElement("serialnumber")]
|
[BsonElement("serialnumber")]
|
||||||
public string? SerialNumber { get; set; }
|
public string? SerialNumber { get; set; }
|
||||||
|
|
||||||
[BsonElement("virtual")]
|
[BsonElement("virtual")]
|
||||||
public bool? Virtual { get; set; }
|
public bool? Virtual { get; set; }
|
||||||
|
|
||||||
[BsonElement("installed")]
|
[BsonElement("installed")]
|
||||||
public DateTime? Installed { get; set; }
|
public DateTime? Installed { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,39 +2,38 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostPrinterEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostPrinterEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("company")]
|
[BsonElement("company")]
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("port")]
|
[BsonElement("port")]
|
||||||
public string? Port { get; set; }
|
public string? Port { get; set; }
|
||||||
|
|
||||||
[BsonElement("location")]
|
[BsonElement("location")]
|
||||||
public string? Location { get; set; }
|
public string? Location { get; set; }
|
||||||
|
|
||||||
[BsonElement("comment")]
|
[BsonElement("comment")]
|
||||||
public string? Comment { get; set; }
|
public string? Comment { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,69 +2,68 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostProcessorEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostProcessorEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("index")]
|
[BsonElement("index")]
|
||||||
public uint? Index { get; set; }
|
public uint? Index { get; set; }
|
||||||
|
|
||||||
[BsonElement("company")]
|
[BsonElement("company")]
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("socket")]
|
[BsonElement("socket")]
|
||||||
public string? Socket { get; set; }
|
public string? Socket { get; set; }
|
||||||
|
|
||||||
[BsonElement("serial")]
|
[BsonElement("serial")]
|
||||||
public string? Serial { get; set; }
|
public string? Serial { get; set; }
|
||||||
|
|
||||||
[BsonElement("version")]
|
[BsonElement("version")]
|
||||||
public string? Version { get; set; }
|
public string? Version { get; set; }
|
||||||
|
|
||||||
[BsonElement("cores")]
|
[BsonElement("cores")]
|
||||||
public uint? Cores { get; set; }
|
public uint? Cores { get; set; }
|
||||||
|
|
||||||
[BsonElement("logicalcores")]
|
[BsonElement("logicalcores")]
|
||||||
public uint? LogicalCores { get; set; }
|
public uint? LogicalCores { get; set; }
|
||||||
|
|
||||||
[BsonElement("clock")]
|
[BsonElement("clock")]
|
||||||
public uint? Clock { get; set; }
|
public uint? Clock { get; set; }
|
||||||
|
|
||||||
[BsonElement("clock_current")]
|
[BsonElement("clock_current")]
|
||||||
public uint? CurrentClock { get; set; }
|
public uint? CurrentClock { get; set; }
|
||||||
|
|
||||||
[BsonElement("l1")]
|
[BsonElement("l1")]
|
||||||
public uint? L1Size { get; set; }
|
public uint? L1Size { get; set; }
|
||||||
|
|
||||||
[BsonElement("l2")]
|
[BsonElement("l2")]
|
||||||
public uint? L2Size { get; set; }
|
public uint? L2Size { get; set; }
|
||||||
|
|
||||||
[BsonElement("l3")]
|
[BsonElement("l3")]
|
||||||
public uint? L3Size { get; set; }
|
public uint? L3Size { get; set; }
|
||||||
|
|
||||||
[BsonElement("virtualization")]
|
[BsonElement("virtualization")]
|
||||||
public bool? Virtualization { get; set; }
|
public bool? Virtualization { get; set; }
|
||||||
|
|
||||||
[BsonElement("pnp")]
|
[BsonElement("pnp")]
|
||||||
public string? PNP { get; set; }
|
public string? PNP { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,54 +2,53 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostServiceEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostServiceEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("company")]
|
[BsonElement("company")]
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("displayname")]
|
[BsonElement("displayname")]
|
||||||
public string? DisplayName { get; set; }
|
public string? DisplayName { get; set; }
|
||||||
|
|
||||||
[BsonElement("description")]
|
[BsonElement("description")]
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
[BsonElement("startmode")]
|
[BsonElement("startmode")]
|
||||||
public string? StartMode { get; set; }
|
public string? StartMode { get; set; }
|
||||||
|
|
||||||
[BsonElement("state")]
|
[BsonElement("state")]
|
||||||
public string? State { get; set; }
|
public string? State { get; set; }
|
||||||
|
|
||||||
[BsonElement("processid")]
|
[BsonElement("processid")]
|
||||||
public uint? ProcessId { get; set; }
|
public uint? ProcessId { get; set; }
|
||||||
|
|
||||||
[BsonElement("delay")]
|
[BsonElement("delay")]
|
||||||
public bool? Delay { get; set; }
|
public bool? Delay { get; set; }
|
||||||
|
|
||||||
[BsonElement("path")]
|
[BsonElement("path")]
|
||||||
public string? Path { get; set; }
|
public string? Path { get; set; }
|
||||||
|
|
||||||
[BsonElement("account")]
|
[BsonElement("account")]
|
||||||
public string? Account { get; set; }
|
public string? Account { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,39 +2,38 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostSessionEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostSessionEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("sid")]
|
[BsonElement("sid")]
|
||||||
public string? Sid { get; set; }
|
public string? Sid { get; set; }
|
||||||
|
|
||||||
[BsonElement("user")]
|
[BsonElement("user")]
|
||||||
public string? User { get; set; }
|
public string? User { get; set; }
|
||||||
|
|
||||||
[BsonElement("remote")]
|
[BsonElement("remote")]
|
||||||
public string? Remote { get; set; }
|
public string? Remote { get; set; }
|
||||||
|
|
||||||
[BsonElement("type")]
|
[BsonElement("type")]
|
||||||
public string? Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
[BsonElement("state")]
|
[BsonElement("state")]
|
||||||
public string? State { get; set; }
|
public string? State { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,206 +2,205 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostStoragePoolEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostStoragePoolEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("uniqueid")]
|
[BsonElement("uniqueid")]
|
||||||
public string? UniqueId { get; set; }
|
public string? UniqueId { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("health")]
|
[BsonElement("health")]
|
||||||
public string? Health { get; set; }
|
public string? Health { get; set; }
|
||||||
|
|
||||||
[BsonElement("resiliency")]
|
[BsonElement("resiliency")]
|
||||||
public string? Resiliency { get; set; }
|
public string? Resiliency { get; set; }
|
||||||
|
|
||||||
[BsonElement("primordial")]
|
[BsonElement("primordial")]
|
||||||
public bool? Primordial { get; set; }
|
public bool? Primordial { get; set; }
|
||||||
|
|
||||||
[BsonElement("readonly")]
|
[BsonElement("readonly")]
|
||||||
public bool? ReadOnly { get; set; }
|
public bool? ReadOnly { get; set; }
|
||||||
|
|
||||||
[BsonElement("clustered")]
|
[BsonElement("clustered")]
|
||||||
public bool? Clustered { get; set; }
|
public bool? Clustered { get; set; }
|
||||||
|
|
||||||
[BsonElement("size")]
|
[BsonElement("size")]
|
||||||
public ulong? Size { get; set; }
|
public ulong? Size { get; set; }
|
||||||
|
|
||||||
[BsonElement("size_allocated")]
|
[BsonElement("size_allocated")]
|
||||||
public ulong? AllocatedSize { get; set; }
|
public ulong? AllocatedSize { get; set; }
|
||||||
|
|
||||||
[BsonElement("sectorsize")]
|
[BsonElement("sectorsize")]
|
||||||
public ulong? SectorSize { get; set; }
|
public ulong? SectorSize { get; set; }
|
||||||
|
|
||||||
[BsonElement("states")]
|
[BsonElement("states")]
|
||||||
public List<string>? States { get; set; }
|
public List<string>? States { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<HostStoragePoolPhysicalDiskEntity>? PhysicalDisks { get; set; }
|
public List<HostStoragePoolPhysicalDiskEntity>? PhysicalDisks { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreIfNull, JsonIgnore]
|
[BsonIgnoreIfNull, JsonIgnore]
|
||||||
public List<HostStoragePoolVirtualDiskEntity>? VirtualDisks { get; set; }
|
public List<HostStoragePoolVirtualDiskEntity>? VirtualDisks { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class HostStoragePoolVirtualDiskEntity
|
public class HostStoragePoolVirtualDiskEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_storagepool"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("storagepool")]
|
[BsonElement("_storagepool"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("storagepool")]
|
||||||
public string? StoragePool { get; set; }
|
public string? StoragePool { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("uniqueid")]
|
[BsonElement("uniqueid")]
|
||||||
public string? UniqueId { get; set; }
|
public string? UniqueId { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("health")]
|
[BsonElement("health")]
|
||||||
public string? Health { get; set; }
|
public string? Health { get; set; }
|
||||||
|
|
||||||
[BsonElement("access")]
|
[BsonElement("access")]
|
||||||
public string? Access { get; set; }
|
public string? Access { get; set; }
|
||||||
|
|
||||||
[BsonElement("provisioning")]
|
[BsonElement("provisioning")]
|
||||||
public string? Provisioning { get; set; }
|
public string? Provisioning { get; set; }
|
||||||
|
|
||||||
[BsonElement("redundancy")]
|
[BsonElement("redundancy")]
|
||||||
public uint? PhysicalRedundancy { get; set; }
|
public uint? PhysicalRedundancy { get; set; }
|
||||||
|
|
||||||
[BsonElement("resiliency")]
|
[BsonElement("resiliency")]
|
||||||
public string? Resiliency { get; set; }
|
public string? Resiliency { get; set; }
|
||||||
|
|
||||||
[BsonElement("deduplication")]
|
[BsonElement("deduplication")]
|
||||||
public bool? Deduplication { get; set; }
|
public bool? Deduplication { get; set; }
|
||||||
|
|
||||||
[BsonElement("snapshot")]
|
[BsonElement("snapshot")]
|
||||||
public bool? Snapshot { get; set; }
|
public bool? Snapshot { get; set; }
|
||||||
|
|
||||||
[BsonElement("size")]
|
[BsonElement("size")]
|
||||||
public ulong? Size { get; set; }
|
public ulong? Size { get; set; }
|
||||||
|
|
||||||
[BsonElement("size_allocated")]
|
[BsonElement("size_allocated")]
|
||||||
public ulong? AllocatedSize { get; set; }
|
public ulong? AllocatedSize { get; set; }
|
||||||
|
|
||||||
[BsonElement("footprint")]
|
[BsonElement("footprint")]
|
||||||
public ulong? Footprint { get; set; }
|
public ulong? Footprint { get; set; }
|
||||||
|
|
||||||
[BsonElement("cache_read_size")]
|
[BsonElement("cache_read_size")]
|
||||||
public ulong? ReadCacheSize { get; set; }
|
public ulong? ReadCacheSize { get; set; }
|
||||||
|
|
||||||
[BsonElement("cache_write_size")]
|
[BsonElement("cache_write_size")]
|
||||||
public ulong? WriteCacheSize { get; set; }
|
public ulong? WriteCacheSize { get; set; }
|
||||||
|
|
||||||
[BsonElement("states")]
|
[BsonElement("states")]
|
||||||
public List<string>? States { get; set; }
|
public List<string>? States { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class HostStoragePoolPhysicalDiskEntity
|
public class HostStoragePoolPhysicalDiskEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_storagepool"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("storagepool")]
|
[BsonElement("_storagepool"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("storagepool")]
|
||||||
public string? StoragePool { get; set; }
|
public string? StoragePool { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("uniqueid")]
|
[BsonElement("uniqueid")]
|
||||||
public string? UniqueId { get; set; }
|
public string? UniqueId { get; set; }
|
||||||
|
|
||||||
[BsonElement("deviceid")]
|
[BsonElement("deviceid")]
|
||||||
public string? DeviceId { get; set; }
|
public string? DeviceId { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("manufacturer")]
|
[BsonElement("manufacturer")]
|
||||||
public string? Manufacturer { get; set; }
|
public string? Manufacturer { get; set; }
|
||||||
|
|
||||||
[BsonElement("Model")]
|
[BsonElement("Model")]
|
||||||
public string? Model { get; set; }
|
public string? Model { get; set; }
|
||||||
|
|
||||||
[BsonElement("media")]
|
[BsonElement("media")]
|
||||||
public string? Media { get; set; }
|
public string? Media { get; set; }
|
||||||
|
|
||||||
[BsonElement("bus")]
|
[BsonElement("bus")]
|
||||||
public string? Bus { get; set; }
|
public string? Bus { get; set; }
|
||||||
|
|
||||||
[BsonElement("health")]
|
[BsonElement("health")]
|
||||||
public string? Health { get; set; }
|
public string? Health { get; set; }
|
||||||
|
|
||||||
[BsonElement("usage")]
|
[BsonElement("usage")]
|
||||||
public ushort? Usage { get; set; }
|
public ushort? Usage { get; set; }
|
||||||
|
|
||||||
[BsonElement("location")]
|
[BsonElement("location")]
|
||||||
public string? Location { get; set; }
|
public string? Location { get; set; }
|
||||||
|
|
||||||
[BsonElement("serial")]
|
[BsonElement("serial")]
|
||||||
public string? Serial { get; set; }
|
public string? Serial { get; set; }
|
||||||
|
|
||||||
[BsonElement("firmware")]
|
[BsonElement("firmware")]
|
||||||
public string? Firmware { get; set; }
|
public string? Firmware { get; set; }
|
||||||
|
|
||||||
[BsonElement("size")]
|
[BsonElement("size")]
|
||||||
public ulong? Size { get; set; }
|
public ulong? Size { get; set; }
|
||||||
|
|
||||||
[BsonElement("size_allocated")]
|
[BsonElement("size_allocated")]
|
||||||
public ulong? AllocatedSize { get; set; }
|
public ulong? AllocatedSize { get; set; }
|
||||||
|
|
||||||
[BsonElement("footprint")]
|
[BsonElement("footprint")]
|
||||||
public ulong? Footprint { get; set; }
|
public ulong? Footprint { get; set; }
|
||||||
|
|
||||||
[BsonElement("sector_size_physical")]
|
[BsonElement("sector_size_physical")]
|
||||||
public ulong? PhysicalSectorSize { get; set; }
|
public ulong? PhysicalSectorSize { get; set; }
|
||||||
|
|
||||||
[BsonElement("sector_size_logical")]
|
[BsonElement("sector_size_logical")]
|
||||||
public ulong? LogicalSectorSize { get; set; }
|
public ulong? LogicalSectorSize { get; set; }
|
||||||
|
|
||||||
[BsonElement("states")]
|
[BsonElement("states")]
|
||||||
public List<string>? States { get; set; }
|
public List<string>? States { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,33 +2,32 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostSystemEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostSystemEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("localtime")]
|
[BsonElement("localtime")]
|
||||||
public DateTime? LocalTime { get; set; }
|
public DateTime? LocalTime { get; set; }
|
||||||
|
|
||||||
[BsonElement("bootuptime")]
|
[BsonElement("bootuptime")]
|
||||||
public DateTime? BootUpTime { get; set; }
|
public DateTime? BootUpTime { get; set; }
|
||||||
|
|
||||||
[BsonElement("processes")]
|
[BsonElement("processes")]
|
||||||
public uint? Processes { get; set; }
|
public uint? Processes { get; set; }
|
||||||
|
|
||||||
[BsonElement("license")]
|
[BsonElement("license")]
|
||||||
public string? License { get; set; }
|
public string? License { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,60 +2,59 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostUpdateEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostUpdateEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("serial")]
|
[BsonElement("serial")]
|
||||||
public string? Serial { get; set; } // os update id
|
public string? Serial { get; set; } // os update id
|
||||||
|
|
||||||
[BsonElement("description")]
|
[BsonElement("description")]
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
[BsonElement("supporturl")]
|
[BsonElement("supporturl")]
|
||||||
public string? SupportUrl { get; set; }
|
public string? SupportUrl { get; set; }
|
||||||
|
|
||||||
[BsonElement("date")]
|
[BsonElement("date")]
|
||||||
public DateTime? Date { get; set; }
|
public DateTime? Date { get; set; }
|
||||||
|
|
||||||
[BsonElement("pending")]
|
[BsonElement("pending")]
|
||||||
public bool? Pending { get; set; }
|
public bool? Pending { get; set; }
|
||||||
|
|
||||||
[BsonElement("result"), BsonIgnoreIfNull] // installed only
|
[BsonElement("result"), BsonIgnoreIfNull] // installed only
|
||||||
public string? Result { get; set; }
|
public string? Result { get; set; }
|
||||||
|
|
||||||
[BsonElement("type"), BsonIgnoreIfNull] // pending only
|
[BsonElement("type"), BsonIgnoreIfNull] // pending only
|
||||||
public string? Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
[BsonElement("size"), BsonIgnoreIfNull] // pending only
|
[BsonElement("size"), BsonIgnoreIfNull] // pending only
|
||||||
public decimal? Size { get; set; }
|
public decimal? Size { get; set; }
|
||||||
|
|
||||||
[BsonElement("downloaded"), BsonIgnoreIfNull] // pending only
|
[BsonElement("downloaded"), BsonIgnoreIfNull] // pending only
|
||||||
public bool? IsDownloaded { get; set; }
|
public bool? IsDownloaded { get; set; }
|
||||||
|
|
||||||
[BsonElement("inputrequest"), BsonIgnoreIfNull] // pending only
|
[BsonElement("inputrequest"), BsonIgnoreIfNull] // pending only
|
||||||
public bool? CanRequestUserInput { get; set; }
|
public bool? CanRequestUserInput { get; set; }
|
||||||
|
|
||||||
[BsonElement("reboot"), BsonIgnoreIfNull] // pending only
|
[BsonElement("reboot"), BsonIgnoreIfNull] // pending only
|
||||||
public string? RebootBehavior { get; set; }
|
public string? RebootBehavior { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,119 +2,118 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostUserEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostUserEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("sid")]
|
[BsonElement("sid")]
|
||||||
public string? Sid { get; set; }
|
public string? Sid { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("domain")]
|
[BsonElement("domain")]
|
||||||
public string? Domain { get; set; }
|
public string? Domain { get; set; }
|
||||||
|
|
||||||
[BsonElement("fullname")]
|
[BsonElement("fullname")]
|
||||||
public string? FullName { get; set; }
|
public string? FullName { get; set; }
|
||||||
|
|
||||||
[BsonElement("description")]
|
[BsonElement("description")]
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
[BsonElement("status")]
|
[BsonElement("status")]
|
||||||
public string? Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
[BsonElement("localaccount")]
|
[BsonElement("localaccount")]
|
||||||
public bool? LocalAccount { get; set; }
|
public bool? LocalAccount { get; set; }
|
||||||
|
|
||||||
[BsonElement("disabled")]
|
[BsonElement("disabled")]
|
||||||
public bool? Disabled { get; set; }
|
public bool? Disabled { get; set; }
|
||||||
|
|
||||||
[BsonElement("lockout")]
|
[BsonElement("lockout")]
|
||||||
public bool? Lockout { get; set; }
|
public bool? Lockout { get; set; }
|
||||||
|
|
||||||
[BsonElement("password_changeable")]
|
[BsonElement("password_changeable")]
|
||||||
public bool? PasswordChangeable { get; set; }
|
public bool? PasswordChangeable { get; set; }
|
||||||
|
|
||||||
[BsonElement("password_expires")]
|
[BsonElement("password_expires")]
|
||||||
public bool? PasswordExpires { get; set; }
|
public bool? PasswordExpires { get; set; }
|
||||||
|
|
||||||
[BsonElement("password_required")]
|
[BsonElement("password_required")]
|
||||||
public bool? PasswordRequired { get; set; }
|
public bool? PasswordRequired { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class HostGroupEntity
|
public class HostGroupEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("sid")]
|
[BsonElement("sid")]
|
||||||
public string? Sid { get; set; }
|
public string? Sid { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("domain")]
|
[BsonElement("domain")]
|
||||||
public string? Domain { get; set; }
|
public string? Domain { get; set; }
|
||||||
|
|
||||||
[BsonElement("description")]
|
[BsonElement("description")]
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
[BsonElement("localaccount")]
|
[BsonElement("localaccount")]
|
||||||
public bool? LocalAccount { get; set; }
|
public bool? LocalAccount { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class HostUserGroupEntity
|
public class HostUserGroupEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_user"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("user")]
|
[BsonElement("_user"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("user")]
|
||||||
public string? User { get; set; }
|
public string? User { get; set; }
|
||||||
|
|
||||||
[BsonElement("_group"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("group")]
|
[BsonElement("_group"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("group")]
|
||||||
public string? Group { get; set; }
|
public string? Group { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,39 +2,38 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostVideocardEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostVideocardEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("company")]
|
[BsonElement("company")]
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("memory")]
|
[BsonElement("memory")]
|
||||||
public ulong? Memory { get; set; }
|
public ulong? Memory { get; set; }
|
||||||
|
|
||||||
[BsonElement("driver")]
|
[BsonElement("driver")]
|
||||||
public string? Driver { get; set; }
|
public string? Driver { get; set; }
|
||||||
|
|
||||||
[BsonElement("date")]
|
[BsonElement("date")]
|
||||||
public DateTime? Date { get; set; }
|
public DateTime? Date { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,75 +2,74 @@
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class HostVolumeEntity
|
||||||
{
|
{
|
||||||
[BsonIgnoreExtraElements]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public class HostVolumeEntity
|
public string? Id { get; set; }
|
||||||
{
|
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
[BsonElement("_host"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("host")]
|
||||||
public string? Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[BsonElement("_drive"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("drive")]
|
[BsonElement("_drive"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("drive")]
|
||||||
public string? Drive { get; set; }
|
public string? Drive { get; set; }
|
||||||
|
|
||||||
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
[BsonElement("_batch"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("batch")]
|
||||||
public string? Batch { get; set; }
|
public string? Batch { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
[BsonElement("index")]
|
[BsonElement("index")]
|
||||||
public uint? Index { get; set; }
|
public uint? Index { get; set; }
|
||||||
|
|
||||||
[BsonElement("label")]
|
[BsonElement("label")]
|
||||||
public string? Label { get; set; }
|
public string? Label { get; set; }
|
||||||
|
|
||||||
[BsonElement("name")]
|
[BsonElement("name")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[BsonElement("serial")]
|
[BsonElement("serial")]
|
||||||
public string? Serial { get; set; }
|
public string? Serial { get; set; }
|
||||||
|
|
||||||
[BsonElement("size")]
|
[BsonElement("size")]
|
||||||
public ulong? Size { get; set; }
|
public ulong? Size { get; set; }
|
||||||
|
|
||||||
[BsonElement("freespace")]
|
[BsonElement("freespace")]
|
||||||
public ulong? FreeSpace { get; set; }
|
public ulong? FreeSpace { get; set; }
|
||||||
|
|
||||||
[BsonElement("type")]
|
[BsonElement("type")]
|
||||||
public string? Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
[BsonElement("filesystem")]
|
[BsonElement("filesystem")]
|
||||||
public string? FileSystem { get; set; }
|
public string? FileSystem { get; set; }
|
||||||
|
|
||||||
[BsonElement("compressed")]
|
[BsonElement("compressed")]
|
||||||
public bool? Compressed { get; set; }
|
public bool? Compressed { get; set; }
|
||||||
|
|
||||||
[BsonElement("bootable")]
|
[BsonElement("bootable")]
|
||||||
public bool? Bootable { get; set; }
|
public bool? Bootable { get; set; }
|
||||||
|
|
||||||
[BsonElement("primary")]
|
[BsonElement("primary")]
|
||||||
public bool? Primary { get; set; }
|
public bool? Primary { get; set; }
|
||||||
|
|
||||||
[BsonElement("boot")]
|
[BsonElement("boot")]
|
||||||
public bool? Boot { get; set; }
|
public bool? Boot { get; set; }
|
||||||
|
|
||||||
[BsonElement("blocksize")]
|
[BsonElement("blocksize")]
|
||||||
public ulong? BlockSize { get; set; }
|
public ulong? BlockSize { get; set; }
|
||||||
|
|
||||||
[BsonElement("blocks")]
|
[BsonElement("blocks")]
|
||||||
public ulong? Blocks { get; set; }
|
public ulong? Blocks { get; set; }
|
||||||
|
|
||||||
[BsonElement("startoffset")]
|
[BsonElement("startoffset")]
|
||||||
public ulong? StartingOffset { get; set; }
|
public ulong? StartingOffset { get; set; }
|
||||||
|
|
||||||
[BsonElement("provider")]
|
[BsonElement("provider")]
|
||||||
public string? Provider { get; set; }
|
public string? Provider { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,96 +4,92 @@ using MongoDB.Bson.Serialization.Attributes;
|
||||||
using MongoDbGenericRepository.Attributes;
|
using MongoDbGenericRepository.Attributes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Entities
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
[CollectionName("user"), BsonIgnoreExtraElements]
|
||||||
|
public class InsightUser : MongoIdentityUser<ObjectId>
|
||||||
{
|
{
|
||||||
[CollectionName("user"), BsonIgnoreExtraElements]
|
public InsightUser() : base() { }
|
||||||
public class InsightUser : MongoIdentityUser<ObjectId>
|
|
||||||
{
|
|
||||||
public InsightUser() : base() { }
|
|
||||||
|
|
||||||
public InsightUser(string userName, string email) : base(userName, email) { }
|
public InsightUser(string userName, string email) : base(userName, email) { }
|
||||||
|
|
||||||
[JsonPropertyName("refresh_tokens")]
|
[JsonPropertyName("refresh_tokens")]
|
||||||
public List<RefreshToken>? RefreshTokens { get; set; }
|
public List<RefreshToken>? RefreshTokens { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonIgnoreExtraElements]
|
||||||
public class InsightUserLogEntity
|
public class InsightUserLogEntity
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_user"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("user")]
|
[BsonElement("_user"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("user")]
|
||||||
public string? User { get; set; }
|
public string? User { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("timestamp")]
|
[BsonElement("timestamp")]
|
||||||
public DateTime? Timestamp { get; set; }
|
public DateTime? Timestamp { get; set; }
|
||||||
|
|
||||||
[BsonElement("message")]
|
[BsonElement("message")]
|
||||||
public string? Message { get; set; }
|
public string? Message { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[CollectionName("user_pref"), BsonIgnoreExtraElements]
|
[CollectionName("user_pref"), BsonIgnoreExtraElements]
|
||||||
public class InsightUserPreferences
|
public class InsightUserPreferences
|
||||||
{
|
{
|
||||||
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[BsonElement("_user"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("user")]
|
[BsonElement("_user"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("user")]
|
||||||
public string? User { get; set; }
|
public string? User { get; set; }
|
||||||
|
|
||||||
[BsonElement("insert")]
|
[BsonElement("insert")]
|
||||||
public DateTime? Insert { get; set; }
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
[BsonElement("update")]
|
[BsonElement("update")]
|
||||||
public DateTime? Update { get; set; }
|
public DateTime? Update { get; set; }
|
||||||
|
[BsonElement("darkmode")]
|
||||||
|
public bool DarkMode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[BsonElement("darkmode")]
|
[CollectionName("role")]
|
||||||
public bool DarkMode { get; set; }
|
public class InsightRole : MongoIdentityRole<ObjectId>
|
||||||
}
|
{
|
||||||
|
|
||||||
[CollectionName("role")]
|
}
|
||||||
public class InsightRole : MongoIdentityRole<ObjectId>
|
|
||||||
{
|
|
||||||
public InsightRole() : base() { }
|
|
||||||
|
|
||||||
public InsightRole(string roleName) : base(roleName) { }
|
[BsonIgnoreExtraElements]
|
||||||
}
|
public class RefreshToken
|
||||||
|
{
|
||||||
|
[BsonElement("token")]
|
||||||
|
public string? Token { get; set; }
|
||||||
|
|
||||||
[BsonIgnoreExtraElements]
|
[BsonElement("created")]
|
||||||
public class RefreshToken
|
public DateTime Created { get; set; }
|
||||||
{
|
|
||||||
[BsonElement("token")]
|
|
||||||
public string? Token { get; set; }
|
|
||||||
|
|
||||||
[BsonElement("created")]
|
[BsonElement("created_ip")]
|
||||||
public DateTime Created { get; set; }
|
public string? CreatedByIp { get; set; }
|
||||||
|
|
||||||
[BsonElement("created_ip")]
|
[BsonElement("expires")]
|
||||||
public string? CreatedByIp { get; set; }
|
public DateTime Expires { get; set; }
|
||||||
|
|
||||||
[BsonElement("expires")]
|
[BsonElement("revoked")]
|
||||||
public DateTime Expires { get; set; }
|
public DateTime? Revoked { get; set; }
|
||||||
|
|
||||||
[BsonElement("revoked")]
|
[BsonElement("revoked_ip")]
|
||||||
public DateTime? Revoked { get; set; }
|
public string? RevokedByIp { get; set; }
|
||||||
|
|
||||||
[BsonElement("revoked_ip")]
|
[BsonElement("revoked_reason")]
|
||||||
public string? RevokedByIp { get; set; }
|
public string? ReasonRevoked { get; set; }
|
||||||
|
|
||||||
[BsonElement("revoked_reason")]
|
[BsonIgnore, JsonIgnore]
|
||||||
public string? ReasonRevoked { get; set; }
|
public bool IsExpired => DateTime.Now >= Expires.ToLocalTime();
|
||||||
|
|
||||||
[BsonIgnore, JsonIgnore]
|
[BsonIgnore, JsonIgnore]
|
||||||
public bool IsExpired => DateTime.Now >= Expires.ToLocalTime();
|
public bool IsRevoked => Revoked != null;
|
||||||
|
|
||||||
[BsonIgnore, JsonIgnore]
|
[BsonIgnore, JsonIgnore]
|
||||||
public bool IsRevoked => Revoked != null;
|
public bool IsActive => !IsRevoked && !IsExpired;
|
||||||
|
|
||||||
[BsonIgnore, JsonIgnore]
|
|
||||||
public bool IsActive => !IsRevoked && !IsExpired;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,46 +2,45 @@
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Extensions;
|
using Microsoft.AspNetCore.Http.Extensions;
|
||||||
|
|
||||||
namespace Insight.Infrastructure
|
namespace Insight.Infrastructure;
|
||||||
|
|
||||||
|
public static class HttpRequestExtensions
|
||||||
{
|
{
|
||||||
public static class HttpRequestExtensions
|
public static void AddPagination<TData>(this HttpRequest request, PagedList<TData> pagelist)
|
||||||
{
|
{
|
||||||
public static void AddPagination<TData>(this HttpRequest request, PagedList<TData> pagelist)
|
var builder = new QueryBuilder();
|
||||||
|
|
||||||
|
foreach (var item in request.Query.Where(p => p.Key.ToLower() != "limit" || p.Key.ToLower() != "offset"))
|
||||||
{
|
{
|
||||||
var builder = new QueryBuilder();
|
builder.Add(item.Key.ToLower(), item.Value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var item in request.Query.Where(p => p.Key.ToLower() != "limit" || p.Key.ToLower() != "offset"))
|
builder.Add("limit", pagelist.Meta.Limit.ToString());
|
||||||
|
|
||||||
|
if (pagelist.Meta.Offset > 0)
|
||||||
|
{
|
||||||
|
var qb = new QueryBuilder(builder);
|
||||||
|
|
||||||
|
if (pagelist.Meta.Offset > pagelist.Meta.Limit)
|
||||||
{
|
{
|
||||||
builder.Add(item.Key.ToLower(), item.Value.ToString());
|
qb.Add("offset", (pagelist.Meta.Offset - pagelist.Meta.Limit).ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qb.Add("offset", 0.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Add("limit", pagelist.Meta.Limit.ToString());
|
pagelist.Meta.Previous = $"{request.Scheme}://{request.Host}{request.PathBase}{request.Path}{qb}";
|
||||||
|
}
|
||||||
|
|
||||||
if (pagelist.Meta.Offset > 0)
|
if ((pagelist.Meta.Offset + pagelist.Meta.Count) < pagelist.Meta.Total)
|
||||||
|
{
|
||||||
|
var qb = new QueryBuilder(builder)
|
||||||
{
|
{
|
||||||
var qb = new QueryBuilder(builder);
|
{ "offset", (pagelist.Meta.Offset + pagelist.Meta.Count).ToString() }
|
||||||
|
};
|
||||||
|
|
||||||
if (pagelist.Meta.Offset > pagelist.Meta.Limit)
|
pagelist.Meta.Next = $"{request.Scheme}://{request.Host}{request.PathBase}{request.Path}{qb}";
|
||||||
{
|
|
||||||
qb.Add("offset", (pagelist.Meta.Offset - pagelist.Meta.Limit).ToString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qb.Add("offset", 0.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
pagelist.Meta.Previous = $"{request.Scheme}://{request.Host}{request.PathBase}{request.Path}{qb}";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pagelist.Meta.Offset + pagelist.Meta.Count) < pagelist.Meta.Total)
|
|
||||||
{
|
|
||||||
var qb = new QueryBuilder(builder)
|
|
||||||
{
|
|
||||||
{ "offset", (pagelist.Meta.Offset + pagelist.Meta.Count).ToString() }
|
|
||||||
};
|
|
||||||
|
|
||||||
pagelist.Meta.Next = $"{request.Scheme}://{request.Host}{request.PathBase}{request.Path}{qb}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,16 +2,15 @@
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Insight.Infrastructure
|
namespace Insight.Infrastructure;
|
||||||
|
|
||||||
|
public static class HttpResponseExtensions
|
||||||
{
|
{
|
||||||
public static class HttpResponseExtensions
|
public static void AddPagination<TData>(this HttpResponse response, PagedList<TData> pagelist)
|
||||||
{
|
{
|
||||||
public static void AddPagination<TData>(this HttpResponse response, PagedList<TData> pagelist)
|
response.Headers.Add("X-Pagination", JsonSerializer.Serialize(pagelist.Meta as PagedHeaderData, new JsonSerializerOptions
|
||||||
{
|
{
|
||||||
response.Headers.Add("X-Pagination", JsonSerializer.Serialize(pagelist.Meta as PagedHeaderData, new JsonSerializerOptions
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||||
{
|
}));
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,80 +4,79 @@ 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 class MongoCollectionExtensions
|
private const int _maximumLimit = 100;
|
||||||
|
|
||||||
|
public static async Task<PagedList<TData>> GetPagedAsync<TData>(
|
||||||
|
this IMongoCollection<TData> collection,
|
||||||
|
FilterDefinition<TData>? filter = null,
|
||||||
|
SortDefinition<TData>? sort = null,
|
||||||
|
int offset = 0,
|
||||||
|
int limit = 10,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
private const int _maximumLimit = 100;
|
if (limit > _maximumLimit) throw new InvalidOperationException("invalid limit value > 100");
|
||||||
|
|
||||||
public static async Task<PagedList<TData>> GetPagedAsync<TData>(
|
var query = collection.Find(filter ?? Builders<TData>.Filter.Empty);
|
||||||
this IMongoCollection<TData> collection,
|
|
||||||
FilterDefinition<TData>? filter = null,
|
|
||||||
SortDefinition<TData>? sort = null,
|
|
||||||
int offset = 0,
|
|
||||||
int limit = 10,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (limit > _maximumLimit) throw new InvalidOperationException("invalid limit value > 100");
|
|
||||||
|
|
||||||
var query = collection.Find(filter ?? Builders<TData>.Filter.Empty);
|
if (sort is not null) query = query.Sort(sort);
|
||||||
|
|
||||||
if (sort is not null) query = query.Sort(sort);
|
var data = await query.Skip(offset).Limit(limit).ToListAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
var total = await collection.EstimatedDocumentCountAsync(null, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var data = await query.Skip(offset).Limit(limit).ToListAsync(cancellationToken).ConfigureAwait(false);
|
return new PagedList<TData>(data, offset, limit, total);
|
||||||
var total = await collection.EstimatedDocumentCountAsync(null, cancellationToken).ConfigureAwait(false);
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
public static async Task<PagedList<TData>> GetPagedAsync<TData>(
|
request?.AddPagination(result);
|
||||||
this IMongoCollection<TData> collection,
|
response?.AddPagination(result);
|
||||||
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);
|
return result;
|
||||||
response?.AddPagination(result);
|
}
|
||||||
|
|
||||||
return result;
|
public static async Task<PagedList<TResult>> GetPagedAsync<TData, TResult>(
|
||||||
}
|
this IMongoCollection<TData> collection,
|
||||||
|
IAggregateFluent<BsonDocument> query,
|
||||||
|
int offset = 0,
|
||||||
|
int limit = 10,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
if (limit > _maximumLimit) throw new InvalidOperationException("invalid limit value");
|
||||||
|
|
||||||
public static async Task<PagedList<TResult>> GetPagedAsync<TData, TResult>(
|
var data = await query.Skip(offset).Limit(limit).ToListAsync(cancellationToken).ConfigureAwait(false);
|
||||||
this IMongoCollection<TData> collection,
|
var total = await collection.EstimatedDocumentCountAsync(null, cancellationToken).ConfigureAwait(false);
|
||||||
IAggregateFluent<BsonDocument> query,
|
|
||||||
int offset = 0,
|
|
||||||
int limit = 10,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (limit > _maximumLimit) throw new InvalidOperationException("invalid limit value");
|
|
||||||
|
|
||||||
var data = await query.Skip(offset).Limit(limit).ToListAsync(cancellationToken).ConfigureAwait(false);
|
return new PagedList<TResult>(data.Select(x => BsonSerializer.Deserialize<TResult>(x)), offset, limit, total);
|
||||||
var total = await collection.EstimatedDocumentCountAsync(null, cancellationToken).ConfigureAwait(false);
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
public static async Task<PagedList<TResult>> GetPagedAsync<TData, TResult>(
|
request?.AddPagination(result);
|
||||||
this IMongoCollection<TData> collection,
|
response?.AddPagination(result);
|
||||||
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);
|
return result;
|
||||||
response?.AddPagination(result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,57 +1,56 @@
|
||||||
using Insight.Infrastructure.Entities;
|
using Insight.Infrastructure.Entities;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
|
||||||
namespace Insight.Infrastructure
|
namespace Insight.Infrastructure;
|
||||||
|
|
||||||
|
public static class MongoDatabaseExtensions
|
||||||
{
|
{
|
||||||
public static class MongoDatabaseExtensions
|
// internal users (roles), groups...
|
||||||
{
|
public static IMongoCollection<InsightUser> User(this IMongoDatabase database) => database.GetCollection<InsightUser>("user");
|
||||||
// internal users (roles), groups...
|
public static IMongoCollection<InsightUserLogEntity> UserLog(this IMongoDatabase database) => database.GetCollection<InsightUserLogEntity>("user_log");
|
||||||
public static IMongoCollection<InsightUser> User(this IMongoDatabase database) => database.GetCollection<InsightUser>("user");
|
public static IMongoCollection<InsightUserPreferences> UserPreference(this IMongoDatabase database) => database.GetCollection<InsightUserPreferences>("user_pref");
|
||||||
public static IMongoCollection<InsightUserLogEntity> UserLog(this IMongoDatabase database) => database.GetCollection<InsightUserLogEntity>("user_log");
|
public static IMongoCollection<InsightRole> Role(this IMongoDatabase database) => database.GetCollection<InsightRole>("role");
|
||||||
public static IMongoCollection<InsightUserPreferences> UserPreference(this IMongoDatabase database) => database.GetCollection<InsightUserPreferences>("user_pref");
|
|
||||||
public static IMongoCollection<InsightRole> Role(this IMongoDatabase database) => database.GetCollection<InsightRole>("role");
|
|
||||||
|
|
||||||
// customers
|
// customers
|
||||||
public static IMongoCollection<CustomerEntity> Customer(this IMongoDatabase database) => database.GetCollection<CustomerEntity>("customer");
|
public static IMongoCollection<CustomerEntity> Customer(this IMongoDatabase database) => database.GetCollection<CustomerEntity>("customer");
|
||||||
|
|
||||||
// agents
|
// agents
|
||||||
public static IMongoCollection<AgentEntity> Agent(this IMongoDatabase database) => database.GetCollection<AgentEntity>("agent");
|
public static IMongoCollection<AgentEntity> Agent(this IMongoDatabase database) => database.GetCollection<AgentEntity>("agent");
|
||||||
public static IMongoCollection<AgentLogEntity> AgentLog(this IMongoDatabase database) => database.GetCollection<AgentLogEntity>("agent_log");
|
public static IMongoCollection<AgentLogEntity> AgentLog(this IMongoDatabase database) => database.GetCollection<AgentLogEntity>("agent_log");
|
||||||
|
|
||||||
// host groups
|
// host groups
|
||||||
public static IMongoCollection<HostEntity> HostGroup(this IMongoDatabase database) => database.GetCollection<HostEntity>("host");
|
public static IMongoCollection<HostEntity> HostGroup(this IMongoDatabase database) => database.GetCollection<HostEntity>("host");
|
||||||
|
|
||||||
// hosts
|
// hosts
|
||||||
public static IMongoCollection<HostEntity> Host(this IMongoDatabase database) => database.GetCollection<HostEntity>("host");
|
public static IMongoCollection<HostEntity> Host(this IMongoDatabase database) => database.GetCollection<HostEntity>("host");
|
||||||
public static IMongoCollection<HostLogEntity> HostLog(this IMongoDatabase database) => database.GetCollection<HostLogEntity>("host_log");
|
public static IMongoCollection<HostLogEntity> HostLog(this IMongoDatabase database) => database.GetCollection<HostLogEntity>("host_log");
|
||||||
|
|
||||||
// hosts extensions
|
// hosts extensions
|
||||||
public static IMongoCollection<HostLogMonitoringEntity> HostLogMonitoring(this IMongoDatabase database) => database.GetCollection<HostLogMonitoringEntity>("host_log_mon");
|
public static IMongoCollection<HostLogMonitoringEntity> HostLogMonitoring(this IMongoDatabase database) => database.GetCollection<HostLogMonitoringEntity>("host_log_mon");
|
||||||
public static IMongoCollection<HostApplicationEntity> HostApplication(this IMongoDatabase database) => database.GetCollection<HostApplicationEntity>("host_app");
|
public static IMongoCollection<HostApplicationEntity> HostApplication(this IMongoDatabase database) => database.GetCollection<HostApplicationEntity>("host_app");
|
||||||
public static IMongoCollection<HostDriveEntity> HostDrive(this IMongoDatabase database) => database.GetCollection<HostDriveEntity>("host_drv");
|
public static IMongoCollection<HostDriveEntity> HostDrive(this IMongoDatabase database) => database.GetCollection<HostDriveEntity>("host_drv");
|
||||||
public static IMongoCollection<HostVolumeEntity> HostVolume(this IMongoDatabase database) => database.GetCollection<HostVolumeEntity>("host_vol");
|
public static IMongoCollection<HostVolumeEntity> HostVolume(this IMongoDatabase database) => database.GetCollection<HostVolumeEntity>("host_vol");
|
||||||
public static IMongoCollection<HostOsEntity> HostOs(this IMongoDatabase database) => database.GetCollection<HostOsEntity>("host_os");
|
public static IMongoCollection<HostOsEntity> HostOs(this IMongoDatabase database) => database.GetCollection<HostOsEntity>("host_os");
|
||||||
public static IMongoCollection<HostUpdateEntity> HostUpdate(this IMongoDatabase database) => database.GetCollection<HostUpdateEntity>("host_upd");
|
public static IMongoCollection<HostUpdateEntity> HostUpdate(this IMongoDatabase database) => database.GetCollection<HostUpdateEntity>("host_upd");
|
||||||
public static IMongoCollection<HostSessionEntity> HostSession(this IMongoDatabase database) => database.GetCollection<HostSessionEntity>("host_session");
|
public static IMongoCollection<HostSessionEntity> HostSession(this IMongoDatabase database) => database.GetCollection<HostSessionEntity>("host_session");
|
||||||
public static IMongoCollection<HostServiceEntity> HostService(this IMongoDatabase database) => database.GetCollection<HostServiceEntity>("host_svc");
|
public static IMongoCollection<HostServiceEntity> HostService(this IMongoDatabase database) => database.GetCollection<HostServiceEntity>("host_svc");
|
||||||
public static IMongoCollection<HostPrinterEntity> HostPrinter(this IMongoDatabase database) => database.GetCollection<HostPrinterEntity>("host_prn");
|
public static IMongoCollection<HostPrinterEntity> HostPrinter(this IMongoDatabase database) => database.GetCollection<HostPrinterEntity>("host_prn");
|
||||||
public static IMongoCollection<HostMainboardEntity> HostMainboard(this IMongoDatabase database) => database.GetCollection<HostMainboardEntity>("host_board");
|
public static IMongoCollection<HostMainboardEntity> HostMainboard(this IMongoDatabase database) => database.GetCollection<HostMainboardEntity>("host_board");
|
||||||
public static IMongoCollection<HostProcessorEntity> HostProcessor(this IMongoDatabase database) => database.GetCollection<HostProcessorEntity>("host_cpu");
|
public static IMongoCollection<HostProcessorEntity> HostProcessor(this IMongoDatabase database) => database.GetCollection<HostProcessorEntity>("host_cpu");
|
||||||
public static IMongoCollection<HostMemoryEntity> HostMemory(this IMongoDatabase database) => database.GetCollection<HostMemoryEntity>("host_mem");
|
public static IMongoCollection<HostMemoryEntity> HostMemory(this IMongoDatabase database) => database.GetCollection<HostMemoryEntity>("host_mem");
|
||||||
public static IMongoCollection<HostVideocardEntity> HostVideocard(this IMongoDatabase database) => database.GetCollection<HostVideocardEntity>("host_gpu");
|
public static IMongoCollection<HostVideocardEntity> HostVideocard(this IMongoDatabase database) => database.GetCollection<HostVideocardEntity>("host_gpu");
|
||||||
public static IMongoCollection<HostUserEntity> HostSystemUser(this IMongoDatabase database) => database.GetCollection<HostUserEntity>("host_sysusr");
|
public static IMongoCollection<HostUserEntity> HostSystemUser(this IMongoDatabase database) => database.GetCollection<HostUserEntity>("host_sysusr");
|
||||||
public static IMongoCollection<HostGroupEntity> HostSystemGroup(this IMongoDatabase database) => database.GetCollection<HostGroupEntity>("host_sysgrp");
|
public static IMongoCollection<HostGroupEntity> HostSystemGroup(this IMongoDatabase database) => database.GetCollection<HostGroupEntity>("host_sysgrp");
|
||||||
public static IMongoCollection<HostUserGroupEntity> HostSystemUserSystemGroup(this IMongoDatabase database) => database.GetCollection<HostUserGroupEntity>("host_sysusr_sysgrp");
|
public static IMongoCollection<HostUserGroupEntity> HostSystemUserSystemGroup(this IMongoDatabase database) => database.GetCollection<HostUserGroupEntity>("host_sysusr_sysgrp");
|
||||||
public static IMongoCollection<HostSystemEntity> HostSystem(this IMongoDatabase database) => database.GetCollection<HostSystemEntity>("host_sys");
|
public static IMongoCollection<HostSystemEntity> HostSystem(this IMongoDatabase database) => database.GetCollection<HostSystemEntity>("host_sys");
|
||||||
public static IMongoCollection<HostStoragePoolEntity> HostStoragePool(this IMongoDatabase database) => database.GetCollection<HostStoragePoolEntity>("host_sp");
|
public static IMongoCollection<HostStoragePoolEntity> HostStoragePool(this IMongoDatabase database) => database.GetCollection<HostStoragePoolEntity>("host_sp");
|
||||||
public static IMongoCollection<HostStoragePoolPhysicalDiskEntity> HostStoragePoolPhysicalDisk(this IMongoDatabase database) => database.GetCollection<HostStoragePoolPhysicalDiskEntity>("host_sp.pd");
|
public static IMongoCollection<HostStoragePoolPhysicalDiskEntity> HostStoragePoolPhysicalDisk(this IMongoDatabase database) => database.GetCollection<HostStoragePoolPhysicalDiskEntity>("host_sp.pd");
|
||||||
public static IMongoCollection<HostStoragePoolVirtualDiskEntity> HostStoragePoolVirtualDisk(this IMongoDatabase database) => database.GetCollection<HostStoragePoolVirtualDiskEntity>("host_sp.vd");
|
public static IMongoCollection<HostStoragePoolVirtualDiskEntity> HostStoragePoolVirtualDisk(this IMongoDatabase database) => database.GetCollection<HostStoragePoolVirtualDiskEntity>("host_sp.vd");
|
||||||
public static IMongoCollection<HostHypervisorVirtualMaschineEntity> HostHypervisorVirtualMaschine(this IMongoDatabase database) => database.GetCollection<HostHypervisorVirtualMaschineEntity>("host_hv_vm");
|
public static IMongoCollection<HostHypervisorVirtualMaschineEntity> HostHypervisorVirtualMaschine(this IMongoDatabase database) => database.GetCollection<HostHypervisorVirtualMaschineEntity>("host_hv_vm");
|
||||||
public static IMongoCollection<HostHypervisorVirtualMaschineConfigEntity> HostVirtualMaschineConfig(this IMongoDatabase database) => database.GetCollection<HostHypervisorVirtualMaschineConfigEntity>("host_hv_vm_cfg");
|
public static IMongoCollection<HostHypervisorVirtualMaschineConfigEntity> HostVirtualMaschineConfig(this IMongoDatabase database) => database.GetCollection<HostHypervisorVirtualMaschineConfigEntity>("host_hv_vm_cfg");
|
||||||
public static IMongoCollection<HostInterfaceEntity> HostInterface(this IMongoDatabase database) => database.GetCollection<HostInterfaceEntity>("host_if");
|
public static IMongoCollection<HostInterfaceEntity> HostInterface(this IMongoDatabase database) => database.GetCollection<HostInterfaceEntity>("host_if");
|
||||||
public static IMongoCollection<HostInterfaceAddressEntity> HostInterfaceAddress(this IMongoDatabase database) => database.GetCollection<HostInterfaceAddressEntity>("host_if_addr");
|
public static IMongoCollection<HostInterfaceAddressEntity> HostInterfaceAddress(this IMongoDatabase database) => database.GetCollection<HostInterfaceAddressEntity>("host_if_addr");
|
||||||
public static IMongoCollection<HostInterfaceGatewayEntity> HostInterfaceGateway(this IMongoDatabase database) => database.GetCollection<HostInterfaceGatewayEntity>("host_if_gw");
|
public static IMongoCollection<HostInterfaceGatewayEntity> HostInterfaceGateway(this IMongoDatabase database) => database.GetCollection<HostInterfaceGatewayEntity>("host_if_gw");
|
||||||
public static IMongoCollection<HostInterfaceNameserverEntity> HostInterfaceNameserver(this IMongoDatabase database) => database.GetCollection<HostInterfaceNameserverEntity>("host_if_ns");
|
public static IMongoCollection<HostInterfaceNameserverEntity> HostInterfaceNameserver(this IMongoDatabase database) => database.GetCollection<HostInterfaceNameserverEntity>("host_if_ns");
|
||||||
public static IMongoCollection<HostInterfaceRouteEntity> HostInterfaceRoute(this IMongoDatabase database) => database.GetCollection<HostInterfaceRouteEntity>("host_if_rt");
|
public static IMongoCollection<HostInterfaceRouteEntity> HostInterfaceRoute(this IMongoDatabase database) => database.GetCollection<HostInterfaceRouteEntity>("host_if_rt");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -16,248 +16,247 @@ using MongoDB.Driver;
|
||||||
using MongoDB.Driver.Core.Configuration;
|
using MongoDB.Driver.Core.Configuration;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Insight.Infrastructure
|
namespace Insight.Infrastructure;
|
||||||
|
|
||||||
|
public static class ServiceExtensions
|
||||||
{
|
{
|
||||||
public static 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)
|
var connectionString = configuration.GetValue<string?>(Appsettings.Database) ?? throw new Exception($"{Appsettings.Database} value not set (appsettings)");
|
||||||
|
|
||||||
|
var settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
|
||||||
|
settings.ConnectTimeout = TimeSpan.FromSeconds(3);
|
||||||
|
settings.IPv6 = false;
|
||||||
|
|
||||||
|
if (loggerFactory is not null)
|
||||||
{
|
{
|
||||||
var connectionString = configuration.GetValue<string?>(Appsettings.Database) ?? throw new Exception($"{Appsettings.Database} value not set (appsettings)");
|
settings.LoggingSettings = new LoggingSettings(loggerFactory);
|
||||||
|
|
||||||
var settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
|
|
||||||
settings.ConnectTimeout = TimeSpan.FromSeconds(3);
|
|
||||||
settings.IPv6 = false;
|
|
||||||
|
|
||||||
if (loggerFactory is not null)
|
|
||||||
{
|
|
||||||
settings.LoggingSettings = new LoggingSettings(loggerFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
services.AddSingleton(new MongoClient(settings));
|
|
||||||
services.AddSingleton<IMongoClient>(provider => provider.GetRequiredService<MongoClient>());
|
|
||||||
return services.AddSingleton(provider => provider.GetRequiredService<MongoClient>().GetDatabase(Settings.Database));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddInfrastructureServices(this IServiceCollection services)
|
services.AddSingleton(new MongoClient(settings));
|
||||||
|
services.AddSingleton<IMongoClient>(provider => provider.GetRequiredService<MongoClient>());
|
||||||
|
return services.AddSingleton(provider => provider.GetRequiredService<MongoClient>().GetDatabase(Settings.Database));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddInfrastructureServices(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddTransient<IdentityService>();
|
||||||
|
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 =>
|
||||||
{
|
{
|
||||||
services.AddTransient<IdentityService>();
|
|
||||||
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)
|
})
|
||||||
|
.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 =>
|
||||||
{
|
{
|
||||||
var connectionString = configuration.GetValue<string?>(Appsettings.Database) ?? throw new Exception($"{Appsettings.Database} value not set (appsettings)");
|
options.DefaultScheme = "Custom";
|
||||||
|
options.DefaultChallengeScheme = "Custom";
|
||||||
services.AddIdentity<InsightUser, InsightRole>(options =>
|
})
|
||||||
{
|
.AddCookie("Cookies", 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(
|
//options.Cookie.Domain = "insight.webmatic.de";
|
||||||
key: configuration.GetValue<string?>(Appsettings.JwtKey) ?? throw new Exception($"{Appsettings.JwtKey} value not set (appsettings)"),
|
options.Cookie.Name = "insight";
|
||||||
expires: configuration.GetValue<int?>(Appsettings.JwtExp) ?? throw new Exception($"{Appsettings.JwtExp} value not set (appsettings)"),
|
options.LoginPath = "/account/login";
|
||||||
audience: configuration.GetValue<Uri?>(Appsettings.JwtAudience) ?? throw new Exception($"{Appsettings.JwtAudience} value not set (appsettings)"),
|
options.LogoutPath = "/account/logout";
|
||||||
issuer: configuration.GetValue<Uri?>(Appsettings.JwtIssuer) ?? throw new Exception($"{Appsettings.JwtIssuer} value not set (appsettings)"));
|
options.ExpireTimeSpan = TimeSpan.FromHours(1);
|
||||||
|
options.SlidingExpiration = true;
|
||||||
|
|
||||||
services.AddSingleton(options);
|
options.Events.OnRedirectToLogin = 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";
|
if (options.Request.Path.StartsWithSegments("/api") && options.Response.StatusCode == 200)
|
||||||
options.DefaultChallengeScheme = "Custom";
|
options.Response.StatusCode = 401;
|
||||||
})
|
else
|
||||||
.AddCookie("Cookies", options =>
|
options.Response.Redirect(options.RedirectUri);
|
||||||
{
|
|
||||||
//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 =>
|
return Task.CompletedTask;
|
||||||
{
|
|
||||||
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)
|
.AddJwtBearer("Bearer", options =>
|
||||||
.AddDefaultTokenProviders()
|
|
||||||
.AddSignInManager<InsightUser>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IServiceCollection AddIdentityAuthentication(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
{
|
||||||
services.AddAuthentication(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 =>
|
||||||
{
|
{
|
||||||
//options.DefaultAuthenticateScheme =
|
string authorization = context.Request.Headers[HeaderNames.Authorization];
|
||||||
});
|
|
||||||
//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.
|
if (!string.IsNullOrEmpty(authorization) && authorization.StartsWith("Bearer ")) return "Bearer";
|
||||||
// // ASP.NET picks a dumb name by default.
|
|
||||||
// options.Cookie.Name = "insight";
|
|
||||||
//});
|
|
||||||
|
|
||||||
return services;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,49 +1,48 @@
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Models
|
namespace Insight.Infrastructure.Models;
|
||||||
|
|
||||||
|
public class PagedList<T>
|
||||||
{
|
{
|
||||||
public class PagedList<T>
|
public PagedMetaData Meta { get; } = new();
|
||||||
{
|
public IEnumerable<T> Data { get; }
|
||||||
public PagedMetaData Meta { get; } = new();
|
|
||||||
public IEnumerable<T> Data { get; }
|
|
||||||
|
|
||||||
public PagedList(IEnumerable<T> data, int offset, int limit, long total)
|
public PagedList(IEnumerable<T> data, int offset, int limit, long total)
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
Meta = new()
|
||||||
{
|
{
|
||||||
Data = data;
|
Offset = offset,
|
||||||
Meta = new()
|
Limit = limit,
|
||||||
{
|
Count = data?.Count() ?? 0,
|
||||||
Offset = offset,
|
Total = total,
|
||||||
Limit = limit,
|
};
|
||||||
Count = data?.Count() ?? 0,
|
|
||||||
Total = total,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class PagedDataRequest
|
public class PagedDataRequest
|
||||||
{
|
{
|
||||||
[JsonPropertyName("offset")]
|
[JsonPropertyName("offset")]
|
||||||
public int Offset { get; set; } = 0;
|
public int Offset { get; set; } = 0;
|
||||||
|
|
||||||
[JsonPropertyName("limit")]
|
[JsonPropertyName("limit")]
|
||||||
public int Limit { get; set; } = 10;
|
public int Limit { get; set; } = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PagedHeaderData : PagedDataRequest
|
public class PagedHeaderData : PagedDataRequest
|
||||||
{
|
{
|
||||||
[JsonPropertyName("count")]
|
[JsonPropertyName("count")]
|
||||||
public int Count { get; set; } = 0;
|
public int Count { get; set; } = 0;
|
||||||
|
|
||||||
[JsonPropertyName("total")]
|
[JsonPropertyName("total")]
|
||||||
public long Total { get; set; } = 0;
|
public long Total { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PagedMetaData : PagedHeaderData
|
public class PagedMetaData : PagedHeaderData
|
||||||
{
|
{
|
||||||
[JsonPropertyName("next")]
|
[JsonPropertyName("next")]
|
||||||
public string? Next { get; set; }
|
public string? Next { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("previous")]
|
[JsonPropertyName("previous")]
|
||||||
public string? Previous { get; set; }
|
public string? Previous { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
namespace Insight.Infrastructure.Models
|
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)
|
public class TokenOptions
|
||||||
{
|
{
|
||||||
Key = key;
|
public string Key { get; set; }
|
||||||
Expires = expires;
|
public int Expires { get; set; }
|
||||||
Audience = audience;
|
public Uri? Audience { get; set; }
|
||||||
Issuer = issuer;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,33 +4,32 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Services
|
namespace Insight.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class AccountService
|
||||||
{
|
{
|
||||||
public class AccountService
|
private readonly IMongoDatabase _database;
|
||||||
|
private readonly ILogger<AccountService> _logger;
|
||||||
|
|
||||||
|
public AccountService(IMongoDatabase database, ILogger<AccountService> logger)
|
||||||
{
|
{
|
||||||
private readonly IMongoDatabase _database;
|
_database = database;
|
||||||
private readonly ILogger<AccountService> _logger;
|
_logger = 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
@ -4,33 +4,32 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Services
|
namespace Insight.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class AgentService
|
||||||
{
|
{
|
||||||
public class AgentService
|
private readonly IMongoDatabase _database;
|
||||||
|
private readonly ILogger<AgentService> _logger;
|
||||||
|
|
||||||
|
public AgentService(IMongoDatabase database, ILogger<AgentService> logger)
|
||||||
{
|
{
|
||||||
private readonly IMongoDatabase _database;
|
_database = database;
|
||||||
private readonly ILogger<AgentService> _logger;
|
_logger = 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
@ -5,108 +5,107 @@ using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Services
|
namespace Insight.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class AuthenticatorService
|
||||||
{
|
{
|
||||||
public class AuthenticatorService
|
private readonly IMongoDatabase _database;
|
||||||
|
private readonly UserManager<InsightUser> _userManager;
|
||||||
|
|
||||||
|
public AuthenticatorService(IMongoDatabase database, UserManager<InsightUser> userManager)
|
||||||
{
|
{
|
||||||
private readonly IMongoDatabase _database;
|
_database = database;
|
||||||
private readonly UserManager<InsightUser> _userManager;
|
_userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
public AuthenticatorService(IMongoDatabase database, UserManager<InsightUser> userManager)
|
public async Task<bool> GetStatusAsync(InsightUser user)
|
||||||
|
{
|
||||||
|
return await _userManager.GetTwoFactorEnabledAsync(user).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string?> GetKeyAsync(InsightUser user)
|
||||||
|
{
|
||||||
|
return await _userManager.GetAuthenticatorKeyAsync(user).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> ResetKeyAsync(InsightUser user)
|
||||||
|
{
|
||||||
|
var result = await _userManager.ResetAuthenticatorKeyAsync(user).ConfigureAwait(false);
|
||||||
|
return result.Succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> VerifyAsync(InsightUser user, string code)
|
||||||
|
{
|
||||||
|
code = code.Replace(" ", string.Empty).Replace("-", string.Empty);
|
||||||
|
return await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, code).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> EnableAsync(InsightUser user)
|
||||||
|
{
|
||||||
|
var result = await _userManager.SetTwoFactorEnabledAsync(user, true).ConfigureAwait(false);
|
||||||
|
return result.Succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DisableAsync(InsightUser user)
|
||||||
|
{
|
||||||
|
var result = await _userManager.SetTwoFactorEnabledAsync(user, false).ConfigureAwait(false);
|
||||||
|
return result.Succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DeleteAsync(InsightUser user)
|
||||||
|
{
|
||||||
|
var result = await _userManager.SetTwoFactorEnabledAsync(user, false).ConfigureAwait(false);
|
||||||
|
if (result.Succeeded is false) return false;
|
||||||
|
|
||||||
|
result = await _userManager.RemoveAuthenticationTokenAsync(user, "[AspNetUserStore]", "AuthenticatorKey").ConfigureAwait(false);
|
||||||
|
if (result.Succeeded is false) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> CountRecoveryCodesAsync(InsightUser user)
|
||||||
|
{
|
||||||
|
return await _userManager.CountRecoveryCodesAsync(user).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> UseRecoveryCodeAsync(InsightUser user, string recoveryCode)
|
||||||
|
{
|
||||||
|
var result = await _userManager.RedeemTwoFactorRecoveryCodeAsync(user, recoveryCode).ConfigureAwait(false);
|
||||||
|
return result.Succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<string>?> ResetRecoveryCodesAsync(InsightUser user, int count = 3)
|
||||||
|
{
|
||||||
|
return await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, count).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GenerateQrCode(string email, string unformattedKey)
|
||||||
|
{
|
||||||
|
var encoder = UrlEncoder.Default;
|
||||||
|
|
||||||
|
return string.Format(CultureInfo.InvariantCulture,
|
||||||
|
@"otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6",
|
||||||
|
encoder.Encode("Insight"),
|
||||||
|
encoder.Encode(email),
|
||||||
|
unformattedKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string HumanizeKey(string unformattedKey)
|
||||||
|
{
|
||||||
|
var result = new StringBuilder();
|
||||||
|
int currentPosition = 0;
|
||||||
|
|
||||||
|
while (currentPosition + 4 < unformattedKey.Length)
|
||||||
{
|
{
|
||||||
_database = database;
|
result.Append(unformattedKey.AsSpan(currentPosition, 4)).Append(' ');
|
||||||
_userManager = userManager;
|
currentPosition += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> GetStatusAsync(InsightUser user)
|
if (currentPosition < unformattedKey.Length)
|
||||||
{
|
{
|
||||||
return await _userManager.GetTwoFactorEnabledAsync(user).ConfigureAwait(false);
|
result.Append(unformattedKey.AsSpan(currentPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string?> GetKeyAsync(InsightUser user)
|
return result.ToString().ToLowerInvariant();
|
||||||
{
|
|
||||||
return await _userManager.GetAuthenticatorKeyAsync(user).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> ResetKeyAsync(InsightUser user)
|
|
||||||
{
|
|
||||||
var result = await _userManager.ResetAuthenticatorKeyAsync(user).ConfigureAwait(false);
|
|
||||||
return result.Succeeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> VerifyAsync(InsightUser user, string code)
|
|
||||||
{
|
|
||||||
code = code.Replace(" ", string.Empty).Replace("-", string.Empty);
|
|
||||||
return await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, code).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> EnableAsync(InsightUser user)
|
|
||||||
{
|
|
||||||
var result = await _userManager.SetTwoFactorEnabledAsync(user, true).ConfigureAwait(false);
|
|
||||||
return result.Succeeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> DisableAsync(InsightUser user)
|
|
||||||
{
|
|
||||||
var result = await _userManager.SetTwoFactorEnabledAsync(user, false).ConfigureAwait(false);
|
|
||||||
return result.Succeeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> DeleteAsync(InsightUser user)
|
|
||||||
{
|
|
||||||
var result = await _userManager.SetTwoFactorEnabledAsync(user, false).ConfigureAwait(false);
|
|
||||||
if (result.Succeeded is false) return false;
|
|
||||||
|
|
||||||
result = await _userManager.RemoveAuthenticationTokenAsync(user, "[AspNetUserStore]", "AuthenticatorKey").ConfigureAwait(false);
|
|
||||||
if (result.Succeeded is false) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> CountRecoveryCodesAsync(InsightUser user)
|
|
||||||
{
|
|
||||||
return await _userManager.CountRecoveryCodesAsync(user).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> UseRecoveryCodeAsync(InsightUser user, string recoveryCode)
|
|
||||||
{
|
|
||||||
var result = await _userManager.RedeemTwoFactorRecoveryCodeAsync(user, recoveryCode).ConfigureAwait(false);
|
|
||||||
return result.Succeeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<string>?> ResetRecoveryCodesAsync(InsightUser user, int count = 3)
|
|
||||||
{
|
|
||||||
return await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, count).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GenerateQrCode(string email, string unformattedKey)
|
|
||||||
{
|
|
||||||
var encoder = UrlEncoder.Default;
|
|
||||||
|
|
||||||
return string.Format(CultureInfo.InvariantCulture,
|
|
||||||
@"otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6",
|
|
||||||
encoder.Encode("Insight"),
|
|
||||||
encoder.Encode(email),
|
|
||||||
unformattedKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string HumanizeKey(string unformattedKey)
|
|
||||||
{
|
|
||||||
var result = new StringBuilder();
|
|
||||||
int currentPosition = 0;
|
|
||||||
|
|
||||||
while (currentPosition + 4 < unformattedKey.Length)
|
|
||||||
{
|
|
||||||
result.Append(unformattedKey.AsSpan(currentPosition, 4)).Append(' ');
|
|
||||||
currentPosition += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentPosition < unformattedKey.Length)
|
|
||||||
{
|
|
||||||
result.Append(unformattedKey.AsSpan(currentPosition));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.ToString().ToLowerInvariant();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,33 +4,32 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Services
|
namespace Insight.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class CustomerService
|
||||||
{
|
{
|
||||||
public class CustomerService
|
private readonly IMongoDatabase _database;
|
||||||
|
private readonly ILogger<CustomerService> _logger;
|
||||||
|
|
||||||
|
public CustomerService(IMongoDatabase database, ILogger<CustomerService> logger)
|
||||||
{
|
{
|
||||||
private readonly IMongoDatabase _database;
|
_database = database;
|
||||||
private readonly ILogger<CustomerService> _logger;
|
_logger = 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
@ -4,33 +4,32 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Services
|
namespace Insight.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class HostService
|
||||||
{
|
{
|
||||||
public class HostService
|
private readonly IMongoDatabase _database;
|
||||||
|
private readonly ILogger<HostService> _logger;
|
||||||
|
|
||||||
|
public HostService(IMongoDatabase database, ILogger<HostService> logger)
|
||||||
{
|
{
|
||||||
private readonly IMongoDatabase _database;
|
_database = database;
|
||||||
private readonly ILogger<HostService> _logger;
|
_logger = 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
@ -3,136 +3,135 @@ using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Services
|
namespace Insight.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class IdentityService
|
||||||
{
|
{
|
||||||
public class IdentityService
|
private readonly UserManager<InsightUser> _userManager;
|
||||||
|
private readonly RoleManager<InsightRole> _roleManager;
|
||||||
|
private readonly ILogger<IdentityService> _logger;
|
||||||
|
|
||||||
|
public IdentityService(UserManager<InsightUser> userManager, RoleManager<InsightRole> roleManager, ILogger<IdentityService> logger)
|
||||||
{
|
{
|
||||||
private readonly UserManager<InsightUser> _userManager;
|
_userManager = userManager;
|
||||||
private readonly RoleManager<InsightRole> _roleManager;
|
_roleManager = roleManager;
|
||||||
private readonly ILogger<IdentityService> _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public IdentityService(UserManager<InsightUser> userManager, RoleManager<InsightRole> roleManager, ILogger<IdentityService> logger)
|
public async Task SeedAsync()
|
||||||
|
{
|
||||||
|
// SEED ROLES
|
||||||
|
if (await _roleManager.FindByNameAsync("system") is not InsightRole systemRole)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
var result = await CreateRoleAsync("system");
|
||||||
_roleManager = roleManager;
|
if (result.Succeeded is false) throw new InvalidProgramException("seeding: system role failed");
|
||||||
_logger = logger;
|
|
||||||
|
systemRole = await _roleManager.FindByNameAsync("system") ?? throw new InvalidProgramException("seeding: system role failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SeedAsync()
|
if (await _roleManager.FindByNameAsync("administrator") is not InsightRole administratorRole)
|
||||||
{
|
{
|
||||||
// SEED ROLES
|
var result = await CreateRoleAsync("administrator");
|
||||||
if (await _roleManager.FindByNameAsync("system") is not InsightRole systemRole)
|
if (result.Succeeded is false) throw new InvalidProgramException("seeding: administrator role failed");
|
||||||
{
|
|
||||||
var result = await CreateRoleAsync("system");
|
|
||||||
if (result.Succeeded is false) throw new InvalidProgramException("seeding: system role failed");
|
|
||||||
|
|
||||||
systemRole = await _roleManager.FindByNameAsync("system") ?? throw new InvalidProgramException("seeding: system role failed");
|
administratorRole = await _roleManager.FindByNameAsync("administrator") ?? throw new InvalidProgramException("seeding: administrator role failed");
|
||||||
}
|
|
||||||
|
|
||||||
if (await _roleManager.FindByNameAsync("administrator") is not InsightRole administratorRole)
|
|
||||||
{
|
|
||||||
var result = await CreateRoleAsync("administrator");
|
|
||||||
if (result.Succeeded is false) throw new InvalidProgramException("seeding: administrator role failed");
|
|
||||||
|
|
||||||
administratorRole = await _roleManager.FindByNameAsync("administrator") ?? throw new InvalidProgramException("seeding: administrator role failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (await _roleManager.FindByNameAsync("chat") is not InsightRole chatRole)
|
|
||||||
{
|
|
||||||
var result = await CreateRoleAsync("chat");
|
|
||||||
if (result.Succeeded is false) throw new InvalidProgramException("seeding: chat role failed");
|
|
||||||
|
|
||||||
chatRole = await _roleManager.FindByNameAsync("chat") ?? throw new InvalidProgramException("seeding: chat role failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// SEED USERS
|
|
||||||
if (await _userManager.FindByEmailAsync("system@insight.local") is not InsightUser systemUser)
|
|
||||||
{
|
|
||||||
var result = await CreateUserAsync("system@insight.local", "Replica3-Unroasted-Respect");
|
|
||||||
if (result.Succeeded is false) throw new InvalidProgramException("seeding: system user failed");
|
|
||||||
|
|
||||||
systemUser = await _userManager.FindByEmailAsync("system@insight.local") ?? throw new InvalidProgramException("seeding: system user failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (systemUser.Roles.Any(p => p == systemRole.Id) is false)
|
|
||||||
{
|
|
||||||
var assign = await _userManager.AddToRoleAsync(systemUser, systemRole.Name);
|
|
||||||
if (assign.Succeeded is false) throw new InvalidProgramException("seeding: system user roles failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IdentityResult> CreateUserAsync(string email, string password)
|
if (await _roleManager.FindByNameAsync("chat") is not InsightRole chatRole)
|
||||||
{
|
{
|
||||||
var user = new InsightUser
|
var result = await CreateRoleAsync("chat");
|
||||||
{
|
if (result.Succeeded is false) throw new InvalidProgramException("seeding: chat role failed");
|
||||||
UserName = email,
|
|
||||||
NormalizedUserName = email.ToUpperInvariant(),
|
|
||||||
Email = email,
|
|
||||||
NormalizedEmail = email.ToUpperInvariant(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return await _userManager.CreateAsync(user, password);
|
chatRole = await _roleManager.FindByNameAsync("chat") ?? throw new InvalidProgramException("seeding: chat role failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IdentityResult> CreateRoleAsync(string name)
|
// SEED USERS
|
||||||
|
if (await _userManager.FindByEmailAsync("system@insight.local") is not InsightUser systemUser)
|
||||||
{
|
{
|
||||||
var role = new InsightRole
|
var result = await CreateUserAsync("system@insight.local", "Replica3-Unroasted-Respect");
|
||||||
{
|
if (result.Succeeded is false) throw new InvalidProgramException("seeding: system user failed");
|
||||||
Name = name,
|
|
||||||
NormalizedName = name.ToUpperInvariant()
|
|
||||||
};
|
|
||||||
|
|
||||||
return await _roleManager.CreateAsync(role);
|
systemUser = await _userManager.FindByEmailAsync("system@insight.local") ?? throw new InvalidProgramException("seeding: system user failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<InsightUser> LoginAsync(string email, string password, string? code = null)
|
if (systemUser.Roles.Any(p => p == systemRole.Id) is false)
|
||||||
{
|
{
|
||||||
if (await _userManager.FindByEmailAsync(email) is not InsightUser user) throw new InvalidDataException("Invalid Credentials");
|
var assign = await _userManager.AddToRoleAsync(systemUser, systemRole.Name);
|
||||||
if (await _userManager.CheckPasswordAsync(user, password) is false) throw new InvalidDataException("Invalid Credentials");
|
if (assign.Succeeded is false) throw new InvalidProgramException("seeding: system user roles failed");
|
||||||
|
|
||||||
if (await _userManager.GetTwoFactorEnabledAsync(user))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(code)) throw new InvalidOperationException("Requires 2FA Code");
|
|
||||||
|
|
||||||
var authCode = code.Replace(" ", string.Empty).Replace("-", string.Empty);
|
|
||||||
|
|
||||||
if (await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, authCode) is false)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Invalid 2FA Code");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> ChangePasswordAsync(InsightUser user, string current, string @new)
|
|
||||||
{
|
|
||||||
var result = await _userManager.ChangePasswordAsync(user, current, @new).ConfigureAwait(false);
|
|
||||||
return result.Succeeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<InsightUser?> GetByEmailAsync(string key)
|
|
||||||
{
|
|
||||||
var result = await _userManager.FindByEmailAsync(key).ConfigureAwait(false);
|
|
||||||
if (result is not null) return result;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IList<Claim>> GetClaimsAsync(InsightUser user, bool includeRoles = true)
|
|
||||||
{
|
|
||||||
var claims = await _userManager.GetClaimsAsync(user).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (includeRoles)
|
|
||||||
{
|
|
||||||
var roles = await _userManager.GetRolesAsync(user).ConfigureAwait(false);
|
|
||||||
foreach (var role in roles) claims.Add(new Claim(ClaimTypes.Role, role));
|
|
||||||
}
|
|
||||||
|
|
||||||
claims.Add(new Claim(ClaimTypes.Email, user.Email));
|
|
||||||
claims.Add(new Claim("user", user.UserName));
|
|
||||||
|
|
||||||
return claims;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IdentityResult> CreateUserAsync(string email, string password)
|
||||||
|
{
|
||||||
|
var user = new InsightUser
|
||||||
|
{
|
||||||
|
UserName = email,
|
||||||
|
NormalizedUserName = email.ToUpperInvariant(),
|
||||||
|
Email = email,
|
||||||
|
NormalizedEmail = email.ToUpperInvariant(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return await _userManager.CreateAsync(user, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IdentityResult> CreateRoleAsync(string name)
|
||||||
|
{
|
||||||
|
var role = new InsightRole
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
NormalizedName = name.ToUpperInvariant()
|
||||||
|
};
|
||||||
|
|
||||||
|
return await _roleManager.CreateAsync(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<InsightUser> LoginAsync(string email, string password, string? code = null)
|
||||||
|
{
|
||||||
|
if (await _userManager.FindByEmailAsync(email) is not InsightUser user) throw new InvalidDataException("Invalid Credentials");
|
||||||
|
if (await _userManager.CheckPasswordAsync(user, password) is false) throw new InvalidDataException("Invalid Credentials");
|
||||||
|
|
||||||
|
if (await _userManager.GetTwoFactorEnabledAsync(user))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(code)) throw new InvalidOperationException("Requires 2FA Code");
|
||||||
|
|
||||||
|
var authCode = code.Replace(" ", string.Empty).Replace("-", string.Empty);
|
||||||
|
|
||||||
|
if (await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, authCode) is false)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException("Invalid 2FA Code");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> ChangePasswordAsync(InsightUser user, string current, string @new)
|
||||||
|
{
|
||||||
|
var result = await _userManager.ChangePasswordAsync(user, current, @new).ConfigureAwait(false);
|
||||||
|
return result.Succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<InsightUser?> GetByEmailAsync(string key)
|
||||||
|
{
|
||||||
|
var result = await _userManager.FindByEmailAsync(key).ConfigureAwait(false);
|
||||||
|
if (result is not null) return result;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IList<Claim>> GetClaimsAsync(InsightUser user, bool includeRoles = true)
|
||||||
|
{
|
||||||
|
var claims = await _userManager.GetClaimsAsync(user).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (includeRoles)
|
||||||
|
{
|
||||||
|
var roles = await _userManager.GetRolesAsync(user).ConfigureAwait(false);
|
||||||
|
foreach (var role in roles) claims.Add(new Claim(ClaimTypes.Role, role));
|
||||||
|
}
|
||||||
|
|
||||||
|
claims.Add(new Claim(ClaimTypes.Email, user.Email));
|
||||||
|
claims.Add(new Claim("user", user.UserName));
|
||||||
|
|
||||||
|
return claims;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,33 +4,32 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Services
|
namespace Insight.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class InventoryService
|
||||||
{
|
{
|
||||||
public class InventoryService
|
private readonly IMongoDatabase _database;
|
||||||
|
private readonly ILogger<InventoryService> _logger;
|
||||||
|
|
||||||
|
public InventoryService(IMongoDatabase database, ILogger<InventoryService> logger)
|
||||||
{
|
{
|
||||||
private readonly IMongoDatabase _database;
|
_database = database;
|
||||||
private readonly ILogger<InventoryService> _logger;
|
_logger = 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
@ -8,142 +8,141 @@ using System.Net;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Insight.Infrastructure.Services
|
namespace Insight.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class TokenService
|
||||||
{
|
{
|
||||||
public class TokenService
|
private readonly TokenOptions _options;
|
||||||
|
private readonly IdentityService _identityService;
|
||||||
|
private readonly IMongoDatabase _database;
|
||||||
|
|
||||||
|
public TokenService(TokenOptions options, IdentityService identityService, IMongoDatabase database)
|
||||||
{
|
{
|
||||||
private readonly TokenOptions _options;
|
_options = options;
|
||||||
private readonly IdentityService _identityService;
|
_identityService = identityService;
|
||||||
private readonly IMongoDatabase _database;
|
_database = database;
|
||||||
|
}
|
||||||
|
|
||||||
public TokenService(TokenOptions options, IdentityService identityService, IMongoDatabase database)
|
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 accessToken = await CreateAccessTokenAsync(user, ipa).ConfigureAwait(false);
|
||||||
|
var refreshToken = await CreateRefreshTokenAsync(user, ipa).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return new TokenResponse
|
||||||
{
|
{
|
||||||
_options = options;
|
AccessToken = accessToken.Item1,
|
||||||
_identityService = identityService;
|
ExpireInSeconds = accessToken.Item2,
|
||||||
_database = database;
|
RefreshToken = refreshToken.Item1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TokenResponse> RefreshAsync(string refreshToken, IPAddress? ipa = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(refreshToken)) throw new ArgumentNullException(nameof(refreshToken));
|
||||||
|
|
||||||
|
var user = await _database.User().Find(p => p.RefreshTokens.Any(t => t.Token == refreshToken)).FirstOrDefaultAsync();
|
||||||
|
if (user is null || user.RefreshTokens is null) throw new InvalidDataException("Invalid Refresh Token");
|
||||||
|
|
||||||
|
var token = user.RefreshTokens.First(p => p.Token == refreshToken);
|
||||||
|
|
||||||
|
if (token.IsRevoked)
|
||||||
|
{
|
||||||
|
// todo: revoke all descendant tokens in case this token has been compromised
|
||||||
|
throw new InvalidDataException("Invalid Refresh Token");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TokenResponse> GetAsync(string email, string password, string? code = null, IPAddress? ipa = null)
|
if (token.IsActive is false)
|
||||||
{
|
{
|
||||||
var user = await _identityService.LoginAsync(email, password, code).ConfigureAwait(false);
|
throw new InvalidDataException("Invalid Refresh Token");
|
||||||
|
}
|
||||||
|
|
||||||
var accessToken = await CreateAccessTokenAsync(user, ipa).ConfigureAwait(false);
|
// remove actual refresh token
|
||||||
var refreshToken = await CreateRefreshTokenAsync(user, ipa).ConfigureAwait(false);
|
user.RefreshTokens.Remove(token);
|
||||||
|
|
||||||
return new TokenResponse
|
// remove old refresh tokens from user
|
||||||
|
user.RefreshTokens.RemoveAll(p => p.IsExpired && p.IsRevoked is false);
|
||||||
|
|
||||||
|
// update users refreshTokens
|
||||||
|
await _database.User().UpdateOneAsync(Builders<InsightUser>
|
||||||
|
.Filter.Eq(p => p.UserName, user.UserName), Builders<InsightUser>
|
||||||
|
.Update.Set(p => p.RefreshTokens, user.RefreshTokens));
|
||||||
|
|
||||||
|
// create new refresh token
|
||||||
|
var newRefreshToken = await CreateRefreshTokenAsync(user, ipa).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// create access token
|
||||||
|
var accessToken = await CreateAccessTokenAsync(user, ipa).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return new TokenResponse
|
||||||
|
{
|
||||||
|
AccessToken = accessToken.Item1,
|
||||||
|
ExpireInSeconds = accessToken.Item2,
|
||||||
|
RefreshToken = newRefreshToken.Item1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RevokeAsync(string refreshToken, string reason, IPAddress? ipa = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(refreshToken)) throw new ArgumentNullException(nameof(refreshToken));
|
||||||
|
|
||||||
|
var user = await _database.User().Find(p => p.RefreshTokens.Any(t => t.Token == refreshToken)).FirstOrDefaultAsync();
|
||||||
|
if (user is null || user.RefreshTokens is null) throw new InvalidDataException("Invalid Refresh Token");
|
||||||
|
|
||||||
|
var token = user.RefreshTokens.First(p => p.Token == refreshToken);
|
||||||
|
|
||||||
|
if (token.IsActive is false)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException("Invalid Refresh Token");
|
||||||
|
}
|
||||||
|
|
||||||
|
token.Revoked = DateTime.Now;
|
||||||
|
token.RevokedByIp = ipa?.ToString();
|
||||||
|
token.ReasonRevoked = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(string, int)> CreateAccessTokenAsync(InsightUser user, IPAddress? ipa = null)
|
||||||
|
{
|
||||||
|
var claims = await _identityService.GetClaimsAsync(user).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var key = Encoding.UTF8.GetBytes(_options.Key);
|
||||||
|
var secret = new SymmetricSecurityKey(key);
|
||||||
|
var signing = new SigningCredentials(secret, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
var securityToken = new JwtSecurityToken(
|
||||||
|
_options.Issuer?.ToString(),
|
||||||
|
_options.Audience?.ToString(),
|
||||||
|
claims,
|
||||||
|
DateTime.Now,
|
||||||
|
DateTime.Now.AddSeconds(Convert.ToDouble(_options.Expires)),
|
||||||
|
signing);
|
||||||
|
|
||||||
|
var token = new JwtSecurityTokenHandler().WriteToken(securityToken);
|
||||||
|
|
||||||
|
return (token, (int)TimeSpan.FromMinutes(Convert.ToDouble(_options.Expires)).TotalSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(string, int)> CreateRefreshTokenAsync(InsightUser user, IPAddress? ipa = null)
|
||||||
|
{
|
||||||
|
var randomNumber = new byte[32];
|
||||||
|
|
||||||
|
using var rng = RandomNumberGenerator.Create();
|
||||||
|
rng.GetBytes(randomNumber);
|
||||||
|
|
||||||
|
var refreshToken = Convert.ToBase64String(randomNumber);
|
||||||
|
|
||||||
|
await _database.User()
|
||||||
|
.UpdateOneAsync(Builders<InsightUser>
|
||||||
|
.Filter.Eq(p => p.UserName, user.UserName), Builders<InsightUser>
|
||||||
|
.Update.AddToSet(p => p.RefreshTokens, new RefreshToken
|
||||||
{
|
{
|
||||||
AccessToken = accessToken.Item1,
|
Token = refreshToken,
|
||||||
ExpireInSeconds = accessToken.Item2,
|
Created = DateTime.Now,
|
||||||
RefreshToken = refreshToken.Item1
|
Expires = DateTime.Now.AddMinutes(30), // change offset to config based
|
||||||
};
|
CreatedByIp = ipa?.ToString()
|
||||||
}
|
}));
|
||||||
|
|
||||||
public async Task<TokenResponse> RefreshAsync(string refreshToken, IPAddress? ipa = null)
|
return (refreshToken, (int)TimeSpan.FromMinutes(30).TotalSeconds);
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(refreshToken)) throw new ArgumentNullException(nameof(refreshToken));
|
|
||||||
|
|
||||||
var user = await _database.User().Find(p => p.RefreshTokens.Any(t => t.Token == refreshToken)).FirstOrDefaultAsync();
|
|
||||||
if (user is null || user.RefreshTokens is null) throw new InvalidDataException("Invalid Refresh Token");
|
|
||||||
|
|
||||||
var token = user.RefreshTokens.First(p => p.Token == refreshToken);
|
|
||||||
|
|
||||||
if (token.IsRevoked)
|
|
||||||
{
|
|
||||||
// todo: revoke all descendant tokens in case this token has been compromised
|
|
||||||
throw new InvalidDataException("Invalid Refresh Token");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.IsActive is false)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Invalid Refresh Token");
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove actual refresh token
|
|
||||||
user.RefreshTokens.Remove(token);
|
|
||||||
|
|
||||||
// remove old refresh tokens from user
|
|
||||||
user.RefreshTokens.RemoveAll(p => p.IsExpired && p.IsRevoked is false);
|
|
||||||
|
|
||||||
// update users refreshTokens
|
|
||||||
await _database.User().UpdateOneAsync(Builders<InsightUser>
|
|
||||||
.Filter.Eq(p => p.UserName, user.UserName), Builders<InsightUser>
|
|
||||||
.Update.Set(p => p.RefreshTokens, user.RefreshTokens));
|
|
||||||
|
|
||||||
// create new refresh token
|
|
||||||
var newRefreshToken = await CreateRefreshTokenAsync(user, ipa).ConfigureAwait(false);
|
|
||||||
|
|
||||||
// create access token
|
|
||||||
var accessToken = await CreateAccessTokenAsync(user, ipa).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return new TokenResponse
|
|
||||||
{
|
|
||||||
AccessToken = accessToken.Item1,
|
|
||||||
ExpireInSeconds = accessToken.Item2,
|
|
||||||
RefreshToken = newRefreshToken.Item1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RevokeAsync(string refreshToken, string reason, IPAddress? ipa = null)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(refreshToken)) throw new ArgumentNullException(nameof(refreshToken));
|
|
||||||
|
|
||||||
var user = await _database.User().Find(p => p.RefreshTokens.Any(t => t.Token == refreshToken)).FirstOrDefaultAsync();
|
|
||||||
if (user is null || user.RefreshTokens is null) throw new InvalidDataException("Invalid Refresh Token");
|
|
||||||
|
|
||||||
var token = user.RefreshTokens.First(p => p.Token == refreshToken);
|
|
||||||
|
|
||||||
if (token.IsActive is false)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Invalid Refresh Token");
|
|
||||||
}
|
|
||||||
|
|
||||||
token.Revoked = DateTime.Now;
|
|
||||||
token.RevokedByIp = ipa?.ToString();
|
|
||||||
token.ReasonRevoked = reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<(string, int)> CreateAccessTokenAsync(InsightUser user, IPAddress? ipa = null)
|
|
||||||
{
|
|
||||||
var claims = await _identityService.GetClaimsAsync(user).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var key = Encoding.UTF8.GetBytes(_options.Key);
|
|
||||||
var secret = new SymmetricSecurityKey(key);
|
|
||||||
var signing = new SigningCredentials(secret, SecurityAlgorithms.HmacSha256);
|
|
||||||
|
|
||||||
var securityToken = new JwtSecurityToken(
|
|
||||||
_options.Issuer?.ToString(),
|
|
||||||
_options.Audience?.ToString(),
|
|
||||||
claims,
|
|
||||||
DateTime.Now,
|
|
||||||
DateTime.Now.AddSeconds(Convert.ToDouble(_options.Expires)),
|
|
||||||
signing);
|
|
||||||
|
|
||||||
var token = new JwtSecurityTokenHandler().WriteToken(securityToken);
|
|
||||||
|
|
||||||
return (token, (int)TimeSpan.FromMinutes(Convert.ToDouble(_options.Expires)).TotalSeconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<(string, int)> CreateRefreshTokenAsync(InsightUser user, IPAddress? ipa = null)
|
|
||||||
{
|
|
||||||
var randomNumber = new byte[32];
|
|
||||||
|
|
||||||
using var rng = RandomNumberGenerator.Create();
|
|
||||||
rng.GetBytes(randomNumber);
|
|
||||||
|
|
||||||
var refreshToken = Convert.ToBase64String(randomNumber);
|
|
||||||
|
|
||||||
await _database.User()
|
|
||||||
.UpdateOneAsync(Builders<InsightUser>
|
|
||||||
.Filter.Eq(p => p.UserName, user.UserName), Builders<InsightUser>
|
|
||||||
.Update.AddToSet(p => p.RefreshTokens, new RefreshToken
|
|
||||||
{
|
|
||||||
Token = refreshToken,
|
|
||||||
Created = DateTime.Now,
|
|
||||||
Expires = DateTime.Now.AddMinutes(30), // change offset to config based
|
|
||||||
CreatedByIp = ipa?.ToString()
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (refreshToken, (int)TimeSpan.FromMinutes(30).TotalSeconds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
namespace Insight.Server
|
namespace Insight.Server;
|
||||||
{
|
|
||||||
internal static class Appsettings
|
|
||||||
{
|
|
||||||
internal const string AgentServerPort = "agent.server.port";
|
|
||||||
internal const string AgentServerCertificate = "agent.server.certificate";
|
|
||||||
internal const string AgentServerCertificatePassword = "agent.server.certificate.password";
|
|
||||||
internal const string DispatchWebmatic = "dispatch.webmatic";
|
|
||||||
|
|
||||||
internal const string WebServerPort = "web.server.port";
|
internal static class Appsettings
|
||||||
internal const string WebServerCertificate = "web.server.certificate";
|
{
|
||||||
internal const string WebServerCertificatePassword = "web.server.certificate.password";
|
internal const string AgentServerPort = "agent.server.port";
|
||||||
}
|
internal const string AgentServerCertificate = "agent.server.certificate";
|
||||||
|
internal const string AgentServerCertificatePassword = "agent.server.certificate.password";
|
||||||
|
internal const string DispatchWebmatic = "dispatch.webmatic";
|
||||||
|
|
||||||
|
internal const string WebServerPort = "web.server.port";
|
||||||
|
internal const string WebServerCertificate = "web.server.certificate";
|
||||||
|
internal const string WebServerCertificatePassword = "web.server.certificate.password";
|
||||||
}
|
}
|
||||||
|
|
@ -1,53 +1,52 @@
|
||||||
using System.Threading.Tasks.Dataflow;
|
using System.Threading.Tasks.Dataflow;
|
||||||
|
|
||||||
namespace Insight.Server.Extensions
|
namespace Insight.Server.Extensions;
|
||||||
|
|
||||||
|
public static class Async
|
||||||
{
|
{
|
||||||
public static class Async
|
public static async Task ParallelForEach<T>(
|
||||||
|
this IAsyncEnumerable<T> source,
|
||||||
|
Func<T, Task> body,
|
||||||
|
int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
|
||||||
|
TaskScheduler scheduler = null)
|
||||||
{
|
{
|
||||||
public static async Task ParallelForEach<T>(
|
var options = new ExecutionDataflowBlockOptions
|
||||||
this IAsyncEnumerable<T> source,
|
|
||||||
Func<T, Task> body,
|
|
||||||
int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
|
|
||||||
TaskScheduler scheduler = null)
|
|
||||||
{
|
{
|
||||||
var options = new ExecutionDataflowBlockOptions
|
MaxDegreeOfParallelism = maxDegreeOfParallelism
|
||||||
{
|
};
|
||||||
MaxDegreeOfParallelism = maxDegreeOfParallelism
|
|
||||||
};
|
|
||||||
|
|
||||||
if (scheduler != null)
|
if (scheduler != null)
|
||||||
options.TaskScheduler = scheduler;
|
options.TaskScheduler = scheduler;
|
||||||
|
|
||||||
var block = new ActionBlock<T>(body, options);
|
var block = new ActionBlock<T>(body, options);
|
||||||
|
|
||||||
await foreach (var item in source)
|
await foreach (var item in source)
|
||||||
block.Post(item);
|
block.Post(item);
|
||||||
|
|
||||||
block.Complete();
|
block.Complete();
|
||||||
await block.Completion;
|
await block.Completion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task ParallelForEach<T>(
|
public static async Task ParallelForEach<T>(
|
||||||
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
|
MaxDegreeOfParallelism = maxDegreeOfParallelism
|
||||||
{
|
};
|
||||||
MaxDegreeOfParallelism = maxDegreeOfParallelism
|
|
||||||
};
|
|
||||||
|
|
||||||
if (scheduler != null)
|
if (scheduler != null)
|
||||||
options.TaskScheduler = scheduler;
|
options.TaskScheduler = scheduler;
|
||||||
|
|
||||||
var block = new ActionBlock<T>(body, options);
|
var block = new ActionBlock<T>(body, options);
|
||||||
|
|
||||||
foreach (var item in source)
|
foreach (var item in source)
|
||||||
block.Post(item);
|
block.Post(item);
|
||||||
|
|
||||||
block.Complete();
|
block.Complete();
|
||||||
await block.Completion;
|
await block.Completion;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace Insight.Server.Extensions
|
namespace Insight.Server.Extensions;
|
||||||
|
|
||||||
|
public static class ConfigurationExtensions
|
||||||
{
|
{
|
||||||
public static class ConfigurationExtensions
|
public static IConfigurationBuilder Defaults(this IConfigurationBuilder configuration)
|
||||||
{
|
{
|
||||||
public static IConfigurationBuilder Defaults(this IConfigurationBuilder configuration)
|
configuration.Sources.Clear();
|
||||||
{
|
configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
||||||
configuration.Sources.Clear();
|
return configuration.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
|
||||||
configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
|
||||||
return configuration.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,49 +1,48 @@
|
||||||
namespace Insight.Setup.Constants
|
namespace Insight.Setup.Constants;
|
||||||
|
|
||||||
|
public static class Deploy
|
||||||
{
|
{
|
||||||
public static class Deploy
|
public static class Runtime
|
||||||
{
|
{
|
||||||
public static class Runtime
|
public static class Core
|
||||||
{
|
{
|
||||||
public static class Core
|
public const string Version = "7.0.2";
|
||||||
{
|
public const string Download = "https://download.visualstudio.microsoft.com/download/pr/df7da01f-1f17-4728-92b7-778e9607da8f/7c18246830f8c78591f02f25aa368dcf/dotnet-runtime-7.0.2-win-x64.exe";
|
||||||
public const string Version = "7.0.2";
|
|
||||||
public const string Download = "https://download.visualstudio.microsoft.com/download/pr/df7da01f-1f17-4728-92b7-778e9607da8f/7c18246830f8c78591f02f25aa368dcf/dotnet-runtime-7.0.2-win-x64.exe";
|
|
||||||
|
|
||||||
public static DirectoryInfo Directory => new DirectoryInfo($@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)}/dotnet/shared/Microsoft.NETCore.App");
|
public static DirectoryInfo Directory => new DirectoryInfo($@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)}/dotnet/shared/Microsoft.NETCore.App");
|
||||||
}
|
|
||||||
|
|
||||||
public static class Asp
|
|
||||||
{
|
|
||||||
public const string Version = "7.0.2";
|
|
||||||
public const string Download = "https://download.visualstudio.microsoft.com/download/pr/3ecad4f7-1342-4688-ae4a-38908c61f4a2/391a9010acad2e312e3d1e766bedfac7/aspnetcore-runtime-7.0.2-win-x64.exe";
|
|
||||||
|
|
||||||
public static DirectoryInfo Directory => new DirectoryInfo($@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)}/dotnet/shared/Microsoft.AspNetCore.App");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Updater
|
public static class Asp
|
||||||
{
|
{
|
||||||
public const string Name = "Updater";
|
public const string Version = "7.0.2";
|
||||||
public const string ServiceName = "insight_updater";
|
public const string Download = "https://download.visualstudio.microsoft.com/download/pr/3ecad4f7-1342-4688-ae4a-38908c61f4a2/391a9010acad2e312e3d1e766bedfac7/aspnetcore-runtime-7.0.2-win-x64.exe";
|
||||||
public const string Description = "Insight Updater";
|
|
||||||
|
|
||||||
public static Uri UpdateHref(Uri api) => new($"{api.AbsoluteUri}/{Name}/windows");
|
public static DirectoryInfo Directory => new DirectoryInfo($@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)}/dotnet/shared/Microsoft.AspNetCore.App");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Agent
|
|
||||||
{
|
|
||||||
public const string Name = "Agent";
|
|
||||||
public const string ServiceName = "insight_agent";
|
|
||||||
public const string Description = "Insight Agent";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DirectoryInfo GetAppDirectory(string appName)
|
|
||||||
=> new($"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}/Webmatic/Insight/{appName}");
|
|
||||||
|
|
||||||
public static FileInfo GetAppExecutable(string appName)
|
|
||||||
=> new($"{GetAppDirectory(appName).FullName}/{appName.ToLower()}.exe");
|
|
||||||
|
|
||||||
public static Uri GetUpdateHref(Uri api, string appName)
|
|
||||||
=> new($"{api.AbsoluteUri}/update/{appName.ToLower()}/windows");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Updater
|
||||||
|
{
|
||||||
|
public const string Name = "Updater";
|
||||||
|
public const string ServiceName = "insight_updater";
|
||||||
|
public const string Description = "Insight Updater";
|
||||||
|
|
||||||
|
public static Uri UpdateHref(Uri api) => new($"{api.AbsoluteUri}/{Name}/windows");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Agent
|
||||||
|
{
|
||||||
|
public const string Name = "Agent";
|
||||||
|
public const string ServiceName = "insight_agent";
|
||||||
|
public const string Description = "Insight Agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DirectoryInfo GetAppDirectory(string appName)
|
||||||
|
=> new($"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}/Webmatic/Insight/{appName}");
|
||||||
|
|
||||||
|
public static FileInfo GetAppExecutable(string appName)
|
||||||
|
=> new($"{GetAppDirectory(appName).FullName}/{appName.ToLower()}.exe");
|
||||||
|
|
||||||
|
public static Uri GetUpdateHref(Uri api, string appName)
|
||||||
|
=> new($"{api.AbsoluteUri}/update/{appName.ToLower()}/windows");
|
||||||
}
|
}
|
||||||
|
|
@ -5,54 +5,53 @@ using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Insight.Setup.Windows
|
namespace Insight.Setup.Windows;
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
internal class Program
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("windows")]
|
public static async Task Main(string[] args)
|
||||||
public class Program
|
|
||||||
{
|
{
|
||||||
public static async Task Main(string[] args)
|
await Host.CreateDefaultBuilder(args)
|
||||||
{
|
.ConfigureAppConfiguration(options =>
|
||||||
await Host.CreateDefaultBuilder(args)
|
{
|
||||||
.ConfigureAppConfiguration(options =>
|
options.Sources.Clear();
|
||||||
|
options.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
||||||
|
options.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
|
||||||
|
|
||||||
|
options.AddCommandLine(args, new Dictionary<string, string>()
|
||||||
{
|
{
|
||||||
options.Sources.Clear();
|
{ "-deploy", "deploy" },
|
||||||
options.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
{ "--deploy", "deploy" }
|
||||||
options.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
|
});
|
||||||
|
})
|
||||||
|
.ConfigureLogging(options =>
|
||||||
|
{
|
||||||
|
options.ClearProviders();
|
||||||
|
options.SetMinimumLevel(LogLevel.Trace);
|
||||||
|
|
||||||
options.AddCommandLine(args, new Dictionary<string, string>()
|
options.AddSimpleConsole(options =>
|
||||||
{
|
|
||||||
{ "-deploy", "deploy" },
|
|
||||||
{ "--deploy", "deploy" }
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.ConfigureLogging(options =>
|
|
||||||
{
|
{
|
||||||
options.ClearProviders();
|
options.IncludeScopes = true;
|
||||||
options.SetMinimumLevel(LogLevel.Trace);
|
options.SingleLine = true;
|
||||||
|
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
||||||
|
});
|
||||||
|
|
||||||
options.AddSimpleConsole(options =>
|
options.AddFilter("Microsoft", LogLevel.Warning);
|
||||||
{
|
})
|
||||||
options.IncludeScopes = true;
|
.ConfigureServices((host, services) =>
|
||||||
options.SingleLine = true;
|
{
|
||||||
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
// SERVICES
|
||||||
});
|
services.AddHostedService<SetupService>();
|
||||||
|
|
||||||
options.AddFilter("Microsoft", LogLevel.Warning);
|
// GLOBALS
|
||||||
})
|
services.AddTransient(provider => new HttpClient(new HttpClientHandler
|
||||||
.ConfigureServices((host, services) =>
|
|
||||||
{
|
{
|
||||||
// SERVICES
|
ClientCertificateOptions = ClientCertificateOption.Manual,
|
||||||
services.AddHostedService<SetupService>();
|
ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true
|
||||||
|
}));
|
||||||
// GLOBALS
|
})
|
||||||
services.AddTransient(provider => new HttpClient(new HttpClientHandler
|
.Build()
|
||||||
{
|
.RunAsync();
|
||||||
ClientCertificateOptions = ClientCertificateOption.Manual,
|
|
||||||
ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true
|
|
||||||
}));
|
|
||||||
})
|
|
||||||
.Build()
|
|
||||||
.RunAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,472 +6,471 @@ using System.Runtime.Versioning;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Insight.Setup.Services
|
namespace Insight.Setup.Services;
|
||||||
|
|
||||||
|
public static class Deployment
|
||||||
{
|
{
|
||||||
public static class Deployment
|
[SupportedOSPlatform("windows")]
|
||||||
|
public static class Windows
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("windows")]
|
public static class Service
|
||||||
public static class Windows
|
|
||||||
{
|
{
|
||||||
public static class Service
|
private static bool ServiceExistence(string serviceName)
|
||||||
{
|
{
|
||||||
private static bool ServiceExistence(string serviceName)
|
try
|
||||||
{
|
{
|
||||||
try
|
if (ServiceController.GetServices().Any(s => s.ServiceName.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase))) return true;
|
||||||
{
|
|
||||||
if (ServiceController.GetServices().Any(s => s.ServiceName.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase))) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
private static bool SetServiceState(string app, ServiceControllerStatus status, TimeSpan timeout)
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool SetServiceState(string app, ServiceControllerStatus status, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
using var sc = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName.Equals(app, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
if (sc is null) return false;
|
||||||
|
|
||||||
|
if (sc.Status != status)
|
||||||
{
|
{
|
||||||
using var sc = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName.Equals(app, StringComparison.InvariantCultureIgnoreCase));
|
switch (status)
|
||||||
if (sc is null) return false;
|
|
||||||
|
|
||||||
if (sc.Status != status)
|
|
||||||
{
|
{
|
||||||
switch (status)
|
case ServiceControllerStatus.Running:
|
||||||
{
|
sc.Start();
|
||||||
case ServiceControllerStatus.Running:
|
break;
|
||||||
sc.Start();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ServiceControllerStatus.Stopped:
|
case ServiceControllerStatus.Stopped:
|
||||||
sc.Stop();
|
sc.Stop();
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
sc.WaitForStatus(status, timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
sc.WaitForStatus(status, timeout);
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async ValueTask<bool> InstallAsync(FileInfo bin, string serviceName, string displayName, string description, bool autorun)
|
||||||
|
{
|
||||||
|
if (bin.Exists is false) return false;
|
||||||
|
if (ServiceExistence(serviceName)) return false;
|
||||||
|
|
||||||
|
var args = @$"/C sc create {serviceName} binPath= ""{bin.FullName}"" DisplayName= ""{displayName}""";
|
||||||
|
args += $@" && sc description {serviceName} ""{description}""";
|
||||||
|
args += $@" && sc config {serviceName} start= {(autorun ? "auto" : "demand")}";
|
||||||
|
args += $@" && sc start {serviceName}";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var process = new System.Diagnostics.Process()
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
WindowStyle = ProcessWindowStyle.Normal,
|
||||||
|
FileName = "cmd.exe",
|
||||||
|
Arguments = args,
|
||||||
|
Verb = "runas",
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
UseShellExecute = false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
|
||||||
|
var output = await process.StandardOutput.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (Directory.GetParent(bin.FullName) is not DirectoryInfo serviceDir) return false;
|
||||||
|
|
||||||
|
return ServiceExistence(serviceName); // may return output as return model if existence false
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async ValueTask<bool> InstallAsync(FileInfo bin, string serviceName, string displayName, string description, bool autorun)
|
|
||||||
{
|
|
||||||
if (bin.Exists is false) return false;
|
|
||||||
if (ServiceExistence(serviceName)) return false;
|
|
||||||
|
|
||||||
var args = @$"/C sc create {serviceName} binPath= ""{bin.FullName}"" DisplayName= ""{displayName}""";
|
|
||||||
args += $@" && sc description {serviceName} ""{description}""";
|
|
||||||
args += $@" && sc config {serviceName} start= {(autorun ? "auto" : "demand")}";
|
|
||||||
args += $@" && sc start {serviceName}";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var process = new System.Diagnostics.Process()
|
|
||||||
{
|
|
||||||
StartInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
WindowStyle = ProcessWindowStyle.Normal,
|
|
||||||
FileName = "cmd.exe",
|
|
||||||
Arguments = args,
|
|
||||||
Verb = "runas",
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
UseShellExecute = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
process.Start();
|
|
||||||
|
|
||||||
var output = await process.StandardOutput.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (Directory.GetParent(bin.FullName) is not DirectoryInfo serviceDir) return false;
|
|
||||||
|
|
||||||
return ServiceExistence(serviceName); // may return output as return model if existence false
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async ValueTask<InstallResult> InstallAsync(HttpClient httpClient, Uri api, FileInfo bin, string serviceName, string serviceDisplayName, string serviceDescription, bool autorun, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var result = new InstallResult
|
|
||||||
{
|
|
||||||
Api = api?.ToString(),
|
|
||||||
SourceDirectory = bin.Directory?.FullName,
|
|
||||||
App = bin.Name,
|
|
||||||
ServiceName = serviceName,
|
|
||||||
Autorun = autorun
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (ServiceExistence(serviceName))
|
|
||||||
{
|
|
||||||
result.Errors.Add("Service already installed");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api, cancellationToken);
|
|
||||||
if (response is null)
|
|
||||||
{
|
|
||||||
result.ApiErrors.Add("not available / response null");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get update file (bytes) to memory
|
|
||||||
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
|
||||||
if (update is null)
|
|
||||||
{
|
|
||||||
result.ApiErrors.Add("update source not available");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.ApiAvailable = true;
|
|
||||||
|
|
||||||
// read update archive to temp (overwrite)
|
|
||||||
var temp = Directory.CreateTempSubdirectory();
|
|
||||||
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
|
||||||
|
|
||||||
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
|
||||||
|
|
||||||
// extract update archive from temp to app dir (overwrite)
|
|
||||||
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
|
||||||
|
|
||||||
// delete temp folder
|
|
||||||
if (temp.Exists) temp.Delete(true);
|
|
||||||
|
|
||||||
// install service with windows api
|
|
||||||
if (await InstallAsync(bin, serviceName, serviceDisplayName, serviceDescription, autorun) is false)
|
|
||||||
{
|
|
||||||
result.Errors.Add("installation failed");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Success = true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
result.Errors.Add(ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async ValueTask<UpdateResult> UpdateAsync(HttpClient httpClient, Uri api, FileInfo bin, string serviceName, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var result = new UpdateResult
|
|
||||||
{
|
|
||||||
Api = api?.ToString(),
|
|
||||||
SourceDirectory = bin.Directory?.FullName,
|
|
||||||
App = bin.Name,
|
|
||||||
ServiceName = serviceName
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// check if service exists
|
|
||||||
if (ServiceExistence(serviceName) is false)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add("service not found");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get service update details
|
|
||||||
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api, cancellationToken);
|
|
||||||
if (response is null)
|
|
||||||
{
|
|
||||||
result.ApiErrors.Add("not available / response null");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.ApiAvailable = true;
|
|
||||||
|
|
||||||
// check if local binary exists
|
|
||||||
if (bin is null)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add("source binary not found");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get local file binary version
|
|
||||||
if (FileVersionInfo.GetVersionInfo(bin.FullName).FileVersion is not string binVersionString)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add("source binary fileversion not valid");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compare local against update version, skip lower or equal update version
|
|
||||||
var actualVersion = Version.Parse(binVersionString);
|
|
||||||
if (actualVersion >= response.Version)
|
|
||||||
{
|
|
||||||
result.Success = true;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.UpdateAvailable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get update file (bytes) to memory
|
|
||||||
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
|
||||||
if (update is null)
|
|
||||||
{
|
|
||||||
result.ApiErrors.Add("update source not available");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop service
|
|
||||||
if (SetServiceState(serviceName, ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10)) is false)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add("service control failed / failed to stop service");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read update archive to temp (overwrite)
|
|
||||||
var temp = Directory.CreateTempSubdirectory();
|
|
||||||
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
|
||||||
|
|
||||||
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
|
||||||
|
|
||||||
// extract update archive from temp to app dir (overwrite)
|
|
||||||
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
|
||||||
|
|
||||||
// delete temp folder
|
|
||||||
if (temp.Exists) temp.Delete(true);
|
|
||||||
|
|
||||||
// start updateds service
|
|
||||||
if (SetServiceState(serviceName, ServiceControllerStatus.Running, TimeSpan.FromSeconds(10)) is false)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add("service control failed / failed to start service");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Success = true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add(ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async ValueTask<UninstallResult> UninstallAsync(string serviceName)
|
|
||||||
{
|
|
||||||
var result = new UninstallResult
|
|
||||||
{
|
|
||||||
ServiceName = serviceName
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (ServiceExistence(serviceName) is false)
|
|
||||||
{
|
|
||||||
result.Errors.Add("service not found");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SetServiceState(serviceName, ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60)) is false)
|
|
||||||
{
|
|
||||||
result.Errors.Add("service control failed / failed to stop service");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
using var process = new System.Diagnostics.Process()
|
|
||||||
{
|
|
||||||
StartInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
WindowStyle = ProcessWindowStyle.Normal,
|
|
||||||
FileName = "cmd.exe",
|
|
||||||
Arguments = $"/C sc delete {serviceName}",
|
|
||||||
Verb = "runas",
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
UseShellExecute = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
process.Start();
|
|
||||||
|
|
||||||
var output = await process.StandardOutput.ReadToEndAsync();
|
|
||||||
|
|
||||||
// may return output as return model if existence true
|
|
||||||
|
|
||||||
if (ServiceExistence(serviceName))
|
|
||||||
{
|
|
||||||
result.Errors.Add("service still existing");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Success = true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
result.Errors.Add(ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Process
|
public static async ValueTask<InstallResult> InstallAsync(HttpClient httpClient, Uri api, FileInfo bin, string serviceName, string serviceDisplayName, string serviceDescription, bool autorun, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
public static bool IsRunning(FileInfo bin)
|
var result = new InstallResult
|
||||||
{
|
{
|
||||||
if (bin.Exists is false) return false;
|
Api = api?.ToString(),
|
||||||
|
SourceDirectory = bin.Directory?.FullName,
|
||||||
|
App = bin.Name,
|
||||||
|
ServiceName = serviceName,
|
||||||
|
Autorun = autorun
|
||||||
|
};
|
||||||
|
|
||||||
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
|
try
|
||||||
|
|
||||||
if (matched is null || matched.Any() is false) return false;
|
|
||||||
|
|
||||||
if (matched.Any(p =>
|
|
||||||
p.MainModule is not null &&
|
|
||||||
p.MainModule.FileName is not null &&
|
|
||||||
p.MainModule.FileName.Equals(bin.FullName,
|
|
||||||
StringComparison.InvariantCultureIgnoreCase))) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Start(FileInfo binary)
|
|
||||||
{
|
{
|
||||||
try
|
if (ServiceExistence(serviceName))
|
||||||
{
|
{
|
||||||
if (IsRunning(binary) is false) return false;
|
result.Errors.Add("Service already installed");
|
||||||
|
return result;
|
||||||
using var process = System.Diagnostics.Process.Start(binary.FullName);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api, cancellationToken);
|
||||||
|
if (response is null)
|
||||||
|
{
|
||||||
|
result.ApiErrors.Add("not available / response null");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get update file (bytes) to memory
|
||||||
|
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
||||||
|
if (update is null)
|
||||||
|
{
|
||||||
|
result.ApiErrors.Add("update source not available");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.ApiAvailable = true;
|
||||||
|
|
||||||
|
// read update archive to temp (overwrite)
|
||||||
|
var temp = Directory.CreateTempSubdirectory();
|
||||||
|
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
||||||
|
|
||||||
|
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
||||||
|
|
||||||
|
// extract update archive from temp to app dir (overwrite)
|
||||||
|
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
||||||
|
|
||||||
|
// delete temp folder
|
||||||
|
if (temp.Exists) temp.Delete(true);
|
||||||
|
|
||||||
|
// install service with windows api
|
||||||
|
if (await InstallAsync(bin, serviceName, serviceDisplayName, serviceDescription, autorun) is false)
|
||||||
|
{
|
||||||
|
result.Errors.Add("installation failed");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Success = true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
result.Errors.Add(ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Stop(FileInfo bin, TimeSpan timeout)
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async ValueTask<UpdateResult> UpdateAsync(HttpClient httpClient, Uri api, FileInfo bin, string serviceName, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = new UpdateResult
|
||||||
{
|
{
|
||||||
try
|
Api = api?.ToString(),
|
||||||
|
SourceDirectory = bin.Directory?.FullName,
|
||||||
|
App = bin.Name,
|
||||||
|
ServiceName = serviceName
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// check if service exists
|
||||||
|
if (ServiceExistence(serviceName) is false)
|
||||||
{
|
{
|
||||||
if (IsRunning(bin) is false) return false;
|
result.UpdateErrors.Add("service not found");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
|
// get service update details
|
||||||
|
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api, cancellationToken);
|
||||||
|
if (response is null)
|
||||||
|
{
|
||||||
|
result.ApiErrors.Add("not available / response null");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (matched is null || matched.Any() is false) return true;
|
result.ApiAvailable = true;
|
||||||
|
|
||||||
foreach (var procsInfo in matched.Where(p =>
|
// check if local binary exists
|
||||||
p.MainModule is not null &&
|
if (bin is null)
|
||||||
p.MainModule.FileName is not null &&
|
{
|
||||||
p.MainModule.FileName.Equals(bin.FullName, StringComparison.InvariantCultureIgnoreCase)))
|
result.UpdateErrors.Add("source binary not found");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get local file binary version
|
||||||
|
if (FileVersionInfo.GetVersionInfo(bin.FullName).FileVersion is not string binVersionString)
|
||||||
|
{
|
||||||
|
result.UpdateErrors.Add("source binary fileversion not valid");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare local against update version, skip lower or equal update version
|
||||||
|
var actualVersion = Version.Parse(binVersionString);
|
||||||
|
if (actualVersion >= response.Version)
|
||||||
|
{
|
||||||
|
result.Success = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.UpdateAvailable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get update file (bytes) to memory
|
||||||
|
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
||||||
|
if (update is null)
|
||||||
|
{
|
||||||
|
result.ApiErrors.Add("update source not available");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop service
|
||||||
|
if (SetServiceState(serviceName, ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10)) is false)
|
||||||
|
{
|
||||||
|
result.UpdateErrors.Add("service control failed / failed to stop service");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read update archive to temp (overwrite)
|
||||||
|
var temp = Directory.CreateTempSubdirectory();
|
||||||
|
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
||||||
|
|
||||||
|
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
||||||
|
|
||||||
|
// extract update archive from temp to app dir (overwrite)
|
||||||
|
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
||||||
|
|
||||||
|
// delete temp folder
|
||||||
|
if (temp.Exists) temp.Delete(true);
|
||||||
|
|
||||||
|
// start updateds service
|
||||||
|
if (SetServiceState(serviceName, ServiceControllerStatus.Running, TimeSpan.FromSeconds(10)) is false)
|
||||||
|
{
|
||||||
|
result.UpdateErrors.Add("service control failed / failed to start service");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Success = true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
result.UpdateErrors.Add(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async ValueTask<UninstallResult> UninstallAsync(string serviceName)
|
||||||
|
{
|
||||||
|
var result = new UninstallResult
|
||||||
|
{
|
||||||
|
ServiceName = serviceName
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (ServiceExistence(serviceName) is false)
|
||||||
|
{
|
||||||
|
result.Errors.Add("service not found");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SetServiceState(serviceName, ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60)) is false)
|
||||||
|
{
|
||||||
|
result.Errors.Add("service control failed / failed to stop service");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var process = new System.Diagnostics.Process()
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
if (procsInfo.CloseMainWindow()) procsInfo.WaitForExit((int)timeout.TotalMilliseconds);
|
WindowStyle = ProcessWindowStyle.Normal,
|
||||||
if (procsInfo.HasExited is false) procsInfo.Kill(true);
|
FileName = "cmd.exe",
|
||||||
|
Arguments = $"/C sc delete {serviceName}",
|
||||||
|
Verb = "runas",
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
UseShellExecute = false
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return true;
|
process.Start();
|
||||||
|
|
||||||
|
var output = await process.StandardOutput.ReadToEndAsync();
|
||||||
|
|
||||||
|
// may return output as return model if existence true
|
||||||
|
|
||||||
|
if (ServiceExistence(serviceName))
|
||||||
|
{
|
||||||
|
result.Errors.Add("service still existing");
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
result.Success = true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
result.Errors.Add(ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async ValueTask<bool> UpdateAsync(HttpClient httpClient, Uri api, FileInfo bin, CancellationToken cancellationToken)
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Process
|
||||||
|
{
|
||||||
|
public static bool IsRunning(FileInfo bin)
|
||||||
|
{
|
||||||
|
if (bin.Exists is false) return false;
|
||||||
|
|
||||||
|
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
|
||||||
|
|
||||||
|
if (matched is null || matched.Any() is false) return false;
|
||||||
|
|
||||||
|
if (matched.Any(p =>
|
||||||
|
p.MainModule is not null &&
|
||||||
|
p.MainModule.FileName is not null &&
|
||||||
|
p.MainModule.FileName.Equals(bin.FullName,
|
||||||
|
StringComparison.InvariantCultureIgnoreCase))) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Start(FileInfo binary)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (IsRunning(binary) is false) return false;
|
||||||
|
|
||||||
|
using var process = System.Diagnostics.Process.Start(binary.FullName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Stop(FileInfo bin, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (IsRunning(bin) is false) return false;
|
if (IsRunning(bin) is false) return false;
|
||||||
|
|
||||||
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api.AbsoluteUri, new JsonSerializerOptions
|
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
|
||||||
|
|
||||||
|
if (matched is null || matched.Any() is false) return true;
|
||||||
|
|
||||||
|
foreach (var procsInfo in matched.Where(p =>
|
||||||
|
p.MainModule is not null &&
|
||||||
|
p.MainModule.FileName is not null &&
|
||||||
|
p.MainModule.FileName.Equals(bin.FullName, StringComparison.InvariantCultureIgnoreCase)))
|
||||||
{
|
{
|
||||||
IncludeFields = true
|
if (procsInfo.CloseMainWindow()) procsInfo.WaitForExit((int)timeout.TotalMilliseconds);
|
||||||
}, cancellationToken);
|
if (procsInfo.HasExited is false) procsInfo.Kill(true);
|
||||||
|
|
||||||
if (response is null) return false;
|
|
||||||
|
|
||||||
Version actualVersion;
|
|
||||||
|
|
||||||
if (FileVersionInfo.GetVersionInfo(bin.FullName).FileVersion is not string binVersionString) return false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
actualVersion = Version.Parse(binVersionString);
|
|
||||||
if (actualVersion >= response.Version) return false;
|
|
||||||
|
|
||||||
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
|
||||||
if (update is null) return false;
|
|
||||||
|
|
||||||
Stop(bin, TimeSpan.FromSeconds(60));
|
|
||||||
|
|
||||||
// read update archive to temp (overwrite)
|
|
||||||
var temp = Directory.CreateTempSubdirectory();
|
|
||||||
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
|
||||||
|
|
||||||
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
|
||||||
|
|
||||||
// extract update archive from temp to app dir (overwrite)
|
|
||||||
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
|
||||||
|
|
||||||
// delete temp folder
|
|
||||||
if (temp.Exists) temp.Delete(true);
|
|
||||||
|
|
||||||
// rewrite with options to start user session process
|
|
||||||
//Start(app, directory, TimeSpan.FromSeconds(60));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
public static bool Delete(FileInfo bin, TimeSpan timeout)
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async ValueTask<bool> UpdateAsync(HttpClient httpClient, Uri api, FileInfo bin, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (IsRunning(bin) is false) return false;
|
||||||
|
|
||||||
|
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api.AbsoluteUri, new JsonSerializerOptions
|
||||||
{
|
{
|
||||||
try
|
IncludeFields = true
|
||||||
{
|
}, cancellationToken);
|
||||||
Stop(bin, timeout);
|
|
||||||
bin.Delete();
|
|
||||||
|
|
||||||
return true;
|
if (response is null) return false;
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
Version actualVersion;
|
||||||
|
|
||||||
|
if (FileVersionInfo.GetVersionInfo(bin.FullName).FileVersion is not string binVersionString) return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
actualVersion = Version.Parse(binVersionString);
|
||||||
|
if (actualVersion >= response.Version) return false;
|
||||||
|
|
||||||
|
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
||||||
|
if (update is null) return false;
|
||||||
|
|
||||||
|
Stop(bin, TimeSpan.FromSeconds(60));
|
||||||
|
|
||||||
|
// read update archive to temp (overwrite)
|
||||||
|
var temp = Directory.CreateTempSubdirectory();
|
||||||
|
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
||||||
|
|
||||||
|
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
||||||
|
|
||||||
|
// extract update archive from temp to app dir (overwrite)
|
||||||
|
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
||||||
|
|
||||||
|
// delete temp folder
|
||||||
|
if (temp.Exists) temp.Delete(true);
|
||||||
|
|
||||||
|
// rewrite with options to start user session process
|
||||||
|
//Start(app, directory, TimeSpan.FromSeconds(60));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Delete(FileInfo bin, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Stop(bin, timeout);
|
||||||
|
bin.Delete();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class InstallResult
|
public class InstallResult
|
||||||
{
|
{
|
||||||
public string? Api { get; set; }
|
public string? Api { get; set; }
|
||||||
public string? SourceDirectory { get; set; }
|
public string? SourceDirectory { get; set; }
|
||||||
public string? App { get; set; }
|
public string? App { get; set; }
|
||||||
public string? ServiceName { get; set; }
|
public string? ServiceName { get; set; }
|
||||||
public bool Autorun { get; set; }
|
public bool Autorun { get; set; }
|
||||||
|
|
||||||
public bool ApiAvailable { get; set; } = false;
|
public bool ApiAvailable { 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; } = new();
|
||||||
public List<string> Errors { get; } = new();
|
public List<string> Errors { get; } = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UpdateResult
|
public class UpdateResult
|
||||||
{
|
{
|
||||||
public string? Api { get; set; }
|
public string? Api { get; set; }
|
||||||
public string? SourceDirectory { get; set; }
|
public string? SourceDirectory { get; set; }
|
||||||
public string? App { get; set; }
|
public string? App { get; set; }
|
||||||
public string? ServiceName { get; set; }
|
public string? ServiceName { get; set; }
|
||||||
|
|
||||||
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; } = new();
|
||||||
public List<string> UpdateErrors { get; } = new();
|
public List<string> UpdateErrors { get; } = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UninstallResult
|
public class UninstallResult
|
||||||
{
|
{
|
||||||
public string? ServiceName { get; set; }
|
public string? ServiceName { get; set; }
|
||||||
|
|
||||||
public bool Success { get; set; } = false;
|
public bool Success { get; set; } = false;
|
||||||
public List<string> Errors { get; } = new();
|
public List<string> Errors { get; } = new();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,243 +5,242 @@ using Microsoft.Extensions.Logging;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Insight.Setup.Services
|
namespace Insight.Setup.Services;
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
internal class SetupService : BackgroundService
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("windows")]
|
private readonly Uri _uri;
|
||||||
internal class SetupService : BackgroundService
|
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
private readonly IHostApplicationLifetime _lifetime;
|
||||||
|
private readonly ILogger<SetupService> _logger;
|
||||||
|
|
||||||
|
public SetupService(HttpClient httpClient, IHostApplicationLifetime lifetime, IConfiguration configuration, ILogger<SetupService> logger)
|
||||||
{
|
{
|
||||||
private readonly Uri _uri;
|
_httpClient = httpClient;
|
||||||
|
_lifetime = lifetime;
|
||||||
|
_uri = configuration.GetValue<Uri?>("api") ?? new Uri("https://insight.webmatic.de/api"); //throw new Exception($"api value not set (appsettings)");
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly HttpClient _httpClient;
|
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||||
private readonly IHostApplicationLifetime _lifetime;
|
{
|
||||||
private readonly ILogger<SetupService> _logger;
|
_logger.LogTrace("ExecuteAsync");
|
||||||
|
|
||||||
public SetupService(HttpClient httpClient, IHostApplicationLifetime lifetime, IConfiguration configuration, ILogger<SetupService> logger)
|
Console.WriteLine("1: Install");
|
||||||
|
Console.WriteLine("2: Update");
|
||||||
|
Console.WriteLine("3: Uninstall");
|
||||||
|
|
||||||
|
Console.WriteLine("\n");
|
||||||
|
|
||||||
|
var key = Console.ReadKey();
|
||||||
|
|
||||||
|
Console.Clear();
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
switch (key.Key)
|
||||||
_lifetime = lifetime;
|
|
||||||
_uri = configuration.GetValue<Uri?>("api") ?? new Uri("https://insight.webmatic.de/api"); //throw new Exception($"api value not set (appsettings)");
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
_logger.LogTrace("ExecuteAsync");
|
|
||||||
|
|
||||||
Console.WriteLine("1: Install");
|
|
||||||
Console.WriteLine("2: Update");
|
|
||||||
Console.WriteLine("3: Uninstall");
|
|
||||||
|
|
||||||
Console.WriteLine("\n");
|
|
||||||
|
|
||||||
var key = Console.ReadKey();
|
|
||||||
|
|
||||||
Console.Clear();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
switch (key.Key)
|
case ConsoleKey.NumPad1:
|
||||||
{
|
case ConsoleKey.D1:
|
||||||
case ConsoleKey.NumPad1:
|
|
||||||
case ConsoleKey.D1:
|
|
||||||
{
|
|
||||||
await InstallAsync(cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ConsoleKey.NumPad2:
|
|
||||||
case ConsoleKey.D2:
|
|
||||||
{
|
|
||||||
await UpdateAsync(cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ConsoleKey.NumPad3:
|
|
||||||
case ConsoleKey.D3:
|
|
||||||
{
|
|
||||||
await UninstallAsync();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
Console.WriteLine("invalid selection");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_lifetime.StopApplication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask InstallAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Install Runtime");
|
|
||||||
await InstallRuntimeAsync(cancellationToken);
|
|
||||||
|
|
||||||
Console.WriteLine("Install ASP Runtime");
|
|
||||||
await InstallAspRuntimeAsync(cancellationToken);
|
|
||||||
|
|
||||||
// UPDATER
|
|
||||||
Console.WriteLine("Install Updater");
|
|
||||||
|
|
||||||
var updaterResult = await Deployment.Windows.Service.InstallAsync(
|
|
||||||
_httpClient,
|
|
||||||
Deploy.GetUpdateHref(_uri, Deploy.Updater.Name),
|
|
||||||
Deploy.GetAppExecutable(Deploy.Updater.Name),
|
|
||||||
Deploy.Updater.ServiceName,
|
|
||||||
Deploy.Updater.Description,
|
|
||||||
Deploy.Updater.Description,
|
|
||||||
true,
|
|
||||||
cancellationToken);
|
|
||||||
|
|
||||||
Console.WriteLine($"Updater: {updaterResult.Success}");
|
|
||||||
Console.WriteLine($"Updater: {string.Concat(updaterResult.Errors)}");
|
|
||||||
|
|
||||||
// AGENT
|
|
||||||
Console.WriteLine("Install Agent");
|
|
||||||
|
|
||||||
var agentResult = await Deployment.Windows.Service.InstallAsync(
|
|
||||||
_httpClient,
|
|
||||||
Deploy.GetUpdateHref(_uri, Deploy.Agent.Name),
|
|
||||||
Deploy.GetAppExecutable(Deploy.Agent.Name),
|
|
||||||
Deploy.Agent.ServiceName,
|
|
||||||
Deploy.Agent.Description,
|
|
||||||
Deploy.Agent.Description,
|
|
||||||
true,
|
|
||||||
cancellationToken);
|
|
||||||
|
|
||||||
Console.WriteLine($"Agent: {agentResult}");
|
|
||||||
Console.WriteLine($"Agent: {string.Concat(agentResult.Errors)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask UpdateAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// UPDATER
|
|
||||||
Console.WriteLine("Update Updater");
|
|
||||||
|
|
||||||
var updateResult = await Deployment.Windows.Service.UpdateAsync(
|
|
||||||
_httpClient,
|
|
||||||
Deploy.GetUpdateHref(_uri, Deploy.Updater.Name),
|
|
||||||
Deploy.GetAppExecutable(Deploy.Updater.Name),
|
|
||||||
Deploy.Updater.ServiceName,
|
|
||||||
cancellationToken);
|
|
||||||
|
|
||||||
Console.WriteLine($"Result: {updateResult}");
|
|
||||||
|
|
||||||
// AGENT
|
|
||||||
Console.WriteLine("Update Agent");
|
|
||||||
|
|
||||||
var agentResult = await Deployment.Windows.Service.UpdateAsync(
|
|
||||||
_httpClient,
|
|
||||||
Deploy.GetUpdateHref(_uri, Deploy.Agent.Name),
|
|
||||||
Deploy.GetAppExecutable(Deploy.Agent.Name),
|
|
||||||
Deploy.Agent.ServiceName,
|
|
||||||
cancellationToken);
|
|
||||||
|
|
||||||
Console.WriteLine($"Result: {agentResult}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async ValueTask UninstallAsync()
|
|
||||||
{
|
|
||||||
// UPDATER
|
|
||||||
Console.WriteLine("Uninstall Updater");
|
|
||||||
|
|
||||||
var updaterResult = await Deployment.Windows.Service.UninstallAsync(Deploy.Updater.ServiceName);
|
|
||||||
Console.WriteLine($"Result: {updaterResult}");
|
|
||||||
|
|
||||||
// AGENT
|
|
||||||
Console.WriteLine("Uninstall Agent");
|
|
||||||
|
|
||||||
var agentResult = await Deployment.Windows.Service.UninstallAsync(Deploy.Agent.ServiceName);
|
|
||||||
Console.WriteLine($"Result: {agentResult}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask InstallRuntimeAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// try get dotnet folders
|
|
||||||
var coreDirectory = Deploy.Runtime.Core.Directory;
|
|
||||||
|
|
||||||
// Runtime Installation Check...
|
|
||||||
if (coreDirectory.Exists && coreDirectory.EnumerateDirectories().Any(x => x.Name == Deploy.Runtime.Core.Version)) return;
|
|
||||||
|
|
||||||
// Downloading Runtime...
|
|
||||||
var queryResult = await _httpClient.GetAsync(Deploy.Runtime.Core.Download, cancellationToken);
|
|
||||||
|
|
||||||
var tempDir = Directory.CreateTempSubdirectory();
|
|
||||||
|
|
||||||
await File.WriteAllBytesAsync(
|
|
||||||
$@"{tempDir.FullName}/runtime.exe",
|
|
||||||
await queryResult.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
|
||||||
|
|
||||||
// Installing Runtime...
|
|
||||||
var runtimeFile = new FileInfo($@"{tempDir.FullName}/runtime.exe");
|
|
||||||
|
|
||||||
using var process = new Process()
|
|
||||||
{
|
|
||||||
StartInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = runtimeFile.FullName,
|
|
||||||
ArgumentList =
|
|
||||||
{
|
{
|
||||||
@"/install",
|
await InstallAsync(cancellationToken);
|
||||||
@"/quiet",
|
break;
|
||||||
@"/norestart"
|
}
|
||||||
},
|
case ConsoleKey.NumPad2:
|
||||||
UseShellExecute = false,
|
case ConsoleKey.D2:
|
||||||
RedirectStandardOutput = true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
process.Start();
|
|
||||||
await process.WaitForExitAsync(cancellationToken);
|
|
||||||
|
|
||||||
if (runtimeFile.Exists) runtimeFile.Delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask InstallAspRuntimeAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// try get dotnet folders
|
|
||||||
var aspDirectory = Deploy.Runtime.Asp.Directory;
|
|
||||||
|
|
||||||
// Runtime Installation Check...
|
|
||||||
if (aspDirectory.Exists && aspDirectory.EnumerateDirectories().Any(x => x.Name == Deploy.Runtime.Asp.Version)) return;
|
|
||||||
|
|
||||||
// Downloading Runtime...
|
|
||||||
var queryResult = await _httpClient.GetAsync(Deploy.Runtime.Asp.Download, cancellationToken);
|
|
||||||
|
|
||||||
var tempDir = Directory.CreateTempSubdirectory();
|
|
||||||
|
|
||||||
await File.WriteAllBytesAsync(
|
|
||||||
$@"{tempDir.FullName}/runtime.exe",
|
|
||||||
await queryResult.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
|
||||||
|
|
||||||
// Installing Runtime...
|
|
||||||
var runtimeFile = new FileInfo($@"{tempDir.FullName}/runtime.exe");
|
|
||||||
|
|
||||||
using var process = new Process()
|
|
||||||
{
|
|
||||||
StartInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = runtimeFile.FullName,
|
|
||||||
ArgumentList =
|
|
||||||
{
|
{
|
||||||
@"/install",
|
await UpdateAsync(cancellationToken);
|
||||||
@"/quiet",
|
break;
|
||||||
@"/norestart"
|
}
|
||||||
},
|
case ConsoleKey.NumPad3:
|
||||||
UseShellExecute = false,
|
case ConsoleKey.D3:
|
||||||
RedirectStandardOutput = true
|
{
|
||||||
}
|
await UninstallAsync();
|
||||||
};
|
break;
|
||||||
|
}
|
||||||
process.Start();
|
default:
|
||||||
await process.WaitForExitAsync(cancellationToken);
|
{
|
||||||
|
Console.WriteLine("invalid selection");
|
||||||
if (runtimeFile.Exists) runtimeFile.Delete();
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lifetime.StopApplication();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async ValueTask InstallAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Install Runtime");
|
||||||
|
await InstallRuntimeAsync(cancellationToken);
|
||||||
|
|
||||||
|
Console.WriteLine("Install ASP Runtime");
|
||||||
|
await InstallAspRuntimeAsync(cancellationToken);
|
||||||
|
|
||||||
|
// UPDATER
|
||||||
|
Console.WriteLine("Install Updater");
|
||||||
|
|
||||||
|
var updaterResult = await Deployment.Windows.Service.InstallAsync(
|
||||||
|
_httpClient,
|
||||||
|
Deploy.GetUpdateHref(_uri, Deploy.Updater.Name),
|
||||||
|
Deploy.GetAppExecutable(Deploy.Updater.Name),
|
||||||
|
Deploy.Updater.ServiceName,
|
||||||
|
Deploy.Updater.Description,
|
||||||
|
Deploy.Updater.Description,
|
||||||
|
true,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
Console.WriteLine($"Updater: {updaterResult.Success}");
|
||||||
|
Console.WriteLine($"Updater: {string.Concat(updaterResult.Errors)}");
|
||||||
|
|
||||||
|
// AGENT
|
||||||
|
Console.WriteLine("Install Agent");
|
||||||
|
|
||||||
|
var agentResult = await Deployment.Windows.Service.InstallAsync(
|
||||||
|
_httpClient,
|
||||||
|
Deploy.GetUpdateHref(_uri, Deploy.Agent.Name),
|
||||||
|
Deploy.GetAppExecutable(Deploy.Agent.Name),
|
||||||
|
Deploy.Agent.ServiceName,
|
||||||
|
Deploy.Agent.Description,
|
||||||
|
Deploy.Agent.Description,
|
||||||
|
true,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
Console.WriteLine($"Agent: {agentResult}");
|
||||||
|
Console.WriteLine($"Agent: {string.Concat(agentResult.Errors)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask UpdateAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// UPDATER
|
||||||
|
Console.WriteLine("Update Updater");
|
||||||
|
|
||||||
|
var updateResult = await Deployment.Windows.Service.UpdateAsync(
|
||||||
|
_httpClient,
|
||||||
|
Deploy.GetUpdateHref(_uri, Deploy.Updater.Name),
|
||||||
|
Deploy.GetAppExecutable(Deploy.Updater.Name),
|
||||||
|
Deploy.Updater.ServiceName,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
Console.WriteLine($"Result: {updateResult}");
|
||||||
|
|
||||||
|
// AGENT
|
||||||
|
Console.WriteLine("Update Agent");
|
||||||
|
|
||||||
|
var agentResult = await Deployment.Windows.Service.UpdateAsync(
|
||||||
|
_httpClient,
|
||||||
|
Deploy.GetUpdateHref(_uri, Deploy.Agent.Name),
|
||||||
|
Deploy.GetAppExecutable(Deploy.Agent.Name),
|
||||||
|
Deploy.Agent.ServiceName,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
Console.WriteLine($"Result: {agentResult}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async ValueTask UninstallAsync()
|
||||||
|
{
|
||||||
|
// UPDATER
|
||||||
|
Console.WriteLine("Uninstall Updater");
|
||||||
|
|
||||||
|
var updaterResult = await Deployment.Windows.Service.UninstallAsync(Deploy.Updater.ServiceName);
|
||||||
|
Console.WriteLine($"Result: {updaterResult}");
|
||||||
|
|
||||||
|
// AGENT
|
||||||
|
Console.WriteLine("Uninstall Agent");
|
||||||
|
|
||||||
|
var agentResult = await Deployment.Windows.Service.UninstallAsync(Deploy.Agent.ServiceName);
|
||||||
|
Console.WriteLine($"Result: {agentResult}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask InstallRuntimeAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// try get dotnet folders
|
||||||
|
var coreDirectory = Deploy.Runtime.Core.Directory;
|
||||||
|
|
||||||
|
// Runtime Installation Check...
|
||||||
|
if (coreDirectory.Exists && coreDirectory.EnumerateDirectories().Any(x => x.Name == Deploy.Runtime.Core.Version)) return;
|
||||||
|
|
||||||
|
// Downloading Runtime...
|
||||||
|
var queryResult = await _httpClient.GetAsync(Deploy.Runtime.Core.Download, cancellationToken);
|
||||||
|
|
||||||
|
var tempDir = Directory.CreateTempSubdirectory();
|
||||||
|
|
||||||
|
await File.WriteAllBytesAsync(
|
||||||
|
$@"{tempDir.FullName}/runtime.exe",
|
||||||
|
await queryResult.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
||||||
|
|
||||||
|
// Installing Runtime...
|
||||||
|
var runtimeFile = new FileInfo($@"{tempDir.FullName}/runtime.exe");
|
||||||
|
|
||||||
|
using var process = new Process()
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = runtimeFile.FullName,
|
||||||
|
ArgumentList =
|
||||||
|
{
|
||||||
|
@"/install",
|
||||||
|
@"/quiet",
|
||||||
|
@"/norestart"
|
||||||
|
},
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
await process.WaitForExitAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (runtimeFile.Exists) runtimeFile.Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask InstallAspRuntimeAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// try get dotnet folders
|
||||||
|
var aspDirectory = Deploy.Runtime.Asp.Directory;
|
||||||
|
|
||||||
|
// Runtime Installation Check...
|
||||||
|
if (aspDirectory.Exists && aspDirectory.EnumerateDirectories().Any(x => x.Name == Deploy.Runtime.Asp.Version)) return;
|
||||||
|
|
||||||
|
// Downloading Runtime...
|
||||||
|
var queryResult = await _httpClient.GetAsync(Deploy.Runtime.Asp.Download, cancellationToken);
|
||||||
|
|
||||||
|
var tempDir = Directory.CreateTempSubdirectory();
|
||||||
|
|
||||||
|
await File.WriteAllBytesAsync(
|
||||||
|
$@"{tempDir.FullName}/runtime.exe",
|
||||||
|
await queryResult.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
||||||
|
|
||||||
|
// Installing Runtime...
|
||||||
|
var runtimeFile = new FileInfo($@"{tempDir.FullName}/runtime.exe");
|
||||||
|
|
||||||
|
using var process = new Process()
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = runtimeFile.FullName,
|
||||||
|
ArgumentList =
|
||||||
|
{
|
||||||
|
@"/install",
|
||||||
|
@"/quiet",
|
||||||
|
@"/norestart"
|
||||||
|
},
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
await process.WaitForExitAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (runtimeFile.Exists) runtimeFile.Delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,21 +1,20 @@
|
||||||
namespace Insight.Updater.Constants
|
namespace Insight.Updater.Constants;
|
||||||
|
|
||||||
|
public static class Deploy
|
||||||
{
|
{
|
||||||
public static class Deploy
|
public static class Agent
|
||||||
{
|
{
|
||||||
public static class Agent
|
public const string Name = "Agent";
|
||||||
{
|
public const string ServiceName = "insight_agent";
|
||||||
public const string Name = "Agent";
|
public const string Description = "Insight Agent";
|
||||||
public const string ServiceName = "insight_agent";
|
|
||||||
public const string Description = "Insight Agent";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DirectoryInfo GetAppDirectory(string appName)
|
|
||||||
=> new($"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}/Webmatic/Insight/{appName}");
|
|
||||||
|
|
||||||
public static FileInfo GetAppExecutable(string appName)
|
|
||||||
=> new($"{GetAppDirectory(appName).FullName}/{appName.ToLower()}.exe");
|
|
||||||
|
|
||||||
public static Uri GetUpdateHref(Uri api, string appName)
|
|
||||||
=> new($"{api.AbsoluteUri}/update/{appName.ToLower()}/windows");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DirectoryInfo GetAppDirectory(string appName)
|
||||||
|
=> new($"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}/Webmatic/Insight/{appName}");
|
||||||
|
|
||||||
|
public static FileInfo GetAppExecutable(string appName)
|
||||||
|
=> new($"{GetAppDirectory(appName).FullName}/{appName.ToLower()}.exe");
|
||||||
|
|
||||||
|
public static Uri GetUpdateHref(Uri api, string appName)
|
||||||
|
=> new($"{api.AbsoluteUri}/update/{appName.ToLower()}/windows");
|
||||||
}
|
}
|
||||||
|
|
@ -5,53 +5,52 @@ using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Insight.Updater.Windows
|
namespace Insight.Updater.Windows;
|
||||||
|
|
||||||
|
internal class Program
|
||||||
{
|
{
|
||||||
internal class Program
|
public static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
public static async Task Main(string[] args)
|
var builder = Host.CreateDefaultBuilder(args);
|
||||||
|
builder.UseWindowsService();
|
||||||
|
builder.UseSystemd();
|
||||||
|
|
||||||
|
builder.ConfigureAppConfiguration(options =>
|
||||||
{
|
{
|
||||||
var builder = Host.CreateDefaultBuilder(args);
|
options.Sources.Clear();
|
||||||
builder.UseWindowsService();
|
options.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
||||||
builder.UseSystemd();
|
options.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
|
||||||
|
});
|
||||||
|
|
||||||
builder.ConfigureAppConfiguration(options =>
|
builder.ConfigureLogging(options =>
|
||||||
|
{
|
||||||
|
options.ClearProviders();
|
||||||
|
options.SetMinimumLevel(LogLevel.Trace);
|
||||||
|
|
||||||
|
options.AddSimpleConsole(options =>
|
||||||
{
|
{
|
||||||
options.Sources.Clear();
|
options.IncludeScopes = true;
|
||||||
options.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
options.SingleLine = true;
|
||||||
options.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
|
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.ConfigureLogging(options =>
|
options.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/updater_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}");
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.ConfigureServices((host, services) =>
|
||||||
|
{
|
||||||
|
// SERVICES
|
||||||
|
services.AddHostedService<UpdateService>();
|
||||||
|
|
||||||
|
// GLOBALS
|
||||||
|
services.AddTransient(provider => new HttpClient(new HttpClientHandler
|
||||||
{
|
{
|
||||||
options.ClearProviders();
|
ClientCertificateOptions = ClientCertificateOption.Manual,
|
||||||
options.SetMinimumLevel(LogLevel.Trace);
|
ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
options.AddSimpleConsole(options =>
|
var host = builder.Build();
|
||||||
{
|
await host.RunAsync().ConfigureAwait(false);
|
||||||
options.IncludeScopes = true;
|
|
||||||
options.SingleLine = true;
|
|
||||||
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
|
||||||
});
|
|
||||||
|
|
||||||
options.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/updater_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}");
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.ConfigureServices((host, services) =>
|
|
||||||
{
|
|
||||||
// SERVICES
|
|
||||||
services.AddHostedService<UpdateService>();
|
|
||||||
|
|
||||||
// GLOBALS
|
|
||||||
services.AddTransient(provider => new HttpClient(new HttpClientHandler
|
|
||||||
{
|
|
||||||
ClientCertificateOptions = ClientCertificateOption.Manual,
|
|
||||||
ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
var host = builder.Build();
|
|
||||||
await host.RunAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,351 +10,350 @@ using System.Runtime.Versioning;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Insight.Updater.Services
|
namespace Insight.Updater.Services;
|
||||||
|
|
||||||
|
public class UpdateService : BackgroundService
|
||||||
{
|
{
|
||||||
public class UpdateService : BackgroundService
|
private readonly Uri _uri;
|
||||||
|
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
private readonly ILogger<UpdateService> _logger;
|
||||||
|
|
||||||
|
public UpdateService(HttpClient httpClient, IConfiguration configuration, ILogger<UpdateService> logger)
|
||||||
{
|
{
|
||||||
private readonly Uri _uri;
|
_httpClient = httpClient;
|
||||||
|
_uri = configuration.GetValue<Uri?>("api") ?? throw new Exception($"api value not set (appsettings)");
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly HttpClient _httpClient;
|
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||||
private readonly ILogger<UpdateService> _logger;
|
{
|
||||||
|
_logger.LogTrace("ExecuteAsync");
|
||||||
|
|
||||||
public UpdateService(HttpClient httpClient, IConfiguration configuration, ILogger<UpdateService> logger)
|
while (cancellationToken.IsCancellationRequested is false)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
try
|
||||||
_uri = configuration.GetValue<Uri?>("api") ?? throw new Exception($"api value not set (appsettings)");
|
{
|
||||||
_logger = logger;
|
UpdateResult? result = null;
|
||||||
|
|
||||||
|
if (OperatingSystem.IsWindows()) result = await WindowsUpdateAsync(cancellationToken);
|
||||||
|
if (OperatingSystem.IsLinux()) result = await LinuxUpdateAsync(cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation("Update Result: {result}", result?.Success);
|
||||||
|
if (result?.UpdateErrors is not null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Update Errors: {errors}", string.Concat(result?.UpdateErrors));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) { }
|
||||||
|
catch (Exception ex) // may inform via client / api about errors
|
||||||
|
{
|
||||||
|
_logger.LogError("{ex}", ex.Message);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
[SupportedOSPlatform("windows")]
|
||||||
|
private async ValueTask<UpdateResult> WindowsUpdateAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return await Windows.Service.UpdateAsync(
|
||||||
|
_httpClient,
|
||||||
|
Deploy.GetUpdateHref(_uri, Deploy.Agent.Name),
|
||||||
|
Deploy.GetAppExecutable(Deploy.Agent.Name),
|
||||||
|
Deploy.Agent.ServiceName,
|
||||||
|
cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("linux")]
|
||||||
|
private ValueTask<UpdateResult> LinuxUpdateAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
private static class Windows
|
||||||
|
{
|
||||||
|
public static class Service
|
||||||
{
|
{
|
||||||
_logger.LogTrace("ExecuteAsync");
|
private static bool ServiceExistence(string serviceName)
|
||||||
|
|
||||||
while (cancellationToken.IsCancellationRequested is false)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UpdateResult? result = null;
|
if (ServiceController.GetServices().Any(s => s.ServiceName.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase))) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows()) result = await WindowsUpdateAsync(cancellationToken);
|
return false;
|
||||||
if (OperatingSystem.IsLinux()) result = await LinuxUpdateAsync(cancellationToken);
|
|
||||||
|
|
||||||
_logger.LogInformation("Update Result: {result}", result?.Success);
|
|
||||||
if (result?.UpdateErrors is not null)
|
|
||||||
{
|
|
||||||
_logger.LogError("Update Errors: {errors}", string.Concat(result?.UpdateErrors));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException) { }
|
|
||||||
catch (Exception ex) // may inform via client / api about errors
|
|
||||||
{
|
|
||||||
_logger.LogError("{ex}", ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
private static bool SetServiceState(string app, ServiceControllerStatus status, TimeSpan timeout)
|
||||||
private async ValueTask<UpdateResult> WindowsUpdateAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return await Windows.Service.UpdateAsync(
|
|
||||||
_httpClient,
|
|
||||||
Deploy.GetUpdateHref(_uri, Deploy.Agent.Name),
|
|
||||||
Deploy.GetAppExecutable(Deploy.Agent.Name),
|
|
||||||
Deploy.Agent.ServiceName,
|
|
||||||
cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[SupportedOSPlatform("linux")]
|
|
||||||
private ValueTask<UpdateResult> LinuxUpdateAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
|
||||||
private static class Windows
|
|
||||||
{
|
|
||||||
public static class Service
|
|
||||||
{
|
{
|
||||||
private static bool ServiceExistence(string serviceName)
|
try
|
||||||
{
|
{
|
||||||
try
|
using var sc = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName.Equals(app, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
if (sc is null) return false;
|
||||||
|
|
||||||
|
if (sc.Status != status)
|
||||||
{
|
{
|
||||||
if (ServiceController.GetServices().Any(s => s.ServiceName.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase))) return true;
|
switch (status)
|
||||||
return false;
|
{
|
||||||
|
case ServiceControllerStatus.Running:
|
||||||
|
sc.Start();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ServiceControllerStatus.Stopped:
|
||||||
|
sc.Stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc.WaitForStatus(status, timeout);
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
private static bool SetServiceState(string app, ServiceControllerStatus status, TimeSpan timeout)
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async ValueTask<UpdateResult> UpdateAsync(HttpClient httpClient, Uri api, FileInfo bin, string serviceName, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = new UpdateResult
|
||||||
{
|
{
|
||||||
try
|
Api = api?.ToString(),
|
||||||
|
SourceDirectory = bin.Directory?.FullName,
|
||||||
|
App = bin.Name,
|
||||||
|
ServiceName = serviceName
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// check if service exists
|
||||||
|
if (ServiceExistence(serviceName) is false)
|
||||||
{
|
{
|
||||||
using var sc = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName.Equals(app, StringComparison.InvariantCultureIgnoreCase));
|
result.UpdateErrors.Add("service not found");
|
||||||
if (sc is null) return false;
|
return result;
|
||||||
|
|
||||||
if (sc.Status != status)
|
|
||||||
{
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case ServiceControllerStatus.Running:
|
|
||||||
sc.Start();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ServiceControllerStatus.Stopped:
|
|
||||||
sc.Stop();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sc.WaitForStatus(status, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
// get service update details
|
||||||
}
|
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api, cancellationToken);
|
||||||
|
if (response is null)
|
||||||
public static async ValueTask<UpdateResult> UpdateAsync(HttpClient httpClient, Uri api, FileInfo bin, string serviceName, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var result = new UpdateResult
|
|
||||||
{
|
{
|
||||||
Api = api?.ToString(),
|
result.ApiErrors.Add("not available / response null");
|
||||||
SourceDirectory = bin.Directory?.FullName,
|
return result;
|
||||||
App = bin.Name,
|
}
|
||||||
ServiceName = serviceName
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
result.ApiAvailable = true;
|
||||||
|
|
||||||
|
// check if local binary exists
|
||||||
|
if (bin is null)
|
||||||
{
|
{
|
||||||
// check if service exists
|
result.UpdateErrors.Add("source binary not found");
|
||||||
if (ServiceExistence(serviceName) is false)
|
return result;
|
||||||
{
|
}
|
||||||
result.UpdateErrors.Add("service not found");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get service update details
|
// get local file binary version
|
||||||
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api, cancellationToken);
|
if (FileVersionInfo.GetVersionInfo(bin.FullName).FileVersion is not string binVersionString)
|
||||||
if (response is null)
|
{
|
||||||
{
|
result.UpdateErrors.Add("source binary fileversion not valid");
|
||||||
result.ApiErrors.Add("not available / response null");
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
result.ApiAvailable = true;
|
|
||||||
|
|
||||||
// check if local binary exists
|
|
||||||
if (bin is null)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add("source binary not found");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get local file binary version
|
|
||||||
if (FileVersionInfo.GetVersionInfo(bin.FullName).FileVersion is not string binVersionString)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add("source binary fileversion not valid");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compare local against update version, skip lower or equal update version
|
|
||||||
var actualVersion = Version.Parse(binVersionString);
|
|
||||||
if (actualVersion >= response.Version)
|
|
||||||
{
|
|
||||||
result.Success = true;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.UpdateAvailable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get update file (bytes) to memory
|
|
||||||
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
|
||||||
if (update is null)
|
|
||||||
{
|
|
||||||
result.ApiErrors.Add("update source not available");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop service
|
|
||||||
if (SetServiceState(serviceName, ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10)) is false)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add("service control failed / failed to stop service");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read update archive to temp (overwrite)
|
|
||||||
var temp = Directory.CreateTempSubdirectory();
|
|
||||||
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
|
||||||
|
|
||||||
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
|
||||||
|
|
||||||
// extract update archive from temp to app dir (overwrite)
|
|
||||||
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
|
||||||
|
|
||||||
// delete temp folder
|
|
||||||
if (temp.Exists) temp.Delete(true);
|
|
||||||
|
|
||||||
// start updateds service
|
|
||||||
if (SetServiceState(serviceName, ServiceControllerStatus.Running, TimeSpan.FromSeconds(10)) is false)
|
|
||||||
{
|
|
||||||
result.UpdateErrors.Add("service control failed / failed to start service");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// compare local against update version, skip lower or equal update version
|
||||||
|
var actualVersion = Version.Parse(binVersionString);
|
||||||
|
if (actualVersion >= response.Version)
|
||||||
|
{
|
||||||
result.Success = true;
|
result.Success = true;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
else
|
||||||
{
|
{
|
||||||
result.UpdateErrors.Add(ex.Message);
|
result.UpdateAvailable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
// get update file (bytes) to memory
|
||||||
|
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
||||||
|
if (update is null)
|
||||||
|
{
|
||||||
|
result.ApiErrors.Add("update source not available");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop service
|
||||||
|
if (SetServiceState(serviceName, ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10)) is false)
|
||||||
|
{
|
||||||
|
result.UpdateErrors.Add("service control failed / failed to stop service");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read update archive to temp (overwrite)
|
||||||
|
var temp = Directory.CreateTempSubdirectory();
|
||||||
|
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
||||||
|
|
||||||
|
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
||||||
|
|
||||||
|
// extract update archive from temp to app dir (overwrite)
|
||||||
|
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
||||||
|
|
||||||
|
// delete temp folder
|
||||||
|
if (temp.Exists) temp.Delete(true);
|
||||||
|
|
||||||
|
// start updateds service
|
||||||
|
if (SetServiceState(serviceName, ServiceControllerStatus.Running, TimeSpan.FromSeconds(10)) is false)
|
||||||
|
{
|
||||||
|
result.UpdateErrors.Add("service control failed / failed to start service");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Success = true;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
result.UpdateErrors.Add(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Process
|
||||||
|
{
|
||||||
|
public static bool IsRunning(FileInfo bin)
|
||||||
|
{
|
||||||
|
if (bin.Exists is false) return false;
|
||||||
|
|
||||||
|
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
|
||||||
|
|
||||||
|
if (matched is null || matched.Any() is false) return false;
|
||||||
|
|
||||||
|
if (matched.Any(p =>
|
||||||
|
p.MainModule is not null &&
|
||||||
|
p.MainModule.FileName is not null &&
|
||||||
|
p.MainModule.FileName.Equals(bin.FullName,
|
||||||
|
StringComparison.InvariantCultureIgnoreCase))) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Process
|
public static bool Start(FileInfo binary)
|
||||||
{
|
{
|
||||||
public static bool IsRunning(FileInfo bin)
|
try
|
||||||
{
|
{
|
||||||
if (bin.Exists is false) return false;
|
if (IsRunning(binary) is false) return false;
|
||||||
|
|
||||||
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
|
using var process = System.Diagnostics.Process.Start(binary.FullName);
|
||||||
|
return true;
|
||||||
if (matched is null || matched.Any() is false) return false;
|
|
||||||
|
|
||||||
if (matched.Any(p =>
|
|
||||||
p.MainModule is not null &&
|
|
||||||
p.MainModule.FileName is not null &&
|
|
||||||
p.MainModule.FileName.Equals(bin.FullName,
|
|
||||||
StringComparison.InvariantCultureIgnoreCase))) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
public static bool Start(FileInfo binary)
|
return false;
|
||||||
{
|
}
|
||||||
try
|
|
||||||
{
|
|
||||||
if (IsRunning(binary) is false) return false;
|
|
||||||
|
|
||||||
using var process = System.Diagnostics.Process.Start(binary.FullName);
|
public static bool Stop(FileInfo bin, TimeSpan timeout)
|
||||||
return true;
|
{
|
||||||
}
|
try
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Stop(FileInfo bin, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (IsRunning(bin) is false) return false;
|
|
||||||
|
|
||||||
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
|
|
||||||
|
|
||||||
if (matched is null || matched.Any() is false) return true;
|
|
||||||
|
|
||||||
foreach (var procsInfo in matched.Where(p =>
|
|
||||||
p.MainModule is not null &&
|
|
||||||
p.MainModule.FileName is not null &&
|
|
||||||
p.MainModule.FileName.Equals(bin.FullName, StringComparison.InvariantCultureIgnoreCase)))
|
|
||||||
{
|
|
||||||
if (procsInfo.CloseMainWindow()) procsInfo.WaitForExit((int)timeout.TotalMilliseconds);
|
|
||||||
if (procsInfo.HasExited is false) procsInfo.Kill(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async ValueTask<bool> UpdateAsync(HttpClient httpClient, Uri api, FileInfo bin, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
if (IsRunning(bin) is false) return false;
|
if (IsRunning(bin) is false) return false;
|
||||||
|
|
||||||
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api.AbsoluteUri, new JsonSerializerOptions
|
var matched = System.Diagnostics.Process.GetProcessesByName(bin.FullName);
|
||||||
|
|
||||||
|
if (matched is null || matched.Any() is false) return true;
|
||||||
|
|
||||||
|
foreach (var procsInfo in matched.Where(p =>
|
||||||
|
p.MainModule is not null &&
|
||||||
|
p.MainModule.FileName is not null &&
|
||||||
|
p.MainModule.FileName.Equals(bin.FullName, StringComparison.InvariantCultureIgnoreCase)))
|
||||||
{
|
{
|
||||||
IncludeFields = true
|
if (procsInfo.CloseMainWindow()) procsInfo.WaitForExit((int)timeout.TotalMilliseconds);
|
||||||
}, cancellationToken);
|
if (procsInfo.HasExited is false) procsInfo.Kill(true);
|
||||||
|
|
||||||
if (response is null) return false;
|
|
||||||
|
|
||||||
Version actualVersion;
|
|
||||||
|
|
||||||
if (FileVersionInfo.GetVersionInfo(bin.FullName).FileVersion is not string binVersionString) return false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
actualVersion = Version.Parse(binVersionString);
|
|
||||||
if (actualVersion >= response.Version) return false;
|
|
||||||
|
|
||||||
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
|
||||||
if (update is null) return false;
|
|
||||||
|
|
||||||
Stop(bin, TimeSpan.FromSeconds(60));
|
|
||||||
|
|
||||||
// read update archive to temp (overwrite)
|
|
||||||
var temp = Directory.CreateTempSubdirectory();
|
|
||||||
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
|
||||||
|
|
||||||
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
|
||||||
|
|
||||||
// extract update archive from temp to app dir (overwrite)
|
|
||||||
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
|
||||||
|
|
||||||
// delete temp folder
|
|
||||||
if (temp.Exists) temp.Delete(true);
|
|
||||||
|
|
||||||
// rewrite with options to start user session process
|
|
||||||
//Start(app, directory, TimeSpan.FromSeconds(60));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
public static bool Delete(FileInfo bin, TimeSpan timeout)
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async ValueTask<bool> UpdateAsync(HttpClient httpClient, Uri api, FileInfo bin, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (IsRunning(bin) is false) return false;
|
||||||
|
|
||||||
|
var response = await httpClient.GetFromJsonAsync<UpdateResponse>(api.AbsoluteUri, new JsonSerializerOptions
|
||||||
{
|
{
|
||||||
try
|
IncludeFields = true
|
||||||
{
|
}, cancellationToken);
|
||||||
Stop(bin, timeout);
|
|
||||||
bin.Delete();
|
|
||||||
|
|
||||||
return true;
|
if (response is null) return false;
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
return false;
|
Version actualVersion;
|
||||||
|
|
||||||
|
if (FileVersionInfo.GetVersionInfo(bin.FullName).FileVersion is not string binVersionString) return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
actualVersion = Version.Parse(binVersionString);
|
||||||
|
if (actualVersion >= response.Version) return false;
|
||||||
|
|
||||||
|
using var update = await httpClient.GetAsync(response.Uri, cancellationToken);
|
||||||
|
if (update is null) return false;
|
||||||
|
|
||||||
|
Stop(bin, TimeSpan.FromSeconds(60));
|
||||||
|
|
||||||
|
// read update archive to temp (overwrite)
|
||||||
|
var temp = Directory.CreateTempSubdirectory();
|
||||||
|
var updateFile = new FileInfo($@"{temp.FullName}/{bin.Name}.zip");
|
||||||
|
|
||||||
|
await File.WriteAllBytesAsync(updateFile.FullName, await update.Content.ReadAsByteArrayAsync(cancellationToken), cancellationToken);
|
||||||
|
|
||||||
|
// extract update archive from temp to app dir (overwrite)
|
||||||
|
ZipFile.ExtractToDirectory(updateFile.FullName, bin.Directory?.FullName, true);
|
||||||
|
|
||||||
|
// delete temp folder
|
||||||
|
if (temp.Exists) temp.Delete(true);
|
||||||
|
|
||||||
|
// rewrite with options to start user session process
|
||||||
|
//Start(app, directory, TimeSpan.FromSeconds(60));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Delete(FileInfo bin, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Stop(bin, timeout);
|
||||||
|
bin.Delete();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class UpdateResult
|
public class UpdateResult
|
||||||
{
|
{
|
||||||
public string? Api { get; set; }
|
public string? Api { get; set; }
|
||||||
public string? SourceDirectory { get; set; }
|
public string? SourceDirectory { get; set; }
|
||||||
public string? App { get; set; }
|
public string? App { get; set; }
|
||||||
public string? ServiceName { get; set; }
|
public string? ServiceName { get; set; }
|
||||||
|
|
||||||
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; } = new();
|
||||||
public List<string> UpdateErrors { get; } = new();
|
public List<string> UpdateErrors { get; } = new();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ using Vaitr.Network.Hosting;
|
||||||
|
|
||||||
namespace Insight.Web;
|
namespace Insight.Web;
|
||||||
|
|
||||||
public class Program
|
internal class Program
|
||||||
{
|
{
|
||||||
public static async Task Main(string[] args)
|
public static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue