# -*- mode: shell-script -*- ## This place is not accessible from container on purpose: container ## don't need that. This should be stored in /var/lib/compose/ in a ## project, service directory a little like relation data. PASSWORD_FILE="$SERVICE_CONFIGSTORE/etc/$SERVICE_NAME/pass" ## Used to check existence and make direct changes when 'occ' command ## can't do it properly. CONFIGDIR="$SERVICE_DATASTORE/var/www/html/config" CONFIGFILE="$CONFIGDIR/config.php" has_user() { local user="$1" if ! out=$(occ user:info "$user"); then if [ "$out" == "user not found" ]; then return 1 else if [ -n "$out" ]; then err "Command 'occ user:info $user' failed with this output:" echo "$out" | prefix " | " >&2 else err "Command 'occ user:info $user' failed with no output." fi return 2 fi fi return 0 } set_admin_user_password() { local user="$1" password="$2" errlvl [ -z "$password" ] && { err "Refusing to set admin user an empty password." return 3 } has_user "$user" errlvl=$? [[ "$errlvl" -gt 1 ]] && { err "'has_user $user' failed. Bailing out." return "$errlvl" } if [[ "$errlvl" == 1 ]]; then info "User $user not found. Creating it in default 'admin' group." ( occ_docker_run_opts=("-e" "OC_PASS=$password") occ user:add --group=admin --password-from-env --display-name="$user" "$user" ) || return 1 else info "User $user found. Resetting password." ( occ_docker_run_opts=("-e" "OC_PASS=$password") occ user:resetpassword "$user" "--password-from-env" ) || { err "'occ user:resetpassword' failed," \ "common reason include password too simple." return 1 } fi ## XXXvlab: DRY violation: init does the same thing mkdir -p "$(dirname "$PASSWORD_FILE")" p0 "$user" "$password" > "$PASSWORD_FILE" } get_admin_user_password() { if [ -e "$PASSWORD_FILE" ]; then cat "$PASSWORD_FILE" else return 1 fi } ## only called after first install and occ is available nextcloud:init() { occ app:disable updatenotification nextcloud_announcements \; \ config:system:set maintenance_window_start --type=integer --value=1 \; \ config:system:set trusted_proxies 0 --value="0.0.0.0/0" \; \ db:add-missing-columns \; \ db:add-missing-indices \; \ db:add-missing-primary-keys \; \ maintenance:repair --include-expensive } create_occ_if_not_exists() { if ! [ -e "$SERVICE_DATASTORE/var/www/html/occ" ]; then ## Here we use a nasty trick to launch only the initialisation ## part of the ``entrypoint.sh``. By setting 'apache' as first ## call argument, we satisfy the big first 'if' condition ## triggering the installation if necessary, and will fail to ## launch any apache ## Last, we do not want the relation web-proxy to run in this ## bare-minimum nextcloud run AND we will use occ to set some info ## in this very same relation. ## Note also that we need to set NEXTCLOUD_ADMIN_{USER,PASSWORD} ## that is required to trigger a full installation if ! out=$( export COMPOSE_IGNORE_ORPHANS=true read-0 LOGIN PASSWORD < "$PASSWORD_FILE" || exit 1 compose --debug --no-init --without-relation="$SERVICE_NAME":web-proxy run \ -v "$CHARM_PATH"/src/fake-apache:/usr/bin/apache \ -e NEXTCLOUD_ADMIN_USER=$LOGIN \ -e NEXTCLOUD_ADMIN_PASSWORD=$PASSWORD \ --rm --entrypoint /entrypoint.sh "$SERVICE_NAME" apache 2>&1 ); then err "Initialization of code or database failed unexpectedly" e "$out" | prefix " | " return 1 fi if ! [ -e "$SERVICE_DATASTORE/var/www/html/occ" ]; then err "Expected last command to create /var/www/html/occ" return 1 fi nextcloud:init || return 1 fi } occ() { create_occ_if_not_exists || return 1 ## occ.batch will require /var/www/html to be populated ('occ' is ## supposed to exist). For that we need to make sure nextcloud have ## be ran and setup prior to running this next command. ## We need here actually only the relation sql-database. Any other hook ## using `occ` would make the call infinitively recursive. export COMPOSE_IGNORE_ORPHANS=true compose --debug -q --no-init --without-relation="$SERVICE_NAME":web-proxy run \ "${occ_docker_run_opts[@]}" \ -v "$HOST_CHARM_STORE/${CHARM_REL_PATH#${CHARM_STORE}/}/src/occ.batch:/var/www/html/occ.batch" \ -T --rm -u www-data "$SERVICE_NAME" /var/www/html/occ.batch "$@" | cat if [ "${PIPESTATUS[0]}" != 0 ]; then err "Failure to execute these ${WHITE}occ${NORMAL} commands:" printf '%s ' "$@" | sed -r "s/\\;/\n/g" | sed -r "s/^\s*(.*)\s*$/${WHITE}\1${NORMAL}/g" | prefix " ${DARKGRAY}>${NORMAL} " >&2 echo "" >&2 echo "" >&2 echo " If the code of nextcloud is already there (command occ is found), but " >&2 echo " the database is not yet created, this situation will arise." >&2 return "${PIPESTATUS[0]}" fi } nextcloud:config:simple:add() { local key="$1" value="$2" create_occ_if_not_exists || return 1 if ! [ -e "$CONFIGFILE" ]; then err "Config file '$CONFIGFILE' does not exist." return 1 fi if [ -z "$value" ]; then err "Value for '$key' is empty. Skipping." return 1 fi ## check for \ and ' in value and key if [[ "$value" =~ [\\\'] ]]; then err "Unsupported value for '$key' contains a backslash or a single quote." return 1 fi if [[ "$key" =~ [\\\'] ]]; then err "Key '$key' contains a backslash or a single quote." return 1 fi if grep "^ '$key' => '" "$CONFIGFILE" >/dev/null; then sed -ri "s/^( '$key' => ')(.*)(',)$/\1${value}\3/g" "$CONFIGFILE" return 0 fi ## Add '$key' => 'value', to the end of the file, before the closing paren. sed -ri "s/^(\);)$/ '$key' => '${value}',\n\1/g" "$CONFIGFILE" } nextcloud:config:version() { for f in {"$SERVICE_CONFIGSTORE","$SERVICE_DATASTORE"}/var/www/html/config/config.php; do if [ -e "$f" ]; then cat "$f" break fi done | grep "'version' =>" | cut -f 4 -d \' | cut -f 1-3 -d . }