refactor(apps): make app tools + helpers fully self-contained per app
Each app now carries everything under containers/<app>/: Tools-tab actions in tools/ (declaration <app>.tools.json + function <app>_<tool_id>.sh) and logic helpers in scripts/ (e.g. <app>_auth.sh). The container scan live-sources every .sh under the app (maxdepth 3, prunes only resources/) and webui_tools.sh auto-merges the .tools.json, so an app is a true drop-in — no central edit, no array regen. - Empty the central webui_tools.sh heredoc; all 34 tools across 11 apps now come from per-app declarations (verified byte-identical to the old output). - Retire the orphaned mattermost tool scripts to scripts/unused (there is no containers/mattermost; its install fn already lived in unused). - Update the dispatch comment/error path, the auth-adapter doc, and DEVELOPMENT.md to the new convention. - Regenerate static arrays (files_app.sh no longer lists app/containers/*). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
parent
7204be3aff
commit
898068a390
106
containers/bookstack/tools/bookstack.tools.json
Normal file
106
containers/bookstack/tools/bookstack.tools.json
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
{
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"id": "reset_password",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Reset User Password",
|
||||||
|
"description": "Reset an existing Bookstack user's password. Leave the password field blank to generate a random one — it is shown in the task log.",
|
||||||
|
"icon": "🔑",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"label": "User email",
|
||||||
|
"type": "text",
|
||||||
|
"placeholder": "user@example.com",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "New password (leave blank to generate)",
|
||||||
|
"type": "password",
|
||||||
|
"placeholder": "Leave blank for random"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "create_account",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Create User Account",
|
||||||
|
"description": "Create a new Bookstack user. Tick \"Make admin\" to grant full admin rights; otherwise the new user gets the default registration role. Leave the password blank to generate a random one.",
|
||||||
|
"icon": "👤",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"label": "Email",
|
||||||
|
"type": "text",
|
||||||
|
"placeholder": "user@example.com",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"label": "Display name",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "Password (leave blank to generate)",
|
||||||
|
"type": "password",
|
||||||
|
"placeholder": "Leave blank for random"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"label": "Make admin",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "list_users",
|
||||||
|
"category": "users",
|
||||||
|
"label": "List Users",
|
||||||
|
"description": "Show every Bookstack user with their roles.",
|
||||||
|
"icon": "📋",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "delete_user",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Delete User Account",
|
||||||
|
"description": "Permanently delete a user account.",
|
||||||
|
"icon": "🗑",
|
||||||
|
"destructive": true,
|
||||||
|
"confirm": "This cannot be undone.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"label": "User email",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "set_admin",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Set Admin Status",
|
||||||
|
"description": "Promote a user to admin or demote them to a normal user.",
|
||||||
|
"icon": "👑",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"label": "User email",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"label": "Make admin",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
21
containers/dashy/tools/dashy.tools.json
Normal file
21
containers/dashy/tools/dashy.tools.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"id": "manage_shortcuts",
|
||||||
|
"label": "Manage Shortcuts",
|
||||||
|
"description": "Pick which service URLs appear as shortcuts on the Dashy dashboard.",
|
||||||
|
"icon": "🧩",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "selected",
|
||||||
|
"label": "URLs to show on the dashboard",
|
||||||
|
"type": "app_urls_multi",
|
||||||
|
"prefillFromCfgKey": "CFG_DASHY_SHORTCUTS",
|
||||||
|
"excludeApps": [
|
||||||
|
"dashy"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
82
containers/focalboard/tools/focalboard.tools.json
Normal file
82
containers/focalboard/tools/focalboard.tools.json
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
{
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"id": "reset_password",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Reset User Password",
|
||||||
|
"description": "Reset an existing Focalboard user's password.",
|
||||||
|
"icon": "🔑",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "New password (leave blank to generate)",
|
||||||
|
"type": "password",
|
||||||
|
"placeholder": "Leave blank for random"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "create_account",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Create User Account",
|
||||||
|
"description": "Create a new Focalboard user. Leave password blank to generate one.",
|
||||||
|
"icon": "👤",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"label": "Email",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "Password (leave blank to generate)",
|
||||||
|
"type": "password"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"label": "Make admin",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "list_users",
|
||||||
|
"category": "users",
|
||||||
|
"label": "List Users",
|
||||||
|
"description": "Show every Focalboard user account.",
|
||||||
|
"icon": "📋",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "delete_user",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Delete User Account",
|
||||||
|
"description": "Permanently delete a user account.",
|
||||||
|
"icon": "🗑",
|
||||||
|
"destructive": true,
|
||||||
|
"confirm": "This cannot be undone.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
105
containers/gitea/tools/gitea.tools.json
Normal file
105
containers/gitea/tools/gitea.tools.json
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"id": "reset_password",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Reset User Password",
|
||||||
|
"description": "Reset a Gitea user's password using the built-in `gitea admin user change-password` CLI. Leave the password blank to generate a random one.",
|
||||||
|
"icon": "🔑",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "New password (leave blank to generate)",
|
||||||
|
"type": "password",
|
||||||
|
"placeholder": "Leave blank for random"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "create_account",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Create User Account",
|
||||||
|
"description": "Create a new Gitea user via the built-in `gitea admin user create` CLI. Tick \"Make admin\" for full admin rights. Leave the password blank to generate a random one. The account starts ready to log in (no forced password change).",
|
||||||
|
"icon": "👤",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"label": "Email",
|
||||||
|
"type": "text",
|
||||||
|
"placeholder": "user@example.com",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "Password (leave blank to generate)",
|
||||||
|
"type": "password",
|
||||||
|
"placeholder": "Leave blank for random"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"label": "Make admin",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "list_users",
|
||||||
|
"category": "users",
|
||||||
|
"label": "List Users",
|
||||||
|
"description": "Show every Gitea user account.",
|
||||||
|
"icon": "📋",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "delete_user",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Delete User Account",
|
||||||
|
"description": "Permanently delete a user account.",
|
||||||
|
"icon": "🗑",
|
||||||
|
"destructive": true,
|
||||||
|
"confirm": "This cannot be undone.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "set_admin",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Set Admin Status",
|
||||||
|
"description": "Promote a user to admin or demote them to a normal user.",
|
||||||
|
"icon": "👑",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"label": "Make admin",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
containers/gluetun/tools/gluetun.tools.json
Normal file
11
containers/gluetun/tools/gluetun.tools.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"id": "refresh_providers",
|
||||||
|
"label": "Refresh VPN Providers",
|
||||||
|
"description": "Re-scan VPN providers and country lists, regenerating the snapshot used by the country picker.",
|
||||||
|
"icon": "🔄",
|
||||||
|
"fields": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
75
containers/invidious/tools/invidious.tools.json
Normal file
75
containers/invidious/tools/invidious.tools.json
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"id": "reset_password",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Reset User Password",
|
||||||
|
"description": "Reset an Invidious user's password (Postgres bcrypt update).",
|
||||||
|
"icon": "🔑",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"label": "Email",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "New password (leave blank to generate)",
|
||||||
|
"type": "password"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "create_account",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Create User Account",
|
||||||
|
"description": "Create a new Invidious user (Invidious uses email as username).",
|
||||||
|
"icon": "👤",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"label": "Email",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "Password (leave blank to generate)",
|
||||||
|
"type": "password"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"label": "Make admin",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "list_users",
|
||||||
|
"category": "users",
|
||||||
|
"label": "List Users",
|
||||||
|
"description": "Show every Invidious user account.",
|
||||||
|
"icon": "📋",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "delete_user",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Delete User Account",
|
||||||
|
"description": "Permanently delete a user account.",
|
||||||
|
"icon": "🗑",
|
||||||
|
"destructive": true,
|
||||||
|
"confirm": "This cannot be undone.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"label": "Email",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
177
containers/nextcloud/tools/nextcloud.tools.json
Normal file
177
containers/nextcloud/tools/nextcloud.tools.json
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
{
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"id": "reset_password",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Reset User Password",
|
||||||
|
"description": "Reset an existing Nextcloud user's password. Leave the password field blank to generate a random one — it is shown in the task log.",
|
||||||
|
"icon": "🔑",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"placeholder": "alice",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "New password (leave blank to generate)",
|
||||||
|
"type": "password",
|
||||||
|
"placeholder": "Leave blank for random"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "create_account",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Create User Account",
|
||||||
|
"description": "Create a new Nextcloud user. Tick \"Make admin\" to add them to the admin group. Leave the password blank to generate a random one.",
|
||||||
|
"icon": "👤",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"placeholder": "alice",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "display_name",
|
||||||
|
"label": "Display name",
|
||||||
|
"type": "text",
|
||||||
|
"placeholder": "Alice Smith"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "Password (leave blank to generate)",
|
||||||
|
"type": "password",
|
||||||
|
"placeholder": "Leave blank for random"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"label": "Make admin",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "list_users",
|
||||||
|
"category": "users",
|
||||||
|
"label": "List Users",
|
||||||
|
"description": "Show every Nextcloud user with their display name and admin flag.",
|
||||||
|
"icon": "📋",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "delete_user",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Delete User Account",
|
||||||
|
"description": "Permanently delete a user and all their files.",
|
||||||
|
"icon": "🗑",
|
||||||
|
"destructive": true,
|
||||||
|
"confirm": "This cannot be undone. The user's files will be removed.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "set_admin",
|
||||||
|
"category": "users",
|
||||||
|
"label": "Set Admin Status",
|
||||||
|
"description": "Add a user to (or remove from) the admin group.",
|
||||||
|
"icon": "👑",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username",
|
||||||
|
"type": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"label": "Make admin",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "toggle_maintenance",
|
||||||
|
"category": "maintenance",
|
||||||
|
"label": "Toggle Maintenance Mode",
|
||||||
|
"description": "Lock all users out and show a maintenance notice — required before running upgrades or repairs from the CLI.",
|
||||||
|
"icon": "🚧",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "enable",
|
||||||
|
"label": "Enable maintenance mode",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rescan_files",
|
||||||
|
"category": "maintenance",
|
||||||
|
"label": "Rescan Files",
|
||||||
|
"description": "Re-index Nextcloud's file metadata. Run this after files were added or removed on disk outside Nextcloud (rsync, restore, manual copy). Leave the username blank to scan every user.",
|
||||||
|
"icon": "🔄",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username (blank = all users)",
|
||||||
|
"type": "text",
|
||||||
|
"placeholder": "blank for all"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "add_trusted_domain",
|
||||||
|
"category": "system",
|
||||||
|
"label": "Add Trusted Domain",
|
||||||
|
"description": "Append a hostname to Nextcloud's trusted_domains list so requests to that host are accepted.",
|
||||||
|
"icon": "🌐",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "domain",
|
||||||
|
"label": "Domain",
|
||||||
|
"type": "text",
|
||||||
|
"placeholder": "cloud.example.org",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system_status",
|
||||||
|
"category": "system",
|
||||||
|
"label": "System Status",
|
||||||
|
"description": "Show Nextcloud's version, install state, and maintenance flag.",
|
||||||
|
"icon": "ℹ️",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tail_logs",
|
||||||
|
"category": "system",
|
||||||
|
"label": "Tail Logs",
|
||||||
|
"description": "Show the most recent lines of nextcloud.log.",
|
||||||
|
"icon": "📜",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "lines",
|
||||||
|
"label": "Lines",
|
||||||
|
"type": "number",
|
||||||
|
"default": 100,
|
||||||
|
"min": 10,
|
||||||
|
"max": 1000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
containers/pihole/tools/pihole.tools.json
Normal file
11
containers/pihole/tools/pihole.tools.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"id": "apply_dns_updater",
|
||||||
|
"label": "Apply DNS Updater",
|
||||||
|
"description": "Rewrite this server's /etc/resolv.conf to use Pi-hole as its DNS resolver right now. Same action that runs automatically when the global DNS Updater requirement is enabled.",
|
||||||
|
"icon": "🌐",
|
||||||
|
"fields": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
24
containers/traefik/tools/traefik.tools.json
Normal file
24
containers/traefik/tools/traefik.tools.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"id": "reset_password",
|
||||||
|
"label": "Reset Dashboard Login",
|
||||||
|
"description": "Reset the Traefik dashboard credentials (CFG_TRAEFIK_USER / CFG_TRAEFIK_PASS) and regenerate the htpasswd entry in protectionauth.yml. Leave fields blank to keep the current username and/or generate a new random password.",
|
||||||
|
"icon": "🔑",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "username",
|
||||||
|
"label": "Username (leave blank to keep current)",
|
||||||
|
"type": "text",
|
||||||
|
"placeholder": "admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"label": "New password (leave blank to generate)",
|
||||||
|
"type": "password",
|
||||||
|
"placeholder": "Leave blank for random"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -170,15 +170,17 @@ is a dev-only escape hatch.
|
|||||||
## Conventions
|
## Conventions
|
||||||
|
|
||||||
- **Versioning:** semver in `VERSION`. Bump before building; `latest.json` carries it.
|
- **Versioning:** semver in `VERSION`. Bump before building; `latest.json` carries it.
|
||||||
- **App tools are self-contained** (preferred): put the declaration in
|
- **An app is a self-contained drop-in.** Everything for an app lives under
|
||||||
`containers/<app>/tools/<app>.tools.json` and each function in
|
`containers/<app>/`:
|
||||||
`containers/<app>/tools/<app>_<tool_id>.sh` (function `app<App><PascalToolId>`).
|
- **Tools tab actions:** declare them in `containers/<app>/tools/<app>.tools.json`
|
||||||
Both are picked up automatically — the container scan live-sources the `.sh`, and
|
(`{ "tools": [ … ] }`) and put each function beside it at
|
||||||
`webui_tools.sh` auto-merges the `.tools.json`. No central edits, no array regen →
|
`containers/<app>/tools/<app>_<tool_id>.sh` (function `app<App><PascalToolId>`).
|
||||||
the app is a true drop-in. (The legacy central style — an entry in the
|
- **Logic helpers** (anything that isn't a Tools-tab action — e.g. the auth
|
||||||
`webui_tools.sh` heredoc + the function under `scripts/app/containers/<app>/` —
|
adapter, post-install fixups): `containers/<app>/scripts/<app>_*.sh`.
|
||||||
still works; both coexist, so apps migrate one at a time. Only *declared tools*
|
- The container scan **live-sources** every `.sh` under `containers/<app>/`
|
||||||
move; shared logic helpers like `<app>_auth.sh` stay in `scripts/app/`.)
|
(`tools/` and `scripts/`), and `webui_tools.sh` **auto-merges** the
|
||||||
|
`.tools.json`. So dropping the folder onto an install is all it takes — no
|
||||||
|
central edits, no array regen.
|
||||||
- **New runtime script?** Add it under `scripts/<area>/…` and run
|
- **New runtime script?** Add it under `scripts/<area>/…` and run
|
||||||
`scripts/source/files/generate_arrays.sh run` so it's sourced (build/standalone
|
`scripts/source/files/generate_arrays.sh run` so it's sourced (build/standalone
|
||||||
tooling under `scripts/release` and `scripts/system` is intentionally excluded).
|
tooling under `scripts/release` and `scripts/system` is intentionally excluded).
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
# Each app declares an auth profile in its config:
|
# Each app declares an auth profile in its config:
|
||||||
# CFG_<APP>_AUTH_PROFILE = single_password | user_password | multi_user | none
|
# CFG_<APP>_AUTH_PROFILE = single_password | user_password | multi_user | none
|
||||||
#
|
#
|
||||||
# And implements adapter functions in scripts/app/containers/<app>/<app>_auth.sh:
|
# And implements adapter functions in containers/<app>/scripts/<app>_auth.sh:
|
||||||
# authAdapter_<app>_setPassword "$user" "$password"
|
# authAdapter_<app>_setPassword "$user" "$password"
|
||||||
# authAdapter_<app>_createUser "$user" "$password" "$email" "$isAdmin"
|
# authAdapter_<app>_createUser "$user" "$password" "$email" "$isAdmin"
|
||||||
# authAdapter_<app>_listUsers
|
# authAdapter_<app>_listUsers
|
||||||
|
|||||||
@ -17,11 +17,11 @@ dockerAppRunTool()
|
|||||||
|
|
||||||
# One-file-per-tool convention: tool id `<verb>_<noun>` resolves to
|
# One-file-per-tool convention: tool id `<verb>_<noun>` resolves to
|
||||||
# function `app<AppName><PascalCaseToolId>`. Each tool lives at
|
# function `app<AppName><PascalCaseToolId>`. Each tool lives at
|
||||||
# scripts/app/containers/<app>/<app>_<tool_id>.sh.
|
# containers/<app>/tools/<app>_<tool_id>.sh (live-sourced by the container scan).
|
||||||
#
|
#
|
||||||
# Examples:
|
# Examples:
|
||||||
# gluetun + refresh_providers → appGluetunRefreshProviders
|
# gluetun + refresh_providers → appGluetunRefreshProviders
|
||||||
# mattermost + reset_password → appMattermostResetPassword
|
# nextcloud + reset_password → appNextcloudResetPassword
|
||||||
local app_name_ucfirst="$(tr '[:lower:]' '[:upper:]' <<< ${app_name:0:1})${app_name:1}"
|
local app_name_ucfirst="$(tr '[:lower:]' '[:upper:]' <<< ${app_name:0:1})${app_name:1}"
|
||||||
|
|
||||||
local tool_pascal=""
|
local tool_pascal=""
|
||||||
@ -35,7 +35,7 @@ dockerAppRunTool()
|
|||||||
local toolFuncName="app${app_name_ucfirst}${tool_pascal}"
|
local toolFuncName="app${app_name_ucfirst}${tool_pascal}"
|
||||||
|
|
||||||
if ! declare -f "$toolFuncName" >/dev/null 2>&1; then
|
if ! declare -f "$toolFuncName" >/dev/null 2>&1; then
|
||||||
isError "App '$app_name' has no tool '$tool_name' (missing function $toolFuncName — expected in scripts/app/containers/$app_name/$app_name_${tool_name}.sh)."
|
isError "App '$app_name' has no tool '$tool_name' (missing function $toolFuncName — expected in containers/$app_name/tools/${app_name}_${tool_name}.sh)."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@ -10,66 +10,5 @@ app_scripts=(
|
|||||||
"app/app_status.sh"
|
"app/app_status.sh"
|
||||||
"app/app_update_specifics.sh"
|
"app/app_update_specifics.sh"
|
||||||
"app/auth_adapter.sh"
|
"app/auth_adapter.sh"
|
||||||
"app/containers/adguard/adguard_auth.sh"
|
|
||||||
"app/containers/bookstack/bookstack_auth.sh"
|
|
||||||
"app/containers/bookstack/bookstack_create_account.sh"
|
|
||||||
"app/containers/bookstack/bookstack_delete_user.sh"
|
|
||||||
"app/containers/bookstack/bookstack_list_users.sh"
|
|
||||||
"app/containers/bookstack/bookstack_reset_password.sh"
|
|
||||||
"app/containers/bookstack/bookstack_set_admin.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_alerts_list.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_console_disable.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_console_enroll.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_decisions_list.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_fix_priority.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_hub_update.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_metrics.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_status.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_unban.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_update.sh"
|
|
||||||
"app/containers/crowdsec/crowdsec_verify_firewall.sh"
|
|
||||||
"app/containers/dashy/dashy_manage_shortcuts.sh"
|
|
||||||
"app/containers/dashy/dashy_update_conf.sh"
|
|
||||||
"app/containers/focalboard/focalboard_auth.sh"
|
|
||||||
"app/containers/focalboard/focalboard_create_account.sh"
|
|
||||||
"app/containers/focalboard/focalboard_delete_user.sh"
|
|
||||||
"app/containers/focalboard/focalboard_list_users.sh"
|
|
||||||
"app/containers/focalboard/focalboard_reset_password.sh"
|
|
||||||
"app/containers/focalboard/focalboard_set_admin.sh"
|
|
||||||
"app/containers/gitea/gitea_auth.sh"
|
|
||||||
"app/containers/gitea/gitea_create_account.sh"
|
|
||||||
"app/containers/gitea/gitea_delete_user.sh"
|
|
||||||
"app/containers/gitea/gitea_list_users.sh"
|
|
||||||
"app/containers/gitea/gitea_reset_password.sh"
|
|
||||||
"app/containers/gitea/gitea_set_admin.sh"
|
|
||||||
"app/containers/gluetun/gluetun_recreate_routed.sh"
|
|
||||||
"app/containers/gluetun/gluetun_refresh_providers.sh"
|
|
||||||
"app/containers/invidious/invidious_auth.sh"
|
|
||||||
"app/containers/invidious/invidious_create_account.sh"
|
|
||||||
"app/containers/invidious/invidious_delete_user.sh"
|
|
||||||
"app/containers/invidious/invidious_list_users.sh"
|
|
||||||
"app/containers/invidious/invidious_reset_password.sh"
|
|
||||||
"app/containers/invidious/invidious_set_admin.sh"
|
|
||||||
"app/containers/mattermost/mattermost_auth.sh"
|
|
||||||
"app/containers/mattermost/mattermost_create_account.sh"
|
|
||||||
"app/containers/mattermost/mattermost_delete_user.sh"
|
|
||||||
"app/containers/mattermost/mattermost_list_users.sh"
|
|
||||||
"app/containers/mattermost/mattermost_reset_password.sh"
|
|
||||||
"app/containers/mattermost/mattermost_set_admin.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_add_trusted_domain.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_auth.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_create_account.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_delete_user.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_list_users.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_rescan_files.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_reset_password.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_set_admin.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_system_status.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_tail_logs.sh"
|
|
||||||
"app/containers/nextcloud/nextcloud_toggle_maintenance.sh"
|
|
||||||
"app/containers/owncloud/owncloud_setup_config.sh"
|
|
||||||
"app/containers/pihole/pihole_apply_dns_updater.sh"
|
|
||||||
"app/containers/traefik/traefik_auth.sh"
|
|
||||||
"app/containers/traefik/traefik_reset_password.sh"
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|||||||
@ -3,10 +3,13 @@
|
|||||||
# Single source of truth for the Tools tab. The frontend reads
|
# Single source of truth for the Tools tab. The frontend reads
|
||||||
# /data/apps/generated/apps-tools.json — this generator emits it.
|
# /data/apps/generated/apps-tools.json — this generator emits it.
|
||||||
#
|
#
|
||||||
# To add a tool:
|
# Tools are self-contained per app. To add one:
|
||||||
# 1. Add an entry under that app's "tools" array below.
|
# 1. Declare it in containers/<app>/tools/<app>.tools.json (a { "tools": [ … ] }
|
||||||
# 2. Drop a one-function file at scripts/app/containers/<app>/<app>_<tool_id>.sh
|
# object — auto-merged below; no edit to this file needed).
|
||||||
# with `app<App><PascalCase(toolId)>()` defined inside.
|
# 2. Drop the one-function file beside it at
|
||||||
|
# containers/<app>/tools/<app>_<tool_id>.sh with
|
||||||
|
# `app<App><PascalCase(toolId)>()` defined inside (live-sourced by the
|
||||||
|
# container scan).
|
||||||
# 3. Re-run the WebUI updater (or call this function directly) to
|
# 3. Re-run the WebUI updater (or call this function directly) to
|
||||||
# regenerate apps-tools.json.
|
# regenerate apps-tools.json.
|
||||||
#
|
#
|
||||||
@ -49,355 +52,19 @@ webuiGenerateAppsToolsConfig() {
|
|||||||
|
|
||||||
runFileOp mkdir -p "$(dirname "$output_file")"
|
runFileOp mkdir -p "$(dirname "$output_file")"
|
||||||
|
|
||||||
# Heredoc carries the JSON literal verbatim — much easier to edit
|
# Start empty; every app declares its own tools (merged below). The heredoc is
|
||||||
# than escaping nested quotes through jq -n.
|
# kept as the seed so a central tool could be added here if ever needed.
|
||||||
cat > "$tmp" <<'JSON'
|
cat > "$tmp" <<'JSON'
|
||||||
{
|
{
|
||||||
"apps": {
|
"apps": {}
|
||||||
"pihole": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "apply_dns_updater",
|
|
||||||
"label": "Apply DNS Updater",
|
|
||||||
"description": "Rewrite this server's /etc/resolv.conf to use Pi-hole as its DNS resolver right now. Same action that runs automatically when the global DNS Updater requirement is enabled.",
|
|
||||||
"icon": "🌐",
|
|
||||||
"fields": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"dashy": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "manage_shortcuts",
|
|
||||||
"label": "Manage Shortcuts",
|
|
||||||
"description": "Pick which service URLs appear as shortcuts on the Dashy dashboard.",
|
|
||||||
"icon": "🧩",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "selected",
|
|
||||||
"label": "URLs to show on the dashboard",
|
|
||||||
"type": "app_urls_multi",
|
|
||||||
"prefillFromCfgKey": "CFG_DASHY_SHORTCUTS",
|
|
||||||
"excludeApps": ["dashy"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"bookstack": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "reset_password",
|
|
||||||
"category": "users",
|
|
||||||
"label": "Reset User Password",
|
|
||||||
"description": "Reset an existing Bookstack user's password. Leave the password field blank to generate a random one — it is shown in the task log.",
|
|
||||||
"icon": "🔑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "email", "label": "User email", "type": "text", "placeholder": "user@example.com", "required": true },
|
|
||||||
{ "name": "password", "label": "New password (leave blank to generate)", "type": "password", "placeholder": "Leave blank for random" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "create_account",
|
|
||||||
"category": "users",
|
|
||||||
"label": "Create User Account",
|
|
||||||
"description": "Create a new Bookstack user. Tick \"Make admin\" to grant full admin rights; otherwise the new user gets the default registration role. Leave the password blank to generate a random one.",
|
|
||||||
"icon": "👤",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "email", "label": "Email", "type": "text", "placeholder": "user@example.com", "required": true },
|
|
||||||
{ "name": "name", "label": "Display name", "type": "text", "required": true },
|
|
||||||
{ "name": "password", "label": "Password (leave blank to generate)", "type": "password", "placeholder": "Leave blank for random" },
|
|
||||||
{ "name": "admin", "label": "Make admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ "id": "list_users", "category": "users", "label": "List Users", "description": "Show every Bookstack user with their roles.", "icon": "📋", "fields": [] },
|
|
||||||
{
|
|
||||||
"id": "delete_user", "category": "users", "label": "Delete User Account",
|
|
||||||
"description": "Permanently delete a user account.", "icon": "🗑",
|
|
||||||
"destructive": true, "confirm": "This cannot be undone.",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "email", "label": "User email", "type": "text", "required": true }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "set_admin", "category": "users", "label": "Set Admin Status",
|
|
||||||
"description": "Promote a user to admin or demote them to a normal user.", "icon": "👑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "email", "label": "User email", "type": "text", "required": true },
|
|
||||||
{ "name": "admin", "label": "Make admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"focalboard": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "reset_password",
|
|
||||||
"category": "users",
|
|
||||||
"label": "Reset User Password",
|
|
||||||
"description": "Reset an existing Focalboard user's password.",
|
|
||||||
"icon": "🔑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true },
|
|
||||||
{ "name": "password", "label": "New password (leave blank to generate)", "type": "password", "placeholder": "Leave blank for random" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "create_account",
|
|
||||||
"category": "users",
|
|
||||||
"label": "Create User Account",
|
|
||||||
"description": "Create a new Focalboard user. Leave password blank to generate one.",
|
|
||||||
"icon": "👤",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true },
|
|
||||||
{ "name": "email", "label": "Email", "type": "text", "required": true },
|
|
||||||
{ "name": "password", "label": "Password (leave blank to generate)", "type": "password" },
|
|
||||||
{ "name": "admin", "label": "Make admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "list_users",
|
|
||||||
"category": "users",
|
|
||||||
"label": "List Users",
|
|
||||||
"description": "Show every Focalboard user account.",
|
|
||||||
"icon": "📋",
|
|
||||||
"fields": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "delete_user", "category": "users", "label": "Delete User Account",
|
|
||||||
"description": "Permanently delete a user account.", "icon": "🗑",
|
|
||||||
"destructive": true, "confirm": "This cannot be undone.",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"mattermost": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "reset_password", "category": "users", "label": "Reset User Password",
|
|
||||||
"description": "Reset a Mattermost user's password via mmctl.", "icon": "🔑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username or Email", "type": "text", "required": true },
|
|
||||||
{ "name": "password", "label": "New password (leave blank to generate)", "type": "password" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "create_account", "category": "users", "label": "Create User Account",
|
|
||||||
"description": "Create a new Mattermost user via mmctl.", "icon": "👤",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true },
|
|
||||||
{ "name": "email", "label": "Email", "type": "text", "required": true },
|
|
||||||
{ "name": "password", "label": "Password (leave blank to generate)", "type": "password" },
|
|
||||||
{ "name": "admin", "label": "Make system admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ "id": "list_users", "category": "users", "label": "List Users", "description": "Show every Mattermost user account.", "icon": "📋", "fields": [] },
|
|
||||||
{
|
|
||||||
"id": "delete_user", "category": "users", "label": "Delete User Account",
|
|
||||||
"description": "Permanently delete a user account.", "icon": "🗑",
|
|
||||||
"destructive": true, "confirm": "This cannot be undone.",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username/Email", "type": "text", "required": true }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "set_admin", "category": "users", "label": "Set Admin Status",
|
|
||||||
"description": "Promote a user to admin or demote them to a normal user.", "icon": "👑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username/Email", "type": "text", "required": true },
|
|
||||||
{ "name": "admin", "label": "Make admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"invidious": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "reset_password", "category": "users", "label": "Reset User Password",
|
|
||||||
"description": "Reset an Invidious user's password (Postgres bcrypt update).", "icon": "🔑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "email", "label": "Email", "type": "text", "required": true },
|
|
||||||
{ "name": "password", "label": "New password (leave blank to generate)", "type": "password" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "create_account", "category": "users", "label": "Create User Account",
|
|
||||||
"description": "Create a new Invidious user (Invidious uses email as username).", "icon": "👤",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "email", "label": "Email", "type": "text", "required": true },
|
|
||||||
{ "name": "password", "label": "Password (leave blank to generate)", "type": "password" },
|
|
||||||
{ "name": "admin", "label": "Make admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ "id": "list_users", "category": "users", "label": "List Users", "description": "Show every Invidious user account.", "icon": "📋", "fields": [] },
|
|
||||||
{
|
|
||||||
"id": "delete_user", "category": "users", "label": "Delete User Account",
|
|
||||||
"description": "Permanently delete a user account.", "icon": "🗑",
|
|
||||||
"destructive": true, "confirm": "This cannot be undone.",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "email", "label": "Email", "type": "text", "required": true }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"gitea": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "reset_password",
|
|
||||||
"category": "users",
|
|
||||||
"label": "Reset User Password",
|
|
||||||
"description": "Reset a Gitea user's password using the built-in `gitea admin user change-password` CLI. Leave the password blank to generate a random one.",
|
|
||||||
"icon": "🔑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true },
|
|
||||||
{ "name": "password", "label": "New password (leave blank to generate)", "type": "password", "placeholder": "Leave blank for random" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "create_account",
|
|
||||||
"category": "users",
|
|
||||||
"label": "Create User Account",
|
|
||||||
"description": "Create a new Gitea user via the built-in `gitea admin user create` CLI. Tick \"Make admin\" for full admin rights. Leave the password blank to generate a random one. The account starts ready to log in (no forced password change).",
|
|
||||||
"icon": "👤",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true },
|
|
||||||
{ "name": "email", "label": "Email", "type": "text", "placeholder": "user@example.com", "required": true },
|
|
||||||
{ "name": "password", "label": "Password (leave blank to generate)", "type": "password", "placeholder": "Leave blank for random" },
|
|
||||||
{ "name": "admin", "label": "Make admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ "id": "list_users", "category": "users", "label": "List Users", "description": "Show every Gitea user account.", "icon": "📋", "fields": [] },
|
|
||||||
{
|
|
||||||
"id": "delete_user", "category": "users", "label": "Delete User Account",
|
|
||||||
"description": "Permanently delete a user account.", "icon": "🗑",
|
|
||||||
"destructive": true, "confirm": "This cannot be undone.",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "set_admin", "category": "users", "label": "Set Admin Status",
|
|
||||||
"description": "Promote a user to admin or demote them to a normal user.", "icon": "👑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true },
|
|
||||||
{ "name": "admin", "label": "Make admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"gluetun": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "refresh_providers",
|
|
||||||
"label": "Refresh VPN Providers",
|
|
||||||
"description": "Re-scan VPN providers and country lists, regenerating the snapshot used by the country picker.",
|
|
||||||
"icon": "🔄",
|
|
||||||
"fields": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"traefik": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "reset_password",
|
|
||||||
"label": "Reset Dashboard Login",
|
|
||||||
"description": "Reset the Traefik dashboard credentials (CFG_TRAEFIK_USER / CFG_TRAEFIK_PASS) and regenerate the htpasswd entry in protectionauth.yml. Leave fields blank to keep the current username and/or generate a new random password.",
|
|
||||||
"icon": "🔑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username (leave blank to keep current)", "type": "text", "placeholder": "admin" },
|
|
||||||
{ "name": "password", "label": "New password (leave blank to generate)", "type": "password", "placeholder": "Leave blank for random" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nextcloud": {
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"id": "reset_password",
|
|
||||||
"category": "users",
|
|
||||||
"label": "Reset User Password",
|
|
||||||
"description": "Reset an existing Nextcloud user's password. Leave the password field blank to generate a random one — it is shown in the task log.",
|
|
||||||
"icon": "🔑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "placeholder": "alice", "required": true },
|
|
||||||
{ "name": "password", "label": "New password (leave blank to generate)", "type": "password", "placeholder": "Leave blank for random" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "create_account",
|
|
||||||
"category": "users",
|
|
||||||
"label": "Create User Account",
|
|
||||||
"description": "Create a new Nextcloud user. Tick \"Make admin\" to add them to the admin group. Leave the password blank to generate a random one.",
|
|
||||||
"icon": "👤",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "placeholder": "alice", "required": true },
|
|
||||||
{ "name": "display_name", "label": "Display name", "type": "text", "placeholder": "Alice Smith" },
|
|
||||||
{ "name": "password", "label": "Password (leave blank to generate)", "type": "password", "placeholder": "Leave blank for random" },
|
|
||||||
{ "name": "admin", "label": "Make admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ "id": "list_users", "category": "users", "label": "List Users", "description": "Show every Nextcloud user with their display name and admin flag.", "icon": "📋", "fields": [] },
|
|
||||||
{
|
|
||||||
"id": "delete_user", "category": "users", "label": "Delete User Account",
|
|
||||||
"description": "Permanently delete a user and all their files.", "icon": "🗑",
|
|
||||||
"destructive": true, "confirm": "This cannot be undone. The user's files will be removed.",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "set_admin", "category": "users", "label": "Set Admin Status",
|
|
||||||
"description": "Add a user to (or remove from) the admin group.", "icon": "👑",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username", "type": "text", "required": true },
|
|
||||||
{ "name": "admin", "label": "Make admin", "type": "checkbox", "default": false }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "toggle_maintenance", "category": "maintenance", "label": "Toggle Maintenance Mode",
|
|
||||||
"description": "Lock all users out and show a maintenance notice — required before running upgrades or repairs from the CLI.", "icon": "🚧",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "enable", "label": "Enable maintenance mode", "type": "checkbox", "default": true }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "rescan_files", "category": "maintenance", "label": "Rescan Files",
|
|
||||||
"description": "Re-index Nextcloud's file metadata. Run this after files were added or removed on disk outside Nextcloud (rsync, restore, manual copy). Leave the username blank to scan every user.", "icon": "🔄",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "username", "label": "Username (blank = all users)", "type": "text", "placeholder": "blank for all" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "add_trusted_domain", "category": "system", "label": "Add Trusted Domain",
|
|
||||||
"description": "Append a hostname to Nextcloud's trusted_domains list so requests to that host are accepted.", "icon": "🌐",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "domain", "label": "Domain", "type": "text", "placeholder": "cloud.example.org", "required": true }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "system_status", "category": "system", "label": "System Status",
|
|
||||||
"description": "Show Nextcloud's version, install state, and maintenance flag.", "icon": "ℹ️",
|
|
||||||
"fields": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "tail_logs", "category": "system", "label": "Tail Logs",
|
|
||||||
"description": "Show the most recent lines of nextcloud.log.", "icon": "📜",
|
|
||||||
"fields": [
|
|
||||||
{ "name": "lines", "label": "Lines", "type": "number", "default": 100, "min": 10, "max": 1000 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
JSON
|
JSON
|
||||||
|
|
||||||
# Merge per-app tool declarations so a DROPPED-IN app (e.g. from LibrePortal-Infra)
|
# Merge per-app tool declarations so any app — core or DROPPED-IN (e.g. from
|
||||||
# registers its own Tools tab actions without editing this file. Each app may ship
|
# LibrePortal-Infra) — registers its own Tools tab actions without editing this
|
||||||
# containers/<app>/<app>.tools.json = { "tools": [ … ] } (same schema as above);
|
# file. Each app ships containers/<app>/tools/<app>.tools.json = { "tools": [ … ] };
|
||||||
# it sets .apps[<app>]. Core apps declared in the heredoc need no such file.
|
# it sets .apps[<app>]. The tool functions live beside it in the same tools/
|
||||||
|
# folder and are live-sourced by the container scan.
|
||||||
if command -v jq >/dev/null 2>&1; then
|
if command -v jq >/dev/null 2>&1; then
|
||||||
local _tj _app
|
local _tj _app
|
||||||
for _tj in "${install_containers_dir}"*/tools/*.tools.json; do
|
for _tj in "${install_containers_dir}"*/tools/*.tools.json; do
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user