diff --git a/src/Controllers/SettingsController.cs b/src/Controllers/SettingsController.cs index 713cc57..bcdb255 100644 --- a/src/Controllers/SettingsController.cs +++ b/src/Controllers/SettingsController.cs @@ -3,11 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Novell.Directory.Ldap; using Berufsschule_HAM.Models; using Berufsschule_HAM.Helpers; -using System.Security.Cryptography; -using System.Text; using Microsoft.AspNetCore.Authorization; -using System.Text.Json; -using System.Buffers.Text; [Authorize] [Route("[controller]")] @@ -23,11 +19,60 @@ public class SettingsController : Controller } [HttpGet("User")] - public new IActionResult User() + public async Task UserAsync() { - return View(); + try + { + var userID = User.Identity?.Name ?? throw new Exception("No name specified"); + UserSettingsModel userSettingsModel = new() + { + userModel = await _ldap.GetUserByUidAsync(userID) + }; + return View(userSettingsModel); + } catch (Exception ex) + { + _logger.LogWarning("An exception happened when trying to show user settings view: {ex.Message} - {ex.StackTrace}", [ex.Message, ex.StackTrace]); + return Redirect("/Home/Logout"); + } } + [HttpPut("User")] + public async Task UpdateUserAsync([FromBody]UserUpdateRequestModel userUpdateRequestModel) + { + if (userUpdateRequestModel is null) + { + return new() {Success = false, ErrorMessage = "userUpdateRequestModel is null"}; + } + try + { + var userID = User.Identity?.Name ?? throw new Exception("No name specified"); + bool anyUpdated = false; + if (userUpdateRequestModel.Password is not null && userUpdateRequestModel.Password.Length > 0) + { + await _ldap.UpdateUser(userID, "userPassword", await UsersHelper.HashPassword(_ldap, userUpdateRequestModel.Password)); + anyUpdated = true; + } + if (userUpdateRequestModel.Image is not null && userUpdateRequestModel.Image.Length > 0) + { + await _ldap.UpdateUser(userID, "jpegPhoto", userUpdateRequestModel.Image); + anyUpdated = true; + } + if (anyUpdated) + { + return new() {Success = true}; + } + else + { + return new() {Success = false, ErrorMessage = "Nothing was updated"}; + } + } catch (Exception ex) + { + _logger.LogWarning("An exception happened when trying to update a user: {ex.Message} - {ex.StackTrace}", [ex.Message, ex.StackTrace]); + return new() {Success = false, ErrorMessage = ex.Message}; + } + } + + [Authorize(Roles = "CanManageSettings")] [HttpGet("Admin")] public async Task AdminAsync() diff --git a/src/Controllers/UsersController.cs b/src/Controllers/UsersController.cs index 5e4fd51..76b5378 100644 --- a/src/Controllers/UsersController.cs +++ b/src/Controllers/UsersController.cs @@ -70,7 +70,6 @@ public class UsersController : Controller } try { - Task settingsTask = _ldap.GetAdminSettingsModelAsync(); string? jpegPhoto = requestModel.JpegPhoto; string? title = requestModel.Title; string userPassword = requestModel.UserPassword ?? ""; @@ -81,10 +80,7 @@ public class UsersController : Controller description ??= new() {Address = new(), BirthDate = "", Workplace = "", Groups = []}; if (!userPassword.StartsWith('{')) { - AdminSettingsModel settings = await settingsTask; - byte[] passwordBytes = Encoding.UTF8.GetBytes(userPassword); - byte[] hashedPassword = settings.hashAlgorithm?.ComputeHash(passwordBytes) ?? throw new Exception("Hash algorithm not instantiated yet"); - userPassword = $"{{{settings.DefaultHashAlgorithm.ToUpperInvariant()}}}{Convert.ToBase64String(hashedPassword)}"; + userPassword = await UsersHelper.HashPassword(_ldap, userPassword); } LdapAttributeSet attributeSet = @@ -118,7 +114,6 @@ public class UsersController : Controller } try { - Task settingsTask = _ldap.GetAdminSettingsModelAsync(); string uid = requestModel.Uid; UserModel? user = null; if (requestModel.NewUid is not null && requestModel.NewUid.Length > 0) @@ -140,11 +135,8 @@ public class UsersController : Controller await _ldap.UpdateUser(uid, "jpegPhoto", requestModel.JpegPhoto); } if (requestModel.UserPassword is not null && requestModel.UserPassword.Length > 0) - { - AdminSettingsModel settings = await settingsTask; - byte[] passwordBytes = Encoding.UTF8.GetBytes(requestModel.UserPassword); - byte[] hashedPassword = settings.hashAlgorithm?.ComputeHash(passwordBytes) ?? throw new Exception("Hash algorithm not instantiated yet"); - requestModel.UserPassword = $"{{{settings.DefaultHashAlgorithm.ToUpperInvariant()}}}{Convert.ToBase64String(hashedPassword)}"; + { + requestModel.UserPassword = await UsersHelper.HashPassword(_ldap, requestModel.UserPassword); await _ldap.UpdateUser(uid, "userPassword", requestModel.UserPassword); } diff --git a/src/Helpers/UsersHelper.cs b/src/Helpers/UsersHelper.cs index 41edf60..975fd85 100644 --- a/src/Helpers/UsersHelper.cs +++ b/src/Helpers/UsersHelper.cs @@ -1,6 +1,8 @@ using System.Globalization; using System.Text; using System.Text.RegularExpressions; +using Berufsschule_HAM.Models; +using Berufsschule_HAM.Services; namespace Berufsschule_HAM.Helpers; public static partial class UsersHelper @@ -39,6 +41,14 @@ public static partial class UsersHelper return cleaned; } + public static async Task HashPassword(LdapService ldapService, string password) + { + AdminSettingsModel settings = await ldapService.GetAdminSettingsModelAsync(); + byte[] passwordBytes = Encoding.UTF8.GetBytes(password); + byte[] hashedPassword = settings.hashAlgorithm?.ComputeHash(passwordBytes) ?? throw new Exception("Hash algorithm not instantiated yet"); + return $"{{{settings.DefaultHashAlgorithm.ToUpperInvariant()}}}{Convert.ToBase64String(hashedPassword)}"; + } + [GeneratedRegex("[^a-z]")] private static partial Regex AtoZ(); } \ No newline at end of file diff --git a/src/Models/SettingsRequestModels.cs b/src/Models/SettingsRequestModels.cs index 1979cee..f57623e 100644 --- a/src/Models/SettingsRequestModels.cs +++ b/src/Models/SettingsRequestModels.cs @@ -2,6 +2,15 @@ using System.Text.Json.Serialization; namespace Berufsschule_HAM.Models; +public class UserUpdateRequestModel +{ + [JsonPropertyName("Password")] + public string? Password { get; set; } + + [JsonPropertyName("Image")] + public string? Image { get; set; } +} + public class AdminUpdateRequestModel { [JsonPropertyName("AdminSettingsModel")] diff --git a/src/Models/SettingsResponseModels.cs b/src/Models/SettingsResponseModels.cs index 8687996..7e0dbc2 100644 --- a/src/Models/SettingsResponseModels.cs +++ b/src/Models/SettingsResponseModels.cs @@ -2,6 +2,14 @@ using System.Text.Json.Serialization; namespace Berufsschule_HAM.Models; +public class UserUpdateResponseModel +{ + [JsonPropertyName("Success")] + public required bool Success { get; set; } + [JsonPropertyName("ErrorMessage")] + public string? ErrorMessage { get; set; } +} + public class AdminUpdateResponseModel { [JsonPropertyName("Success")] diff --git a/src/Models/UserSettingsModel.cs b/src/Models/UserSettingsModel.cs new file mode 100644 index 0000000..8adddbc --- /dev/null +++ b/src/Models/UserSettingsModel.cs @@ -0,0 +1,6 @@ +using Berufsschule_HAM.Models; + +public class UserSettingsModel +{ + public required UserModel userModel; +} \ No newline at end of file diff --git a/src/Resources/Views.Settings.User.de.resx b/src/Resources/Views.Settings.User.de.resx new file mode 100644 index 0000000..532804f --- /dev/null +++ b/src/Resources/Views.Settings.User.de.resx @@ -0,0 +1,67 @@ + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, ... + + + System.Resources.ResXResourceWriter, System.Windows.Forms, ... + + + + Einstellungen + + + Persönliche Daten + + + Benutzername + + + Anrede + + + Name + + + Nachname + + + Geburtsdatum + + + Adresse + + + Konto + + + Arbeitsplatz + + + Passwort + + + Profilbild + + + Änderungen anwenden + + + Passwort muss mindestens 8 Zeichen lang sein und Groß- und Kleinbuchstaben, sowie Zahlen und Sonderzeichen enthalten + + + Einstellungen erfolgreich aktualisiert + + + Unbekannter Fehler + + + Fehler bei der Kommunikation mit dem Server + + diff --git a/src/Views/Settings/User.cshtml b/src/Views/Settings/User.cshtml index e9c7309..e64adff 100644 --- a/src/Views/Settings/User.cshtml +++ b/src/Views/Settings/User.cshtml @@ -1 +1,132 @@ -

Empty view lol

\ No newline at end of file +@using Microsoft.AspNetCore.Mvc.Localization +@using Berufsschule_HAM.Models +@model UserSettingsModel +@inject IViewLocalizer T +@inject IConfiguration Configuration +@{ + ViewData["Title"] = T["User settings"]; + string barcodeType = Configuration["BarcodeType"] ?? "EAN13"; +} + + +
+

@T["Account"]

+
+
+ + +
+
+ + +
+
+
+
+ + + +
+ +
+
+
+

@T["Personal data"]

+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+
+
+ + + \ No newline at end of file