Auth stack certs tab, arrs db fallbacks, cert monitor cache, conf parser fix
- Auth stack: fold cert monitor into Auth Stack page as fourth tab (Certs); remove standalone cert page and top-level tab - cert_monitor.sh: write JSON status cache to State_Files/cert_status.json after each run; expose per-domain days/expiry via _CERT_DAYS/_CERT_EXPIRY globals - api/cert.php: new — serves cached cert status; falls back to configured domains as UNKN when no cache exists; POST action=run triggers live check - arrs db fallbacks: vv_arr_cleanup_stats/discovery_stats/recovery_stats now read from data/*.db files when log JSON files don't yet exist - config.php vv_conf_vars(): unescape bash \$ → $ so passwords with dollar signs read correctly from conf files - host1.conf: fill in HOST1_NPM_USER/PASS and HOST1_LLDAP_USER/PASS - Partnership adapter pattern: Unraid-specific container logic extracted to Plugin/unraid/Partnership/; platform-agnostic structure stays in Partnership/ - First-run wizard: uniform multi-step flow for all hosts; HOST2 pull moved to checklist; auto SSH keygen and API key creation on save - api/checklist.php: live setup checklist with pull_master action - Fullscreen toggle: hide Unraid header/menu; state persists via localStorage
This commit is contained in:
@@ -149,7 +149,7 @@ function vv_script_suggested_cron(string $path): array {
|
||||
// Parse user_script_plug-in.sh into an array of script blocks.
|
||||
// Each block: title, schedule, desc (array of lines), scripts (array of {rel, cron})
|
||||
function vv_parse_user_script_template(): array {
|
||||
$file = SCRIPTS_DIR . '/user_script_plug-in.sh';
|
||||
$file = SCRIPTS_DIR . '/Plugin/unraid/user_script_plug-in.sh';
|
||||
if (!file_exists($file)) return [];
|
||||
$lines = file($file, FILE_IGNORE_NEW_LINES);
|
||||
$prefix = rtrim(SCRIPTS_DIR, '/') . '/';
|
||||
@@ -231,41 +231,69 @@ function vv_script_description(string $path): string {
|
||||
}
|
||||
|
||||
function vv_tools_scripts(): array {
|
||||
$dir = SCRIPTS_DIR . '/Tools';
|
||||
// Background writers managed automatically — not user-facing tools
|
||||
static $EXCLUDE = ['api_cache_writer.sh', 'remote_arr_cache_writer.sh'];
|
||||
|
||||
$schedule = vv_schedule_load();
|
||||
$scripts = [];
|
||||
foreach (glob("$dir/*.sh") ?: [] as $path) {
|
||||
$rel = 'Tools/' . basename($path);
|
||||
$entry = $schedule[$rel] ?? [];
|
||||
$scripts[] = [
|
||||
'id' => $rel,
|
||||
'label' => vv_pretty_label(basename($path, '.sh')),
|
||||
'desc' => vv_script_description($path),
|
||||
'enabled' => (bool)($entry['enabled'] ?? false),
|
||||
'cron' => $entry['cron'] ?? '',
|
||||
'log_enabled' => (bool)($entry['log_enabled'] ?? false),
|
||||
];
|
||||
|
||||
$collect = function(string $dir, string $relPrefix) use ($schedule, $EXCLUDE, &$scripts): void {
|
||||
foreach (glob("$dir/*.sh") ?: [] as $path) {
|
||||
$base = basename($path);
|
||||
if (in_array($base, $EXCLUDE, true)) continue;
|
||||
$rel = $relPrefix . $base;
|
||||
$entry = $schedule[$rel] ?? [];
|
||||
$scripts[] = [
|
||||
'id' => $rel,
|
||||
'label' => vv_pretty_label(basename($path, '.sh')),
|
||||
'desc' => vv_script_description($path),
|
||||
'enabled' => (bool)($entry['enabled'] ?? false),
|
||||
'cron' => $entry['cron'] ?? '',
|
||||
'log_enabled' => (bool)($entry['log_enabled'] ?? false),
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
// General tools
|
||||
$collect(SCRIPTS_DIR . '/Tools', 'Tools/');
|
||||
|
||||
// Platform adapter tools (Plugin/<platform>/Tools/)
|
||||
foreach (glob(SCRIPTS_DIR . '/Plugin/*/Tools') ?: [] as $toolsDir) {
|
||||
$platform = basename(dirname($toolsDir));
|
||||
$collect($toolsDir, "Plugin/$platform/Tools/");
|
||||
}
|
||||
|
||||
usort($scripts, fn($a, $b) => strcmp($a['label'], $b['label']));
|
||||
return $scripts;
|
||||
}
|
||||
|
||||
function vv_custom_scripts(): array {
|
||||
$dir = SCRIPTS_DIR . '/Custom';
|
||||
$schedule = vv_schedule_load();
|
||||
$scripts = [];
|
||||
foreach (glob("$dir/*.sh") ?: [] as $path) {
|
||||
$rel = 'Custom/' . basename($path);
|
||||
$entry = $schedule[$rel] ?? [];
|
||||
$scripts[] = [
|
||||
'id' => $rel,
|
||||
'label' => vv_pretty_label(basename($path, '.sh')),
|
||||
'desc' => vv_script_description($path),
|
||||
'enabled' => (bool)($entry['enabled'] ?? false),
|
||||
'cron' => $entry['cron'] ?? '',
|
||||
'log_enabled' => (bool)($entry['log_enabled'] ?? false),
|
||||
];
|
||||
|
||||
$collect = function(string $dir, string $relPrefix) use ($schedule, &$scripts): void {
|
||||
foreach (glob("$dir/*.sh") ?: [] as $path) {
|
||||
$rel = $relPrefix . basename($path);
|
||||
$entry = $schedule[$rel] ?? [];
|
||||
$scripts[] = [
|
||||
'id' => $rel,
|
||||
'label' => vv_pretty_label(basename($path, '.sh')),
|
||||
'desc' => vv_script_description($path),
|
||||
'enabled' => (bool)($entry['enabled'] ?? false),
|
||||
'cron' => $entry['cron'] ?? '',
|
||||
'log_enabled' => (bool)($entry['log_enabled'] ?? false),
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
$collect(SCRIPTS_DIR . '/Custom', 'Custom/');
|
||||
|
||||
// Platform adapter custom scripts (Plugin/<platform>/Custom/)
|
||||
foreach (glob(SCRIPTS_DIR . '/Plugin/*/Custom') ?: [] as $customDir) {
|
||||
$platform = basename(dirname($customDir));
|
||||
$collect($customDir, "Plugin/$platform/Custom/");
|
||||
}
|
||||
|
||||
return $scripts;
|
||||
}
|
||||
|
||||
@@ -287,7 +315,7 @@ function vv_orch_conf_arrays(string $orchPath): array {
|
||||
}
|
||||
|
||||
// Return .sh scripts that exist in SCRIPTS_DIR but are not referenced in any
|
||||
// master.conf *_SCRIPTS array and are not orchestrators or custom scripts.
|
||||
// master.conf *_SCRIPTS array and are not shown in any other scheduler card.
|
||||
function vv_script_library(): array {
|
||||
$scriptsDir = SCRIPTS_DIR;
|
||||
$confMap = vv_conf_script_map();
|
||||
@@ -295,7 +323,17 @@ function vv_script_library(): array {
|
||||
foreach (glob("$scriptsDir/Orchestrators/*.sh") ?: [] as $p) {
|
||||
$orchIds[] = 'Orchestrators/' . basename($p);
|
||||
}
|
||||
$exclude = ['Plugin', '.git', 'Orchestrators', 'Custom', 'Configurations'];
|
||||
// Scripts already shown in their own cards are not "unlisted"
|
||||
$schedule = vv_schedule_load();
|
||||
$cardIds = array_flip(array_merge(
|
||||
array_column(vv_tools_scripts(), 'id'),
|
||||
array_column(vv_custom_scripts(), 'id')
|
||||
));
|
||||
|
||||
// UI-only subdirs under Plugin/<platform>/ — no runnable scripts
|
||||
$pluginUiDirs = ['api', 'include', 'pages', 'css', 'js', 'icons', 'event'];
|
||||
|
||||
$exclude = ['.git', 'Orchestrators', 'Custom', 'Configurations'];
|
||||
$library = [];
|
||||
try {
|
||||
$ri = new RecursiveIteratorIterator(
|
||||
@@ -306,8 +344,16 @@ function vv_script_library(): array {
|
||||
if (!$rf->isFile() || strtolower($rf->getExtension()) !== 'sh') continue;
|
||||
$rel = ltrim(str_replace($base, '', $rf->getPathname()), '/');
|
||||
$parts = explode('/', $rel);
|
||||
if (count($parts) < 2 || in_array($parts[0], $exclude)) continue;
|
||||
if (in_array($rel, $orchIds) || isset($confMap[$rel])) continue;
|
||||
if (in_array($parts[0], $exclude)) continue;
|
||||
if ($parts[0] === 'Plugin') {
|
||||
// Require Plugin/<platform>/<category>/<script>.sh — skip root-level adapter files
|
||||
if (count($parts) < 4) continue;
|
||||
// Skip UI-only category dirs
|
||||
if (in_array($parts[2], $pluginUiDirs)) continue;
|
||||
} elseif (count($parts) < 2) {
|
||||
continue;
|
||||
}
|
||||
if (in_array($rel, $orchIds) || isset($confMap[$rel]) || isset($cardIds[$rel]) || isset($schedule[$rel])) continue;
|
||||
$library[] = ['id' => $rel, 'label' => vv_pretty_label(basename($rel, '.sh'))];
|
||||
}
|
||||
} catch (Exception $e) {}
|
||||
|
||||
Reference in New Issue
Block a user