diff --git a/check_process b/check_process new file mode 100644 index 0000000..6efab9e --- /dev/null +++ b/check_process @@ -0,0 +1,36 @@ +;; Test complet + auto_remove=1 + ; Manifest + domain="domain.tld" (DOMAIN) + path="/path" (PATH) + language="fr" + disablecacheck=1 + ; pre-install + sudo yunohost app fetchlist + sudo yunohost domain add --verbose baikaldomain.tld --admin-password $PASSWORD + sudo yunohost app install baikal -a "domain=baikaldomain.tld&path=/baikal&password=admin" + ; Checks + pkg_linter=1 + setup_sub_dir=1 + setup_root=0 + setup_nourl=0 +# Private test only should be fixed in package check before. +# setup_private=1 + setup_public=0 + upgrade=1 + backup_restore=1 + multi_instance=0 + incorrect_path=1 + port_already_use=0 + change_url=0 +;;; Levels + Level 1=auto + Level 2=auto + Level 3=auto + Level 4=1 + Level 5=auto + Level 6=auto + Level 7=auto + Level 8=0 + Level 9=0 + Level 10=0 diff --git a/conf/app.src b/conf/app.src new file mode 100644 index 0000000..b3de28a --- /dev/null +++ b/conf/app.src @@ -0,0 +1,4 @@ +SOURCE_URL=https://github.com/adobo/agendav/releases/download/2.2.0/agendav-2.2.0.tar.gz +SOURCE_SUM=0056154ae0a7aa3401f4f24c51f0f2de3d1e97eaa83e74a2129714b67013129f +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=tar.gz diff --git a/conf/nginx.conf b/conf/nginx.conf index baeceae..a49a1ca 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,42 +1,42 @@ -location {PATH}/ { - alias {DESTDIR}/web/public/; - index index.php; +location __PATH__/ { + alias __FINALPATH__/web/public/; + index index.php; - if ($scheme = http) { - rewrite ^ https://$server_name$request_uri? permanent; - } + if ($scheme = http) { + rewrite ^ https://$server_name$request_uri? permanent; + } - # The seemingly weird syntax is due to a long-standing bug in nginx, - # see: https://trac.nginx.org/nginx/ticket/97 - try_files $uri {PATH}/{PATH}/index.php$is_args$args; + # The seemingly weird syntax is due to a long-standing bug in nginx, + # see: https://trac.nginx.org/nginx/ticket/97 + try_files $uri __PATH__/__PATH__/index.php$is_args$args; - # Another alternative to the weird try_files is to use a rewrite, like this : - # - #  if (-f $request_filename) { - # break; - # } - #  rewrite (.*) {LOCATION}/index.php$request_uri; - # - # But remember that if-is-evil : - # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#check-if-file-exists + # Another alternative to the weird try_files is to use a rewrite, like this : + # + # if (-f $request_filename) { + # break; + # } + # rewrite (.*) {LOCATION}/index.php$request_uri; + # + # But remember that if-is-evil : + # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#check-if-file-exists - location ~ ^{PATH}/index\.php(/|$) { - fastcgi_split_path_info ^(.+?\.php)(/.*)$; - fastcgi_pass unix:/var/run/php5-fpm-{POOLNAME}.sock; - fastcgi_index index.php; - include fastcgi_params; - fastcgi_param REMOTE_USER $remote_user; - fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_param SCRIPT_FILENAME $request_filename; - } + location ~ ^__PATH__/index\.php(/|$) { + fastcgi_split_path_info ^(.+?\.php)(/.*)$; + fastcgi_pass unix:/var/run/php5-fpm-__NAME__.sock; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param REMOTE_USER $remote_user; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param SCRIPT_FILENAME $request_filename; + } - location ~ \.php$ { - return 404; - } + location ~ \.php$ { + return 404; + } - # Include SSOWAT user panel. - include conf.d/yunohost_panel.conf.inc; + # Include SSOWAT user panel. + include conf.d/yunohost_panel.conf.inc; } # append trailing slash in case of a subpath -location = {LOCATION} { return 302 {PATH}/; } +location = __PATH__ { return 302 __PATH__/; } diff --git a/conf/php-fpm.conf b/conf/php-fpm.conf index 49fb4a9..3e23b7b 100644 --- a/conf/php-fpm.conf +++ b/conf/php-fpm.conf @@ -1,6 +1,6 @@ -[{POOLNAME}] +[__NAMETOCHANGE__] ; The address on which to accept FastCGI requests. -listen = /var/run/php5-fpm-{POOLNAME}.sock +listen = /var/run/php5-fpm-__NAMETOCHANGE__.sock ; Set permissions for unix socket, if one is used. listen.owner = www-data @@ -8,8 +8,8 @@ listen.group = www-data listen.mode = 0600 ; Unix user/group of processes. -user = {USER} -group = {GROUP} +user = __USER__ +group = __USER__ ; Choose how the process manager will control the number of child processes. pm = dynamic @@ -47,7 +47,7 @@ request_terminate_timeout = 1d request_slowlog_timeout = 5s ; The log file for slow requests. -slowlog = /var/log/nginx/{POOLNAME}.slow.log +slowlog = /var/log/nginx/__NAMETOCHANGE__.slow.log ; Set open file descriptor rlimit. rlimit_files = 4096 @@ -56,7 +56,7 @@ rlimit_files = 4096 rlimit_core = 0 ; Chdir to this directory at the start. -chdir = {DESTDIR} +chdir = __FINALPATH__ ; Redirect worker stdout and stderr into main error log. catch_workers_output = yes diff --git a/conf/settings.php b/conf/settings.php index 3398903..ac70cb2 100644 --- a/conf/settings.php +++ b/conf/settings.php @@ -39,6 +39,9 @@ $app['caldav.baseurl'] = '{CALDAV_BASEURL}'; // Authentication method required by CalDAV server (basic or digest) $app['caldav.authmethod'] = 'basic'; +// Do not verify SSL certificate, it is self signed +$app['caldav.certificate.verify'] = __CACHECK__; + // Whether to show public CalDAV urls $app['caldav.publicurls'] = true; diff --git a/manifest.json b/manifest.json index 6d5dacd..814e55b 100644 --- a/manifest.json +++ b/manifest.json @@ -7,7 +7,7 @@ "fr": "Client web pour CalDAV" }, "url": "http://agendav.org/", - "license": "GPL-3", + "license": "GPL-3.0", "version": "2.0.0", "maintainer": { "name": "julien", @@ -15,7 +15,7 @@ }, "multi_instance": false, "requirements": { - "yunohost": ">= 2.4.0" + "yunohost": ">= 2.7.0" }, "services": [ "nginx", @@ -53,6 +53,14 @@ "de", "en", "es", "fr", "it", "nl" ], "default": "en" + }, + { + "name": "disablecacheck", + "ask": { + "en": "Disable certificate checks? (if not using a valid certificate)" + }, + "type": "boolean", + "default": false } ] } diff --git a/patches/00-add-http-auth.patch b/patches/00-add-http-auth.patch deleted file mode 100644 index 74153c9..0000000 --- a/patches/00-add-http-auth.patch +++ /dev/null @@ -1,56 +0,0 @@ ---- a/web/app/controllers.php -+++ b/web/app/controllers.php -@@ -71,13 +71,20 @@ $controllers->before(function(Request $request, Silex\Application $app) { - // processing the request - if ($app['session']->has('username')) { - $username = $app['session']->get('username'); -- $preferences = $app['preferences.repository']->userPreferences($username); -- $app['user.preferences'] = $preferences; -- $app['user.timezone'] = $preferences->get('timezone'); - -- // Set application language -- $app['locale'] = $preferences->get('language'); -- return; -+ // Clear user session if HTTP authentication changed -+ if (isset($_SERVER['PHP_AUTH_USER']) -+ && $username != $_SERVER['PHP_AUTH_USER']) { -+ $app['session']->clear(); -+ } else { -+ $preferences = $app['preferences.repository']->userPreferences($username); -+ $app['user.preferences'] = $preferences; -+ $app['user.timezone'] = $preferences->get('timezone'); -+ -+ // Set application language -+ $app['locale'] = $preferences->get('language'); -+ return; -+ } - } - - if ($request->isXmlHttpRequest()) { ---- a/web/src/Controller/Authentication.php -+++ b/web/src/Controller/Authentication.php -@@ -33,7 +33,7 @@ class Authentication - { - $template_vars = []; - -- if ($request->isMethod('POST')) { -+ if ($request->isMethod('POST') || isset($_SERVER['PHP_AUTH_USER'])) { - $result = $this->processLogin($request, $app); - - if ($result === true) { -@@ -62,8 +62,13 @@ class Authentication - - protected function processLogin(Request $request, Application $app) - { -- $user = $request->request->get('user'); -- $password = $request->request->get('password'); -+ if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { -+ $user = $_SERVER['PHP_AUTH_USER']; -+ $password = $_SERVER['PHP_AUTH_PW']; -+ } else { -+ $user = $request->request->get('user'); -+ $password = $request->request->get('password'); -+ } - - if (empty($user) || empty($password)) { - return $app['translator']->trans('messages.error_empty_fields'); diff --git a/scripts/_common.sh b/scripts/_common.sh index 5e0f815..65e9d26 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -1,19 +1,8 @@ +#!/bin/bash # # Common variables # -# AgenDAV version -VERSION="2.0.0" - -# Source tarball checksum -SOURCE_SHA256="142e8d9ea0e3e6feacd1523c5cabc834fe8bc3e9dbae03034089758b9c3abb92" - -# Source tarball URL -SOURCE_URL="https://github.com/adobo/agendav/releases/download/${VERSION}/agendav-${VERSION}.tar.gz" - -# App package root directory should be the parent folder -PKGDIR=$(cd ../; pwd) - # Associative array of languages declare -A LANGUAGES=( [nl]=nl_NL @@ -28,27 +17,6 @@ declare -A LANGUAGES=( # Common helpers # -# Source app helpers -source /usr/share/yunohost/helpers - -# Download and extract AgenDAV sources to the given directory -# usage: extract_agendav DESTDIR -extract_agendav() { - local DESTDIR=$1 - - # retrieve and extract tarball - tarball_path="/tmp/agendav.tar.gz" - rm -f "$tarball_path" - wget -q -O "$tarball_path" "$SOURCE_URL" \ - || ynh_die "Unable to download AgenDAV archive" - echo "$SOURCE_SHA256 $tarball_path" | sha256sum -c >/dev/null \ - || ynh_die "Invalid checksum of downloaded archive" - tar xf "$tarball_path" -C "$DESTDIR" --strip-components 1 \ - || ynh_die "Unable to extract AgenDAV archive" - rm -rf "$tarball_path" - - # apply patches - (cd "$DESTDIR" \ - && for p in ${PKGDIR}/patches/*.patch; do patch -p1 < $p; done) \ - || die "Unable to apply patches to AgenDAV" +agendav_app_check_installation() { + echo $(yunohost app list --installed -f "$1" | grep "id:") } diff --git a/scripts/backup b/scripts/backup index 7b57653..e190c3c 100644 --- a/scripts/backup +++ b/scripts/backup @@ -1,27 +1,65 @@ #!/bin/bash -set -eu + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +if [ ! -e _common.sh ]; then + # Get the _common.sh file if it's not in the current directory + cp ../settings/scripts/_common.sh ./_common.sh + chmod a+rx _common.sh +fi +source _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 + +#================================================= +# LOAD SETTINGS +#================================================= # Set app specific variables -app="$YNH_APP_INSTANCE_NAME" -dbname=$app -dbuser=$app - -# Source YunoHost helpers -source /usr/share/yunohost/helpers +app=$YNH_APP_INSTANCE_NAME +db_name=$app # Retrieve app settings domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_app_setting_get "$app" path) -dbpass=$(ynh_app_setting_get "$app" mysqlpwd) +final_path=$(ynh_app_setting_get "$app" final_path) -# Copy the app files -DESTDIR="/var/www/$app" -ynh_backup "$DESTDIR" "sources" +#================================================= +# STANDARD BACKUP STEPS +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= -# Copy the conf files -ynh_backup "/etc/nginx/conf.d/${domain}.d/${app}.conf" "nginx.conf" -ynh_backup "/etc/php5/fpm/pool.d/${app}.conf" "php-fpm.conf" +# Clean cache files before backup +ynh_secure_remove "${final_path}/web/var/cache/"{profiler,twig}/* + +ynh_backup "$final_path" + +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup "/etc/nginx/conf.d/${domain}.d/${app}.conf" + +#================================================= +# BACKUP THE PHP-FPM CONFIGURATION +#================================================= + +ynh_backup "/etc/php5/fpm/pool.d/${app}.conf" + +#================================================= +# BACKUP THE MYSQL DATABASE +#================================================= # Dump the database -mysqldump -u "$dbuser" -p"$dbpass" --no-create-db "$dbname" > ./dump.sql +ynh_mysql_dump_db "$db_name" > db.sql diff --git a/scripts/install b/scripts/install index 8a895c2..829758c 100644 --- a/scripts/install +++ b/scripts/install @@ -1,127 +1,212 @@ #!/bin/bash -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Retrieve arguments -domain=$1 -path=${2%/} -language=$3 +source _common.sh +source /usr/share/yunohost/helpers -# Source common variables and helpers -source ./_common.sh +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# RETRIEVE ARGUMENTS FROM THE MANIFEST +#================================================= + +domain=$YNH_APP_ARG_DOMAIN +path_url=$YNH_APP_ARG_PATH +language=$YNH_APP_ARG_LANGUAGE +disablecacheck=$YNH_APP_ARG_DISABLECACHECK + +# Set and store language +language=${LANGUAGES[$language]} # Set app specific variables -app="$YNH_APP_INSTANCE_NAME" +app=$YNH_APP_INSTANCE_NAME dbname=$app dbuser=$app -# Check domain/path availability -sudo yunohost app checkurl "${domain}${path}" -a "$app" \ - || exit 1 +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= -# Set and store language -language=${LANGUAGES[$3]} -ynh_app_setting_set "$app" language "$language" +final_path=/var/www/$app +test ! -e "$final_path" || ynh_die "This path already contains a folder" # Define LOGDIR (create it later when user is created) LOGDIR=/var/log/$app +test ! -e "$LOGDIR" || ynh_die "This log path already contains a folder" + +# Normalize the url path syntax +path_url=$(ynh_normalize_url_path "$path_url") + +# Check web path availability +ynh_webpath_available "$domain" "$path_url" +# Register (book) web path +ynh_webpath_register "$app" "$domain" "$path_url" -# Check destination directory -DESTDIR="/var/www/${app}" -[[ -d "$DESTDIR" ]] && ynh_die \ -"The destination directory '${DESTDIR}' already exists.\ - You should safely delete it before installing this app." # Check whether Baïkal or Radicale is installed -if sudo yunohost app list --installed -f baikal | grep -q id ; then +baikal_install=$(agendav_app_check_installation "baikal") +radicale_install=$(agendav_app_check_installation "radicale") +if [[ -n "$baikal_install" ]] +then caldav_app="baikal" caldav_baseurl="/cal.php/" -elif sudo yunohost app list --installed -f radicale | grep -q id ; then +elif [[ -n "$radicale_install" ]] +then caldav_app="radicale" caldav_baseurl="/" else - ynh_die "You must install Baïkal or Radicale before" + ynh_die "Baikal or Radicale is mandatory" fi +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= + +ynh_app_setting_set "$app" language "$language" +ynh_app_setting_set "$app" path "$path_url" +ynh_app_setting_set "$app" domain "$domain" +ynh_app_setting_set "$app" disablecacheck "$disablecacheck" +ynh_app_setting_set "$app" final_path "$final_path" + +#================================================= +# STANDARD MODIFICATIONS +#================================================= + # Install dependencies -ynh_package_is_installed "php5-cli" \ - || ynh_package_install "php5-cli" +ynh_install_app_dependencies php5-cli -# Create tmp directory and fetch app inside -TMPDIR=$(mktemp -d) -extract_agendav "$TMPDIR" +#================================================= +# CREATE A MYSQL DATABASE +#================================================= -# Generate random password and encryption key +# Initialize database dbpass=$(ynh_string_random) + +ynh_mysql_setup_db "$dbname" "$dbuser" "$dbpass" + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +ynh_setup_source "$final_path" + +#================================================= +# NGINX CONFIGURATION +#================================================= + +# Copy and set nginx configuration +ynh_add_nginx_config + +#================================================= +# CREATE DEDICATED USER +#================================================= + +ynh_system_user_create "$app" + +#================================================= +# PHP-FPM CONFIGURATION +#================================================ + +# Copy and set php-fpm configuration +ynh_add_fpm_config + +#================================================= +# SPECIFIC SETUP +#================================================= +# Create settings.php +#================================================= + +# Generate random encryption key encryptkey=$(ynh_string_random 24) + ynh_app_setting_set "$app" encryptkey "$encryptkey" -ynh_app_setting_set "$app" mysqlpwd "$dbpass" # Copy and set AgenDAV configuration -conf_path="${TMPDIR}/web/config/settings.php" -cp ../conf/settings.php "$conf_path" -sed -i "s/{DBUSER}/${dbuser}/g" "$conf_path" -sed -i "s/{DBPASS}/${dbpass}/g" "$conf_path" -sed -i "s/{DBNAME}/${dbname}/g" "$conf_path" -sed -i "s/{ENCRYPTKEY}/${encryptkey}/g" "$conf_path" -sed -i "s@{LOGDIR}@${LOGDIR}@g" "$conf_path" -sed -i "s@{TIMEZONE}@$(cat /etc/timezone)@g" "$conf_path" -sed -i "s@{LANGUAGE}@${language}@g" "$conf_path" +timezone=$(cat /etc/timezone) -# CalDAV config caldav_domain=$(ynh_app_setting_get "$caldav_app" domain) caldav_path=$(ynh_app_setting_get "$caldav_app" path) caldav_url="https://${caldav_domain}${caldav_path%/}" -sed -i "s@{CALDAV_BASEURL}@${caldav_url}${caldav_baseurl}@g" "$conf_path" -sed -i "s@{CALDAV_DOMAIN}@${caldav_domain}@g" "$conf_path" -# Install files and set permissions -sudo mv "$TMPDIR" "$DESTDIR" +conf_path="${final_path}/web/config/settings.php" +cp ../conf/settings.php "$conf_path" -sudo useradd -c "$app system account" \ - -d /var/www/$app --system --user-group $app --shell /usr/sbin/nologin \ - || ynh_die "Unable to create $app system account" +ynh_replace_string "{DBUSER}" "${dbuser}" "$conf_path" +ynh_replace_string "{DBPASS}" "${dbpass}" "$conf_path" +ynh_replace_string "{DBNAME}" "${dbname}" "$conf_path" +ynh_replace_string "{ENCRYPTKEY}" "${encryptkey}" "$conf_path" +ynh_replace_string "{LOGDIR}" "${LOGDIR}" "$conf_path" +ynh_replace_string "{TIMEZONE}" "$timezone" "$conf_path" +ynh_replace_string "{LANGUAGE}" "${language}" "$conf_path" +ynh_replace_string "{CALDAV_BASEURL}" "${caldav_url}${caldav_baseurl}" "$conf_path" +ynh_replace_string "{CALDAV_DOMAIN}" "${caldav_domain}" "$conf_path" -# Protect source code against modifications -sudo find "${DESTDIR}" -type f -exec chown root:root {} \; -exec chmod 644 {} \; -sudo find "${DESTDIR}" -type d -exec chown root:root {} \; -exec chmod 755 {} \; +if [ "$disablecacheck" -eq 0 ]; then + ynh_replace_string "__CACHECK__" "true" "$conf_path" +else + ynh_replace_string "__CACHECK__" "false" "$conf_path" +fi + +#================================================= +# STORE THE CHECKSUM OF THE CONFIG FILE +#================================================= + +ynh_store_file_checksum "$conf_path" + +#================================================= +# Run database migrations (includes initialization) +#================================================= + +( + cd "$final_path" + php agendavcli migrations:migrate --no-interaction +) + +#================================================= +# SETUP LOG directory +#================================================= + +mkdir -p "$LOGDIR" +chown -R "$app": "$LOGDIR" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +chown -R root: "$final_path" # Only agendav user should write here -sudo chown -hR $app: "${DESTDIR}/web/var/cache/"{profiler,twig} -sudo chmod -R 750 "${DESTDIR}/web/var/cache/"{profiler,twig} +chown -R "$app" "${final_path}/web/var/cache/"{profiler,twig} # The agendav user should read here, but does not need to write +chown -R root:"$app" "${final_path}/web/config/" +chmod -R g+rx "${final_path}/web/config/" + # Other users should not be able to read as it stores passwords. -sudo find "${DESTDIR}/web/config" -type f -exec chown root:$app {} \; -exec chmod 640 {} \; -sudo find "${DESTDIR}/web/config" -type d -exec chown root:$app {} \; -exec chmod 750 {} \; +chmod -R o-rwx "${final_path}/web/config/" -# Create log directory -sudo install -m 750 -o $app -g adm -d "$LOGDIR" +#================================================= +# SETUP SSOWAT +#================================================= -# Initialize database -ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" -(cd "$DESTDIR" && sudo sudo -u $app \ - php agendavcli migrations:migrate --no-interaction) \ - || ynh_die "Unable to create AgenDAV tables" +# Nothing to do, this app is private -# Copy and set nginx configuration -nginx_conf="/etc/nginx/conf.d/${domain}.d/${app}.conf" -sed -i "s@{PATH}@${path}@g" ../conf/nginx.conf -sed -i "s@{LOCATION}@${path:-/}@g" ../conf/nginx.conf -sed -i "s@{DESTDIR}@${DESTDIR}@g" ../conf/nginx.conf -sed -i "s@{POOLNAME}@${app}@g" ../conf/nginx.conf -# comment redirection in case of an installation at root -[[ -n "$path" ]] || sed -i '$s/^/#/' ../conf/nginx.conf -sudo cp ../conf/nginx.conf "$nginx_conf" - -# Copy and set php-fpm configuration -phpfpm_conf="/etc/php5/fpm/pool.d/${app}.conf" -sed -i "s@{POOLNAME}@${app}@g" ../conf/php-fpm.conf -sed -i "s@{DESTDIR}@${DESTDIR}/@g" ../conf/php-fpm.conf -sed -i "s@{USER}@${app}@g" ../conf/php-fpm.conf -sed -i "s@{GROUP}@${app}@g" ../conf/php-fpm.conf -sudo cp ../conf/php-fpm.conf "$phpfpm_conf" +#================================================= +# RELOAD NGINX and FPM +#================================================= # Reload services -sudo service php5-fpm restart -sudo service nginx reload +service php5-fpm reload +service nginx reload diff --git a/scripts/remove b/scripts/remove index 3c22df3..6954292 100644 --- a/scripts/remove +++ b/scripts/remove @@ -1,31 +1,73 @@ #!/bin/bash -# Set app specific variables -app="$YNH_APP_INSTANCE_NAME" -dbname=$app -dbuser=$app +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Source YunoHost helpers +source _common.sh source /usr/share/yunohost/helpers -# Drop MySQL database and user -ynh_mysql_drop_db "$dbname" || true -ynh_mysql_drop_user "$dbuser" || true +#================================================= +# LOAD SETTINGS +#================================================= -# Retrieve domain from app settings +app="$YNH_APP_INSTANCE_NAME" domain=$(ynh_app_setting_get "$app" domain) +final_path=$(ynh_app_setting_get "$app" final_path) -# Delete app directory and configurations -sudo rm -rf "/var/www/${app}" "/var/log/${app}" -sudo rm -f "/etc/php5/fpm/pool.d/${app}.conf" -[[ -n $domain ]] && sudo rm -f "/etc/nginx/conf.d/${domain}.d/${app}.conf" +db_name=$app +db_user=$app -# Reload services -sudo service php5-fpm restart || true -sudo service nginx reload || true +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE DEPENDENCIES +#================================================= + +# Remove metapackage and its dependencies +ynh_remove_app_dependencies + +#================================================= +# REMOVE THE MYSQL DATABASE +#================================================= + +# Remove a database if it exists, along with the associated user +ynh_mysql_remove_db "$db_user" "$db_name" + +#================================================= +# REMOVE APP MAIN DIR +#================================================= + +# Remove the app directory securely +ynh_secure_remove "$final_path" + +#================================================= +# REMOVE LOG +#================================================= + +ynh_secure_remove "/var/log/$app" + +#================================================= +# REMOVE NGINX CONFIGURATION +#================================================= + +# Remove the dedicated nginx config +ynh_remove_nginx_config + +#================================================= +# REMOVE PHP-FPM CONFIGURATION +#================================================= + +# Remove the dedicated php-fpm config +ynh_remove_fpm_config + +#================================================= +# GENERIC FINALIZATION +#================================================= +# REMOVE DEDICATED USER +#================================================= # Remove the user account -# (must be done after php-fpm restart) -id "$app" >/dev/null 2>&1 \ - && sudo deluser --quiet --remove-home "$app" >/dev/null \ - || true +ynh_system_user_delete "$app" diff --git a/scripts/restore b/scripts/restore index 8a8bca2..1db77b5 100644 --- a/scripts/restore +++ b/scripts/restore @@ -1,96 +1,126 @@ #!/bin/bash -set -eu + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +if [ ! -e _common.sh ]; then + # Get the _common.sh file if it's not in the current directory + cp ../settings/scripts/_common.sh ./_common.sh + chmod a+rx _common.sh +fi + +source _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 + +#================================================= +# LOAD SETTINGS +#================================================= # Set app specific variables app="$YNH_APP_INSTANCE_NAME" dbname=$app dbuser=$app -# Source app helpers -source /usr/share/yunohost/helpers - # Retrieve old app settings domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_app_setting_get "$app" path) +path_url=$(ynh_app_setting_get "$app" path) +final_path=$(ynh_app_setting_get "$app" final_path) dbpass=$(ynh_app_setting_get "$app" mysqlpwd) -# Check domain/path availability -sudo yunohost app checkurl "${domain}${path}" -a "$app" \ - || exit 1 +LOGDIR=/var/log/$app -# Check destination directory -DESTDIR="/var/www/$app" -[[ -d $DESTDIR ]] && ynh_die \ -"The destination directory '$DESTDIR' already exists.\ - You should safely delete it before restoring this app." +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= -# Check configuration files -nginx_conf="/etc/nginx/conf.d/${domain}.d/${app}.conf" -[[ -f $nginx_conf ]] && ynh_die \ -"The NGINX configuration already exists at '${nginx_conf}'. - You should safely delete it before restoring this app." -phpfpm_conf="/etc/php5/fpm/pool.d/${app}.conf" -[[ -f $phpfpm_conf ]] && ynh_die \ -"The PHP FPM configuration already exists at '${phpfpm_conf}'. - You should safely delete it before restoring this app." +ynh_webpath_available "$domain" "$path_url" \ + || ynh_die "Path not available: ${domain}${path_url}" +test ! -d "$final_path" \ +|| ynh_die "There is already a directory: $final_path " -# Check whether Baïkal or Radicale is installed -if sudo yunohost app list --installed -f baikal | grep -q id ; then - caldav_app="baikal" - caldav_baseurl="/cal.php/" -elif sudo yunohost app list --installed -f radicale | grep -q id ; then - caldav_app="radicale" - caldav_baseurl="/" -else - ynh_die "You must install Baïkal or Radicale before" -fi +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= -if ! id -u $app > /dev/null 2>&1 ; then - sudo useradd -c "$app system account" \ - -d /var/www/$app --system --user-group $app --shell /usr/sbin/nologin \ - || ynh_die "Unable to create $app system account" -fi +# Restore configuration files +ynh_restore_file "/etc/nginx/conf.d/${domain}.d/${app}.conf" -# Restore the app files and set permissions -sudo cp -a ./sources "$DESTDIR" +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= -# Protect source code against modifications -sudo chown -hR root: "$DESTDIR" +ynh_restore_file "$final_path" -# Only agendav user should write here -sudo chown -hR $app: "${DESTDIR}/web/var/cache/"{profiler,twig} -sudo chmod -R 750 "${DESTDIR}/web/var/cache/"{profiler,twig} - -# The agendav user should read here, but does not need to write -# Other users should not be able to read as it stores passwords. -sudo find "${DESTDIR}/web/config" -type f -exec chown root:$app {} \; -exec chmod 640 {} \; -sudo find "${DESTDIR}/web/config" -type d -exec chown root:$app {} \; -exec chmod 750 {} \; - -# Clean caches -sudo rm -rf "${DESTDIR}/web/var/cache/"{profiler,twig}/* - -# CalDAV config -caldav_domain=$(ynh_app_setting_get "$caldav_app" domain) -caldav_path=$(ynh_app_setting_get "$caldav_app" path) -caldav_url="https://${caldav_domain}${caldav_path%/}" -conf_path="${DESTDIR}/web/config/settings.php" -sudo sed -i "s@^\(\$app\['caldav.baseurl'\] = \).*\ -@\1'${caldav_url}${caldav_baseurl}';@g" "$conf_path" -sudo sed -i "s@^\(\$app\['caldav.baseurl.public'\] = \).*\ -@\1'${caldav_domain}';@g" "$conf_path" - -# Create log directory -sudo install -m 750 -o www-data -g adm -d "/var/log/${app}" +#================================================= +# RESTORE THE MYSQL DATABASE +#================================================= # Create and restore the database ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" -ynh_mysql_connect_as "$dbuser" "$dbpass" "$dbname" < ./dump.sql +ynh_mysql_connect_as "$dbuser" "$dbpass" "$dbname" < ./db.sql -# Restore configuration files -sudo cp -a ./nginx.conf "$nginx_conf" -sudo cp -a ./php-fpm.conf "$phpfpm_conf" +#================================================= +# RECREATE THE DEDICATED USER +#================================================= -# Reload services -sudo service php5-fpm restart -sudo service nginx reload +ynh_system_user_create "$app" "$final_path" + +#================================================= +# RESTORE USER RIGHTS +#================================================= + +chown -R root: "$final_path" + +# Only agendav user should write here +chown -R "$app" "${final_path}/web/var/cache/"{profiler,twig} + +# The agendav user should read here, but does not need to write +chown -R root:"$app" "${final_path}/web/config/" +chmod -R g+rx "${final_path}/web/config/" + +# Other users should not be able to read as it stores passwords. +chmod -R o-rwx "${final_path}/web/config/" + +#================================================= +# RESTORE THE PHP-FPM CONFIGURATION +#================================================= + +ynh_restore_file "/etc/php5/fpm/pool.d/${app}.conf" + +#================================================= +# SPECIFIC RESTORATION +#================================================= +# REINSTALL DEPENDENCIES +#================================================= + +# Install dependencies +ynh_install_app_dependencies php5-cli + +#================================================= +# SETUP LOG directory +#================================================= + +mkdir -p "$LOGDIR" +chown -R "$app": "$LOGDIR" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX AND PHP-FPM +#================================================= + +service php5-fpm reload +service nginx reload diff --git a/scripts/upgrade b/scripts/upgrade index 7ab8868..b8f016e 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,9 +1,17 @@ #!/bin/bash -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Source common variables and helpers -source ./_common.sh +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= # Set app specific variables app="$YNH_APP_INSTANCE_NAME" @@ -12,11 +20,17 @@ dbuser=$app # Retrieve arguments domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_app_setting_get "$app" path) -path=${path%/} +path_url=$(ynh_app_setting_get "$app" path) dbpass=$(ynh_app_setting_get "$app" mysqlpwd) encryptkey=$(ynh_app_setting_get "$app" encryptkey) language=$(ynh_app_setting_get "$app" language) +disablecacheck=$(ynh_app_setting_get "$app" disablecacheck) + +LOGDIR=/var/log/$app + +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= # Set and store language if [[ -z "$language" ]]; then @@ -29,100 +43,189 @@ if [[ -z "$language" ]]; then ynh_app_setting_set "$app" language "$language" fi -# Define LOGDIR (create it later when user is created) -LOGDIR=/var/log/$app -# Check destination directory -DESTDIR="/var/www/$app" -[[ ! -d $DESTDIR ]] && ynh_die \ -"The destination directory '$DESTDIR' does not exist.\ - The app is not correctly installed, you should remove it first." +# Fix is_public as a boolean value +if [ "$is_public" = "Yes" ]; then + ynh_app_setting_set "$app" is_public 1 + is_public=1 +elif [ "$is_public" = "No" ]; then + ynh_app_setting_set "$app" is_public 0 + is_public=0 +fi + +# If db_name doesn't exist, create it +if [ -z "$db_name" ]; then + db_name=$(ynh_sanitize_dbid "$app") + ynh_app_setting_set "$app" db_name "$db_name" +fi + +# If disablecacheck doesn't exist, create it +if [ -z "$disablecacheck" ]; then + disablecacheck=0 + ynh_app_setting_set "$app" disablecacheck "$disablecacheck" +fi + +# If final_path doesn't exist, create it +if [ -z "$final_path" ]; then + final_path=/var/www/$app + ynh_app_setting_set "$app" final_path "$final_path" +fi # Check whether Baïkal or Radicale is installed -if sudo yunohost app list --installed -f baikal | grep -q id ; then +baikal_install=$(agendav_app_check_installation "baikal") +radicale_install=$(agendav_app_check_installation "radicale") +if [[ -n "$baikal_install" ]] +then caldav_app="baikal" caldav_baseurl="/cal.php/" -elif sudo yunohost app list --installed -f radicale | grep -q id ; then +elif [[ -n "$radicale_install" ]] +then caldav_app="radicale" caldav_baseurl="/" else - ynh_die "You must install Baïkal or Radicale before" + ynh_die "Baikal or Radicale is mandatory" fi -# Install dependencies -ynh_package_is_installed "php5-cli" \ - || ynh_package_install "php5-cli" +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= -# Create tmp directory and fetch app inside -TMPDIR=$(mktemp -d) -extract_agendav "$TMPDIR" +# 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 + +#================================================= +# CHECK THE PATH +#================================================= + +# Normalize the URL path syntax +path_url=$(ynh_normalize_url_path "$path_url") + +#================================================= +# STANDARD MODIFICATIONS +#================================================= + +# Install dependencies +ynh_install_app_dependencies php5-cli + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +ynh_setup_source "$final_path" + +#================================================= +# NGINX CONFIGURATION +#================================================= + +# Copy and set nginx configuration +ynh_add_nginx_config + +#================================================= +# CREATE DEDICATED USER +#================================================= + +ynh_system_user_create "$app" + +#================================================= +# PHP-FPM CONFIGURATION +#================================================ + +# Copy and set php-fpm configuration +ynh_add_fpm_config + +#================================================= +# SPECIFIC SETUP +#================================================= +# Create settings.php +#================================================= + +# Generate random encryption key +encryptkey=$(ynh_app_setting_get "$app" encryptkey) # Copy and set AgenDAV configuration -conf_path="${TMPDIR}/web/config/settings.php" -cp ../conf/settings.php "$conf_path" -sed -i "s/{DBUSER}/${dbuser}/g" "$conf_path" -sed -i "s/{DBPASS}/${dbpass}/g" "$conf_path" -sed -i "s/{DBNAME}/${dbname}/g" "$conf_path" -sed -i "s/{ENCRYPTKEY}/${encryptkey}/g" "$conf_path" -sed -i "s@{LOGDIR}@${LOGDIR}@g" "$conf_path" -sed -i "s@{TIMEZONE}@$(cat /etc/timezone)@g" "$conf_path" -sed -i "s@{LANGUAGE}@${language}@g" "$conf_path" +timezone=$(cat /etc/timezone) -# CalDAV config caldav_domain=$(ynh_app_setting_get "$caldav_app" domain) caldav_path=$(ynh_app_setting_get "$caldav_app" path) caldav_url="https://${caldav_domain}${caldav_path%/}" -sed -i "s@{CALDAV_BASEURL}@${caldav_url}${caldav_baseurl}@g" "$conf_path" -sed -i "s@{CALDAV_DOMAIN}@${caldav_domain}@g" "$conf_path" -# Replace files and set permissions -sudo rm -rf "$DESTDIR" -sudo mv "$TMPDIR" "$DESTDIR" -if ! id -u $app > /dev/null 2>&1 ; then - sudo useradd -c "$app system account" \ - -d /var/www/$app --system --user-group $app --shell /usr/sbin/nologin \ - || ynh_die "Unable to create $app system account" +conf_path="${final_path}/web/config/settings.php" +ynh_backup_if_checksum_is_different "$conf_path" + +cp ../conf/settings.php "$conf_path" + +ynh_replace_string "{DBUSER}" "${dbuser}" "$conf_path" +ynh_replace_string "{DBPASS}" "${dbpass}" "$conf_path" +ynh_replace_string "{DBNAME}" "${dbname}" "$conf_path" +ynh_replace_string "{ENCRYPTKEY}" "${encryptkey}" "$conf_path" +ynh_replace_string "{LOGDIR}" "${LOGDIR}" "$conf_path" +ynh_replace_string "{TIMEZONE}" "$timezone" "$conf_path" +ynh_replace_string "{LANGUAGE}" "${language}" "$conf_path" +ynh_replace_string "{CALDAV_BASEURL}" "${caldav_url}${caldav_baseurl}" "$conf_path" +ynh_replace_string "{CALDAV_DOMAIN}" "${caldav_domain}" "$conf_path" + +if [ "$disablecacheck" -eq 0 ]; then + ynh_replace_string "__CACHECK__" "true" "$conf_path" +else + ynh_replace_string "__CACHECK__" "false" "$conf_path" fi -# Protect source code against modifications -sudo find "${DESTDIR}" -type f -exec chown root:root {} \; -exec chmod 644 {} \; -sudo find "${DESTDIR}" -type d -exec chown root:root {} \; -exec chmod 755 {} \; +#================================================= +# STORE THE CHECKSUM OF THE CONFIG FILE +#================================================= + +ynh_store_file_checksum "$conf_path" + +#================================================= +# Run database migrations (includes initialization) +#================================================= + +( + cd "$final_path" + php agendavcli migrations:migrate --no-interaction +) + +#================================================= +# SETUP LOG directory +#================================================= + +mkdir -p "$LOGDIR" +chown -R "$app": "$LOGDIR" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +chown -R root: "$final_path" # Only agendav user should write here -sudo chown -hR $app: "${DESTDIR}/web/var/cache/"{profiler,twig} -sudo chmod -R 750 "${DESTDIR}/web/var/cache/"{profiler,twig} +chown -R "$app" "${final_path}/web/var/cache/"{profiler,twig} # The agendav user should read here, but does not need to write +chown -R root:"$app" "${final_path}/web/config/" +chmod -R g+rx "${final_path}/web/config/" + # Other users should not be able to read as it stores passwords. -sudo find "${DESTDIR}/web/config" -type f -exec chown root:$app {} \; -exec chmod 640 {} \; -sudo find "${DESTDIR}/web/config" -type d -exec chown root:$app {} \; -exec chmod 750 {} \; +chmod -R o-rwx "${final_path}/web/config/" -# Create log directory -sudo install -m 750 -o $app -g adm -d "$LOGDIR" +#================================================= +# SETUP SSOWAT +#================================================= -# Run database migrations -(cd "$DESTDIR" && sudo sudo -u $app \ - php agendavcli migrations:migrate --no-interaction) \ - || ynh_die "Unable to run AgenDAV database migration" +# Nothing to do, this app is private -# Copy and set nginx configuration -nginx_conf="/etc/nginx/conf.d/${domain}.d/${app}.conf" -sed -i "s@{PATH}@${path}@g" ../conf/nginx.conf -sed -i "s@{LOCATION}@${path:-/}@g" ../conf/nginx.conf -sed -i "s@{DESTDIR}@${DESTDIR}@g" ../conf/nginx.conf -sed -i "s@{POOLNAME}@${app}@g" ../conf/nginx.conf -# comment redirection in case of an installation at root -[[ -n "$path" ]] || sed -i '$s/^/#/' ../conf/nginx.conf -sudo cp ../conf/nginx.conf "$nginx_conf" - -# Copy and set php-fpm configuration -phpfpm_conf="/etc/php5/fpm/pool.d/${app}.conf" -sed -i "s@{POOLNAME}@${app}@g" ../conf/php-fpm.conf -sed -i "s@{DESTDIR}@${DESTDIR}/@g" ../conf/php-fpm.conf -sed -i "s@{USER}@${app}@g" ../conf/php-fpm.conf -sed -i "s@{GROUP}@${app}@g" ../conf/php-fpm.conf -sudo cp ../conf/php-fpm.conf "$phpfpm_conf" +#================================================= +# RELOAD NGINX and FPM +#================================================= # Reload services -sudo service php5-fpm restart || true -sudo service nginx reload || true +service php5-fpm reload +service nginx reload