Serilog konfiguriert und Code in Heartbeat- Home- und Auth-Controller aufräumen gestartet
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,6 @@
|
|||||||
# Per-Use special Files and Directories
|
# Per-Use special Files and Directories
|
||||||
/persistance/*.db
|
/persistance/*.db
|
||||||
/logs
|
/logs/*.log
|
||||||
*.env
|
*.env
|
||||||
/wwwroot/downloads/sqlite/*.sql
|
/wwwroot/downloads/sqlite/*.sql
|
||||||
|
|
||||||
|
@@ -22,12 +22,19 @@ public class AuthController : Controller
|
|||||||
private readonly AppDbContext _context;
|
private readonly AppDbContext _context;
|
||||||
private readonly AppSettings _settings;
|
private readonly AppSettings _settings;
|
||||||
|
|
||||||
public AuthController(AppDbContext context, IOptions<AppSettings> options)
|
// Logging einbinden
|
||||||
|
private readonly ILogger<AuthController> _logger;
|
||||||
|
|
||||||
|
|
||||||
|
public AuthController(AppDbContext context, IOptions<AppSettings> options, ILogger<AuthController> logger)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_settings = options.Value;
|
_settings = options.Value;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Login Seite anzeigen
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult Login(string? returnUrl = null)
|
public IActionResult Login(string? returnUrl = null)
|
||||||
{
|
{
|
||||||
@@ -41,6 +48,7 @@ public class AuthController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Login mit lokalem User
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Login(LoginViewModel model)
|
public async Task<IActionResult> Login(LoginViewModel model)
|
||||||
{
|
{
|
||||||
@@ -55,20 +63,23 @@ public class AuthController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
var claims = new List<Claim>
|
var claims = new List<Claim>
|
||||||
{
|
{
|
||||||
new Claim(ClaimTypes.Name, user.Username),
|
new Claim(ClaimTypes.Name, user.Username),
|
||||||
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
||||||
};
|
};
|
||||||
|
|
||||||
var identity = new ClaimsIdentity(claims, "local");
|
var identity = new ClaimsIdentity(claims, "local");
|
||||||
var principal = new ClaimsPrincipal(identity);
|
var principal = new ClaimsPrincipal(identity);
|
||||||
|
|
||||||
await HttpContext.SignInAsync("Cookies", principal);
|
await HttpContext.SignInAsync("Cookies", principal);
|
||||||
|
|
||||||
|
_logger.LogInformation("lokaler User angemeldet: " + user.Username);
|
||||||
|
|
||||||
return Redirect("Home/Index");
|
return Redirect("Home/Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Login mit OIDC-Provider
|
||||||
public IActionResult SignIn()
|
public IActionResult SignIn()
|
||||||
{
|
{
|
||||||
return Challenge(new AuthenticationProperties
|
return Challenge(new AuthenticationProperties
|
||||||
@@ -77,6 +88,9 @@ public class AuthController : Controller
|
|||||||
}, "oidc");
|
}, "oidc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Logout
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public async Task<IActionResult> Logout()
|
public async Task<IActionResult> Logout()
|
||||||
@@ -89,26 +103,32 @@ public class AuthController : Controller
|
|||||||
await HttpContext.SignOutAsync("Cookies");
|
await HttpContext.SignOutAsync("Cookies");
|
||||||
await HttpContext.SignOutAsync("oidc", props);
|
await HttpContext.SignOutAsync("oidc", props);
|
||||||
|
|
||||||
|
_logger.LogInformation("User abgemeldet");
|
||||||
|
|
||||||
return Redirect("/"); // nur als Fallback
|
return Redirect("/"); // nur als Fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Anzeigen der User-Informationen
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public IActionResult Info()
|
public IActionResult Info()
|
||||||
{
|
{
|
||||||
var username = User.Identity?.Name;
|
|
||||||
Console.WriteLine("gefundener User: " + username);
|
|
||||||
var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToList();
|
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 == username);
|
var user = _context.Users.FirstOrDefault(u => u.Username == Identity_User);
|
||||||
if (user == null) return NotFound();
|
if (user == null) return NotFound();
|
||||||
|
|
||||||
|
// Anzeigedaten
|
||||||
var DbProvider = _context.Database.ProviderName;
|
var DbProvider = _context.Database.ProviderName;
|
||||||
|
var username = user.Username;
|
||||||
var mail = user.Email;
|
var mail = user.Email;
|
||||||
var Id = user.Id;
|
var Id = user.Id;
|
||||||
|
|
||||||
ViewBag.Name = username;
|
// Anzeigedaten an View übergeben
|
||||||
ViewBag.Claims = claims;
|
ViewBag.Claims = claims;
|
||||||
|
ViewBag.Name = username;
|
||||||
ViewBag.Mail = mail;
|
ViewBag.Mail = mail;
|
||||||
ViewBag.Id = Id;
|
ViewBag.Id = Id;
|
||||||
|
|
||||||
@@ -154,9 +174,12 @@ public class AuthController : Controller
|
|||||||
|
|
||||||
// Eventuell hier das Auth-Cookie erneuern, wenn Username sich ändert
|
// Eventuell hier das Auth-Cookie erneuern, wenn Username sich ändert
|
||||||
|
|
||||||
|
_logger.LogTrace("Passwort-Change durchgeführt");
|
||||||
|
|
||||||
return RedirectToAction("Index", "Home");
|
return RedirectToAction("Index", "Home");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Edit-Form anzeigen
|
// Edit-Form anzeigen
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
@@ -1,13 +1,10 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using Watcher.Data;
|
using Watcher.Data;
|
||||||
using Watcher.Models;
|
using Watcher.Models;
|
||||||
using Watcher.ViewModels;
|
|
||||||
|
|
||||||
|
// eingehender Heartbeat-Payload
|
||||||
public class HeartbeatDto
|
public class HeartbeatDto
|
||||||
{
|
{
|
||||||
public string? IpAddress { get; set; }
|
public string? IpAddress { get; set; }
|
||||||
@@ -18,18 +15,27 @@ public class HeartbeatDto
|
|||||||
public class HeartbeatController : Controller
|
public class HeartbeatController : Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Datenbankverbindung
|
||||||
private readonly AppDbContext _context;
|
private readonly AppDbContext _context;
|
||||||
|
|
||||||
public HeartbeatController(AppDbContext context)
|
// Logging einbinden
|
||||||
|
private readonly ILogger<HeartbeatController> _logger;
|
||||||
|
|
||||||
|
public HeartbeatController(AppDbContext context, ILogger<HeartbeatController> logger)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Endpoint um Heartbeat-Payloads zu empfangen
|
||||||
[HttpPost("receive")]
|
[HttpPost("receive")]
|
||||||
public async Task<IActionResult> Receive([FromBody] HeartbeatDto dto)
|
public async Task<IActionResult> Receive([FromBody] HeartbeatDto dto)
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation("Heartbeat empfangen");
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(dto.IpAddress))
|
if (string.IsNullOrWhiteSpace(dto.IpAddress))
|
||||||
{
|
{
|
||||||
|
_logger.LogWarning("Eingehender Payload enthält keine IP-Adresse");
|
||||||
return BadRequest("Missing IP address.");
|
return BadRequest("Missing IP address.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,9 +46,11 @@ public class HeartbeatController : Controller
|
|||||||
{
|
{
|
||||||
server.LastSeen = DateTime.UtcNow;
|
server.LastSeen = DateTime.UtcNow;
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
_logger.LogInformation("Heartbeat von {server} in Datenbank eingetragen.", server.Name);
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.LogWarning("Eingehender Payload kann keiner bekannten IP-Adresse zugewiesen werden.");
|
||||||
return NotFound("No matching server found.");
|
return NotFound("No matching server found.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
|
// .NET Packages
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Security.Claims;
|
// Local Namespaces
|
||||||
using Watcher.Data;
|
using Watcher.Data;
|
||||||
using Watcher.Models;
|
|
||||||
using Watcher.ViewModels;
|
using Watcher.ViewModels;
|
||||||
|
|
||||||
namespace Watcher.Controllers
|
namespace Watcher.Controllers
|
||||||
@@ -11,13 +11,20 @@ namespace Watcher.Controllers
|
|||||||
[Authorize]
|
[Authorize]
|
||||||
public class HomeController : Controller
|
public class HomeController : Controller
|
||||||
{
|
{
|
||||||
|
// Datenbankverbindung
|
||||||
private readonly AppDbContext _context;
|
private readonly AppDbContext _context;
|
||||||
|
|
||||||
public HomeController(AppDbContext context)
|
// Logging einbinden
|
||||||
|
private readonly ILogger<HomeController> _logger;
|
||||||
|
|
||||||
|
// HomeController Constructor
|
||||||
|
public HomeController(AppDbContext context, ILogger<HomeController> logger)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dashboard unter /home/index
|
||||||
public async Task<IActionResult> Index()
|
public async Task<IActionResult> Index()
|
||||||
{
|
{
|
||||||
var preferredUserName = User.FindFirst("preferred_username")?.Value;
|
var preferredUserName = User.FindFirst("preferred_username")?.Value;
|
||||||
@@ -39,9 +46,10 @@ namespace Watcher.Controllers
|
|||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Funktion für /Views/Home/Index.cshtml um das DashboardStats-Partial neu zu laden.
|
||||||
|
// Die Funktion wird nicht direkt aufgerufen, sondern nur der /Home/DashboardStats Endpoint angefragt.
|
||||||
public IActionResult DashboardStats()
|
public IActionResult DashboardStats()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Dashboard aktualisiert");
|
|
||||||
var servers = _context.Servers.ToList();
|
var servers = _context.Servers.ToList();
|
||||||
var containers = _context.Containers.ToList();
|
var containers = _context.Containers.ToList();
|
||||||
|
|
||||||
@@ -51,9 +59,12 @@ namespace Watcher.Controllers
|
|||||||
{
|
{
|
||||||
ActiveServers = servers.Count(s => (now - s.LastSeen).TotalSeconds <= 120),
|
ActiveServers = servers.Count(s => (now - s.LastSeen).TotalSeconds <= 120),
|
||||||
OfflineServers = servers.Count(s => (now - s.LastSeen).TotalSeconds > 120),
|
OfflineServers = servers.Count(s => (now - s.LastSeen).TotalSeconds > 120),
|
||||||
|
|
||||||
|
//TODO: anwendbar, wenn Container implementiert wurden.
|
||||||
//RunningContainers = containers.Count(c => (now - c.LastSeen).TotalSeconds <= 120),
|
//RunningContainers = containers.Count(c => (now - c.LastSeen).TotalSeconds <= 120),
|
||||||
//FailedContainers = containers.Count(c => (now - c.LastSeen).TotalSeconds > 120),
|
//FailedContainers = containers.Count(c => (now - c.LastSeen).TotalSeconds > 120),
|
||||||
LastLogin = DateTime.Now // Oder was auch immer hier richtig ist
|
|
||||||
|
LastLogin = DateTime.Now
|
||||||
};
|
};
|
||||||
|
|
||||||
return PartialView("_DashboardStats", model);
|
return PartialView("_DashboardStats", model);
|
||||||
|
@@ -4,17 +4,39 @@ using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Sqlite;
|
using Microsoft.EntityFrameworkCore.Sqlite;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
using Watcher.Data;
|
using Watcher.Data;
|
||||||
using Watcher.Models;
|
using Watcher.Models;
|
||||||
|
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
|
||||||
|
// Serilog konfigurieren – nur Logs, die nicht von Microsoft stammen
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
.MinimumLevel.Information()
|
||||||
|
.MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning) // <--
|
||||||
|
.Enrich.FromLogContext()
|
||||||
|
.WriteTo.File(
|
||||||
|
"logs/watcher-.log",
|
||||||
|
outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}",
|
||||||
|
rollingInterval: RollingInterval.Day
|
||||||
|
)
|
||||||
|
.CreateLogger();
|
||||||
|
|
||||||
|
builder.Host.UseSerilog();
|
||||||
|
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
builder.Services.AddControllersWithViews();
|
builder.Services.AddControllersWithViews();
|
||||||
|
|
||||||
|
|
||||||
// HttpContentAccessor
|
// HttpContentAccessor
|
||||||
builder.Services.AddHttpContextAccessor();
|
builder.Services.AddHttpContextAccessor();
|
||||||
|
|
||||||
|
|
||||||
// ---------- Konfiguration ----------
|
// ---------- Konfiguration ----------
|
||||||
DotNetEnv.Env.Load();
|
DotNetEnv.Env.Load();
|
||||||
|
|
||||||
@@ -22,14 +44,14 @@ builder.Configuration
|
|||||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||||
.AddEnvironmentVariables();
|
.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
|
||||||
// Konfiguration laden
|
// Konfiguration laden
|
||||||
var configuration = builder.Configuration;
|
var configuration = builder.Configuration;
|
||||||
|
|
||||||
// ---------- DB-Kontext ----------
|
|
||||||
|
|
||||||
|
// ---------- DB-Kontext ----------
|
||||||
var dbProvider = configuration["Database:Provider"] ?? "MySQL";
|
var dbProvider = configuration["Database:Provider"] ?? "MySQL";
|
||||||
var connectionString = configuration["Database:ConnectionString"];
|
var connectionString = configuration["Database:ConnectionString"];
|
||||||
|
|
||||||
builder.Services.AddDbContext<AppDbContext>((serviceProvider, options) =>
|
builder.Services.AddDbContext<AppDbContext>((serviceProvider, options) =>
|
||||||
{
|
{
|
||||||
var config = serviceProvider.GetRequiredService<IConfiguration>();
|
var config = serviceProvider.GetRequiredService<IConfiguration>();
|
||||||
@@ -51,19 +73,21 @@ builder.Services.AddDbContext<AppDbContext>((serviceProvider, options) =>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// ---------- Authentifizierung konfigurieren ----------
|
// ---------- Authentifizierung konfigurieren ----------
|
||||||
// PocketID nur konfigurieren, wenn aktiviert
|
// PocketID nur konfigurieren, wenn aktiviert
|
||||||
var pocketIdSection = builder.Configuration.GetSection("Authentication:PocketID");
|
var pocketIdSection = builder.Configuration.GetSection("Authentication:PocketID");
|
||||||
var pocketIdEnabled = pocketIdSection.GetValue<bool>("Enabled");
|
var pocketIdEnabled = pocketIdSection.GetValue<bool>("Enabled");
|
||||||
|
|
||||||
var auth = builder.Services.AddAuthentication("Cookies");
|
|
||||||
|
|
||||||
|
var auth = builder.Services.AddAuthentication("Cookies");
|
||||||
auth.AddCookie("Cookies", options =>
|
auth.AddCookie("Cookies", options =>
|
||||||
{
|
{
|
||||||
options.LoginPath = "/Auth/Login";
|
options.LoginPath = "/Auth/Login";
|
||||||
options.AccessDeniedPath = "/Auth/AccessDenied";
|
options.AccessDeniedPath = "/Auth/AccessDenied";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
builder.Services.AddAuthentication()
|
builder.Services.AddAuthentication()
|
||||||
.AddOpenIdConnect("oidc", options =>
|
.AddOpenIdConnect("oidc", options =>
|
||||||
{
|
{
|
||||||
@@ -124,12 +148,9 @@ builder.Services.AddAuthentication()
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Migrationen anwenden (für SQLite oder andere DBs)
|
// Migrationen anwenden (für SQLite oder andere DBs)
|
||||||
using (var scope = app.Services.CreateScope())
|
using (var scope = app.Services.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -169,6 +190,7 @@ using (var scope = app.Services.CreateScope())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
if (!app.Environment.IsDevelopment())
|
if (!app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
@@ -178,10 +200,6 @@ if (!app.Environment.IsDevelopment())
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
@@ -190,11 +208,9 @@ app.UseAuthorization();
|
|||||||
|
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
|
||||||
|
|
||||||
app.MapControllerRoute(
|
app.MapControllerRoute(
|
||||||
name: "default",
|
name: "default",
|
||||||
pattern: "{controller=Auth}/{action=Login}/"
|
pattern: "{controller=Auth}/{action=Login}/"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
@@ -47,6 +47,7 @@
|
|||||||
try {
|
try {
|
||||||
const response = await fetch('/Home/DashboardStats');
|
const response = await fetch('/Home/DashboardStats');
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
console.log("reload")
|
||||||
const html = await response.text();
|
const html = await response.text();
|
||||||
document.getElementById('dashboard-stats').innerHTML = html;
|
document.getElementById('dashboard-stats').innerHTML = html;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
<!-- Auth via OpenID Connect + Cookies -->
|
<!-- Auth via OpenID Connect + Cookies -->
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.3.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.3.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.6" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.6" />
|
||||||
|
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
Reference in New Issue
Block a user