From a80fe4ecbe6bf7bb7af3d3f4f46d7bb87834c154 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:28:45 +0100 Subject: [PATCH 01/20] [enh] New config panel --- config_panel.toml | 66 +++++++++++++++++++++++++++++++++++++++ scripts/config | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 config_panel.toml create mode 100644 scripts/config diff --git a/config_panel.toml b/config_panel.toml new file mode 100644 index 0000000..d1b143f --- /dev/null +++ b/config_panel.toml @@ -0,0 +1,66 @@ +version = "0.1" +name = "APP configuration panel" + +[main] +name = "Main configuration" + + [main.config_file] + name = "" + + [main.config_file.warning] + ask = "Here you can display a warning to user." + type = "warning" + + [main.config_file.outgoing_email] + ask = "Outgoing email From" + type = "string" + help = "Email from which comes email from this app" + + [main.config_file.expiration] + ask = "Default expiration" + type = "date" + + [main.config_file.logo] + ask = "Outgoing email From" + type = "file" + default = "" + optional = true + help = "You should upload a CA certificate to start" + source="__FINALPATH__/img/logo.png" + + [main.auth] + name = "Authentication" + + [main.auth.user] + ask = "Username" + type = "string" + default = "" + optional = true + pattern = "^[^/ ]+$" + + [main.auth.passphrase] + ask = "Password" + type = "password" + default = "" + optional = true + + +[advanced] +name = "Advanced configuration" + + [manual.dns] + name = "DNS" + + [manual.dns.dns0] + ask = "First resolver" + type = "string" + default = "" + optional = true + pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" + + [manual.dns.dns1] + ask = "Second resolver" + type = "string" + default = "" + optional = true + pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" diff --git a/scripts/config b/scripts/config new file mode 100644 index 0000000..4f6f300 --- /dev/null +++ b/scripts/config @@ -0,0 +1,78 @@ +#!/bin/bash + +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +app=$YNH_APP_INSTANCE_NAME +final_path=$(ynh_app_setting_get $app final_path) + +#================================================= +# SPECIFIC GETTERS FOR TOML SHORT KEY +#================================================= +get__user() { + if [ -s $final_path/keys/credentials ] + then + sed -n 1p $final_path/keys/credentials + fi +} + +get__passphrase() { + if [ -s $final_path/keys/credentials ] + then + sed -n 2p $final_path/keys/credentials + fi +} + + +#================================================= +# SPECIFIC VALIDATORS FOR TOML SHORT KEYS +#================================================= +validate__user() { + [[ -n "$passphrase" && -z "$user" ]] && + echo 'A Username is needed when you suggest a Password' +} + +validate__passphrase() { + [[ -n "$user" && -z "$passphrase" ]] && + echo 'A Password is needed when you suggest a Username' +} + +#================================================= +# SPECIFIC SETTERS FOR TOML SHORT KEYS +#================================================= +set__user() { + if [ -z "$user" ] + then + echo "$user\n$passphrase" > $final_path/keys/credentials + else + echo "" > $final_path/keys/credentials + fi +} + +set__passphrase() { + : +} + + +#================================================= +# OVERWRITING APPLY STEP +#================================================= +ynh_panel_apply() { + + _ynh_panel_apply + + # Start vpn client + systemctl reload APP + +} + From 3051124936f3d74048746c60f130a7840f490844 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:38:15 +0100 Subject: [PATCH 02/20] [enh] New config panel --- config_panel.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/config_panel.toml b/config_panel.toml index d1b143f..406b842 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -11,14 +11,18 @@ name = "Main configuration" ask = "Here you can display a warning to user." type = "warning" - [main.config_file.outgoing_email] + [main.config_file.from_email] ask = "Outgoing email From" type = "string" help = "Email from which comes email from this app" + pattern = "^[^@]+@[^@]+$" + source = "__FINALPATH__/conf/config.php" [main.config_file.expiration] ask = "Default expiration" type = "date" + pattern = "^\d\d\d\d-\d\d-\d\d$" + source = "__FINALPATH__/conf/config.php" [main.config_file.logo] ask = "Outgoing email From" @@ -48,7 +52,7 @@ name = "Main configuration" [advanced] name = "Advanced configuration" - [manual.dns] + [advanced.dns] name = "DNS" [manual.dns.dns0] From 6718f6403eed13e2321d2fc50ecf399c707df239 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:40:15 +0100 Subject: [PATCH 03/20] [enh] Remove uneeded title --- config_panel.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/config_panel.toml b/config_panel.toml index 406b842..03f9cf4 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -1,5 +1,4 @@ version = "0.1" -name = "APP configuration panel" [main] name = "Main configuration" From 0864c8b525c596f5beb104a2ac6581549739d28d Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:42:27 +0100 Subject: [PATCH 04/20] [enh] Upgrade version config panel --- config_panel.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_panel.toml b/config_panel.toml index 03f9cf4..b459c71 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -1,4 +1,4 @@ -version = "0.1" +version = "1.0" [main] name = "Main configuration" From 1dc8e862a6390c812556cfd65d43f277aee39706 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:48:58 +0100 Subject: [PATCH 05/20] [enh] Some doc about config panel --- scripts/config | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/scripts/config b/scripts/config index 4f6f300..bc1e6c6 100644 --- a/scripts/config +++ b/scripts/config @@ -1,20 +1,16 @@ #!/bin/bash -#================================================= -# GENERIC STARTING -#================================================= -# IMPORT GENERIC HELPERS -#================================================= +# In most simple cases, you don't need a config script (or just to reload services). + +# With a simple config_panel.toml, you can write in the app settings, in the +# upstream config file or replace complete files (logo ...). + +# The config scripts allows you to go further, to handle specific cases +# (validation of several interdependent fields, specific getter/setter for a value, +# pre-loading of config type .cube ). -source _common.sh -source /usr/share/yunohost/helpers -#================================================= -# RETRIEVE ARGUMENTS -#================================================= -app=$YNH_APP_INSTANCE_NAME -final_path=$(ynh_app_setting_get $app final_path) #================================================= # SPECIFIC GETTERS FOR TOML SHORT KEY @@ -71,7 +67,7 @@ ynh_panel_apply() { _ynh_panel_apply - # Start vpn client + # Reload app service systemctl reload APP } From 6431e1eaff5bf4290b7ce47f14afe597d509884f Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Tue, 1 Jun 2021 01:26:50 +0200 Subject: [PATCH 06/20] [enh] Update config panel example --- config_panel.toml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/config_panel.toml b/config_panel.toml index b459c71..1a0a23c 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -12,21 +12,21 @@ name = "Main configuration" [main.config_file.from_email] ask = "Outgoing email From" - type = "string" + type = "email" help = "Email from which comes email from this app" pattern = "^[^@]+@[^@]+$" - source = "__FINALPATH__/conf/config.php" + source = "email:__FINALPATH__/conf/config.php" [main.config_file.expiration] ask = "Default expiration" type = "date" pattern = "^\d\d\d\d-\d\d-\d\d$" - source = "__FINALPATH__/conf/config.php" + source = ":__FINALPATH__/conf/config.php" [main.config_file.logo] - ask = "Outgoing email From" + ask = "Logo" type = "file" - default = "" + accept = ".png" optional = true help = "You should upload a CA certificate to start" source="__FINALPATH__/img/logo.png" @@ -37,19 +37,20 @@ name = "Main configuration" [main.auth.user] ask = "Username" type = "string" - default = "" + example = "camille" optional = true pattern = "^[^/ ]+$" [main.auth.passphrase] ask = "Password" type = "password" - default = "" optional = true + visibleIf = "user" [advanced] name = "Advanced configuration" +collapsed = true [advanced.dns] name = "DNS" @@ -57,13 +58,11 @@ name = "Advanced configuration" [manual.dns.dns0] ask = "First resolver" type = "string" - default = "" optional = true pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" [manual.dns.dns1] ask = "Second resolver" type = "string" - default = "" optional = true pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" From 471d9abf2b054fcf73e299988c28a65d56f34c88 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:28:45 +0100 Subject: [PATCH 07/20] [enh] New config panel --- config_panel.toml | 66 +++++++++++++++++++++++++++++++++++++++ scripts/config | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 config_panel.toml create mode 100644 scripts/config diff --git a/config_panel.toml b/config_panel.toml new file mode 100644 index 0000000..d1b143f --- /dev/null +++ b/config_panel.toml @@ -0,0 +1,66 @@ +version = "0.1" +name = "APP configuration panel" + +[main] +name = "Main configuration" + + [main.config_file] + name = "" + + [main.config_file.warning] + ask = "Here you can display a warning to user." + type = "warning" + + [main.config_file.outgoing_email] + ask = "Outgoing email From" + type = "string" + help = "Email from which comes email from this app" + + [main.config_file.expiration] + ask = "Default expiration" + type = "date" + + [main.config_file.logo] + ask = "Outgoing email From" + type = "file" + default = "" + optional = true + help = "You should upload a CA certificate to start" + source="__FINALPATH__/img/logo.png" + + [main.auth] + name = "Authentication" + + [main.auth.user] + ask = "Username" + type = "string" + default = "" + optional = true + pattern = "^[^/ ]+$" + + [main.auth.passphrase] + ask = "Password" + type = "password" + default = "" + optional = true + + +[advanced] +name = "Advanced configuration" + + [manual.dns] + name = "DNS" + + [manual.dns.dns0] + ask = "First resolver" + type = "string" + default = "" + optional = true + pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" + + [manual.dns.dns1] + ask = "Second resolver" + type = "string" + default = "" + optional = true + pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" diff --git a/scripts/config b/scripts/config new file mode 100644 index 0000000..4f6f300 --- /dev/null +++ b/scripts/config @@ -0,0 +1,78 @@ +#!/bin/bash + +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +app=$YNH_APP_INSTANCE_NAME +final_path=$(ynh_app_setting_get $app final_path) + +#================================================= +# SPECIFIC GETTERS FOR TOML SHORT KEY +#================================================= +get__user() { + if [ -s $final_path/keys/credentials ] + then + sed -n 1p $final_path/keys/credentials + fi +} + +get__passphrase() { + if [ -s $final_path/keys/credentials ] + then + sed -n 2p $final_path/keys/credentials + fi +} + + +#================================================= +# SPECIFIC VALIDATORS FOR TOML SHORT KEYS +#================================================= +validate__user() { + [[ -n "$passphrase" && -z "$user" ]] && + echo 'A Username is needed when you suggest a Password' +} + +validate__passphrase() { + [[ -n "$user" && -z "$passphrase" ]] && + echo 'A Password is needed when you suggest a Username' +} + +#================================================= +# SPECIFIC SETTERS FOR TOML SHORT KEYS +#================================================= +set__user() { + if [ -z "$user" ] + then + echo "$user\n$passphrase" > $final_path/keys/credentials + else + echo "" > $final_path/keys/credentials + fi +} + +set__passphrase() { + : +} + + +#================================================= +# OVERWRITING APPLY STEP +#================================================= +ynh_panel_apply() { + + _ynh_panel_apply + + # Start vpn client + systemctl reload APP + +} + From 17fe3b1f26acde0592a10524522117db873d4d21 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:38:15 +0100 Subject: [PATCH 08/20] [enh] New config panel --- config_panel.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/config_panel.toml b/config_panel.toml index d1b143f..406b842 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -11,14 +11,18 @@ name = "Main configuration" ask = "Here you can display a warning to user." type = "warning" - [main.config_file.outgoing_email] + [main.config_file.from_email] ask = "Outgoing email From" type = "string" help = "Email from which comes email from this app" + pattern = "^[^@]+@[^@]+$" + source = "__FINALPATH__/conf/config.php" [main.config_file.expiration] ask = "Default expiration" type = "date" + pattern = "^\d\d\d\d-\d\d-\d\d$" + source = "__FINALPATH__/conf/config.php" [main.config_file.logo] ask = "Outgoing email From" @@ -48,7 +52,7 @@ name = "Main configuration" [advanced] name = "Advanced configuration" - [manual.dns] + [advanced.dns] name = "DNS" [manual.dns.dns0] From 5017bf8e0d777aed876cf7d577a5b2c7b5399fb7 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:40:15 +0100 Subject: [PATCH 09/20] [enh] Remove uneeded title --- config_panel.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/config_panel.toml b/config_panel.toml index 406b842..03f9cf4 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -1,5 +1,4 @@ version = "0.1" -name = "APP configuration panel" [main] name = "Main configuration" From 47d426be05492aa09e5d14eac47beb1b502ec93d Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:42:27 +0100 Subject: [PATCH 10/20] [enh] Upgrade version config panel --- config_panel.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_panel.toml b/config_panel.toml index 03f9cf4..b459c71 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -1,4 +1,4 @@ -version = "0.1" +version = "1.0" [main] name = "Main configuration" From 01d79fbaeebce398a400c9220a451cb6912ddfe3 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 3 Nov 2020 21:48:58 +0100 Subject: [PATCH 11/20] [enh] Some doc about config panel --- scripts/config | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/scripts/config b/scripts/config index 4f6f300..bc1e6c6 100644 --- a/scripts/config +++ b/scripts/config @@ -1,20 +1,16 @@ #!/bin/bash -#================================================= -# GENERIC STARTING -#================================================= -# IMPORT GENERIC HELPERS -#================================================= +# In most simple cases, you don't need a config script (or just to reload services). + +# With a simple config_panel.toml, you can write in the app settings, in the +# upstream config file or replace complete files (logo ...). + +# The config scripts allows you to go further, to handle specific cases +# (validation of several interdependent fields, specific getter/setter for a value, +# pre-loading of config type .cube ). -source _common.sh -source /usr/share/yunohost/helpers -#================================================= -# RETRIEVE ARGUMENTS -#================================================= -app=$YNH_APP_INSTANCE_NAME -final_path=$(ynh_app_setting_get $app final_path) #================================================= # SPECIFIC GETTERS FOR TOML SHORT KEY @@ -71,7 +67,7 @@ ynh_panel_apply() { _ynh_panel_apply - # Start vpn client + # Reload app service systemctl reload APP } From a58978c4e52fc08a34db6d8206d7362df0aed653 Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Tue, 1 Jun 2021 01:26:50 +0200 Subject: [PATCH 12/20] [enh] Update config panel example --- config_panel.toml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/config_panel.toml b/config_panel.toml index b459c71..1a0a23c 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -12,21 +12,21 @@ name = "Main configuration" [main.config_file.from_email] ask = "Outgoing email From" - type = "string" + type = "email" help = "Email from which comes email from this app" pattern = "^[^@]+@[^@]+$" - source = "__FINALPATH__/conf/config.php" + source = "email:__FINALPATH__/conf/config.php" [main.config_file.expiration] ask = "Default expiration" type = "date" pattern = "^\d\d\d\d-\d\d-\d\d$" - source = "__FINALPATH__/conf/config.php" + source = ":__FINALPATH__/conf/config.php" [main.config_file.logo] - ask = "Outgoing email From" + ask = "Logo" type = "file" - default = "" + accept = ".png" optional = true help = "You should upload a CA certificate to start" source="__FINALPATH__/img/logo.png" @@ -37,19 +37,20 @@ name = "Main configuration" [main.auth.user] ask = "Username" type = "string" - default = "" + example = "camille" optional = true pattern = "^[^/ ]+$" [main.auth.passphrase] ask = "Password" type = "password" - default = "" optional = true + visibleIf = "user" [advanced] name = "Advanced configuration" +collapsed = true [advanced.dns] name = "DNS" @@ -57,13 +58,11 @@ name = "Advanced configuration" [manual.dns.dns0] ask = "First resolver" type = "string" - default = "" optional = true pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" [manual.dns.dns1] ask = "Second resolver" type = "string" - default = "" optional = true pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" From 62c97c223b563008b89671322f9cf3dcc73b9b84 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 28 Sep 2021 17:06:01 +0200 Subject: [PATCH 13/20] [enh] Rename to avoid bad config panel in real apps --- config_panel.toml | 68 ----------------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 config_panel.toml diff --git a/config_panel.toml b/config_panel.toml deleted file mode 100644 index 1a0a23c..0000000 --- a/config_panel.toml +++ /dev/null @@ -1,68 +0,0 @@ -version = "1.0" - -[main] -name = "Main configuration" - - [main.config_file] - name = "" - - [main.config_file.warning] - ask = "Here you can display a warning to user." - type = "warning" - - [main.config_file.from_email] - ask = "Outgoing email From" - type = "email" - help = "Email from which comes email from this app" - pattern = "^[^@]+@[^@]+$" - source = "email:__FINALPATH__/conf/config.php" - - [main.config_file.expiration] - ask = "Default expiration" - type = "date" - pattern = "^\d\d\d\d-\d\d-\d\d$" - source = ":__FINALPATH__/conf/config.php" - - [main.config_file.logo] - ask = "Logo" - type = "file" - accept = ".png" - optional = true - help = "You should upload a CA certificate to start" - source="__FINALPATH__/img/logo.png" - - [main.auth] - name = "Authentication" - - [main.auth.user] - ask = "Username" - type = "string" - example = "camille" - optional = true - pattern = "^[^/ ]+$" - - [main.auth.passphrase] - ask = "Password" - type = "password" - optional = true - visibleIf = "user" - - -[advanced] -name = "Advanced configuration" -collapsed = true - - [advanced.dns] - name = "DNS" - - [manual.dns.dns0] - ask = "First resolver" - type = "string" - optional = true - pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" - - [manual.dns.dns1] - ask = "Second resolver" - type = "string" - optional = true - pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" From 1a1a2c49898ae85404ec03c09839af2f29921b85 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 28 Sep 2021 17:07:02 +0200 Subject: [PATCH 14/20] [enh] Rename to avoid bad config panel in real apps --- config_panel.toml.example | 68 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 config_panel.toml.example diff --git a/config_panel.toml.example b/config_panel.toml.example new file mode 100644 index 0000000..1a0a23c --- /dev/null +++ b/config_panel.toml.example @@ -0,0 +1,68 @@ +version = "1.0" + +[main] +name = "Main configuration" + + [main.config_file] + name = "" + + [main.config_file.warning] + ask = "Here you can display a warning to user." + type = "warning" + + [main.config_file.from_email] + ask = "Outgoing email From" + type = "email" + help = "Email from which comes email from this app" + pattern = "^[^@]+@[^@]+$" + source = "email:__FINALPATH__/conf/config.php" + + [main.config_file.expiration] + ask = "Default expiration" + type = "date" + pattern = "^\d\d\d\d-\d\d-\d\d$" + source = ":__FINALPATH__/conf/config.php" + + [main.config_file.logo] + ask = "Logo" + type = "file" + accept = ".png" + optional = true + help = "You should upload a CA certificate to start" + source="__FINALPATH__/img/logo.png" + + [main.auth] + name = "Authentication" + + [main.auth.user] + ask = "Username" + type = "string" + example = "camille" + optional = true + pattern = "^[^/ ]+$" + + [main.auth.passphrase] + ask = "Password" + type = "password" + optional = true + visibleIf = "user" + + +[advanced] +name = "Advanced configuration" +collapsed = true + + [advanced.dns] + name = "DNS" + + [manual.dns.dns0] + ask = "First resolver" + type = "string" + optional = true + pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" + + [manual.dns.dns1] + ask = "Second resolver" + type = "string" + optional = true + pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" From 8afe35a53a03615e4ce89b62300f7441db6dcf1e Mon Sep 17 00:00:00 2001 From: ljf Date: Wed, 29 Sep 2021 01:51:43 +0200 Subject: [PATCH 15/20] [enh] Add config panel doc --- config_panel.toml.example | 300 ++++++++++++++++++++++++++++++++------ 1 file changed, 252 insertions(+), 48 deletions(-) diff --git a/config_panel.toml.example b/config_panel.toml.example index 1a0a23c..81dfeac 100644 --- a/config_panel.toml.example +++ b/config_panel.toml.example @@ -1,27 +1,236 @@ + +## Config panel are available from webadmin > Apps > YOUR_APP > Config Panel Button +## Those panels let user configure some params on there apps to avoid them to change +## its by hand in configuration file and be abliged to reapply their changes at each +## app upgrade. + +## ----------------------------------------------------------------------------- +## IMPORTANT: YunoHost spirits is simplicity, please don't expose here tons of +## misunderstanble app settings or not really useful feature. +## ----------------------------------------------------------------------------- + +## The top level describe the entire config panels screen. + +## The version is a required property. +## Here a small reminder to associate config panel version with YunoHost version +## | Config | YNH | Config panel small change log | +## | ------ | --- | ------------------------------------------------------- | +## | 0.1 | 3.x | 0.1 config script not compatible with YNH >= 4.3 | +## | 1.0 | 4.3.x | The new config panel system with 'bind' property | version = "1.0" +## (optional) i18n property let you internationalize questions, however this feature +## is only available in core configuration panel (like yunohost domain config). +## So in app config panel this key is ignored for now, but you can internationalize +## by using a lang dictionary (see property name bellow) +# i18n = "prefix_translation_key" + +################################################################################ +#### ABOUT PANELS +################################################################################ + +## The next level describes web admin panels +## You have to choose an ID for each panel, in this example the ID is "main" +## Keep in mind this id will be used in cli to refer to your question, so choose +## something short and meaningfull. +## Note: each panel is a distinct HTML form. [main] + +## (recommended) You should define the label of your panel (and associated tab) +## If you don't define it, the ID will be used as title name = "Main configuration" - [main.config_file] +## To internationalize the name, and other textual properties you can suggest +## translation like this: +# name.en = "Main configuration" +# name.fr = "Configuration principale" + +## (optional) If you need to trigger a service reload-or-restart after the user +## change a question in this panel, you can add your service in the list. +services = ["nginx", "__APP__"] + +## (optional) This help properties is a short help displayed on the same line +## than the panel title but not displayed in the tab. +# help = "" + + ############################################################################ + #### ABOUT SECTIONS + ############################################################################ + + ## A panel is compound of one or several sections. + ## You have to choose an ID for your section and prefix it with the panel ID + ## Be sure to not make a typo in panel prefix, or you will get an unwanted + ## panel in more. + ## For this example we imagine, we package the pepettes_ynh app. + ## It's a really simple donation form without administration panel, so we + ## want to expose some settings + [main.customization] + + ## (optional) A section could have a title, or not. It depends of what you + ## are doing exactly. In web admin it will display an

