#!/bin/bash

set -e


role_exists() {
    local rolename=$1
    if sudo -u postgres psql asterisk -Atqc "SELECT 1 FROM pg_roles WHERE rolname='$rolename'" 2>/dev/null | grep -q "1"; then
        return 0
    else
        return 1
    fi
}

fix_privileges_to_stats_role_on_asterisk_db() {
    sudo -u postgres psql asterisk -c "GRANT USAGE ON SCHEMA xc TO stats"
    sudo -u postgres psql asterisk -c "GRANT SELECT ON ALL TABLES IN SCHEMA public, xc TO stats"
    sudo -u postgres psql asterisk -c "GRANT SELECT ON ALL SEQUENCES IN SCHEMA public, xc TO stats"
}


grant_default_privileges_to_stats_role_on_asterisk_db() {
    sudo -u postgres psql asterisk -c "ALTER DEFAULT PRIVILEGES FOR ROLE asterisk IN SCHEMA public, xc GRANT SELECT ON TABLES TO stats"
    sudo -u postgres psql asterisk -c "ALTER DEFAULT PRIVILEGES FOR ROLE asterisk IN SCHEMA public, xc GRANT SELECT ON SEQUENCES TO stats;"
}

add_dbreplic_role_on_asterisk_db() {
    if ! role_exists "dbreplic"; then
        sudo -u postgres psql asterisk -c "CREATE ROLE dbreplic WITH LOGIN PASSWORD 'dbreplic'"
    fi
    sudo -u postgres psql asterisk -c "GRANT USAGE ON SCHEMA xc TO dbreplic"
    sudo -u postgres psql asterisk -c "GRANT SELECT ON ALL TABLES IN SCHEMA public, xc TO dbreplic"
    sudo -u postgres psql asterisk -c "GRANT SELECT ON ALL SEQUENCES IN SCHEMA public, xc TO dbreplic"
    sudo -u postgres psql asterisk -c "GRANT SELECT, INSERT, UPDATE ON replication_state TO dbreplic;"
}

grant_default_privileges_to_dbreplic_role_on_asterisk_db() {
    sudo -u postgres psql asterisk -c "ALTER DEFAULT PRIVILEGES FOR ROLE asterisk IN SCHEMA public, xc GRANT SELECT ON TABLES TO dbreplic"
    sudo -u postgres psql asterisk -c "ALTER DEFAULT PRIVILEGES FOR ROLE asterisk IN SCHEMA public, xc GRANT SELECT ON SEQUENCES TO dbreplic"
}

reassign_owned_configmgt() {
    sudo -u postgres psql asterisk -c "REASSIGN OWNED BY configmgt TO asterisk"
}

remove_configmgt_role() {
    # Remove configmgt user
    # - Reassign everything owned by configmgt to asterisk
    reassign_owned_configmgt
    # - Revoke all of configmgt privileges
    sudo -u postgres psql asterisk -c "REVOKE ALL PRIVILEGES ON DATABASE asterisk FROM configmgt"
    sudo -u postgres psql asterisk -c "REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM configmgt"
    sudo -u postgres psql asterisk -c "REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA xc FROM configmgt"
    sudo -u postgres psql asterisk -c "REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM configmgt"
    sudo -u postgres psql asterisk -c "REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA xc FROM configmgt"
    # - Drop configmgt role
    sudo -u postgres psql asterisk -c "DROP ROLE IF EXISTS configmgt"
}

clean_old_configmgt_tables_definition() {
    # Change use of a custom function to native function
    # 1. Drop triggers
    sudo -u postgres psql asterisk -c "DROP TRIGGER IF EXISTS callback_list_uuid_trigger ON callback_list"
    sudo -u postgres psql asterisk -c "DROP TRIGGER IF EXISTS callback_request_uuid_trigger ON callback_request"
    sudo -u postgres psql asterisk -c "DROP TRIGGER IF EXISTS preferred_callback_period_uuid_trigger ON preferred_callback_period"
    # 2. Set default to native uuid_generate_v4
    sudo -u postgres psql asterisk -c "ALTER TABLE IF EXISTS callback_list ALTER COLUMN uuid SET DEFAULT uuid_generate_v4()"
    sudo -u postgres psql asterisk -c "ALTER TABLE IF EXISTS callback_request ALTER COLUMN uuid SET DEFAULT uuid_generate_v4()"
    sudo -u postgres psql asterisk -c "ALTER TABLE IF EXISTS preferred_callback_period ALTER COLUMN uuid SET DEFAULT uuid_generate_v4()"
    # 3. Drop custom function
    sudo -u postgres psql asterisk -c "DROP FUNCTION IF EXISTS uuid_generator()"

    # Drop play_evolutions table
    sudo -u postgres psql asterisk -c "DROP TABLE IF EXISTS play_evolutions"
}

add_new_category_type() {
    # Add new value to right_type Enum
    sudo -u postgres psql asterisk -c "ALTER TYPE right_type ADD VALUE IF NOT EXISTS 'recording_access'"
    # Add recording_access right to current supervisor
    sudo -u postgres psql asterisk -c "INSERT INTO rights(user_id, category, category_id) SELECT id,'recording_access','1' FROM users WHERE type = 'supervisor'"
}

is_postgres_9_running() {
    if pg_lsclusters --no-header | grep -q online ; then
        return 0
    else
        return 1
    fi
}

