in app/src/main/java/com/amazon/aws/partners/saasfactory/pgrls/configuration/DatabaseInit.java [40:82]
public void onApplicationEvent(ApplicationContextInitializedEvent event) {
Environment env = event.getApplicationContext().getEnvironment();
String dbAppUser = env.getRequiredProperty("spring.datasource.username");
String dbAppPassword = env.getRequiredProperty("spring.datasource.password");
String dbHost = env.getRequiredProperty("DB_HOST");
String dbDatabase = env.getRequiredProperty("DB_NAME");
String jdbcUrl = "jdbc:postgresql://" + dbHost + ":5432/" + dbDatabase;
Properties masterConnectionProperties = new Properties();
masterConnectionProperties.put("user", env.getRequiredProperty("admin.datasource.username"));
masterConnectionProperties.put("password", env.getRequiredProperty("admin.datasource.password"));
// Bootstrap the database objects. The SQL is written to be idempotent so it can run each time Spring Boot
// launches. This bootstrapping creates the tables and RLS policies. The RDS master user will be the owner
// of these tables and by default will bypass RLS which is what we need for new tenant on-boarding where
// INSERT statements would otherwise fail.
//
// This also will create a non root user with full read/write privileges for our application code to connect
// as. This user will not be the owner of tables or other objects and will be bound by the RLS policies.
try (Connection connection = DriverManager.getConnection(jdbcUrl, masterConnectionProperties); Statement sql = connection.createStatement()) {
connection.setAutoCommit(false);
LOGGER.info("Executing bootstrap database");
try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("bootstrap.sql")) {
Scanner scanner = new Scanner(is, "UTF-8");
// Break on blank newline so we can send the DO...END statements as a single statement
scanner.useDelimiter("\n\n");
while (scanner.hasNext()) {
String stmt = scanner.next()
.replace("{{DB_APP_USER}}", dbAppUser)
.replace("{{DB_APP_PASS}}", dbAppPassword)
.trim();
sql.addBatch(stmt);
}
int[] count = sql.executeBatch();
connection.commit();
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}