feat: Admin-Benutzerverwaltung + Dashboard-Layout-Fixes
Backend: - AdminEndpoint.cs: 5 Endpunkte (List, Create, Update, Reset PW, Delete) - Admin-only - DatabaseService: CreateUser(), UpdateUserAdmin(), DeleteUser() (kaskadiert Tokens + Shares) - Route in Program.cs registriert Frontend: - admin-page.js: User-Liste mit Edit/Delete, Inline-Formular Create/Edit - api.js: 5 Admin-API-Funktionen - index.html: Template tpl-admin, Script-Tag, Dashboard-Link 'Benutzerverwaltung' - dashboard.js: Admin-Link nur für Admins sichtbar - form.css: Styles für admin-user-list, admin-user-row, admin-checkbox-row - dashboard.css: Header-Overflow-Fix, Agents vor Cronjobs - index.html: Template-Reihenfolge Agents vor Cronjobs TODO: User-Management als erledigt markiert
This commit is contained in:
1 parent
489b5e0eb0
commit
3ef78b5eb1
10 files changed
+667
-57
No files matched your search
@@ -912,6 +912,34 @@ public class DatabaseService
|
||||
new { userId, settings, now = DateTime.UtcNow.ToString("o") });
|
||||
}
|
||||
|
||||
public async Task<UserRecord> CreateUser(string username, string passwordHash, string displayName, bool isAdmin)
|
||||
{
|
||||
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 });
|
||||
return await GetUser(userId);
|
||||
}
|
||||
|
||||
public async Task UpdateUserAdmin(string userId, string username, string displayName, bool isAdmin)
|
||||
{
|
||||
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") });
|
||||
}
|
||||
|
||||
public async Task DeleteUser(string userId)
|
||||
{
|
||||
using var conn = CreateConnection();
|
||||
await conn.ExecuteAsync("DELETE FROM tokens WHERE user_id = @userId", new { userId });
|
||||
await conn.ExecuteAsync("DELETE FROM shared_messages WHERE user_id = @userId", new { userId });
|
||||
await conn.ExecuteAsync("DELETE FROM users WHERE user_id = @userId", new { userId });
|
||||
}
|
||||
|
||||
// ── Telegram (Session-basiert) ──
|
||||
|
||||
public async Task<SessionRecord> GetSessionByTelegramChatId(long chatId)
|
||||
|
||||
Reference in new issue
Block a user