Skip to content
Snippets Groups Projects
Select Git revision
  • 5a59dc3afaca48b8158d77b22f9c49debd2ba03d
  • main default protected
  • dev protected
  • f-linkahead-rename
  • f-real-id
  • f-filesystem-import
  • f-filesystem-link
  • f-filesystem-directory
  • f-filesystem-core
  • f-filesystem-cleanup
  • f-filesystem-main
  • f-name
  • keep_changes
  • f-permission-checks-2
  • f-mysql8-tests
  • f-retrieve-history
  • t-distinct-parents
  • v8.1.0
  • v8.0.0
  • v7.0.2
  • v7.0.1
  • v7.0.0
  • v6.0.1
  • v6.0.0
  • v5.0.0
  • v4.1.0
  • v4.0.0
  • v3.0
  • v2.0.30
29 results

make_db

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    make_db 8.56 KiB
    #!/bin/bash
    
    # This file is a part of the LinkAhead Project.
    #
    # Copyright (C) 2021, 2024 Indiscale GmbH <info@indiscale.com>
    # Copyright (C) 2019, 2020, 2021, 2024 Daniel Hornung <d.hornung@indiscale.com>
    # Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
    # Copyright (C) 2020 Henrik tom Wörden <h.tomwoerden@indiscale.com>
    # Copyright (C) 2020 IndiScale <info@indiscale.com>
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU Affero General Public License as
    # published by the Free Software Foundation, either version 3 of the
    # License, or (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU Affero General Public License for more details.
    #
    # You should have received a copy of the GNU Affero General Public License
    # along with this program. If not, see <https://www.gnu.org/licenses/>.
    #
    
    # Although some sanity checks are performed, this script still allows lots of SQL injection
    # possibilities.
    
    
    set -e
    
    INSTALL_SQL_FILE="db_5_0.sql"
    
    if [ -z "$UTILSPATH" ]; then
        UTILSPATH="$(realpath $(dirname $0))"
        export UTILSPATH
    fi
    
    source $UTILSPATH/load_settings.sh
    source $UTILSPATH/helpers.sh
    
    UNITTEST_DATABASE=${UNITTEST_DATABASE-_caosdb_schema_unit_tests}
    
    # optional parameter: [--fresh] for installing a fresh data base. Otherwise an existing one would be reused.
    function runtests() {
        DATABASE_NAME=$UNITTEST_DATABASE
        _setup_mytap
    
        _install_unit_test_database $@
    
        _execute_tests || ( failure )
        echo "[PASS]"
    }
    
    function _execute_tests () {
        pushd tests
        TESTS="./test*.sql"
    
        rm -f .TEST_RESULTS
        for tfile in $TESTS ; do
            echo "Running $tfile"
            echo "----- $tfile -----" >> .TEST_RESULTS
            < $tfile $MYSQL_CMD \
              -D $UNITTEST_DATABASE $(get_db_args_nodb) --disable-pager \
              --batch --raw --skip-column-names --unbuffered \
              >> .TEST_RESULTS 2>&1
        done;
    
        popd
        cat tests/.TEST_RESULTS
        grep -c -i "failed" tests/.TEST_RESULTS > /dev/null && return 1
        grep -c -i "ERROR" tests/.TEST_RESULTS > /dev/null && return 1
        return 0
    }
    
    # install/reset database for unit tests.
    # optional parameter: [--fresh] for installing a fresh data base. Otherwise an existing one would be reused.
    function _install_unit_test_database () {
        DATABASE_NAME=$UNITTEST_DATABASE
        if [[ $1 = "--fresh" ]] ; then
            if _db_exists "$DATABASE_NAME"; then
                drop "$DATABASE_NAME" ;
            fi
        fi
    
        if _db_exists "$DATABASE_NAME"; then
            echo "using $DATABASE_NAME"
        else
            sed "s/db_5_0/$DATABASE_NAME/g" "$INSTALL_SQL_FILE" | $MYSQL_CMD $(get_db_args_nodb)
    
            # create test user
            grant
        fi
    
    
        echo "DATABASE_NAME=\"$UNITTEST_DATABASE\"" >> .test_config
        pushd patches > /dev/null
        export ENV_FILE=$(realpath ../.test_config)
        ./applyPatches.sh
        unset ENV_FILE
        popd > /dev/null
        rm .test_config
    }
    
    # install test framework MyTAP if not installed
    function _setup_mytap() {
        if _db_exists "tap" ; then
            echo MyTAB framework is already installed [OK]
            return 0
        fi
        echo -n "Installing MyTAP framework ... "
        pushd libs > /dev/null
        unzip -u mytap*.zip > /dev/null
        pushd mytap*/ > /dev/null
        $MYSQL_CMD $(get_db_args_nodb) < mytap.sql > /dev/null || exit 1
        popd > /dev/null
        rm -r mytap*/
        popd > /dev/null
        echo "[DONE]"
    }
    
    function install_db() {
        if _db_exists ; then
            echo -e "\n
    A database with with the name '$DATABASE_NAME' exists already.
    Call 'make drop-$DATABASE_NAME' to delete that database or change the database
    name in your .config file "
            exit 0
        fi
    
        sed "s/db_5_0/$DATABASE_NAME/g" "$INSTALL_SQL_FILE" | $MYSQL_CMD $(get_db_args_nodb)
    }
    
    function sanity_check() {
        trap "$(shopt -po errexit)" RETURN
        set +e
        echo -n "running sanity checks ..."
        msg="$($MYSQL_CMD $(get_db_args) < "utils/sanity_check.sql" 2>/dev/null)"
        code="$?"
        if [ "$code" -eq "0" ] ; then
            echo " [OK]"
        else
            echo " [FAILED]"
            echo "$msg"
            exit 1
        fi
    }
    
    # Inserts the dump (arg 1) into the database
    function restore_db() {
        SQL_FILE="$1"
        $MYSQL_CMD $(get_db_args) < "$SQL_FILE"
        cat <<EOF
    If this is not the same SQL server where the SQL dump was originally created
    from, make sure that a user with sufficient permissions exists.  Note that you
    can use the 'grant' action of this script to do this.
    EOF
    }
    
    function test-connection() {
        $MYSQL_CMD $(get_db_args_nodb) -e "select 0;"
    }
    
    # Creates a user and grants it sufficient rights.
    # If called with --strict, the user is not allowed to exist previously.
    function grant() {
        if [ -z "$DATABASE_USER_PW" ] ; then
            while true; do
                read -p "Please enter the password for ${DATABASE_USER}: " \
                     -s password
                echo
                read -p "Please repeat the password: " -s password2
                echo
                [[ "$password" = "$password2" ]] && {
                    DATABASE_USER_PW="$password"
                    break
                }
                echo -e "\nThe passwords didn't match. Try again."
            done
        fi
    
        if [[ $1 = "--strict" ]] ; then
            for host in ${DATABASE_USER_HOST_LIST//,/ } ; do
                CMD="SELECT COUNT(*) FROM mysql.user WHERE user='${DATABASE_USER}' AND host='${host}';"
                [[ $($MYSQL_CMD $(get_db_args_nodb) -s -N -e "$CMD") = 0 ]] || {
                    echo "The user '${DATABASE_USER}@${host}' is already in the database."
                    echo "Please use another user or delete it, e.g. with"
                    echo "'mysql -u ${MYSQL_USER} -p -e \"DROP USER ${DATABASE_USER}@${host};\"'"
                    exit 1
                }
            done
        fi
    
        for host in ${DATABASE_USER_HOST_LIST//,/ } ; do
            echo "Granting admin privileges to '$DATABASE_USER'@'$host'"
            # FIXME Are all these permissions necessary? See
            # https://gitlab.indiscale.com/caosdb/src/caosdb-mysqlbackend/-/issues/28 "Default
            # installation target does not work for existing databases"
            $MYSQL_CMD $(get_db_args_nodb) <<EOF
    CREATE USER IF NOT EXISTS
        '$DATABASE_USER'@'$host' identified by '$DATABASE_USER_PW';
    GRANT USAGE ON *.* TO '$DATABASE_USER'@'$host';
    GRANT ALL PRIVILEGES ON *.* TO '$DATABASE_USER'@'$host' WITH GRANT OPTION;
    GRANT EXECUTE ON *.* TO '$DATABASE_USER'@'$host';
    EOF
        done
    }
    
    # Drops the caosdb user plus a given database from all listed database hosts.
    # The first argument to this function is the database that shal be dropped.
    function drop() {
        DROPDB="$1"
        for host in ${DATABASE_USER_HOST_LIST//,/ } ; do
            $MYSQL_CMD $(get_db_args_nodb) -e "DROP USER '${DATABASE_USER}'@'${host}';" || true
        done
        "$MYSQLADMIN_CMD" $(get_db_args_nodb) -f drop "$DROPDB"
    }
    
    
    # Returns 0 or non-zero, depending on whether the database exists already.
    # Optional parameter: [DATABASE_NAME], else $DATABASE_NAME is used.
    function _db_exists() {
        $MYSQL_CMD $(get_db_args_nodb) -D "${1-${DATABASE_NAME}}" -e "show tables;" > /dev/null 2>&1 \
            && return 0 || return 1
    }
    
    
    # Grant the given permissions to the given role.
    #
    # Arguments
    # ---------
    # role : str
    # The role, may consist of alphanumerical letters plus `.`, `_`, `-`.  The role must exist in the
    # `roles` table.
    #
    # permissions : str
    # The permissions string.  May not contain single quotes, should be similar to:
    # [{"grant":"true","priority":"true","permission":"*"}]
    function grant-permission() {
        role="$1"
        permissions="$2"
        if echo -n "$role" | grep -v -q "^[[:alnum:]._-]*$" ; then
            echo "Role contains invalid character(s)!"
            exit 1
        fi
        if [[ $permissions == "'" ]]; then
            echo "Permissions string contains single quote!"
            exit 1
        fi
    
        cmd="SELECT COUNT(1) from roles where name='${role}';"
        count=$($MYSQL_CMD $(get_db_args) -AN -e "$cmd")
        if [[ $count == "0" ]]; then
            echo "Role not found!"
            exit 1
        fi
    
        cmd="INSERT INTO permissions (role, permissions) VALUE ('${role}', '${permissions}')"
        cmd+="ON DUPLICATE KEY UPDATE role='${role}', permissions='${permissions}'"
        cmd+=";"
        $MYSQL_CMD $(get_db_args) -e "$cmd"
    }
    
    
    case $1 in
        "drop") drop $2 ;;
        "grant") grant $2 ;;
        "grant-permission") grant-permission $2 $3 ;; # Args: role, permissions
        "test") shift ; runtests $@ ;;
        "test-connection") test-connection ;;
        "install_db") install_db ;;
        "restore_db") restore_db $2 ;;
        "sanity_check") sanity_check ;;
        *) echo "Unknown action: $1"; exit 32
    esac