Browse Source

Merge e054287886 into cc80f689ed

pull/6349/merge
Lukas Pieper 3 days ago
committed by GitHub
parent
commit
cc67404ed7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      src/api/admin.rs
  2. 18
      src/db/mod.rs
  3. 8
      src/main.rs

2
src/api/admin.rs

@ -799,7 +799,7 @@ async fn delete_config(_token: AdminToken) -> EmptyResult {
#[post("/config/backup_db", format = "application/json")] #[post("/config/backup_db", format = "application/json")]
fn backup_db(_token: AdminToken) -> ApiResult<String> { fn backup_db(_token: AdminToken) -> ApiResult<String> {
if *CAN_BACKUP { if *CAN_BACKUP {
match backup_sqlite() { match backup_sqlite(None) {
Ok(f) => Ok(format!("Backup to '{f}' was successful")), Ok(f) => Ok(format!("Backup to '{f}' was successful")),
Err(e) => err!(format!("Backup was unsuccessful {e}")), Err(e) => err!(format!("Backup was unsuccessful {e}")),
} }

18
src/db/mod.rs

@ -385,7 +385,7 @@ pub mod models;
/// Creates a back-up of the sqlite database /// Creates a back-up of the sqlite database
/// MySQL/MariaDB and PostgreSQL are not supported. /// MySQL/MariaDB and PostgreSQL are not supported.
#[cfg(sqlite)] #[cfg(sqlite)]
pub fn backup_sqlite() -> Result<String, Error> { pub fn backup_sqlite(output_dir: Option<String>) -> Result<String, Error> {
use diesel::Connection; use diesel::Connection;
use std::{fs::File, io::Write}; use std::{fs::File, io::Write};
@ -395,8 +395,18 @@ pub fn backup_sqlite() -> Result<String, Error> {
// This way we can set a readonly flag on the opening mode without issues. // This way we can set a readonly flag on the opening mode without issues.
let mut conn = diesel::sqlite::SqliteConnection::establish(&format!("sqlite://{db_url}?mode=ro"))?; let mut conn = diesel::sqlite::SqliteConnection::establish(&format!("sqlite://{db_url}?mode=ro"))?;
let db_path = std::path::Path::new(&db_url).parent().unwrap(); let backup_dir = match &output_dir {
let backup_file = db_path Some(dir) => {
let output_path = std::path::Path::new(dir);
if !output_path.exists() || !output_path.is_dir() {
err!(format!("Backup directory does not exist or is not a directory: {}", dir));
}
output_path
}
None => std::path::Path::new(&db_url).parent().unwrap(),
};
let backup_file = backup_dir
.join(format!("db_{}.sqlite3", chrono::Utc::now().format("%Y%m%d_%H%M%S"))) .join(format!("db_{}.sqlite3", chrono::Utc::now().format("%Y%m%d_%H%M%S")))
.to_string_lossy() .to_string_lossy()
.into_owned(); .into_owned();
@ -417,7 +427,7 @@ pub fn backup_sqlite() -> Result<String, Error> {
} }
#[cfg(not(sqlite))] #[cfg(not(sqlite))]
pub fn backup_sqlite() -> Result<String, Error> { pub fn backup_sqlite(_output_dir: Option<String>) -> Result<String, Error> {
err_silent!("The database type is not SQLite. Backups only works for SQLite databases") err_silent!("The database type is not SQLite. Backups only works for SQLite databases")
} }

8
src/main.rs

@ -105,7 +105,7 @@ FLAGS:
COMMAND: COMMAND:
hash [--preset {bitwarden|owasp}] Generate an Argon2id PHC ADMIN_TOKEN hash [--preset {bitwarden|owasp}] Generate an Argon2id PHC ADMIN_TOKEN
backup Create a backup of the SQLite database backup [-o, --output <dir>] Create a backup of the SQLite database
You can also send the USR1 signal to trigger a backup You can also send the USR1 signal to trigger a backup
PRESETS: m= t= p= PRESETS: m= t= p=
@ -187,7 +187,9 @@ fn parse_args() {
exit(1); exit(1);
} }
} else if command == "backup" { } else if command == "backup" {
match db::backup_sqlite() { let output_dir: Option<String> = pargs.opt_value_from_str(["-o", "--output"]).unwrap_or_default();
match db::backup_sqlite(output_dir) {
Ok(f) => { Ok(f) => {
println!("Backup to '{f}' was successful"); println!("Backup to '{f}' was successful");
exit(0); exit(0);
@ -606,7 +608,7 @@ async fn launch_rocket(pool: db::DbPool, extra_debug: bool) -> Result<(), Error>
// If we need more signals to act upon, we might want to use select! here. // If we need more signals to act upon, we might want to use select! here.
// With only one item to listen for this is enough. // With only one item to listen for this is enough.
let _ = signal_user1.recv().await; let _ = signal_user1.recv().await;
match db::backup_sqlite() { match db::backup_sqlite(None) {
Ok(f) => info!("Backup to '{f}' was successful"), Ok(f) => info!("Backup to '{f}' was successful"),
Err(e) => error!("Backup failed. {e:?}"), Err(e) => error!("Backup failed. {e:?}"),
} }

Loading…
Cancel
Save