Huge updates

This commit is contained in:
MarcWieland
2026-06-24 22:29:05 +02:00
parent 94c10aebdd
commit 0d59d521dc
12 changed files with 559 additions and 40 deletions
+20
View File
@@ -55,6 +55,26 @@ public class AuthService(IDbContextFactory<TimetrackerDbContext> factory, UserNo
return null;
}
public async Task<string?> ChangePasswordAsync(int userId, string currentPassword, string newPassword)
{
if (string.IsNullOrWhiteSpace(newPassword) || newPassword.Length < 6)
return "Passwort muss mindestens 6 Zeichen lang sein.";
await using var db = await factory.CreateDbContextAsync();
var user = await db.Users.FindAsync(userId);
if (user == null) return "Benutzer nicht gefunden.";
if (!VerifyPassword(currentPassword, user.PasswordHash, user.PasswordSalt))
return "Das aktuelle Passwort ist nicht korrekt.";
var (hash, salt) = HashPassword(newPassword);
user.PasswordHash = hash;
user.PasswordSalt = salt;
await db.SaveChangesAsync();
return null;
}
public async Task<(User? User, string? Error)> RegisterAsync(string username, string password, string? honeypot = null) {
if (string.IsNullOrWhiteSpace(username) || username.Length < 3)
return (null, "Benutzername muss mindestens 3 Zeichen lang sein.");
@@ -173,7 +173,10 @@ public class TimetrackerService(IDbContextFactory<TimetrackerDbContext> factory)
.Where(b => b.StartTime.HasValue && b.EndTime.HasValue && b.EndTime > b.StartTime)
.Aggregate(TimeSpan.Zero, (s, b) =>
s + (b.EndTime!.Value.ToTimeSpan() - b.StartTime!.Value.ToTimeSpan()));
actual = (gross - breakTotal).TotalHours;
var minMinutes = gross.TotalHours >= 9.0 ? 45 : 30;
var minBreak = TimeSpan.FromMinutes(Math.Max(minMinutes, settings.MinimumBreakMinutes));
var finalBreak = breakTotal > minBreak ? breakTotal : minBreak;
actual = (gross - finalBreak).TotalHours;
if (actual < 0) actual = 0.0;
}
}
+11
View File
@@ -243,6 +243,16 @@ usersApi.MapPut("/{userId:int}/rename", async (int userId, [FromBody] RenameRequ
return Results.Ok();
});
usersApi.MapPut("/{userId:int}/change-password", async (int userId, [FromBody] ChangePasswordRequest req, IAuthService authService) =>
{
var error = await authService.ChangePasswordAsync(userId, req.CurrentPassword, req.NewPassword);
if (error != null)
{
return Results.BadRequest(error);
}
return Results.Ok();
});
// ── Timetracker-API-Endpoints (Protected) ─────────────────────────────────────
var trackerApi = app.MapGroup("/api/tracker").RequireAuthorization();
@@ -362,3 +372,4 @@ app.Run();
public record LoginRequest(string Username, string Password);
public record RegisterRequest(string Username, string Password, string? Honeypot = null);
public record RenameRequest(string Username);
public record ChangePasswordRequest(string CurrentPassword, string NewPassword);