From 050273c097c3c686535044bbb1c1ae71083253d5 Mon Sep 17 00:00:00 2001 From: leonard Date: Mon, 4 Dec 2023 06:59:26 +0100 Subject: [PATCH 01/13] tentative d'ajout d'une configuration --- config_panel.toml | 18 +++ config_panel.toml.example | 302 -------------------------------------- scripts/config | 74 +--------- 3 files changed, 25 insertions(+), 369 deletions(-) create mode 100644 config_panel.toml delete mode 100644 config_panel.toml.example diff --git a/config_panel.toml b/config_panel.toml new file mode 100644 index 0000000..630fb2a --- /dev/null +++ b/config_panel.toml @@ -0,0 +1,18 @@ +version = "1.0" + +[main] +name.en = "Information about your app's code" +name.fr = "Information à propos de votre propre code" + + [main.custom_main_folder] + ask = "Name of your app's main folder" + type = "string" + default = "FastAPIAppFolder" + help = "It's the folder containing the object 'app' in __init__.py" + + [main.custom_requirements] + ask = "Do you have a custom requirement.txt" + type = "boolean" + optional = true + help = "Check it if you want my_FastAPI_app to install your custom python dependencies." + bind = "install_custom_requirements()" diff --git a/config_panel.toml.example b/config_panel.toml.example deleted file mode 100644 index ed147af..0000000 --- a/config_panel.toml.example +++ /dev/null @@ -1,302 +0,0 @@ - -## Config panel are available from webadmin > Apps > YOUR_APP > Config Panel Button -## 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: 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. - -## 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. -## In the webadmin, each panel corresponds to a distinct tab / form -[main] - -## 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 = ["__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. -# help = "" - - ############################################################################ - #### ABOUT SECTIONS - ############################################################################ - - ## 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) 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, meant to provide additional details - # 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 = false - - ## (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 - - ######################################################################## - #### 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. - ## --------------------------------------------------------------------- - - ## 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.customization.project_name] - - ## (required) The ask property is equivalent to the ask property in - ## 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. - ## - ## 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 and where the data will be read, validated and written. - - ## By default, 'bind property is in "settings" mode, it means it will - ## **only** read and write the value in application settings file. - ## bind = "settings" - - ## 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 should be tested carefully. - - ## 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" - - - ## 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: - ## - ## 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() - ## - ## 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: 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 - ## --------------------------------------------------------------------- - - ######################################################################## - #### 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) for boolean questions you can specify replacement values - ## bound to true and false, in case property is bound to config file - # useful if bound property in config file expects something else than integer 1 - yes = "Enable" - # useful if bound property in config file expects something else than integer 0 - no = "Disable" - - ## (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" - bind = "__INSTALL_DIR__/img/logo.png" - - [main.customization.favicon] - ask = "Favicon" - type = "file" - accept = ".png" - help = "Fill with an already sized favicon" - bind = "__INSTALL_DIR__/img/favicon.png" - - - [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" - type = "string" - redact = true - help = "Indicate here the stripe publishable key" - bind = ":/var/www/__APP__/settings.py" - - [main.stripe.secret_key] - ask = "Secret key" - type = "string" - 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" diff --git a/scripts/config b/scripts/config index 711fd16..9972955 100644 --- a/scripts/config +++ b/scripts/config @@ -23,77 +23,17 @@ ynh_abort_if_errors #================================================= install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) +data_dir=$(ynh_app_setting_get --app=$app --key=data_dir) #================================================= -# SPECIFIC GETTERS FOR TOML SHORT KEY +# SPECIFIC ACTION FOR TOML SHORT KEY #================================================= +install_custom_requirements() { + #Enable python virtual environnement + source $install_dir/bin/activate -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 - 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__prices() { - local prices = "$(grep "DONATION\['" "$install_dir/settings.py" | sed -r "s@^DONATION\['([^']*)'\]\['([^']*)'\] = '([^']*)'@\1/\2/\3@g" | sed -z 's/\n/,/g;s/,$/\n/')" - if [ "$prices" == "," ]; - then - # Return YNH_NULL if you prefer to not return a value at all. - echo YNH_NULL - else - echo $prices - fi -} - - -#================================================= -# SPECIFIC VALIDATORS FOR TOML SHORT KEYS -#================================================= -validate__publishable_key() { - - # We can imagine here we test if the key is really a publishable key - (is_secret_key $publishable_key) && - echo 'This key seems to be a secret key' -} - -#================================================= -# SPECIFIC SETTERS FOR TOML SHORT KEYS -#================================================= -set__prices() { - - #--------------------------------------------- - # IMPORTANT: setters are triggered 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'\]" "$install_dir/settings.py" - - echo "DONATION['$frequency']['$currency'] = '$price_id'" >> "$install_dir/settings.py" - done - - #--------------------------------------------- - # IMPORTANT: to be able to upgrade properly, you have to save the value in settings too - #--------------------------------------------- - ynh_app_setting_set $app prices $prices + #Install user's custom requirements + pip install -r $data_dir/requirements.txt } #================================================= From 9c23894b92d5fcc4a1c2d846289a5f4d80dd0472 Mon Sep 17 00:00:00 2001 From: leonard Date: Mon, 4 Dec 2023 07:19:43 +0100 Subject: [PATCH 02/13] fixing some linter error --- config_panel.toml | 22 +++++++++++----------- manifest.toml | 4 ++-- scripts/config | 2 +- scripts/install | 4 +++- scripts/restore | 2 +- scripts/upgrade | 2 +- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/config_panel.toml b/config_panel.toml index 630fb2a..ab07d29 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -4,15 +4,15 @@ version = "1.0" name.en = "Information about your app's code" name.fr = "Information à propos de votre propre code" - [main.custom_main_folder] - ask = "Name of your app's main folder" - type = "string" - default = "FastAPIAppFolder" - help = "It's the folder containing the object 'app' in __init__.py" + [main.custom_code] + [main.custom_code.main_folder] + ask = "Name of your app's main folder" + type = "string" + default = "FastAPIAppFolder" + help = "It's the folder containing the object 'app' in __init__.py" - [main.custom_requirements] - ask = "Do you have a custom requirement.txt" - type = "boolean" - optional = true - help = "Check it if you want my_FastAPI_app to install your custom python dependencies." - bind = "install_custom_requirements()" + [main.custom_code.requirements] + ask = "Do you have a custom requirement.txt" + type = "boolean" + optional = true + help = "Check it if you want my_FastAPI_app to install your custom python dependencies." \ No newline at end of file diff --git a/manifest.toml b/manifest.toml index bb9f3ce..d5f0660 100644 --- a/manifest.toml +++ b/manifest.toml @@ -38,8 +38,8 @@ ram.runtime = "50M" default = "visitors" [install.password] - ask.en = "Password that you will need to upload your code on YunoHost" - ask.fr = "Le mot de passe que vous utiliserez pour téléverser votre code sur Yunohost" + help.en = "Password that you will need to upload your code on YunoHost" + help.fr = "Le mot de passe que vous utiliserez pour téléverser votre code sur Yunohost" type = "password" [resources] diff --git a/scripts/config b/scripts/config index 9972955..4a53e15 100644 --- a/scripts/config +++ b/scripts/config @@ -28,7 +28,7 @@ data_dir=$(ynh_app_setting_get --app=$app --key=data_dir) #================================================= # SPECIFIC ACTION FOR TOML SHORT KEY #================================================= -install_custom_requirements() { +setter__requirements() { #Enable python virtual environnement source $install_dir/bin/activate diff --git a/scripts/install b/scripts/install index 87cd107..ea4d260 100755 --- a/scripts/install +++ b/scripts/install @@ -46,6 +46,8 @@ ynh_add_config --template="gunicorn.conf.py" --destination="$install_dir/gunicor mkdir -p "$data_dir/FastAPIAppFolder" ynh_add_config --template="__init__.py" --destination="$data_dir/FastAPIAppFolder/__init__.py" +ynh_app_setting_set --app=$app --key=main_folder --value="FastAPIAppFolder" +ynh_app_setting_set --app=$app --key=requirements --value=0 # Add the password to this user chpasswd <<< "${app}:${password}" @@ -68,7 +70,7 @@ ynh_add_nginx_config ynh_add_systemd_config -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" +yunohost service add $app --description="Gunicorn running a FastAPI app" --log="/var/log/$app/$app.log" #================================================= # Start the app server via systemd diff --git a/scripts/restore b/scripts/restore index 6b9f503..b9cb9f5 100755 --- a/scripts/restore +++ b/scripts/restore @@ -58,7 +58,7 @@ ynh_systemd_action --service_name=$app --action="start" --log_path="$log_file" #================================================= ynh_script_progression --message="Integrating service in YunoHost..." -yunohost service add $app +yunohost service add $app --description="Gunicorn running a FastAPI app" --log="/var/log/$app/$app.log" #================================================= # RESTORE THE LOGROTATE CONFIGURATION diff --git a/scripts/upgrade b/scripts/upgrade index 1a7be5e..1892674 100755 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -65,7 +65,7 @@ ynh_add_nginx_config ynh_add_systemd_config -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" +yunohost service add $app --description="Gunicorn running a FastAPI app" --log="/var/log/$app/$app.log" #================================================= # START SYSTEMD SERVICE From 3b75f53b0ead8f5badf5387ceaffe64a472b37b2 Mon Sep 17 00:00:00 2001 From: leonard Date: Tue, 5 Dec 2023 11:27:14 +0100 Subject: [PATCH 03/13] =?UTF-8?q?am=C3=A9lioration=20de=20la=20configurati?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config_panel.toml | 2 +- config_panel.toml.exampl22e | 302 ++++++++++++++++++++++++++++++++++++ manifest.toml | 2 +- scripts/config | 42 ++++- 4 files changed, 338 insertions(+), 10 deletions(-) create mode 100644 config_panel.toml.exampl22e diff --git a/config_panel.toml b/config_panel.toml index ab07d29..24cbbc1 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -15,4 +15,4 @@ name.fr = "Information à propos de votre propre code" ask = "Do you have a custom requirement.txt" type = "boolean" optional = true - help = "Check it if you want my_FastAPI_app to install your custom python dependencies." \ No newline at end of file + help = "Check it if you want my_FastAPI_app to install your custom python dependencies." diff --git a/config_panel.toml.exampl22e b/config_panel.toml.exampl22e new file mode 100644 index 0000000..ed147af --- /dev/null +++ b/config_panel.toml.exampl22e @@ -0,0 +1,302 @@ + +## Config panel are available from webadmin > Apps > YOUR_APP > Config Panel Button +## 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: 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. + +## 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. +## In the webadmin, each panel corresponds to a distinct tab / form +[main] + +## 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 = ["__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. +# help = "" + + ############################################################################ + #### ABOUT SECTIONS + ############################################################################ + + ## 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) 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, meant to provide additional details + # 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 = false + + ## (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 + + ######################################################################## + #### 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. + ## --------------------------------------------------------------------- + + ## 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.customization.project_name] + + ## (required) The ask property is equivalent to the ask property in + ## 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. + ## + ## 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 and where the data will be read, validated and written. + + ## By default, 'bind property is in "settings" mode, it means it will + ## **only** read and write the value in application settings file. + ## bind = "settings" + + ## 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 should be tested carefully. + + ## 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" + + + ## 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: + ## + ## 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() + ## + ## 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: 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 + ## --------------------------------------------------------------------- + + ######################################################################## + #### 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) for boolean questions you can specify replacement values + ## bound to true and false, in case property is bound to config file + # useful if bound property in config file expects something else than integer 1 + yes = "Enable" + # useful if bound property in config file expects something else than integer 0 + no = "Disable" + + ## (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" + bind = "__INSTALL_DIR__/img/logo.png" + + [main.customization.favicon] + ask = "Favicon" + type = "file" + accept = ".png" + help = "Fill with an already sized favicon" + bind = "__INSTALL_DIR__/img/favicon.png" + + + [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" + type = "string" + redact = true + help = "Indicate here the stripe publishable key" + bind = ":/var/www/__APP__/settings.py" + + [main.stripe.secret_key] + ask = "Secret key" + type = "string" + 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" diff --git a/manifest.toml b/manifest.toml index d5f0660..d4ba193 100644 --- a/manifest.toml +++ b/manifest.toml @@ -45,7 +45,7 @@ ram.runtime = "50M" [resources] [resources.system_user] allow_sftp = true - allow_ssh = false + allow_ssh = true home = "/home/yunohost.app/__APP__" # This will provision/deprovision a unix system user diff --git a/scripts/config b/scripts/config index 4a53e15..78bcbf3 100644 --- a/scripts/config +++ b/scripts/config @@ -26,17 +26,43 @@ install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) data_dir=$(ynh_app_setting_get --app=$app --key=data_dir) #================================================= -# SPECIFIC ACTION FOR TOML SHORT KEY +# SPECIFIC SETTERS FOR TOML SHORT KEYS #================================================= -setter__requirements() { - #Enable python virtual environnement - source $install_dir/bin/activate - - #Install user's custom requirements - pip install -r $data_dir/requirements.txt -} #================================================= # GENERIC FINALIZATION #================================================= + +ynh_app_config_apply() { + _ynh_app_config_apply + + #TODO : add password question to configuration panel + password="" + # Set new password + if [ ! "$password" == "" ] + then + ynh_print_info --message="Changing password for user ${app}" + chpasswd <<< "${app}:${password}" + fi + + # Symbolic link to main app folder + if [ ! "$main_folder" == "FastAPIAppFolder" ] + then + ynh_print_info --message="Deleting $data_dir/FastAPIAppFolder" + rm -rf "$data_dir/FastAPIAppFolder" + ynh_print_info --message="Creating symbolic link to folder ${main_folder}" + ln -s "$data_dir/$main_folder" "$data_dir/FastAPIAppFolder" + fi + + if [ $requirements == 1 ] + then + ynh_print_info --message="Installing python custom requirements" + # Enable python virtual environnement + source $install_dir/venv/bin/activate + + # Install user's custom requirements + pip install -r $data_dir/requirements.txt + fi +} + ynh_app_config_run $1 From 2fe22d9d440ce1f28cbcc731250512c2a80f9c7a Mon Sep 17 00:00:00 2001 From: leonard Date: Fri, 8 Dec 2023 13:47:47 +0100 Subject: [PATCH 04/13] changement de programme pour la config --- config_panel.toml | 10 +++++----- scripts/config | 10 ++++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/config_panel.toml b/config_panel.toml index 24cbbc1..f129352 100644 --- a/config_panel.toml +++ b/config_panel.toml @@ -7,12 +7,12 @@ name.fr = "Information à propos de votre propre code" [main.custom_code] [main.custom_code.main_folder] ask = "Name of your app's main folder" - type = "string" + type = "path" default = "FastAPIAppFolder" help = "It's the folder containing the object 'app' in __init__.py" - [main.custom_code.requirements] - ask = "Do you have a custom requirement.txt" - type = "boolean" + [main.custom_code.requirements_path] + ask = "path to your requirements.txt file" + type = "path" optional = true - help = "Check it if you want my_FastAPI_app to install your custom python dependencies." + help = "Relative path to your requirement file, including it's name" diff --git a/scripts/config b/scripts/config index 78bcbf3..0bffb37 100644 --- a/scripts/config +++ b/scripts/config @@ -45,6 +45,9 @@ ynh_app_config_apply() { chpasswd <<< "${app}:${password}" fi + ynh_script_progression --message="Stopping a systemd service..." --weight=1 + ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" + # Symbolic link to main app folder if [ ! "$main_folder" == "FastAPIAppFolder" ] then @@ -54,15 +57,18 @@ ynh_app_config_apply() { ln -s "$data_dir/$main_folder" "$data_dir/FastAPIAppFolder" fi - if [ $requirements == 1 ] + if [ ! "$requirements_path" == "" ] then ynh_print_info --message="Installing python custom requirements" # Enable python virtual environnement source $install_dir/venv/bin/activate # Install user's custom requirements - pip install -r $data_dir/requirements.txt + pip install -r $data_dir/$requirements_path fi + + ynh_script_progression --message="Starting a systemd service..." --weight=1 + ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" } ynh_app_config_run $1 From 1525e652aff54b4762da35779a149d1e922080aa Mon Sep 17 00:00:00 2001 From: leonard Date: Fri, 8 Dec 2023 15:03:41 +0100 Subject: [PATCH 05/13] =?UTF-8?q?d=C3=A9finition=20du=20root=5Fpath=20via?= =?UTF-8?q?=20uvicorn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/__init__.py | 5 ++++- conf/systemd.service | 3 +++ scripts/change_url | 5 +++++ scripts/install | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/conf/__init__.py b/conf/__init__.py index f75a4af..5703e85 100644 --- a/conf/__init__.py +++ b/conf/__init__.py @@ -1,9 +1,12 @@ +import os from typing import Union from fastapi import FastAPI -app = FastAPI(root_path="__PATH__") +UVICORN_ROOT_PATH = os.environ.get('UVICORN_ROOT_PATH') +#app = FastAPI(root_path=UVICORN_ROOT_PATH) +app = FastAPI() @app.get("/") def read_root(): diff --git a/conf/systemd.service b/conf/systemd.service index 2c69049..84dd1bb 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -7,6 +7,9 @@ User=__APP__ Group=__APP__ WorkingDirectory=__DATA_DIR__/ +# UVICORN_ROOT_PATH is used by FastAPI to serve the 'docs' page correctly +Environment="UVICORN_ROOT_PATH=__PATH__" + ExecStart=__INSTALL_DIR__/venv/bin/gunicorn --config __INSTALL_DIR__/gunicorn.conf.py FastAPIAppFolder:app --worker-class uvicorn.workers.UvicornWorker StandardOutput=syslog diff --git a/scripts/change_url b/scripts/change_url index ae914ad..0512850 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -25,6 +25,11 @@ ynh_script_progression --message="Updating NGINX web server configuration..." -- ynh_change_url_nginx_config +ynh_script_progression --message="Updating systemd service..." --weight=1 + +ynh_add_systemd_config + + #================================================= # GENERIC FINALISATION #================================================= diff --git a/scripts/install b/scripts/install index ea4d260..2a58011 100755 --- a/scripts/install +++ b/scripts/install @@ -47,7 +47,7 @@ ynh_add_config --template="gunicorn.conf.py" --destination="$install_dir/gunicor mkdir -p "$data_dir/FastAPIAppFolder" ynh_add_config --template="__init__.py" --destination="$data_dir/FastAPIAppFolder/__init__.py" ynh_app_setting_set --app=$app --key=main_folder --value="FastAPIAppFolder" -ynh_app_setting_set --app=$app --key=requirements --value=0 +ynh_app_setting_set --app=$app --key=requirements_path --value="" # Add the password to this user chpasswd <<< "${app}:${password}" From 7b65a58c6955aecb301ffe60498429ae9b542bae Mon Sep 17 00:00:00 2001 From: leonard Date: Mon, 11 Dec 2023 09:58:57 +0100 Subject: [PATCH 06/13] Ajout de la configuration nginx pour activer les CORS pour FastAPI --- conf/nginx.conf | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 28a396a..3505ee9 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -4,11 +4,41 @@ location = __PATH__/ { } location __PATH__/ { - # https://github.com/benoitc/gunicorn/blob/master/examples/nginx.conf + # Wide-open CORS config for nginx + # From : https://enable-cors.org/server_nginx.html + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + # + # Custom headers and headers various browsers *should* be OK with but aren't + # + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + # + # Tell client that this pre-flight info is valid for 20 days + # + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + if ($request_method = 'POST') { + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; + add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always; + } + if ($request_method = 'GET') { + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; + add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always; + } # this is needed if you have file import via upload enabled client_max_body_size 100M; + # Configuration to pass request to Gunicorn + # https://github.com/benoitc/gunicorn/blob/master/examples/nginx.conf proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -16,6 +46,9 @@ location __PATH__/ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; + # do not pass the CORS header from the response of the proxied server to the client + proxy_hide_header 'Access-Control-Allow-Origin'; + proxy_read_timeout 30; proxy_send_timeout 30; proxy_connect_timeout 30; From 85d5c941da0c4f67bb174001318dd870241e6791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?E=CC=81ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Fri, 15 Dec 2023 20:36:45 +0100 Subject: [PATCH 07/13] fix linter --- conf/nginx.conf | 28 +++++++++++----------------- manifest.toml | 11 +++-------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 3505ee9..337513f 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -7,31 +7,25 @@ location __PATH__/ { # Wide-open CORS config for nginx # From : https://enable-cors.org/server_nginx.html if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + more_set_headers "Access-Control-Allow-Origin: *"; + more_set_headers "Access-Control-Allow-Methods: GET, POST, OPTIONS"; # # Custom headers and headers various browsers *should* be OK with but aren't # - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + more_set_headers "Access-Control-Allow-Headers" 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; # # Tell client that this pre-flight info is valid for 20 days # - add_header 'Access-Control-Max-Age' 1728000; - add_header 'Content-Type' 'text/plain; charset=utf-8'; - add_header 'Content-Length' 0; + more_set_headers "Access-Control-Max-Age: 1728000"; + more_set_headers "Content-Type: text/plain; charset=utf-8"; + more_set_headers "Content-Length: 0"; return 204; } - if ($request_method = 'POST') { - add_header 'Access-Control-Allow-Origin' '*' always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; - add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always; - } - if ($request_method = 'GET') { - add_header 'Access-Control-Allow-Origin' '*' always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; - add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always; + if ($request_method = (POST|GET)$) { + more_set_headers "Access-Control-Allow-Origin: * always"; + more_set_headers "Access-Control-Allow-Methods: GET, POST, OPTIONS' always"; + more_set_headers "Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range always"; + more_set_headers "Access-Control-Expose-Headers: Content-Length,Content-Range always"; } # this is needed if you have file import via upload enabled diff --git a/manifest.toml b/manifest.toml index d4ba193..c5edd37 100644 --- a/manifest.toml +++ b/manifest.toml @@ -19,8 +19,11 @@ code = "https://github.com/leonarf/FastAPI_ynh" yunohost = ">= 11.2.5" architectures = "all" multi_instance = true + ldap = "not_relevant" + sso = "not_relevant" + disk = "50M" ram.build = "350M" ram.runtime = "50M" @@ -47,24 +50,16 @@ ram.runtime = "50M" allow_sftp = true allow_ssh = true home = "/home/yunohost.app/__APP__" - # This will provision/deprovision a unix system user [resources.install_dir] [resources.data_dir] - # This will create/remove the data dir as /home/yunohost.app/$app - # and store the corresponding setting $data_dir dir = "/home/yunohost.app/__APP__" [resources.permissions] - # This will configure SSOwat permission for $domain/$path/ - # The initial allowed group of user is configured via the init_main_permission question (public=visitors, private=all_users) main.url = "/" [resources.ports] - # This will pick a random port for reverse-proxying and store it as the $port setting [resources.apt] - # This will automatically install/uninstall the following apt packages - # and implicitly define the $phpversion setting as 8.0 (if phpX.Y-foobar dependencies are listed) packages = "python3-dev, python3-pip, python3-venv" From 5235913731718233a2167a0c4e4ba9de7c994923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?E=CC=81ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Fri, 15 Dec 2023 20:44:19 +0100 Subject: [PATCH 08/13] Update nginx.conf --- conf/nginx.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 337513f..d56d97a 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -23,7 +23,7 @@ location __PATH__/ { } if ($request_method = (POST|GET)$) { more_set_headers "Access-Control-Allow-Origin: * always"; - more_set_headers "Access-Control-Allow-Methods: GET, POST, OPTIONS' always"; + more_set_headers "Access-Control-Allow-Methods: GET, POST, OPTIONS always"; more_set_headers "Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range always"; more_set_headers "Access-Control-Expose-Headers: Content-Length,Content-Range always"; } From d6156e0900cc62cfc74393b647e14a4def22119d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?E=CC=81ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Fri, 15 Dec 2023 23:04:10 +0100 Subject: [PATCH 09/13] Update nginx.conf --- conf/nginx.conf | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index d56d97a..57e2c51 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -12,7 +12,7 @@ location __PATH__/ { # # Custom headers and headers various browsers *should* be OK with but aren't # - more_set_headers "Access-Control-Allow-Headers" 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + more_set_headers "Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range"; # # Tell client that this pre-flight info is valid for 20 days # @@ -21,7 +21,14 @@ location __PATH__/ { more_set_headers "Content-Length: 0"; return 204; } - if ($request_method = (POST|GET)$) { + if ($request_method = 'POST') { + more_set_headers "Access-Control-Allow-Origin: * always"; + more_set_headers "Access-Control-Allow-Methods: GET, POST, OPTIONS always"; + more_set_headers "Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range always"; + more_set_headers "Access-Control-Expose-Headers: Content-Length,Content-Range always"; + } + + if ($request_method = 'GET') { more_set_headers "Access-Control-Allow-Origin: * always"; more_set_headers "Access-Control-Allow-Methods: GET, POST, OPTIONS always"; more_set_headers "Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range always"; From 500bbcd7d1050a0683c2494f2ed57c96ce33298b Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 16 Dec 2023 09:31:42 +0100 Subject: [PATCH 10/13] Update manifest.toml --- manifest.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.toml b/manifest.toml index c5edd37..42daf60 100644 --- a/manifest.toml +++ b/manifest.toml @@ -42,7 +42,7 @@ ram.runtime = "50M" [install.password] help.en = "Password that you will need to upload your code on YunoHost" - help.fr = "Le mot de passe que vous utiliserez pour téléverser votre code sur Yunohost" + help.fr = "Le mot de passe que vous utiliserez pour téléverser votre code sur YunoHost" type = "password" [resources] From 25780686480e62bc906f229cf0b7efba5eb88f49 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 16 Dec 2023 09:32:26 +0100 Subject: [PATCH 11/13] Update manifest.toml --- manifest.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.toml b/manifest.toml index 42daf60..e6068d4 100644 --- a/manifest.toml +++ b/manifest.toml @@ -7,7 +7,7 @@ name = "my_FastAPI_app" description.en = "Custom Web app to run a FastAPI program written in Python" description.fr = "Une application web personnalisée pour faire tourner une application FastAPI écrite en Python" -version = "1.0~ynh1" +version = "1.0~ynh2" maintainers = ["leonarf"] From 76a88fccbc46760a80d6903870f9be87cc806ea9 Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Sat, 16 Dec 2023 08:32:38 +0000 Subject: [PATCH 12/13] Auto-update README --- README.md | 2 +- README_fr.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b8e67dc..121f7c1 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in This Application install a FastAPI application "Hello Word" ready to be customized by your own code -**Shipped version:** 1.0~ynh1 +**Shipped version:** 1.0~ynh2 ## Screenshots diff --git a/README_fr.md b/README_fr.md index 5ca7936..676ec37 100644 --- a/README_fr.md +++ b/README_fr.md @@ -18,7 +18,7 @@ Si vous n’avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) po Cette application installe une application FastAPI "Hello world" prête à être personnalisée par votre propre code. -**Version incluse :** 1.0~ynh1 +**Version incluse :** 1.0~ynh2 ## Captures d’écran From 1157340b46ddaf40f3e4db49d11f59c3ce3c3fe9 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 16 Dec 2023 09:34:34 +0100 Subject: [PATCH 13/13] Update change_url --- scripts/change_url | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/change_url b/scripts/change_url index 0512850..65a653e 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -29,7 +29,6 @@ ynh_script_progression --message="Updating systemd service..." --weight=1 ynh_add_systemd_config - #================================================= # GENERIC FINALISATION #=================================================