feat: Stripe-Key-Checker, Krea AI Pattern, Scan-Progress-Tracking
- StripeKeyChecker: 2-Schritt-Check (/v1/balance + /v1/account), Live/Test-Erkennung, Balance, Account-Details - KeyPatterns: Stripe-Patterns einkommentiert (sk_live_, sk_test_), Krea AI Pattern (UUID:Token), Mindest-Suchlänge 4 - KeyScannerService: Stripe-Check integriert, Auto-Check nach Scan entfernt (manuell separat), Progress-Tracking (Phase, Detail, Current/Total, KeysFound) - ApiKeysEndpoint: Stripe in HandleCheck/HandleCheckAll/HandleAdopt, Progress im Status-Endpoint - Frontend: Live-Fortschrittsanzeige mit Spinner, Phase, Query, Counter, Polling 1.5s, Krea AI in typeNames/typeIcons
This commit is contained in:
1 parent
122000487c
commit
3cd35ebbfa
6 files changed
+326
-14
No files matched your search
@@ -33,10 +33,38 @@ public class KeyScannerService : BackgroundService
|
||||
private readonly ManualResetEventSlim _triggerNow = new(false);
|
||||
private string _scanMode = "full"; // full, quick, web
|
||||
|
||||
// Progress-Tracking
|
||||
private string _progressPhase = "";
|
||||
private string _progressDetail = "";
|
||||
private int _progressCurrent;
|
||||
private int _progressTotal;
|
||||
private int _progressKeysFound;
|
||||
|
||||
public bool IsRunning { get { lock (_lock) return _isRunning; } }
|
||||
public string LastRun { get { lock (_lock) return _lastRun; } }
|
||||
public string LastResult { get { lock (_lock) return _lastResult; } }
|
||||
|
||||
public (string Phase, string Detail, int Current, int Total, int KeysFound) Progress
|
||||
{
|
||||
get { lock (_lock) return (_progressPhase, _progressDetail, _progressCurrent, _progressTotal, _progressKeysFound); }
|
||||
}
|
||||
|
||||
private void SetProgress(string phase, string detail = "", int current = 0, int total = 0)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_progressPhase = phase;
|
||||
_progressDetail = detail;
|
||||
_progressCurrent = current;
|
||||
_progressTotal = total;
|
||||
}
|
||||
}
|
||||
|
||||
private void IncrementKeysFound()
|
||||
{
|
||||
lock (_lock) _progressKeysFound++;
|
||||
}
|
||||
|
||||
private void AddLog(string type, string message, string details = null)
|
||||
{
|
||||
_logger.LogInformation("[CodeSearch] [{Type}] {Message}", type, message);
|
||||
@@ -161,6 +189,8 @@ public class KeyScannerService : BackgroundService
|
||||
var modeLabels = new Dictionary<string, string> { ["quick"] = "Quick", ["web"] = "Web", ["full"] = "Full" };
|
||||
var modeLabel = modeLabels.ContainsKey(mode) ? modeLabels[mode] : "Full";
|
||||
AddLog("scan", modeLabel + "-Scan gestartet");
|
||||
lock (_lock) _progressKeysFound = 0;
|
||||
SetProgress("Starte " + modeLabel + "-Scan…");
|
||||
var newKeysFound = 0;
|
||||
var totalFound = 0;
|
||||
|
||||
@@ -174,6 +204,7 @@ public class KeyScannerService : BackgroundService
|
||||
// Web: nur Serper
|
||||
if (mode != "web" && !string.IsNullOrWhiteSpace(_githubToken))
|
||||
{
|
||||
SetProgress("GitHub Code Search", "Starte…");
|
||||
var ghKeys = mode == "quick" ? await ScanGitHubQuick(ct) : await ScanGitHub(ct);
|
||||
allFoundKeys.AddRange(ghKeys.Select(k => (k.Key, k.Url, "github")));
|
||||
AddLog("scan", "GitHub-Scan (" + modeLabel + "): " + ghKeys.Count + " Key(s) gefunden");
|
||||
@@ -181,6 +212,7 @@ public class KeyScannerService : BackgroundService
|
||||
|
||||
if (mode != "quick" && !string.IsNullOrWhiteSpace(_serperApiKey))
|
||||
{
|
||||
SetProgress("Web-Suche (Serper)", "Starte…");
|
||||
var spKeys = await ScanSerper(ct);
|
||||
allFoundKeys.AddRange(spKeys.Select(k => (k.Key, k.Url, "serper")));
|
||||
AddLog("scan", "Serper-Scan: " + spKeys.Count + " Key(s) gefunden");
|
||||
@@ -189,9 +221,13 @@ public class KeyScannerService : BackgroundService
|
||||
totalFound = allFoundKeys.Count;
|
||||
|
||||
// Phase 2: Neue Keys in DB speichern (dedupliziert)
|
||||
SetProgress("Speichere Keys", totalFound + " gefunden, prüfe Duplikate…", 0, totalFound);
|
||||
var seen = new HashSet<string>(StringComparer.Ordinal);
|
||||
var saveIdx = 0;
|
||||
foreach (var (key, sourceUrl, source) in allFoundKeys)
|
||||
{
|
||||
saveIdx++;
|
||||
SetProgress("Speichere Keys", totalFound + " gefunden, prüfe Duplikate…", saveIdx, totalFound);
|
||||
if (!seen.Add(key)) continue;
|
||||
if (await _db.ScannedKeyExists(key) || await _db.ApiKeyExistsInKeys(key))
|
||||
continue;
|
||||
@@ -201,6 +237,7 @@ public class KeyScannerService : BackgroundService
|
||||
var typeName = KeyPatterns.DisplayName(keyType);
|
||||
|
||||
newKeysFound++;
|
||||
IncrementKeysFound();
|
||||
await _db.CreateScannedKey(new ScannedKeyRecord
|
||||
{
|
||||
ScannedKeyId = Guid.NewGuid().ToString("N"),
|
||||
@@ -234,6 +271,7 @@ public class KeyScannerService : BackgroundService
|
||||
_lastResult = $"{modeLabel}: {totalFound} gefunden, {newKeysFound} neu";
|
||||
}
|
||||
|
||||
SetProgress("Abgeschlossen", _lastResult);
|
||||
AddLog("scan", "Scan abgeschlossen – " + _lastResult);
|
||||
}
|
||||
catch (OperationCanceledException) { /* shutdown */ }
|
||||
@@ -286,6 +324,7 @@ public class KeyScannerService : BackgroundService
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
var (query, regex) = queries[i];
|
||||
SetProgress("GitHub Code Search (Quick)", query, i + 1, queries.Count);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -295,6 +334,7 @@ public class KeyScannerService : BackgroundService
|
||||
}
|
||||
catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||
{
|
||||
SetProgress("GitHub Code Search (Quick)", "⏳ Rate-Limit, warte 60s…", i + 1, queries.Count);
|
||||
AddLog("rate_limit", "GitHub Rate-Limit (Quick), warte 60s");
|
||||
await Task.Delay(60_000, ct);
|
||||
}
|
||||
@@ -323,6 +363,7 @@ public class KeyScannerService : BackgroundService
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
var (query, regex) = queries[i];
|
||||
SetProgress("GitHub Code Search", query, i + 1, queries.Count);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -332,6 +373,7 @@ public class KeyScannerService : BackgroundService
|
||||
}
|
||||
catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||
{
|
||||
SetProgress("GitHub Code Search", "⏳ Rate-Limit, warte 60s…", i + 1, queries.Count);
|
||||
AddLog("rate_limit", "GitHub Rate-Limit erreicht, warte 60s");
|
||||
await Task.Delay(60_000, ct);
|
||||
try
|
||||
@@ -484,9 +526,11 @@ public class KeyScannerService : BackgroundService
|
||||
var client = _httpFactory.CreateClient();
|
||||
client.DefaultRequestHeaders.Add("X-API-KEY", _serperApiKey);
|
||||
|
||||
foreach (var (pattern, searchTerm, _) in SearchPatterns)
|
||||
for (int i = 0; i < SearchPatterns.Length; i++)
|
||||
{
|
||||
var (pattern, searchTerm, _) = SearchPatterns[i];
|
||||
ct.ThrowIfCancellationRequested();
|
||||
SetProgress("Web-Suche (Serper)", searchTerm, i + 1, SearchPatterns.Length);
|
||||
var regex = new Regex(pattern, RegexOptions.Compiled);
|
||||
|
||||
try
|
||||
@@ -567,6 +611,14 @@ public class KeyScannerService : BackgroundService
|
||||
var checkMsg = $"🔍 {typeName} geprüft: {status} · {result.Message} · {keyPrefix}";
|
||||
AddLog("key_checked", checkMsg, JsonSerializer.Serialize(new { key_type = type, key_prefix = keyPrefix, status, message = result.Message, source_url = sk.SourceUrl }));
|
||||
}
|
||||
else if (type == "stripe_live" || type == "stripe_test")
|
||||
{
|
||||
var result = await StripeKeyChecker.CheckKeyAsync(_httpFactory, sk.ApiKey);
|
||||
var status = result.Status == "ok" ? "valid" : result.Status;
|
||||
await _db.UpdateScannedKeyStatus(sk.ScannedKeyId, status, result.Message, null, null);
|
||||
var checkMsg = $"🔍 {typeName} geprüft: {status} · {result.Message} · {keyPrefix}";
|
||||
AddLog("key_checked", checkMsg, JsonSerializer.Serialize(new { key_type = type, key_prefix = keyPrefix, status, message = result.Message, is_live = result.IsLiveKey, account_id = result.AccountId, account_name = result.AccountName, account_email = result.AccountEmail, country = result.AccountCountry, balance_available = result.BalanceAvailable, balance_pending = result.BalancePending, currency = result.Currency, charges_enabled = result.ChargesEnabled, payouts_enabled = result.PayoutsEnabled, source_url = sk.SourceUrl }));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Andere Key-Typen: Typ korrekt setzen, kein Check möglich
|
||||
|
||||
Reference in new issue
Block a user