diff --git a/README.md b/README.md index 00a2308..fe1bca7 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,65 @@ -Yunohost app for « I hate money » budget web app -================================================ +--- -[![Install « I hate money » with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=ihatemoney) + -- Supported Yunohost versions : 2.6.x, 2.7.x 3.x -- Tested Yunohost version : 3.3.1 +# I Hate Money for YunoHost -*NB: That means I'll try not to drop support for YunoHost 2.x too soon, and -accept patches to keep retro-compatibility, but I'll not test it myself against -YunoHost 2.x* +[![Integration level](https://dash.yunohost.org/integration/ihatemoney.svg)](https://dash.yunohost.org/appci/app/ihatemoney) ![](https://ci-apps.yunohost.org/ci/badges/ihatemoney.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/ihatemoney.maintain.svg) +[![Install I Hate Money with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=ihatemoney) -Backs on MySQL database, the identifiers are per-project, not per-user, so no -way to do advanced SSO integration with yunohost accounts. +*[Lire ce readme en français.](./README_fr.md)* -The behaviour is either: +> *This package allows you to install I Hate Money 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 + +I hate money is a web application made to ease shared budget management. It keeps track of who bought what, when, and for whom; and helps to settle the bills. + +**Shipped version:** 4.1.5~ynh2 + +## Screenshots + +![](./doc/screenshots/screenshot_1_global.webp) +![](./doc/screenshots/screenshot_2_new_operation.webp) + +## Disclaimers / important information + +* Is LDAP and HTTP authentication supported ? **No** + +The logins are per-project (not per-user) so it's not integrable in the Yunohost login system. + +The app can be public or not. The behaviour is either: - **non-public app**: - yunohost login required - per-project identifiers required - - any yunohost user with authorized access to the app can create a new - project). + - any yunohost user with access to the app can create a new project. - **public app** : - no yunohost login required - per-project identifiers required - any visitor can create a new project. -Update ------- +## Documentation and resources -To update the app, use: +* Official app website: https://github.com/spiral-project/ihatemoney +* Official admin documentation: https://ihatemoney.readthedocs.org/ +* Upstream app code repository: https://github.com/spiral-project/ihatemoney +* YunoHost documentation for this app: https://yunohost.org/app_ihatemoney +* Report a bug: https://github.com/YunoHost-Apps/ihatemoney_ynh/issues -`sudo yunohost app upgrade ihatemoney -u https://github.com/YunoHost-Apps/ihatemoney_ynh` - +## Developer info -Maintainer ----------- +Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/ihatemoney_ynh/tree/testing). -I rely on -[ihatemoney official releases](https://github.com/spiral-project/ihatemoney/releases) -(tarballs). Don't hesitate to pull-request this repo if I missed one :-). - - -Ihatemoney license ------------------- - -> The code is distributed under a BSD beerware derivative: if you meet the -> people in person and you want to pay them a craft beer, you are highly -> encouraged to do so. - -[Full license text](https://github.com/spiral-project/ihatemoney/blob/master/LICENSE) +To try the testing branch, please proceed like that. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/ihatemoney_ynh/tree/testing --debug +or +sudo yunohost app upgrade ihatemoney -u https://github.com/YunoHost-Apps/ihatemoney_ynh/tree/testing --debug +``` +**More info regarding app packaging:** https://yunohost.org/packaging_apps diff --git a/README_fr.md b/README_fr.md new file mode 100644 index 0000000..2331937 --- /dev/null +++ b/README_fr.md @@ -0,0 +1,59 @@ +# I Hate Money pour YunoHost + +[![Niveau d'intégration](https://dash.yunohost.org/integration/ihatemoney.svg)](https://dash.yunohost.org/appci/app/ihatemoney) ![](https://ci-apps.yunohost.org/ci/badges/ihatemoney.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/ihatemoney.maintain.svg) +[![Installer I Hate Money avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=ihatemoney) + +*[Read this readme in english.](./README.md)* +*[Lire ce readme en français.](./README_fr.md)* + +> *Ce package vous permet d'installer I Hate Money 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 + +Une application web de comptes partagés à plusieurs + +**Version incluse:** 4.1.5~ynh2 + +## Captures d'écran + +![](./doc/screenshots/screenshot_1_global.webp) +![](./doc/screenshots/screenshot_2_new_operation.webp) + +## Avertissements / informations importantes + +* L'authentification LDAP et HTTP est-elle prise en charge ? **Non** + +L'authentification est par projet (et non par utilisateur) donc ce n'est pas intégrable dans le système d'authentification de Yunohost. + +L'application peut néanmoins être configurée en public ou non : + +- **app non publique**: + - authentification Yunohost requise + - identifiants de projets requis + - Tout utilisateur Yunohost avec accès à l'app peut créer un nouveau projet. +- **app publique** : + - authentification Yunohost non requise + - identifiants de projets requis + - Tout visiteur peut créer un nouveau projet. + +## Documentations et ressources + +* Site officiel de l'app : https://github.com/spiral-project/ihatemoney +* Documentation officielle de l'admin: https://ihatemoney.readthedocs.org/ +* Dépôt de code officiel de l'app: https://github.com/spiral-project/ihatemoney +* Documentation YunoHost pour cette app: https://yunohost.org/app_ihatemoney +* Signaler un bug: https://github.com/YunoHost-Apps/ihatemoney_ynh/issues + +## Informations pour les développeurs + +Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/ihatemoney_ynh/tree/testing). + +Pour essayer la branche testing, procédez comme suit. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/ihatemoney_ynh/tree/testing --debug +or +sudo yunohost app upgrade ihatemoney -u https://github.com/YunoHost-Apps/ihatemoney_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/check_process b/check_process index 755855f..461d489 100644 --- a/check_process +++ b/check_process @@ -1,8 +1,8 @@ ;; Full test ; Manifest - domain="domain.tld" (DOMAIN) - path="/path" (PATH) - is_public=1 (PUBLIC|public=1|private=0) + domain="domain.tld" + path="/path" + is_public=1 ; Checks pkg_linter=1 setup_sub_dir=1 @@ -11,23 +11,14 @@ setup_private=1 setup_public=1 upgrade=1 + upgrade=1 from_commit=0f904d99367cfec27ec5fe303941fbf1124a7571 backup_restore=1 - multi_instance=0 - incorrect_path=1 + multi_instance=1 port_already_use=0 - change_url=0 -;;; Levels - Level 1=auto - Level 2=auto - Level 3=auto - # There is no user concept in ihatemoney - Level 4=1 - Level 5=auto - Level 6=auto - Level 7=auto - Level 8=0 - Level 9=0 - Level 10=0 + change_url=1 ;;; Options Email= -Notification=change +Notification=none +;;; Upgrade options + ; commit=0f904d99367cfec27ec5fe303941fbf1124a7571 + name=Before refactoring yunohost package diff --git a/conf/gunicorn.conf.py b/conf/gunicorn.conf.py index 60fcdd1..f38b59a 100644 --- a/conf/gunicorn.conf.py +++ b/conf/gunicorn.conf.py @@ -2,6 +2,6 @@ backlog = 2048 daemon = False debug = True workers = 3 -logfile = "/var/log/ihatemoney/budget.gunicorn.log" +logfile = "/var/log/__APP__/budget.gunicorn.log" loglevel = "info" -bind = "unix:/tmp/budget.gunicorn.sock" +bind = "unix:/tmp/budget.gunicorn___APP__.sock" diff --git a/conf/ihatemoney.cfg b/conf/ihatemoney.cfg index f41f6ce..147c189 100644 --- a/conf/ihatemoney.cfg +++ b/conf/ihatemoney.cfg @@ -1,10 +1,10 @@ DEBUG = True -SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://ihatemoney:MY_MYSQL_PW@localhost/ihatemoney' +SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://__DB_USER__:__DB_PWD__@localhost/__DB_NAME__' SQLACHEMY_ECHO = DEBUG -SECRET_KEY = "MY_SECRET_KEY" +SECRET_KEY = "__SECRET_KEY__" -MAIL_DEFAULT_SENDER = ("Budget manager", "MY_EMAIL") -APPLICATION_ROOT='MY_PATH' +MAIL_DEFAULT_SENDER = ("Budget manager", "__MAILS_SENDER__") +__SUB_PATH_ONLY__APPLICATION_ROOT='__PATH__' try: from settings import * diff --git a/conf/nginx.conf b/conf/nginx.conf index 3d13167..e096719 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,8 +1,9 @@ -location PATHTOCHANGE/static/ { - alias /opt/yunohost/ihatemoney/venv/lib/pythonPYTHON_VERSION/site-packages/ihatemoney/static/; +#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; +location __PATH__/static/ { + alias __PYTHON_VENV_SITE_PACKAGES__/ihatemoney/static/; } -location PATHTOCHANGE { - # Force https. +location __PATH__/ { + # Force usage of https if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; } @@ -18,7 +19,7 @@ location PATHTOCHANGE { proxy_busy_buffers_size 32k; proxy_intercept_errors on; if (!-f $request_filename) { - proxy_pass http://unix:/tmp/budget.gunicorn.sock; + proxy_pass http://unix:/tmp/budget.gunicorn___APP__.sock; break; } diff --git a/conf/supervisord.conf b/conf/supervisord.conf deleted file mode 100644 index 86e36b3..0000000 --- a/conf/supervisord.conf +++ /dev/null @@ -1,6 +0,0 @@ -[program:budget] -command=/opt/yunohost/ihatemoney/venv/bin/gunicorn -c /etc/ihatemoney/gunicorn.conf.py ihatemoney.wsgi:application -user=ihatemoney -autostart=true -autorestart=true -redirect_stderr=true diff --git a/conf/systemd.service b/conf/systemd.service new file mode 100644 index 0000000..5803179 --- /dev/null +++ b/conf/systemd.service @@ -0,0 +1,15 @@ +[Unit] +Description=I hate money +Requires=network.target mysql.service +After=network.target mysql.service + +[Service] +Type=simple +User=__APP__ +Environment=IHATEMONEY_SETTINGS_FILE_PATH=__FINALPATH__/ihatemoney.cfg +ExecStart=__FINALPATH__/venv/bin/gunicorn -c __FINALPATH__/gunicorn.conf.py ihatemoney.wsgi:application +Restart=always +RestartSec=2 + +[Install] +WantedBy=multi-user.target diff --git a/doc/DISCLAIMER.md b/doc/DISCLAIMER.md new file mode 100644 index 0000000..37b4fcf --- /dev/null +++ b/doc/DISCLAIMER.md @@ -0,0 +1,10 @@ +* LDAP authentication and Single Sign-on is not supported. The login mechanism in IHateMoney is per-project (not per-user) and therefore can't be integrated in YunoHost. + +- **non-public app**: + - yunohost login required + - per-project identifiers required + - any yunohost user with access to the app can create a new project. +- **public app** : + - no yunohost login required + - per-project identifiers required + - any visitor can create a new project. diff --git a/doc/DISCLAIMER_fr.md b/doc/DISCLAIMER_fr.md new file mode 100644 index 0000000..5403414 --- /dev/null +++ b/doc/DISCLAIMER_fr.md @@ -0,0 +1,10 @@ +* L'authentification LDAP et login unifié (SSO) n'est pas supportée. Le mécanisme de connexion sur IHateMoney se fait par projet et ne peut donc pas être intégrée dans YunoHost + +- **app non publique**: + - authentification Yunohost requise + - identifiants de projets requis + - Tout utilisateur Yunohost avec accès à l'app peut créer un nouveau projet. +- **app publique** : + - authentification Yunohost non requise + - identifiants de projets requis + - Tout visiteur peut créer un nouveau projet. diff --git a/doc/screenshots/screenshot_1_global.webp b/doc/screenshots/screenshot_1_global.webp new file mode 100644 index 0000000..e626c28 Binary files /dev/null and b/doc/screenshots/screenshot_1_global.webp differ diff --git a/doc/screenshots/screenshot_2_new_operation.webp b/doc/screenshots/screenshot_2_new_operation.webp new file mode 100644 index 0000000..d76564d Binary files /dev/null and b/doc/screenshots/screenshot_2_new_operation.webp differ diff --git a/manifest.json b/manifest.json index 5e1bd73..88e0287 100644 --- a/manifest.json +++ b/manifest.json @@ -3,49 +3,47 @@ "id": "ihatemoney", "packaging_format": 1, "description": { - "en": "A simple shared budget manager web application", - "fr": "Une application web de comptes partagés à plusieurs" + "en": "Simple app to manage your collective expenses", + "fr": "Gérez simplement vos dépenses collectives" }, "url": "http://ihatemoney.org/", - "version": "4.1.5~ynh2", - "license": "free", + "version": "4.1.5~ynh3", + "license": "Beerware", + "upstream": { + "license": "MIT", + "website": "https://github.com/spiral-project/ihatemoney", + "admindoc": "https://ihatemoney.readthedocs.org/", + "code": "https://github.com/spiral-project/ihatemoney", + "demo": "https://ihatemoney.org/demo/" + }, "maintainer": { "name": "Jocelyn Delalande", "email": "jocelyn@crapouillou.net", "url": "https://jocelyn.delalande.fr" }, "requirements": { - "yunohost": ">= 3.8" + "yunohost": ">= 4.1.0" }, - "multi_instance": false, + "multi_instance": true, "services": ["nginx", "mysql", "postfix"], "arguments": { "install" : [ { "name": "domain", - "type": "domain", - "ask": { - "en": "Choose a domain for ihatemoney", - "fr": "Choisir un domaine pour ihatemoney" - }, - "example": "example.com" + "type": "domain" }, { "name": "path", "type": "path", - "ask": { - "en": "Choose a path for ihatemoney", - "fr": "Choisir un chemin pour ihatemoney" - }, - "example": "/example", + "example": "/ihatemoney", "default": "/ihatemoney" }, { "name": "is_public", "type": "boolean", - "ask": { - "en": "Is it a public website ? (even if service is public, each project is protected by a password)", - "fr": "Le service est-il public ? (même dans ce cas, chaque projet est protégé par un mot de passe)" + "help": { + "en": "Each ihatemoney project is protected by a password anyways", + "fr": "Les projets ihatemoney sont protégés par un mot de passe dans tous les cas" }, "default": true } diff --git a/scripts/_common.sh b/scripts/_common.sh index 8c54da6..7ca836a 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -1,69 +1,56 @@ +#!/bin/bash + +#================================================= +# COMMON VARIABLES +#================================================= + +# dependencies used by the app +pkg_dependencies=( + python3-dev + python3-venv + libffi-dev + libssl-dev +) + +pip_dependencies=( + 'setuptools>=18.5' + 'gunicorn>=19.3.0' + 'PyMySQL>=0.9,<0.10' + 'SQLAlchemy<1.4' + 'ihatemoney>=4,<5' +) + ### Constants -supervisor_conf_path="/etc/supervisor/conf.d/ihatemoney.conf" -gunicorn_conf_path="/etc/ihatemoney/gunicorn.conf.py" -ihatemoney_conf_path="/etc/ihatemoney/ihatemoney.cfg" -INSTALL_DIR="/opt/yunohost/ihatemoney" +#================================================= +# PERSONAL HELPERS +#================================================= +__ynh_python_venv_setup() { + local -A args_array=( [d]=venv_dir= [p]=packages= ) + local venv_dir + local packages + ynh_handle_getopts_args "$@" -### Functions + python3 -m venv --system-site-packages "$venv_dir" - -install_apt_dependencies() { - ynh_install_app_dependencies \ - python3-dev \ - python3-virtualenv \ - libffi-dev \ - libssl-dev \ - supervisor \ - virtualenv + IFS=" " read -r -a pip_packages <<< "$packages" + "$venv_dir/bin/python3" -m pip install --upgrade pip "${pip_packages[@]}" } -create_unix_user() { - mkdir -p /opt/yunohost - useradd ihatemoney -d /opt/yunohost/ihatemoney/ --create-home || ynh_die "User creation failed" +__ynh_python_venv_get_site_packages_dir() { + local -A args_array=( [d]=venv_dir= ) + local venv_dir + ynh_handle_getopts_args "$@" + + "$venv_dir/bin/python3" -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])' } -create_system_dirs() { - install -o ihatemoney -g ihatemoney -m 755 -d \ - /var/log/ihatemoney \ - /etc/ihatemoney - mkdir -p /opt/yunohost -} -init_virtualenv () { - virtualenv /opt/yunohost/ihatemoney/venv --python /usr/bin/python3 +#================================================= +# EXPERIMENTAL HELPERS +#================================================= - # PyMySQL → cryptography → setuptools>=18.5 - # Required on Jessie, Stretch has setuptools>=18.5 - /opt/yunohost/ihatemoney/venv/bin/pip install 'setuptools>=18.5' -} - -pip_install () { - # SQLAlchemy requirement is workaround https://github.com/pallets/flask-sqlalchemy/issues/910 - # Might be removed later when IHM dependency set will no longer prevent working installation. - /opt/yunohost/ihatemoney/venv/bin/pip install --upgrade \ - 'gunicorn>=19.3.0' \ - 'PyMySQL>=0.9,<0.10' \ - 'ihatemoney>=4,<5' \ - 'SQLAlchemy<1.4' \ - -} - -configure_nginx () { - local domain=$1 - local path=$2 - local python_version="$(readlink /usr/bin/python3|sed s/.*python//)" - - ynh_replace_string "PATHTOCHANGE" "$path" ../conf/nginx.conf - ynh_replace_string "PYTHON_VERSION" "$python_version" ../conf/nginx.conf - # Fix double-slash for domain-root install - ynh_replace_string "location //" "location /" ../conf/nginx.conf - install -o root -g root -m644 \ - ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/ihatemoney.conf -} - -configure_supervisor () { - install -o root -g root -m 644 \ - ../conf/supervisord.conf /etc/supervisor/conf.d/ihatemoney.conf -} +#================================================= +# FUTURE OFFICIAL HELPERS +#================================================= diff --git a/scripts/backup b/scripts/backup old mode 100644 new mode 100755 index 7c21e82..030071d --- a/scripts/backup +++ b/scripts/backup @@ -1,34 +1,82 @@ #!/bin/bash -# Source YunoHost helpers +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +# Exit if an error occurs during the execution of the script ynh_abort_if_errors -# Get multi-instances specific variables +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info --message="Loading installation settings..." + app=$YNH_APP_INSTANCE_NAME -# Set app specific variables -dbname=$app -dbuser=$app +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) -INSTALL_DIR=/opt/yunohost/ihatemoney +#================================================= +# DECLARE DATA AND CONF FILES TO BACKUP +#================================================= +ynh_print_info --message="Declaring files to be backed up..." -# Retrieve app settings -domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_app_setting_get "$app" path) -dbpass=$(ynh_app_setting_get "$app" mysqlpwd) +### N.B. : the following 'ynh_backup' calls are only a *declaration* of what needs +### to be backuped and not an actual copy of any file. The actual backup that +### creates and fill the archive with the files happens in the core after this +### script is called. Hence ynh_backups calls takes basically 0 seconds to run. -# Backup conf files -mkdir ./conf -ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" -ynh_backup "$gunicorn_conf_path" -ynh_backup "$supervisor_conf_path" -ynh_backup "$ihatemoney_conf_path" +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= -# Dump the database -mysqldump -u "$dbuser" -p"$dbpass" --no-create-db "$dbname" > ./db.sql +ynh_backup --src_path="$final_path" -# Backup code and venv -ynh_backup "$INSTALL_DIR" "install_dir" +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# BACKUP FAIL2BAN CONFIGURATION +#================================================= + +# ynh_backup --src_path="/etc/fail2ban/jail.d/$app.conf" +# ynh_backup --src_path="/etc/fail2ban/filter.d/$app.conf" + +#================================================= +# SPECIFIC BACKUP +#================================================= +# BACKUP SYSTEMD +#================================================= + +ynh_backup --src_path="/etc/systemd/system/$app.service" + +#================================================= +# BACKUP THE MYSQL DATABASE +#================================================= +ynh_print_info --message="Backing up the MySQL database..." + +### (However, things like MySQL dumps *do* take some time to run, though the +### copy of the generated dump to the archive still happens later) + +ynh_mysql_dump_db --database="$db_name" > db.sql + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." diff --git a/scripts/change_url b/scripts/change_url new file mode 100644 index 0000000..92e79e2 --- /dev/null +++ b/scripts/change_url @@ -0,0 +1,150 @@ +#!/bin/bash + +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +old_domain=$YNH_APP_OLD_DOMAIN +old_path=$YNH_APP_OLD_PATH + +new_domain=$YNH_APP_NEW_DOMAIN +new_path=$YNH_APP_NEW_PATH + +app=$YNH_APP_INSTANCE_NAME +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +db_pwd=$(ynh_app_setting_get --app=$app --key=mysqlpwd) + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --time --weight=1 + +# Needed for helper "ynh_add_nginx_config" +final_path=$(ynh_app_setting_get --app=$app --key=final_path) + +python_venv_site_packages=$(__ynh_python_venv_get_site_packages_dir -d "$final_path/venv") + +#================================================= +# BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." --time --weight=1 + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + # Remove the new domain config file, the remove script won't do it as it doesn't know yet its location. + ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" + + # Restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# CHECK WHICH PARTS SHOULD BE CHANGED +#================================================= + +change_domain=0 +if [ "$old_domain" != "$new_domain" ] +then + change_domain=1 +fi + +change_path=0 +if [ "$old_path" != "$new_path" ] +then + change_path=1 +fi + +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="stop" --log_path=systemd + +#================================================= +# MODIFY URL IN NGINX CONF +#================================================= +ynh_script_progression --message="Updating NGINX web server configuration..." --time --weight=1 + +nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf + +# Change the path in the NGINX config file +if [ $change_path -eq 1 ] +then + # Make a backup of the original NGINX config file if modified + ynh_backup_if_checksum_is_different --file="$nginx_conf_path" + # Set global variables for NGINX helper + domain="$old_domain" + path_url="$new_path" + # Create a dedicated NGINX config + ynh_add_nginx_config +fi + +# Change the domain for NGINX +if [ $change_domain -eq 1 ] +then + # Delete file checksum for the old conf file location + ynh_delete_file_checksum --file="$nginx_conf_path" + mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf + # Store file checksum for the new config file location + ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" +fi + +#================================================= +# SPECIFIC MODIFICATIONS +#================================================= +# Setup ihatemoney.cfg +#================================================= + +path_url="$new_path" +domain="$new_domain" + +# Secret key for cookies encryption. +secret_key=$(ynh_string_random --length 32) +mails_sender="no-reply@$domain" +# Allows to comment some config lines if not using sub path +sub_path_only="$(if [[ "$path_url" == "/" ]]; then echo '# ' ; else echo ''; fi)" + +ynh_backup_if_checksum_is_different --file="$final_path/ihatemoney.cfg" +ynh_add_config --template ../conf/ihatemoney.cfg --destination "$final_path/ihatemoney.cfg" + +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" + +#================================================= +# GENERIC FINALISATION +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path=systemd + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --time --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Change of URL completed for $app" --time --last diff --git a/scripts/install b/scripts/install index 8c1202c..eb05f17 100755 --- a/scripts/install +++ b/scripts/install @@ -1,88 +1,191 @@ #!/bin/bash -# Source YunoHost helpers +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + source _common.sh source /usr/share/yunohost/helpers -# Retrieve arguments -domain=$YNH_APP_ARG_DOMAIN -path=$YNH_APP_ARG_PATH -is_public=$YNH_APP_ARG_IS_PUBLIC -app=ihatemoney - -# Database settings -db_pwd=$(ynh_string_random) -db_name=$app -db_user=$app - -# Constant arguments -secret_key=$(ynh_string_random --length 32) -mails_sender="no-reply@${domain}" - +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= +# Exit if an error occurs during the execution of the script ynh_abort_if_errors -ynh_webpath_register $app $domain $path +#================================================= +# RETRIEVE ARGUMENTS FROM THE MANIFEST +#================================================= -# Configure database -ynh_mysql_create_db "$db_name" "$db_user" "$db_pwd" +domain=$YNH_APP_ARG_DOMAIN +path_url=$YNH_APP_ARG_PATH +is_public=$YNH_APP_ARG_IS_PUBLIC +app=$YNH_APP_INSTANCE_NAME -# Save app settings -ynh_app_setting_set "$app" mysqlpwd "$db_pwd" -ynh_app_setting_set "$app" is_public "$is_public" +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= +ynh_script_progression --message="Validating installation parameters..." --weight=1 -install_apt_dependencies +final_path=/var/www/$app +test ! -e "$final_path" || ynh_die --message="This path already contains a folder" -create_unix_user +# Register (book) web path +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url -# Prepare venv -init_virtualenv -pip_install +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= +ynh_script_progression --message="Storing installation settings..." --weight=1 -create_system_dirs +ynh_app_setting_set --app=$app --key=domain --value=$domain +ynh_app_setting_set --app=$app --key=path --value=$path_url -# Configure gunicorn -install -o ihatemoney -g ihatemoney -m 644 \ - ../conf/gunicorn.conf.py /etc/ihatemoney/gunicorn.conf.py +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Installing dependencies..." --weight=3 -# Configure supervisor -configure_supervisor -# In case it was already installed before, -# so that it picks /etc/supervisor/conf.d/ihatemoney.conf: -supervisorctl update -yunohost service add supervisor +ynh_install_app_dependencies "${pkg_dependencies[@]}" -# Configure ihatemoney -ynh_replace_string "MY_SECRET_KEY" "$secret_key" ../conf/ihatemoney.cfg -ynh_replace_string "MY_EMAIL" "$mails_sender" ../conf/ihatemoney.cfg -ynh_replace_string "MY_MYSQL_PW" "$db_pwd" ../conf/ihatemoney.cfg -ynh_replace_string "MY_PATH" "$path" ../conf/ihatemoney.cfg -# Remove the conf directive if served at root -sed -i "/APPLICATION_ROOT='\/'/d" ../conf/ihatemoney.cfg -install -o ihatemoney -g ihatemoney -m 640 \ - ../conf/ihatemoney.cfg /etc/ihatemoney/ihatemoney.cfg +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Configuring system user..." --weight=1 -# If app is public, add url to SSOWat conf as skipped_uris -if [[ "$is_public" -ne 0 ]]; -then - ynh_app_setting_set $app unprotected_uris "/" -fi +# Create a system user +ynh_system_user_create --username=$app --home_dir="$final_path" -# Configure Nginx -configure_nginx "$domain" "$path" +#================================================= +# CREATE A MYSQL DATABASE +#================================================= +ynh_script_progression --message="Creating a MySQL database..." --weight=1 -# Start backend -systemctl start supervisor +db_name=$(ynh_sanitize_dbid --db_name=$app) +db_user=$db_name +ynh_app_setting_set --app=$app --key=db_name --value=$db_name +ynh_mysql_setup_db --db_user=$db_user --db_name=$db_name +# defines $db_pwd and setting mysqlpwd -# Wait that gunicorn is ready to consider the install finished, that is to -# avoid HTTP 502 right after installation -for i in `seq 1 120` -do - test -S /tmp/budget.gunicorn.sock && break +#================================================= +# SPECIFIC SETUP +#================================================= +# Init venv +#================================================= + +ynh_script_progression --message="Configuring the app's installation..." --weight=6 + +ynh_app_setting_set --app=$app --key=final_path --value=$final_path + +__ynh_python_venv_setup --venv_dir="$final_path/venv" --packages "${pip_dependencies[*]}" +python_venv_site_packages=$(__ynh_python_venv_get_site_packages_dir -d "$final_path/venv") + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Configuring NGINX web server..." --weight=1 + +# Create a dedicated NGINX config +## Needs $python_venv_site_packages +ynh_add_nginx_config + +#================================================= +# Setup gunicorn +#================================================= + +ynh_add_config --template ../conf/gunicorn.conf.py --destination "$final_path/gunicorn.conf.py" +chmod 644 "$final_path/gunicorn.conf.py" + +#================================================= +# Setup ihatemoney +#================================================= + +# Secret key for cookies encryption. +secret_key=$(ynh_string_random --length 32) +mails_sender="no-reply@$domain" +# Allows to comment some config lines if not using sub path +sub_path_only="$(if [[ "$path_url" == "/" ]]; then echo '# ' ; else echo ''; fi)" + +ynh_add_config --template ../conf/ihatemoney.cfg --destination "$final_path/ihatemoney.cfg" +chmod 640 "$final_path/ihatemoney.cfg" + + +# FIXME: this should be managed by the core in the future +# Here, as a packager, you may have to tweak the ownerhsip/permissions +# such that the appropriate users (e.g. maybe www-data) can access +# files in some cases. +# But FOR THE LOVE OF GOD, do not allow r/x for "others" on the entire folder - +# this will be treated as a security issue. +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_script_progression --message="Configuring a systemd service..." --weight=1 + +# Create a dedicated systemd config +ynh_add_systemd_config + +#================================================= +# GENERIC FINALIZATION +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 + +yunohost service add $app --description="$app daemon for IHateMoney" --log_type=systemd + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=1 + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="systemd" --line_match="Booting worker" --timeout 30 + +# line_match isn't enough because ihatemoney may stop if database upgrades +for _ in {1..20}; do + test -S /tmp/budget.gunicorn_$app.sock && break sleep 1 done -# If socket not ready after 2 minutes waiting, ihatemoney will not work. -test -S /tmp/budget.gunicorn.sock || ynh_die +#================================================= +# SETUP FAIL2BAN +#================================================= +# ynh_script_progression --message="Configuring Fail2Ban..." --weight=1 -systemctl reload nginx +# Create a dedicated Fail2Ban config +# ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" + +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Configuring permissions..." --weight=1 + +# Make app public if necessary +if [ $is_public -eq 1 ] +then + # Everyone can access the app. + # The "main" permission is automatically created before the install script. + ynh_permission_update --permission="main" --add="visitors" +fi + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Installation of $app completed" --last diff --git a/scripts/remove b/scripts/remove index 5620f80..4685e83 100755 --- a/scripts/remove +++ b/scripts/remove @@ -1,37 +1,109 @@ #!/bin/bash -# Source YunoHost helpers +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh source /usr/share/yunohost/helpers -# supervisord and other Debian dependencies remain installed -# there is no way to know if they are used by other programs +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 -# Retrieve arguments -app=ihatemoney -domain=$(ynh_app_setting_get $app domain) -db_user=$app -db_name=$app +app=$YNH_APP_INSTANCE_NAME -# Stop service -supervisorctl stop budget +domain=$(ynh_app_setting_get --app=$app --key=domain) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +final_path=$(ynh_app_setting_get --app=$app --key=final_path) -# Drop database -ynh_mysql_drop_db $db_name -ynh_mysql_drop_user $db_user +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE SERVICE INTEGRATION IN YUNOHOST +#================================================= -# Remove src and venv -ynh_secure_remove /opt/yunohost/ihatemoney +# 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 settings -ynh_secure_remove /etc/ihatemoney -ynh_secure_remove /etc/supervisor/conf.d/ihatemoney.conf -ynh_remove_nginx_config +#================================================= +# STOP AND REMOVE SERVICE +#================================================= +ynh_script_progression --message="Stopping and removing the systemd service..." --weight=1 -# Restart services -systemctl force-reload supervisor +# Remove the dedicated systemd config +ynh_remove_systemd_config -# Remove app dependencies +#================================================= +# REMOVE THE MYSQL DATABASE +#================================================= +ynh_script_progression --message="Removing the MySQL database..." --weight=1 + +# Remove a database if it exists, along with the associated user +ynh_mysql_remove_db --db_user=$db_user --db_name=$db_name + +#================================================= +# REMOVE DEPENDENCIES +#================================================= +ynh_script_progression --message="Removing dependencies..." --weight=2 + +# Remove metapackage and its dependencies ynh_remove_app_dependencies -# Delete user -userdel ihatemoney +#================================================= +# REMOVE APP MAIN DIR +#================================================= +ynh_script_progression --message="Removing app main directory..." --weight=1 + +# Remove the app directory securely +ynh_secure_remove --file="$final_path" + +#================================================= +# REMOVE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Removing NGINX web server configuration..." --weight=1 + +# Remove the dedicated NGINX config +ynh_remove_nginx_config + +#================================================= +# REMOVE FAIL2BAN CONFIGURATION +#================================================= +# ynh_script_progression --message="Removing Fail2ban configuration..." --weight=1 + +# # Remove the dedicated Fail2Ban config +# ynh_remove_fail2ban_config + +#================================================= +# SPECIFIC REMOVE +#================================================= +# REMOVE VARIOUS FILES +#================================================= +ynh_script_progression --message="Removing configuration files..." --weight=1 + +# Remove the log files +ynh_secure_remove --file="/var/log/$app" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# REMOVE DEDICATED USER +#================================================= +ynh_script_progression --message="Removing the dedicated system user..." --weight=1 + +# Delete a system user +ynh_system_user_delete --username=$app + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Removal of $app completed" --last diff --git a/scripts/restore b/scripts/restore old mode 100644 new mode 100755 index 0912f3f..ede60f0 --- a/scripts/restore +++ b/scripts/restore @@ -1,58 +1,145 @@ #!/bin/bash -# Source app helpers +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +# Exit if an error occurs during the execution of the script ynh_abort_if_errors -# Get multi-instances specific variables +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 + app=$YNH_APP_INSTANCE_NAME -# Set app specific variables -dbname=$app -dbuser=$app +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) -# Retrieve old app settings -domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_app_setting_get "$app" path) -dbpass=$(ynh_app_setting_get "$app" mysqlpwd) +#================================================= +# 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 $INSTALL_DIR && ynh_die \ -"The destination directory '$INSTALL_DIR' already exists.\ - You should safely delete it before restoring this app." +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Restoring the NGINX configuration..." --weight=1 -test -f $supervisor_conf_path && ynh_die \ -"The Supervisor configuration already exists at '${supervisor_conf_path}'. - You should safely delete it before restoring this app." +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" -test -f $gunicorn_conf_path && ynh_die \ -"The Gunicorn configuration already exists at '${gunicorn_conf_path}'. - You should safely delete it before restoring this app." +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 -install_apt_dependencies +# Create the dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir="$final_path" -create_unix_user +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Restoring the app main directory..." --weight=1 -create_system_dirs +ynh_restore_file --origin_path="$final_path" -# Restore all backed-up files -ynh_restore +# FIXME: this should be managed by the core in the future +# Here, as a packager, you may have to tweak the ownerhsip/permissions +# such that the appropriate users (e.g. maybe www-data) can access +# files in some cases. +# But FOR THE LOVE OF GOD, do not allow r/x for "others" on the entire folder - +# this will be treated as a security issue. +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" -# Create and restore the database -ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" -ynh_mysql_connect_as "$dbuser" "$dbpass" "$dbname" < ./db.sql +#================================================= +# RESTORE FAIL2BAN CONFIGURATION +#================================================= +# ynh_script_progression --message="Restoring the Fail2Ban configuration..." --weight=1 -# Reload -systemctl reload nginx -systemctl restart supervisor -supervisorctl restart budget +# ynh_restore_file "/etc/fail2ban/jail.d/$app.conf" +# ynh_restore_file "/etc/fail2ban/filter.d/$app.conf" +# ynh_systemd_action --action=restart --service_name=fail2ban -# Wait that gunicorn is ready to consider the install finished, that is to -# avoid HTTP 502 right after installation -for i in `seq 1 120` -do - test -S /tmp/budget.gunicorn.sock && break +#================================================= +# SPECIFIC RESTORATION +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Reinstalling dependencies..." --weight=4 + +# Define and install dependencies +ynh_install_app_dependencies "${pkg_dependencies[@]}" + +#================================================= +# RESTORE THE MYSQL DATABASE +#================================================= +ynh_script_progression --message="Restoring the MySQL database..." --weight=1 + +db_pwd=$(ynh_app_setting_get --app=$app --key=mysqlpwd) +ynh_mysql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd +ynh_mysql_connect_as --user=$db_user --password=$db_pwd --database=$db_name < ./db.sql + +#================================================= +# RESTORE SYSTEMD +#================================================= +ynh_script_progression --message="Restoring the systemd configuration..." --weight=1 + +ynh_restore_file --origin_path="/etc/systemd/system/$app.service" +systemctl enable $app.service --quiet + +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 + +yunohost service add $app --description="$app daemon for IHateMoney" --log_type=systemd + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path="systemd" --line_match="Booting worker" --timeout 30 + +# line_match isn't enough because ihatemoney may stop if database upgrades +for _ in {1..20}; do + test -S /tmp/budget.gunicorn_$app.sock && break sleep 1 done + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX AND PHP-FPM +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for $app" --last diff --git a/scripts/upgrade b/scripts/upgrade old mode 100755 new mode 100644 index ef98703..855d95f --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,141 +1,227 @@ #!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 + app=$YNH_APP_INSTANCE_NAME +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +db_pwd=$(ynh_app_setting_get --app=$app --key=mysqlpwd) -# Installation paths -INSTALL_DIR=/opt/yunohost/ihatemoney +#================================================= +# CHECK VERSION +#================================================= -# Source YunoHost helpers -. /usr/share/yunohost/helpers +### This helper will compare the version of the currently installed app and the version of the upstream package. +### $upgrade_type can have 2 different values +### - UPGRADE_APP if the upstream app version has changed +### - UPGRADE_PACKAGE if only the YunoHost package has changed +### ynh_check_app_version_changed will stop the upgrade if the app is up to date. +### UPGRADE_APP should be used to upgrade the core app only if there's an upgrade to do. +upgrade_type=$(ynh_check_app_version_changed) -domain=$(ynh_app_setting_get $app domain) -path=$(ynh_app_setting_get $app path) -is_public=$(ynh_app_setting_get "$app" is_public) +if ynh_compare_current_package_version --comparison le --version "4.1.5~ynh2"; then + upgrade_from_opt=true +else + upgrade_from_opt=false +fi -VENV_PY_VERSION=$(echo ${INSTALL_DIR}/venv/bin/python*.*|sed 's/.*python//') -SYSTEM_PY_VERSION=$(readlink /usr/bin/python3|sed s/.*python//) - -# Source local utils -source _common.sh +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=3 +# Backup the current version of the app +ynh_backup_before_upgrade ynh_clean_setup () { - if [ -e /opt/yunohost/ihatemoney/venv-old ] - then - mv /opt/yunohost/ihatemoney/venv{-old,} - fi + # Restore it if the upgrade fails + ynh_restore_upgradebackup } - +# Exit if an error occurs during the execution of the script ynh_abort_if_errors +#================================================= +# STANDARD UPGRADE STEPS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= -#----------------------------PRE-UPGRADE MIGRATIONS----------------------- +if [[ "$upgrade_from_opt" == "false" ]]; then + ynh_script_progression --message="Stopping a systemd service..." --weight=1 - - -# MIGRATION: upgrade arg to typed boolean form - -if (($is_public != 0)) && (($is_public != 1)) -then - if [ $is_public = "No" ]; - then - is_public=0 - else - is_public=1 - fi - ynh_app_setting_set "$app" is_public "$is_public" + ynh_systemd_action --service_name=$app --action="stop" --log_path=systemd fi +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= +ynh_script_progression --message="Ensuring downward compatibility..." --weight=1 +# Cleaning legacy permissions +if ynh_legacy_permissions_exists; then + ynh_legacy_permissions_delete_all -# MIGRATION: Switch to a python3 venv -if [[ "$VENV_PY_VERSION" == 2.7 ]] -then - install_apt_dependencies - # Trash py2 venv - mv ${INSTALL_DIR}/venv ${INSTALL_DIR}/venv-old - init_virtualenv - - # Clears all cookie-sessions, because py2 & py3 sessions are incompatible - # Relates https://github.com/lepture/flask-wtf/issues/279 (fix unreleased) - new_secret_key=$(ynh_string_random 32) - ynh_replace_string "SECRET_KEY = \".*\"" "SECRET_KEY = \"${new_secret_key}\"" /etc/ihatemoney/ihatemoney.cfg + ynh_app_setting_delete --app=$app --key=is_public fi +# MIGRATION: Remove old code (from pre-4.1.5 versions, not using venv) +if [[ "$upgrade_from_opt" == "true" ]]; then + # Remove legacy install dir + ynh_secure_remove /opt/yunohost/ihatemoney -# MIGRATION: minor Py version has changed ? rebuilt venv + # Remove legacy Supervisor config + rm -f /etc/supervisor/conf.d/ihatemoney.conf -# Useful for Py 3.4 → 3.5, Jessie → Stretch, ynh 2.x → 3.x -if [[ "$VENV_PY_VERSION" != '2.7' ]] && [[ "$VENV_PY_VERSION" != "$SYSTEM_PY_VERSION" ]] -then - mv ${INSTALL_DIR}/venv ${INSTALL_DIR}/venv-old - init_virtualenv + if [ -e /etc/ihatemoney/settings.py ]; then + # Strip out the no longer used part of the settings + python3 -c "d = open('/etc/ihatemoney/settings.py').read().replace('try:\n from settings import *\nexcept ImportError:\n pass\n', ''); open('/etc/ihatemoney/settings.py', 'w').write(d)" + # Rename + mv /etc/ihatemoney/settings.py "/etc/ihatemoney/ihatemoney.cfg" + fi - # the static path changed - configure_nginx "$domain" "$path" + for old_file in "/etc/ihatemoney/ihatemoney.cfg" "/etc/$app/gunicorn.conf.py"; do + ynh_backup_if_checksum_is_different --file="$old_file" + ynh_delete_file_checksum --file="$old_file" + done + + final_path=/var/www/$app + ynh_app_setting_set --app=$app --key=final_path --value=$final_path + + db_name=ihatemoney + db_user=$db_name + ynh_app_setting_set --app=$app --key=db_name --value=$db_name fi -#-------------------------------UPGRADE------------------------- +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 + +# Create a dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir="$final_path" + +#================================================= +# UPGRADE DEPENDENCIES +#================================================= +ynh_script_progression --message="Upgrading dependencies..." --weight=1 + +ynh_install_app_dependencies "${pkg_dependencies[@]}" + +#================================================= +# SPECIFIC UPGRADE +#================================================= +# Init venv +#================================================= +ynh_script_progression --message="Configuring the app's installation..." --weight=6 + +ynh_app_setting_set --app=$app --key=final_path --value=$final_path + +# MIGRATION: Upgrade venv +python3 -m venv --upgrade "$final_path/venv" +"$final_path/venv/bin/python3" -m pip install --upgrade pip "${pip_dependencies[@]}" +python_venv_site_packages=$(__ynh_python_venv_get_site_packages_dir -d "$final_path/venv") + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Upgrading NGINX web server configuration..." --weight=1 + +# Create a dedicated NGINX config +## Needs $python_venv_site_packages +ynh_add_nginx_config "PYTHON_VERSION" + +#================================================= +# Setup gunicorn +#================================================= + +ynh_add_config --template ../conf/gunicorn.conf.py --destination "$final_path/gunicorn.conf.py" +chmod 600 "$final_path/gunicorn.conf.py" + +#================================================= +# Setup ihatemoney +#================================================= + +# Secret key for cookies encryption. +secret_key=$(ynh_string_random --length 32) +mails_sender="no-reply@$domain" +# Allows to comment some config lines if not using sub path +sub_path_only="$(if [[ "$path_url" == "/" ]]; then echo '# ' ; else echo ''; fi)" + +ynh_add_config --template ../conf/ihatemoney.cfg --destination "$final_path/ihatemoney.cfg" +chmod 600 "$final_path/ihatemoney.cfg" -# Upgrade code and dependencies -pip_install +# FIXME: this should be managed by the core in the future +# Here, as a packager, you may have to tweak the ownerhsip/permissions +# such that the appropriate users (e.g. maybe www-data) can access +# files in some cases. +# But FOR THE LOVE OF GOD, do not allow r/x for "others" on the entire folder - +# this will be treated as a security issue. +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_script_progression --message="Upgrading systemd configuration..." --weight=1 -#-----------------------POST-UPGRADE MIGRATIONS----------------- +# Create a dedicated systemd config +ynh_add_systemd_config +#================================================= +# GENERIC FINALIZATION +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 +yunohost service add $app --description="$app daemon for IHateMoney" --log_type=systemd +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=1 -# Python-MySQL is no longer maintained and does not support Py3 -ynh_replace_string "'mysql://" "'mysql+pymysql://" ${ihatemoney_conf_path} +ynh_systemd_action --service_name=$app --action="start" --log_path="systemd" --line_match="Booting worker" --timeout 30 +# line_match isn't enough because ihatemoney may stop if database upgrades +# FIXME: We need to wait for the db to upgrade and gunicorn to restart! +sleep 3 +#================================================= +# UPGRADE FAIL2BAN +#================================================= +# ynh_script_progression --message="Reconfiguring Fail2Ban..." --weight=1 -# MIGRATION: Remove old code (from pre-2.x versions, not using pip) +# # Create a dedicated Fail2Ban config +# ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" -ynh_secure_remove ${INSTALL_DIR}/src +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 +ynh_systemd_action --service_name=nginx --action=reload +#================================================= +# END OF SCRIPT +#================================================= -# MIGRATION: change the static path (from pre-2.x versions, not using pip) - -if grep -q /opt/yunohost/ihatemoney/src/ /etc/nginx/conf.d/${domain}.d/ihatemoney.conf -then - # the static path changed - configure_nginx "$domain" "$path" - - # Supervisor no longer change its directory to src/ dir - configure_supervisor - supervisorctl update -fi - - -# MIGRATION: new-style settings - -if [ -e /etc/ihatemoney/settings.py ]; then - # Strip out the no longer used part of the settings - python3 -c "d = open('/etc/ihatemoney/settings.py').read().replace('try:\n from settings import *\nexcept ImportError:\n pass\n', ''); open('/etc/ihatemoney/settings.py', 'w').write(d)" - # Rename - mv /etc/ihatemoney/settings.py ${ihatemoney_conf_path} -fi - - - -# MIGRATION: Remove no longer used symlink - -# (ihatemoney now read its conf by default from /etc/ihatemoney/ihatemoney.cfg) -ynh_secure_remove ${INSTALL_DIR}/src/budget/settings.py - - - -#----------------------------FINALIZATION----------------------- - -# Everything went ok ? Let's keep this new venv. -ynh_secure_remove ${INSTALL_DIR}/venv-old - -# Restart backend -supervisorctl restart budget - -# Reload nginx conf -systemctl reload nginx +ynh_script_progression --message="Upgrade of $app completed" --last