User-spezifische API-Key-Auswahl, globales is_active entfernt

Backend:
- is_active komplett entfernt, durch is_public (Admin-Toggle) ersetzt
- Neues selected_api_key_id auf users-Tabelle
- AnthropicService: globaler _token entfernt, apiToken pro Request
- Token-Durchreichung: StreamChat → ProcessStream → RunAgentChat →
  RunPreparer/RunReview/RunFinalizer, ExecuteTool, send_to_session
- ChatEndpoint: User-Key aus DB laden, an StreamChat übergeben
- TelegramService: Key per bot.UserId auflösen
- CronjobService: Key per job.UserId auflösen
- Neue Endpoints: GET /api/api-keys/available, PUT /api/api-keys/select/{keyId},
  GET /api/api-keys/selected, PUT /api/admin/api-keys/{keyId}/public,
  POST /api/admin/api-keys/check-all
- Program.cs: AnthropicService ohne Token-Parameter

Frontend:
- API-Keys-Page: Public-Toggle (Globe/Lock) statt Activate/Deactivate
- Alle prüfen Button für Batch-Key-Check
- Chat: Key-Auswahl für alle User (nicht nur Admin)
- Dummy-Badge wenn kein Key ausgewählt
- Fallback-Badge bei Key ohne Usage-Daten
- Key-Switch-Modal: apiGetAvailableKeys + apiSelectApiKey
This commit is contained in:
Meleki committed 2026-03-13 12:27:03 +01:00
1 parent cc46cf2bbc
commit dde0fede7d
18 files changed
+340 -193

No files matched your search

+28
View File
@@ -187,4 +187,32 @@ public partial class DatabaseService
await conn.ExecuteAsync("DELETE FROM users WHERE user_id = @userId", new { userId });
}
// ── User API-Key Auswahl ──
public async Task SetUserSelectedApiKey(string userId, string keyId)
{
using var conn = CreateConnection();
await conn.ExecuteAsync(
"UPDATE users SET selected_api_key_id = @keyId, updated_at = @now WHERE user_id = @userId",
new { userId, keyId = (object)keyId ?? DBNull.Value, now = DateTime.UtcNow.ToString("o") });
}
public async Task<string> GetUserSelectedApiKeyId(string userId)
{
using var conn = CreateConnection();
return await conn.QuerySingleOrDefaultAsync<string>(
"SELECT selected_api_key_id FROM users WHERE user_id = @userId",
new { userId });
}
public async Task<ApiKeyRecord> GetUserSelectedApiKey(string userId)
{
using var conn = CreateConnection();
return await conn.QuerySingleOrDefaultAsync<ApiKeyRecord>(@"
SELECT k.* FROM api_keys k
INNER JOIN users u ON u.selected_api_key_id = k.key_id
WHERE u.user_id = @userId",
new { userId });
}
}