diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/App.razor b/src/Elektrifikatsiya/Elektrifikatsiya/App.razor index f673a24..a21c2fc 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/App.razor +++ b/src/Elektrifikatsiya/Elektrifikatsiya/App.razor @@ -1,64 +1,63 @@ - - - - - - -

Sorry, there's nothing at this address.

-
-
- - - +@using Blazorise.Components + + + + + + +

Sorry, there's nothing at this address.

+
+
+ + +
@code { - private Theme theme = new() - { - BarOptions = new() - { - HorizontalHeight = "72px", - DarkColors = new() - { - ItemColorOptions = new() - { - ActiveBackgroundColor = "#1a237e", - ActiveColor = "#1a237e", - HoverColor = "#1a237e", - } - - } - }, - ColorOptions = new() - { - Primary = "#1a237e", - Secondary = "#A65529", - Success = "#23C02E", - Info = "#9BD8FE", - Warning = "#F8B86C", - Danger = "#F95741", - Light = "#F0F0F0", - Dark = "#535353", - }, - BackgroundOptions = new() - { - Primary = "#1a237e", - Secondary = "#A65529", - Success = "#23C02E", - Info = "#9BD8FE", - Warning = "#F8B86C", - Danger = "#F95741", - Light = "#F0F0F0", - Dark = "#535353", - }, - InputOptions = new() - { - CheckColor = "#1a237e", - }, - TextColorOptions = new() - { - Dark = "#000000", - Primary = "#1a237e" - } - }; + private Theme theme = new() + { + BarOptions = new() + { + HorizontalHeight = "72px", + DarkColors = new() + { + ItemColorOptions = new() + { + ActiveBackgroundColor = "#1a237e", + ActiveColor = "#1a237e", + HoverColor = "#1a237e", + } + } + }, + ColorOptions = new() + { + Primary = "#1a237e", + Secondary = "#A65529", + Success = "#23C02E", + Info = "#9BD8FE", + Warning = "#F8B86C", + Danger = "#F95741", + Light = "#F0F0F0", + Dark = "#535353", + }, + BackgroundOptions = new() + { + Primary = "#1a237e", + Secondary = "#A65529", + Success = "#23C02E", + Info = "#9BD8FE", + Warning = "#F8B86C", + Danger = "#F95741", + Light = "#F0F0F0", + Dark = "#535353", + }, + InputOptions = new() + { + CheckColor = "#1a237e", + }, + TextColorOptions = new() + { + Dark = "#000000", + Primary = "#1a237e" + } + }; } - diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Database/DeviceManagementDatabaseContext.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Database/DeviceManagementDatabaseContext.cs index 693b9e5..85d2699 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Database/DeviceManagementDatabaseContext.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Database/DeviceManagementDatabaseContext.cs @@ -6,5 +6,9 @@ namespace Elektrifikatsiya.Database public class DeviceManagmentDatabaseContext : DbContext { public DbSet Devices { get; set; } + + public DeviceManagmentDatabaseContext(DbContextOptions options) : base(options) + { + } } } diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj b/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj index 2912297..4dca5d7 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj @@ -17,6 +17,22 @@ ..\docker-compose.dcproj + + + + + + + + + + + + + + + + @@ -28,11 +44,7 @@ - - - - - + diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Layouts/LoginLayout.razor b/src/Elektrifikatsiya/Elektrifikatsiya/Layouts/LoginLayout.razor new file mode 100644 index 0000000..4962196 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Layouts/LoginLayout.razor @@ -0,0 +1,18 @@ +@using System.Diagnostics; +@inherits LayoutComponentBase + + + + + + + + + + +@code { + private void Clicked() + { + Debug.WriteLine("Button was clicked!"); + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Layouts/MainLayout.razor b/src/Elektrifikatsiya/Elektrifikatsiya/Layouts/MainLayout.razor index 08efa17..e268a9f 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Layouts/MainLayout.razor +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Layouts/MainLayout.razor @@ -1,8 +1,6 @@ @using Elektrifikatsiya.Components.Layout @inherits LayoutComponentBase - - @@ -14,4 +12,4 @@ @Body - \ No newline at end of file + diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Models/Device.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Models/Device.cs index 0176b78..0bcca1a 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Models/Device.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Models/Device.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; using System.Net; namespace Elektrifikatsiya.Models; @@ -6,21 +7,30 @@ namespace Elektrifikatsiya.Models; public class Device { [Key] - public string Key { get; private set; } + public string MacAddress { get; private set; } + [Required] - public string Name { get; private set; } = string.Empty; + public string Name { get; set; } + [Required] - public IPAddress Address { get; private set; } + public IPAddress IpAddress { get; set; } + + [Required] + public User User { get; set; } + + [NotMapped] public int PowerUsage { get; set; } - public string User { get; set; } + public string Room { get; set; } - public Device(string key, string name, IPAddress address, int powerUsage, string user, string room) + [NotMapped] + public bool Available { get; set; } + + public Device(string macAddress, string name, IPAddress address, User user, string room) { - Key = key; + MacAddress = macAddress; Name = name; - Address = address; - PowerUsage = powerUsage; + IpAddress = address; User = user; Room = room; } diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Models/DeviceStatusChagedEventArgs.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Models/DeviceStatusChagedEventArgs.cs new file mode 100644 index 0000000..8b85cd5 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Models/DeviceStatusChagedEventArgs.cs @@ -0,0 +1,11 @@ +namespace Elektrifikatsiya.Models; + +public class DeviceStatusChagedEventArgs : EventArgs +{ + public string MacAddress { get; set; } + + public DeviceStatusChagedEventArgs(string macAddress) + { + MacAddress = macAddress; + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Models/PrometheusQueryResult.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Models/PrometheusQueryResult.cs new file mode 100644 index 0000000..9732592 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Models/PrometheusQueryResult.cs @@ -0,0 +1,73 @@ +using System.Text.Json.Serialization; + +namespace Elektrifikatsiya.Models; + +public enum Status +{ + Success, + Error +} + +public enum ResultType +{ + Matrix, + Vector, + Scalar, + String +} + +public class PrometheusQueryResult +{ + public Status Status { get; set; } + + public string? ErrorType { get; set; } + public string? Error { get; set; } + public List? Warnings { get; set; } + + public PrometheusQueryResult(Status status, string? errorType, string? error, List? warnings) + { + Status = status; + ErrorType = errorType; + Error = error; + Warnings = warnings; + } +} + +internal class PrometheusDataWrapper +{ + public ResultType ResultType { get; set; } + public List Result { get; set; } + + public PrometheusDataWrapper(ResultType resultType, List result) + { + ResultType = resultType; + Result = result; + } +} + +internal class PrometheusDataMetric +{ + [JsonPropertyName("__name__")] public string Name { get; set; } + + public string Job { get; set; } + public string Instance { get; set; } + + public PrometheusDataMetric(string name, string job, string instance) + { + Name = name; + Job = job; + Instance = instance; + } +} + +internal class PrometheusData +{ + public PrometheusDataMetric Metric { get; set; } + public object Value { get; set; } + + public PrometheusData(PrometheusDataMetric metric, object value) + { + Metric = metric; + Value = value; + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Models/ShellyResponse.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Models/ShellyResponse.cs new file mode 100644 index 0000000..bf6cd03 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Models/ShellyResponse.cs @@ -0,0 +1,13 @@ +namespace Elektrifikatsiya.Models; + +public class ShellyResponse +{ + public string Type { get; set; } + public string Mac { get; set; } + + public ShellyResponse(string type, string mac) + { + Type = type; + Mac = mac; + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor index 858b2c4..0a0789e 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor @@ -3,88 +3,90 @@ @using Elektrifikatsiya.Models; @inject IVersionProvider VersionProvider - -
- - - - Plugs - - - - - - - - - - @context.Item.Name - - - - - User: @context.Item.User -
- Room: @context.Item.Room -
- - @context.Item.PowerUsage W - -
-
- - - -
-
-
-
+
+ +
+ + + + Plugs + + + + + + + + + + @context.Item.Name + + + + + User: @context.Item.User +
+ Room: @context.Item.Room +
+ + @context.Item.PowerUsage W + +
+
+ + + +
+
+
+
+
+ + + + Logs + + + + +
+ @context.Item.EventName + @context.Item.Date +
+ @context.Item.Description +
+
+
+
+
+ + + + - - - - Plugs - - - + +
- -
- @context.Item.EventName - @context.Item.Date -
- @context.Item.Description -
- -
-
-
- - - - - - @code { //TODO: insert new event here if plug produces one diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Login.razor b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Login.razor new file mode 100644 index 0000000..5c303a0 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Login.razor @@ -0,0 +1,4 @@ +@using System.Diagnostics; +@using Elektrifikatsiya.Layouts; +@page "/login" +@layout LoginLayout; \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs index 30a299e..dfa27db 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs @@ -4,6 +4,8 @@ using Blazorise.Icons.Material; using Blazorise.Material; using Elektrifikatsiya.Database; +using Elektrifikatsiya.Services; +using Elektrifikatsiya.Services.Implementations; using Microsoft.EntityFrameworkCore; @@ -12,7 +14,16 @@ WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); +builder.Services.AddHostedService(); +builder.Services.AddSingleton(); +builder.Services.AddTransient(); builder.Services.AddDbContext(options => options.UseSqlite("Data Source=./UserDatabase.sqlite")); +builder.Services.AddDbContext((options) => options.UseSqlite("Data Source=./DeviceManagement.sqlite")); +builder.Services.AddBootstrapProviders(); +builder.Services.AddBlazorise(options => +{ + options.Immediate = true; +}); AddBlazorise(builder.Services); @@ -37,19 +48,16 @@ app.MapFallbackToPage("/_Host"); IServiceScope serviceScope = app.Services.GetRequiredService().CreateScope(); serviceScope.ServiceProvider.GetRequiredService().Database.EnsureCreated(); +app.MapControllers(); + +AsyncServiceScope scope = app.Services.CreateAsyncScope(); +scope.ServiceProvider.GetRequiredService().Database.EnsureCreated(); + app.Run(); void AddBlazorise(IServiceCollection services) { - _ = services - .AddBlazorise(); - _ = services - .AddMaterialProviders() - .AddMaterialIcons(); -} -builder.Services - .AddBlazorise(options => - { - options.Immediate = true; - }) - .AddBootstrapProviders(); \ No newline at end of file + _ = services.AddBlazorise(); + _ = services.AddMaterialProviders(); + _ = services.AddMaterialIcons(); +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IAuthenticationService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IAuthenticationService.cs index 2ccc8ec..611a36a 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IAuthenticationService.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IAuthenticationService.cs @@ -15,7 +15,9 @@ public interface IAuthenticationService /// /// Registers a new user. /// - /// The E-mail address of the user. + /// The name address of the user. + /// The password of the user. + /// The default role of the user. /// A to . Task RegisterUserAsync(string name, string password, Role role); @@ -23,7 +25,8 @@ public interface IAuthenticationService /// /// Logs a user in. /// - /// The E-mail address of the user. + /// The name of the user. + /// The password of the user. /// A to . Task LoginUserAsync(string name, string password); @@ -36,14 +39,13 @@ public interface IAuthenticationService /// /// Deletes the current user. /// - /// The deletion token. - /// A to and a that indicates if the operation was successful. + /// A to . Task DeleteUserAsync(); /// /// Checks if a user exists. /// - /// The E-mail address of the user. + /// The name address of the user. /// A to and a that indicates if the user exists. Task> UserExistsAsync(string name); diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs new file mode 100644 index 0000000..bda0e67 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs @@ -0,0 +1,22 @@ +using Elektrifikatsiya.Models; + +using FluentResults; + +using System.Net; + +namespace Elektrifikatsiya.Services; + +public interface IDeviceManagmentService +{ + public Task> Register(IPAddress ip, User user, string? name = null, string room = "default"); + + public Task Unregister(string macAdress); + + public Result GetDevice(string macAdress); + + public Result> GetDevices(); + + public Result> GetDevicesInRoom(string room); + + public Result> GetDevicesOfUser(int userId); +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs new file mode 100644 index 0000000..61e1cc1 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs @@ -0,0 +1,18 @@ +using Elektrifikatsiya.Models; + +using FluentResults; + +namespace Elektrifikatsiya.Services; + +public interface IDeviceStatusService +{ + public event EventHandler OnDeviceStatusChanged; + + public Result> GetDevices(); + + public Result UpdateDeviceStatus(Device device); + + public Result TrackDevice(Device device); + + public Result UntrackDevice(string macAddress); +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs new file mode 100644 index 0000000..b659cf1 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs @@ -0,0 +1,125 @@ +using Elektrifikatsiya.Database; +using Elektrifikatsiya.Models; + +using FluentResults; + +using System.Net; +using System.Net.NetworkInformation; + +namespace Elektrifikatsiya.Services.Implementations; + +public class DeviceManagmentService : IDeviceManagmentService +{ + private readonly DeviceManagmentDatabaseContext deviceManagmentDatabaseContext; + private readonly IDeviceStatusService deviceStatusService; + private readonly HttpClient httpClient; + + public DeviceManagmentService(DeviceManagmentDatabaseContext deviceManagmentDatabaseContext, IDeviceStatusService deviceStatusService, HttpClient httpClient) + { + this.deviceManagmentDatabaseContext = deviceManagmentDatabaseContext; + this.deviceStatusService = deviceStatusService; + this.httpClient = httpClient; + } + + public Result GetDevice(string macAdress) + { + Result> getDevicesResult = deviceStatusService.GetDevices(); + + if (getDevicesResult.IsFailed) + { + return getDevicesResult.ToResult(); + } + + Device? device = getDevicesResult.Value.FirstOrDefault(d => d.MacAddress == macAdress); + + if (device is null) + { + return Result.Fail("Device does not exist!"); + } + + return device; + } + + public Result> GetDevices() + { + Result> getDevicesResult = deviceStatusService.GetDevices(); + + if (getDevicesResult.IsFailed) + { + return getDevicesResult.ToResult(); + } + + return getDevicesResult.Value.ToList(); + } + + public Result> GetDevicesInRoom(string room) + { + Result> getDevicesResult = deviceStatusService.GetDevices(); + + if (getDevicesResult.IsFailed) + { + return getDevicesResult.ToResult(); + } + + return getDevicesResult.Value.Where(d => d.Room == room).ToList(); + } + + public Result> GetDevicesOfUser(int userId) + { + Result> getDevicesResult = deviceStatusService.GetDevices(); + + if (getDevicesResult.IsFailed) + { + return getDevicesResult.ToResult(); + } + + return getDevicesResult.Value.Where(d => d.User.Id == userId).ToList(); + } + + public async Task> Register(IPAddress ip, User user, string? name = null, string room = "default") + { + ShellyResponse? shellyResponse = await httpClient.GetFromJsonAsync($"{ip}/shelly"); + + if(shellyResponse is null || shellyResponse.Type != "SHPLG-S") + { + return Result.Fail("Device is not a \"SHPLG-S\" or not reachable!"); + } + + string mac = shellyResponse.Mac; + + if(PhysicalAddress.TryParse(mac, out _)) + { + return Result.Fail("Invalid mac address!"); + } + + Device device = new Device(mac, name ?? mac, ip, user, room); + + deviceManagmentDatabaseContext.Add(device); + Result saveDatabaseChangesResult = await Result.Try(async Task () => await deviceManagmentDatabaseContext.SaveChangesAsync()); + + Result trackDeviceResult = deviceStatusService.TrackDevice(device); + + return Result.Merge(saveDatabaseChangesResult, trackDeviceResult).ToResult(device); + } + + public async Task Unregister(string macAdress) + { + Result getDeviceResult = GetDevice(macAdress); + + if (getDeviceResult.IsFailed) + { + return getDeviceResult.ToResult(); + } + + Result untrackDeviceResult = deviceStatusService.UntrackDevice(macAdress); + + if (untrackDeviceResult.IsFailed) + { + return untrackDeviceResult; + } + + deviceManagmentDatabaseContext.Remove(getDeviceResult.Value); + + return await Result.Try(async Task () => await deviceManagmentDatabaseContext.SaveChangesAsync()); + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs new file mode 100644 index 0000000..3574cec --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs @@ -0,0 +1,53 @@ +using Elektrifikatsiya.Models; + +using FluentResults; + +namespace Elektrifikatsiya.Services.Implementations; + +public class DeviceStatusService : IDeviceStatusService +{ + public event EventHandler? OnDeviceStatusChanged; + + private readonly Dictionary devices = new(); + + public Result> GetDevices() + { + return devices.Values.ToList(); + } + + public Result UpdateDeviceStatus(Device device) + { + Device? modDevice = devices.GetValueOrDefault(device.MacAddress); + + if (modDevice is null) + { + return Result.Fail("Device not tracked!"); + } + + modDevice.PowerUsage = device.PowerUsage; + modDevice.Available = device.Available; + modDevice.IpAddress = device.IpAddress; + modDevice.Name = device.Name; + + OnDeviceStatusChanged?.Invoke(this, new DeviceStatusChagedEventArgs(device.MacAddress)); + + return Result.Ok(); + } + + public Result TrackDevice(Device device) + { + if (devices.ContainsKey(device.MacAddress)) + { + return Result.Fail("Device already tracked!"); + } + + devices[device.MacAddress] = device; + + return Result.Ok(); + } + + public Result UntrackDevice(string macAddress) + { + return devices.Remove(macAddress) ? Result.Ok() : Result.Fail("Device is not tracked!"); + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs new file mode 100644 index 0000000..980826d --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs @@ -0,0 +1,73 @@ +using Elektrifikatsiya.Database; +using Elektrifikatsiya.Models; +using FluentResults; +using Microsoft.EntityFrameworkCore; +using System.Threading.Tasks; + +namespace Elektrifikatsiya.Services.Implementations; + +public class UpdateService : IHostedService, IDisposable +{ + private readonly ILogger logger; + private readonly IDeviceStatusService deviceStatusService; + private readonly DeviceManagmentDatabaseContext deviceManagmentDatabaseContext; + private Timer? timer = null; + + public UpdateService(ILogger logger, IDeviceStatusService deviceStatusService, DeviceManagmentDatabaseContext deviceManagmentDatabaseContext) + { + this.logger = logger; + this.deviceStatusService = deviceStatusService; + this.deviceManagmentDatabaseContext = deviceManagmentDatabaseContext; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + logger.LogInformation("Starting update service..."); + + foreach (Device device in await deviceManagmentDatabaseContext.Devices.AsNoTracking().ToListAsync(cancellationToken)) + { + _ = deviceStatusService.TrackDevice(device); + } + + timer = new Timer(async (_) => await Update(), null, TimeSpan.Zero, TimeSpan.FromSeconds(15)); + + logger.LogInformation("Update service started."); + } + + private async Task Update() + { + Result> getDeviceStatusResult = deviceStatusService.GetDevices(); + + if (getDeviceStatusResult.IsFailed) + { + logger.LogError("Updating devices failed!"); + } + + foreach(Device device in getDeviceStatusResult.Value) + { + //TODO: Some update magic + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + logger.LogInformation("Stopping update service."); + + _ = timer?.Change(Timeout.Infinite, 0); + + logger.LogInformation("Stopped update service."); + + return Task.CompletedTask; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + timer?.Dispose(); + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/PrometheusQuery.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/PrometheusQuery.cs new file mode 100644 index 0000000..a635857 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/PrometheusQuery.cs @@ -0,0 +1,25 @@ +using System.Net; +using System.Net.Sockets; +using System.Text.Encodings.Web; +using System.Text.Json; +using Elektrifikatsiya.Models; +using FluentResults; + +namespace Elektrifikatsiya.Utilities; + +public class PrometheusQuery +{ + private string connectionString; + private readonly HttpClient client = new(); + + public PrometheusQuery(string connectionString) + { + this.connectionString = connectionString; + client.BaseAddress = new Uri(connectionString); + } + + public Task Query(string query) + { + return client.GetFromJsonAsync($"/v1/query?{UrlEncoder.Create().Encode(query)}"); + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/TokenGenerator.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/TokenGenerator.cs index 99faf60..17e6a02 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/TokenGenerator.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/TokenGenerator.cs @@ -2,11 +2,24 @@ public static class TokenGenerator { + /// + /// Creates secure token and uses an UID to make it unique. + /// + /// The type of the token. + /// The UID of a user. + /// The length of the token. + /// public static string GenerateToken(string tokenType, int uid = 0, int length = 128) { return tokenType + "-" + SecureStringGenerator.CreateCryptographicRandomString(length, uid); } + /// + /// Checks if a token is valid. + /// + /// The token to validate. + /// The type the token should have. + /// public static bool ValidateToken(string? token, string tokenType) { if (token is null) diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/wwwroot/Pictures/logo.png b/src/Elektrifikatsiya/Elektrifikatsiya/wwwroot/Pictures/logo.png new file mode 100644 index 0000000..1904fe3 Binary files /dev/null and b/src/Elektrifikatsiya/Elektrifikatsiya/wwwroot/Pictures/logo.png differ diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/wwwroot/logo.png b/src/Elektrifikatsiya/Elektrifikatsiya/wwwroot/logo.png index 20091ee..413ea80 100644 Binary files a/src/Elektrifikatsiya/Elektrifikatsiya/wwwroot/logo.png and b/src/Elektrifikatsiya/Elektrifikatsiya/wwwroot/logo.png differ