From a27723e8721aa626555bd3fa41641faf9a0c0d81 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 18:07:29 +0100 Subject: [PATCH 01/59] Upgrade to v.3.0.0 --- README.md | 2 +- conf/app.src | 4 ++-- manifest.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 531ad06..66ea36b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in ## Overview Grocy is a web-based self-hosted groceries & household management solution for your home. -**Shipped version:** 2.7.1 +**Shipped version:** 3.0.0 ## Screenshots diff --git a/conf/app.src b/conf/app.src index c73adaa..0174290 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://github.com/grocy/grocy/releases/download/v2.7.1/grocy_2.7.1.zip -SOURCE_SUM=f95cc2cc279a6445738ef9b5cc05a8cee438348d343081a76a6aa74464f76129 +SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.0.0/grocy_3.0.0.zip +SOURCE_SUM=3bb0e4b1f03de481ef2c9c91ad61bc88409c5140ec3adcad77bf24a0d65d4331 SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=zip SOURCE_IN_SUBDIR=false diff --git a/manifest.json b/manifest.json index 6303a02..9b6231b 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Issue tracker that provides a balance between simplicity and power", "fr": "Gestionnaire de ticket avec un équilibre entre simplicité et puissance" }, - "version": "2.7.1~ynh1", + "version": "3.0.0~ynh1", "url": "https://github.com/grocy/grocy", "license": "MIT", "maintainer": { From a136314b1af79b513fa092970fdbf9c9f103e551 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 18:33:59 +0100 Subject: [PATCH 02/59] Fix --- manifest.json | 6 +++--- scripts/install | 10 +++++++--- scripts/restore | 19 +++++++++++++------ scripts/upgrade | 18 +++++++----------- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/manifest.json b/manifest.json index 9b6231b..9675e40 100644 --- a/manifest.json +++ b/manifest.json @@ -3,8 +3,8 @@ "id": "grocy", "packaging_format": 1, "description": { - "en": "Issue tracker that provides a balance between simplicity and power", - "fr": "Gestionnaire de ticket avec un équilibre entre simplicité et puissance" + "en": "Web-based self-hosted groceries & household management solution for your home", + "fr": "Solution Web auto-hébergée de gestion d'épicerie et de gestion de la maison" }, "version": "3.0.0~ynh1", "url": "https://github.com/grocy/grocy", @@ -48,7 +48,7 @@ "en": "Choose the application language", "fr": "Choisissez la langue de l'application" }, - "choices": ["fr", "en"], + "choices": ["de", "en", "es", "fr", "it", "pt"], "default": "fr" }, { diff --git a/scripts/install b/scripts/install index d666990..340ef04 100644 --- a/scripts/install +++ b/scripts/install @@ -88,10 +88,7 @@ phpversion=$(ynh_app_setting_get --app="$app" --key=phpversion) cp -a ../conf/config-dist.php "$final_path/data/config.php" -#ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$final_path/data/config.php" -#ynh_replace_string --match_string="__PATH_URL__" --replace_string="$path_url" --target_file="$final_path/data/config.php" ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$final_path/data/config.php" -#ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$final_path/data/config.php" #================================================= # STORE THE CONFIG FILE CHECKSUM @@ -108,6 +105,13 @@ ynh_store_file_checksum --file="$final_path/data/config.php" # Set permissions to app files chown -R $app: $final_path +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 + +yunohost service add $app --description="Self-hosted groceries & household management" --log="/var/log/$app/$app.log" + #================================================= # SETUP SSOWAT #================================================= diff --git a/scripts/restore b/scripts/restore index 0c671a5..310e62d 100644 --- a/scripts/restore +++ b/scripts/restore @@ -61,6 +61,16 @@ ynh_script_progression --message="Recreating the dedicated system user..." --wei # Create the dedicated user (if not existing) ynh_system_user_create --username=$app +#================================================= +# RESTORE THE PHP-FPM CONFIGURATION +#================================================= +ynh_script_progression --message="Restoring PHP-FPM configuration..." + +ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" + +# Recreate a dedicated PHP-FPM config +ynh_add_fpm_config --package="$extra_php_dependencies" + #================================================= # RESTORE USER RIGHTS #================================================= @@ -69,14 +79,11 @@ ynh_system_user_create --username=$app chown -R $app: $final_path #================================================= -# RESTORE THE PHP-FPM CONFIGURATION +# INTEGRATE SERVICE IN YUNOHOST #================================================= -ynh_script_progression --message="Restoring PHP-FPM configuration..." +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 -ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" - -# Recreate a dedicated php-fpm config -ynh_add_fpm_config --usage=low --footprint=low --package="$extra_php_dependencies" +yunohost service add $app --description="Self-hosted groceries & household management" --log="/var/log/$app/$app.log" #================================================= # GENERIC FINALIZATION diff --git a/scripts/upgrade b/scripts/upgrade index d9f323f..3a27844 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -34,15 +34,6 @@ upgrade_type=$(ynh_check_app_version_changed) #================================================= ynh_script_progression --message="Ensuring downward compatibility..." --weight=1 -# Fix is_public as a boolean value -if [ "$is_public" = "Yes" ]; then - ynh_app_setting_set --app=$app --key=is_public --value=1 - is_public=1 -elif [ "$is_public" = "No" ]; then - ynh_app_setting_set --app=$app --key=is_public --value=0 - is_public=0 -fi - # If final_path doesn't exist, create it if [ -z "$final_path" ]; then final_path=/var/www/$app @@ -112,10 +103,15 @@ ynh_add_fpm_config --package="$extra_php_dependencies" cp -a ../conf/config-dist.php "$final_path/config-dist.php" -#ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$final_path/data/config.php" -#ynh_replace_string --match_string="__PATH_URL__" --replace_string="$path_url" --target_file="$final_path/data/config.php" ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$final_path/data/config.php" +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 + +yunohost service add $app --description="Self-hosted groceries & household management" --log="/var/log/$app/$app.log" + #================================================= # RELOAD NGINX #================================================= From 3426cd48f154fa9482bc328736cc573296cff225 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 18:37:01 +0100 Subject: [PATCH 03/59] Fix --- check_process | 2 +- scripts/remove | 17 ++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/check_process b/check_process index c309eb9..f22c51d 100644 --- a/check_process +++ b/check_process @@ -12,7 +12,7 @@ is_public=1 (PUBLIC|public=1|private=0) ; Checks pkg_linter=1 - setup_sub_dir=1 + setup_sub_dir=0 setup_root=1 setup_nourl=0 setup_private=1 diff --git a/scripts/remove b/scripts/remove index 220a43d..10b1f03 100644 --- a/scripts/remove +++ b/scripts/remove @@ -24,18 +24,13 @@ final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= # STOP AND REMOVE SERVICE #================================================= -ynh_script_progression --message="Stopping and removing the systemd service" --weight=1 -# Remove the dedicated systemd config -ynh_remove_systemd_config - -#================================================= -# REMOVE DEPENDENCIES -#================================================= -ynh_script_progression --message="Removing dependencies..." --weight=1 - -# Remove metapackage and its dependencies -ynh_remove_app_dependencies +# Remove the service from the list of services known by Yunohost (added from `yunohost service add`) +if ynh_exec_warn_less yunohost service status $app >/dev/null +then + ynh_script_progression --message="Removing $app service integration..." --weight=1 + yunohost service remove $app +fi #================================================= # REMOVE APP MAIN DIR From b388c4f0884ebd8a9d49c23b39b57478c106ea02 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 18:47:23 +0100 Subject: [PATCH 04/59] Add README_fr --- README.md | 2 +- README_fr.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 README_fr.md diff --git a/README.md b/README.md index 66ea36b..b7a1033 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Grocy for YunoHost [![Integration level](https://dash.yunohost.org/integration/grocy.svg)](https://dash.yunohost.org/appci/app/grocy) ![](https://ci-apps.yunohost.org/ci/badges/grocy.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/grocy.maintain.svg) -[![Install Mantis with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=grocy) +[![Install Grocy with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=grocy) *[Lire ce readme en français.](./README_fr.md)* diff --git a/README_fr.md b/README_fr.md new file mode 100644 index 0000000..3287b27 --- /dev/null +++ b/README_fr.md @@ -0,0 +1,73 @@ +# Grocy pour YunoHost + +[![Niveau d'intégration](https://dash.yunohost.org/integration/grocy.svg)](https://dash.yunohost.org/appci/app/grocy) ![](https://ci-apps.yunohost.org/ci/badges/grocy.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/grocy.maintain.svg) +[![Install Grocy with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=grocy) + +*[Read this readme in english.](./README.md)* + +> *Ce package vous permet d'installer Grocy rapidement et simplement sur un serveur YunoHost. +Si vous n'avez pas YunoHost, consultez [le guide](https://yunohost.org/#/install) pour apprendre comment l'installer.* + +## Vue d'ensemble +Grocy is a web-based self-hosted groceries & household management solution for your home. + +**Version incluse :** 3.0.0 + +## Captures d'écran + +![](https://grocy.info/img/grocy-desktop-en.png) + +## Démo + +* [Démo officielle](https://en.demo.grocy.info/stockoverview) + +## Configuration + + Default login + user: **admin** + password: **admin** + +## Documentation + + * Documentation officielle : Lien vers la documentation officielle de cette application. + * Documentation YunoHost : Si une documentation spécifique est nécessaire, n'hésitez pas à contribuer. + +## Caractéristiques spécifiques YunoHost + +#### Support multi-utilisateur + +* L'authentification LDAP et HTTP est-elle prise en charge ? +* L'application peut-elle être utilisée par plusieurs utilisateurs ? + +#### Supported architectures + +* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/grocy%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/grocy/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/grocy%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/grocy/) + +## Limitations + +* Limitations connues. + +## Informations additionnelles + +* Autres informations que vous souhaitez ajouter sur cette application. + +## Liens + + * Signaler un bug : https://github.com/YunoHost-Apps/grocy_ynh/issues + * Site de l'application : https://grocy.info/ + * Dépôt de l'application principale : https://github.com/grocy/grocy + * Site web YunoHost : https://yunohost.org/ + +--- + +## Informations pour les développeurs + +Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/grocy_ynh/tree/testing). + +Pour essayer la branche testing, procédez comme suit. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/grocy_ynh/tree/testing --debug +or +sudo yunohost app upgrade grocy -u https://github.com/YunoHost-Apps/grocy_ynh/tree/testing --debug +``` From 8466f412ba3571b6a878dd6ec50a939b526802af Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 18:53:38 +0100 Subject: [PATCH 05/59] Fix --- conf/nginx.conf | 6 ++++-- scripts/upgrade | 16 ++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 0ab9560..2e4bbf2 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,4 +1,5 @@ -location / { +#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; +location __PATH__/ { # Path to source alias __FINALPATH__/public/ ; @@ -10,7 +11,8 @@ location / { index index.php; - try_files $uri __PATH__/index.php; + #try_files $uri __PATH__/index.php; + try_files $uri __PATH__/index.php$is_args$query_string; location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; diff --git a/scripts/upgrade b/scripts/upgrade index 3a27844..d485a90 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -21,7 +21,7 @@ path_url=$(ynh_app_setting_get --app=$app --key=path) is_public=$(ynh_app_setting_get --app=$app --key=is_public) final_path=$(ynh_app_setting_get --app=$app --key=final_path) language=$(ynh_app_setting_get --app=$app --key=language) -phpversion=$(ynh_app_setting_get --app="$app" --key=phpversion) +phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) #================================================= # CHECK VERSION @@ -82,13 +82,6 @@ ynh_script_progression --message="Making sure dedicated system user exists..." - # Create a dedicated user (if not existing) ynh_system_user_create --username=$app -#================================================= -# SECURE FILES AND DIRECTORIES -#================================================= - -# Set permissions to app files -chown -R $app: $final_path - #================================================= # PHP-FPM CONFIGURATION #================================================= @@ -97,6 +90,13 @@ ynh_script_progression --message="Upgrading PHP-FPM configuration..." --weight=1 # Create a dedicated php-fpm config ynh_add_fpm_config --package="$extra_php_dependencies" +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +# Set permissions to app files +chown -R $app: $final_path + #================================================= # MODIFY A CONFIG FILE #================================================= From e3a52e3181bad26e5e0f48204b40ba464a3a2029 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 18:55:12 +0100 Subject: [PATCH 06/59] Update nginx.conf --- conf/nginx.conf | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 2e4bbf2..8cb9e61 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,5 +1,4 @@ -#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; -location __PATH__/ { +location / { # Path to source alias __FINALPATH__/public/ ; @@ -11,9 +10,8 @@ location __PATH__/ { index index.php; - #try_files $uri __PATH__/index.php; - try_files $uri __PATH__/index.php$is_args$query_string; - + try_files $uri __PATH__/index.php; + location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_pass unix:/var/run/php/php__PHPVERSION__-fpm-__NAME__.sock; From 0f421c514505a4f445e43440e37c0c61da085286 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 19:05:38 +0100 Subject: [PATCH 07/59] Fix --- scripts/install | 1 + scripts/restore | 1 + scripts/upgrade | 18 ++++++++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/scripts/install b/scripts/install index 340ef04..845e4c1 100644 --- a/scripts/install +++ b/scripts/install @@ -104,6 +104,7 @@ ynh_store_file_checksum --file="$final_path/data/config.php" # Set permissions to app files chown -R $app: $final_path +chmod -R 755 $final_path/data #================================================= # INTEGRATE SERVICE IN YUNOHOST diff --git a/scripts/restore b/scripts/restore index 310e62d..ae4d2e8 100644 --- a/scripts/restore +++ b/scripts/restore @@ -77,6 +77,7 @@ ynh_add_fpm_config --package="$extra_php_dependencies" # Restore permissions on app files chown -R $app: $final_path +chmod -R 755 $final_path/data #================================================= # INTEGRATE SERVICE IN YUNOHOST diff --git a/scripts/upgrade b/scripts/upgrade index d485a90..3c4c2b2 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -62,8 +62,22 @@ if [ "$upgrade_type" == "UPGRADE_APP" ] then ynh_script_progression --message="Upgrading source files..." --weight=5 - # Download, check integrity, uncompress and patch the source from app.src - ynh_setup_source --dest_dir="$final_path" + tmpdir="$(mktemp -d)" + + # Backup the config file in the temp dir + cp -a "$final_path/data" "$tmpdir/data" + + # Remove the app directory securely + ynh_secure_remove --file="$final_path" + + # Download, check integrity, uncompress and patch the source from app.src + ynh_setup_source --dest_dir="$final_path" + + # Copy the admin saved settings from tmp directory to final path + cp -a "$tmpdir/data" "$final_path/config/data" + + # Remove the tmp directory securely + ynh_secure_remove --file="$tmpdir" fi #================================================= From c899441995ade218d8833d94765d7a6ffbb09c4e Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 19:06:59 +0100 Subject: [PATCH 08/59] Update manifest.json --- manifest.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/manifest.json b/manifest.json index 9675e40..44e66c0 100644 --- a/manifest.json +++ b/manifest.json @@ -58,6 +58,10 @@ "en": "Is it a public site?", "fr": "Est-ce un site public ?" }, + "help": { + "en": "If enabled, Grocy will be accessible by people who do not have an account. This can be changed later via the webadmin.", + "fr": "Si cette case est cochée, Grocy sera accessible aux personnes n’ayant pas de compte. Vous pourrez changer ceci plus tard via la webadmin." + }, "default": true } ] From ea59adff9ff9cd86651a6ae9861a642c8f702759 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 19:12:19 +0100 Subject: [PATCH 09/59] Update upgrade --- scripts/upgrade | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/upgrade b/scripts/upgrade index 3c4c2b2..8d7e7b6 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -62,6 +62,15 @@ if [ "$upgrade_type" == "UPGRADE_APP" ] then ynh_script_progression --message="Upgrading source files..." --weight=5 + if [[ ! -f "$final_path/data" ]]; then + # config.ini.php is only created during the post-install process... + # it is therefore not present when the CI tests are carried out... + # This condition is only for CI test to go through the upgrade process + ynh_secure_remove --file="$final_path" + # Download, check integrity, uncompress and patch the source from app.src + ynh_setup_source --dest_dir="$final_path" + else + tmpdir="$(mktemp -d)" # Backup the config file in the temp dir @@ -110,14 +119,7 @@ ynh_add_fpm_config --package="$extra_php_dependencies" # Set permissions to app files chown -R $app: $final_path - -#================================================= -# MODIFY A CONFIG FILE -#================================================= - -cp -a ../conf/config-dist.php "$final_path/config-dist.php" - -ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$final_path/data/config.php" +chmod -R 755 $final_path/data #================================================= # INTEGRATE SERVICE IN YUNOHOST From 7691d27aa39cd01ba342b8cb065e4454ec98d927 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 19:18:26 +0100 Subject: [PATCH 10/59] Update upgrade --- scripts/upgrade | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/scripts/upgrade b/scripts/upgrade index 8d7e7b6..748ec26 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -62,31 +62,11 @@ if [ "$upgrade_type" == "UPGRADE_APP" ] then ynh_script_progression --message="Upgrading source files..." --weight=5 - if [[ ! -f "$final_path/data" ]]; then - # config.ini.php is only created during the post-install process... - # it is therefore not present when the CI tests are carried out... - # This condition is only for CI test to go through the upgrade process - ynh_secure_remove --file="$final_path" - # Download, check integrity, uncompress and patch the source from app.src - ynh_setup_source --dest_dir="$final_path" - else - - tmpdir="$(mktemp -d)" - - # Backup the config file in the temp dir - cp -a "$final_path/data" "$tmpdir/data" - # Remove the app directory securely ynh_secure_remove --file="$final_path" # Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$final_path" - - # Copy the admin saved settings from tmp directory to final path - cp -a "$tmpdir/data" "$final_path/config/data" - - # Remove the tmp directory securely - ynh_secure_remove --file="$tmpdir" fi #================================================= @@ -113,6 +93,15 @@ ynh_script_progression --message="Upgrading PHP-FPM configuration..." --weight=1 # Create a dedicated php-fpm config ynh_add_fpm_config --package="$extra_php_dependencies" +#================================================= +# MODIFY A CONFIG FILE +#================================================= + +cp -a ../conf/config-dist.php "$final_path/data/config.php" + +ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$final_path/data/config.php" + + #================================================= # SECURE FILES AND DIRECTORIES #================================================= From b3e8ff96a3ae05b3ba4f2ff325ca6b06428f1574 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 19:29:43 +0100 Subject: [PATCH 11/59] Remove service --- scripts/install | 7 ------- scripts/remove | 13 ------------- scripts/restore | 7 ------- scripts/upgrade | 7 ------- 4 files changed, 34 deletions(-) diff --git a/scripts/install b/scripts/install index 845e4c1..f5646f2 100644 --- a/scripts/install +++ b/scripts/install @@ -106,13 +106,6 @@ ynh_store_file_checksum --file="$final_path/data/config.php" chown -R $app: $final_path chmod -R 755 $final_path/data -#================================================= -# INTEGRATE SERVICE IN YUNOHOST -#================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 - -yunohost service add $app --description="Self-hosted groceries & household management" --log="/var/log/$app/$app.log" - #================================================= # SETUP SSOWAT #================================================= diff --git a/scripts/remove b/scripts/remove index 10b1f03..7ee6368 100644 --- a/scripts/remove +++ b/scripts/remove @@ -19,19 +19,6 @@ app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) final_path=$(ynh_app_setting_get --app=$app --key=final_path) -#================================================= -# STANDARD REMOVE -#================================================= -# STOP AND REMOVE SERVICE -#================================================= - -# Remove the service from the list of services known by Yunohost (added from `yunohost service add`) -if ynh_exec_warn_less yunohost service status $app >/dev/null -then - ynh_script_progression --message="Removing $app service integration..." --weight=1 - yunohost service remove $app -fi - #================================================= # REMOVE APP MAIN DIR #================================================= diff --git a/scripts/restore b/scripts/restore index ae4d2e8..afccc7e 100644 --- a/scripts/restore +++ b/scripts/restore @@ -79,13 +79,6 @@ ynh_add_fpm_config --package="$extra_php_dependencies" chown -R $app: $final_path chmod -R 755 $final_path/data -#================================================= -# INTEGRATE SERVICE IN YUNOHOST -#================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 - -yunohost service add $app --description="Self-hosted groceries & household management" --log="/var/log/$app/$app.log" - #================================================= # GENERIC FINALIZATION #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index 748ec26..210ff0d 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -110,13 +110,6 @@ ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" -- chown -R $app: $final_path chmod -R 755 $final_path/data -#================================================= -# INTEGRATE SERVICE IN YUNOHOST -#================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 - -yunohost service add $app --description="Self-hosted groceries & household management" --log="/var/log/$app/$app.log" - #================================================= # RELOAD NGINX #================================================= From 27891e4e8be3e42ca80950eb61298ebf013357ac Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 19:38:35 +0100 Subject: [PATCH 12/59] Update upgrade --- scripts/upgrade | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/upgrade b/scripts/upgrade index 210ff0d..ad4ccf2 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -62,11 +62,23 @@ if [ "$upgrade_type" == "UPGRADE_APP" ] then ynh_script_progression --message="Upgrading source files..." --weight=5 + # Create a temporary directory + tmpdir="$(mktemp -d)" + + # Backup the config file in the temp dir + cp -R "$final_path/data" "$tmpdir/data" + # Remove the app directory securely ynh_secure_remove --file="$final_path" # Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$final_path" + + # Copy the admin saved settings from tmp directory to final path + cp -RT "$tmpdir/data" "$final_path/data" + + # Remove the tmp directory securely + ynh_secure_remove --file="$tmpdir" fi #================================================= From c3fe4f367cac9da6882b4097e4c18e26160ee09c Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 26 Dec 2020 20:02:52 +0100 Subject: [PATCH 13/59] Update config-dist.php --- conf/config-dist.php | 191 ++++++++++++++++++++++++------------------- 1 file changed, 109 insertions(+), 82 deletions(-) diff --git a/conf/config-dist.php b/conf/config-dist.php index abc0b00..143cea9 100644 --- a/conf/config-dist.php +++ b/conf/config-dist.php @@ -1,140 +1,169 @@ BASE_PATH = /grocy +// When running grocy in a subdirectory, this should be set to the relative path, otherwise empty +// It needs to be set to the part (of the URL) after the document root, +// if URL rewriting is disabled, including index.php +// Example with URL Rewriting support: +// Root URL = https://example.com/grocy +// => BASE_PATH = /grocy +// Example without URL Rewriting support: +// Root URL = https://example.com/grocy/public/index.php/ +// => BASE_PATH = /grocy/public/index.php Setting('BASE_PATH', ''); -# The base url of your installation, -# should be just "/" when running directly under the root of a (sub)domain -# or for example "https://example.com/grocy" when using a subdirectory +// The base URL of your installation, +// should be just "/" when running directly under the root of a (sub)domain +// or for example "https://example.com/grocy" when using a subdirectory Setting('BASE_URL', '/'); -# The plugin to use for external barcode lookups, -# must be the filename without .php extension and must be located in /data/plugins, -# see /data/plugins/DemoBarcodeLookupPlugin.php for an example implementation +// The plugin to use for external barcode lookups, +// must be the filename without .php extension and must be located in /data/plugins, +// see /data/plugins/DemoBarcodeLookupPlugin.php for an example implementation Setting('STOCK_BARCODE_LOOKUP_PLUGIN', 'DemoBarcodeLookupPlugin'); -# If, however, your webserver does not support URL rewriting, set this to true +// If, however, your webserver does not support URL rewriting, set this to true Setting('DISABLE_URL_REWRITING', false); -# Specify an custom homepage if desired - by default the homepage will be set to the stock overview, -# this needs to be one of the following values: -# stock, shoppinglist, recipes, chores, tasks, batteries, equipment, calendar, mealplan +// Specify an custom homepage if desired - by default the homepage will be set to the stock overview page, +// this needs to be one of the following values: +// stock, shoppinglist, recipes, chores, tasks, batteries, equipment, calendar, mealplan Setting('ENTRY_PAGE', 'stock'); -# Set this to true if you want to disable authentication / the login screen, -# places where user context is needed will then use the default (first existing) user +// Set this to true if you want to disable authentication / the login screen, +// places where user context is needed will then use the default (first existing) user Setting('DISABLE_AUTH', false); -# Set this to true if you want to disable the ability to scan a barcode via the device camera (Browser API) +// Either "Grocy\Middleware\DefaultAuthMiddleware", "Grocy\Middleware\ReverseProxyAuthMiddleware" +// or any class that implements Grocy\Middleware\AuthMiddleware +Setting('AUTH_CLASS', 'Grocy\Middleware\DefaultAuthMiddleware'); + +// When using ReverseProxyAuthMiddleware, +// the name of the HTTP header which your reverse proxy uses to pass the username (on successful authentication) +Setting('REVERSE_PROXY_AUTH_HEADER', 'REMOTE_USER'); + +// When using LdapAuthMiddleware +Setting('LDAP_DOMAIN', 'local'); // Example value "local" +Setting('LDAP_ADDRESS', 'ldap://127.0.0.1:389'); // Example value "ldap://vm-dc2019.local.berrnd.net" +Setting('LDAP_BASE_DN', 'ou=users,dc=yunohost,dc=org'); // Example value "OU=OU_Users,DC=local,DC=berrnd,DC=net" + +// Set this to true if you want to disable the ability to scan a barcode via the device camera (Browser API) Setting('DISABLE_BROWSER_BARCODE_CAMERA_SCANNING', false); -# Set this if you want to have a different start day for the weekly meal plan view, -# leave empty to use CALENDAR_FIRST_DAY_OF_WEEK (see above) -# Needs to be a number where Sunday = 0, Monday = 1 and so forth +// Set this if you want to have a different start day for the weekly meal plan view, +// leave empty to use CALENDAR_FIRST_DAY_OF_WEEK (see above) +// Needs to be a number where Sunday = 0, Monday = 1 and so forth Setting('MEAL_PLAN_FIRST_DAY_OF_WEEK', ''); +// Default permissions for new users +// the array needs to contain the technical/constant names +// see the file controllers/Users/User.php for possible values +Setting('DEFAULT_PERMISSIONS', ['ADMIN']); -# Default user settings -# These settings can be changed per user, here the defaults -# are defined which are used when the user has not changed the setting so far +// Default user settings +// These settings can be changed per user, here the defaults +// are defined which are used when the user has not changed the setting so far -# Night mode related +// Night mode related DefaultUserSetting('night_mode_enabled', false); // If night mode is enabled always DefaultUserSetting('auto_night_mode_enabled', false); // If night mode is enabled automatically when inside a given time range (see the two settings below) -DefaultUserSetting('auto_night_mode_time_range_from', "20:00"); // Format HH:mm -DefaultUserSetting('auto_night_mode_time_range_to', "07:00"); // Format HH:mm +DefaultUserSetting('auto_night_mode_time_range_from', '20:00'); // Format HH:mm +DefaultUserSetting('auto_night_mode_time_range_to', '07:00'); // Format HH:mm DefaultUserSetting('auto_night_mode_time_range_goes_over_midnight', true); // If the time range above goes over midnight DefaultUserSetting('currently_inside_night_mode_range', false); // If we're currently inside of night mode time range (this is not user configurable, but stored as a user setting because it's evaluated client side to be able to use the client time instead of the maybe different server time) -# Keep screen on settings +// Keep screen on settings DefaultUserSetting('keep_screen_on', false); // Keep the screen always on DefaultUserSetting('keep_screen_on_when_fullscreen_card', false); // Keep the screen on when a "fullscreen-card" is displayed -# Stock settings +// Stock settings DefaultUserSetting('product_presets_location_id', -1); // Default location id for new products (-1 means no location is preset) DefaultUserSetting('product_presets_product_group_id', -1); // Default product group id for new products (-1 means no product group is preset) DefaultUserSetting('product_presets_qu_id', -1); // Default quantity unit id for new products (-1 means no quantity unit is preset) -DefaultUserSetting('stock_expring_soon_days', 5); +DefaultUserSetting('stock_decimal_places_amounts', 4); // Default decimal places allowed for amounts +DefaultUserSetting('stock_decimal_places_prices', 2); // Default decimal places allowed for prices +DefaultUserSetting('stock_due_soon_days', 5); DefaultUserSetting('stock_default_purchase_amount', 0); DefaultUserSetting('stock_default_consume_amount', 1); +DefaultUserSetting('stock_default_consume_amount_use_quick_consume_amount', false); DefaultUserSetting('scan_mode_consume_enabled', false); DefaultUserSetting('scan_mode_purchase_enabled', false); DefaultUserSetting('show_icon_on_stock_overview_page_when_product_is_on_shopping_list', true); +DefaultUserSetting('show_purchased_date_on_purchase', false); // Wheter the purchased date should be editable on purchase (defaults to today otherwise) +DefaultUserSetting('show_warning_on_purchase_when_due_date_is_earlier_than_next', true); // Show a warning on purchase when the due date of the purchased product is earlier than the next due date in stock -# Shopping list settings -DefaultUserSetting('shopping_list_to_stock_workflow_auto_submit_when_prefilled', false); // Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default best before days" set +// Shopping list settings +DefaultUserSetting('shopping_list_to_stock_workflow_auto_submit_when_prefilled', false); // Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default due days" set DefaultUserSetting('shopping_list_show_calendar', false); -DefaultUserSetting('shopping_list_disable_auto_compact_view_on_mobile', false); -# Recipe settings +// Recipe settings DefaultUserSetting('recipe_ingredients_group_by_product_group', false); // Group recipe ingredients by their product group -# Chores settings +// Chores settings DefaultUserSetting('chores_due_soon_days', 5); -# Batteries settings +// Batteries settings DefaultUserSetting('batteries_due_soon_days', 5); -# Tasks settings +// Tasks settings DefaultUserSetting('tasks_due_soon_days', 5); -# If the page should be automatically reloaded when there was -# an external change +// If the page should be automatically reloaded when there was +// an external change DefaultUserSetting('auto_reload_on_db_change', true); -# Show a clock in the header next to the logo or not +// Show a clock in the header next to the logo or not DefaultUserSetting('show_clock_in_header', false); -# Component configuration +// Component configuration for Quagga2 - read https://github.com/ericblade/quagga2#configobject for details +// Below is a generic good configuration, +// for an iPhone 7 Plus, halfsample = true, patchsize = small, frequency = 5 yields very good results DefaultUserSetting('quagga2_numofworkers', 4); +DefaultUserSetting('quagga2_halfsample', false); +DefaultUserSetting('quagga2_patchsize', 'medium'); +DefaultUserSetting('quagga2_frequency', 10); +DefaultUserSetting('quagga2_debug', true); - -# Feature flags -# grocy was initially about "stock management for your household", many other things -# came and still come by, because they are useful - here you can disable the parts -# which you don't need to have a less cluttered UI -# (set the setting to "false" to disable the corresponding part, which should be self explanatory) +// Feature flags +// grocy was initially about "stock management for your household", many other things +// came and still come by, because they are useful - here you can disable the parts +// which you don't need to have a less cluttered UI +// (set the setting to "false" to disable the corresponding part, which should be self explanatory) Setting('FEATURE_FLAG_STOCK', true); Setting('FEATURE_FLAG_SHOPPINGLIST', true); Setting('FEATURE_FLAG_RECIPES', true); @@ -144,18 +173,16 @@ Setting('FEATURE_FLAG_BATTERIES', true); Setting('FEATURE_FLAG_EQUIPMENT', true); Setting('FEATURE_FLAG_CALENDAR', true); - -# Sub feature flags +// Sub feature flags Setting('FEATURE_FLAG_STOCK_PRICE_TRACKING', true); Setting('FEATURE_FLAG_STOCK_LOCATION_TRACKING', true); Setting('FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING', true); Setting('FEATURE_FLAG_STOCK_PRODUCT_OPENED_TRACKING', true); Setting('FEATURE_FLAG_STOCK_PRODUCT_FREEZING', true); -Setting('FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_FIELD_NUMBER_PAD', true); // Activate the number pad in best-before-date fields on (supported) mobile browsers +Setting('FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_FIELD_NUMBER_PAD', true); // Activate the number pad in due date fields on (supported) mobile browsers Setting('FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS', true); Setting('FEATURE_FLAG_CHORES_ASSIGNMENTS', true); - -# Feature settings -Setting('FEATURE_SETTING_STOCK_COUNT_OPENED_PRODUCTS_AGAINST_MINIMUM_STOCK_AMOUNT', true); // When set to false, opened products will not be considered for minimum stock amounts -Setting('FEATURE_FLAG_AUTO_TORCH_ON_WITH_CAMERA', true); // Enables the torch automaticaly in every camera barcode scanner. +// Feature settings +Setting('FEATURE_SETTING_STOCK_COUNT_OPENED_PRODUCTS_AGAINST_MINIMUM_STOCK_AMOUNT', true); // When set to true, opened items will be counted as missing for calculating if a product is below its minimum stock amount +Setting('FEATURE_FLAG_AUTO_TORCH_ON_WITH_CAMERA', true); // Enables the torch automaticaly (if the device has one) From fcc1beffbfa2dbfbd189a8013f7dc8321e950d82 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 22 Jan 2021 09:23:21 +0100 Subject: [PATCH 14/59] Remove path --- README.md | 2 +- README_fr.md | 6 +----- manifest.json | 12 +----------- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index b7a1033..7c4a257 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Grocy is a web-based self-hosted groceries & household management solution for y ## Limitations -* Any known limitations. +:warning: For now, Grocy must be installed in a root domain or subdirectory. ## Additional information diff --git a/README_fr.md b/README_fr.md index 3287b27..46f67ce 100644 --- a/README_fr.md +++ b/README_fr.md @@ -23,10 +23,6 @@ Grocy is a web-based self-hosted groceries & household management solution for y ## Configuration - Default login - user: **admin** - password: **admin** - ## Documentation * Documentation officielle : Lien vers la documentation officielle de cette application. @@ -46,7 +42,7 @@ Grocy is a web-based self-hosted groceries & household management solution for y ## Limitations -* Limitations connues. +:warning: Pour l'instant, Grocy doit être installé dans un domaine racine ou un sous-dpmaine. ## Informations additionnelles diff --git a/manifest.json b/manifest.json index 44e66c0..84584d6 100644 --- a/manifest.json +++ b/manifest.json @@ -29,17 +29,7 @@ "en": "Choose a domain name for Grocy", "fr": "Choisissez un nom de domaine pour Grocy" }, - "example": "example.com" - }, - { - "name": "path", - "type": "path", - "ask": { - "en": "Choose a path for Grocy", - "fr": "Choisissez un chemin pour Grocy" - }, - "example": "/", - "default": "/" + "example": "grocy.example.com" }, { "name": "language", From a277da304caca13607dfa2292e16afd5f1722d14 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 22 Jan 2021 09:28:25 +0100 Subject: [PATCH 15/59] Update README_fr.md --- README_fr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_fr.md b/README_fr.md index 9205740..93ee4a0 100644 --- a/README_fr.md +++ b/README_fr.md @@ -42,7 +42,7 @@ Grocy is a web-based self-hosted groceries & household management solution for y ## Limitations -:warning: Pour l'instant, Grocy doit être installé dans un domaine racine ou un sous-dpmaine. +:warning: Pour l'instant, Grocy doit être installé dans un domaine racine ou un sous-domaine. ## Informations additionnelles From b36b834ec75e2aefcb401c16eb2ca179a75fa851 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 22 Jan 2021 10:17:48 +0100 Subject: [PATCH 16/59] Update README_fr.md --- README_fr.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README_fr.md b/README_fr.md index 93ee4a0..84993ce 100644 --- a/README_fr.md +++ b/README_fr.md @@ -23,6 +23,10 @@ Grocy is a web-based self-hosted groceries & household management solution for y ## Configuration +Connexion par défaut + utilisateur : **admin** + mot de passe : **admin** + ## Documentation * Documentation officielle : Lien vers la documentation officielle de cette application. From 31f43b6f507179ebb88b720ad42e67a6c568db95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Fri, 22 Jan 2021 10:32:28 +0100 Subject: [PATCH 17/59] Upgrade to 3.0.1 (#4) * Upgrade to 3.0.1 --- README.md | 4 ++-- README_fr.md | 2 +- conf/app.src | 4 ++-- manifest.json | 6 +++--- scripts/_common.sh | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7c4a257..2230b78 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in ## Overview Grocy is a web-based self-hosted groceries & household management solution for your home. -**Shipped version:** 3.0.0 +**Shipped version:** 3.0.1 ## Screenshots @@ -24,7 +24,7 @@ Grocy is a web-based self-hosted groceries & household management solution for y ## Configuration Default login - user: **admin** + user: **admin** password: **admin** ## Documentation diff --git a/README_fr.md b/README_fr.md index 84993ce..3bdc065 100644 --- a/README_fr.md +++ b/README_fr.md @@ -11,7 +11,7 @@ Si vous n'avez pas YunoHost, consultez [le guide](https://yunohost.org/#/install ## Vue d'ensemble Grocy is a web-based self-hosted groceries & household management solution for your home. -**Version incluse :** 3.0.0 +**Version incluse :** 3.0.1 ## Captures d'écran diff --git a/conf/app.src b/conf/app.src index 0174290..2afc137 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.0.0/grocy_3.0.0.zip -SOURCE_SUM=3bb0e4b1f03de481ef2c9c91ad61bc88409c5140ec3adcad77bf24a0d65d4331 +SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.0.1/grocy_3.0.1.zip +SOURCE_SUM=623c6fd0b70b36da58b389ed05a9e8f4d531c1d5a01797ad03f33a85457339af SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=zip SOURCE_IN_SUBDIR=false diff --git a/manifest.json b/manifest.json index 5b039e2..918e96a 100644 --- a/manifest.json +++ b/manifest.json @@ -3,10 +3,10 @@ "id": "grocy", "packaging_format": 1, "description": { - "en": "Web-based self-hosted groceries & household management solution for your home", - "fr": "Solution Web auto-hébergée de gestion d'épicerie et de gestion de la maison" + "en": "Web-based groceries & household management solution for your home", + "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.0.0~ynh2", + "version": "3.0.1~ynh1", "url": "https://github.com/grocy/grocy", "license": "MIT", "maintainer": { diff --git a/scripts/_common.sh b/scripts/_common.sh index 66e31fe..58131e6 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -4,7 +4,7 @@ # COMMON VARIABLES #================================================= -YNH_PHP_VERSION="7.3" +YNH_PHP_VERSION="7.4" extra_php_dependencies="php${YNH_PHP_VERSION}-fileinfo php${YNH_PHP_VERSION}-sqlite3 php${YNH_PHP_VERSION}-gd" From 889d399e985f4292021e6d1cedd6dae48f9472c6 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 25 Jan 2021 10:18:00 +0100 Subject: [PATCH 19/59] Update manifest.json --- manifest.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 918e96a..a658f0d 100644 --- a/manifest.json +++ b/manifest.json @@ -19,7 +19,7 @@ "multi_instance": true, "services": [ "nginx", - "php7.0-fpm" + "php7.3-fpm" ], "arguments": { "install": [{ @@ -29,6 +29,10 @@ "en": "Choose a domain name for Grocy", "fr": "Choisissez un nom de domaine pour Grocy" }, + "help": { + "en": "Grocy needs to be installed in its own root domain or subdomain.", + "fr": "Grocy doit être installé dans son propre domaine racine ou sous-domaine." + }, "example": "grocy.example.com" }, { From ebcc8c105166b6c9864b42cd124379f20a81347e Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 20 Feb 2021 00:06:43 +0100 Subject: [PATCH 20/59] add pull request --- pull_request_template.md | 16 ++++++++++++++++ scripts/install | 4 ++-- scripts/upgrade | 7 +++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 pull_request_template.md diff --git a/pull_request_template.md b/pull_request_template.md new file mode 100644 index 0000000..6c28fc5 --- /dev/null +++ b/pull_request_template.md @@ -0,0 +1,16 @@ +## Problem +- *Description of why you made this PR* + +## Solution +- *And how do you fix that problem* + +## PR Status +- [ ] Code finished. +- [ ] Tested with Package_check. +- [ ] Fix or enhancement tested. +- [ ] Upgrade from last version tested. +- [ ] Can be reviewed and tested. + +## Package_check results +--- +* An automatic package_check will be launch at https://ci-apps-dev.yunohost.org/, when you add a specific comment to your Pull Request: "!testme", "!gogogadgetoci" or "By the power of systemd, I invoke The Great App CI to test this Pull Request!"* diff --git a/scripts/install b/scripts/install index f5646f2..adbe298 100644 --- a/scripts/install +++ b/scripts/install @@ -109,12 +109,12 @@ chmod -R 755 $final_path/data #================================================= # SETUP SSOWAT #================================================= -ynh_script_progression --message="Configuring SSOwat..." --weight=1 +ynh_script_progression --message="Configuring permissions..." --weight=1 # Make app public if necessary or protect it if [ $is_public -eq 1 ] then - ynh_permission_update --permission "main" --add "visitors" + ynh_permission_update --permission="main" --add="visitors" fi #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index ad4ccf2..4ab54e8 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -40,6 +40,13 @@ if [ -z "$final_path" ]; then ynh_app_setting_set --app=$app --key=final_path --value=$final_path fi +# Cleaning legacy permissions +if ynh_legacy_permissions_exists; then + ynh_legacy_permissions_delete_all + + ynh_app_setting_delete --app=$app --key=is_public +fi + #================================================= # BACKUP BEFORE UPGRADE THEN ACTIVE TRAP #================================================= From 499d0a759dfd8b0722e0500a1fd5a580c301d763 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 14 Mar 2021 23:56:45 +0100 Subject: [PATCH 21/59] Cleaning up --- scripts/install | 1 - scripts/upgrade | 1 - 2 files changed, 2 deletions(-) diff --git a/scripts/install b/scripts/install index adbe298..c0f0fb2 100644 --- a/scripts/install +++ b/scripts/install @@ -45,7 +45,6 @@ ynh_script_progression --message="Storing installation settings..." --weight=1 ynh_app_setting_set --app=$app --key=domain --value=$domain ynh_app_setting_set --app=$app --key=path --value=$path_url -ynh_app_setting_set --app=$app --key=is_public --value=$is_public ynh_app_setting_set --app=$app --key=language --value=$language #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index 4ab54e8..b233f3b 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -18,7 +18,6 @@ app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) path_url=$(ynh_app_setting_get --app=$app --key=path) -is_public=$(ynh_app_setting_get --app=$app --key=is_public) final_path=$(ynh_app_setting_get --app=$app --key=final_path) language=$(ynh_app_setting_get --app=$app --key=language) phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) From f6e24cd9530c87321212040c6bafde48b385058b Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 15 Mar 2021 08:51:30 +0100 Subject: [PATCH 22/59] Update manifest.json --- manifest.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/manifest.json b/manifest.json index a658f0d..25f3e77 100644 --- a/manifest.json +++ b/manifest.json @@ -25,10 +25,6 @@ "install": [{ "name": "domain", "type": "domain", - "ask": { - "en": "Choose a domain name for Grocy", - "fr": "Choisissez un nom de domaine pour Grocy" - }, "help": { "en": "Grocy needs to be installed in its own root domain or subdomain.", "fr": "Grocy doit être installé dans son propre domaine racine ou sous-domaine." @@ -48,10 +44,6 @@ { "name": "is_public", "type": "boolean", - "ask": { - "en": "Is it a public site?", - "fr": "Est-ce un site public ?" - }, "help": { "en": "If enabled, Grocy will be accessible by people who do not have an account. This can be changed later via the webadmin.", "fr": "Si cette case est cochée, Grocy sera accessible aux personnes n’ayant pas de compte. Vous pourrez changer ceci plus tard via la webadmin." From a5b51aeabdfe8ec5b345825920ae409467e70900 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 19 Mar 2021 18:23:36 +0100 Subject: [PATCH 23/59] Cleaning up --- README.md | 4 ++-- README_fr.md | 4 ++-- manifest.json | 10 +--------- scripts/install | 4 +--- scripts/upgrade | 5 +---- 5 files changed, 7 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 2230b78..210e8df 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ Grocy is a web-based self-hosted groceries & household management solution for y ## Configuration Default login - user: **admin** - password: **admin** + * user: **admin** + * password: **admin** ## Documentation diff --git a/README_fr.md b/README_fr.md index 3bdc065..08f09ca 100644 --- a/README_fr.md +++ b/README_fr.md @@ -24,8 +24,8 @@ Grocy is a web-based self-hosted groceries & household management solution for y ## Configuration Connexion par défaut - utilisateur : **admin** - mot de passe : **admin** + * utilisateur : **admin** + * mot de passe : **admin** ## Documentation diff --git a/manifest.json b/manifest.json index 25f3e77..72be1a0 100644 --- a/manifest.json +++ b/manifest.json @@ -14,7 +14,7 @@ "email": "" }, "requirements": { - "yunohost": ">= 4.0.0" + "yunohost": ">= 4.1.7" }, "multi_instance": true, "services": [ @@ -25,10 +25,6 @@ "install": [{ "name": "domain", "type": "domain", - "help": { - "en": "Grocy needs to be installed in its own root domain or subdomain.", - "fr": "Grocy doit être installé dans son propre domaine racine ou sous-domaine." - }, "example": "grocy.example.com" }, { @@ -44,10 +40,6 @@ { "name": "is_public", "type": "boolean", - "help": { - "en": "If enabled, Grocy will be accessible by people who do not have an account. This can be changed later via the webadmin.", - "fr": "Si cette case est cochée, Grocy sera accessible aux personnes n’ayant pas de compte. Vous pourrez changer ceci plus tard via la webadmin." - }, "default": true } ] diff --git a/scripts/install b/scripts/install index c0f0fb2..0e41654 100644 --- a/scripts/install +++ b/scripts/install @@ -85,9 +85,7 @@ phpversion=$(ynh_app_setting_get --app="$app" --key=phpversion) # MODIFY A CONFIG FILE #================================================= -cp -a ../conf/config-dist.php "$final_path/data/config.php" - -ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$final_path/data/config.php" +ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/data/config.php" #================================================= # STORE THE CONFIG FILE CHECKSUM diff --git a/scripts/upgrade b/scripts/upgrade index b233f3b..b67a01c 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -115,10 +115,7 @@ ynh_add_fpm_config --package="$extra_php_dependencies" # MODIFY A CONFIG FILE #================================================= -cp -a ../conf/config-dist.php "$final_path/data/config.php" - -ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$final_path/data/config.php" - +ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/data/config.php" #================================================= # SECURE FILES AND DIRECTORIES From 179d8ea133fcbf3c57a284be03ea347360c70d05 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Thu, 25 Mar 2021 08:38:52 +0100 Subject: [PATCH 24/59] Fix --- scripts/install | 1 + scripts/restore | 1 + scripts/upgrade | 1 + 3 files changed, 3 insertions(+) diff --git a/scripts/install b/scripts/install index 0e41654..4ef8537 100644 --- a/scripts/install +++ b/scripts/install @@ -101,6 +101,7 @@ ynh_store_file_checksum --file="$final_path/data/config.php" # Set permissions to app files chown -R $app: $final_path +chmod o-rwx $final_path chmod -R 755 $final_path/data #================================================= diff --git a/scripts/restore b/scripts/restore index afccc7e..425d5f4 100644 --- a/scripts/restore +++ b/scripts/restore @@ -77,6 +77,7 @@ ynh_add_fpm_config --package="$extra_php_dependencies" # Restore permissions on app files chown -R $app: $final_path +chmod o-rwx $final_path chmod -R 755 $final_path/data #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index b67a01c..d2dc13c 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -123,6 +123,7 @@ ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/d # Set permissions to app files chown -R $app: $final_path +chmod o-rwx $final_path chmod -R 755 $final_path/data #================================================= From fcf960949b572a96564c543752fb4840ecca3c7f Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 10 Apr 2021 23:09:52 +0200 Subject: [PATCH 25/59] Fix path --- README.md | 4 ++-- README_fr.md | 4 ++-- scripts/change_url | 2 +- scripts/install | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 210e8df..7f5ed00 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,8 @@ Grocy is a web-based self-hosted groceries & household management solution for y #### Supported architectures -* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/grocy%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/grocy/) -* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/grocy%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/grocy/) +* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/grocy.svg)](https://ci-apps.yunohost.org/ci/apps/grocy/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/grocy.svg)](https://ci-apps-arm.yunohost.org/ci/apps/grocy/) ## Limitations diff --git a/README_fr.md b/README_fr.md index 08f09ca..d9adaab 100644 --- a/README_fr.md +++ b/README_fr.md @@ -41,8 +41,8 @@ Connexion par défaut #### Supported architectures -* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/grocy%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/grocy/) -* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/grocy%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/grocy/) +* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/grocy.svg)](https://ci-apps.yunohost.org/ci/apps/grocy/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/grocy.svg)](https://ci-apps-arm.yunohost.org/ci/apps/grocy/) ## Limitations diff --git a/scripts/change_url b/scripts/change_url index b5d9d89..945088b 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -17,7 +17,7 @@ old_domain=$YNH_APP_OLD_DOMAIN old_path=$YNH_APP_OLD_PATH new_domain=$YNH_APP_NEW_DOMAIN -new_path=$YNH_APP_NEW_PATH +new_path="/" app=$YNH_APP_INSTANCE_NAME diff --git a/scripts/install b/scripts/install index 4ef8537..367a871 100644 --- a/scripts/install +++ b/scripts/install @@ -21,7 +21,7 @@ ynh_abort_if_errors # Retrieve arguments domain=$YNH_APP_ARG_DOMAIN -path_url=$"/" +path_url="/" is_public=$YNH_APP_ARG_IS_PUBLIC language=$YNH_APP_ARG_LANGUAGE From af9aa984945cf24be8ffd54cf955ab5eb19492dc Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 11 Apr 2021 11:43:31 +0200 Subject: [PATCH 26/59] Fix --- check_process | 6 +++--- manifest.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/check_process b/check_process index f22c51d..f176d51 100644 --- a/check_process +++ b/check_process @@ -18,14 +18,14 @@ setup_private=1 setup_public=1 upgrade=1 + upgrade=1 from_commit=cbbb845cc8d7324b6e23ab6d7739233523283542 backup_restore=1 multi_instance=1 - port_already_use=0 change_url=1 ;;; Options Email= Notification=none ;;; Upgrade options - ; commit=CommitHash - name=Name and date of the commit. + ; commit=cbbb845cc8d7324b6e23ab6d7739233523283542 + name=Testing (#8) manifest_arg=domain=DOMAIN&path=PATH&admin=USER&language=fr&is_public=1&password=pass&port=666& diff --git a/manifest.json b/manifest.json index 72be1a0..f5745fc 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.0.1~ynh1", + "version": "3.0.1~ynh2", "url": "https://github.com/grocy/grocy", "license": "MIT", "maintainer": { From 3a64725c8f3ddf66660f757a0a9fc567081c2415 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 18 Apr 2021 16:35:43 +0200 Subject: [PATCH 27/59] Fix permissions --- scripts/install | 1 - scripts/restore | 1 - scripts/upgrade | 1 - 3 files changed, 3 deletions(-) diff --git a/scripts/install b/scripts/install index 367a871..f85ae99 100644 --- a/scripts/install +++ b/scripts/install @@ -101,7 +101,6 @@ ynh_store_file_checksum --file="$final_path/data/config.php" # Set permissions to app files chown -R $app: $final_path -chmod o-rwx $final_path chmod -R 755 $final_path/data #================================================= diff --git a/scripts/restore b/scripts/restore index 425d5f4..afccc7e 100644 --- a/scripts/restore +++ b/scripts/restore @@ -77,7 +77,6 @@ ynh_add_fpm_config --package="$extra_php_dependencies" # Restore permissions on app files chown -R $app: $final_path -chmod o-rwx $final_path chmod -R 755 $final_path/data #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index d2dc13c..b67a01c 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -123,7 +123,6 @@ ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/d # Set permissions to app files chown -R $app: $final_path -chmod o-rwx $final_path chmod -R 755 $final_path/data #================================================= From 5f612cef23cc39e3a6ac13fcf9d3273141a537c7 Mon Sep 17 00:00:00 2001 From: YunoHost Bot Date: Tue, 11 May 2021 07:27:11 +0200 Subject: [PATCH 28/59] [autopatch] Update issue and PR templates (#11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Testing (#9) * Cleaning up * [autopatch] Update issue and PR templates Co-authored-by: Éric Gaspar <46165813+ericgaspar@users.noreply.github.com> Co-authored-by: Yunohost-Bot <> --- scripts/install | 1 + scripts/restore | 1 + scripts/upgrade | 1 + 3 files changed, 3 insertions(+) diff --git a/scripts/install b/scripts/install index f85ae99..367a871 100644 --- a/scripts/install +++ b/scripts/install @@ -101,6 +101,7 @@ ynh_store_file_checksum --file="$final_path/data/config.php" # Set permissions to app files chown -R $app: $final_path +chmod o-rwx $final_path chmod -R 755 $final_path/data #================================================= diff --git a/scripts/restore b/scripts/restore index afccc7e..425d5f4 100644 --- a/scripts/restore +++ b/scripts/restore @@ -77,6 +77,7 @@ ynh_add_fpm_config --package="$extra_php_dependencies" # Restore permissions on app files chown -R $app: $final_path +chmod o-rwx $final_path chmod -R 755 $final_path/data #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index b67a01c..d2dc13c 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -123,6 +123,7 @@ ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/d # Set permissions to app files chown -R $app: $final_path +chmod o-rwx $final_path chmod -R 755 $final_path/data #================================================= From 610dbf7ac34adf34b6996ccfa91e3301c4d0d3e3 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Tue, 11 May 2021 16:21:18 +0200 Subject: [PATCH 29/59] Fix --- .github/ISSUE_TEMPLATE.md | 55 ++++++++++++++++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 16 ++++++++++ README.md | 2 +- README_fr.md | 2 +- manifest.json | 2 +- pull_request_template.md | 16 ---------- scripts/upgrade | 12 +++---- 7 files changed, 80 insertions(+), 25 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md delete mode 100644 pull_request_template.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..2729a6b --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,55 @@ +--- +name: Bug report +about: When creating a bug report, please use the following template to provide all the relevant information and help debugging efficiently. + +--- + +**How to post a meaningful bug report** +1. *Read this whole template first.* +2. *Determine if you are on the right place:* + - *If you were performing an action on the app from the webadmin or the CLI (install, update, backup, restore, change_url...), you are on the right place!* + - *Otherwise, the issue may be due to the app itself. Refer to its documentation or repository for help.* + - *When in doubt, post here and we will figure it out together.* +3. *Delete the italic comments as you write over them below, and remove this guide.* +--- + +### Describe the bug + +*A clear and concise description of what the bug is.* + +### Context + +- Hardware: *VPS bought online / Old laptop or computer / Raspberry Pi at home / Internet Cube with VPN / Other ARM board / ...* +- YunoHost version: x.x.x +- I have access to my server: *Through SSH | through the webadmin | direct access via keyboard / screen | ...* +- Are you in a special context or did you perform some particular tweaking on your YunoHost instance?: *no / yes* + - If yes, please explain: +- Using, or trying to install package version/branch: +- If upgrading, current package version: *can be found in the admin, or with `yunohost app info $app_id`* + +### Steps to reproduce + +- *If you performed a command from the CLI, the command itself is enough. For example:* + ```sh + sudo yunohost app install the_app + ``` +- *If you used the webadmin, please perform the equivalent command from the CLI first.* +- *If the error occurs in your browser, explain what you did:* + 1. *Go to '...'* + 2. *Click on '...'* + 3. *Scroll down to '...'* + 4. *See error* + +### Expected behavior + +*A clear and concise description of what you expected to happen. You can remove this section if the command above is enough to understand your intent.* + +### Logs + +*When an operation fails, YunoHost provides a simple way to share the logs.* +- *In the webadmin, the error message contains a link to the relevant log page. On that page, you will be able to 'Share with Yunopaste'. If you missed it, the logs of previous operations are also available under Tools > Logs.* +- *In command line, the command to share the logs is displayed at the end of the operation and looks like `yunohost log display [log name] --share`. If you missed it, you can find the log ID of a previous operation using `yunohost log list`.* + +*After sharing the log, please copypaste directly the link provided by YunoHost (to help readability, no need to copypaste the entire content of the log here, just the link is enough...)* + +*If applicable and useful, add screenshots to help explain your problem.* diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..ef70e18 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +## Problem + +- *Description of why you made this PR* + +## Solution + +- *And how do you fix that problem* + +## PR Status + +- [ ] Code finished and ready to be reviewed/tested +- [ ] The fix/enhancement were manually tested (if applicable) + +## Automatic tests + +Automatic tests can be triggered on https://ci-apps-dev.yunohost.org/ *after creating the PR*, by commenting "!testme", "!gogogadgetoci" or "By the power of systemd, I invoke The Great App CI to test this Pull Request!". (N.B. : for this to work you need to be a member of the Yunohost-Apps organization) diff --git a/README.md b/README.md index 7f5ed00..435221c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ *[Lire ce readme en français.](./README_fr.md)* > *This package allows you to install Grocy quickly and simply on a YunoHost server. -If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* +If you don't have YunoHost, please consult [the guide](https://yunohost.org/install) to learn how to install it.* ## Overview Grocy is a web-based self-hosted groceries & household management solution for your home. diff --git a/README_fr.md b/README_fr.md index d9adaab..bb1701b 100644 --- a/README_fr.md +++ b/README_fr.md @@ -6,7 +6,7 @@ *[Read this readme in english.](./README.md)* > *Ce package vous permet d'installer Grocy rapidement et simplement sur un serveur YunoHost. -Si vous n'avez pas YunoHost, consultez [le guide](https://yunohost.org/#/install) pour apprendre comment l'installer.* +Si vous n'avez pas YunoHost, consultez [le guide](https://yunohost.org/install) pour apprendre comment l'installer.* ## Vue d'ensemble Grocy is a web-based self-hosted groceries & household management solution for your home. diff --git a/manifest.json b/manifest.json index f5745fc..61f50af 100644 --- a/manifest.json +++ b/manifest.json @@ -14,7 +14,7 @@ "email": "" }, "requirements": { - "yunohost": ">= 4.1.7" + "yunohost": ">= 4.2.4" }, "multi_instance": true, "services": [ diff --git a/pull_request_template.md b/pull_request_template.md deleted file mode 100644 index 6c28fc5..0000000 --- a/pull_request_template.md +++ /dev/null @@ -1,16 +0,0 @@ -## Problem -- *Description of why you made this PR* - -## Solution -- *And how do you fix that problem* - -## PR Status -- [ ] Code finished. -- [ ] Tested with Package_check. -- [ ] Fix or enhancement tested. -- [ ] Upgrade from last version tested. -- [ ] Can be reviewed and tested. - -## Package_check results ---- -* An automatic package_check will be launch at https://ci-apps-dev.yunohost.org/, when you add a specific comment to your Pull Request: "!testme", "!gogogadgetoci" or "By the power of systemd, I invoke The Great App CI to test this Pull Request!"* diff --git a/scripts/upgrade b/scripts/upgrade index d2dc13c..b802671 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -69,22 +69,22 @@ then ynh_script_progression --message="Upgrading source files..." --weight=5 # Create a temporary directory - tmpdir="$(mktemp -d)" + #tmpdir="$(mktemp -d)" # Backup the config file in the temp dir - cp -R "$final_path/data" "$tmpdir/data" + #cp -R "$final_path/data" "$tmpdir/data" # Remove the app directory securely - ynh_secure_remove --file="$final_path" + #ynh_secure_remove --file="$final_path" # Download, check integrity, uncompress and patch the source from app.src - ynh_setup_source --dest_dir="$final_path" + ynh_setup_source --dest_dir="$final_path" --keep="$final_path/data" # Copy the admin saved settings from tmp directory to final path - cp -RT "$tmpdir/data" "$final_path/data" + #cp -RT "$tmpdir/data" "$final_path/data" # Remove the tmp directory securely - ynh_secure_remove --file="$tmpdir" + #ynh_secure_remove --file="$tmpdir" fi #================================================= From c71476b2dd75c557af50d927b0f16a9e2203979e Mon Sep 17 00:00:00 2001 From: YunoHost Bot Date: Thu, 13 May 2021 21:06:11 +0200 Subject: [PATCH 30/59] [autopatch] Update issue and PR templates (#12) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Testing (#9) * Cleaning up * [autopatch] Update issue and PR templates Co-authored-by: Éric Gaspar <46165813+ericgaspar@users.noreply.github.com> Co-authored-by: Yunohost-Bot <> --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 61f50af..f5745fc 100644 --- a/manifest.json +++ b/manifest.json @@ -14,7 +14,7 @@ "email": "" }, "requirements": { - "yunohost": ">= 4.2.4" + "yunohost": ">= 4.1.7" }, "multi_instance": true, "services": [ From b0aed70573b53ae47a71cd0d5efddc93ba324ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Wed, 26 May 2021 22:39:37 +0200 Subject: [PATCH 31/59] Add headers (#13) --- check_process | 15 +++++---------- conf/nginx.conf | 4 +++- doc/DISCLAIMER.md | 9 +++++++++ doc/DISCLAIMER_fr.md | 9 +++++++++ doc/screenshots/stock-en.png | Bin 0 -> 122337 bytes manifest.json | 10 ++++++++-- scripts/install | 33 +++++++++++++++++---------------- scripts/restore | 26 +++++++++++++++----------- scripts/upgrade | 13 ++++++++++--- 9 files changed, 76 insertions(+), 43 deletions(-) create mode 100644 doc/DISCLAIMER.md create mode 100644 doc/DISCLAIMER_fr.md create mode 100644 doc/screenshots/stock-en.png diff --git a/check_process b/check_process index f176d51..9252357 100644 --- a/check_process +++ b/check_process @@ -1,15 +1,10 @@ -# See here for more information -# https://github.com/YunoHost/package_check#syntax-check_process-file - -# Move this file from check_process.default to check_process when you have filled it. - ;; Test complet ; Manifest - domain="domain.tld" (DOMAIN) - path="/path" (PATH) - admin="john" (USER) - language="fr" (LANGUAGE) - is_public=1 (PUBLIC|public=1|private=0) + domain="domain.tld" + path="/path" + admin="john" + language="fr" + is_public=1 ; Checks pkg_linter=1 setup_sub_dir=0 diff --git a/conf/nginx.conf b/conf/nginx.conf index 8cb9e61..42927cc 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -8,8 +8,10 @@ location / { rewrite ^ https://$server_name$request_uri? permanent; } - index index.php; + more_set_headers "X-Content-Type-Options: nosniff"; + index index.php; + try_files $uri __PATH__/index.php; location ~ [^/]\.php(/|$) { diff --git a/doc/DISCLAIMER.md b/doc/DISCLAIMER.md new file mode 100644 index 0000000..d87cd4c --- /dev/null +++ b/doc/DISCLAIMER.md @@ -0,0 +1,9 @@ +## Configuration + + Default login + * user: **admin** + * password: **admin** + +## Limitations + +:warning: For now, Grocy must be installed in a root domain or subdirectory. diff --git a/doc/DISCLAIMER_fr.md b/doc/DISCLAIMER_fr.md new file mode 100644 index 0000000..4837ba4 --- /dev/null +++ b/doc/DISCLAIMER_fr.md @@ -0,0 +1,9 @@ +## Configuration + +Connexion par défaut + * utilisateur : **admin** + * mot de passe : **admin** + +## Limitations + +:warning: Pour l'instant, Grocy doit être installé dans un domaine racine ou un sous-domaine. diff --git a/doc/screenshots/stock-en.png b/doc/screenshots/stock-en.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d18edc8aac82dd5f216840c2041ab211359e7c GIT binary patch literal 122337 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 A(EtDd literal 0 HcmV?d00001 diff --git a/manifest.json b/manifest.json index f5745fc..bdacf8b 100644 --- a/manifest.json +++ b/manifest.json @@ -7,14 +7,20 @@ "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, "version": "3.0.1~ynh2", - "url": "https://github.com/grocy/grocy", + "url": "https://grocy.info", + "upstream": { + "license": "MIT", + "website": "https://grocy.info/", + "demo": "https://en.demo.grocy.info/stockoverview", + "code": "https://github.com/grocy/grocy" + }, "license": "MIT", "maintainer": { "name": "", "email": "" }, "requirements": { - "yunohost": ">= 4.1.7" + "yunohost": ">= 4.2.4" }, "multi_instance": true, "services": [ diff --git a/scripts/install b/scripts/install index 367a871..6a7513d 100644 --- a/scripts/install +++ b/scripts/install @@ -47,6 +47,14 @@ ynh_app_setting_set --app=$app --key=domain --value=$domain ynh_app_setting_set --app=$app --key=path --value=$path_url ynh_app_setting_set --app=$app --key=language --value=$language +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Configuring system user..." --weight=1 + +# Create a system user +ynh_system_user_create --username=$app --home_dir="$final_path" + #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= @@ -56,6 +64,10 @@ ynh_app_setting_set --app=$app --key=final_path --value=$final_path # Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$final_path" +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" + #================================================= # NGINX CONFIGURATION #================================================= @@ -64,14 +76,6 @@ ynh_script_progression --message="Configuring NGINX web server..." --weight=10 # Create a dedicated NGINX config ynh_add_nginx_config -#================================================= -# CREATE DEDICATED USER -#================================================= -ynh_script_progression --message="Configuring system user..." --weight=1 - -# Create a system user -ynh_system_user_create --username=$app - #================================================= # PHP-FPM CONFIGURATION #================================================= @@ -87,11 +91,8 @@ phpversion=$(ynh_app_setting_get --app="$app" --key=phpversion) ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/data/config.php" -#================================================= -# STORE THE CONFIG FILE CHECKSUM -#================================================= - -ynh_store_file_checksum --file="$final_path/data/config.php" +chmod 400 "$final_path/data/config.php" +chown $app "$final_path/data/config.php" #================================================= # GENERIC FINALIZATION @@ -100,9 +101,9 @@ ynh_store_file_checksum --file="$final_path/data/config.php" #================================================= # Set permissions to app files -chown -R $app: $final_path -chmod o-rwx $final_path -chmod -R 755 $final_path/data +# chown -R $app: $final_path +# chmod o-rwx $final_path +# chmod -R 755 $final_path/data #================================================= # SETUP SSOWAT diff --git a/scripts/restore b/scripts/restore index 425d5f4..75d5681 100644 --- a/scripts/restore +++ b/scripts/restore @@ -46,6 +46,14 @@ test ! -d $final_path \ ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 + +# Create the dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir="$final_path" + #================================================= # RESTORE THE APP MAIN DIR #================================================= @@ -53,13 +61,9 @@ ynh_script_progression --message="Restoring $app main directory..." --weight=5 ynh_restore_file --origin_path="$final_path" -#================================================= -# RECREATE THE DEDICATED USER -#================================================= -ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 - -# Create the dedicated user (if not existing) -ynh_system_user_create --username=$app +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" #================================================= # RESTORE THE PHP-FPM CONFIGURATION @@ -75,10 +79,10 @@ ynh_add_fpm_config --package="$extra_php_dependencies" # RESTORE USER RIGHTS #================================================= -# Restore permissions on app files -chown -R $app: $final_path -chmod o-rwx $final_path -chmod -R 755 $final_path/data +# # Restore permissions on app files +# chown -R $app: $final_path +# chmod o-rwx $final_path +# chmod -R 755 $final_path/data #================================================= # GENERIC FINALIZATION diff --git a/scripts/upgrade b/scripts/upgrade index b802671..b993ea9 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -87,6 +87,10 @@ then #ynh_secure_remove --file="$tmpdir" fi +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" + #================================================= # NGINX CONFIGURATION #================================================= @@ -117,14 +121,17 @@ ynh_add_fpm_config --package="$extra_php_dependencies" ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/data/config.php" +chmod 400 "$final_path/data/config.php" +chown $app "$final_path/data/config.php" + #================================================= # SECURE FILES AND DIRECTORIES #================================================= # Set permissions to app files -chown -R $app: $final_path -chmod o-rwx $final_path -chmod -R 755 $final_path/data +# chown -R $app: $final_path +# chmod o-rwx $final_path +# chmod -R 755 $final_path/data #================================================= # RELOAD NGINX From f1ebbd00ba821fd35ffcb93a4d491267b4467af4 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 26 May 2021 23:24:42 +0200 Subject: [PATCH 32/59] Cleaning up --- conf/nginx.conf | 2 -- scripts/install | 11 ----------- scripts/restore | 9 --------- scripts/upgrade | 24 ------------------------ 4 files changed, 46 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 42927cc..648af53 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -7,8 +7,6 @@ location / { if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; } - - more_set_headers "X-Content-Type-Options: nosniff"; index index.php; diff --git a/scripts/install b/scripts/install index 6a7513d..ffbf659 100644 --- a/scripts/install +++ b/scripts/install @@ -94,17 +94,6 @@ ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/d chmod 400 "$final_path/data/config.php" chown $app "$final_path/data/config.php" -#================================================= -# GENERIC FINALIZATION -#================================================= -# SECURE FILES AND DIRECTORIES -#================================================= - -# Set permissions to app files -# chown -R $app: $final_path -# chmod o-rwx $final_path -# chmod -R 755 $final_path/data - #================================================= # SETUP SSOWAT #================================================= diff --git a/scripts/restore b/scripts/restore index 75d5681..86aef78 100644 --- a/scripts/restore +++ b/scripts/restore @@ -75,15 +75,6 @@ ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" # Recreate a dedicated PHP-FPM config ynh_add_fpm_config --package="$extra_php_dependencies" -#================================================= -# RESTORE USER RIGHTS -#================================================= - -# # Restore permissions on app files -# chown -R $app: $final_path -# chmod o-rwx $final_path -# chmod -R 755 $final_path/data - #================================================= # GENERIC FINALIZATION #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index b993ea9..033dfe7 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -68,23 +68,8 @@ if [ "$upgrade_type" == "UPGRADE_APP" ] then ynh_script_progression --message="Upgrading source files..." --weight=5 - # Create a temporary directory - #tmpdir="$(mktemp -d)" - - # Backup the config file in the temp dir - #cp -R "$final_path/data" "$tmpdir/data" - - # Remove the app directory securely - #ynh_secure_remove --file="$final_path" - # Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$final_path" --keep="$final_path/data" - - # Copy the admin saved settings from tmp directory to final path - #cp -RT "$tmpdir/data" "$final_path/data" - - # Remove the tmp directory securely - #ynh_secure_remove --file="$tmpdir" fi chmod 750 "$final_path" @@ -124,15 +109,6 @@ ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/d chmod 400 "$final_path/data/config.php" chown $app "$final_path/data/config.php" -#================================================= -# SECURE FILES AND DIRECTORIES -#================================================= - -# Set permissions to app files -# chown -R $app: $final_path -# chmod o-rwx $final_path -# chmod -R 755 $final_path/data - #================================================= # RELOAD NGINX #================================================= From ce445e1ed2e2a362cd5400e716aca0ccb81f0d4c Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 26 May 2021 23:32:23 +0200 Subject: [PATCH 33/59] Update manifest.json --- manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest.json b/manifest.json index bdacf8b..64abda8 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.0.1~ynh2", + "version": "3.0.1~ynh3", "url": "https://grocy.info", "upstream": { "license": "MIT", @@ -20,7 +20,7 @@ "email": "" }, "requirements": { - "yunohost": ">= 4.2.4" + "yunohost": ">= 4.2.0" }, "multi_instance": true, "services": [ From 243b91b43209414e857ab1e9b8eed9e03b5dc0a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Fri, 16 Jul 2021 19:27:48 +0200 Subject: [PATCH 34/59] 3.1.0 (#15) * 3.1.0 --- README.md | 59 +++++++++++++++------------------------- README_fr.md | 57 +++++++++++++------------------------- conf/app.src | 4 +-- conf/config-dist.php | 50 ++++++++++++++++++++++++++++------ manifest.json | 4 +-- pull_request_template.md | 16 ----------- scripts/_common.sh | 4 +-- scripts/backup | 2 +- scripts/install | 2 +- 9 files changed, 91 insertions(+), 107 deletions(-) delete mode 100644 pull_request_template.md diff --git a/README.md b/README.md index 435221c..e8a2bf9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ + + # Grocy for YunoHost [![Integration level](https://dash.yunohost.org/integration/grocy.svg)](https://dash.yunohost.org/appci/app/grocy) ![](https://ci-apps.yunohost.org/ci/badges/grocy.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/grocy.maintain.svg) @@ -5,61 +10,39 @@ *[Lire ce readme en français.](./README_fr.md)* -> *This package allows you to install Grocy quickly and simply on a YunoHost server. -If you don't have YunoHost, please consult [the guide](https://yunohost.org/install) to learn how to install it.* +> *This package allows you to install Grocy quickly and simply on a YunoHost server. +If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* ## Overview -Grocy is a web-based self-hosted groceries & household management solution for your home. -**Shipped version:** 3.0.1 +Web-based groceries & household management solution for your home + +**Shipped version:** 3.1.0~ynh0 + +**Demo:** https://en.demo.grocy.info/stockoverview ## Screenshots -![](https://grocy.info/img/grocy-desktop-en.png) +![](./doc/screenshots/stock-en.png) -## Demo - -* [Official demo](https://en.demo.grocy.info/stockoverview) +## Disclaimers / important information ## Configuration Default login * user: **admin** * password: **admin** - -## Documentation - - * Official documentation: Link to the official documentation of this app - * YunoHost documentation: If specific documentation is needed, feel free to contribute. - -## YunoHost specific features - -#### Multi-user support - -* Are LDAP and HTTP auth supported? -* Can the app be used by multiple users? - -#### Supported architectures - -* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/grocy.svg)](https://ci-apps.yunohost.org/ci/apps/grocy/) -* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/grocy.svg)](https://ci-apps-arm.yunohost.org/ci/apps/grocy/) - + ## Limitations :warning: For now, Grocy must be installed in a root domain or subdirectory. -## Additional information +## Documentation and resources -* Other info you would like to add about this app. - -## Links - - * Report a bug: https://github.com/YunoHost-Apps/grocy_ynh/issues - * App website: https://grocy.info/ - * Upstream app repository: https://github.com/grocy/grocy - * YunoHost website: https://yunohost.org/ - ---- +* Official app website: https://grocy.info/ +* Upstream app code repository: https://github.com/grocy/grocy +* YunoHost documentation for this app: https://yunohost.org/app_grocy +* Report a bug: https://github.com/YunoHost-Apps/grocy_ynh/issues ## Developer info @@ -71,3 +54,5 @@ sudo yunohost app install https://github.com/YunoHost-Apps/grocy_ynh/tree/testin or sudo yunohost app upgrade grocy -u https://github.com/YunoHost-Apps/grocy_ynh/tree/testing --debug ``` + +**More info regarding app packaging:** https://yunohost.org/packaging_apps \ No newline at end of file diff --git a/README_fr.md b/README_fr.md index bb1701b..d9b0cbc 100644 --- a/README_fr.md +++ b/README_fr.md @@ -1,65 +1,44 @@ # Grocy pour YunoHost [![Niveau d'intégration](https://dash.yunohost.org/integration/grocy.svg)](https://dash.yunohost.org/appci/app/grocy) ![](https://ci-apps.yunohost.org/ci/badges/grocy.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/grocy.maintain.svg) -[![Install Grocy with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=grocy) +[![Installer Grocy avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=grocy) -*[Read this readme in english.](./README.md)* +*[Read this readme in english.](./README.md)* +*[Lire ce readme en français.](./README_fr.md)* -> *Ce package vous permet d'installer Grocy rapidement et simplement sur un serveur YunoHost. -Si vous n'avez pas YunoHost, consultez [le guide](https://yunohost.org/install) pour apprendre comment l'installer.* +> *Ce package vous permet d'installer Grocy rapidement et simplement sur un serveur YunoHost. +Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l'installer et en profiter.* ## Vue d'ensemble -Grocy is a web-based self-hosted groceries & household management solution for your home. -**Version incluse :** 3.0.1 +Solution Web de gestion d'épicerie et de gestion de la maison + +**Version incluse :** 3.1.0~ynh0 + +**Démo :** https://en.demo.grocy.info/stockoverview ## Captures d'écran -![](https://grocy.info/img/grocy-desktop-en.png) +![](./doc/screenshots/stock-en.png) -## Démo - -* [Démo officielle](https://en.demo.grocy.info/stockoverview) +## Avertissements / informations importantes ## Configuration Connexion par défaut * utilisateur : **admin** * mot de passe : **admin** - -## Documentation - - * Documentation officielle : Lien vers la documentation officielle de cette application. - * Documentation YunoHost : Si une documentation spécifique est nécessaire, n'hésitez pas à contribuer. - -## Caractéristiques spécifiques YunoHost - -#### Support multi-utilisateur - -* L'authentification LDAP et HTTP est-elle prise en charge ? -* L'application peut-elle être utilisée par plusieurs utilisateurs ? - -#### Supported architectures - -* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/grocy.svg)](https://ci-apps.yunohost.org/ci/apps/grocy/) -* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/grocy.svg)](https://ci-apps-arm.yunohost.org/ci/apps/grocy/) ## Limitations :warning: Pour l'instant, Grocy doit être installé dans un domaine racine ou un sous-domaine. -## Informations additionnelles +## Documentations et ressources -* Autres informations que vous souhaitez ajouter sur cette application. - -## Liens - - * Signaler un bug : https://github.com/YunoHost-Apps/grocy_ynh/issues - * Site de l'application : https://grocy.info/ - * Dépôt de l'application principale : https://github.com/grocy/grocy - * Site web YunoHost : https://yunohost.org/ - ---- +* Site officiel de l'app : https://grocy.info/ +* Dépôt de code officiel de l'app : https://github.com/grocy/grocy +* Documentation YunoHost pour cette app : https://yunohost.org/app_grocy +* Signaler un bug : https://github.com/YunoHost-Apps/grocy_ynh/issues ## Informations pour les développeurs @@ -71,3 +50,5 @@ sudo yunohost app install https://github.com/YunoHost-Apps/grocy_ynh/tree/testin ou sudo yunohost app upgrade grocy -u https://github.com/YunoHost-Apps/grocy_ynh/tree/testing --debug ``` + +**Plus d'infos sur le packaging d'applications :** https://yunohost.org/packaging_apps \ No newline at end of file diff --git a/conf/app.src b/conf/app.src index 2afc137..91b08de 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.0.1/grocy_3.0.1.zip -SOURCE_SUM=623c6fd0b70b36da58b389ed05a9e8f4d531c1d5a01797ad03f33a85457339af +SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.1.0/grocy_3.1.0.zip +SOURCE_SUM=a21be24c8da7a7acfe4a357608349ca2e23c2e1d91bb8f82134d0a9604f8d22f SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=zip SOURCE_IN_SUBDIR=false diff --git a/conf/config-dist.php b/conf/config-dist.php index 143cea9..00a321a 100644 --- a/conf/config-dist.php +++ b/conf/config-dist.php @@ -77,10 +77,13 @@ Setting('AUTH_CLASS', 'Grocy\Middleware\DefaultAuthMiddleware'); // the name of the HTTP header which your reverse proxy uses to pass the username (on successful authentication) Setting('REVERSE_PROXY_AUTH_HEADER', 'REMOTE_USER'); -// When using LdapAuthMiddleware -Setting('LDAP_DOMAIN', 'local'); // Example value "local" +// LDAP options when using LdapAuthMiddleware Setting('LDAP_ADDRESS', 'ldap://127.0.0.1:389'); // Example value "ldap://vm-dc2019.local.berrnd.net" -Setting('LDAP_BASE_DN', 'ou=users,dc=yunohost,dc=org'); // Example value "OU=OU_Users,DC=local,DC=berrnd,DC=net" +Setting('LDAP_BASE_DN', 'ou=users,dc=yunohost,dc=org'); // Example value "DC=local,DC=berrnd,DC=net" +Setting('LDAP_BIND_DN', ''); // Example value "CN=grocy_bind_account,OU=service_accounts,DC=local,DC=berrnd,DC=net" +Setting('LDAP_BIND_PW', ''); // Password for the above account +Setting('LDAP_USER_FILTER', ''); // Example value "(OU=grocy_users)" +Setting('LDAP_UID_ATTR', ''); // Windows AD: "sAMAccountName", OpenLDAP: "uid", GLAuth: "cn" // Set this to true if you want to disable the ability to scan a barcode via the device camera (Browser API) Setting('DISABLE_BROWSER_BARCODE_CAMERA_SCANNING', false); @@ -95,6 +98,34 @@ Setting('MEAL_PLAN_FIRST_DAY_OF_WEEK', ''); // see the file controllers/Users/User.php for possible values Setting('DEFAULT_PERMISSIONS', ['ADMIN']); +// 1D (=> Code128) or 2D (=> DataMatrix) +Setting('GROCYCODE_TYPE', '1D'); + +// Label printer settings +// This is the URI that grocy will POST to when asked to print a label +Setting('LABEL_PRINTER_WEBHOOK', ''); +// This setting decides whether the webhook will be called server- or clientside +// If the machine grocy runs on has a network connection to the host the webhook receiver is on, this is probably a good idea +// If, for example, grocy runs in the cloud and your printer daemon runs locally to you, set this to false to let your browser call the webhook instead +Setting('LABEL_PRINTER_RUN_SERVER', true); +// Additional parameters supplied to the webhook +Setting('LABEL_PRINTER_PARAMS', ['font_family' => 'Source Sans Pro (Regular)']); +// TRUE to use JSON or FALSE to use normal POST request variables +Setting('LABEL_PRINTER_HOOK_JSON', false); + +// Thermal printer options +// Thermal printers are receipt printers, not regular printers, +// the printer must support the ESC/POS protocol, see https://github.com/mike42/escpos-php +Setting('TPRINTER_IS_NETWORK_PRINTER', false); // Set to true if it's' a network printer +Setting('TPRINTER_PRINT_QUANTITY_NAME', true); // Set to false if you do not want to print the quantity names (related to the shopping list) +Setting('TPRINTER_PRINT_NOTES', true); // Set to false if you do not want to print notes (related to the shopping list) +Setting('TPRINTER_IP', '127.0.0.1'); // IP of the network printer (does only matter if it's a network printer) +Setting('TPRINTER_PORT', 9100); // Port of the network printer +Setting('TPRINTER_CONNECTOR', '/dev/usb/lp0'); // Printer device (does only matter if you use a locally attached printer) +// For USB on Linux this is often '/dev/usb/lp0', for serial printers it could be similar to '/dev/ttyS0' +// Make sure that the user that runs the webserver has permissions to write to the printer - on Linux add your webserver user to the LP group with usermod -a -G lp www-data + + // Default user settings // These settings can be changed per user, here the defaults // are defined which are used when the user has not changed the setting so far @@ -117,6 +148,7 @@ DefaultUserSetting('product_presets_product_group_id', -1); // Default product g DefaultUserSetting('product_presets_qu_id', -1); // Default quantity unit id for new products (-1 means no quantity unit is preset) DefaultUserSetting('stock_decimal_places_amounts', 4); // Default decimal places allowed for amounts DefaultUserSetting('stock_decimal_places_prices', 2); // Default decimal places allowed for prices +DefaultUserSetting('stock_auto_decimal_separator_prices', false); DefaultUserSetting('stock_due_soon_days', 5); DefaultUserSetting('stock_default_purchase_amount', 0); DefaultUserSetting('stock_default_consume_amount', 1); @@ -124,7 +156,7 @@ DefaultUserSetting('stock_default_consume_amount_use_quick_consume_amount', fals DefaultUserSetting('scan_mode_consume_enabled', false); DefaultUserSetting('scan_mode_purchase_enabled', false); DefaultUserSetting('show_icon_on_stock_overview_page_when_product_is_on_shopping_list', true); -DefaultUserSetting('show_purchased_date_on_purchase', false); // Wheter the purchased date should be editable on purchase (defaults to today otherwise) +DefaultUserSetting('show_purchased_date_on_purchase', false); // Whether the purchased date should be editable on purchase (defaults to today otherwise) DefaultUserSetting('show_warning_on_purchase_when_due_date_is_earlier_than_next', true); // Show a warning on purchase when the due date of the purchased product is earlier than the next due date in stock // Shopping list settings @@ -143,9 +175,8 @@ DefaultUserSetting('batteries_due_soon_days', 5); // Tasks settings DefaultUserSetting('tasks_due_soon_days', 5); -// If the page should be automatically reloaded when there was -// an external change -DefaultUserSetting('auto_reload_on_db_change', true); +// If the page should be automatically reloaded when there was an external change +DefaultUserSetting('auto_reload_on_db_change', false); // Show a clock in the header next to the logo or not DefaultUserSetting('show_clock_in_header', false); @@ -159,6 +190,7 @@ DefaultUserSetting('quagga2_patchsize', 'medium'); DefaultUserSetting('quagga2_frequency', 10); DefaultUserSetting('quagga2_debug', true); + // Feature flags // grocy was initially about "stock management for your household", many other things // came and still come by, because they are useful - here you can disable the parts @@ -172,6 +204,7 @@ Setting('FEATURE_FLAG_TASKS', true); Setting('FEATURE_FLAG_BATTERIES', true); Setting('FEATURE_FLAG_EQUIPMENT', true); Setting('FEATURE_FLAG_CALENDAR', true); +Setting('FEATURE_FLAG_LABEL_PRINTER', false); // Sub feature flags Setting('FEATURE_FLAG_STOCK_PRICE_TRACKING', true); @@ -182,7 +215,8 @@ Setting('FEATURE_FLAG_STOCK_PRODUCT_FREEZING', true); Setting('FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_FIELD_NUMBER_PAD', true); // Activate the number pad in due date fields on (supported) mobile browsers Setting('FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS', true); Setting('FEATURE_FLAG_CHORES_ASSIGNMENTS', true); +Setting('FEATURE_FLAG_THERMAL_PRINTER', false); // Feature settings Setting('FEATURE_SETTING_STOCK_COUNT_OPENED_PRODUCTS_AGAINST_MINIMUM_STOCK_AMOUNT', true); // When set to true, opened items will be counted as missing for calculating if a product is below its minimum stock amount -Setting('FEATURE_FLAG_AUTO_TORCH_ON_WITH_CAMERA', true); // Enables the torch automaticaly (if the device has one) +Setting('FEATURE_FLAG_AUTO_TORCH_ON_WITH_CAMERA', true); // Enables the torch automatically (if the device has one) diff --git a/manifest.json b/manifest.json index 64abda8..322cade 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.0.1~ynh3", + "version": "3.1.0~ynh0", "url": "https://grocy.info", "upstream": { "license": "MIT", @@ -25,7 +25,7 @@ "multi_instance": true, "services": [ "nginx", - "php7.3-fpm" + "php8.0-fpm" ], "arguments": { "install": [{ diff --git a/pull_request_template.md b/pull_request_template.md deleted file mode 100644 index 6c28fc5..0000000 --- a/pull_request_template.md +++ /dev/null @@ -1,16 +0,0 @@ -## Problem -- *Description of why you made this PR* - -## Solution -- *And how do you fix that problem* - -## PR Status -- [ ] Code finished. -- [ ] Tested with Package_check. -- [ ] Fix or enhancement tested. -- [ ] Upgrade from last version tested. -- [ ] Can be reviewed and tested. - -## Package_check results ---- -* An automatic package_check will be launch at https://ci-apps-dev.yunohost.org/, when you add a specific comment to your Pull Request: "!testme", "!gogogadgetoci" or "By the power of systemd, I invoke The Great App CI to test this Pull Request!"* diff --git a/scripts/_common.sh b/scripts/_common.sh index 58131e6..c2e47ec 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -4,9 +4,9 @@ # COMMON VARIABLES #================================================= -YNH_PHP_VERSION="7.4" +YNH_PHP_VERSION="8.0" -extra_php_dependencies="php${YNH_PHP_VERSION}-fileinfo php${YNH_PHP_VERSION}-sqlite3 php${YNH_PHP_VERSION}-gd" +extra_php_dependencies="php${YNH_PHP_VERSION}-fileinfo php${YNH_PHP_VERSION}-sqlite3 php${YNH_PHP_VERSION}-gd php${YNH_PHP_VERSION}-json php${YNH_PHP_VERSION}-intl" #================================================= # PERSONAL HELPERS diff --git a/scripts/backup b/scripts/backup index 2d90ed5..2a2b65e 100644 --- a/scripts/backup +++ b/scripts/backup @@ -25,7 +25,7 @@ app=$YNH_APP_INSTANCE_NAME final_path=$(ynh_app_setting_get --app=$app --key=final_path) domain=$(ynh_app_setting_get --app=$app --key=domain) -phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) +phpversion=$YNH_PHP_VERSION #================================================= # DECLARE DATA AND CONF FILES TO BACKUP diff --git a/scripts/install b/scripts/install index ffbf659..5b5560f 100644 --- a/scripts/install +++ b/scripts/install @@ -83,7 +83,7 @@ ynh_script_progression --message="Configuring PHP-FPM..." --weight=3 # Create a dedicated PHP-FPM config ynh_add_fpm_config --package="$extra_php_dependencies" -phpversion=$(ynh_app_setting_get --app="$app" --key=phpversion) +phpversion=$YNH_PHP_VERSION #================================================= # MODIFY A CONFIG FILE From 6fb54e85273623d7d92a7d6b0d841d2214d42b14 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 16 Jul 2021 19:59:04 +0200 Subject: [PATCH 35/59] Fix --- doc/DISCLAIMER.md | 8 +++++--- doc/DISCLAIMER_fr.md | 6 ++++-- manifest.json | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/DISCLAIMER.md b/doc/DISCLAIMER.md index d87cd4c..4f720fa 100644 --- a/doc/DISCLAIMER.md +++ b/doc/DISCLAIMER.md @@ -1,9 +1,11 @@ ## Configuration Default login - * user: **admin** - * password: **admin** - +``` + user: **admin** + password: **admin** +``` + ## Limitations :warning: For now, Grocy must be installed in a root domain or subdirectory. diff --git a/doc/DISCLAIMER_fr.md b/doc/DISCLAIMER_fr.md index 4837ba4..836ff54 100644 --- a/doc/DISCLAIMER_fr.md +++ b/doc/DISCLAIMER_fr.md @@ -1,8 +1,10 @@ ## Configuration Connexion par défaut - * utilisateur : **admin** - * mot de passe : **admin** +``` + utilisateur : **admin** + mot de passe : **admin** +``` ## Limitations diff --git a/manifest.json b/manifest.json index 322cade..4a77648 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.1.0~ynh0", + "version": "3.1.0~ynh1", "url": "https://grocy.info", "upstream": { "license": "MIT", From 0cbd852eeaeee56ab8633b211068f44cfb1fdb04 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Fri, 16 Jul 2021 17:59:11 +0000 Subject: [PATCH 36/59] Auto-update README --- README.md | 10 ++++++---- README_fr.md | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e8a2bf9..e274172 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Web-based groceries & household management solution for your home -**Shipped version:** 3.1.0~ynh0 +**Shipped version:** 3.1.0~ynh1 **Demo:** https://en.demo.grocy.info/stockoverview @@ -30,9 +30,11 @@ Web-based groceries & household management solution for your home ## Configuration Default login - * user: **admin** - * password: **admin** - +``` + user: **admin** + password: **admin** +``` + ## Limitations :warning: For now, Grocy must be installed in a root domain or subdirectory. diff --git a/README_fr.md b/README_fr.md index d9b0cbc..88f78ab 100644 --- a/README_fr.md +++ b/README_fr.md @@ -13,7 +13,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Solution Web de gestion d'épicerie et de gestion de la maison -**Version incluse :** 3.1.0~ynh0 +**Version incluse :** 3.1.0~ynh1 **Démo :** https://en.demo.grocy.info/stockoverview @@ -26,8 +26,10 @@ Solution Web de gestion d'épicerie et de gestion de la maison ## Configuration Connexion par défaut - * utilisateur : **admin** - * mot de passe : **admin** +``` + utilisateur : **admin** + mot de passe : **admin** +``` ## Limitations From fc3241b724e4d0520c0bdf764adef90c673d276e Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 16 Jul 2021 23:39:32 +0200 Subject: [PATCH 37/59] Fix --- doc/DISCLAIMER.md | 4 ++-- doc/DISCLAIMER_fr.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/DISCLAIMER.md b/doc/DISCLAIMER.md index 4f720fa..ccb2c82 100644 --- a/doc/DISCLAIMER.md +++ b/doc/DISCLAIMER.md @@ -2,8 +2,8 @@ Default login ``` - user: **admin** - password: **admin** + user: admin + password: admin ``` ## Limitations diff --git a/doc/DISCLAIMER_fr.md b/doc/DISCLAIMER_fr.md index 836ff54..c059f0b 100644 --- a/doc/DISCLAIMER_fr.md +++ b/doc/DISCLAIMER_fr.md @@ -2,8 +2,8 @@ Connexion par défaut ``` - utilisateur : **admin** - mot de passe : **admin** + utilisateur : admin + mot de passe : admin ``` ## Limitations From 436893d47f050d9b32e5c10507b91752614c5a8d Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Fri, 16 Jul 2021 21:39:39 +0000 Subject: [PATCH 38/59] Auto-update README --- README.md | 4 ++-- README_fr.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e274172..25752f7 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ Web-based groceries & household management solution for your home Default login ``` - user: **admin** - password: **admin** + user: admin + password: admin ``` ## Limitations diff --git a/README_fr.md b/README_fr.md index 88f78ab..35a797f 100644 --- a/README_fr.md +++ b/README_fr.md @@ -27,8 +27,8 @@ Solution Web de gestion d'épicerie et de gestion de la maison Connexion par défaut ``` - utilisateur : **admin** - mot de passe : **admin** + utilisateur : admin + mot de passe : admin ``` ## Limitations From ff4b13792139332ed804a0e64820c18a8b9d3d03 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 25 Jul 2021 23:25:27 +0200 Subject: [PATCH 39/59] Set client_max_body_size to 50M --- conf/nginx.conf | 2 ++ conf/php-fpm.conf | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 648af53..1994a8e 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -10,6 +10,8 @@ location / { index index.php; + client_max_body_size 50M; + try_files $uri __PATH__/index.php; location ~ [^/]\.php(/|$) { diff --git a/conf/php-fpm.conf b/conf/php-fpm.conf index ab1a471..b4c2372 100644 --- a/conf/php-fpm.conf +++ b/conf/php-fpm.conf @@ -419,8 +419,8 @@ chdir = __FINALPATH__ ;php_admin_value[memory_limit] = 32M ; Common values to change to increase file upload limit -; php_admin_value[upload_max_filesize] = 50M -; php_admin_value[post_max_size] = 50M +php_admin_value[upload_max_filesize] = 50M +php_admin_value[post_max_size] = 50M ; php_admin_flag[mail.add_x_header] = Off ; Other common parameters From 91812e9473e9b2688773b968bc85458f71507cd7 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 25 Jul 2021 23:42:04 +0200 Subject: [PATCH 40/59] Update manifest.json --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 4a77648..c25517e 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.1.0~ynh1", + "version": "3.1.0~ynh2", "url": "https://grocy.info", "upstream": { "license": "MIT", From 950b85b4c18c52ffa66d2a071283fd5133627b89 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Sun, 25 Jul 2021 21:42:10 +0000 Subject: [PATCH 41/59] 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 e274172..571f6a4 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Web-based groceries & household management solution for your home -**Shipped version:** 3.1.0~ynh1 +**Shipped version:** 3.1.0~ynh2 **Demo:** https://en.demo.grocy.info/stockoverview diff --git a/README_fr.md b/README_fr.md index 88f78ab..a0b69b0 100644 --- a/README_fr.md +++ b/README_fr.md @@ -13,7 +13,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Solution Web de gestion d'épicerie et de gestion de la maison -**Version incluse :** 3.1.0~ynh1 +**Version incluse :** 3.1.0~ynh2 **Démo :** https://en.demo.grocy.info/stockoverview From c04e801c6bbe56070e62c8c7c94b832d12ffccaa Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 18 Aug 2021 16:49:52 +0200 Subject: [PATCH 42/59] Update manifest.json --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index c25517e..7ffec13 100644 --- a/manifest.json +++ b/manifest.json @@ -20,7 +20,7 @@ "email": "" }, "requirements": { - "yunohost": ">= 4.2.0" + "yunohost": ">= 4.24" }, "multi_instance": true, "services": [ From 4c4ee127d0e22d2d6cb1734ac4adbb738f1aeb24 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 21 Aug 2021 21:06:35 +0200 Subject: [PATCH 43/59] 3.1.1 --- conf/app.src | 4 ++-- manifest.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/conf/app.src b/conf/app.src index 91b08de..3d33cdd 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.1.0/grocy_3.1.0.zip -SOURCE_SUM=a21be24c8da7a7acfe4a357608349ca2e23c2e1d91bb8f82134d0a9604f8d22f +SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.1.1/grocy_3.1.1.zip +SOURCE_SUM=c6862369917b16bcfe40f677edf0526e05d3c2c47ff8d6be5ec3f9b5f01380d8 SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=zip SOURCE_IN_SUBDIR=false diff --git a/manifest.json b/manifest.json index 7ffec13..46a7da2 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.1.0~ynh2", + "version": "3.1.1~ynh1", "url": "https://grocy.info", "upstream": { "license": "MIT", @@ -20,7 +20,7 @@ "email": "" }, "requirements": { - "yunohost": ">= 4.24" + "yunohost": ">= 4.2.4" }, "multi_instance": true, "services": [ From aab0172bd5f7608eae2fda3b847f3ee81627d75a Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Sat, 21 Aug 2021 19:06:40 +0000 Subject: [PATCH 44/59] 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 571f6a4..95fb4fc 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Web-based groceries & household management solution for your home -**Shipped version:** 3.1.0~ynh2 +**Shipped version:** 3.1.1~ynh1 **Demo:** https://en.demo.grocy.info/stockoverview diff --git a/README_fr.md b/README_fr.md index a0b69b0..52c4669 100644 --- a/README_fr.md +++ b/README_fr.md @@ -13,7 +13,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Solution Web de gestion d'épicerie et de gestion de la maison -**Version incluse :** 3.1.0~ynh2 +**Version incluse :** 3.1.1~ynh1 **Démo :** https://en.demo.grocy.info/stockoverview From c0097eee282c13367d3f6bcf9d087ce9f2b4d078 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 29 Aug 2021 10:20:07 +0200 Subject: [PATCH 45/59] Fix --- doc/DESCRIPTION.md | 0 manifest.json | 2 +- scripts/restore | 2 -- 3 files changed, 1 insertion(+), 3 deletions(-) create mode 100644 doc/DESCRIPTION.md diff --git a/doc/DESCRIPTION.md b/doc/DESCRIPTION.md new file mode 100644 index 0000000..e69de29 diff --git a/manifest.json b/manifest.json index 46a7da2..2194267 100644 --- a/manifest.json +++ b/manifest.json @@ -16,7 +16,7 @@ }, "license": "MIT", "maintainer": { - "name": "", + "name": "eric_G", "email": "" }, "requirements": { diff --git a/scripts/restore b/scripts/restore index 86aef78..f5fd81c 100644 --- a/scripts/restore +++ b/scripts/restore @@ -33,8 +33,6 @@ phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) #================================================= ynh_script_progression --message="Validating restoration parameters..." --weight=1 -ynh_webpath_available --domain=$domain --path_url=$path_url \ - || ynh_die --message="Path not available: ${domain}${path_url}" test ! -d $final_path \ || ynh_die --message="There is already a directory: $final_path " From 86eb100015811d1e8b31db3e3a708135c532b7d8 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Tue, 21 Sep 2021 23:35:11 +0200 Subject: [PATCH 46/59] Update manifest.json --- manifest.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/manifest.json b/manifest.json index 2194267..dfdd3aa 100644 --- a/manifest.json +++ b/manifest.json @@ -30,8 +30,7 @@ "arguments": { "install": [{ "name": "domain", - "type": "domain", - "example": "grocy.example.com" + "type": "domain" }, { "name": "language", From d099b562a2805a036edecef9d7e863164b3151fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Mon, 27 Sep 2021 19:11:03 +0200 Subject: [PATCH 47/59] Upgrade 3.1.2 (#20) --- conf/app.src | 7 +++---- manifest.json | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/conf/app.src b/conf/app.src index 3d33cdd..7054907 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,7 +1,6 @@ -SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.1.1/grocy_3.1.1.zip -SOURCE_SUM=c6862369917b16bcfe40f677edf0526e05d3c2c47ff8d6be5ec3f9b5f01380d8 +SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.1.2/grocy_3.1.2.zip +SOURCE_SUM=2b0d940378c911f18fafd8cc9c3989e065bcedfc0cf34a50a6a4f3f6e817ce8c SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=zip SOURCE_IN_SUBDIR=false -SOURCE_EXTRACT=true -SOURCE_FILENAME= \ No newline at end of file +SOURCE_EXTRACT=true \ No newline at end of file diff --git a/manifest.json b/manifest.json index dfdd3aa..edc94fd 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.1.1~ynh1", + "version": "3.1.2~ynh1", "url": "https://grocy.info", "upstream": { "license": "MIT", From db524f98c1ef57fa493ea393664077d64910c65c Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Mon, 27 Sep 2021 17:11:06 +0000 Subject: [PATCH 48/59] 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 95fb4fc..fa10530 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Web-based groceries & household management solution for your home -**Shipped version:** 3.1.1~ynh1 +**Shipped version:** 3.1.2~ynh1 **Demo:** https://en.demo.grocy.info/stockoverview diff --git a/README_fr.md b/README_fr.md index 52c4669..7211237 100644 --- a/README_fr.md +++ b/README_fr.md @@ -13,7 +13,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Solution Web de gestion d'épicerie et de gestion de la maison -**Version incluse :** 3.1.1~ynh1 +**Version incluse :** 3.1.2~ynh1 **Démo :** https://en.demo.grocy.info/stockoverview From ce75af6de859031cbdb5b2de5fdfabd3cee8da34 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Thu, 30 Sep 2021 09:29:28 +0200 Subject: [PATCH 49/59] Add mbstring --- scripts/_common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/_common.sh b/scripts/_common.sh index c2e47ec..87667cd 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -6,7 +6,7 @@ YNH_PHP_VERSION="8.0" -extra_php_dependencies="php${YNH_PHP_VERSION}-fileinfo php${YNH_PHP_VERSION}-sqlite3 php${YNH_PHP_VERSION}-gd php${YNH_PHP_VERSION}-json php${YNH_PHP_VERSION}-intl" +extra_php_dependencies="php${YNH_PHP_VERSION}-mbstring php${YNH_PHP_VERSION}-fileinfo php${YNH_PHP_VERSION}-sqlite3 php${YNH_PHP_VERSION}-gd php${YNH_PHP_VERSION}-json php${YNH_PHP_VERSION}-intl" #================================================= # PERSONAL HELPERS From bcf411aeb423339a5059500c2aa49eecc5061eb3 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Thu, 30 Sep 2021 09:31:01 +0200 Subject: [PATCH 50/59] Update manifest.json --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index edc94fd..b02f4f5 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.1.2~ynh1", + "version": "3.1.2~ynh2", "url": "https://grocy.info", "upstream": { "license": "MIT", From cbb0eec0f2ddd1e2e53eb40249dd5387ca220858 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Thu, 30 Sep 2021 07:31:07 +0000 Subject: [PATCH 51/59] 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 fa10530..54fd7ad 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Web-based groceries & household management solution for your home -**Shipped version:** 3.1.2~ynh1 +**Shipped version:** 3.1.2~ynh2 **Demo:** https://en.demo.grocy.info/stockoverview diff --git a/README_fr.md b/README_fr.md index 7211237..6924bd5 100644 --- a/README_fr.md +++ b/README_fr.md @@ -13,7 +13,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Solution Web de gestion d'épicerie et de gestion de la maison -**Version incluse :** 3.1.2~ynh1 +**Version incluse :** 3.1.2~ynh2 **Démo :** https://en.demo.grocy.info/stockoverview From ee71346ca38e403077c0db98d2ec4b9d54277cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Tue, 16 Nov 2021 10:37:50 +0100 Subject: [PATCH 52/59] 3.1.3 (#24) * 3.1.3 --- README.md | 2 +- README_fr.md | 2 +- conf/app.src | 4 ++-- manifest.json | 4 ++-- scripts/_common.sh | 2 +- scripts/backup | 2 +- scripts/install | 13 +++++++++++-- scripts/restore | 13 ++++++++++--- scripts/upgrade | 43 +++++++++++++++++++++++++------------------ 9 files changed, 54 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 54fd7ad..8da0a91 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Web-based groceries & household management solution for your home -**Shipped version:** 3.1.2~ynh2 +**Shipped version:** 3.1.3~ynh1 **Demo:** https://en.demo.grocy.info/stockoverview diff --git a/README_fr.md b/README_fr.md index 6924bd5..c9f491e 100644 --- a/README_fr.md +++ b/README_fr.md @@ -13,7 +13,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Solution Web de gestion d'épicerie et de gestion de la maison -**Version incluse :** 3.1.2~ynh2 +**Version incluse :** 3.1.3~ynh1 **Démo :** https://en.demo.grocy.info/stockoverview diff --git a/conf/app.src b/conf/app.src index 7054907..9a1bd48 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.1.2/grocy_3.1.2.zip -SOURCE_SUM=2b0d940378c911f18fafd8cc9c3989e065bcedfc0cf34a50a6a4f3f6e817ce8c +SOURCE_URL=https://github.com/grocy/grocy/releases/download/v3.1.3/grocy_3.1.3.zip +SOURCE_SUM=eaf82757d1d01f02465071b100c5f15d78848f690d4d6a867079e93c7be66bf4 SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=zip SOURCE_IN_SUBDIR=false diff --git a/manifest.json b/manifest.json index b02f4f5..44da7f4 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.1.2~ynh2", + "version": "3.1.3~ynh1", "url": "https://grocy.info", "upstream": { "license": "MIT", @@ -20,7 +20,7 @@ "email": "" }, "requirements": { - "yunohost": ">= 4.2.4" + "yunohost": ">= 4.3.0" }, "multi_instance": true, "services": [ diff --git a/scripts/_common.sh b/scripts/_common.sh index 87667cd..f058cd3 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -6,7 +6,7 @@ YNH_PHP_VERSION="8.0" -extra_php_dependencies="php${YNH_PHP_VERSION}-mbstring php${YNH_PHP_VERSION}-fileinfo php${YNH_PHP_VERSION}-sqlite3 php${YNH_PHP_VERSION}-gd php${YNH_PHP_VERSION}-json php${YNH_PHP_VERSION}-intl" +pkg_dependencies="php${YNH_PHP_VERSION}-mbstring php${YNH_PHP_VERSION}-fileinfo php${YNH_PHP_VERSION}-sqlite3 php${YNH_PHP_VERSION}-gd php${YNH_PHP_VERSION}-json php${YNH_PHP_VERSION}-intl" #================================================= # PERSONAL HELPERS diff --git a/scripts/backup b/scripts/backup index 2a2b65e..2d90ed5 100644 --- a/scripts/backup +++ b/scripts/backup @@ -25,7 +25,7 @@ app=$YNH_APP_INSTANCE_NAME final_path=$(ynh_app_setting_get --app=$app --key=final_path) domain=$(ynh_app_setting_get --app=$app --key=domain) -phpversion=$YNH_PHP_VERSION +phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) #================================================= # DECLARE DATA AND CONF FILES TO BACKUP diff --git a/scripts/install b/scripts/install index 5b5560f..5202159 100644 --- a/scripts/install +++ b/scripts/install @@ -24,6 +24,7 @@ domain=$YNH_APP_ARG_DOMAIN path_url="/" is_public=$YNH_APP_ARG_IS_PUBLIC language=$YNH_APP_ARG_LANGUAGE +phpversion=$YNH_PHP_VERSION app=$YNH_APP_INSTANCE_NAME @@ -47,6 +48,13 @@ ynh_app_setting_set --app=$app --key=domain --value=$domain ynh_app_setting_set --app=$app --key=path --value=$path_url ynh_app_setting_set --app=$app --key=language --value=$language +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Installing dependencies..." --weight=1 + +ynh_install_app_dependencies $pkg_dependencies + #================================================= # CREATE DEDICATED USER #================================================= @@ -82,12 +90,13 @@ ynh_add_nginx_config ynh_script_progression --message="Configuring PHP-FPM..." --weight=3 # Create a dedicated PHP-FPM config -ynh_add_fpm_config --package="$extra_php_dependencies" -phpversion=$YNH_PHP_VERSION +ynh_add_fpm_config +phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) #================================================= # MODIFY A CONFIG FILE #================================================= +ynh_script_progression --message="Adding a configuration file..." --weight=1 ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/data/config.php" diff --git a/scripts/restore b/scripts/restore index f5fd81c..c1a8324 100644 --- a/scripts/restore +++ b/scripts/restore @@ -63,15 +63,22 @@ chmod 750 "$final_path" chmod -R o-rwx "$final_path" chown -R $app:www-data "$final_path" +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Reinstalling dependencies..." --weight=1 + +# Define and install dependencies +ynh_install_app_dependencies $pkg_dependencies + #================================================= # RESTORE THE PHP-FPM CONFIGURATION #================================================= -ynh_script_progression --message="Restoring PHP-FPM configuration..." +ynh_script_progression --message="Restoring PHP-FPM configuration..." --weight=1 ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" - # Recreate a dedicated PHP-FPM config -ynh_add_fpm_config --package="$extra_php_dependencies" +#ynh_add_fpm_config #================================================= # GENERIC FINALIZATION diff --git a/scripts/upgrade b/scripts/upgrade index 033dfe7..a17e175 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -28,6 +28,20 @@ phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) upgrade_type=$(ynh_check_app_version_changed) +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=5 + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + # restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + #================================================= # ENSURE DOWNWARD COMPATIBILITY #================================================= @@ -47,18 +61,12 @@ if ynh_legacy_permissions_exists; then fi #================================================= -# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +# CREATE DEDICATED USER #================================================= -ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=5 +ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 -# Backup the current version of the app -ynh_backup_before_upgrade -ynh_clean_setup () { - # restore it if the upgrade fails - ynh_restore_upgradebackup -} -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors +# Create a dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir="$final_path" #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE @@ -85,12 +93,11 @@ ynh_script_progression --message="Upgrading NGINX web server configuration..." - ynh_add_nginx_config #================================================= -# CREATE DEDICATED USER +# UPGRADE DEPENDENCIES #================================================= -ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 +ynh_script_progression --message="Upgrading dependencies..." --weight=1 -# Create a dedicated user (if not existing) -ynh_system_user_create --username=$app +ynh_install_app_dependencies $pkg_dependencies #================================================= # PHP-FPM CONFIGURATION @@ -98,16 +105,16 @@ ynh_system_user_create --username=$app ynh_script_progression --message="Upgrading PHP-FPM configuration..." --weight=1 # Create a dedicated php-fpm config -ynh_add_fpm_config --package="$extra_php_dependencies" +ynh_add_fpm_config #================================================= # MODIFY A CONFIG FILE #================================================= -ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/data/config.php" +#ynh_add_config --template="../conf/config-dist.php" --destination="$final_path/data/config.php" -chmod 400 "$final_path/data/config.php" -chown $app "$final_path/data/config.php" +#chmod 400 "$final_path/data/config.php" +#chown $app "$final_path/data/config.php" #================================================= # RELOAD NGINX From dbee853238de11374cf9a4fbbbef766c1f557a4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Fri, 19 Nov 2021 15:07:08 +0100 Subject: [PATCH 53/59] Allow api (#27) * Allow API * Update upgrade * Update scripts/upgrade Co-authored-by: tituspijean Co-authored-by: tituspijean --- scripts/install | 2 ++ scripts/upgrade | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/scripts/install b/scripts/install index 5202159..d339473 100644 --- a/scripts/install +++ b/scripts/install @@ -114,6 +114,8 @@ then ynh_permission_update --permission="main" --add="visitors" fi +ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --auth_header="false" --show_tile="false" --protected="true" + #================================================= # RELOAD NGINX #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index a17e175..aed8bcf 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -60,6 +60,11 @@ if ynh_legacy_permissions_exists; then ynh_app_setting_delete --app=$app --key=is_public fi +# Add /api permission if needed +if ! ynh_permission_exists --permission="api"; then + ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --auth_header="false" --show_tile="false" --protected="true" +fi + #================================================= # CREATE DEDICATED USER #================================================= From 43d9d98fc511001f06f8cae749755cf8f593371d Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 19 Nov 2021 15:08:09 +0100 Subject: [PATCH 54/59] Update manifest.json --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 44da7f4..e87d4e6 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.1.3~ynh1", + "version": "3.1.3~ynh2", "url": "https://grocy.info", "upstream": { "license": "MIT", From d998e9b340ee5768717bb433f19c4e5b65df4320 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Fri, 19 Nov 2021 14:08:15 +0000 Subject: [PATCH 55/59] 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 8da0a91..cd6c974 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Web-based groceries & household management solution for your home -**Shipped version:** 3.1.3~ynh1 +**Shipped version:** 3.1.3~ynh2 **Demo:** https://en.demo.grocy.info/stockoverview diff --git a/README_fr.md b/README_fr.md index c9f491e..9305346 100644 --- a/README_fr.md +++ b/README_fr.md @@ -13,7 +13,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Solution Web de gestion d'épicerie et de gestion de la maison -**Version incluse :** 3.1.3~ynh1 +**Version incluse :** 3.1.3~ynh2 **Démo :** https://en.demo.grocy.info/stockoverview From 1bdc98441a86ae07d92bb2bbe7306f8f40fa87ef Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 1 Dec 2021 23:20:49 +0100 Subject: [PATCH 56/59] remove https --- conf/nginx.conf | 5 ----- scripts/remove | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 1994a8e..9aa7449 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -3,11 +3,6 @@ location / { # Path to source alias __FINALPATH__/public/ ; - # Force usage of https - if ($scheme = http) { - rewrite ^ https://$server_name$request_uri? permanent; - } - index index.php; client_max_body_size 50M; diff --git a/scripts/remove b/scripts/remove index 7ee6368..8576dac 100644 --- a/scripts/remove +++ b/scripts/remove @@ -25,7 +25,7 @@ final_path=$(ynh_app_setting_get --app=$app --key=final_path) ynh_script_progression --message="Removing $app main directory..." --weight=4 # Remove the app directory securely -ynh_secure_remove "$final_path" +ynh_secure_remove --file="$final_path" #================================================= # REMOVE NGINX CONFIGURATION From 8a94a86c8b47b1407401c51e62997984568c327b Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 1 Dec 2021 23:22:47 +0100 Subject: [PATCH 57/59] Update DESCRIPTION.md --- doc/DESCRIPTION.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/DESCRIPTION.md b/doc/DESCRIPTION.md index e69de29..6bdcf9d 100644 --- a/doc/DESCRIPTION.md +++ b/doc/DESCRIPTION.md @@ -0,0 +1 @@ +grocy is a web-based self-hosted groceries & household management solution for your home. \ No newline at end of file From 4112bf4d921dbaa4ac607d31b755bb060e48c981 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Wed, 1 Dec 2021 22:22:58 +0000 Subject: [PATCH 58/59] 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 cd6c974..84eb3e6 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in ## Overview -Web-based groceries & household management solution for your home +grocy is a web-based self-hosted groceries & household management solution for your home. **Shipped version:** 3.1.3~ynh2 diff --git a/README_fr.md b/README_fr.md index 9305346..363f645 100644 --- a/README_fr.md +++ b/README_fr.md @@ -11,7 +11,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour ## Vue d'ensemble -Solution Web de gestion d'épicerie et de gestion de la maison +grocy is a web-based self-hosted groceries & household management solution for your home. **Version incluse :** 3.1.3~ynh2 From 5327d670747accc446415903a40eda15e937d413 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 8 Dec 2021 22:48:08 +0100 Subject: [PATCH 59/59] Add config panel --- .github/workflows/updater.sh | 130 +++++++++++++++++++++++++++++++++++ config_panel.toml | 25 +++++++ manifest.json | 2 +- scripts/config | 95 +++++++++++++++++++++++++ scripts/install | 2 +- scripts/restore | 11 +-- scripts/upgrade | 17 ++++- 7 files changed, 275 insertions(+), 7 deletions(-) create mode 100755 .github/workflows/updater.sh create mode 100644 config_panel.toml create mode 100644 scripts/config diff --git a/.github/workflows/updater.sh b/.github/workflows/updater.sh new file mode 100755 index 0000000..4a51430 --- /dev/null +++ b/.github/workflows/updater.sh @@ -0,0 +1,130 @@ +#!/bin/bash + +#================================================= +# PACKAGE UPDATING HELPER +#================================================= + +# This script is meant to be run by GitHub Actions +# The YunoHost-Apps organisation offers a template Action to run this script periodically +# Since each app is different, maintainers can adapt its contents so as to perform +# automatic actions when a new upstream release is detected. + +# Remove this exit command when you are ready to run this Action +#exit 1 + +#================================================= +# FETCHING LATEST RELEASE AND ITS ASSETS +#================================================= + +# Fetching information +current_version=$(cat manifest.json | jq -j '.version|split("~")[0]') +repo=$(cat manifest.json | jq -j '.upstream.code|split("https://github.com/")[1]') +# Some jq magic is needed, because the latest upstream release is not always the latest version (e.g. security patches for older versions) +version=$(curl --silent "https://api.github.com/repos/$repo/releases" | jq -r '.[] | select( .prerelease != true ) | .tag_name' | sort -V | tail -1) +assets=($(curl --silent "https://api.github.com/repos/$repo/releases" | jq -r '[ .[] | select(.tag_name=="'$version'").assets[].browser_download_url ] | join(" ") | @sh' | tr -d "'")) + +# Later down the script, we assume the version has only digits and dots +# Sometimes the release name starts with a "v", so let's filter it out. +# You may need more tweaks here if the upstream repository has different naming conventions. +if [[ ${version:0:1} == "v" || ${version:0:1} == "V" ]]; then + version=${version:1} +fi + +# Setting up the environment variables +echo "Current version: $current_version" +echo "Latest release from upstream: $version" +echo "VERSION=$version" >> $GITHUB_ENV +# For the time being, let's assume the script will fail +echo "PROCEED=false" >> $GITHUB_ENV + +# Proceed only if the retrieved version is greater than the current one +if ! dpkg --compare-versions "$current_version" "lt" "$version" ; then + echo "::warning ::No new version available" + exit 0 +# Proceed only if a PR for this new version does not already exist +elif git ls-remote -q --exit-code --heads https://github.com/$GITHUB_REPOSITORY.git ci-auto-update-v$version ; then + echo "::warning ::A branch already exists for this update" + exit 0 +fi + +# Each release can hold multiple assets (e.g. binaries for different architectures, source code, etc.) +echo "${#assets[@]} available asset(s)" + +#================================================= +# UPDATE SOURCE FILES +#================================================= + +# Here we use the $assets variable to get the resources published in the upstream release. +# Here is an example for Grav, it has to be adapted in accordance with how the upstream releases look like. + +# Let's loop over the array of assets URLs +for asset_url in ${assets[@]}; do + +echo "Handling asset at $asset_url" + +# Assign the asset to a source file in conf/ directory +# Here we base the source file name upon a unique keyword in the assets url (admin vs. update) +# Leave $src empty to ignore the asset +case $asset_url in + *"grocy_"*".zip") + src="app" + ;; +esac + +# If $src is not empty, let's process the asset +if [ ! -z "$src" ]; then + +# Create the temporary directory +tempdir="$(mktemp -d)" + +# Download sources and calculate checksum +filename=${asset_url##*/} +curl --silent -4 -L $asset_url -o "$tempdir/$filename" +checksum=$(sha256sum "$tempdir/$filename" | head -c 64) + +# Delete temporary directory +rm -rf $tempdir + +# Get extension +if [[ $filename == *.tar.gz ]]; then + extension=tar.gz +else + extension=${filename##*.} +fi + +# Rewrite source file +cat < conf/$src.src +SOURCE_URL=$asset_url +SOURCE_SUM=$checksum +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=zip +SOURCE_IN_SUBDIR=false +SOURCE_EXTRACT=true +EOT +echo "... conf/$src.src updated" + +else +echo "... asset ignored" +fi + +done + +#================================================= +# SPECIFIC UPDATE STEPS +#================================================= + +# Any action on the app's source code can be done. +# The GitHub Action workflow takes care of committing all changes after this script ends. + +#================================================= +# GENERIC FINALIZATION +#================================================= + +# Replace new version in manifest +echo "$(jq -s --indent 4 ".[] | .version = \"$version~ynh1\"" manifest.json)" > manifest.json + +# No need to update the README, yunohost-bot takes care of it + +# The Action will proceed only if the PROCEED environment variable is set to true +echo "PROCEED=true" >> $GITHUB_ENV +exit 0 diff --git a/config_panel.toml b/config_panel.toml new file mode 100644 index 0000000..1ea9635 --- /dev/null +++ b/config_panel.toml @@ -0,0 +1,25 @@ +version = "1.0" + +[main] +name = "Grocy configuration" + + [main.php_fpm_config] + name = "PHP-FPM configuration" + + [main.php_fpm_config.fpm_footprint] + ask = "Memory footprint of the service?" + choices = ["low", "medium", "high", "specific"] + default = "low" + help = "low <= 20Mb per pool. medium between 20Mb and 40Mb per pool. high > 40Mb per pool.
Use specific to set a value with the following option." + + [main.php_fpm_config.free_footprint] + ask = "Memory footprint of the service?" + type = "number" + default = "0" + help = "Free field to specify exactly the footprint in Mb if you don't want to use one of the three previous values." + + [main.php_fpm_config.fpm_usage] + ask = "Expected usage of the service?" + choices = ["low", "medium", "high"] + default = "low" + help = "low: Personal usage, behind the SSO. No RAM footprint when not used, but the impact on the processor can be high if many users are using the service.
medium: Low usage, few people or/and publicly accessible. Low RAM footprint, medium processor footprint when used.
high: High usage, frequently visited website. High RAM footprint, but lower on processor usage and quickly responding." diff --git a/manifest.json b/manifest.json index e87d4e6..a7a14d8 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Web-based groceries & household management solution for your home", "fr": "Solution Web de gestion d'épicerie et de gestion de la maison" }, - "version": "3.1.3~ynh2", + "version": "3.1.3~ynh3", "url": "https://grocy.info", "upstream": { "license": "MIT", diff --git a/scripts/config b/scripts/config new file mode 100644 index 0000000..3440bd2 --- /dev/null +++ b/scripts/config @@ -0,0 +1,95 @@ +#!/bin/bash + +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +ynh_abort_if_errors + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) +current_fpm_footprint=$(ynh_app_setting_get --app=$app --key=fpm_footprint) + +#================================================= +# SPECIFIC GETTERS FOR TOML SHORT KEY +#================================================= + +get__fpm_footprint() { + # Free footprint value for php-fpm + # Check if current_fpm_footprint is an integer + if [ "$current_fpm_footprint" -eq "$current_fpm_footprint" ] 2> /dev/null + then + echo "specific" + else + echo "$current_fpm_footprint" + fi +} + +get__free_footprint() { + # Free footprint value for php-fpm + # Check if current_fpm_footprint is an integer + if [ "$current_fpm_footprint" -eq "$current_fpm_footprint" ] 2> /dev/null + then + # If current_fpm_footprint is an integer, that's a numeric value for the footprint + echo "$current_fpm_footprint" + else + echo "0" + fi +} + +#================================================= +# SPECIFIC SETTERS FOR TOML SHORT KEYS +#================================================= + +set__fpm_footprint() { + if [ "$fpm_footprint" != "specific" ] + then + ynh_app_setting_set --app=$app --key=fpm_footprint --value="$fpm_footprint" + fi +} + +set__free_footprint() { + if [ "$fpm_footprint" = "specific" ] + then + ynh_app_setting_set --app=$app --key=fpm_footprint --value="$free_footprint" + fi +} + +#================================================= +# GENERIC FINALIZATION +#================================================= + +ynh_app_config_validate() { + _ynh_app_config_validate + + if [ "${changed[fpm_usage]}" == "true" ] || [ "${changed[fpm_footprint]}" == "true" ] || [ "${changed[free_footprint]}" == "true" ]; then + # If fpm_footprint is set to 'specific', use $free_footprint value. + if [ "$fpm_footprint" = "specific" ] + then + fpm_footprint=$free_footprint + fi + + if [ "$fpm_footprint" == "0" ] + then + ynh_print_err --message="When selecting 'specific', you have to set a footprint value into the field below." + + exit 0 + fi + fi +} + +ynh_app_config_apply() { + _ynh_app_config_apply + + ynh_add_fpm_config --phpversion=$phpversion --usage=$fpm_usage --footprint=$fpm_footprint +} + +ynh_app_config_run $1 diff --git a/scripts/install b/scripts/install index d339473..4447174 100644 --- a/scripts/install +++ b/scripts/install @@ -90,7 +90,7 @@ ynh_add_nginx_config ynh_script_progression --message="Configuring PHP-FPM..." --weight=3 # Create a dedicated PHP-FPM config -ynh_add_fpm_config +ynh_add_fpm_config --usage=low --footprint=low phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) #================================================= diff --git a/scripts/restore b/scripts/restore index c1a8324..2270694 100644 --- a/scripts/restore +++ b/scripts/restore @@ -28,13 +28,15 @@ path_url=$(ynh_app_setting_get --app=$app --key=path) final_path=$(ynh_app_setting_get --app=$app --key=final_path) phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) +fpm_footprint=$(ynh_app_setting_get --app=$app --key=fpm_footprint) +fpm_usage=$(ynh_app_setting_get --app=$app --key=fpm_usage) + #================================================= # CHECK IF THE APP CAN BE RESTORED #================================================= ynh_script_progression --message="Validating restoration parameters..." --weight=1 -test ! -d $final_path \ - || ynh_die --message="There is already a directory: $final_path " +test ! -d $final_path || ynh_die --message="There is already a directory: $final_path " #================================================= # STANDARD RESTORATION STEPS @@ -77,8 +79,9 @@ ynh_install_app_dependencies $pkg_dependencies ynh_script_progression --message="Restoring PHP-FPM configuration..." --weight=1 ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" -# Recreate a dedicated PHP-FPM config -#ynh_add_fpm_config + +# Recreate a dedicated php-fpm config +ynh_add_fpm_config --usage=$fpm_usage --footprint=$fpm_footprint --phpversion=$phpversion #================================================= # GENERIC FINALIZATION diff --git a/scripts/upgrade b/scripts/upgrade index aed8bcf..f194231 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -22,6 +22,9 @@ final_path=$(ynh_app_setting_get --app=$app --key=final_path) language=$(ynh_app_setting_get --app=$app --key=language) phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) +fpm_footprint=$(ynh_app_setting_get --app=$app --key=fpm_footprint) +fpm_usage=$(ynh_app_setting_get --app=$app --key=fpm_usage) + #================================================= # CHECK VERSION #================================================= @@ -53,6 +56,18 @@ if [ -z "$final_path" ]; then ynh_app_setting_set --app=$app --key=final_path --value=$final_path fi +# If fpm_footprint doesn't exist, create it +if [ -z "$fpm_footprint" ]; then + fpm_footprint=low + ynh_app_setting_set --app=$app --key=fpm_footprint --value=$fpm_footprint +fi + +# If fpm_usage doesn't exist, create it +if [ -z "$fpm_usage" ]; then + fpm_usage=low + ynh_app_setting_set --app=$app --key=fpm_usage --value=$fpm_usage +fi + # Cleaning legacy permissions if ynh_legacy_permissions_exists; then ynh_legacy_permissions_delete_all @@ -110,7 +125,7 @@ ynh_install_app_dependencies $pkg_dependencies ynh_script_progression --message="Upgrading PHP-FPM configuration..." --weight=1 # Create a dedicated php-fpm config -ynh_add_fpm_config +ynh_add_fpm_config --phpversion=$phpversion --usage=$fpm_usage --footprint=$fpm_footprint #================================================= # MODIFY A CONFIG FILE