title. name = "" + + ## (optional) This help properties is a short help displayed on the same line + ## than the section title. + # help = "" + + ## (optional) As for panel, you can specify to trigger a service + ## reload-or-restart after the user change a question in this section. + ## This property is added to the panel property, it doesn't deactivate it. + ## So no need to replicate, the service list from panel services property. + # services = [] + + ## (optional) By default all questions are optionals, but you can specify a + ## default behaviour for question in the section + # optional = true - [main.config_file.warning] - ask = "Here you can display a warning to user." - type = "warning" + ## (optional) It's also possible with the 'visible' property to display the + ## question only if the user answer the form in a specific way. + ## However, you should not refer to questions after the point where you put + ## the visible property. SO the first section should never have a visible + ## property + ## In more this feature is available in webadmin but not in cli, so keep in + ## mind cli user could be prompted for the question... + # visible = true + + ######################################################################## + #### ABOUT QUESTIONS + ######################################################################## + + ## A section is compound of one or several questions. + + ## --------------------------------------------------------------------- + ## IMPORTANT: as for panel and section you have to choose an ID, but this + ## one should be unique in all this document, even if the question is in + ## an other panel. + ## --------------------------------------------------------------------- - [main.config_file.from_email] - ask = "Outgoing email From" - type = "email" - help = "Email from which comes email from this app" - pattern = "^[^@]+@[^@]+$" - source = "email:__FINALPATH__/conf/config.php" + ## You can use same questions types and properties than in manifest.yml + ## install part. However, in YNH 4.3, a lot of change has been made to + ## extend availables questions types list. + ## See: TODO DOC LINK - [main.config_file.expiration] - ask = "Default expiration" - type = "date" - pattern = "^\d\d\d\d-\d\d-\d\d$" - source = ":__FINALPATH__/conf/config.php" + [main.customization.project_name] + + ## (required) The ask property is equivalent to the ask property in + ## manifest.yml. However, in config panel questions are displayed on the + ## left. So, it's more a label than a complete question, make short. + ask = "Name of the project" + + ## (required) The type property indicates how the question should be + ## displayed, validated and managed. Some types have specific properties. + ## + ## Types available: string, boolean, number, range, text, password, path + ## email, url, date, time, color, select, domain, user, tags, file. + ## + ## For a complete list with specific properties, see: TODO DOC LINK + type = "string" + + ######################################################################## + #### ABOUT THE BIND PROPERTY + ######################################################################## + + ## (recommended) 'bind' property is a powerful feature that let you + ## configure how the data will be read, validated and write. + + ## By default, 'bind property is in "settings" mode, it means it will + ## read / write the value in application settings file. + ## bind = "settings" + + ## But in general, you prefer use the ":FILE" mode to read/write a + ## specific variable in a file. + + ## Configuration file format supported: yaml, toml, json, ini, env, php, + ## python. The feature probably works with others formats, but you need + ## to test it carefully. + + ## Unsupported: XML format, custom config function call, php define(), + ## array/list on several lines. + + ## More info on TODO + # bind = ":/var/www/__APP__/settings.py" + + ## NOTE: in pepettes, the python variable is called 'name' and not + ## 'project_name', wo here we need to specify the variable name by hand + ## before columns + ## Here pepettes config file to understand: https://github.com/YunoHost-Apps/pepettes_ynh/blob/5cc2d3ffd6529cc7356ff93af92dbb6785c3ab9a/conf/settings.py##L11 + + bind = "name:/var/www/__APP__/settings.py" + + ## --------------------------------------------------------------------- + ## IMPORTANT: other 'bind' mode exists: + ## + ## The null mode, to explicitly disable default read / write in settings. + # bind = "null" + ## + ## Without columns before the path it means all the file will be replaced + ## by the value (reserved for file and multiline text question): + # bind = "/var/www/__APP__/img/logo.png" + ## + ## Finally, if you define a custom getter, setter or validator in config + ## script it will use it instead of apply default bind behaviour. + ## getter: get__PROPERTY() + ## setter: set__PROPERTY() + ## validator: validate__PROPERTY() + ## You can also specify a common getter / setter / validator, with the + ## function 'bind' mode, for example here it will try to run + ## get__array_settings() first. + # bind = "array_settings()" + ## --------------------------------------------------------------------- + + ## --------------------------------------------------------------------- + ## IMPORTANT: during install/upgrade you should save a first value in + ## the source of the bind key and in app settings. + ## During upgrade you should reset values in template files based on + ## value saved in app settings. + ## --------------------------------------------------------------------- + + ######################################################################## + #### OTHER GENERIC PROPERTY FOR QUESTIONS + ######################################################################## + + ## (optional) An help text for the question + help = "Fill the name of the project which will received donation" + + ## (optional) An example display as placeholder in web form + # example = "YunoHost" + + ## (optional) set to true in order to redact the value in operation logs + # redact = false + + ## (optional) A validation pattern + ## --------------------------------------------------------------------- + ## IMPORTANT: your pattern should be between simple quote, not double. + ## --------------------------------------------------------------------- + pattern.regexp = '^\w{3,30}$' + pattern.error = "The name should be at least 3 chars and less than 30 chars. Alphanumeric chars are accepted" + + ## Note: visible and optional properties are also available for questions + + + [main.customization.contact_url] + ask = "Contact url" + type = "url" + example = "mailto: contact@example.org" + help = "mailto: accepted" + pattern.regexp = "^mailto:[^@]+@[^@]+|https://$" + pattern.error = "Should be https or mailto:" + bind = ":/var/www/__APP__/settings.py" + + [main.customization.logo] + ask = "Logo" + type = "file" + accept = ".png" + help = "Fill with an already resized logo" + source="__FINALPATH__/img/logo.png" + + [main.customization.favicon] + ask = "Favicon" + type = "file" + accept = ".png" + help = "Fill with an already sized favicon" + source="__FINALPATH__/img/favicon.png" + [main.config_file.logo] ask = "Logo" @@ -29,40 +238,35 @@ name = "Main configuration" accept = ".png" optional = true help = "You should upload a CA certificate to start" - source="__FINALPATH__/img/logo.png" - [main.auth] - name = "Authentication" - - [main.auth.user] - ask = "Username" + [main.stripe] + name = "Stripe general info" + + [main.stripe.publishable_key] + ask = "Publishable key" type = "string" - example = "camille" - optional = true - pattern = "^[^/ ]+$" - - [main.auth.passphrase] - ask = "Password" - type = "password" - optional = true - visibleIf = "user" + redact = true + help = "Indicate here the stripe publishable key" + bind = ":/var/www/__APP__/settings.py" - -[advanced] -name = "Advanced configuration" -collapsed = true - - [advanced.dns] - name = "DNS" - - [manual.dns.dns0] - ask = "First resolver" + [main.stripe.secret_key] + ask = "Secret key" type = "string" - optional = true - pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" - - [manual.dns.dns1] - ask = "Second resolver" - type = "string" - optional = true - pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" + redact = true + help = "Indicate here the stripe secret key" + bind = ":/var/www/__APP__/settings.py" + + [main.stripe.prices] + ask = "Prices ID" + type = "tags" + help = """\ + Indicates here the prices ID of donation products you created in stripe interfaces. \ + Go on [Stripe products](https://dashboard.stripe.com/products) to create those donation products. \ + Fill it tag with 'FREQUENCY/CURRENCY/PRICE_ID' \ + FREQUENCY: 'one_time' or 'recuring' \ + CURRENCY: 'EUR' or 'USD' \ + PRICE_ID: ID from stripe interfaces starting with 'price_' \ + """ + pattern.regexp = '^(one_time|recuring)/(EUR|USD)/price_.*$' + pattern.error = "Please respect the format describe in help text for each price ID" + bind = ":/var/www/__APP__/settings.py" From 8e21cb4df3986e6266bdfbf00b3e596b849627b4 Mon Sep 17 00:00:00 2001 From: ljf Date: Wed, 29 Sep 2021 02:41:30 +0200 Subject: [PATCH 16/20] [enh] A small config script --- scripts/config | 104 +++++++++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 38 deletions(-) diff --git a/scripts/config b/scripts/config index bc1e6c6..b9e79f8 100644 --- a/scripts/config +++ b/scripts/config @@ -1,31 +1,64 @@ #!/bin/bash - -# In most simple cases, you don't need a config script (or just to reload services). +# In simple cases, you don't need a config script. # With a simple config_panel.toml, you can write in the app settings, in the -# upstream config file or replace complete files (logo ...). +# upstream config file or replace complete files (logo ...) and restart services. # The config scripts allows you to go further, to handle specific cases # (validation of several interdependent fields, specific getter/setter for a value, -# pre-loading of config type .cube ). +# display dynamic informations or choices, pre-loading of config type .cube... ). +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= +source /usr/share/yunohost/helpers +ynh_abort_if_errors + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +final_path=$(ynh_app_setting_get $app final_path) #================================================= # SPECIFIC GETTERS FOR TOML SHORT KEY #================================================= -get__user() { - if [ -s $final_path/keys/credentials ] + +get__amount() { + # Here we can imagine to have an API call to stripe to know the amount of donation during a month + local amount = 200 + + # It's possible to change some properties of the question by overriding it: + if [ $amount -gt 100 ] then - sed -n 1p $final_path/keys/credentials + cat << EOF +style: success +value: $amount +ask: + en: A lot of donation this month: **$amount €** +EOF + else + cat << EOF +style: danger +value: $amount +ask: + en: Not so much donation this month: $amount € +EOF fi } -get__passphrase() { - if [ -s $final_path/keys/credentials ] +get__prices() { + local prices = "$(grep "DONATION\['" "$final_path/settings.py" | sed -r "s@^DONATION\['([^']*)'\]\['([^']*)'\] = '([^']*)'@\1/\2/\3@g" | sed -z 's/\n/,/g;s/,$/\n/')" + if [ "$prices" == "," ]; then - sed -n 2p $final_path/keys/credentials + # Return YNH_NULL if you prefer to not return a value at all. + echo YNH_NULL + else + echo $prices fi } @@ -33,42 +66,37 @@ get__passphrase() { #================================================= # SPECIFIC VALIDATORS FOR TOML SHORT KEYS #================================================= -validate__user() { - [[ -n "$passphrase" && -z "$user" ]] && - echo 'A Username is needed when you suggest a Password' -} +validate__publishable_key() { -validate__passphrase() { - [[ -n "$user" && -z "$passphrase" ]] && - echo 'A Password is needed when you suggest a Username' + # We can imagine here we test if the key is really a publisheable key + (is_secret_key $publishable_key) && + echo 'This key seems to be a secret key' } #================================================= # SPECIFIC SETTERS FOR TOML SHORT KEYS #================================================= -set__user() { - if [ -z "$user" ] - then - echo "$user\n$passphrase" > $final_path/keys/credentials - else - echo "" > $final_path/keys/credentials - fi -} +set__prices() { -set__passphrase() { - : -} + #--------------------------------------------- + # IMPORTANT: setter are trigger only if a change is detected + #--------------------------------------------- + for price in $(echo $prices | sed "s/,/ /"); do + frequency=$(echo $price | cut -d/ -f1) + currency=$(echo $price | cut -d/ -f2) + price_id=$(echo $price | cut -d/ -f3) + sed "d/DONATION\['$frequency'\]\['$currency'\]" "$final_path/settings.py" - -#================================================= -# OVERWRITING APPLY STEP -#================================================= -ynh_panel_apply() { + echo "DONATION['$frequency']['$currency'] = '$price_id'" >> "$final_path/settings.py" + done - _ynh_panel_apply - - # Reload app service - systemctl reload APP - + #--------------------------------------------- + # IMPORTANT: to be able to upgrade properly, you have to saved the value in settings too + #--------------------------------------------- + ynh_app_setting_set $app prices $prices } +#================================================= +# GENERIC FINALIZATION +#================================================= +ynh_app_config_run $1 From b89af4b7b0509b4dd5464651f9fc8f0a00cf46f6 Mon Sep 17 00:00:00 2001 From: ljf Date: Wed, 29 Sep 2021 02:42:19 +0200 Subject: [PATCH 17/20] [fix] bind key not needed --- config_panel.toml.example | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/config_panel.toml.example b/config_panel.toml.example index 81dfeac..588a3ef 100644 --- a/config_panel.toml.example +++ b/config_panel.toml.example @@ -82,7 +82,7 @@ services = ["nginx", "__APP__"] ## (optional) By default all questions are optionals, but you can specify a ## default behaviour for question in the section - # optional = true + optional = false ## (optional) It's also possible with the 'visible' property to display the ## question only if the user answer the form in a specific way. @@ -232,15 +232,15 @@ services = ["nginx", "__APP__"] source="__FINALPATH__/img/favicon.png" - [main.config_file.logo] - ask = "Logo" - type = "file" - accept = ".png" - optional = true - help = "You should upload a CA certificate to start" - [main.stripe] name = "Stripe general info" + optional = false + + # The next alert is overwrited with a getter from the config script + [main.stripe.amount] + ask = "Donation in the month : XX € + type = "alert" + style = "success" [main.stripe.publishable_key] ask = "Publishable key" @@ -269,4 +269,3 @@ services = ["nginx", "__APP__"] """ pattern.regexp = '^(one_time|recuring)/(EUR|USD)/price_.*$' pattern.error = "Please respect the format describe in help text for each price ID" - bind = ":/var/www/__APP__/settings.py" From 12eb08b590f76fdc8f9a6a9edde8c8c24c4df99e Mon Sep 17 00:00:00 2001 From: ljf Date: Wed, 29 Sep 2021 02:45:44 +0200 Subject: [PATCH 18/20] [fix] Remove not wanted panel --- config_panel.toml | 68 ----------------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 config_panel.toml diff --git a/config_panel.toml b/config_panel.toml deleted file mode 100644 index 1a0a23c..0000000 --- a/config_panel.toml +++ /dev/null @@ -1,68 +0,0 @@ -version = "1.0" - -[main] -name = "Main configuration" - - [main.config_file] - name = "" - - [main.config_file.warning] - ask = "Here you can display a warning to user." - type = "warning" - - [main.config_file.from_email] - ask = "Outgoing email From" - type = "email" - help = "Email from which comes email from this app" - pattern = "^[^@]+@[^@]+$" - source = "email:__FINALPATH__/conf/config.php" - - [main.config_file.expiration] - ask = "Default expiration" - type = "date" - pattern = "^\d\d\d\d-\d\d-\d\d$" - source = ":__FINALPATH__/conf/config.php" - - [main.config_file.logo] - ask = "Logo" - type = "file" - accept = ".png" - optional = true - help = "You should upload a CA certificate to start" - source="__FINALPATH__/img/logo.png" - - [main.auth] - name = "Authentication" - - [main.auth.user] - ask = "Username" - type = "string" - example = "camille" - optional = true - pattern = "^[^/ ]+$" - - [main.auth.passphrase] - ask = "Password" - type = "password" - optional = true - visibleIf = "user" - - -[advanced] -name = "Advanced configuration" -collapsed = true - - [advanced.dns] - name = "DNS" - - [manual.dns.dns0] - ask = "First resolver" - type = "string" - optional = true - pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" - - [manual.dns.dns1] - ask = "Second resolver" - type = "string" - optional = true - pattern = "^([0-9.]{8,16}|[0-9a-fA-F:]+)$" From 2c2ebd5ec15c317c0702f789927681e2146e8549 Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Thu, 30 Sep 2021 19:11:39 +0200 Subject: [PATCH 19/20] [enh] Apply suggestions from code review Co-authored-by: Alexandre Aubin --- config_panel.toml.example | 150 ++++++++++++++++++++++---------------- 1 file changed, 87 insertions(+), 63 deletions(-) diff --git a/config_panel.toml.example b/config_panel.toml.example index 588a3ef..ea8fefc 100644 --- a/config_panel.toml.example +++ b/config_panel.toml.example @@ -1,12 +1,16 @@ ## Config panel are available from webadmin > Apps > YOUR_APP > Config Panel Button -## Those panels let user configure some params on there apps to avoid them to change -## its by hand in configuration file and be abliged to reapply their changes at each -## app upgrade. +## Those panels let user configure some params on their apps using a friendly interface, +## and remove the need to manually edit files from the command line. + +## From a packager perspective, this .toml is coupled to the scripts/config script, +## which may be used to define custom getters/setters. However, most use cases +## should be covered automagically by the core, thus it may not be necessary +## to define a scripts/config at all! ## ----------------------------------------------------------------------------- -## IMPORTANT: YunoHost spirits is simplicity, please don't expose here tons of -## misunderstanble app settings or not really useful feature. +## IMPORTANT: In accordance with YunoHost's spirit, please keep things simple and +## do not overwhelm the admin with tons of misunderstandable or advanced settings. ## ----------------------------------------------------------------------------- ## The top level describe the entire config panels screen. @@ -33,21 +37,18 @@ version = "1.0" ## You have to choose an ID for each panel, in this example the ID is "main" ## Keep in mind this id will be used in cli to refer to your question, so choose ## something short and meaningfull. -## Note: each panel is a distinct HTML form. +## In the webadmin, each panel corresponds to a distinct tab / form [main] -## (recommended) You should define the label of your panel (and associated tab) -## If you don't define it, the ID will be used as title -name = "Main configuration" - -## To internationalize the name, and other textual properties you can suggest -## translation like this: +## Define the label for your panel +## Internationalization works similarly to the 'description' and 'ask' questions in the manifest # name.en = "Main configuration" # name.fr = "Configuration principale" ## (optional) If you need to trigger a service reload-or-restart after the user ## change a question in this panel, you can add your service in the list. -services = ["nginx", "__APP__"] +services = ["__APP__"] +# or services = ["nginx", "__APP__"] to also reload-or-restart nginx ## (optional) This help properties is a short help displayed on the same line ## than the panel title but not displayed in the tab. @@ -57,21 +58,27 @@ services = ["nginx", "__APP__"] #### ABOUT SECTIONS ############################################################################ - ## A panel is compound of one or several sections. - ## You have to choose an ID for your section and prefix it with the panel ID - ## Be sure to not make a typo in panel prefix, or you will get an unwanted - ## panel in more. - ## For this example we imagine, we package the pepettes_ynh app. - ## It's a really simple donation form without administration panel, so we - ## want to expose some settings + ## A panel is composed of one or several sections. + ## + ## Sections are meant to group questions together when they correspond to + ## a same subtopic. This impacts the rendering in terms of CLI prompts + ## and HTML forms + ## + ## You should choose an ID for your section, and prefix it with the panel ID + ## (Be sure to not make a typo in the panel ID, which would implicitly create + ## an other entire panel) + ## + ## We use the context of pepettes_ynh as an example, + ## which is a simple donation form app written in python, + ## and for which the admin will want to edit the configuration [main.customization] - ## (optional) A section could have a title, or not. It depends of what you - ## are doing exactly. In web admin it will display an

