From eff89e71000c6438cc9355c3d113526a22591a58 Mon Sep 17 00:00:00 2001 From: "D. Scott Boggs" Date: Tue, 13 Jun 2023 10:19:14 -0400 Subject: [PATCH] Add unsafe_import route --- .gitignore | 1 + server/Cargo.toml | 4 ++++ server/src/api/import.rs | 27 +++++++++++++++++++++++++++ server/src/api/mod.rs | 13 ++++++++++--- 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 server/src/api/import.rs diff --git a/.gitignore b/.gitignore index 0def1c0..b1b2d52 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ python-venv/ tickmate-backup-20230524.db server/public/ db.mount/ +tickmate-dump.sql diff --git a/server/Cargo.toml b/server/Cargo.toml index 7068bbe..329ce44 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -3,6 +3,10 @@ name = "kalkulog-server" version = "0.1.0" edition = "2021" +[features] +default = ["unsafe_import"] +unsafe_import = [] + [[bin]] name = "kalkulog-server" path = "src/main.rs" diff --git a/server/src/api/import.rs b/server/src/api/import.rs new file mode 100644 index 0000000..f6dc8db --- /dev/null +++ b/server/src/api/import.rs @@ -0,0 +1,27 @@ +use rocket::{http::Status, State}; +use sea_orm::{ConnectionTrait, DatabaseBackend, DatabaseConnection, Statement}; + +use crate::error::Error; + +use super::error::ApiResult; + +/// This is behind a feature gate for a reason: it's wildly unsafe and +/// insecure. It absolutely enables arbitrary sql injection. +#[cfg(feature = "unsafe_import")] +#[post("/import", data = "")] +pub(crate) async fn import_sql( + db: &State, + sql_dump: &str, +) -> ApiResult { + for line in sql_dump.lines() { + let line = line.to_ascii_lowercase(); + if line.starts_with("insert into") + && !(line.contains("sqlite_sequence") || line.contains("android_metadata")) + { + db.execute(Statement::from_string(DatabaseBackend::Postgres, line)) + .await + .map_err(Error::from)?; + } + } + Ok(Status::Ok) +} diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs index af68032..8a8930a 100644 --- a/server/src/api/mod.rs +++ b/server/src/api/mod.rs @@ -1,5 +1,6 @@ mod error; mod groups; +mod import; mod ticks; mod tracks; @@ -7,9 +8,10 @@ use std::default::default; use std::net::{IpAddr, Ipv4Addr}; use rocket::fs::{FileServer, NamedFile}; -use rocket::Config; +use rocket::{routes, Config}; use sea_orm::DatabaseConnection; +use crate::api::import::import_sql; use crate::error::Error; use crate::rocket::{Build, Rocket}; @@ -33,7 +35,7 @@ pub(crate) fn start_server(db: DatabaseConnection) -> Rocket { use groups::*; use ticks::*; use tracks::*; - rocket::build() + let it = rocket::build() .configure(Config { address: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), ..default() @@ -53,5 +55,10 @@ pub(crate) fn start_server(db: DatabaseConnection) -> Rocket { "/api/v1/groups", routes![all_groups, group, insert_group, update_group, delete_group], ) - .mount("/", FileServer::from("/src/public")) + .mount("/", FileServer::from("/src/public")); + + #[cfg(feature = "unsafe_import")] + let it = it.mount("/api/v1", routes![import_sql]); + + it }