diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonDBConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonDBConfig.java index b7bd7a52f11..417cb3de2bd 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonDBConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonDBConfig.java @@ -69,10 +69,23 @@ public DataSourceProperties extractJdbcProperties(String dbUrl) { ds.setUsername(userDetails[0]); ds.setPassword(userDetails[1]); } - // If the port is not mentioned default it to standard 5432 + // If the port is not mentioned, default it to the standard PostgreSQL port 5432 int port = uri.getPort() == -1 ? 5432 : uri.getPort(); - String updatedUrl = - String.format("%s%s://%s:%s%s", JDBC_PREFIX, uri.getScheme(), uri.getHost(), port, uri.getPath()); + + // Check if the URL already has query parameters + String query = uri.getQuery(); + String updatedUrl; + if (StringUtils.hasLength(query)) { + // Append currentSchema=appsmith if there are already parameters + updatedUrl = String.format( + "%s%s://%s:%s%s?%s¤tSchema=appsmith", + JDBC_PREFIX, uri.getScheme(), uri.getHost(), port, uri.getPath(), query); + } else { + // No parameters, just append currentSchema + updatedUrl = String.format( + "%s%s://%s:%s%s?currentSchema=appsmith", + JDBC_PREFIX, uri.getScheme(), uri.getHost(), port, uri.getPath()); + } ds.setUrl(updatedUrl); return ds; } catch (URISyntaxException e) { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/CommonDBConfigTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/CommonDBConfigTest.java index 1332b7241de..eb859178637 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/CommonDBConfigTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/CommonDBConfigTest.java @@ -16,13 +16,13 @@ public void testExtractAndSaveJdbcParams_validDbUrlWithUsernameAndPassword() { DataSourceProperties ds = commonDBConfig.extractJdbcProperties(dbUrl); assertEquals("postgres", ds.getUsername()); assertEquals("password", ds.getPassword()); - assertEquals("jdbc:postgresql://localhost:5432/postgres", ds.getUrl()); + assertEquals("jdbc:postgresql://localhost:5432/postgres?currentSchema=appsmith", ds.getUrl()); String dbUrlWithPort = "postgresql://postgres:password@localhost:1234/postgres"; ds = commonDBConfig.extractJdbcProperties(dbUrlWithPort); assertEquals("postgres", ds.getUsername()); assertEquals("password", ds.getPassword()); - assertEquals("jdbc:postgresql://localhost:1234/postgres", ds.getUrl()); + assertEquals("jdbc:postgresql://localhost:1234/postgres?currentSchema=appsmith", ds.getUrl()); } @Test @@ -32,7 +32,7 @@ public void testExtractAndSaveJdbcParams_validDbUrlWithoutUsernameAndPassword() DataSourceProperties ds = commonDBConfig.extractJdbcProperties(dbUrl); assertNull(ds.getUsername()); assertNull(ds.getPassword()); - assertEquals("jdbc:postgresql://localhost:5432/postgres", ds.getUrl()); + assertEquals("jdbc:postgresql://localhost:5432/postgres?currentSchema=appsmith", ds.getUrl()); } @Test @@ -44,4 +44,31 @@ public void testExtractAndSaveJdbcParams_invalidDbUrl() { dbUrl); assertThrows(IllegalArgumentException.class, () -> commonDBConfig.extractJdbcProperties(dbUrl), errorString); } + + @Test + void testExtractJdbcPropertiesWithQueryParams() { + CommonDBConfig commonDBConfig = new CommonDBConfig(); + String dbUrl = "postgresql://user:password@localhost:5432/mydb?sslmode=require"; + + DataSourceProperties dataSourceProperties = commonDBConfig.extractJdbcProperties(dbUrl); + + String expectedUrl = "jdbc:postgresql://localhost:5432/mydb?sslmode=require¤tSchema=appsmith"; + assertEquals( + expectedUrl, + dataSourceProperties.getUrl(), + "URL with existing query params should append the currentSchema correctly."); + } + + @Test + void testExtractJdbcPropertiesWithoutQueryParams() { + CommonDBConfig commonDBConfig = new CommonDBConfig(); + String dbUrl = "postgresql://user:password@localhost:5432/mydb"; + DataSourceProperties dataSourceProperties = commonDBConfig.extractJdbcProperties(dbUrl); + + String expectedUrl = "jdbc:postgresql://localhost:5432/mydb?currentSchema=appsmith"; + assertEquals( + expectedUrl, + dataSourceProperties.getUrl(), + "URL without query params should append the currentSchema correctly."); + } } diff --git a/deploy/docker/fs/opt/appsmith/entrypoint.sh b/deploy/docker/fs/opt/appsmith/entrypoint.sh index 3d73af5b391..5e42418d92a 100644 --- a/deploy/docker/fs/opt/appsmith/entrypoint.sh +++ b/deploy/docker/fs/opt/appsmith/entrypoint.sh @@ -58,6 +58,7 @@ init_env_file() { # Generate new docker.env file when initializing container for first time or in Heroku which does not have persistent volume tlog "Generating default configuration file" mkdir -p "$CONF_PATH" + local default_appsmith_mongodb_user="appsmith" local generated_appsmith_mongodb_password=$( tr -dc A-Za-z0-9 "$ENV_PATH" fi - tlog "Load environment configuration" # Load the ones in `docker.env` in the stacks folder. diff --git a/deploy/docker/fs/opt/appsmith/pg-utils.sh b/deploy/docker/fs/opt/appsmith/pg-utils.sh index 315446f552d..7c37c8c4ebe 100755 --- a/deploy/docker/fs/opt/appsmith/pg-utils.sh +++ b/deploy/docker/fs/opt/appsmith/pg-utils.sh @@ -87,6 +87,54 @@ extract_postgres_db_params() { export PG_DB_NAME="$DB" } +init_pg_db() { + # Create the appsmith schema + echo "Initializing PostgreSQL with schema..." + + # Check if APPSMITH_DB_URL is a PostgreSQL URL + if [[ -n "$APPSMITH_DB_URL" && "$APPSMITH_DB_URL" == postgres*://* ]]; then + echo "APPSMITH_DB_URL is a valid PostgreSQL URL." + + # Check if the DB_HOST is local (localhost or 127.0.0.1) + if [[ "$PG_DB_HOST" == "localhost" || "$PG_DB_HOST" == "127.0.0.1" ]]; then + + # Check if the database exists + DB_CHECK=$(psql -h "$PG_DB_HOST" -p "$PG_DB_PORT" -U postgres -d "postgres" -tAc "SELECT 1 FROM pg_database WHERE datname='$PG_DB_NAME'") + + if [ "$DB_CHECK" != "1" ]; then + echo "Database $PG_DB_NAME does not exist. Creating database..." + psql -h "$PG_DB_HOST" -p "$PG_DB_PORT" -U postgres -d "postgres" -c "CREATE DATABASE $PG_DB_NAME;" + else + echo "Database $PG_DB_NAME already exists." + fi + + # Check if the schema exists + SCHEMA_CHECK=$(psql -h "$PG_DB_HOST" -p "$PG_DB_PORT" -U postgres -d "$PG_DB_NAME" -tAc "SELECT 1 FROM information_schema.schemata WHERE schema_name='appsmith'") + + # Create schema and user if not exists + if [ "$SCHEMA_CHECK" != "1" ]; then + echo "Creating user '$PG_DB_USER' with password " + psql -h "$PG_DB_HOST" -p "$PG_DB_PORT" -U postgres -d "$PG_DB_NAME" -c "CREATE USER \"$PG_DB_USER\" WITH PASSWORD '$PG_DB_PASSWORD';" + + echo "Schema 'appsmith' does not exist. Creating schema..." + psql -h "$PG_DB_HOST" -p "$PG_DB_PORT" -U postgres -d "$PG_DB_NAME" -c "CREATE SCHEMA appsmith;" + fi + else + echo "Remote PostgreSQL detected, running as current user." + PGPASSWORD=$PG_DB_PASSWORD psql -h "$PG_DB_HOST" -p "$PG_DB_PORT" -U "$PG_DB_USER" -d "$PG_DB_NAME" -c "CREATE SCHEMA IF NOT EXISTS appsmith;" + fi + + # Check if the schema creation was successful + if [ $? -eq 0 ]; then + echo "Schema 'appsmith' created or already exists." + else + echo "Failed to create schema 'appsmith'." + exit 1 + fi + echo "PostgreSQL initialization completed." + fi +} + # Example usage of the functions # waitForPostgresAvailability -# extract_postgres_db_params "postgresql://user:password@localhost:5432/dbname" \ No newline at end of file +# extract_postgres_db_params "postgresql://user:password@localhost:5432/dbname" diff --git a/deploy/docker/fs/opt/appsmith/run-java.sh b/deploy/docker/fs/opt/appsmith/run-java.sh index ed88e26e119..77d5ccfe744 100755 --- a/deploy/docker/fs/opt/appsmith/run-java.sh +++ b/deploy/docker/fs/opt/appsmith/run-java.sh @@ -36,6 +36,7 @@ match-proxy-url() { if [[ "$mode" == "pg" ]]; then extract_postgres_db_params "$APPSMITH_DB_URL" waitForPostgresAvailability + init_pg_db fi if match-proxy-url "${HTTP_PROXY-}"; then diff --git a/deploy/docker/fs/opt/appsmith/templates/docker.env.sh b/deploy/docker/fs/opt/appsmith/templates/docker.env.sh index e8013324280..9a826d4dfb6 100644 --- a/deploy/docker/fs/opt/appsmith/templates/docker.env.sh +++ b/deploy/docker/fs/opt/appsmith/templates/docker.env.sh @@ -2,7 +2,7 @@ set -o nounset MONGO_USER="$1" -MONGO_PASSWORD="$2" +DB_PASSWORD="$2" ENCRYPTION_PASSWORD="$3" ENCRYPTION_SALT="$4" SUPERVISOR_PASSWORD="$5" @@ -63,9 +63,10 @@ APPSMITH_RECAPTCHA_SITE_KEY= APPSMITH_RECAPTCHA_SECRET_KEY= APPSMITH_RECAPTCHA_ENABLED= -APPSMITH_DB_URL=mongodb://$MONGO_USER:$MONGO_PASSWORD@localhost:27017/appsmith +APPSMITH_DB_URL=mongodb://$MONGO_USER:$DB_PASSWORD@localhost:27017/appsmith +APPSMITH_POSTGRES_DB_URL=postgresql://appsmith:$DB_PASSWORD@localhost:5432/appsmith APPSMITH_MONGODB_USER=$MONGO_USER -APPSMITH_MONGODB_PASSWORD=$MONGO_PASSWORD +APPSMITH_MONGODB_PASSWORD=$DB_PASSWORD APPSMITH_API_BASE_URL=http://localhost:8080/api/v1 APPSMITH_REDIS_URL=redis://127.0.0.1:6379