823 lines
22 KiB
Bash
823 lines
22 KiB
Bash
#!/bin/sh
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
# RPCD backend for MetaBlogizer Static Site Publisher
|
|
# Copyright (C) 2025 CyberMind.fr
|
|
|
|
. /lib/functions.sh
|
|
. /usr/share/libubox/jshn.sh
|
|
|
|
UCI_CONFIG="metablogizer"
|
|
SITES_ROOT="/srv/metablogizer/sites"
|
|
NGINX_CONTAINER="nginx"
|
|
PORT_BASE=8900
|
|
|
|
# Helper: Get UCI value with default
|
|
get_uci() {
|
|
local section="$1"
|
|
local option="$2"
|
|
local default="$3"
|
|
local value
|
|
value=$(uci -q get "$UCI_CONFIG.$section.$option")
|
|
echo "${value:-$default}"
|
|
}
|
|
|
|
# Runtime detection (uhttpd preferred, nginx fallback)
|
|
detect_runtime() {
|
|
local configured=$(get_uci main runtime "auto")
|
|
case "$configured" in
|
|
uhttpd) [ -x /etc/init.d/uhttpd ] && echo "uhttpd" || echo "none" ;;
|
|
nginx) lxc-info -n "$NGINX_CONTAINER" >/dev/null 2>&1 && echo "nginx" || echo "none" ;;
|
|
auto|*) [ -x /etc/init.d/uhttpd ] && echo "uhttpd" || \
|
|
(lxc-info -n "$NGINX_CONTAINER" >/dev/null 2>&1 && echo "nginx" || echo "none") ;;
|
|
esac
|
|
}
|
|
|
|
# Get next available port for uhttpd
|
|
get_next_port() {
|
|
local port=$PORT_BASE
|
|
while uci show uhttpd 2>/dev/null | grep -q "listen_http='0.0.0.0:$port'"; do
|
|
port=$((port + 1))
|
|
done
|
|
echo $port
|
|
}
|
|
|
|
# Fix permissions for web serving (755 for dirs, 644 for files)
|
|
fix_permissions() {
|
|
local dir="$1"
|
|
[ -d "$dir" ] || return 1
|
|
chmod 755 "$dir"
|
|
find "$dir" -type d -exec chmod 755 {} \;
|
|
find "$dir" -type f -exec chmod 644 {} \;
|
|
}
|
|
|
|
# Status method - get overall status and list all sites
|
|
method_status() {
|
|
local enabled runtime detected_runtime nginx_running site_count
|
|
|
|
enabled=$(get_uci main enabled 0)
|
|
runtime=$(get_uci main runtime "auto")
|
|
SITES_ROOT=$(get_uci main sites_root "$SITES_ROOT")
|
|
NGINX_CONTAINER=$(get_uci main nginx_container "$NGINX_CONTAINER")
|
|
|
|
# Detect runtime
|
|
detected_runtime=$(detect_runtime)
|
|
|
|
# Check nginx container if using nginx
|
|
nginx_running="0"
|
|
if lxc-info -n "$NGINX_CONTAINER" -s 2>/dev/null | grep -q "RUNNING"; then
|
|
nginx_running="1"
|
|
fi
|
|
|
|
# Count sites
|
|
site_count=0
|
|
config_load "$UCI_CONFIG"
|
|
config_foreach _count_site site
|
|
site_count="$_site_count"
|
|
|
|
json_init
|
|
json_add_boolean "enabled" "$enabled"
|
|
json_add_string "runtime" "$runtime"
|
|
json_add_string "detected_runtime" "$detected_runtime"
|
|
json_add_boolean "nginx_running" "$nginx_running"
|
|
json_add_int "site_count" "$site_count"
|
|
json_add_string "sites_root" "$SITES_ROOT"
|
|
json_add_string "nginx_container" "$NGINX_CONTAINER"
|
|
json_dump
|
|
}
|
|
|
|
_site_count=0
|
|
_count_site() {
|
|
_site_count=$((_site_count + 1))
|
|
}
|
|
|
|
# List all sites with their status
|
|
method_list_sites() {
|
|
SITES_ROOT=$(get_uci main sites_root "$SITES_ROOT")
|
|
|
|
json_init
|
|
json_add_array "sites"
|
|
|
|
config_load "$UCI_CONFIG"
|
|
config_foreach _add_site site
|
|
|
|
json_close_array
|
|
json_dump
|
|
}
|
|
|
|
_add_site() {
|
|
local section="$1"
|
|
local name domain gitea_repo ssl enabled description
|
|
local has_content last_sync
|
|
|
|
config_get name "$section" name ""
|
|
config_get domain "$section" domain ""
|
|
config_get gitea_repo "$section" gitea_repo ""
|
|
config_get ssl "$section" ssl "1"
|
|
config_get enabled "$section" enabled "1"
|
|
config_get description "$section" description ""
|
|
|
|
# Check if site has content
|
|
has_content="0"
|
|
if [ -d "$SITES_ROOT/$name" ] && [ -f "$SITES_ROOT/$name/index.html" ]; then
|
|
has_content="1"
|
|
fi
|
|
|
|
# Get last sync time
|
|
last_sync=""
|
|
if [ -d "$SITES_ROOT/$name/.git" ]; then
|
|
last_sync=$(cd "$SITES_ROOT/$name" && git log -1 --format="%ci" 2>/dev/null || echo "")
|
|
fi
|
|
|
|
json_add_object
|
|
json_add_string "id" "$section"
|
|
json_add_string "name" "$name"
|
|
json_add_string "domain" "$domain"
|
|
json_add_string "gitea_repo" "$gitea_repo"
|
|
json_add_string "description" "$description"
|
|
json_add_boolean "ssl" "$ssl"
|
|
json_add_boolean "enabled" "$enabled"
|
|
json_add_boolean "has_content" "$has_content"
|
|
json_add_string "last_sync" "$last_sync"
|
|
json_add_string "url" "https://$domain"
|
|
json_close_object
|
|
}
|
|
|
|
# Create a new site with auto-vhost
|
|
method_create_site() {
|
|
local name domain gitea_repo ssl description
|
|
local section_id gitea_url
|
|
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var name name
|
|
json_get_var domain domain
|
|
json_get_var gitea_repo gitea_repo
|
|
json_get_var ssl ssl "1"
|
|
json_get_var description description ""
|
|
|
|
# Validate required fields
|
|
if [ -z "$name" ] || [ -z "$domain" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Name and domain are required"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
# Sanitize name for section ID
|
|
section_id="site_$(echo "$name" | sed 's/[^a-zA-Z0-9]/_/g')"
|
|
|
|
# Check if site already exists
|
|
if uci -q get "$UCI_CONFIG.$section_id" >/dev/null 2>&1; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Site with this name already exists"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
SITES_ROOT=$(get_uci main sites_root "$SITES_ROOT")
|
|
NGINX_CONTAINER=$(get_uci main nginx_container "$NGINX_CONTAINER")
|
|
|
|
# 1. Create UCI site config
|
|
uci set "$UCI_CONFIG.$section_id=site"
|
|
uci set "$UCI_CONFIG.$section_id.name=$name"
|
|
uci set "$UCI_CONFIG.$section_id.domain=$domain"
|
|
uci set "$UCI_CONFIG.$section_id.ssl=$ssl"
|
|
uci set "$UCI_CONFIG.$section_id.enabled=1"
|
|
[ -n "$gitea_repo" ] && uci set "$UCI_CONFIG.$section_id.gitea_repo=$gitea_repo"
|
|
[ -n "$description" ] && uci set "$UCI_CONFIG.$section_id.description=$description"
|
|
|
|
# 2. Create site directory
|
|
mkdir -p "$SITES_ROOT/$name"
|
|
|
|
# 3. Clone from Gitea if repo specified
|
|
if [ -n "$gitea_repo" ]; then
|
|
gitea_url=$(uci -q get gitea.main.url || echo "http://192.168.255.1:3000")
|
|
git clone "$gitea_url/$gitea_repo.git" "$SITES_ROOT/$name" 2>/dev/null || true
|
|
fi
|
|
|
|
# 4. Fix permissions for web serving
|
|
fix_permissions "$SITES_ROOT/$name"
|
|
|
|
# 5. Create default index.html with OG tags if no content
|
|
if [ ! -f "$SITES_ROOT/$name/index.html" ]; then
|
|
cat > "$SITES_ROOT/$name/index.html" <<EOF
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>$name</title>
|
|
<meta property="og:title" content="$name">
|
|
<meta property="og:url" content="https://$domain">
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:description" content="$description">
|
|
<meta name="twitter:card" content="summary">
|
|
<meta name="twitter:title" content="$name">
|
|
<meta name="twitter:url" content="https://$domain">
|
|
<style>
|
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
display: flex; justify-content: center; align-items: center;
|
|
min-height: 100vh; margin: 0; background: #f5f5f5; }
|
|
.container { text-align: center; padding: 2rem; }
|
|
h1 { color: #333; }
|
|
p { color: #666; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>$name</h1>
|
|
<p>Site published with MetaBlogizer</p>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
EOF
|
|
fi
|
|
|
|
# 6. Detect runtime and configure accordingly
|
|
local current_runtime=$(detect_runtime)
|
|
local port=""
|
|
local server_address="192.168.255.1"
|
|
local server_port="80"
|
|
|
|
if [ "$current_runtime" = "uhttpd" ]; then
|
|
# Create uhttpd instance
|
|
port=$(get_next_port)
|
|
uci set "uhttpd.metablog_${section_id}=uhttpd"
|
|
uci set "uhttpd.metablog_${section_id}.listen_http=0.0.0.0:$port"
|
|
uci set "uhttpd.metablog_${section_id}.home=$SITES_ROOT/$name"
|
|
uci set "uhttpd.metablog_${section_id}.index_page=index.html"
|
|
uci set "uhttpd.metablog_${section_id}.error_page=/index.html"
|
|
uci commit uhttpd
|
|
/etc/init.d/uhttpd reload 2>/dev/null
|
|
server_port="$port"
|
|
else
|
|
# Configure nginx location in container
|
|
_configure_nginx "$name"
|
|
local nginx_ip
|
|
nginx_ip=$(lxc-info -n "$NGINX_CONTAINER" -iH 2>/dev/null | head -1)
|
|
[ -n "$nginx_ip" ] && server_address="$nginx_ip"
|
|
fi
|
|
|
|
# Save port to site config
|
|
[ -n "$port" ] && uci set "$UCI_CONFIG.$section_id.port=$port"
|
|
uci set "$UCI_CONFIG.$section_id.runtime=$current_runtime"
|
|
|
|
# 7. Create HAProxy backend
|
|
local backend_name="metablog_$(echo "$name" | sed 's/[^a-zA-Z0-9]/_/g')"
|
|
|
|
uci set "haproxy.$backend_name=backend"
|
|
uci set "haproxy.$backend_name.name=$backend_name"
|
|
uci set "haproxy.$backend_name.mode=http"
|
|
uci set "haproxy.$backend_name.balance=roundrobin"
|
|
uci set "haproxy.$backend_name.enabled=1"
|
|
|
|
# Create server
|
|
local server_name="${backend_name}_srv"
|
|
uci set "haproxy.$server_name=server"
|
|
uci set "haproxy.$server_name.backend=$backend_name"
|
|
uci set "haproxy.$server_name.name=srv"
|
|
uci set "haproxy.$server_name.address=$server_address"
|
|
uci set "haproxy.$server_name.port=$server_port"
|
|
uci set "haproxy.$server_name.weight=100"
|
|
uci set "haproxy.$server_name.check=1"
|
|
uci set "haproxy.$server_name.enabled=1"
|
|
|
|
# 8. Create HAProxy vhost
|
|
local vhost_name=$(echo "$domain" | sed 's/[^a-zA-Z0-9]/_/g')
|
|
local acme_val="0"
|
|
[ "$ssl" = "1" ] && acme_val="1"
|
|
|
|
uci set "haproxy.$vhost_name=vhost"
|
|
uci set "haproxy.$vhost_name.domain=$domain"
|
|
uci set "haproxy.$vhost_name.backend=$backend_name"
|
|
uci set "haproxy.$vhost_name.ssl=$ssl"
|
|
uci set "haproxy.$vhost_name.ssl_redirect=$ssl"
|
|
uci set "haproxy.$vhost_name.acme=$acme_val"
|
|
uci set "haproxy.$vhost_name.enabled=1"
|
|
uci commit haproxy
|
|
|
|
# Regenerate HAProxy config
|
|
/usr/sbin/haproxyctl generate >/dev/null 2>&1
|
|
/etc/init.d/haproxy reload >/dev/null 2>&1
|
|
|
|
uci commit "$UCI_CONFIG"
|
|
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_add_string "id" "$section_id"
|
|
json_add_string "url" "https://$domain"
|
|
json_add_string "name" "$name"
|
|
json_add_string "domain" "$domain"
|
|
json_dump
|
|
}
|
|
|
|
# Configure nginx location for a site
|
|
_configure_nginx() {
|
|
local site_name="$1"
|
|
local nginx_conf="/var/lib/lxc/$NGINX_CONTAINER/rootfs/etc/nginx/sites.d"
|
|
|
|
# Create nginx config for site
|
|
mkdir -p "$nginx_conf"
|
|
|
|
cat > "$nginx_conf/metablog-$site_name.conf" <<EOF
|
|
location /$site_name/ {
|
|
alias /srv/sites/$site_name/;
|
|
index index.html;
|
|
try_files \$uri \$uri/ /index.html;
|
|
}
|
|
EOF
|
|
|
|
# Reload nginx in container
|
|
lxc-attach -n "$NGINX_CONTAINER" -- nginx -s reload 2>/dev/null || true
|
|
}
|
|
|
|
# Delete a site and cleanup
|
|
method_delete_site() {
|
|
local id
|
|
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var id id
|
|
|
|
if [ -z "$id" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Missing site id"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
local name domain
|
|
name=$(get_uci "$id" name "")
|
|
domain=$(get_uci "$id" domain "")
|
|
|
|
if [ -z "$name" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Site not found"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
SITES_ROOT=$(get_uci main sites_root "$SITES_ROOT")
|
|
NGINX_CONTAINER=$(get_uci main nginx_container "$NGINX_CONTAINER")
|
|
|
|
# Get site runtime
|
|
local site_runtime=$(get_uci "$id" runtime "")
|
|
|
|
# 1. Delete HAProxy vhost
|
|
local vhost_id=$(echo "$domain" | sed 's/[^a-zA-Z0-9]/_/g')
|
|
uci delete "haproxy.$vhost_id" 2>/dev/null
|
|
|
|
# 2. Delete HAProxy backend and server
|
|
local backend_name="metablog_$(echo "$name" | sed 's/[^a-zA-Z0-9]/_/g')"
|
|
uci delete "haproxy.$backend_name" 2>/dev/null
|
|
uci delete "haproxy.${backend_name}_srv" 2>/dev/null
|
|
uci commit haproxy
|
|
/usr/sbin/haproxyctl generate >/dev/null 2>&1
|
|
/etc/init.d/haproxy reload >/dev/null 2>&1
|
|
|
|
# 3. Remove runtime config
|
|
if [ "$site_runtime" = "uhttpd" ]; then
|
|
# Remove uhttpd instance
|
|
uci delete "uhttpd.metablog_$id" 2>/dev/null
|
|
uci commit uhttpd
|
|
/etc/init.d/uhttpd reload 2>/dev/null
|
|
else
|
|
# Remove nginx config
|
|
rm -f "/var/lib/lxc/$NGINX_CONTAINER/rootfs/etc/nginx/sites.d/metablog-$name.conf"
|
|
lxc-attach -n "$NGINX_CONTAINER" -- nginx -s reload 2>/dev/null || true
|
|
fi
|
|
|
|
# 4. Remove site directory
|
|
rm -rf "$SITES_ROOT/$name"
|
|
|
|
# 5. Delete UCI config
|
|
uci delete "$UCI_CONFIG.$id"
|
|
uci commit "$UCI_CONFIG"
|
|
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_dump
|
|
}
|
|
|
|
# Sync site from Gitea (git pull)
|
|
method_sync_site() {
|
|
local id
|
|
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var id id
|
|
|
|
if [ -z "$id" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Missing site id"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
local name gitea_repo
|
|
name=$(get_uci "$id" name "")
|
|
gitea_repo=$(get_uci "$id" gitea_repo "")
|
|
|
|
if [ -z "$name" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Site not found"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
SITES_ROOT=$(get_uci main sites_root "$SITES_ROOT")
|
|
|
|
local site_path="$SITES_ROOT/$name"
|
|
|
|
if [ -d "$site_path/.git" ]; then
|
|
# Pull latest changes
|
|
cd "$site_path"
|
|
local result
|
|
result=$(git pull 2>&1)
|
|
local rc=$?
|
|
|
|
# Fix permissions after pull
|
|
fix_permissions "$site_path"
|
|
|
|
json_init
|
|
if [ $rc -eq 0 ]; then
|
|
json_add_boolean "success" 1
|
|
json_add_string "message" "$result"
|
|
else
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "$result"
|
|
fi
|
|
json_dump
|
|
elif [ -n "$gitea_repo" ]; then
|
|
# Clone if not exists
|
|
local gitea_url
|
|
gitea_url=$(uci -q get gitea.main.url || echo "http://192.168.255.1:3000")
|
|
|
|
rm -rf "$site_path"
|
|
local result
|
|
result=$(git clone "$gitea_url/$gitea_repo.git" "$site_path" 2>&1)
|
|
local rc=$?
|
|
|
|
# Fix permissions after clone
|
|
fix_permissions "$site_path"
|
|
|
|
json_init
|
|
if [ $rc -eq 0 ]; then
|
|
json_add_boolean "success" 1
|
|
json_add_string "message" "Cloned from $gitea_repo"
|
|
else
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "$result"
|
|
fi
|
|
json_dump
|
|
else
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "No git repository configured for this site"
|
|
json_dump
|
|
fi
|
|
}
|
|
|
|
# Get publish info for QR code generation
|
|
method_get_publish_info() {
|
|
local id
|
|
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var id id
|
|
|
|
if [ -z "$id" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Missing site id"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
local name domain description ssl
|
|
name=$(get_uci "$id" name "")
|
|
domain=$(get_uci "$id" domain "")
|
|
description=$(get_uci "$id" description "")
|
|
ssl=$(get_uci "$id" ssl "1")
|
|
|
|
if [ -z "$name" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Site not found"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
local protocol="http"
|
|
[ "$ssl" = "1" ] && protocol="https"
|
|
local url="${protocol}://${domain}"
|
|
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_add_string "id" "$id"
|
|
json_add_string "name" "$name"
|
|
json_add_string "domain" "$domain"
|
|
json_add_string "url" "$url"
|
|
json_add_string "description" "$description"
|
|
json_add_string "title" "$name - Published with SecuBox"
|
|
json_dump
|
|
}
|
|
|
|
# Get site details
|
|
method_get_site() {
|
|
local id
|
|
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var id id
|
|
|
|
if [ -z "$id" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Missing site id"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
local name domain gitea_repo ssl enabled description
|
|
name=$(get_uci "$id" name "")
|
|
domain=$(get_uci "$id" domain "")
|
|
gitea_repo=$(get_uci "$id" gitea_repo "")
|
|
ssl=$(get_uci "$id" ssl "1")
|
|
enabled=$(get_uci "$id" enabled "1")
|
|
description=$(get_uci "$id" description "")
|
|
|
|
if [ -z "$name" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Site not found"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
SITES_ROOT=$(get_uci main sites_root "$SITES_ROOT")
|
|
|
|
local has_content last_sync
|
|
has_content="0"
|
|
if [ -d "$SITES_ROOT/$name" ] && [ -f "$SITES_ROOT/$name/index.html" ]; then
|
|
has_content="1"
|
|
fi
|
|
last_sync=""
|
|
if [ -d "$SITES_ROOT/$name/.git" ]; then
|
|
last_sync=$(cd "$SITES_ROOT/$name" && git log -1 --format="%ci" 2>/dev/null || echo "")
|
|
fi
|
|
|
|
local protocol="http"
|
|
[ "$ssl" = "1" ] && protocol="https"
|
|
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_add_string "id" "$id"
|
|
json_add_string "name" "$name"
|
|
json_add_string "domain" "$domain"
|
|
json_add_string "gitea_repo" "$gitea_repo"
|
|
json_add_string "description" "$description"
|
|
json_add_boolean "ssl" "$ssl"
|
|
json_add_boolean "enabled" "$enabled"
|
|
json_add_boolean "has_content" "$has_content"
|
|
json_add_string "last_sync" "$last_sync"
|
|
json_add_string "url" "${protocol}://${domain}"
|
|
json_dump
|
|
}
|
|
|
|
# Update site settings
|
|
method_update_site() {
|
|
local id name domain gitea_repo ssl enabled description
|
|
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var id id
|
|
json_get_var name name
|
|
json_get_var domain domain
|
|
json_get_var gitea_repo gitea_repo
|
|
json_get_var ssl ssl
|
|
json_get_var enabled enabled
|
|
json_get_var description description
|
|
|
|
if [ -z "$id" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Missing site id"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
# Check site exists
|
|
local current_name
|
|
current_name=$(get_uci "$id" name "")
|
|
if [ -z "$current_name" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Site not found"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
[ -n "$name" ] && uci set "$UCI_CONFIG.$id.name=$name"
|
|
[ -n "$domain" ] && uci set "$UCI_CONFIG.$id.domain=$domain"
|
|
[ -n "$gitea_repo" ] && uci set "$UCI_CONFIG.$id.gitea_repo=$gitea_repo"
|
|
[ -n "$ssl" ] && uci set "$UCI_CONFIG.$id.ssl=$ssl"
|
|
[ -n "$enabled" ] && uci set "$UCI_CONFIG.$id.enabled=$enabled"
|
|
[ -n "$description" ] && uci set "$UCI_CONFIG.$id.description=$description"
|
|
uci commit "$UCI_CONFIG"
|
|
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_dump
|
|
}
|
|
|
|
# Upload file to site
|
|
method_upload_file() {
|
|
local id filename content
|
|
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var id id
|
|
json_get_var filename filename
|
|
json_get_var content content
|
|
|
|
if [ -z "$id" ] || [ -z "$filename" ] || [ -z "$content" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Missing required fields (id, filename, content)"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
local name
|
|
name=$(get_uci "$id" name "")
|
|
if [ -z "$name" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Site not found"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
SITES_ROOT=$(get_uci main sites_root "$SITES_ROOT")
|
|
local site_path="$SITES_ROOT/$name"
|
|
local file_path="$site_path/$filename"
|
|
|
|
# Create directory structure if needed
|
|
local dir_path=$(dirname "$file_path")
|
|
mkdir -p "$dir_path"
|
|
chmod 755 "$dir_path"
|
|
|
|
# Decode base64 content and write file
|
|
echo "$content" | base64 -d > "$file_path" 2>/dev/null
|
|
local rc=$?
|
|
|
|
if [ $rc -eq 0 ]; then
|
|
chmod 644 "$file_path"
|
|
# Ensure parent directories are also accessible
|
|
chmod 755 "$site_path"
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_add_string "filename" "$filename"
|
|
json_add_string "path" "$file_path"
|
|
json_dump
|
|
else
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Failed to write file"
|
|
json_dump
|
|
fi
|
|
}
|
|
|
|
# List files in a site
|
|
method_list_files() {
|
|
local id
|
|
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var id id
|
|
|
|
if [ -z "$id" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Missing site id"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
local name
|
|
name=$(get_uci "$id" name "")
|
|
if [ -z "$name" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "Site not found"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
SITES_ROOT=$(get_uci main sites_root "$SITES_ROOT")
|
|
local site_path="$SITES_ROOT/$name"
|
|
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_add_array "files"
|
|
|
|
if [ -d "$site_path" ]; then
|
|
find "$site_path" -type f 2>/dev/null | while read -r file; do
|
|
local rel_path="${file#$site_path/}"
|
|
local size=$(stat -c%s "$file" 2>/dev/null || echo "0")
|
|
json_add_object ""
|
|
json_add_string "name" "$rel_path"
|
|
json_add_int "size" "$size"
|
|
json_close_object
|
|
done
|
|
fi
|
|
|
|
json_close_array
|
|
json_dump
|
|
}
|
|
|
|
# Get global settings
|
|
method_get_settings() {
|
|
json_init
|
|
json_add_boolean "enabled" "$(get_uci main enabled 0)"
|
|
json_add_string "runtime" "$(get_uci main runtime auto)"
|
|
json_add_string "detected_runtime" "$(detect_runtime)"
|
|
json_add_string "nginx_container" "$(get_uci main nginx_container nginx)"
|
|
json_add_string "sites_root" "$(get_uci main sites_root /srv/metablogizer/sites)"
|
|
json_add_string "gitea_url" "$(get_uci main gitea_url http://localhost:3000)"
|
|
json_dump
|
|
}
|
|
|
|
# Save global settings
|
|
method_save_settings() {
|
|
local enabled runtime nginx_container sites_root gitea_url
|
|
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var enabled enabled
|
|
json_get_var runtime runtime
|
|
json_get_var nginx_container nginx_container
|
|
json_get_var sites_root sites_root
|
|
json_get_var gitea_url gitea_url
|
|
|
|
# Ensure main section exists
|
|
uci -q get "$UCI_CONFIG.main" >/dev/null 2>&1 || uci set "$UCI_CONFIG.main=metablogizer"
|
|
|
|
[ -n "$enabled" ] && uci set "$UCI_CONFIG.main.enabled=$enabled"
|
|
[ -n "$runtime" ] && uci set "$UCI_CONFIG.main.runtime=$runtime"
|
|
[ -n "$nginx_container" ] && uci set "$UCI_CONFIG.main.nginx_container=$nginx_container"
|
|
[ -n "$sites_root" ] && uci set "$UCI_CONFIG.main.sites_root=$sites_root"
|
|
[ -n "$gitea_url" ] && uci set "$UCI_CONFIG.main.gitea_url=$gitea_url"
|
|
uci commit "$UCI_CONFIG"
|
|
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_dump
|
|
}
|
|
|
|
# Main RPC interface
|
|
case "$1" in
|
|
list)
|
|
cat <<'EOF'
|
|
{
|
|
"status": {},
|
|
"list_sites": {},
|
|
"get_site": { "id": "string" },
|
|
"create_site": { "name": "string", "domain": "string", "gitea_repo": "string", "ssl": "boolean", "description": "string" },
|
|
"update_site": { "id": "string", "name": "string", "domain": "string", "gitea_repo": "string", "ssl": "boolean", "enabled": "boolean", "description": "string" },
|
|
"delete_site": { "id": "string" },
|
|
"sync_site": { "id": "string" },
|
|
"get_publish_info": { "id": "string" },
|
|
"upload_file": { "id": "string", "filename": "string", "content": "string" },
|
|
"list_files": { "id": "string" },
|
|
"get_settings": {},
|
|
"save_settings": { "enabled": "boolean", "nginx_container": "string", "sites_root": "string" }
|
|
}
|
|
EOF
|
|
;;
|
|
call)
|
|
case "$2" in
|
|
status) method_status ;;
|
|
list_sites) method_list_sites ;;
|
|
get_site) method_get_site ;;
|
|
create_site) method_create_site ;;
|
|
update_site) method_update_site ;;
|
|
delete_site) method_delete_site ;;
|
|
sync_site) method_sync_site ;;
|
|
get_publish_info) method_get_publish_info ;;
|
|
upload_file) method_upload_file ;;
|
|
list_files) method_list_files ;;
|
|
get_settings) method_get_settings ;;
|
|
save_settings) method_save_settings ;;
|
|
*) echo '{"error": "unknown method"}' ;;
|
|
esac
|
|
;;
|
|
esac
|