Merge pull request 'enhancement/UserInfo' (#48) from enhancement/UserInfo into development

Reviewed-on: daniel-hbn/Watcher#48
This commit is contained in:
2025-06-25 21:54:03 +00:00
8 changed files with 196 additions and 229 deletions

View File

@@ -110,126 +110,5 @@ public class AuthController : Controller
// Anzeigen der User-Informationen
[Authorize]
public IActionResult Info()
{
var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToList();
var Identity_User = User.Identity?.Name;
var user = _context.Users.FirstOrDefault(u => u.Username == Identity_User);
if (user == null) return NotFound();
// Anzeigedaten
var DbProvider = _context.Database.ProviderName;
var username = user.Username;
var mail = user.Email;
var Id = user.Id;
// Anzeigedaten an View übergeben
ViewBag.Claims = claims;
ViewBag.Name = username;
ViewBag.Mail = mail;
ViewBag.Id = Id;
return View();
}
// Edit-Form anzeigen
[Authorize]
[HttpGet]
public IActionResult Edit()
{
var username = User.Identity?.Name;
var user = _context.Users.FirstOrDefault(u => u.Username == username);
if (user == null) return NotFound();
var model = new EditUserViewModel
{
Username = user.Username
};
return View(model);
}
// Edit speichern
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(EditUserViewModel model)
{
if (!ModelState.IsValid) return View(model);
var username = User.Identity?.Name;
var user = _context.Users.FirstOrDefault(u => u.Username == username);
if (user == null) return NotFound();
user.Username = model.Username;
if (!string.IsNullOrWhiteSpace(model.NewPassword))
{
user.Password = BCrypt.Net.BCrypt.HashPassword(model.NewPassword);
}
_context.SaveChanges();
// Eventuell hier das Auth-Cookie erneuern, wenn Username sich ändert
_logger.LogTrace("Passwort-Change durchgeführt");
return RedirectToAction("Index", "Home");
}
// Edit-Form anzeigen
[Authorize]
[HttpGet]
public IActionResult UserSettings()
{
var username = User.Identity?.Name;
Console.WriteLine("gefundener User: " + username);
var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToList();
var user = _context.Users.FirstOrDefault(u => u.Username == username);
if (user == null) return NotFound();
var DbProvider = _context.Database.ProviderName;
var mail = user.Email;
ViewBag.Name = username;
ViewBag.mail = mail;
ViewBag.Claims = claims;
ViewBag.IdentityProvider = user.IdentityProvider;
ViewBag.DbProvider = DbProvider;
return View();
}
// Edit speichern
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult UserSettings(EditUserViewModel model)
{
if (!ModelState.IsValid) return View(model);
var username = User.Identity?.Name;
var user = _context.Users.FirstOrDefault(u => u.Username == username);
if (user == null) return NotFound();
var databaseProvider = _context.Database.ProviderName;
user.Username = model.Username;
// Passwort ändern
if (!string.IsNullOrWhiteSpace(model.NewPassword))
{
user.Username = BCrypt.Net.BCrypt.HashPassword(model.NewPassword);
}
_context.SaveChanges();
// Eventuell hier das Auth-Cookie erneuern, wenn Username sich ändert
return RedirectToAction("Index", "Home");
}
}

View File

@@ -115,13 +115,15 @@ namespace Watcher.Controllers
//return Ok($"Dump erfolgreich erstellt: {dumpFileName}");
TempData["DumpMessage"] = "SQLite-Dump erfolgreich erstellt.";
return RedirectToAction("UserSettings", "Auth");
_logger.LogInformation("SQLite-Dump erfolgreich erstellt.");
return RedirectToAction("UserSettings", "User");
}
catch (Exception ex)
{
//return StatusCode(500, $"Fehler beim Erstellen des Dumps: {ex.Message}");
TempData["DumpError"] = $"Fehler beim Erstellen des Dumps: {ex.Message}";
return RedirectToAction("UserSettings", "Auth");
_logger.LogError("Fehler beim Erstellen des Dumps: {message}", ex.Message);
return RedirectToAction("UserSettings", "User");
}
}

View File

