yunohost/data/helpers.d/configpanel

266 lines
8.2 KiB
Bash

#!/bin/bash
ynh_lowerdot_to_uppersnake() {
local lowerdot
lowerdot=$(echo "$1" | cut -d= -f1 | sed "s/\./_/g")
echo "${lowerdot^^}"
}
# Get a value from heterogeneous file (yaml, json, php, python...)
#
# usage: ynh_value_get --file=PATH --key=KEY
# | arg: -f, --file= - the path to the file
# | arg: -k, --key= - the key to get
#
# This helpers match several var affectation use case in several languages
# We don't use jq or equivalent to keep comments and blank space in files
# This helpers work line by line, it is not able to work correctly
# if you have several identical keys in your files
#
# Example of line this helpers can managed correctly
# .yml
# title: YunoHost documentation
# email: 'yunohost@yunohost.org'
# .json
# "theme": "colib'ris",
# "port": 8102
# "some_boolean": false,
# "user": null
# .ini
# some_boolean = On
# action = "Clear"
# port = 20
# .php
# $user=
# user => 20
# .py
# USER = 8102
# user = 'https://donate.local'
# CUSTOM['user'] = 'YunoHost'
# Requires YunoHost version 4.3 or higher.
ynh_value_get() {
# Declare an array to define the options of this helper.
local legacy_args=fk
local -A args_array=( [f]=file= [k]=key= )
local file
local key
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local var_part="[ \t]*(\$?\w*\[)?[ \t]*[\"']?${key}[\"']?[ \t]*\]?[ \t]*[:=]>?[ \t]*"
local crazy_value="$(grep -i -o -P "^${var_part}\K.*(?=[ \t,\n;]*\$)" ${file} | head -n1)"
local first_char="${crazy_value:0:1}"
if [[ "$first_char" == '"' ]] ; then
echo "$crazy_value" | grep -m1 -o -P '"\K([^"](\\")?)*[^\\](?=")' | head -n1 | sed 's/\\"/"/g'
elif [[ "$first_char" == "'" ]] ; then
echo "$crazy_value" | grep -m1 -o -P "'\K([^'](\\\\')?)*[^\\\\](?=')" | head -n1 | sed "s/\\\\'/'/g"
else
echo "$crazy_value"
fi
}
# Set a value into heterogeneous file (yaml, json, php, python...)
#
# usage: ynh_value_set --file=PATH --key=KEY --value=VALUE
# | arg: -f, --file= - the path to the file
# | arg: -k, --key= - the key to set
# | arg: -v, --value= - the value to set
#
# Requires YunoHost version 4.3 or higher.
ynh_value_set() {
# Declare an array to define the options of this helper.
local legacy_args=fkv
local -A args_array=( [f]=file= [k]=key= [v]=value=)
local file
local key
local value
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local var_part="[ \t]*(\$?\w*\[)?[ \t]*[\"']?${key}[\"']?[ \t]*\]?[ \t]*[:=]>?[ \t]*"
local crazy_value="$(grep -i -o -P "^${var_part}\K.*(?=[ \t,\n;]*\$)" ${file} | head -n1)"
local var_part="^[ \t]*(\$?\w*\[)?[ \t]*[\"']?${key}[\"']?[ \t]*\]?[ \t]*[:=]>?[ \t]*"
local first_char="${crazy_value:0:1}"
if [[ "$first_char" == '"' ]] ; then
value="$(echo "$value" | sed 's/"/\\"/g')"
sed -ri "s%^(${var_part}\")[^\"]*(\"[ \t\n,;]*)\$%\1${value}\2%i" ${file}
elif [[ "$first_char" == "'" ]] ; then
value="$(echo "$value" | sed "s/'/\\\\'/g")"
sed -ri "s%^(${var_part}')[^']*('[ \t\n,;]*)\$%\1${value}\2%i" ${file}
else
if [[ "$value" == *"'"* ]] || [[ "$value" == *'"'* ]] ; then
value="\"$(echo "$value" | sed 's/"/\\"/g')\""
fi
sed -ri "s%^(${var_part}')[^']*('[ \t\n,;]*)\$%\1${value}\2%i" ${file}
fi
}
_ynh_panel_get() {
# From settings
local params_sources
params_sources=`python3 << EOL
import toml
from collections import OrderedDict
with open("/etc/yunohost/apps/vpnclient/config_panel.toml", "r") as f:
file_content = f.read()
loaded_toml = toml.loads(file_content, _dict=OrderedDict)
for panel_name,panel in loaded_toml.items():
if isinstance(panel, dict):
for section_name, section in panel.items():
if isinstance(section, dict):
for name, param in section.items():
if isinstance(param, dict) and param.get('source', '') == 'settings':
print("%s.%s.%s=%s" %(panel_name, section_name, name, param.get('source', 'settings')))
EOL
`
for param_source in params_sources
do
local _dot_setting=$(echo "$param_source" | cut -d= -f1)
local _snake_setting="YNH_CONFIG_$(ynh_lowerdot_to_uppersnake $dot_setting)"
local short_setting=$(echo "$_dot_setting" | cut -d. -f3)
local getter="get__${short_setting}"
local source="$(echo $param_source | cut -d= -f2)"
# Get value from getter if exists
if type $getter | grep -q '^function$' 2>/dev/null; then
old[$short_setting]="$($getter)"
# Get value from app settings
elif [[ "$source" == "settings" ]] ; then
old[$short_setting]="$(ynh_app_setting_get $app $short_setting)"
# Get value from a kind of key/value file
elif [[ "$source" == *":"* ]] ; then
local source_key="$(echo "$source" | cut -d: -f1)"
source_key=${source_key:-$short_setting}
local source_file="$(echo "$source" | cut -d: -f2)"
old[$short_setting]="$(ynh_value_get --file="${source_file}" --key="${source_key}")"
# Specific case for files (all content of the file is the source)
else
old[$short_setting]="$source"
fi
done
}
_ynh_panel_apply() {
for short_setting in "${!dot_settings[@]}"
do
local setter="set__${short_setting}"
local source="$sources[$short_setting]"
# Apply setter if exists
if type $setter | grep -q '^function$' 2>/dev/null; then
$setter
# Copy file in right place
elif [[ "$source" == "settings" ]] ; then
ynh_app_setting_set $app $short_setting "$new[$short_setting]"
# Get value from a kind of key/value file
elif [[ "$source" == *":"* ]]
then
local source_key="$(echo "$source" | cut -d: -f1)"
source_key=${source_key:-$short_setting}
local source_file="$(echo "$source" | cut -d: -f2)"
ynh_value_set --file="${source_file}" --key="${source_key}" --value="$new[$short_setting]"
# Specific case for files (all content of the file is the source)
else
cp "$new[$short_setting]" "$source"
fi
done
}
_ynh_panel_show() {
for short_setting in "${!old[@]}"
do
local key="YNH_CONFIG_$(ynh_lowerdot_to_uppersnake $dot_settings[$short_setting])"
ynh_return "$key=${old[$short_setting]}"
done
}
_ynh_panel_validate() {
# Change detection
local is_error=true
#for changed_status in "${!changed[@]}"
for short_setting in "${!dot_settings[@]}"
do
#TODO file hash
file_hash[$setting]=$(sha256sum "$_source" | cut -d' ' -f1)
file_hash[$form_setting]=$(sha256sum "${!form_setting}" | cut -d' ' -f1)
if [[ "${file_hash[$setting]}" != "${file_hash[$form_setting]}" ]]
then
changed[$setting]=true
fi
if [[ "$new[$short_setting]" == "$old[$short_setting]" ]]
then
changed[$short_setting]=false
else
changed[$short_setting]=true
is_error=false
fi
done
# Run validation if something is changed
if [[ "$is_error" == "false" ]]
then
for short_setting in "${!dot_settings[@]}"
do
local result=""
if type validate__$short_setting | grep -q '^function$' 2>/dev/null; then
result="$(validate__$short_setting)"
fi
if [ -n "$result" ]
then
local key="YNH_ERROR_$(ynh_lowerdot_to_uppersnake $dot_settings[$short_setting])"
ynh_return "$key=$result"
is_error=true
fi
done
fi
if [[ "$is_error" == "true" ]]
then
ynh_die
fi
}
ynh_panel_get() {
_ynh_panel_get
}
ynh_panel_show() {
_ynh_panel_show
}
ynh_panel_validate() {
_ynh_panel_validate
}
ynh_panel_apply() {
_ynh_panel_apply
}
ynh_panel_run() {
declare -A old=()
declare -A changed=()
declare -A file_hash=()
ynh_panel_get
case $1 in
show) ynh_panel_show;;
apply) ynh_panel_validate && ynh_panel_apply;;
esac
}