is_postgres_running_on_port() {
    result=$(psql -h localhost -p $1 -U postgres --quiet -tAc "SELECT 1 FROM pg_catalog.pg_database WHERE datname='$2'" 2> /dev/null)

    [ $? -eq 0 ] && [ "$result" = "1" ]
}

pull_and_start_db() {
    xivo-dcomp upgrade-db
}

wait_for_postgres() {
    local wait_time=600
    echo -n "Waiting $wait_time seconds for database $2 on port $1..."

    local db_running="false"
    for i in $(seq 1 $wait_time); do
        if is_postgres_running_on_port "$1" "$2"; then
            db_running="true"
            break
        else
            sleep 1
            echo -n "."
        fi
    done
    echo
    if [ "$db_running" = "false" ]; then
        echo "ERROR: database is not running."
    fi
}

ensure_user_group_postgres() {    
    if ! getent group postgres &> /dev/null; then
        groupadd -r postgres
    fi

    if ! getent passwd postgres &> /dev/null; then
        useradd -r -g postgres --home-dir=/var/lib/postgresql --shell=/bin/bash -c "PostgreSQL administrator" postgres
    fi

    if [ ! -d /var/lib/postgresql ]; then
        mkdir -p /var/lib/postgresql
        chown -R postgres:postgres /var/lib/postgresql
    fi

    if [ ! -d /var/log/postgresql ]; then
        mkdir -p /var/log/postgresql
        chown -R postgres:postgres /var/log/postgresql
    fi

    # Check default group for postgres
    local POSTGRES_USER_GROUP=$(id -gn postgres)
    if [ "$POSTGRES_USER_GROUP" != "postgres" ]; then
        usermod -g postgres postgres
    fi
}

create_pgpass_file() {
    echo "Overwriting .pgpass file"
    echo "localhost:5432:asterisk:asterisk:proformatique" > /root/.pgpass
    echo "localhost:5432:postgres:postgres:proformatique" >> /root/.pgpass
    echo "localhost:5432:asterisk:postgres:proformatique" >> /root/.pgpass
    echo "localhost:5433:asterisk:asterisk:proformatique" >> /root/.pgpass
    echo "localhost:5433:postgres:postgres:proformatique" >> /root/.pgpass
    echo "localhost:5433:asterisk:postgres:proformatique" >> /root/.pgpass
    chmod 600 /root/.pgpass
}


case "$1" in
    configure)
        ensure_user_group_postgres
        
        if [ -z "$2" ]; then
            # First installation
            
            create_pgpass_file
            pull_and_start_db
            wait_for_postgres 5432 asterisk

            if is_postgres_running_on_port 5432 asterisk; then
                xivo-update-keys
                xivo-configure-uuid
            fi

        else
            # Migration from old version
            previous_version="$2"

            # All the upgrades steps below should run only on XiVO that were below 2019.04.00
            # (i.e. before postgres was in a container)
            if dpkg --compare-versions "$previous_version" "<<" "2019.04.00"; then

                new_dir=/var/lib/xivo-manage-db/update-db
                for old_dir in /var/lib/xivo-update-db /var/lib/xivo-upgrade/update-db ; do
                    if [ -d "$old_dir" ]; then
                        mv "$old_dir"/* "$new_dir"
                        rm -fr "$old_dir"
                    fi
                done

                if is_postgres_9_running ; then
                    # Apply to postgres 9.4 database
                    if dpkg --compare-versions "$previous_version" "<<" "16.01~20160125"; then
                        su - -c "psql -c 'create extension if not exists pgcrypto;' asterisk > /dev/null 2>&1" postgres
                    fi
                    if dpkg --compare-versions "$previous_version" "<<" "2018.09.00"; then
                        if dpkg --compare-versions "$previous_version" ">=" "2018.04.00"; then
                            # Re-give ownership to configmgt
                            if role_exists "configmgt"; then
                                reassign_owned_configmgt
                            fi
                        fi
                    fi

                    if dpkg --compare-versions "$previous_version" "<<" "2019.04.00"; then
                        xivo-update-db
                        xivo-update-keys
                        xivo-configure-uuid

                        create_pgpass_file
                    fi

                    # These actions must be done after database schema migration
                    if dpkg --compare-versions "$previous_version" "<<" "2018.09.00"; then
                        # For all versions, remove configmgt role
                        # (it was added during db update by alembic script 41c2e6de9334)
                        remove_configmgt_role

                        # For versions where configmgt tables were already in xivo
                        if dpkg --compare-versions "$previous_version" ">=" "2018.04.00"; then
                            clean_old_configmgt_tables_definition
                            add_new_category_type
                        fi
                    fi

                    if dpkg --compare-versions "$previous_version" "<<" "2018.10.00"; then
                        # Fix stats role rights on all tables in schema public, xc
                        fix_privileges_to_stats_role_on_asterisk_db
                        # And then, for the future, grant default privileges to the stats role
                        grant_default_privileges_to_stats_role_on_asterisk_db
                    fi

                    if dpkg --compare-versions "$previous_version" "<<" "2018.12.00"; then
                        # Add dbreplic user for asterisk db
                        add_dbreplic_role_on_asterisk_db
                        # And then, for the future, grant default privileges to the dbreplic role
                        grant_default_privileges_to_dbreplic_role_on_asterisk_db
                    fi
                fi
            fi

        fi
    ;;

    abort-upgrade)
    ;;

    *)
        echo "postinst called with unknown argument \`$1'" >&2
        exit 1
    ;;
esac

# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.

#DEBHELPER#

exit 0