@@ -0,0 +1,146 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Watcher.Data;
using Watcher.ViewModels;
namespace Watcher.Controllers;
public class UserController : Controller
{
private readonly AppDbContext _context;
private readonly ILogger<UserController> _logger;
public UserController(AppDbContext context, ILogger<UserController> logger)
{
_context = context;
_logger = logger;
}
// Anzeigen der User-Informationen
[Authorize]
public IActionResult Info()
{
var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToList();
var Identity_User = User.Identity?.Name;
var user = _context.Users.FirstOrDefault(u => u.Username == Identity_User);
if (user == null) return NotFound();
// Anzeigedaten
var DbProvider = _context.Database.ProviderName;
var username = user.Username;
var mail = user.Email;
var Id = user.Id;
var IdProvider = user.IdentityProvider;
// Anzeigedaten an View übergeben
ViewBag.Claims = claims;
ViewBag.Name = username;
ViewBag.Mail = mail;
ViewBag.Id = Id;
ViewBag.IdProvider = IdProvider;
return View();
}
// Edit-Form anzeigen
[Authorize]
[HttpGet]
public IActionResult Edit()
{
var username = User.Identity?.Name;
var user = _context.Users.FirstOrDefault(u => u.Username == username);
if (user == null) return NotFound();
var model = new EditUserViewModel
{
Username = user.Username
};
return View(model);
}
// Edit speichern
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(EditUserViewModel model)
{
if (!ModelState.IsValid) return View(model);
var username = User.Identity?.Name;
var user = _context.Users.FirstOrDefault(u => u.Username == username);
if (user == null) return NotFound();
user.Username = model.Username;
if (!string.IsNullOrWhiteSpace(model.NewPassword))
{
user.Password = BCrypt.Net.BCrypt.HashPassword(model.NewPassword);
}
_context.SaveChanges();
// Eventuell hier das Auth-Cookie erneuern, wenn Username sich ändert
_logger.LogTrace("Passwort-Change durchgeführt");
return RedirectToAction("Index", "Home");
}
// Edit-Form anzeigen
[Authorize]
[HttpGet]
public IActionResult UserSettings()
{
var username = User.Identity?.Name;
Console.WriteLine("gefundener User: " + username);
var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToList();
var user = _context.Users.FirstOrDefault(u => u.Username == username);
if (user == null) return NotFound();
var DbProvider = _context.Database.ProviderName;
var mail = user.Email;
ViewBag.Name = username;
ViewBag.mail = mail;
ViewBag.Claims = claims;
ViewBag.IdentityProvider = user.IdentityProvider;
ViewBag.DbProvider = DbProvider;
return View();
}
// Edit speichern
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult UserSettings(EditUserViewModel model)
{
if (!ModelState.IsValid) return View(model);
var username = User.Identity?.Name;
var user = _context.Users.FirstOrDefault(u => u.Username == username);
if (user == null) return NotFound();
var databaseProvider = _context.Database.ProviderName;
user.Username = model.Username;
// Passwort ändern
if (!string.IsNullOrWhiteSpace(model.NewPassword))
{
user.Username = BCrypt.Net.BCrypt.HashPassword(model.NewPassword);
}
_context.SaveChanges();
// Eventuell hier das Auth-Cookie erneuern, wenn Username sich ändert
return RedirectToAction("Index", "Home");
}
}

View File

@@ -87,13 +87,13 @@
<div class="account-box mt-auto">
@if (User.Identity?.IsAuthenticated ?? false)
{
<a href="/Auth/Info" class="d-block text-decoration-none text-light">
<a href="/User/Info" class="d-block text-decoration-none text-light">
<div class="d-flex align-items-center gap-2">
<div class="rounded-circle bg-secondary text-white px-2 py-1">
<i class="bi bi-person"></i>
</div>
<div>
<strong>@User.Claims.FirstOrDefault(c => c.Type == "name")?.Value</strong><br />
<strong>@User.Identity?.Name</strong><br />
<small class="text-muted">Profil ansehen</small>
</div>
</div>

View File

@@ -1,9 +1,9 @@
@{
ViewData["Title"] = "Account Info";
var pictureUrl = User.Claims.FirstOrDefault(c => c.Type == "picture")?.Value ?? "";
var preferredUsername = User.Claims.FirstOrDefault(c => c.Type == "preferred_username")?.Value ?? "admin";
var isAdmin = preferredUsername == "admin";
var preferred_username = ViewBag.name;
var Id = ViewBag.Id;
var preferredUsername = ViewBag.name;
var IdProvider = ViewBag.IdProvider;
}
<div class="container mt-5">
@@ -21,7 +21,7 @@
</div>
}
<h3 class="mt-3">
<i class="bi bi-person-circle me-1"></i>@(User.FindFirst("PreferredUsername")?.Value ?? "Unbekannter Nutzer")
<i class="bi bi-person-circle me-1"></i>@preferredUsername
</h3>
</div>
@@ -40,6 +40,8 @@
<th><i class="bi bi-fingerprint me-1"></i>Benutzer-ID</th>
<td>@(ViewBag.Id ?? "Nicht verfügbar")</td>
</tr>
@if(IdProvider != "local")
{
<tr>
<th><i class="bi bi-clock-history me-1"></i>Login-Zeit</th>
<td>
@@ -77,10 +79,12 @@
}
</td>
</tr>
}
</tbody>
</table>
<div>
<form method="get" asp-controller="Auth" asp-action="UserSettings" class="text-center mt-4">
<form method="get" asp-controller="User" asp-action="UserSettings" class="text-center mt-4">
<button type="submit" class="btn btn-info">
<i class="bi bi-gear-wide-connected me-1"></i>Einstellungen
</button>

