#!/bin/bash -e
#
# Helper script file for package openproject
#
# Copyright (c) 2020 Matthew Trescott <matthewtrescott@gmail.com>
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.

cd "/usr/lib/openproject"

RUBY_VERSION="2.7"
RAKE_CMD="rake.ruby$RUBY_VERSION"
RAILS_CMD="rails.ruby$RUBY_VERSION"

# Just in case we're not being run by systemd
export RAILS_ENV="production"
source /etc/sysconfig/openproject-application
source /etc/sysconfig/openproject-database
export OPENPROJECT_SECRET_KEY_BASE
export RAILS_CACHE_STORE
export RAILS_CACHE_NAMESPACE
export MEMCACHED_SERVERS
export OPENPROJECT_ATTACHMENTS_STORAGE_PATH
export OPENPROJECT_GIT_LOCAL_CHECKOUT_PATH
export RAILS_LOG_TO_STDOUT=yes

# Fragile helper function
function run_as_openproject {
    IFS=" " # Make sure $* works as expected
    
    su --command "$*" --shell /bin/bash openproject
}

function update_db {
    [ -n "$RUNNING_UNDER_SYSTEMD" ] && systemd-notify --status="Checking for OpenProject PostgreSQL role"
    
    # Thanks, https://stackoverflow.com/a/8546783. This also serves as a clumsy test of whether OpenProject is using a local PostgreSQL with peer/ident authentication.
    ROLE_EXISTS="$(su postgres -c  "psql --dbname=\"$OPENPROJECT_DATABASE_URL\" --username=postgres --no-password -tAc \"SELECT 1 FROM pg_roles WHERE rolname='openproject'\"")"
    HAVE_PG_ADMIN=$?
    
    if [ "$HAVE_PG_ADMIN" = "0" ] && [ "$ROLE_EXISTS" != "1" ]; then
        [ -n "$RUNNING_UNDER_SYSTEMD" ] && systemd-notify --status="Creating OpenProject PostgreSQL role"
        echo "Creating PostgreSQL user for OpenProject"
        su postgres -c "createuser --no-password --createdb openproject"
    fi
    
    [ -n "$RUNNING_UNDER_SYSTEMD" ] && systemd-notify --status="Creating database/running migrations if needed"
    echo "Creating database/running migrations if needed."
    run_as_openproject $RAKE_CMD db:create db:migrate
    
    [ -n "$RUNNING_UNDER_SYSTEMD" ] && systemd-notify --status="Seeding database"
    [ -n "$RUNNING_UNDER_SYSTEMD" ] && systemd-notify EXTEND_TIMEOUT_USEC=100000000 # Seeding the database can take a long time. This provides an extra 100 seconds
    echo "Seeding database (if needed)"
    run_as_openproject $RAKE_CMD db:seed
    
    [ -n "$RUNNING_UNDER_SYSTEMD" ] && systemd-notify --status="Database start-up tasks completed. Proceeding to the next step."
}

function fillup_secret_key {
    [ -n "$RUNNING_UNDER_SYSTEMD" ] && systemd-notify --status="Checking and generating secret key base and Sys API key if needed"
    if [ "$(id -u)" != "0" ]; then
        echo "Error: root privileges are required to modify the OpenProject secret key."
        exit 4;
    fi
    
    if [ "$OPENPROJECT_SECRET_KEY_BASE" = "abc123" ]; then
        echo "Secret key base not generated. Generating a new secret key base now."
        # Send the script to stdin so we don't expose the secrets on the command line
        sed -i -f - /etc/sysconfig/openproject-application <<< "s/OPENPROJECT_SECRET_KEY_BASE=\"abc123\"/OPENPROJECT_SECRET_KEY_BASE=\"$($RAKE_CMD secret)\"/"
    else
        echo "Secret key is already set; no need to generate a new one."
    fi
    
    if [ "$OPENPROJECT_SYS_API_KEY" = "abc123" ]; then
        echo "SYS API key not generated. Generating a new secret API key now."
        sed -i -f - /etc/sysconfig/openproject-application <<< "s/OPENPROJECT_SYS_API_KEY=\"abc123\"/OPENPROJECT_SYS_API_KEY=\"$(head --bytes=20 /dev/urandom | base32)\"/"
    else
        echo "SYS API key is already set; no need to generate a new one."
    fi
}

