mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-06-12 05:07:40 +02:00
Add support for multiple simultaneous database features by using macros.
Diesel requires the following changes: - Separate connection and pool types per connection, the generate_connections! macro generates an enum with a variant per db type - Separate migrations and schemas, these were always imported as one type depending on db feature, now they are all imported under different module names - Separate model objects per connection, the db_object! macro generates one object for each connection with the diesel macros, a generic object, and methods to convert between the connection-specific and the generic ones - Separate connection queries, the db_run! macro allows writing only one that gets compiled for all databases or multiple ones
This commit is contained in:
82
src/main.rs
82
src/main.rs
@ -33,6 +33,7 @@ mod api;
|
||||
mod auth;
|
||||
mod config;
|
||||
mod crypto;
|
||||
#[macro_use]
|
||||
mod db;
|
||||
mod mail;
|
||||
mod util;
|
||||
@ -61,10 +62,8 @@ fn main() {
|
||||
_ => false,
|
||||
};
|
||||
|
||||
check_db();
|
||||
check_rsa_keys();
|
||||
check_web_vault();
|
||||
migrations::run_migrations();
|
||||
|
||||
create_icon_cache_folder();
|
||||
|
||||
@ -200,30 +199,6 @@ fn chain_syslog(logger: fern::Dispatch) -> fern::Dispatch {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_db() {
|
||||
if cfg!(feature = "sqlite") {
|
||||
let url = CONFIG.database_url();
|
||||
let path = Path::new(&url);
|
||||
|
||||
if let Some(parent) = path.parent() {
|
||||
if create_dir_all(parent).is_err() {
|
||||
error!("Error creating database directory");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn on WAL in SQLite
|
||||
if CONFIG.enable_db_wal() {
|
||||
use diesel::RunQueryDsl;
|
||||
let connection = db::get_connection().expect("Can't connect to DB");
|
||||
diesel::sql_query("PRAGMA journal_mode=wal")
|
||||
.execute(&connection)
|
||||
.expect("Failed to turn on WAL");
|
||||
}
|
||||
}
|
||||
db::get_connection().expect("Can't connect to DB");
|
||||
}
|
||||
|
||||
fn create_icon_cache_folder() {
|
||||
// Try to create the icon cache folder, and generate an error if it could not.
|
||||
create_dir_all(&CONFIG.icon_cache_folder()).expect("Error creating icon cache directory");
|
||||
@ -285,57 +260,22 @@ fn check_web_vault() {
|
||||
let index_path = Path::new(&CONFIG.web_vault_folder()).join("index.html");
|
||||
|
||||
if !index_path.exists() {
|
||||
error!("Web vault is not found. To install it, please follow the steps in: ");
|
||||
error!("Web vault is not found at '{}'. To install it, please follow the steps in: ", CONFIG.web_vault_folder());
|
||||
error!("https://github.com/dani-garcia/bitwarden_rs/wiki/Building-binary#install-the-web-vault");
|
||||
error!("You can also set the environment variable 'WEB_VAULT_ENABLED=false' to disable it");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Embed the migrations from the migrations folder into the application
|
||||
// This way, the program automatically migrates the database to the latest version
|
||||
// https://docs.rs/diesel_migrations/*/diesel_migrations/macro.embed_migrations.html
|
||||
#[allow(unused_imports)]
|
||||
mod migrations {
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
embed_migrations!("migrations/sqlite");
|
||||
#[cfg(feature = "mysql")]
|
||||
embed_migrations!("migrations/mysql");
|
||||
#[cfg(feature = "postgresql")]
|
||||
embed_migrations!("migrations/postgresql");
|
||||
|
||||
pub fn run_migrations() {
|
||||
// Make sure the database is up to date (create if it doesn't exist, or run the migrations)
|
||||
let connection = crate::db::get_connection().expect("Can't connect to DB");
|
||||
|
||||
use std::io::stdout;
|
||||
|
||||
// Disable Foreign Key Checks during migration
|
||||
use diesel::RunQueryDsl;
|
||||
|
||||
// FIXME: Per https://www.postgresql.org/docs/12/sql-set-constraints.html,
|
||||
// "SET CONSTRAINTS sets the behavior of constraint checking within the
|
||||
// current transaction", so this setting probably won't take effect for
|
||||
// any of the migrations since it's being run outside of a transaction.
|
||||
// Migrations that need to disable foreign key checks should run this
|
||||
// from within the migration script itself.
|
||||
#[cfg(feature = "postgres")]
|
||||
diesel::sql_query("SET CONSTRAINTS ALL DEFERRED").execute(&connection).expect("Failed to disable Foreign Key Checks during migrations");
|
||||
|
||||
// Scoped to a connection/session.
|
||||
#[cfg(feature = "mysql")]
|
||||
diesel::sql_query("SET FOREIGN_KEY_CHECKS = 0").execute(&connection).expect("Failed to disable Foreign Key Checks during migrations");
|
||||
|
||||
// Scoped to a connection.
|
||||
#[cfg(feature = "sqlite")]
|
||||
diesel::sql_query("PRAGMA foreign_keys = OFF").execute(&connection).expect("Failed to disable Foreign Key Checks during migrations");
|
||||
|
||||
embedded_migrations::run_with_output(&connection, &mut stdout()).expect("Can't run migrations");
|
||||
}
|
||||
}
|
||||
|
||||
fn launch_rocket(extra_debug: bool) {
|
||||
let pool = match db::DbPool::from_config() {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
error!("Error creating database pool: {:?}", e);
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let basepath = &CONFIG.domain_path();
|
||||
|
||||
// If adding more paths here, consider also adding them to
|
||||
@ -347,7 +287,7 @@ fn launch_rocket(extra_debug: bool) {
|
||||
.mount(&[basepath, "/identity"].concat(), api::identity_routes())
|
||||
.mount(&[basepath, "/icons"].concat(), api::icons_routes())
|
||||
.mount(&[basepath, "/notifications"].concat(), api::notifications_routes())
|
||||
.manage(db::init_pool())
|
||||
.manage(pool)
|
||||
.manage(api::start_notification_server())
|
||||
.attach(util::AppHeaders())
|
||||
.attach(util::CORS())
|
||||
|
Reference in New Issue
Block a user