View File

@@ -27,7 +27,7 @@
{
<div class="card shadow mt-5 p-4" style="width: 40%; margin: auto;">
<h4><i class="bi bi-pencil-square me-2"></i>Benutzerdaten ändern</h4>
<form asp-action="Edit" method="post" asp-controller="Auth">
<form asp-action="Edit" method="post" asp-controller="User">
<div class="mb-3">
<label for="Username" class="form-label">Neuer Benutzername</label>
<input type="text" class="form-control" id="Username" name="Username" value="@preferredUsername" />
@@ -111,20 +111,45 @@
</div>
<div class="card shadow mt-5 p-4" style="width: 55%; margin: auto;">
<h4><i class="bi bi-pencil-square me-2"></i>Systemeinstellungen ändern</h4>
<h5>Anzeigeeinstellungen: </h5>
<hr class="my-4" />
<h4><i class="bi bi-pencil-square me-2"></i>Systemeinstellungen</h4>
<h5>Benachrichtigungen: </h5>
<p>Registrierte E-Mail Adresse: <strong>@(ViewBag.mail ?? "nicht gefunden")</strong></p>
<!-- action="/Notification/UpdateSettings" existiert noch nicht-->
<form method="post" action="#">
<div class="card p-4 shadow-sm" style="max-width: 500px;">
<h5 class="card-title mb-3">
<i class="bi bi-bell me-2"></i>Benachrichtigungseinstellungen
</h5>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" id="notifyOffline" name="NotifyOffline" checked>
<label class="form-check-label" for="notifyOffline">Benachrichtigung bei Server-Offline</label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" id="notifyUpdates" name="NotifyUpdates">
<label class="form-check-label" for="notifyUpdates">Benachrichtigung bei neuen Updates</label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" id="notifyUser" name="NotifyUser">
<label class="form-check-label" for="notifyUser">Benachrichtigung bei neuen Benutzern</label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" id="notifyMaintenance" name="NotifyMaintenance">
<label class="form-check-label" for="notifyMaintenance">Wartungsinformationen erhalten</label>
</div>
<button type="submit" class="btn btn-primary mt-3">
<i class="bi bi-save me-1"></i>Speichern
</button>
</div>
</form>
<hr class="my-4" />
<h5>...: </h5>
</div>
</div>

View File

@@ -1,89 +0,0 @@
CREATE TABLE "__EFMigrationsHistory" (
"MigrationId" TEXT NOT NULL CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY,
"ProductVersion" TEXT NOT NULL
);
CREATE TABLE "Tags" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Tags" PRIMARY KEY AUTOINCREMENT,
"Name" TEXT NULL
);
CREATE TABLE sqlite_sequence(name,seq);
CREATE TABLE "Servers" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Servers" PRIMARY KEY AUTOINCREMENT,
"CpuCores" INTEGER NOT NULL,
"CpuType" TEXT NULL,
"CreatedAt" TEXT NOT NULL,
"Description" TEXT NULL,
"GpuType" TEXT NULL,
"IPAddress" TEXT NOT NULL,
"IsOnline" INTEGER NOT NULL,
"LastSeen" TEXT NOT NULL,
"Name" TEXT NOT NULL,
"RamSize" REAL NOT NULL,
"TagId" INTEGER NULL,
"Type" TEXT NOT NULL, "IsVerified" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "FK_Servers_Tags_TagId" FOREIGN KEY ("TagId") REFERENCES "Tags" ("Id")
);
CREATE TABLE "LogEvents" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_LogEvents" PRIMARY KEY AUTOINCREMENT,
"ContainerId" INTEGER NULL,
"Level" TEXT NULL,
"Message" TEXT NULL,
"ServerId" INTEGER NULL,
"Timestamp" TEXT NOT NULL,
CONSTRAINT "FK_LogEvents_Containers_ContainerId" FOREIGN KEY ("ContainerId") REFERENCES "Containers" ("Id"),
CONSTRAINT "FK_LogEvents_Servers_ServerId" FOREIGN KEY ("ServerId") REFERENCES "Servers" ("Id")
);
CREATE TABLE "Images" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Images" PRIMARY KEY AUTOINCREMENT,
"Name" TEXT NULL,
"Tag" TEXT NULL
);
CREATE TABLE "Containers" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Containers" PRIMARY KEY AUTOINCREMENT,
"CreatedAt" TEXT NOT NULL,
"Hostname" TEXT NOT NULL,
"ImageId" INTEGER NULL,
"IsRunning" INTEGER NOT NULL,
"Name" TEXT NOT NULL,
"Status" TEXT NOT NULL,
"TagId" INTEGER NULL,
"Type" TEXT NOT NULL,
CONSTRAINT "FK_Containers_Images_ImageId" FOREIGN KEY ("ImageId") REFERENCES "Images" ("Id"),
CONSTRAINT "FK_Containers_Tags_TagId" FOREIGN KEY ("TagId") REFERENCES "Tags" ("Id")
);
CREATE TABLE "Metrics" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Metrics" PRIMARY KEY AUTOINCREMENT,
"CPU_Load" REAL NOT NULL,
"CPU_Temp" REAL NOT NULL,
"DISK_Size" REAL NOT NULL,
"DISK_Temp" REAL NOT NULL,
"DISK_Usage" REAL NOT NULL,
"GPU_Load" REAL NOT NULL,
"GPU_Temp" REAL NOT NULL,
"GPU_Vram_Size" REAL NOT NULL,
"GPU_Vram_Usage" REAL NOT NULL,
"NET_In" REAL NOT NULL,
"NET_Out" REAL NOT NULL,
"RAM_Load" REAL NOT NULL,
"RAM_Size" REAL NOT NULL,
"ServerId" INTEGER NULL,
"Timestamp" TEXT NOT NULL
);
CREATE TABLE "Users" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Users" PRIMARY KEY AUTOINCREMENT,
"Email" TEXT NULL,
"IdentityProvider" TEXT NOT NULL,
"LastLogin" TEXT NOT NULL,
"OIDC_Id" TEXT NULL,
"Password" TEXT NOT NULL,
"Username" TEXT NOT NULL
);
INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) VALUES ('20250617153602_InitialMigration','8.0.6');
INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) VALUES ('20250617165126_ServerPrimaryKey','8.0.6');
INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) VALUES ('20250617174242_UserPasswordAdded','8.0.6');
INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) VALUES ('20250621124832_DB-Update Issue#32','8.0.6');
INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) VALUES ('20250621125157_DB-Update Issue#32 IsVerified-Servers','8.0.6');
INSERT INTO Servers (Id,CpuCores,CpuType,CreatedAt,Description,GpuType,IPAddress,IsOnline,LastSeen,Name,RamSize,TagId,Type,IsVerified) VALUES ('2','0','','2025-06-21 13:56:23.5504821','','','192.168.178.158','1','2025-06-23 14:30:23.9455939','Ubuntu Workstation','0',NULL,'Standalone','0');
INSERT INTO Servers (Id,CpuCores,CpuType,CreatedAt,Description,GpuType,IPAddress,IsOnline,LastSeen,Name,RamSize,TagId,Type,IsVerified) VALUES ('3','0','','2025-06-23 14:03:08.8875782','','','82.29.178.161','0','0001-01-01 00:00:00','hostinger-vps-1','0',NULL,'VPS','0');
INSERT INTO Servers (Id,CpuCores,CpuType,CreatedAt,Description,GpuType,IPAddress,IsOnline,LastSeen,Name,RamSize,TagId,Type,IsVerified) VALUES ('4','0','','2025-06-23 14:07:49.0219821','','','192.168.178.68','0','0001-01-01 00:00:00','Unraid NAS','0',NULL,'Standalone','0');
INSERT INTO Users (Id,Email,IdentityProvider,LastLogin,OIDC_Id,Password,Username) VALUES ('1','','local','2025-06-21 13:54:26.4374285','','$2a$11$iWF.vOrHuzgelKm3xWeJouVtmUd7LemK11yDxlw9t.YbLUZtJWRH6','admin');