function copy_repoman_key {
    if [ ! -f /etc/sysconfig/openproject-repoman ]; then
        echo "The sysconfig file for the repository manager script does not exist."
        echo "This is OK if you have not installed openproject-scm-perl-scripts."
        exit 0
    fi
    
    source /etc/sysconfig/openproject-repoman
    [ -n "$RUNNING_UNDER_SYSTEMD" ] && systemd-notify --status="Generating repository management script tokens (if needed) and copying to application config"
    
    if [ "$OPENPROJECT_REPOMAN_TOKEN" = "abc123" ]; then
        echo "Repository management token has not been generated. Generating a new token now."
        NEW_TOKEN="$(head --bytes=20 /dev/urandom | base32)"
        
        sed -i -f - /etc/sysconfig/openproject-repoman <<< "s/OPENPROJECT_REPOMAN_TOKEN=\"abc123\"/OPENPROJECT_REPOMAN_TOKEN=\"${NEW_TOKEN}\"/"
        
        OPENPROJECT_REPOMAN_TOKEN="$NEW_TOKEN"
    else
        echo "Repository management token already set; no need to generate a new one."
    fi
    
    if [ "$OPENPROJECT_SUBVERSION_REPOMAN_TOKEN" = "abc123" ]; then
        echo "Copying repository management script token to OpenProject application configuration (Subversion)."
        sed -i -f - /etc/sysconfig/openproject-application <<< "s/OPENPROJECT_SUBVERSION_REPOMAN_TOKEN=\"abc123\"/OPENPROJECT_SUBVERSION_REPOMAN_TOKEN=\"${OPENPROJECT_REPOMAN_TOKEN}\"/"
    fi
    if [ "$OPENPROJECT_GIT_REPOMAN_TOKEN" = "abc123" ]; then
        echo "Copying repository management script token to OpenProject application configuration (Git)."
        sed -i -f - /etc/sysconfig/openproject-application <<< "s/OPENPROJECT_GIT_REPOMAN_TOKEN=\"abc123\"/OPENPROJECT_GIT_REPOMAN_TOKEN=\"${OPENPROJECT_REPOMAN_TOKEN}\"/"
    fi
        
}

function share_sys_api_key {
    if [ ! -f /etc/sysconfig/openproject-repoauth ]; then
        echo "The sysconfig file for the repository authentication script does not exist."
        echo "This is OK if you have not installed openproject-scm-perl-scripts."
        exit 0
    fi
    
    source /etc/sysconfig/openproject-repoauth
    
    if [ "$OPENPROJECT_REPOAUTH_SYS_API_KEY" = "abc123" ]; then
        echo "Sharing SYS API key with OpenProject repository authentication script configuration."
        sed -i -f - /etc/sysconfig/openproject-repoauth <<< "s/OPENPROJECT_REPOAUTH_SYS_API_KEY=\"abc123\"/OPENPROJECT_REPOAUTH_SYS_API_KEY=\"${OPENPROJECT_SYS_API_KEY}\"/"
    fi
}

case $1 in
    'update-db')
        update_db
        ;;
    'fillup-secret-key')
        fillup_secret_key
        ;;
    'copy-repoman-key')
        copy_repoman_key
        ;;
    'share-sys-api-key')
        share_sys_api_key
        ;;
    *)
        echo "This script allows OpenProject to be installed on non-running system."
        echo "It should be called by systemd prior to starting OpenProject."
        echo "It should run as root, and will switch to the openproject user"
        echo "for database operations."
        echo "USAGE: $0 [COMMAND]"
        echo "The following commands are available:"
        echo "    update-db:         Creates OpenProject user in PostgreSQL, creates the"
        echo "                       OpenProject database, runs migrations, and seeds the"
        echo "                       database as needed."
        echo
        echo "    fillup-secret-key: Generates secret key base and SYS API key and stores"
        echo "                       them in /etc/sysconfig/openproject-application"
        echo
        echo "    copy-repoman-key:  Copies the repository manager Perl script's"
        echo "                       API key from /etc/sysconfig/openproject-repoman"
        echo "                       to /etc/sysconfig/openproject-application."
        echo "                       Generates it if it doesn't exist yet."
        echo
        echo "    share-sys-api-key: Shares the SYS API key with the repository authentication"
        echo "                       Perl script via /etc/sysconfig/openproject-repoauth"
        exit 2
        ;;
esac
