From dfc2b5af177853e94a15b817b6e9f99b4778f8f6 Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Mon, 5 Feb 2024 22:39:09 +0100 Subject: [PATCH] Added hotkey service. Modified jwt service to use jwt types --- Moonlight/Core/Configuration/ConfigV1.cs | 12 ++++++ Moonlight/Core/Services/HotKeyService.cs | 39 +++++++++++++++++++ Moonlight/Core/Services/IdentityService.cs | 2 +- .../Core/Services/Users/UserAuthService.cs | 10 ++++- Moonlight/Core/Services/Utils/JwtService.cs | 33 +++++++++++++--- 5 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 Moonlight/Core/Services/HotKeyService.cs diff --git a/Moonlight/Core/Configuration/ConfigV1.cs b/Moonlight/Core/Configuration/ConfigV1.cs index 1e611326..bdc56855 100644 --- a/Moonlight/Core/Configuration/ConfigV1.cs +++ b/Moonlight/Core/Configuration/ConfigV1.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using MoonCore.Helpers; using Moonlight.Features.Advertisement.Configuration; +using Moonlight.Features.FileManager.Configuration; using Moonlight.Features.StoreSystem.Configuration; using Moonlight.Features.Theming.Configuration; using Newtonsoft.Json; @@ -22,6 +23,17 @@ public class ConfigV1 [JsonProperty("Theme")] public ThemeData Theme { get; set; } = new(); [JsonProperty("Advertisement")] public AdvertisementData Advertisement { get; set; } = new(); + [JsonProperty("FileManager")] public FileManagerData FileManager { get; set; } = new(); + + [JsonProperty("WebServer")] public WebServerData WebServer { get; set; } = new(); + + public class WebServerData + { + [JsonProperty("HttpUploadLimit")] + [Description("This sets the kestrel upload limit in megabytes. Changing this will need an restart")] + public int HttpUploadLimit { get; set; } = 100 * 1024; + } + public class SecurityData { [JsonProperty("Token")] diff --git a/Moonlight/Core/Services/HotKeyService.cs b/Moonlight/Core/Services/HotKeyService.cs new file mode 100644 index 00000000..ec9541de --- /dev/null +++ b/Moonlight/Core/Services/HotKeyService.cs @@ -0,0 +1,39 @@ +using Microsoft.JSInterop; +using MoonCore.Attributes; +using MoonCore.Helpers; + +namespace Moonlight.Core.Services; + +[Scoped] +public class HotKeyService : IAsyncDisposable +{ + private readonly IJSRuntime JsRuntime; + + public SmartEventHandler HotKeyPressed { get; set; } = new(); + + public HotKeyService(IJSRuntime jsRuntime) + { + JsRuntime = jsRuntime; + } + + public async Task Initialize() + { + var reference = DotNetObjectReference.Create(this); + await JsRuntime.InvokeVoidAsync("moonlight.hotkeys.registerListener", reference); + } + + [JSInvokable] + public async void OnHotkeyPressed(string hotKey) + { + await HotKeyPressed.Invoke(hotKey); + } + + public async ValueTask DisposeAsync() + { + try + { + await JsRuntime.InvokeVoidAsync("moonlight.keyListener.unregisterListener"); + } + catch (Exception) { /* ignored */} + } +} \ No newline at end of file diff --git a/Moonlight/Core/Services/IdentityService.cs b/Moonlight/Core/Services/IdentityService.cs index 5ea75267..f66570f0 100644 --- a/Moonlight/Core/Services/IdentityService.cs +++ b/Moonlight/Core/Services/IdentityService.cs @@ -152,7 +152,7 @@ public class IdentityService { data.Add("userId", user.Id.ToString()); data.Add("issuedAt", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()); - }, TimeSpan.FromDays(10)); + }, "User", TimeSpan.FromDays(10)); return token; } diff --git a/Moonlight/Core/Services/Users/UserAuthService.cs b/Moonlight/Core/Services/Users/UserAuthService.cs index f09ca716..f5034e9c 100644 --- a/Moonlight/Core/Services/Users/UserAuthService.cs +++ b/Moonlight/Core/Services/Users/UserAuthService.cs @@ -101,7 +101,10 @@ public class UserAuthService public async Task SendVerification(User user) { - var jwt = await JwtService.Create(data => { data.Add("mailToVerify", user.Email); }, TimeSpan.FromMinutes(10)); + var jwt = await JwtService.Create(data => + { + data.Add("mailToVerify", user.Email); + }, "EmailVerification", TimeSpan.FromMinutes(10)); await MailService.Send(user, "Verify your account", "verifyMail", user, new MailVerify() { @@ -118,7 +121,10 @@ public class UserAuthService if (user == null) throw new DisplayException("An account with that email was not found"); - var jwt = await JwtService.Create(data => { data.Add("accountToReset", user.Id.ToString()); }); + var jwt = await JwtService.Create(data => + { + data.Add("accountToReset", user.Id.ToString()); + }, "PasswordReset", TimeSpan.FromHours(1)); await MailService.Send(user, "Password reset for your account", "passwordReset", user, new ResetPassword() { diff --git a/Moonlight/Core/Services/Utils/JwtService.cs b/Moonlight/Core/Services/Utils/JwtService.cs index ef671370..ababe258 100644 --- a/Moonlight/Core/Services/Utils/JwtService.cs +++ b/Moonlight/Core/Services/Utils/JwtService.cs @@ -19,11 +19,12 @@ public class JwtService ConfigService = configService; } - public Task Create(Action> data, TimeSpan? validDuration = null) + public Task Create(Action> data, string type, TimeSpan? validDuration = null) { var builder = new JwtBuilder() .WithSecret(ConfigService.Get().Security.Token) .IssuedAt(DateTime.UtcNow) + .AddHeader("Type", type) .ExpirationTime(DateTime.UtcNow.Add(validDuration ?? DefaultDuration)) .WithAlgorithm(new HMACSHA512Algorithm()); @@ -38,17 +39,39 @@ public class JwtService return Task.FromResult(jwt); } - public Task Validate(string token) + public Task Validate(string token, params string[] allowedJwtTypes) { try { - _ = new JwtBuilder() + var headerJson = new JwtBuilder() .WithSecret(ConfigService.Get().Security.Token) .WithAlgorithm(new HMACSHA512Algorithm()) .MustVerifySignature() - .Decode(token); + .DecodeHeader(token); + + if (headerJson == null) + return Task.FromResult(false); - return Task.FromResult(true); + // Jwt type validation + if(allowedJwtTypes.Length == 0) + return Task.FromResult(true); + + var headerData = JsonConvert.DeserializeObject>(headerJson); + + if(headerData == null) // => Invalid header + return Task.FromResult(false); + + if(!headerData.ContainsKey("Type")) // => Invalid header, Type is missing + return Task.FromResult(false); + + foreach (var name in allowedJwtTypes) + { + if(headerData["Type"] == name) // => Correct type found + return Task.FromResult(true); + } + + // None found? Invalid type! + return Task.FromResult(false); } catch (Exception e) {