title. + ## (optional) Defining a proper title for sections is not mandatory + ## and depends on the exact rendering you're aiming for the CLI / webadmin name = "" ## (optional) This help properties is a short help displayed on the same line - ## than the section title. + ## than the section title, meant to provide additional details # help = "" ## (optional) As for panel, you can specify to trigger a service @@ -84,13 +91,14 @@ services = ["nginx", "__APP__"] ## default behaviour for question in the section optional = false - ## (optional) It's also possible with the 'visible' property to display the - ## question only if the user answer the form in a specific way. - ## However, you should not refer to questions after the point where you put - ## the visible property. SO the first section should never have a visible - ## property - ## In more this feature is available in webadmin but not in cli, so keep in - ## mind cli user could be prompted for the question... + ## (optional) It's also possible with the 'visible' property to only + ## display the section depending on the user's answers to previous questions. + ## + ## Be careful that the 'visible' property should only refer to **previous** questions + ## Hence, it should not make sense to have a "visible" property on the very first section. + ## + ## Also, keep in mind that this feature only works in the webadmin and not in CLI + ## (therefore a user could be prompted in CLI for a question that may not be relevant) # visible = true ######################################################################## @@ -113,9 +121,11 @@ services = ["nginx", "__APP__"] [main.customization.project_name] ## (required) The ask property is equivalent to the ask property in - ## manifest.yml. However, in config panel questions are displayed on the - ## left. So, it's more a label than a complete question, make short. - ask = "Name of the project" + ## the manifest. However, in config panels, questions are displayed on the + ## left side and therefore have less space to be rendered. Therefore, + ## it is better to use a short question, and use the "help" property to + ## provide additional details if necessary. + ask.en = "Name of the project" ## (required) The type property indicates how the question should be ## displayed, validated and managed. Some types have specific properties. @@ -131,47 +141,60 @@ services = ["nginx", "__APP__"] ######################################################################## ## (recommended) 'bind' property is a powerful feature that let you - ## configure how the data will be read, validated and write. + ## configure how and where the data will be read, validated and written. ## By default, 'bind property is in "settings" mode, it means it will - ## read / write the value in application settings file. + ## **only** read and write the value in application settings file. ## bind = "settings" - ## But in general, you prefer use the ":FILE" mode to read/write a - ## specific variable in a file. + ## However, settings usually correspond to key/values in actual app configurations + ## Hence, a more useful mode is to have bind = ":FILENAME". In that case, YunoHost + ## will automagically find a line with "KEY=VALUE" in FILENAME + ## (with the adequate separator between KEY and VALUE) + ## + ## YunoHost will then use this value for the read/get operation. + ## During write/set operations, YunoHost will overwrite the value + ## in **both** FILENAME and in the app's settings.yml ## Configuration file format supported: yaml, toml, json, ini, env, php, - ## python. The feature probably works with others formats, but you need - ## to test it carefully. + ## python. The feature probably works with others formats, but should be tested carefully. - ## Unsupported: XML format, custom config function call, php define(), - ## array/list on several lines. + ## Note that this feature only works with relatively simple cases + ## such as `KEY: VALUE`, but won't properly work with + ## complex data structures like multilin array/lists or dictionnaries. + ## It also doesn't work with XML format, custom config function call, php define(), ... ## More info on TODO # bind = ":/var/www/__APP__/settings.py" - ## NOTE: in pepettes, the python variable is called 'name' and not - ## 'project_name', wo here we need to specify the variable name by hand - ## before columns - ## Here pepettes config file to understand: https://github.com/YunoHost-Apps/pepettes_ynh/blob/5cc2d3ffd6529cc7356ff93af92dbb6785c3ab9a/conf/settings.py##L11 + + ## By default, bind = ":FILENAME" will use the question ID as KEY + ## ... but the question ID may sometime not be the exact KEY name in the configuration file. + ## + ## In particular, in pepettes, the python variable is 'name' and not 'project_name' + ## (c.f. https://github.com/YunoHost-Apps/pepettes_ynh/blob/5cc2d3ffd6529cc7356ff93af92dbb6785c3ab9a/conf/settings.py##L11 ) + ## + ## In that case, the key name can be specified before the column ':' bind = "name:/var/www/__APP__/settings.py" ## --------------------------------------------------------------------- ## IMPORTANT: other 'bind' mode exists: ## - ## The null mode, to explicitly disable default read / write in settings. - # bind = "null" + ## bind = "FILENAME" (with no column character before FILENAME) + ## may be used to bind to the **entire file content** (instead of a single KEY/VALUE) + ## This could be used to expose an entire configuration file, or binary files such as images + ## For example: + ## bind = "/var/www/__APP__/img/logo.png" + ## + ## bind = "null" can be used to disable reading / writing in settings. + ## This creates sort of a "virtual" or "ephemeral" question which is not related to any actual setting + ## In this mode, you are expected to define custom getter/setters/validators in scripts/config: + ## + ## getter: get__QUESTIONID() + ## setter: set__QUESTIONID() + ## validator: validate__QUESTIONID() ## - ## Without columns before the path it means all the file will be replaced - ## by the value (reserved for file and multiline text question): - # bind = "/var/www/__APP__/img/logo.png" - ## - ## Finally, if you define a custom getter, setter or validator in config - ## script it will use it instead of apply default bind behaviour. - ## getter: get__PROPERTY() - ## setter: set__PROPERTY() - ## validator: validate__PROPERTY() ## You can also specify a common getter / setter / validator, with the ## function 'bind' mode, for example here it will try to run ## get__array_settings() first. @@ -179,10 +202,11 @@ services = ["nginx", "__APP__"] ## --------------------------------------------------------------------- ## --------------------------------------------------------------------- - ## IMPORTANT: during install/upgrade you should save a first value in - ## the source of the bind key and in app settings. - ## During upgrade you should reset values in template files based on - ## value saved in app settings. + ## IMPORTANT: with the exception of bind=null questions, + ## question IDs should almost **always** correspond to an app setting + ## initialized / reused during install/upgrade. + ## Not doing so may result in inconsistencies between the config panel mechanism + ## and the use of ynh_add_config ## --------------------------------------------------------------------- ######################################################################## @@ -213,7 +237,7 @@ services = ["nginx", "__APP__"] type = "url" example = "mailto: contact@example.org" help = "mailto: accepted" - pattern.regexp = "^mailto:[^@]+@[^@]+|https://$" + pattern.regexp = '^mailto:[^@]+@[^@]+|https://$' pattern.error = "Should be https or mailto:" bind = ":/var/www/__APP__/settings.py" @@ -222,14 +246,14 @@ services = ["nginx", "__APP__"] type = "file" accept = ".png" help = "Fill with an already resized logo" - source="__FINALPATH__/img/logo.png" + bind = "__FINALPATH__/img/logo.png" [main.customization.favicon] ask = "Favicon" type = "file" accept = ".png" help = "Fill with an already sized favicon" - source="__FINALPATH__/img/favicon.png" + bind = "__FINALPATH__/img/favicon.png" [main.stripe] From ad14cc664b58d1cdd1fe9796298f663200417649 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 6 Oct 2021 19:51:34 +0200 Subject: [PATCH 20/20] Update config_panel.toml.example --- config_panel.toml.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_panel.toml.example b/config_panel.toml.example index ea8fefc..c6bccd8 100644 --- a/config_panel.toml.example +++ b/config_panel.toml.example @@ -35,7 +35,7 @@ version = "1.0" ## The next level describes web admin panels ## You have to choose an ID for each panel, in this example the ID is "main" -## Keep in mind this id will be used in cli to refer to your question, so choose +## Keep in mind this ID will be used in CLI to refer to your question, so choose ## something short and meaningfull. ## In the webadmin, each panel corresponds to a distinct tab / form [main]