From 17a5634c42079d2f370855fd6aa8ec677fccd595 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Mon, 3 Apr 2023 01:44:58 +0200 Subject: [PATCH] untested totp / password change --- Moonlight/App/Models/Misc/AuditLogType.cs | 1 + Moonlight/App/Services/TotpService.cs | 11 +- .../Navigations/ProfileNavigation.razor | 11 +- Moonlight/Shared/Views/Profile/Security.razor | 288 ++++++++++++++++++ .../Shared/Views/Profile/Subscriptions.razor | 2 +- Moonlight/resources/lang/de_de.lang | 16 +- 6 files changed, 322 insertions(+), 7 deletions(-) create mode 100644 Moonlight/Shared/Views/Profile/Security.razor diff --git a/Moonlight/App/Models/Misc/AuditLogType.cs b/Moonlight/App/Models/Misc/AuditLogType.cs index 13fafa1..a2ccf6d 100644 --- a/Moonlight/App/Models/Misc/AuditLogType.cs +++ b/Moonlight/App/Models/Misc/AuditLogType.cs @@ -23,4 +23,5 @@ public enum AuditLogType CleanupEnabled, CleanupDisabled, CleanupTriggered, + PasswordChange, } \ No newline at end of file diff --git a/Moonlight/App/Services/TotpService.cs b/Moonlight/App/Services/TotpService.cs index be76546..0e359fe 100644 --- a/Moonlight/App/Services/TotpService.cs +++ b/Moonlight/App/Services/TotpService.cs @@ -46,8 +46,7 @@ public class TotpService public async Task Enable() { var user = (await IdentityService.Get())!; - - user.TotpEnabled = true; + user.TotpSecret = GenerateSecret(); UserRepository.Update(user); @@ -55,6 +54,14 @@ public class TotpService await AuditLogService.Log(AuditLogType.EnableTotp, user.Email); } + public async Task EnforceTotpLogin() + { + var user = (await IdentityService.Get())!; + + user.TotpEnabled = true; + UserRepository.Update(user); + } + public async Task Disable() { var user = (await IdentityService.Get())!; diff --git a/Moonlight/Shared/Components/Navigations/ProfileNavigation.razor b/Moonlight/Shared/Components/Navigations/ProfileNavigation.razor index 67b3816..ab04ef6 100644 --- a/Moonlight/Shared/Components/Navigations/ProfileNavigation.razor +++ b/Moonlight/Shared/Components/Navigations/ProfileNavigation.razor @@ -27,12 +27,17 @@ diff --git a/Moonlight/Shared/Views/Profile/Security.razor b/Moonlight/Shared/Views/Profile/Security.razor new file mode 100644 index 0000000..8b29c58 --- /dev/null +++ b/Moonlight/Shared/Views/Profile/Security.razor @@ -0,0 +1,288 @@ +@page "/profile/security" + +@using Moonlight.Shared.Components.Navigations +@using QRCoder +@using Moonlight.App.Services.LogServices +@using Moonlight.App.Services.Sessions +@using Moonlight.App.Services +@using Moonlight.App.Services.Interop +@using System.Text.RegularExpressions +@using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Misc + +@inject SmartTranslateService SmartTranslateService +@inject AuditLogService AuditLogService +@inject TotpService TotpService +@inject NavigationManager NavigationManager +@inject IdentityService IdentityService +@inject UserService UserService +@inject AlertService AlertService +@inject ToastService ToastService + + + +
+
+
+

+ Security +

+
+
+ + +
+
+ @if (TotpEnabled) + { +
+ + + + + + +
+
+

+ Your account is secured with 2fa +

+
+ anyone write a fancy text here? +
+
+ + +
+
+ } + else + { +
+ + + + + + +
+
+

+ Secure your account +

+
+ 2fa adds another layer of security to your account. You have to enter a 6 digit code in order to login. +
+
+ + + Enable + +
+
+ } + + + + +
+
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+ +@code +{ + private bool TotpEnabled = false; + private bool EnablingTotp = false; + private string TotpSecret = ""; + private User User; + private string Issuer = "Moonlight"; + private string currentTotp = ""; + + private string Password = ""; + + private async void Enable() + { + await AuditLogService.Log(AuditLogType.EnableTotp, "Totp enabled"); + await TotpService.Enable(); + TotpEnabled = await TotpService.GetEnabled(); + TotpSecret = await TotpService.GetSecret(); + EnablingTotp = true; + StateHasChanged(); + } + + public async Task CheckAndSaveTotp() + { + if (await TotpService.Verify(TotpSecret, currentTotp)) + { + await TotpService.EnforceTotpLogin(); + TotpEnabled = await TotpService.GetEnabled(); + TotpSecret = await TotpService.GetSecret(); + await ToastService.Success("Successfully enabled 2fa!"); + } + else + { + await AlertService.Error("2fa code incorrect", "The given 2fa code is incorrect. Maybe check if the code in your 2fa app has changed."); + } + } + + private async void Disable() + { + await AuditLogService.Log(AuditLogType.DisableTotp, "Totp disabled"); + await TotpService.Disable(); + NavigationManager.NavigateTo(NavigationManager.Uri, true); + } + + private async Task Load(LazyLoader lazyLoader) + { + await lazyLoader.SetText("Requesting secrets"); + + TotpEnabled = await TotpService.GetEnabled(); + TotpSecret = await TotpService.GetSecret(); + + await lazyLoader.SetText("Requesting identity"); + User = await IdentityService.Get(); + + await InvokeAsync(StateHasChanged); + } + + private async Task ChangePassword() + { + if (Regex.IsMatch(Password, @"^(?=.*[A-Za-z])(?=.*\d)[A-Za-z@$!%*#.,?&\d]{8,}$")) + { + await UserService.ChangePassword(User, Password); + + await AuditLogService.Log(AuditLogType.PasswordChange, "The password has been set to a new one"); + + // Reload to make the user login again + NavigationManager.NavigateTo(NavigationManager.Uri, true); + } + else + { + await AlertService.Error("Error", "Your password must be at least 8 characters and must contain a number"); + } + } +} \ No newline at end of file diff --git a/Moonlight/Shared/Views/Profile/Subscriptions.razor b/Moonlight/Shared/Views/Profile/Subscriptions.razor index 2a371a6..30b8d19 100644 --- a/Moonlight/Shared/Views/Profile/Subscriptions.razor +++ b/Moonlight/Shared/Views/Profile/Subscriptions.razor @@ -8,7 +8,7 @@ @inject SmartTranslateService SmartTranslateService @inject NavigationManager NavigationManager - +
diff --git a/Moonlight/resources/lang/de_de.lang b/Moonlight/resources/lang/de_de.lang index 8f280da..c520cf7 100644 --- a/Moonlight/resources/lang/de_de.lang +++ b/Moonlight/resources/lang/de_de.lang @@ -406,4 +406,18 @@ The City field is required.;The City field is required. The State field is required.;The State field is required. The Country field is required.;The Country field is required. Street and house number requered;Street and house number requered -Max lenght reached;Max lenght reached \ No newline at end of file +Max lenght reached;Max lenght reached +Security;Security +Subscriptions;Subscriptions +Secure your account;Secure your account +2fa adds another layer of security to your account. You have to enter a 6 digit code in order to login.;2fa adds another layer of security to your account. You have to enter a 6 digit code in order to login. +enable;enable +Activate 2fa;Activate 2fa +2fa apps;2fa apps +Use an app like ;Use an app like +or;or +and scan the following QR Code;and scan the following QR Code +If you have trouble using the QR Code, select manual input in the app and enter your email and the following code:;If you have trouble using the QR Code, select manual input in the app and enter your email and the following code: +Finish activation;Finish activation +New password;New password +Enable;Enable