diff --git a/Endpoints/AdminEndpoint.cs b/Endpoints/AdminEndpoint.cs index d4d417a..f03bdc4 100644 --- a/Endpoints/AdminEndpoint.cs +++ b/Endpoints/AdminEndpoint.cs @@ -17,6 +17,7 @@ public static class AdminEndpoint app.MapPut("/api/admin/users/{userId}", HandleUpdateUser); app.MapPut("/api/admin/users/{userId}/password", HandleResetPassword); app.MapDelete("/api/admin/users/{userId}", HandleDeleteUser); + app.MapPost("/api/admin/users/{userId}/impersonate", HandleImpersonate); } private static async System.Threading.Tasks.Task HandleListUsers(HttpContext ctx, DatabaseService db) @@ -35,6 +36,7 @@ public static class AdminEndpoint username = u.Username, displayName = u.DisplayName, isAdmin = u.IsAdmin, + defaultPath = u.DefaultPath, createdAt = u.CreatedAt, updatedAt = u.UpdatedAt }); @@ -56,6 +58,7 @@ public static class AdminEndpoint var password = body.TryGetProperty("password", out var p) ? p.GetString() : null; var displayName = body.TryGetProperty("displayName", out var dn) ? dn.GetString() : null; var isAdmin = body.TryGetProperty("isAdmin", out var ia) && ia.GetBoolean(); + var defaultPath = body.TryGetProperty("defaultPath", out var dp) ? dp.GetString() : null; if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password)) { @@ -80,7 +83,7 @@ public static class AdminEndpoint } var hash = auth.HashPassword(password); - var user = await db.CreateUser(username, hash, displayName, isAdmin); + var user = await db.CreateUser(username, hash, displayName, isAdmin, defaultPath); ctx.Response.StatusCode = 201; await ctx.Response.WriteAsJsonAsync(new @@ -89,6 +92,7 @@ public static class AdminEndpoint username = user.Username, displayName = user.DisplayName, isAdmin = user.IsAdmin, + defaultPath = user.DefaultPath, createdAt = user.CreatedAt }); } @@ -114,6 +118,7 @@ public static class AdminEndpoint var username = body.TryGetProperty("username", out var u) ? u.GetString() : user.Username; var displayName = body.TryGetProperty("displayName", out var dn) ? dn.GetString() : user.DisplayName; var isAdmin = body.TryGetProperty("isAdmin", out var ia) ? ia.GetBoolean() : user.IsAdmin; + var defaultPath = body.TryGetProperty("defaultPath", out var dp) ? dp.GetString() : user.DefaultPath; if (string.IsNullOrWhiteSpace(username)) { @@ -131,7 +136,7 @@ public static class AdminEndpoint return; } - await db.UpdateUserAdmin(userId, username, displayName, isAdmin); + await db.UpdateUserAdmin(userId, username, displayName, isAdmin, defaultPath); var updated = await db.GetUser(userId); await ctx.Response.WriteAsJsonAsync(new @@ -140,6 +145,7 @@ public static class AdminEndpoint username = updated.Username, displayName = updated.DisplayName, isAdmin = updated.IsAdmin, + defaultPath = updated.DefaultPath, createdAt = updated.CreatedAt, updatedAt = updated.UpdatedAt }); @@ -207,4 +213,41 @@ public static class AdminEndpoint await db.DeleteUser(userId); await ctx.Response.WriteAsJsonAsync(new { ok = true }); } + + private static async System.Threading.Tasks.Task HandleImpersonate(HttpContext ctx, DatabaseService db, AuthService auth, string userId) + { + if (!ctx.IsAdmin()) + { + ctx.Response.StatusCode = 403; + await ctx.Response.WriteAsJsonAsync(new { error = "Admin access required" }); + return; + } + + var user = await db.GetUser(userId); + if (user == null) + { + ctx.Response.StatusCode = 404; + await ctx.Response.WriteAsJsonAsync(new { error = "Benutzer nicht gefunden" }); + return; + } + + // Token für den Zieluser erstellen und als Cookie setzen + var token = auth.CreateToken(user.UserId); + + ctx.Response.Cookies.Append("gott_token", token, new CookieOptions + { + HttpOnly = true, + SameSite = SameSiteMode.Strict, + Path = "/", + MaxAge = System.TimeSpan.FromDays(365) + }); + + await ctx.Response.WriteAsJsonAsync(new + { + userId = user.UserId, + username = user.Username, + displayName = user.DisplayName, + isAdmin = user.IsAdmin + }); + } } diff --git a/Endpoints/AuthEndpoint.cs b/Endpoints/AuthEndpoint.cs index 0a25292..5550c65 100644 --- a/Endpoints/AuthEndpoint.cs +++ b/Endpoints/AuthEndpoint.cs @@ -93,7 +93,8 @@ public static class AuthEndpoint userId = user.UserId, username = user.Username, displayName = user.DisplayName, - isAdmin = user.IsAdmin + isAdmin = user.IsAdmin, + defaultPath = user.DefaultPath }); } } diff --git a/Endpoints/ProfileEndpoint.cs b/Endpoints/ProfileEndpoint.cs index 6a276c3..e7faa18 100644 --- a/Endpoints/ProfileEndpoint.cs +++ b/Endpoints/ProfileEndpoint.cs @@ -33,6 +33,7 @@ public static class ProfileEndpoint username = user.Username, displayName = user.DisplayName, persona = user.Persona, + defaultPath = user.DefaultPath, isAdmin = user.IsAdmin }); } @@ -44,8 +45,9 @@ public static class ProfileEndpoint var displayName = body.TryGetProperty("displayName", out var dn) ? dn.GetString() : null; var persona = body.TryGetProperty("persona", out var p) ? p.GetString() : null; + var defaultPath = body.TryGetProperty("defaultPath", out var dp) ? dp.GetString() : null; - await db.UpdateUserProfile(userId, displayName, persona); + await db.UpdateUserProfile(userId, displayName, persona, defaultPath); var user = await db.GetUser(userId); await ctx.Response.WriteAsJsonAsync(new @@ -54,6 +56,7 @@ public static class ProfileEndpoint username = user.Username, displayName = user.DisplayName, persona = user.Persona, + defaultPath = user.DefaultPath, isAdmin = user.IsAdmin }); } diff --git a/Models/UserRecord.cs b/Models/UserRecord.cs index 205fdd8..0551834 100644 --- a/Models/UserRecord.cs +++ b/Models/UserRecord.cs @@ -12,6 +12,7 @@ public class UserRecord public bool IsAdmin { get; set; } public string Persona { get; set; } public string Settings { get; set; } + public string DefaultPath { get; set; } public string GetEffectivePersona() { diff --git a/Services/DatabaseService.cs b/Services/DatabaseService.cs index 576b4a6..70e1fa0 100644 --- a/Services/DatabaseService.cs +++ b/Services/DatabaseService.cs @@ -166,6 +166,7 @@ public class DatabaseService TryAddColumn(conn, "users", "is_admin", "INTEGER NOT NULL DEFAULT 0"); TryAddColumn(conn, "users", "persona", "TEXT"); TryAddColumn(conn, "users", "settings", "TEXT"); + TryAddColumn(conn, "users", "default_path", "TEXT"); TryAddColumn(conn, "cronjobs", "notify_session_id", "TEXT"); conn.Execute(@" @@ -888,12 +889,12 @@ public class DatabaseService new { userId, passwordHash, now = DateTime.UtcNow.ToString("o") }); } - public async Task UpdateUserProfile(string userId, string displayName, string persona) + public async Task UpdateUserProfile(string userId, string displayName, string persona, string defaultPath = null) { using var conn = CreateConnection(); await conn.ExecuteAsync( - "UPDATE users SET display_name = @displayName, persona = @persona, updated_at = @now WHERE user_id = @userId", - new { userId, displayName, persona, now = DateTime.UtcNow.ToString("o") }); + "UPDATE users SET display_name = @displayName, persona = @persona, default_path = @defaultPath, updated_at = @now WHERE user_id = @userId", + new { userId, displayName, persona, defaultPath, now = DateTime.UtcNow.ToString("o") }); } public async Task GetUserSettings(string userId) @@ -912,24 +913,24 @@ public class DatabaseService new { userId, settings, now = DateTime.UtcNow.ToString("o") }); } - public async Task CreateUser(string username, string passwordHash, string displayName, bool isAdmin) + public async Task CreateUser(string username, string passwordHash, string displayName, bool isAdmin, string defaultPath = null) { using var conn = CreateConnection(); var now = DateTime.UtcNow.ToString("o"); var userId = Guid.NewGuid().ToString("N"); await conn.ExecuteAsync(@" - INSERT INTO users (user_id, username, password_hash, display_name, is_admin, created_at, updated_at) - VALUES (@userId, @username, @passwordHash, @displayName, @isAdmin, @now, @now)", - new { userId, username, passwordHash, displayName, isAdmin, now }); + INSERT INTO users (user_id, username, password_hash, display_name, is_admin, default_path, created_at, updated_at) + VALUES (@userId, @username, @passwordHash, @displayName, @isAdmin, @defaultPath, @now, @now)", + new { userId, username, passwordHash, displayName, isAdmin, defaultPath, now }); return await GetUser(userId); } - public async Task UpdateUserAdmin(string userId, string username, string displayName, bool isAdmin) + public async Task UpdateUserAdmin(string userId, string username, string displayName, bool isAdmin, string defaultPath) { using var conn = CreateConnection(); await conn.ExecuteAsync( - "UPDATE users SET username = @username, display_name = @displayName, is_admin = @isAdmin, updated_at = @now WHERE user_id = @userId", - new { userId, username, displayName, isAdmin, now = DateTime.UtcNow.ToString("o") }); + "UPDATE users SET username = @username, display_name = @displayName, is_admin = @isAdmin, default_path = @defaultPath, updated_at = @now WHERE user_id = @userId", + new { userId, username, displayName, isAdmin, defaultPath, now = DateTime.UtcNow.ToString("o") }); } public async Task DeleteUser(string userId) diff --git a/wwwroot/index.html b/wwwroot/index.html index b3a755a..50ceec9 100644 --- a/wwwroot/index.html +++ b/wwwroot/index.html @@ -397,6 +397,12 @@ + + Wird als Basis-Pfad beim Auswählen eines Workspace in Sessions verwendet. +
+ + +
Wird im System-Prompt verwendet, wenn der Agent "Kennt sein Gegenüber" aktiviert hat. @@ -448,6 +454,11 @@ + +
+ + +