Main update
All checks were successful
Deploy / deploy-staging (push) Successful in 25s
Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-06-24 02:24:39 +02:00
parent 5ff4c3fb2b
commit d121f74bd0
34 changed files with 2548 additions and 67 deletions

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
require_once dirname(__DIR__, 3) . '/src/App/bootstrap.php';
require_once dirname(__DIR__) . '/bootstrap.php';
use App\CronAuth;
use ModulesCore\ModuleHttp;
if (session_status() !== PHP_SESSION_ACTIVE) {
@@ -12,11 +13,15 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
}
$projectRoot = dirname(__DIR__, 3);
ModuleHttp::requireDesktopAccess($projectRoot, true);
$action = (string)($_GET['action'] ?? '');
$cronAllowedActions = ['gravity', 'update', 'widget_status'];
$isCronRequest = in_array($action, $cronAllowedActions, true) && CronAuth::isAuthorizedRequest($projectRoot);
if (!$isCronRequest) {
ModuleHttp::requireDesktopAccess($projectRoot, true);
}
header('Content-Type: application/json; charset=utf-8');
$action = (string)($_GET['action'] ?? '');
$instances = module_fn('pihole', 'instances');
$listsPrimaryOnly = module_fn('pihole', 'lists_primary_only');
$moduleSettings = modules()->settings('pihole');
@@ -36,6 +41,22 @@ $respond = function (array $data, int $status = 200): void {
exit;
};
$requireAdminAccess = static function (bool $allowCron = false) use ($isCronRequest, $respond): void {
if ($allowCron && $isCronRequest) {
return;
}
$currentUser = is_array($_SESSION['desktop_auth']['user'] ?? null) ? $_SESSION['desktop_auth']['user'] : [];
$groups = array_map(
static fn (string $group): string => strtolower(trim($group, '/')),
array_values(array_map('strval', (array) ($currentUser['groups'] ?? [])))
);
if (!in_array('administrators', $groups, true)) {
$respond(['ok' => false, 'error' => 'forbidden'], 403);
}
};
$debugPush = static function (string $label, array $payload = []): void {
module_debug_push('pihole', array_merge(['label' => $label], $payload));
};
@@ -886,8 +907,31 @@ if ($action === 'dashboard') {
]);
}
if ($action === 'widget_status') {
$statusText = 'Keine Pi-hole-Instanzen konfiguriert.';
if (!empty($instances)) {
$primaryId = $resolvePrimaryId();
$primaryName = $primaryId !== null && isset($instances[$primaryId])
? (string) ($instances[$primaryId]['name'] ?? $primaryId)
: (string) array_key_first($instances);
$statusText = sprintf(
'%d Instanz(en) hinterlegt · Primaer: %s',
count($instances),
$primaryName !== '' ? $primaryName : 'n/a'
);
}
$respond([
'ok' => true,
'data' => [
'status_text' => $statusText,
'instance_count' => count($instances),
],
]);
}
if ($action === 'test') {
require_admin();
$requireAdminAccess();
$target = (string)($payload['instance'] ?? '');
if ($target === '') {
$respond(['ok' => false, 'error' => 'missing_instance'], 400);
@@ -988,7 +1032,7 @@ if ($action === 'test') {
}
if ($action === 'disable') {
require_admin();
$requireAdminAccess();
$debugPush('disable.request', ['payload' => $payload]);
$minutes = (int)($payload['minutes'] ?? 0);
$target = (string)($payload['instance'] ?? 'all');
@@ -1021,7 +1065,7 @@ if ($action === 'disable') {
}
if ($action === 'enable') {
require_admin();
$requireAdminAccess();
$debugPush('enable.request', ['payload' => $payload]);
$target = (string)($payload['instance'] ?? 'all');
$targets = $pickInstances($target);
@@ -1049,7 +1093,7 @@ if ($action === 'enable') {
}
if ($action === 'gravity') {
require_admin();
$requireAdminAccess(true);
$debugPush('gravity.request', ['payload' => $payload]);
$actionTimeout = $resolveActionTimeout();
$target = $listsPrimaryOnly ? 'primary' : (string)($payload['instance'] ?? 'primary');
@@ -1075,7 +1119,7 @@ if ($action === 'gravity') {
}
if ($action === 'domain_add') {
require_admin();
$requireAdminAccess();
$debugPush('domain_add.request', ['payload' => $payload]);
$domain = trim((string)($payload['domain'] ?? ''));
$type = (string)($payload['type'] ?? 'block');
@@ -1109,7 +1153,7 @@ if ($action === 'domain_add') {
}
if ($action === 'adlist_add') {
require_admin();
$requireAdminAccess();
$debugPush('adlist_add.request', ['payload' => $payload]);
$url = trim((string)($payload['url'] ?? ''));
if ($url === '') {
@@ -1138,7 +1182,7 @@ if ($action === 'adlist_add') {
}
if ($action === 'update') {
require_admin();
$requireAdminAccess(true);
$debugPush('update.request', ['payload' => $payload]);
$actionTimeout = $resolveActionTimeout();
$target = (string)($payload['instance'] ?? 'primary');

View File

@@ -3,6 +3,80 @@
"version": "0.1.0",
"description": "Pi-hole Monitoring, Listen und Steuerung fuer mehrere Instanzen.",
"enabled_by_default": true,
"app_scope": "module",
"installable": true,
"desktop": {
"available": true,
"show_on_desktop": true,
"show_in_start_menu": true
},
"widgets": [
{
"widget_id": "pihole-maintenance",
"title": "Pi-hole Wartung",
"icon": "PH",
"zone": "sidebar",
"default_enabled": false,
"supports_public_home": false,
"summary": "Gravity-Update und Listen-Refresh direkt aus dem Desktop.",
"content": "Schnellaktionen fuer die Pflege der Pi-hole-Instanzen.",
"launch_app_id": "pihole",
"action_label": "App oeffnen",
"widget_type": "action-panel",
"status_api": "/api/pihole/index.php?action=widget_status",
"actions": [
{
"action_id": "gravity",
"label": "Gravity aktualisieren",
"endpoint": "/api/pihole/index.php?action=gravity",
"method": "POST",
"payload": {
"instance": "primary"
}
},
{
"action_id": "update",
"label": "Pi-hole updaten",
"endpoint": "/api/pihole/index.php?action=update",
"method": "POST",
"payload": {
"instance": "primary"
},
"variant": "secondary"
}
]
}
],
"cron_jobs": [
{
"job_id": "gravity-primary",
"label": "Pi-hole Gravity Update",
"description": "Aktualisiert die Blocklisten auf der Primaer-Instanz.",
"endpoint_path": "/api/pihole/index.php?action=gravity",
"method": "POST",
"payload": {
"instance": "primary",
"trigger_source": "cron"
},
"default_enabled": false,
"default_cron": "20 4 * * *",
"lock_minutes": 30
},
{
"job_id": "update-primary",
"label": "Pi-hole Systemupdate",
"description": "Startet ein Update der Primaer-Instanz.",
"endpoint_path": "/api/pihole/index.php?action=update",
"method": "POST",
"payload": {
"instance": "primary",
"trigger_source": "cron"
},
"default_enabled": false,
"default_cron": "50 4 * * 0",
"lock_minutes": 45
}
],
"setup": {
"fields": [
{