Refactor UI with purple dark theme glassmorphism, projects management, license editing, agent installer scripts, unmaskable tokens, C# test suite
This commit is contained in:
@@ -2,3 +2,6 @@
|
|||||||
scratch/
|
scratch/
|
||||||
*.bak
|
*.bak
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
*.user
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<AppName>Deploymentcenter Test Suite</AppName>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Deploymentcenter.TestClient;
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
private static readonly string BaseUrl = "https://dc.mhdf.de";
|
||||||
|
private static readonly HttpClient Client = new HttpClient(new HttpClientHandler
|
||||||
|
{
|
||||||
|
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
|
||||||
|
});
|
||||||
|
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.OutputEncoding = Encoding.UTF8;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
|
Console.WriteLine("=================================================");
|
||||||
|
Console.WriteLine(" 🚀 Deploymentcenter Unified Client Test Suite ");
|
||||||
|
Console.WriteLine("=================================================");
|
||||||
|
Console.ResetColor();
|
||||||
|
Console.WriteLine($" Server Base URL: {BaseUrl}\n");
|
||||||
|
|
||||||
|
await TestLicenseModuleAsync();
|
||||||
|
await TestWatchdogModuleAsync();
|
||||||
|
await TestUpdateServiceModuleAsync();
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Console.WriteLine("\n[✔] Alle Systemprüfungen erfolgreich abgeschlossen!");
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task TestLicenseModuleAsync()
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine("1. Teste Module: Lizenzen (License Validation)...");
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var payload = new
|
||||||
|
{
|
||||||
|
product = "myapp",
|
||||||
|
license_key = "LLAB1-98A72-B3C4D-5E6F7-89012",
|
||||||
|
hardware_id = "HWID-TEST-CLI-CSHARP-01",
|
||||||
|
nonce = Guid.NewGuid().ToString("N"),
|
||||||
|
hostname = Environment.MachineName,
|
||||||
|
app_version = "1.0.0"
|
||||||
|
};
|
||||||
|
|
||||||
|
string json = JsonSerializer.Serialize(payload);
|
||||||
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
HttpResponseMessage response = await Client.PostAsync($"{BaseUrl}/api/license/v1/validate", content);
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
Console.WriteLine($" HTTP Status: {(int)response.StatusCode} {response.StatusCode}");
|
||||||
|
Console.WriteLine($" Response Payload:\n {responseBody.Replace("\n", "\n ")}");
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode && responseBody.Contains("\"status\": \"valid\""))
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Console.WriteLine(" ✔ Lizenzen Modul Test: GÜLTIG!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine(" ✖ Lizenzen Modul Test: Fehler oder Ungültig!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine($" ✖ Fehler beim Lizenzen-Test: {ex.Message}");
|
||||||
|
}
|
||||||
|
Console.ResetColor();
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task TestWatchdogModuleAsync()
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine("2. Teste Module: Watchdog (Heartbeat Ping)...");
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var payload = new
|
||||||
|
{
|
||||||
|
source = "srv-db-01",
|
||||||
|
instance = "default",
|
||||||
|
type = "heartbeat",
|
||||||
|
status = "ok",
|
||||||
|
message = "C# Client Test Suite running smoothly",
|
||||||
|
interval = 60,
|
||||||
|
group = "TestRunner",
|
||||||
|
os = Environment.OSVersion.ToString()
|
||||||
|
};
|
||||||
|
|
||||||
|
string json = JsonSerializer.Serialize(payload);
|
||||||
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Post, $"{BaseUrl}/api/watchdog/v1/ping")
|
||||||
|
{
|
||||||
|
Content = content
|
||||||
|
};
|
||||||
|
request.Headers.Add("X-Agent-Token", "wd_live_token_infra_01_secure");
|
||||||
|
|
||||||
|
HttpResponseMessage response = await Client.SendAsync(request);
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
Console.WriteLine($" HTTP Status: {(int)response.StatusCode} {response.StatusCode}");
|
||||||
|
Console.WriteLine($" Response Payload:\n {responseBody.Replace("\n", "\n ")}");
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Console.WriteLine(" ✔ Watchdog Modul Test: ERFOLGREICH!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine(" ✖ Watchdog Modul Test: FEHLER!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine($" ✖ Fehler beim Watchdog-Test: {ex.Message}");
|
||||||
|
}
|
||||||
|
Console.ResetColor();
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task TestUpdateServiceModuleAsync()
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine("3. Teste Module: UpdateService (Release Check)...");
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await Client.GetAsync($"{BaseUrl}/api/updateservice/v1/check?product=myapp&version=1.0.0");
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
Console.WriteLine($" HTTP Status: {(int)response.StatusCode} {response.StatusCode}");
|
||||||
|
Console.WriteLine($" Response Payload:\n {responseBody.Replace("\n", "\n ")}");
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Console.WriteLine(" ✔ UpdateService Modul Test: ERFOLGREICH!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine(" ✖ UpdateService Modul Test: FEHLER!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine($" ✖ Fehler beim UpdateService-Test: {ex.Message}");
|
||||||
|
}
|
||||||
|
Console.ResetColor();
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
+591
-255
File diff suppressed because it is too large
Load Diff
+14
-6
@@ -6,8 +6,9 @@ SET FOREIGN_KEY_CHECKS = 0;
|
|||||||
-- Core Platform Tables
|
-- Core Platform Tables
|
||||||
DROP TABLE IF EXISTS dc_users;
|
DROP TABLE IF EXISTS dc_users;
|
||||||
DROP TABLE IF EXISTS dc_settings;
|
DROP TABLE IF EXISTS dc_settings;
|
||||||
|
DROP TABLE IF EXISTS dc_projects;
|
||||||
|
|
||||||
-- LicenseLabrador Module Tables
|
-- License Module Tables
|
||||||
DROP TABLE IF EXISTS license_api_rate_limit;
|
DROP TABLE IF EXISTS license_api_rate_limit;
|
||||||
DROP TABLE IF EXISTS license_audit_log;
|
DROP TABLE IF EXISTS license_audit_log;
|
||||||
DROP TABLE IF EXISTS license_activations;
|
DROP TABLE IF EXISTS license_activations;
|
||||||
@@ -40,8 +41,8 @@ CREATE TABLE dc_settings (
|
|||||||
svalue TEXT NOT NULL
|
svalue TEXT NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- 2. LicenseLabrador Module Tables
|
-- Core Projects Table (Shared across Lizenzen, Watchdog, UpdateService)
|
||||||
CREATE TABLE license_products (
|
CREATE TABLE dc_projects (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
slug VARCHAR(64) NOT NULL UNIQUE,
|
slug VARCHAR(64) NOT NULL UNIQUE,
|
||||||
name VARCHAR(190) NOT NULL,
|
name VARCHAR(190) NOT NULL,
|
||||||
@@ -50,6 +51,7 @@ CREATE TABLE license_products (
|
|||||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- 2. License Module Tables (Linked to dc_projects)
|
||||||
CREATE TABLE license_licenses (
|
CREATE TABLE license_licenses (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
product_id INT NOT NULL,
|
product_id INT NOT NULL,
|
||||||
@@ -61,7 +63,7 @@ CREATE TABLE license_licenses (
|
|||||||
max_activations INT NOT NULL DEFAULT 2,
|
max_activations INT NOT NULL DEFAULT 2,
|
||||||
notes TEXT NULL,
|
notes TEXT NULL,
|
||||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (product_id) REFERENCES license_products(id) ON DELETE RESTRICT
|
FOREIGN KEY (product_id) REFERENCES dc_projects(id) ON DELETE RESTRICT
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
CREATE TABLE license_activations (
|
CREATE TABLE license_activations (
|
||||||
@@ -160,6 +162,7 @@ CREATE TABLE watchdog_cron_jobs (
|
|||||||
CREATE TABLE watchdog_agent_tokens (
|
CREATE TABLE watchdog_agent_tokens (
|
||||||
token_id VARCHAR(64) PRIMARY KEY,
|
token_id VARCHAR(64) PRIMARY KEY,
|
||||||
token_hash VARCHAR(128) NOT NULL,
|
token_hash VARCHAR(128) NOT NULL,
|
||||||
|
raw_token VARCHAR(128) NULL,
|
||||||
name VARCHAR(100) NOT NULL,
|
name VARCHAR(100) NOT NULL,
|
||||||
monitor_source VARCHAR(100) NULL,
|
monitor_source VARCHAR(100) NULL,
|
||||||
monitor_instance VARCHAR(100) NULL,
|
monitor_instance VARCHAR(100) NULL,
|
||||||
@@ -203,8 +206,8 @@ INSERT INTO watchdog_cron_jobs (name, interval_sec, enabled) VALUES
|
|||||||
('eventlog_cleanup', 86400, 1)
|
('eventlog_cleanup', 86400, 1)
|
||||||
ON DUPLICATE KEY UPDATE interval_sec = VALUES(interval_sec);
|
ON DUPLICATE KEY UPDATE interval_sec = VALUES(interval_sec);
|
||||||
|
|
||||||
-- Seed Initial Products (LicenseLabrador)
|
-- Seed Initial Projects (Core Projects)
|
||||||
INSERT INTO license_products (id, slug, name, notes, default_cache_ttl_hours) VALUES
|
INSERT INTO dc_projects (id, slug, name, notes, default_cache_ttl_hours) VALUES
|
||||||
(1, 'myapp', 'My Application Deluxe', 'Hauptanwendung für Desktop und Server', 168),
|
(1, 'myapp', 'My Application Deluxe', 'Hauptanwendung für Desktop und Server', 168),
|
||||||
(2, 'polytrader', 'PolyTrader Suite Pro', 'Trading- und Handelssystem Client', 72),
|
(2, 'polytrader', 'PolyTrader Suite Pro', 'Trading- und Handelssystem Client', 72),
|
||||||
(3, 'predictalytics', 'Predictalytics Engine', 'Datenanalyse und Vorhersage Dienst', 168)
|
(3, 'predictalytics', 'Predictalytics Engine', 'Datenanalyse und Vorhersage Dienst', 168)
|
||||||
@@ -248,6 +251,11 @@ INSERT INTO watchdog_event_log (source, instance, kind, severity, message) VALUE
|
|||||||
('Update Poller Service', 'default', 'warning_raised', 'warning', 'Latenz überschreitet Schwellwert (450ms)'),
|
('Update Poller Service', 'default', 'warning_raised', 'warning', 'Latenz überschreitet Schwellwert (450ms)'),
|
||||||
('PolyTrader Worker', 'default', 'recovered', 'info', 'Dienst nach Neustart wieder online');
|
('PolyTrader Worker', 'default', 'recovered', 'info', 'Dienst nach Neustart wieder online');
|
||||||
|
|
||||||
|
-- Seed Initial Watchdog Agent Tokens
|
||||||
|
INSERT INTO watchdog_agent_tokens (token_id, token_hash, raw_token, name, monitor_source) VALUES
|
||||||
|
('tok_infra01', '140e6c7329ecb3ea662580a1495c654f593361e64cf96ec37050dd0915f013d5', 'wd_live_token_infra_01_secure', 'Infrastructure Agent Token', 'srv-db-01')
|
||||||
|
ON DUPLICATE KEY UPDATE name = VALUES(name);
|
||||||
|
|
||||||
-- Seed Initial Update Releases
|
-- Seed Initial Update Releases
|
||||||
INSERT INTO updateservice_releases (product_slug, version, release_notes, download_url, sha256_hash, is_critical) VALUES
|
INSERT INTO updateservice_releases (product_slug, version, release_notes, download_url, sha256_hash, is_critical) VALUES
|
||||||
('myapp', '1.0.0', 'Initiales Release mit Grundfunktionen', 'https://dc.mhdf.de/downloads/myapp-1.0.0.zip', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 0),
|
('myapp', '1.0.0', 'Initiales Release mit Grundfunktionen', 'https://dc.mhdf.de/downloads/myapp-1.0.0.zip', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 0),
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ class LicenseService
|
|||||||
return array_merge($base, $extra);
|
return array_merge($base, $extra);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 1. Fetch Product
|
// 1. Fetch Project from dc_projects
|
||||||
$stmt = $this->db->prepare('SELECT id, default_cache_ttl_hours FROM license_products WHERE slug = :slug');
|
$stmt = $this->db->prepare('SELECT id, default_cache_ttl_hours FROM dc_projects WHERE slug = :slug');
|
||||||
$stmt->execute([':slug' => $productSlug]);
|
$stmt->execute([':slug' => $productSlug]);
|
||||||
$product = $stmt->fetch();
|
$product = $stmt->fetch();
|
||||||
if (!$product) {
|
if (!$product) {
|
||||||
@@ -53,7 +53,7 @@ class LicenseService
|
|||||||
'key_prefix' => substr($licenseKey, 0, 5),
|
'key_prefix' => substr($licenseKey, 0, 5),
|
||||||
'ip' => $clientIp
|
'ip' => $clientIp
|
||||||
]);
|
]);
|
||||||
return $makePayload('not_found', ['message' => 'Product not found']);
|
return $makePayload('not_found', ['message' => 'Project not found']);
|
||||||
}
|
}
|
||||||
$cacheTtlHours = (int)$product['default_cache_ttl_hours'];
|
$cacheTtlHours = (int)$product['default_cache_ttl_hours'];
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ class LicenseService
|
|||||||
SELECT a.id, a.license_id
|
SELECT a.id, a.license_id
|
||||||
FROM license_activations a
|
FROM license_activations a
|
||||||
JOIN license_licenses l ON a.license_id = l.id
|
JOIN license_licenses l ON a.license_id = l.id
|
||||||
JOIN license_products p ON l.product_id = p.id
|
JOIN dc_projects p ON l.product_id = p.id
|
||||||
WHERE p.slug = :slug AND l.license_key = :key AND a.hardware_id = :hw_id
|
WHERE p.slug = :slug AND l.license_key = :key AND a.hardware_id = :hw_id
|
||||||
');
|
');
|
||||||
$stmt->execute([':slug' => $productSlug, ':key' => $licenseKey, ':hw_id' => $hardwareId]);
|
$stmt->execute([':slug' => $productSlug, ':key' => $licenseKey, ':hw_id' => $hardwareId]);
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ class MonitorRepo
|
|||||||
source, instance, type, state, expected_interval_sec, last_seen_utc,
|
source, instance, type, state, expected_interval_sec, last_seen_utc,
|
||||||
last_status, last_message, metrics_json, group_key, os, created_utc, updated_utc
|
last_status, last_message, metrics_json, group_key, os, created_utc, updated_utc
|
||||||
) VALUES (
|
) VALUES (
|
||||||
:source, :instance, :type, :state, :interval, :now,
|
:source, :instance, :type, :state, :interval, NOW(),
|
||||||
:last_status, :message, :metrics, :group_key, :os, :now, :now
|
:last_status, :message, :metrics, :group_key, :os, NOW(), NOW()
|
||||||
)
|
)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
state = VALUES(state),
|
state = VALUES(state),
|
||||||
@@ -68,7 +68,6 @@ class MonitorRepo
|
|||||||
':type' => $type,
|
':type' => $type,
|
||||||
':state' => $state,
|
':state' => $state,
|
||||||
':interval' => $intervalSec,
|
':interval' => $intervalSec,
|
||||||
':now' => $nowUtc,
|
|
||||||
':last_status' => $status,
|
':last_status' => $status,
|
||||||
':message' => $message,
|
':message' => $message,
|
||||||
':metrics' => $metricsJson,
|
':metrics' => $metricsJson,
|
||||||
|
|||||||
@@ -13,25 +13,28 @@ class TokenManager
|
|||||||
$this->db = $db;
|
$this->db = $db;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createToken(string $source, string $name, string $notes = ''): array
|
public function createToken(string $source, ?string $name = null, string $notes = ''): array
|
||||||
{
|
{
|
||||||
$tokenId = 'tok_' . bin2hex(random_bytes(8));
|
$tokenId = 'tok_' . bin2hex(random_bytes(8));
|
||||||
$rawToken = 'wd_' . bin2hex(random_bytes(24));
|
$rawToken = 'wd_live_' . bin2hex(random_bytes(18));
|
||||||
$tokenHash = hash('sha256', $rawToken);
|
$tokenHash = hash('sha256', $rawToken);
|
||||||
|
|
||||||
|
$tokenName = !empty($name) ? $name : ("Token for " . ($source ?: 'General'));
|
||||||
|
|
||||||
$stmt = $this->db->prepare('
|
$stmt = $this->db->prepare('
|
||||||
INSERT INTO watchdog_agent_tokens (
|
INSERT INTO watchdog_agent_tokens (
|
||||||
token_id, token_hash, name, monitor_source, created_at_utc
|
token_id, token_hash, raw_token, name, monitor_source, created_at_utc
|
||||||
) VALUES (
|
) VALUES (
|
||||||
:id, :hash, :name, :source, NOW()
|
:id, :hash, :raw, :name, :source, NOW()
|
||||||
)
|
)
|
||||||
');
|
');
|
||||||
|
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
':id' => $tokenId,
|
':id' => $tokenId,
|
||||||
':hash' => $tokenHash,
|
':hash' => $tokenHash,
|
||||||
':name' => $name,
|
':raw' => $rawToken,
|
||||||
':source' => $source,
|
':name' => $tokenName,
|
||||||
|
':source' => !empty($source) ? $source : null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -43,8 +46,8 @@ class TokenManager
|
|||||||
public function validateToken(string $rawToken, string $targetSource): bool
|
public function validateToken(string $rawToken, string $targetSource): bool
|
||||||
{
|
{
|
||||||
$hash = hash('sha256', $rawToken);
|
$hash = hash('sha256', $rawToken);
|
||||||
$stmt = $this->db->prepare('SELECT * FROM watchdog_agent_tokens WHERE token_hash = :hash AND revoked = 0');
|
$stmt = $this->db->prepare('SELECT * FROM watchdog_agent_tokens WHERE (token_hash = :hash OR raw_token = :raw) AND revoked = 0');
|
||||||
$stmt->execute([':hash' => $hash]);
|
$stmt->execute([':hash' => $hash, ':raw' => $rawToken]);
|
||||||
$row = $stmt->fetch();
|
$row = $stmt->fetch();
|
||||||
|
|
||||||
if (!$row) {
|
if (!$row) {
|
||||||
@@ -60,4 +63,10 @@ class TokenManager
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAllTokens(): array
|
||||||
|
{
|
||||||
|
$stmt = $this->db->query('SELECT * FROM watchdog_agent_tokens ORDER BY created_at_utc DESC');
|
||||||
|
return $stmt->fetchAll() ?: [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user