mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-02-04 12:23:26 +01:00
Update contribution docs and templates for best practices
Refreshed AI.md with new reference scripts, expanded checklist, and improved AI assistant tips. Updated container and install script templates for modern defaults (Debian 13, larger disk, two tags), clarified helper function usage, and improved update/backup patterns. Enhanced JSON template with realistic metadata, new fields, and example notes.
This commit is contained in:
@@ -624,40 +624,33 @@ cleanup_lxc
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Checklist Before PR Creation
|
||||
## 📖 Reference: Good Example Scripts
|
||||
|
||||
- [ ] No Docker installation used
|
||||
- [ ] `fetch_and_deploy_gh_release` used for GitHub releases
|
||||
- [ ] `check_for_gh_release` used for update checks
|
||||
- [ ] `setup_*` functions used for runtimes (nodejs, postgresql, etc.)
|
||||
- [ ] **`tools.func` functions NOT wrapped in msg_info/msg_ok blocks**
|
||||
- [ ] No redundant variables
|
||||
- [ ] `$STD` before all apt/npm/build commands
|
||||
- [ ] `msg_info`/`msg_ok`/`msg_error` for logging (only for custom code)
|
||||
- [ ] Correct script structure followed
|
||||
- [ ] Update function present and functional
|
||||
- [ ] Data backup implemented in update function
|
||||
- [ ] `motd_ssh`, `customize`, `cleanup_lxc` at the end
|
||||
- [ ] No custom download/version-check logic
|
||||
- [ ] JSON metadata file created in `frontend/public/json/<appname>.json`
|
||||
Look at these recent well-implemented applications as reference:
|
||||
|
||||
---
|
||||
### Container Scripts (Latest 10)
|
||||
- [ct/thingsboard.sh](../ct/thingsboard.sh) - IoT platform with proper update_script
|
||||
- [ct/unifi-os-server.sh](../ct/unifi-os-server.sh) - Complex setup with podman
|
||||
- [ct/trip.sh](../ct/trip.sh) - Simple Ruby app
|
||||
- [ct/fladder.sh](../ct/fladder.sh) - Media app with database
|
||||
- [ct/qui.sh](../ct/qui.sh) - Lightweight utility
|
||||
- [ct/kutt.sh](../ct/kutt.sh) - Node.js with PostgreSQL
|
||||
- [ct/flatnotes.sh](../ct/flatnotes.sh) - Python notes app
|
||||
- [ct/investbrain.sh](../ct/investbrain.sh) - Finance app
|
||||
- [ct/gwn-manager.sh](../ct/gwn-manager.sh) - Network management
|
||||
- [ct/sportarr.sh](../ct/sportarr.sh) - Specialized *Arr variant
|
||||
|
||||
## 📖 Reference: Good Example (Termix)
|
||||
### Install Scripts (Latest)
|
||||
- [install/unifi-os-server-install.sh](../install/unifi-os-server-install.sh) - Complex setup with API integration
|
||||
- [install/trip-install.sh](../install/trip-install.sh) - Rails application setup
|
||||
- [install/mail-archiver-install.sh](../install/mail-archiver-install.sh) - Email-related service
|
||||
|
||||
### CT Script: [ct/termix.sh](../ct/termix.sh)
|
||||
|
||||
- Uses `check_for_gh_release` for version checking
|
||||
- Uses `CLEAN_INSTALL=1 fetch_and_deploy_gh_release` for clean updates
|
||||
- Backup/restore of `/opt/termix/data`
|
||||
- Correct structure with all required variables
|
||||
|
||||
### Install Script: [install/termix-install.sh](../install/termix-install.sh)
|
||||
|
||||
- `NODE_VERSION="22" setup_nodejs` instead of manual installation
|
||||
- `fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix"` instead of wget/curl
|
||||
- Clean service configuration
|
||||
- Correct footer with `motd_ssh`, `customize`, `cleanup_lxc`
|
||||
**Key things to notice:**
|
||||
- Proper error handling with `catch_errors`
|
||||
- Use of `check_for_gh_release` and `fetch_and_deploy_gh_release`
|
||||
- Correct backup/restore patterns in `update_script`
|
||||
- Footer always ends with `motd_ssh`, `customize`, `cleanup_lxc`
|
||||
- JSON metadata files created for each app
|
||||
|
||||
---
|
||||
|
||||
@@ -792,19 +785,51 @@ Or no credentials:
|
||||
|
||||
---
|
||||
|
||||
## <EFBFBD>💡 Tips for AI Assistants
|
||||
## 🔍 Checklist Before PR Creation
|
||||
|
||||
1. **Search `tools.func` first** before implementing custom solutions
|
||||
2. **Use existing scripts as reference** (e.g., `linkwarden-install.sh`, `homarr-install.sh`)
|
||||
- [ ] No Docker installation used
|
||||
- [ ] `fetch_and_deploy_gh_release` used for GitHub releases
|
||||
- [ ] `check_for_gh_release` used for update checks
|
||||
- [ ] `setup_*` functions used for runtimes (nodejs, postgresql, etc.)
|
||||
- [ ] **`tools.func` functions NOT wrapped in msg_info/msg_ok blocks**
|
||||
- [ ] No redundant variables (only when used multiple times)
|
||||
- [ ] `$STD` before all apt/npm/build commands
|
||||
- [ ] `msg_info`/`msg_ok`/`msg_error` for logging (only for custom code)
|
||||
- [ ] Correct script structure followed (see templates)
|
||||
- [ ] Update function present and functional (CT scripts)
|
||||
- [ ] Data backup implemented in update function (if applicable)
|
||||
- [ ] `motd_ssh`, `customize`, `cleanup_lxc` at the end of install scripts
|
||||
- [ ] No custom download/version-check logic
|
||||
- [ ] All links point to `community-scripts/ProxmoxVE` (not `ProxmoxVED`!)
|
||||
- [ ] JSON metadata file created in `frontend/public/json/<appname>.json`
|
||||
- [ ] Category IDs are valid (0-25)
|
||||
- [ ] Default OS version is Debian 13 or newer (unless special requirement)
|
||||
- [ ] Default resources are reasonable for the application
|
||||
|
||||
---
|
||||
|
||||
## 💡 Tips for AI Assistants
|
||||
|
||||
1. **ALWAYS search `tools.func` first** before implementing custom solutions
|
||||
2. **Use recent scripts as reference** (Thingsboard, UniFi OS, Trip, Flatnotes, etc.)
|
||||
3. **Ask when uncertain** instead of introducing wrong patterns
|
||||
4. **Consistency > Creativity** - follow established patterns
|
||||
5. **Test local variables** - use `${VAR:-default}` pattern for optional values
|
||||
4. **Test locally** - try running scripts in test containers
|
||||
5. **Consistency > Creativity** - follow established patterns strictly
|
||||
6. **Check the templates** - they show the correct structure
|
||||
7. **Don't wrap tools.func functions** - they handle their own msg_info/msg_ok output
|
||||
8. **Minimal variables** - only create variables that are truly reused multiple times
|
||||
9. **Always use $STD** - ensures silent/non-interactive execution
|
||||
10. **Reference good examples** - look at recent additions in each category
|
||||
|
||||
---
|
||||
|
||||
## 📚 Further Documentation
|
||||
|
||||
- [CONTRIBUTING.md](contribution/CONTRIBUTING.md) - General contribution guidelines
|
||||
- [GUIDE.md](contribution/GUIDE.md) - Detailed developer documentation
|
||||
- [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md) - Technical details
|
||||
- [EXIT_CODES.md](EXIT_CODES.md) - Exit code reference
|
||||
- [CONTRIBUTING.md](CONTRIBUTING.md) - General contribution guidelines
|
||||
- [GUIDE.md](GUIDE.md) - Detailed developer documentation
|
||||
- [HELPER_FUNCTIONS.md](HELPER_FUNCTIONS.md) - Complete tools.func reference
|
||||
- [../TECHNICAL_REFERENCE.md](../TECHNICAL_REFERENCE.md) - Technical deep dive
|
||||
- [../EXIT_CODES.md](../EXIT_CODES.md) - Exit code reference
|
||||
- [templates_ct/](templates_ct/) - CT script templates
|
||||
- [templates_install/](templates_install/) - Install script templates
|
||||
- [templates_json/](templates_json/) - JSON metadata templates
|
||||
|
||||
@@ -7,12 +7,12 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
||||
|
||||
# App Default Values
|
||||
APP="[AppName]"
|
||||
var_tags="${var_tags:-[category]}"
|
||||
var_tags="${var_tags:-[category1];[category2]}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-2048}"
|
||||
var_disk="${var_disk:-4}"
|
||||
var_disk="${var_disk:-8}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-12}"
|
||||
var_version="${var_version:-13}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
# =============================================================================
|
||||
@@ -20,12 +20,12 @@ var_unprivileged="${var_unprivileged:-1}"
|
||||
# =============================================================================
|
||||
# APP - Display name, title case (e.g. "Koel", "Wallabag", "Actual Budget")
|
||||
# var_tags - Max 2 tags, semicolon separated (e.g. "music;streaming", "finance")
|
||||
# var_cpu - CPU cores: 1-4 typical
|
||||
# var_ram - RAM in MB: 512, 1024, 2048, 4096 typical
|
||||
# var_disk - Disk in GB: 4, 6, 8, 10, 20 typical
|
||||
# var_cpu - CPU cores: 1-4 typical, 4+ for heavy apps
|
||||
# var_ram - RAM in MB: 512, 1024, 2048, 4096, 8192 typical
|
||||
# var_disk - Disk in GB: 6, 8, 10, 20 typical (more for data-heavy apps)
|
||||
# var_os - OS: debian, ubuntu, alpine
|
||||
# var_version - OS version: 12/13 (debian), 22.04/24.04 (ubuntu), 3.20/3.21 (alpine)
|
||||
# var_unprivileged - 1 = unprivileged (secure, default), 0 = privileged (for docker etc.)
|
||||
# var_version - OS version: 13 (debian), 24.04 (ubuntu), 3.21 (alpine)
|
||||
# var_unprivileged - 1 = unprivileged (secure, default), 0 = privileged (for podman/docker)
|
||||
|
||||
header_info "$APP"
|
||||
variables
|
||||
@@ -45,39 +45,32 @@ function update_script() {
|
||||
|
||||
# check_for_gh_release returns 0 (true) if update available, 1 (false) if not
|
||||
if check_for_gh_release "[appname]" "[owner/repo]"; then
|
||||
msg_info "Stopping Services"
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop [appname]
|
||||
msg_ok "Stopped Services"
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
# Optional: Backup important data before update
|
||||
msg_info "Creating Backup"
|
||||
mkdir -p /tmp/[appname]_backup
|
||||
cp /opt/[appname]/.env /tmp/[appname]_backup/ 2>/dev/null || true
|
||||
cp -r /opt/[appname]/data /tmp/[appname]_backup/ 2>/dev/null || true
|
||||
msg_ok "Created Backup"
|
||||
msg_info "Backing up Data"
|
||||
cp -r /opt/[appname]/data /opt/[appname]_data_backup 2>/dev/null || true
|
||||
msg_ok "Backed up Data"
|
||||
|
||||
# CLEAN_INSTALL=1 removes old directory before extracting new version
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "[appname]" "[owner/repo]" "tarball" "latest" "/opt/[appname]"
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "[appname]" "[owner/repo]"
|
||||
|
||||
# Restore configuration and data
|
||||
# Restore configuration and data (if needed)
|
||||
msg_info "Restoring Data"
|
||||
cp /tmp/[appname]_backup/.env /opt/[appname]/ 2>/dev/null || true
|
||||
cp -r /tmp/[appname]_backup/data/* /opt/[appname]/data/ 2>/dev/null || true
|
||||
rm -rf /tmp/[appname]_backup
|
||||
cp -r /opt/[appname]_data_backup/. /opt/[appname]/data/ 2>/dev/null || true
|
||||
rm -rf /opt/[appname]_data_backup
|
||||
msg_ok "Restored Data"
|
||||
|
||||
# Optional: Run any post-update commands
|
||||
msg_info "Running Post-Update Tasks"
|
||||
cd /opt/[appname]
|
||||
# Examples:
|
||||
# $STD npm ci --production
|
||||
# $STD php artisan migrate --force
|
||||
# $STD composer install --no-dev
|
||||
msg_ok "Ran Post-Update Tasks"
|
||||
# Optional: Run any post-update commands (npm, composer, migrations, etc.)
|
||||
# cd /opt/[appname] && $STD npm ci --production
|
||||
# cd /opt/[appname] && $STD composer install --no-dev
|
||||
# cd /opt/[appname] && $STD php artisan migrate --force
|
||||
|
||||
msg_info "Starting Services"
|
||||
msg_info "Starting Service"
|
||||
systemctl start [appname]
|
||||
msg_ok "Started Services"
|
||||
msg_ok "Started Service"
|
||||
|
||||
msg_ok "Updated successfully!"
|
||||
fi
|
||||
|
||||
@@ -14,90 +14,121 @@ setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
# =============================================================================
|
||||
# AVAILABLE HELPER FUNCTIONS (from tools.func)
|
||||
# =============================================================================
|
||||
#
|
||||
# LANGUAGE/RUNTIME SETUP (use these, DON'T do manual installation!):
|
||||
# NODE_VERSION="22" setup_nodejs # Node.js (18, 20, 22)
|
||||
# PYTHON_VERSION="3.13" setup_uv # Python with uv package manager
|
||||
# GO_VERSION="1.22" setup_go # Go language
|
||||
# RUST_CRATES="monolith" setup_rust # Rust
|
||||
# RUBY_VERSION="3.3" setup_ruby # Ruby
|
||||
# JAVA_VERSION="21" setup_java # Java (17, 21)
|
||||
# PHP_VERSION="8.4" setup_php # PHP
|
||||
#
|
||||
# DATABASE SETUP (use these instead of manual setup!):
|
||||
# setup_postgresql # PostgreSQL server
|
||||
# PG_DB_NAME="mydb" PG_DB_USER="myuser" setup_postgresql_db # Create DB & user
|
||||
# setup_mariadb # MariaDB server
|
||||
# MARIADB_DB_NAME="mydb" setup_mariadb_db # Create MariaDB DB
|
||||
# setup_mysql # MySQL server
|
||||
# setup_mongodb # MongoDB server
|
||||
#
|
||||
# GITHUB RELEASES (PREFERRED - handles versioning automatically!):
|
||||
# fetch_and_deploy_gh_release "appname" "owner/repo" # Auto-detect mode
|
||||
# fetch_and_deploy_gh_release "appname" "owner/repo" "binary" # .deb package
|
||||
# CLEAN_INSTALL=1 fetch_and_deploy_gh_release ... # Clean install (remove old dir first)
|
||||
#
|
||||
# UTILITIES:
|
||||
# import_local_ip # Sets $LOCAL_IP variable (call early!)
|
||||
# setup_ffmpeg # FFmpeg with codecs
|
||||
# setup_imagemagick # ImageMagick 7
|
||||
# setup_hwaccel # GPU acceleration
|
||||
# setup_docker # Docker Engine
|
||||
# setup_adminer # Adminer (DB web interface)
|
||||
|
||||
# =============================================================================
|
||||
# DEPENDENCIES
|
||||
# =============================================================================
|
||||
# Only install what's actually needed - curl/sudo/mc are already in the base image
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt install -y \
|
||||
nginx \
|
||||
build-essential
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
# =============================================================================
|
||||
# HELPER FUNCTIONS FROM tools.func
|
||||
# =============================================================================
|
||||
# These functions are available via $FUNCTIONS_FILE_PATH (tools.func)
|
||||
# Call them with optional environment variables for configuration
|
||||
#
|
||||
# --- Runtime & Language Setup ---
|
||||
# NODE_VERSION="22" setup_nodejs # Install Node.js (22, 24)
|
||||
# NODE_VERSION="24" NODE_MODULE="pnpm" setup_nodejs # With pnpm
|
||||
# PYTHON_VERSION="3.13" setup_uv # Python with uv package manager
|
||||
# setup_go # Install Go (latest)
|
||||
# setup_rust # Install Rust via rustup
|
||||
# setup_ruby # Install Ruby
|
||||
# PHP_VERSION="8.4" PHP_FPM="YES" PHP_MODULE="mysqli,gd" setup_php
|
||||
# PHP_VERSION="8.3" PHP_FPM="YES" PHP_APACHE="YES" PHP_MODULE="bcmath,curl,gd,intl,mbstring,mysql,xml,zip" setup_php
|
||||
# setup_composer # Install PHP Composer
|
||||
# JAVA_VERSION="21" setup_java # Install Java (17, 21)
|
||||
#
|
||||
# --- Database Setup ---
|
||||
# setup_mariadb # Install MariaDB server
|
||||
# MARIADB_DB_NAME="mydb" MARIADB_DB_USER="myuser" setup_mariadb_db
|
||||
# setup_mysql # Install MySQL server
|
||||
# PG_VERSION="17" setup_postgresql # Install PostgreSQL (16, 17)
|
||||
# PG_VERSION="17" PG_MODULES="postgis" setup_postgresql # With extensions
|
||||
# PG_DB_NAME="mydb" PG_DB_USER="myuser" setup_postgresql_db
|
||||
# setup_mongodb # Install MongoDB
|
||||
#
|
||||
# --- GitHub Release (PREFERRED METHOD) ---
|
||||
# fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" # Downloads, extracts, tracks version
|
||||
# fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname"
|
||||
# fetch_and_deploy_gh_release "appname" "owner/repo" "prebuild" "latest" "/opt/appname" "app-*.tar.gz"
|
||||
#
|
||||
# --- Tools & Utilities ---
|
||||
# import_local_ip # Sets $LOCAL_IP variable (call early!)
|
||||
# setup_ffmpeg # Install FFmpeg with codecs
|
||||
# setup_hwaccel # Setup GPU hardware acceleration
|
||||
# setup_imagemagick # Install ImageMagick 7
|
||||
# setup_docker # Install Docker Engine
|
||||
# setup_adminer # Install Adminer for DB management
|
||||
# create_self_signed_cert # Creates cert in /etc/ssl/[appname]/
|
||||
|
||||
# =============================================================================
|
||||
# EXAMPLE 1: Node.js Application with PostgreSQL
|
||||
# EXAMPLE: Node.js App with PostgreSQL
|
||||
# =============================================================================
|
||||
# NODE_VERSION="22" setup_nodejs
|
||||
# PG_VERSION="17" setup_postgresql
|
||||
# PG_DB_NAME="myapp" PG_DB_USER="myapp" setup_postgresql_db
|
||||
# import_local_ip
|
||||
# fetch_and_deploy_gh_release "myapp" "owner/myapp" "tarball" "latest" "/opt/myapp"
|
||||
#
|
||||
# msg_info "Configuring MyApp"
|
||||
# msg_info "Deploying Application"
|
||||
# fetch_and_deploy_gh_release "myapp" "owner/myapp"
|
||||
# msg_ok "Deployed Application"
|
||||
#
|
||||
# msg_info "Installing Dependencies"
|
||||
# cd /opt/myapp
|
||||
# $STD npm ci
|
||||
# $STD npm ci --production
|
||||
# msg_ok "Installed Dependencies"
|
||||
#
|
||||
# msg_info "Configuring Environment"
|
||||
# cat <<EOF >/opt/myapp/.env
|
||||
# DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME}
|
||||
# HOST=${LOCAL_IP}
|
||||
# PORT=3000
|
||||
# APP_HOST=${LOCAL_IP}
|
||||
# APP_PORT=3000
|
||||
# NODE_ENV=production
|
||||
# EOF
|
||||
# msg_ok "Configured MyApp"
|
||||
# msg_ok "Configured Environment"
|
||||
|
||||
# =============================================================================
|
||||
# EXAMPLE 2: Python Application with uv
|
||||
# EXAMPLE: Python App with uv
|
||||
# =============================================================================
|
||||
# PYTHON_VERSION="3.13" setup_uv
|
||||
# import_local_ip
|
||||
# fetch_and_deploy_gh_release "myapp" "owner/myapp" "tarball" "latest" "/opt/myapp"
|
||||
# msg_info "Deploying Application"
|
||||
# fetch_and_deploy_gh_release "myapp" "owner/myapp"
|
||||
# msg_ok "Deployed Application"
|
||||
#
|
||||
# msg_info "Setting up MyApp"
|
||||
# msg_info "Installing Dependencies"
|
||||
# cd /opt/myapp
|
||||
# $STD uv sync
|
||||
# $STD uv sync --frozen
|
||||
# msg_ok "Installed Dependencies"
|
||||
#
|
||||
# cat <<EOF >/opt/myapp/.env
|
||||
# HOST=${LOCAL_IP}
|
||||
# PORT=8000
|
||||
# DEBUG=false
|
||||
# EOF
|
||||
|
||||
# =============================================================================
|
||||
# CREATE SYSTEMD SERVICE
|
||||
# =============================================================================
|
||||
|
||||
msg_info "Creating Service"
|
||||
cat <<EOF >/etc/systemd/system/[appname].service
|
||||
[Unit]
|
||||
Description=[AppName] Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/[appname]
|
||||
Environment=NODE_ENV=production
|
||||
ExecStart=/usr/bin/node /opt/[appname]/server.js
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now [appname]
|
||||
msg_ok "Created Service"
|
||||
# EOF
|
||||
# msg_ok "Setup MyApp"
|
||||
|
||||
|
||||
28
docs/contribution/templates_json/AppName.json
generated
28
docs/contribution/templates_json/AppName.json
generated
@@ -4,25 +4,26 @@
|
||||
"categories": [
|
||||
0
|
||||
],
|
||||
"date_created": "DATE CREATED",
|
||||
"date_created": "2026-01-18",
|
||||
"type": "ct",
|
||||
"updateable": true,
|
||||
"privileged": false,
|
||||
"interface_port": "DEFAULT-PORT",
|
||||
"documentation": null,
|
||||
"website": "LINK TO WEBSITE",
|
||||
"logo": "LINK TO LOGO",
|
||||
"description": "Description of the app",
|
||||
"interface_port": 3000,
|
||||
"documentation": "https://docs.example.com/",
|
||||
"website": "https://example.com/",
|
||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/appname.webp",
|
||||
"config_path": "/opt/appname/.env",
|
||||
"description": "Short description of what AppName does and its main features.",
|
||||
"install_methods": [
|
||||
{
|
||||
"type": "default",
|
||||
"script": "ct/AppName.sh",
|
||||
"script": "ct/appname.sh",
|
||||
"resources": {
|
||||
"cpu": 2,
|
||||
"ram": 2048,
|
||||
"hdd": 4,
|
||||
"os": "debian",
|
||||
"version": "12"
|
||||
"hdd": 8,
|
||||
"os": "Debian",
|
||||
"version": "13"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -30,5 +31,10 @@
|
||||
"username": null,
|
||||
"password": null
|
||||
},
|
||||
"notes": []
|
||||
"notes": [
|
||||
{
|
||||
"text": "Change the default password after first login!",
|
||||
"type": "warning"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user