From 5d8d1b7c2ddeda41855879642be04af652c30fb1 Mon Sep 17 00:00:00 2001 From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> Date: Sat, 31 Aug 2024 17:09:08 +0200 Subject: [PATCH] Fix 'without db' confusion --- .github/workflows/general.yml | 26 +++++++++++++++++++++++ scripts/init_db.sh | 40 ++++++++++++++++++++--------------- src/configuration.rs | 7 ++---- src/startup.rs | 2 +- tests/api/helpers.rs | 14 ++++++++---- 5 files changed, 62 insertions(+), 27 deletions(-) diff --git a/.github/workflows/general.yml b/.github/workflows/general.yml index 67956f6..0c21e98 100644 --- a/.github/workflows/general.yml +++ b/.github/workflows/general.yml @@ -16,6 +16,9 @@ env: CARGO_TERM_COLOR: always SQLX_VERSION: 0.8.0 SQLX_FEATURES: "rustls,postgres" + APP_USER: app + APP_USER_PWD: secret + APP_DB_NAME: newsletter jobs: test: @@ -60,6 +63,18 @@ jobs: # This may be useful for ensuring reproducible builds, to use the exact same set of dependencies that were available when the package was published. # It may also be useful if a newer version of a dependency is published that no longer builds on your system, or has other problems + - name: Create app user in Postgres + run: | + sudo apt-get install postgresql-client + + # Create the application user + CREATE_QUERY="CREATE USER ${APP_USER} WITH PASSWORD '${APP_USER_PWD}';" + PGPASSWORD="password" psql -U "postgres" -h "localhost" -c "${CREATE_QUERY}" + + # Grant create db privileges to the app user + GRANT_QUERY="ALTER USER ${APP_USER} CREATEDB;" + PGPASSWORD="password" psql -U "postgres" -h "localhost" -c "${GRANT_QUERY}" + - name: Migrate database run: | SKIP_DOCKER=true ./scripts/init_db.sh @@ -125,6 +140,17 @@ jobs: --features ${{ env.SQLX_FEATURES }} --no-default-features --locked + - name: Create app user in Postgres + run: | + sudo apt-get install postgresql-client + + # Create the application user + CREATE_QUERY="CREATE USER ${APP_USER} WITH PASSWORD '${APP_USER_PWD}';" + PGPASSWORD="password" psql -U "postgres" -h "localhost" -c "${CREATE_QUERY}" + + # Grant create db privileges to the app user + GRANT_QUERY="ALTER USER ${APP_USER} CREATEDB;" + PGPASSWORD="password" psql -U "postgres" -h "localhost" -c "${GRANT_QUERY}" - name: Migrate database run: SKIP_DOCKER=true ./scripts/init_db.sh - name: Install cargo-llvm-cov diff --git a/scripts/init_db.sh b/scripts/init_db.sh index 8c91502..42625bf 100755 --- a/scripts/init_db.sh +++ b/scripts/init_db.sh @@ -10,16 +10,13 @@ if ! [ -x "$(command -v sqlx)" ]; then exit 1 fi -# Check if a custom user has been set, otherwise default to 'postgres' -DB_USER="${POSTGRES_USER:=postgres}" -# Check if a custom password has been set, otherwise default to 'password' -DB_PASSWORD="${POSTGRES_PASSWORD:=password}" -# Check if a custom database name has been set, otherwise default to 'newsletter' -DB_NAME="${POSTGRES_DB:=newsletter}" -# Check if a custom port has been set, otherwise default to '5432' -DB_PORT="${POSTGRES_PORT:=5432}" -# Check if a custom host has been set, otherwise default to 'localhost' -DB_HOST="${POSTGRES_HOST:=localhost}" +# Check if a custom parameter has been set, otherwise use default values +DB_PORT="${DB_PORT:=5432}" +SUPERUSER="${SUPERUSER:=postgres}" +SUPERUSER_PWD="${SUPERUSER_PWD:=password}" +APP_USER="${APP_USER:=app}" +APP_USER_PWD="${APP_USER_PWD:=secret}" +APP_DB_NAME="${APP_DB_NAME:=newsletter}" # Allow to skip Docker if a dockerized Postgres database is already running if [[ -z "${SKIP_DOCKER}" ]] @@ -34,15 +31,14 @@ then CONTAINER_NAME="postgres_$(date '+%s')" # Launch postgres using Docker docker run \ - -e POSTGRES_USER=${DB_USER} \ - -e POSTGRES_PASSWORD=${DB_PASSWORD} \ - -e POSTGRES_DB=${DB_NAME} \ - --health-cmd="pg_isready -U ${DB_USER} || exit 1" \ + --env POSTGRES_USER=${SUPERUSER} \ + --env POSTGRES_PASSWORD=${SUPERUSER_PWD} \ + --health-cmd="pg_isready -U ${SUPERUSER} || exit 1" \ --health-interval=1s \ --health-timeout=5s \ --health-retries=5 \ - -p "${DB_PORT}":5432 \ - -d \ + --publish "${DB_PORT}":5432 \ + --detach \ --name "${CONTAINER_NAME}" \ postgres -N 1000 # ^ Increased maximum number of connections for testing purposes @@ -54,11 +50,21 @@ then >&2 echo "Postgres is still unavailable - sleeping" sleep 1 done + + # Create the application user + CREATE_QUERY="CREATE USER ${APP_USER} WITH PASSWORD '${APP_USER_PWD}';" + docker exec -it "${CONTAINER_NAME}" psql -U "${SUPERUSER}" -c "${CREATE_QUERY}" + + # Grant create db privileges to the app user + GRANT_QUERY="ALTER USER ${APP_USER} CREATEDB;" + docker exec -it "${CONTAINER_NAME}" psql -U "${SUPERUSER}" -c "${GRANT_QUERY}" fi >&2 echo "Postgres is up and running on port ${DB_PORT} - running migrations now!" -export DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME} +# Create the application database +DATABASE_URL=postgres://${APP_USER}:${APP_USER_PWD}@localhost:${DB_PORT}/${APP_DB_NAME} +export DATABASE_URL sqlx database create sqlx migrate run diff --git a/src/configuration.rs b/src/configuration.rs index 8d7fdab..e17d908 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -33,7 +33,7 @@ pub struct DatabaseSettings { } impl DatabaseSettings { - pub fn without_db(&self) -> PgConnectOptions { + pub fn connect_options(&self) -> PgConnectOptions { let ssl_mode = if self.require_ssl { PgSslMode::Require } else { @@ -45,10 +45,7 @@ impl DatabaseSettings { .password(self.password.expose_secret()) .port(self.port) .ssl_mode(ssl_mode) - } - - pub fn with_db(&self) -> PgConnectOptions { - self.without_db().database(&self.database_name) + .database(&self.database_name) } } diff --git a/src/startup.rs b/src/startup.rs index 313999f..77e80d8 100644 --- a/src/startup.rs +++ b/src/startup.rs @@ -73,7 +73,7 @@ impl Application { pub async fn get_connection_pool(configuration: &DatabaseSettings) -> Result { PgPoolOptions::new() - .connect_with(configuration.with_db()) + .connect_with(configuration.connect_options()) .await } diff --git a/tests/api/helpers.rs b/tests/api/helpers.rs index 6f0f588..d650fce 100644 --- a/tests/api/helpers.rs +++ b/tests/api/helpers.rs @@ -1,5 +1,6 @@ use argon2::password_hash::SaltString; use argon2::{Algorithm, Argon2, Params, PasswordHasher, Version}; +use secrecy::Secret; use sqlx::{Connection, Executor, PgConnection, PgPool}; use std::sync::LazyLock; use uuid::Uuid; @@ -201,23 +202,28 @@ pub async fn spawn_app() -> TestApp { async fn configure_database(config: &DatabaseSettings) -> PgPool { // Create database - let mut connection = PgConnection::connect_with(&config.without_db()) + let maintenance_settings = DatabaseSettings { + database_name: "postgres".to_string(), + username: "postgres".to_string(), + password: Secret::new("password".to_string()), + ..config.clone() + }; + let mut connection = PgConnection::connect_with(&maintenance_settings.connect_options()) .await .expect("Failed to connect to Postgres"); connection - .execute(&*format!(r#"CREATE DATABASE "{}";"#, config.database_name)) + .execute(format!(r#"CREATE DATABASE "{}";"#, config.database_name).as_str()) .await .expect("Failed to create database."); // Migrate database - let connection_pool = PgPool::connect_with(config.with_db()) + let connection_pool = PgPool::connect_with(config.connect_options()) .await .expect("Failed to connect to Postgres."); sqlx::migrate!("./migrations") .run(&connection_pool) .await .expect("Failed to migrate the database"); - connection_pool }