diff --git a/gitlab/base.sh b/gitlab/base.sh index a07f026d5b..9317ce825b 100755 --- a/gitlab/base.sh +++ b/gitlab/base.sh @@ -33,7 +33,7 @@ fi # Generate a dbpasswords file # Note that this does not use ${DATABASE_NAME} since Symfony adds the _test postfix itself -echo "unused:sqlserver:domjudge:domjudge:domjudge:3306" > etc/dbpasswords.secret +echo 'unused:sqlserver:domjudge:domjudge:domjudge_+% #$*)@(!/;,.:3306' > etc/dbpasswords.secret # Generate APP_SECRET for symfony # shellcheck disable=SC2164 diff --git a/sql/dj_setup_database.in b/sql/dj_setup_database.in index 03742fc161..7f719e802f 100755 --- a/sql/dj_setup_database.in +++ b/sql/dj_setup_database.in @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # @configure_input@ # This script allows one to perform DOMjudge database setup actions. @@ -29,6 +29,7 @@ Commands: status check database installation status genpass generate DB,API,Symfony,admin password files create-db-users create (empty) database and users + update-password update DB user database to that in 'etc/dbpasswords.secret' install create database, example contest and users if not existing bare-install create database, setup defaults if not existing uninstall remove database users and database, INCLUDING ALL DATA! @@ -51,32 +52,47 @@ not have to pass any of the options above. EOF } +urlencode() +{ + php -r "echo rawurlencode('$1');" +} + +# This is global variable to be able to return the output from +# mysql_options() below as an array, which is not possible otherwise. +declare -a _mysql_options + mysql_options() { local user pass + _mysql_options=() # shellcheck disable=SC2153 if [ -n "$DBUSER" ]; then - user="-u $DBUSER" - else - user="${DBA_USER:+-u ${DBA_USER}}" + _mysql_options+=('-u' "$DBUSER") + elif [ -n "$DBA_USER" ]; then + _mysql_options+=('-u' "$DBA_USER") fi # shellcheck disable=SC2153 if [ -n "$PASSWD" ]; then - pass="-p$PASSWD" - else - [ -n "$PROMPT_PASSWD" ] && pass="-p" - [ -n "$DBA_PASSWD" ] && pass="-p$DBA_PASSWD" + _mysql_options+=("-p$PASSWD") + elif [ -n "$DBA_PASSWD" ]; then + _mysql_options+=("-p$DBA_PASSWD") + elif [ -n "$PROMPT_PASSWD" ]; then + _mysql_options+=('-p') fi - [ -z "$USE_SOCKET" ] && port="-P$DBPORT" - echo $user ${pass:+"$pass"} -h "$DBHOST" ${port:+"$port"} + _mysql_options+=('-h' "$DBHOST") + + if [ -z "$USE_SOCKET" ]; then + _mysql_options+=("-P$DBPORT") + fi } # Wrapper around mysql command to allow setting options, user, etc. mysql() { - command mysql $(mysql_options) --silent --skip-column-names "$@" + mysql_options + command mysql "${_mysql_options[@]}" --silent --skip-column-names "$@" } # Quick shell hack to get a key from an INI file. @@ -127,10 +143,13 @@ symfony_console() fi if [ -n "$DBA_USER" ]; then + user=$(urlencode "${DBA_USER}") + host=$(urlencode "${domjudge_DBHOST}") + db=$(urlencode "${domjudge_DBNAME}") if [ -n "$DBA_PASSWD" ]; then - DATABASE_URL=mysql://${DBA_USER}:${DBA_PASSWD}@${domjudge_DBHOST}:${domjudge_DBPORT}/${domjudge_DBNAME} + DATABASE_URL="mysql://$user:$(urlencode "${DBA_PASSWD}")@$host:${domjudge_DBPORT}/$db" else - DATABASE_URL=mysql://${DBA_USER}@${domjudge_DBHOST}:${domjudge_DBPORT}/${domjudge_DBNAME} + DATABASE_URL="mysql://$user@$host:${domjudge_DBPORT}/$db" fi fi fi @@ -235,6 +254,17 @@ remove_db_users() verbose "DOMjudge database and user(s) removed." } +update_password() +{ + read_dbpasswords + ( + echo "ALTER USER '$domjudge_DBUSER'@'localhost' IDENTIFIED BY '$domjudge_PASSWD';" + echo "FLUSH PRIVILEGES;" + ) | mysql + verbose "ALTER USER '$domjudge_DBUSER'@'localhost' IDENTIFIED BY '$domjudge_PASSWD';" + verbose "Database user password updated from credentials file." +} + install_examples() { DBUSER=$domjudge_DBUSER PASSWD=$domjudge_PASSWD symfony_console domjudge:load-example-data @@ -337,6 +367,10 @@ create-db-users) create_db_users_helper ;; +update-password) + update_password + ;; + bare-install|install) read_dbpasswords create_db_users diff --git a/webapp/config/load_db_secrets.php b/webapp/config/load_db_secrets.php index ea4ca11b83..c3a8b3dfb5 100644 --- a/webapp/config/load_db_secrets.php +++ b/webapp/config/load_db_secrets.php @@ -36,7 +36,11 @@ function get_db_url(): string break; } - return sprintf('mysql://%s:%s@%s:%d/%s?serverVersion=5.7.0', $user, $pass, $host, $port ?? 3306, $db); + return sprintf( + 'mysql://%s:%s@%s:%d/%s?serverVersion=5.7.0', + rawurlencode($user), rawurlencode($pass), rawurlencode($host), + $port ?? 3306, rawurlencode($db) + ); } function get_app_secret(): string diff --git a/webapp/config/packages/doctrine.yaml b/webapp/config/packages/doctrine.yaml index d04de47c52..d4ba6543f6 100644 --- a/webapp/config/packages/doctrine.yaml +++ b/webapp/config/packages/doctrine.yaml @@ -7,7 +7,7 @@ doctrine: charset: utf8mb4 collate: utf8mb4_unicode_ci - url: '%env(resolve:DATABASE_URL)%' + url: '%env(DATABASE_URL)%' profiling_collect_backtrace: '%kernel.debug%' types: tinyint: App\Doctrine\DBAL\Types\TinyIntType