From 8dd5486250bdb961bf916649c373b92294b93685 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 1 Nov 2020 18:03:42 +0100 Subject: [PATCH] implementing multiple database systems support! --- Cargo.toml | 8 ++- config.toml.sample | 4 +- .../20200809180000_create_form/down.sql | 0 .../mysql/20200809180000_create_form/up.sql | 8 +++ .../20200809180000_create_form/down.sql | 1 + .../20200809180000_create_form/up.sql | 8 +++ .../20200809180000_create_form/down.sql | 1 + .../20200809180000_create_form/up.sql | 0 src/account.rs | 7 +- src/database/methods.rs | 11 ++- src/forward.rs | 69 +++++++++++-------- src/sniff.rs | 4 +- 12 files changed, 79 insertions(+), 42 deletions(-) rename migrations/{ => mysql}/20200809180000_create_form/down.sql (100%) create mode 100644 migrations/mysql/20200809180000_create_form/up.sql create mode 100644 migrations/postgres/20200809180000_create_form/down.sql create mode 100644 migrations/postgres/20200809180000_create_form/up.sql create mode 100644 migrations/sqlite/20200809180000_create_form/down.sql rename migrations/{ => sqlite}/20200809180000_create_form/up.sql (100%) diff --git a/Cargo.toml b/Cargo.toml index 9ed9ba4..d6e7a72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,17 @@ version = "1.0.0" authors = ["Association 42l "] edition = "2018" +[features] +default = [ "diesel/postgres" ] +postgres = [ "diesel/postgres" ] +mysql = [ "diesel/mysql" ] +sqlite = [ "diesel/sqlite" ] + [dependencies] actix-rt = "1.0.0" actix-web = "3.0.2" actix-files = "0.3.0" -diesel = { version = "1.4", features = ["sqlite", "r2d2", "chrono"] } +diesel = { version = "1.4", features = ["r2d2", "chrono"] } diesel_migrations = "1.4" url = "2.1" toml = "0.5" diff --git a/config.toml.sample b/config.toml.sample index 5546acd..8164eef 100644 --- a/config.toml.sample +++ b/config.toml.sample @@ -6,7 +6,9 @@ listening_port = 8000 # includes protocol, FQDN and port, without the trailing slash. sncf_url = "http://localhost:8000" -# path to the SQLite DB +# SQLite: path to the SQLite DB +# PostgreSQL: postgres://user:password@address:port/database +# MySQL: mysql://user:password@address:port/database database_path = "./db/sncf.sqlite" # IP address of the Nextcloud instance, including protocol and port diff --git a/migrations/20200809180000_create_form/down.sql b/migrations/mysql/20200809180000_create_form/down.sql similarity index 100% rename from migrations/20200809180000_create_form/down.sql rename to migrations/mysql/20200809180000_create_form/down.sql diff --git a/migrations/mysql/20200809180000_create_form/up.sql b/migrations/mysql/20200809180000_create_form/up.sql new file mode 100644 index 0000000..0e555ed --- /dev/null +++ b/migrations/mysql/20200809180000_create_form/up.sql @@ -0,0 +1,8 @@ +CREATE TABLE form ( + id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT UNIQUE, + created_at TIMESTAMP NOT NULL, + lastvisit_at TIMESTAMP NOT NULL, + token VARCHAR(128) NOT NULL UNIQUE, + nc_username VARCHAR(128) NOT NULL UNIQUE, + nc_password VARCHAR(128) NOT NULL +); diff --git a/migrations/postgres/20200809180000_create_form/down.sql b/migrations/postgres/20200809180000_create_form/down.sql new file mode 100644 index 0000000..5605fc4 --- /dev/null +++ b/migrations/postgres/20200809180000_create_form/down.sql @@ -0,0 +1 @@ +DELETE TABLE form; diff --git a/migrations/postgres/20200809180000_create_form/up.sql b/migrations/postgres/20200809180000_create_form/up.sql new file mode 100644 index 0000000..399d95d --- /dev/null +++ b/migrations/postgres/20200809180000_create_form/up.sql @@ -0,0 +1,8 @@ +CREATE TABLE form ( + id serial4 PRIMARY KEY UNIQUE NOT NULL, + created_at TIMESTAMP NOT NULL, + lastvisit_at TIMESTAMP NOT NULL, + token VARCHAR UNIQUE NOT NULL, + nc_username VARCHAR UNIQUE NOT NULL, + nc_password VARCHAR NOT NULL +); diff --git a/migrations/sqlite/20200809180000_create_form/down.sql b/migrations/sqlite/20200809180000_create_form/down.sql new file mode 100644 index 0000000..5605fc4 --- /dev/null +++ b/migrations/sqlite/20200809180000_create_form/down.sql @@ -0,0 +1 @@ +DELETE TABLE form; diff --git a/migrations/20200809180000_create_form/up.sql b/migrations/sqlite/20200809180000_create_form/up.sql similarity index 100% rename from migrations/20200809180000_create_form/up.sql rename to migrations/sqlite/20200809180000_create_form/up.sql diff --git a/src/account.rs b/src/account.rs index 4ad4b02..0241480 100644 --- a/src/account.rs +++ b/src/account.rs @@ -264,7 +264,12 @@ pub fn gen_name() -> String { // uppercasing gen_token because NC would probably refuse two // users with the same name but a different case // and that'd be a pain to debug - format!("{}{}-{}", list_rand(&ADJ_LIST), list_rand(&NAME_LIST), gen_token(4).to_uppercase()) + format!( + "{}{}-{}", + list_rand(&ADJ_LIST), + list_rand(&NAME_LIST), + gen_token(4).to_uppercase() + ) } pub fn list_rand(list: &[String]) -> &String { diff --git a/src/database/methods.rs b/src/database/methods.rs index 83338ae..3032735 100644 --- a/src/database/methods.rs +++ b/src/database/methods.rs @@ -5,7 +5,7 @@ use diesel::prelude::*; use crate::database::schema::form; use crate::database::schema::form::dsl::*; use crate::database::structs::Form; -use crate::SqliteConnection; +use crate::DbConn; #[table_name = "form"] #[derive(Serialize, Insertable)] @@ -22,7 +22,7 @@ impl Form { // also updates lastvisit_at. pub fn get_from_token( i_token: &str, - conn: &SqliteConnection, + conn: &DbConn, ) -> Result, diesel::result::Error> { if let Some(formdata) = form .filter(token.eq(i_token)) @@ -38,10 +38,7 @@ impl Form { } } - pub fn update_lastvisit( - &self, - conn: &SqliteConnection, - ) -> Result { + pub fn update_lastvisit(&self, conn: &DbConn) -> Result { diesel::update(form.find(self.id)) .set(lastvisit_at.eq(Utc::now().naive_utc())) .execute(conn) @@ -49,7 +46,7 @@ impl Form { pub fn insert<'b>( i_form: InsertableForm<'b>, - conn: &SqliteConnection, + conn: &DbConn, ) -> Result, diesel::result::Error> { match diesel::insert_into(form).values(&i_form).execute(conn) { Ok(_) => Ok(i_form), diff --git a/src/forward.rs b/src/forward.rs index 04a32e7..8a53a28 100644 --- a/src/forward.rs +++ b/src/forward.rs @@ -66,7 +66,7 @@ pub async fn forward( { client_resp.header(header_name.clone(), header_value.clone()); } - + // sparing the use of a mutable body when not needed // For now, the body only needs to be modified when the route // is "create a new form" route @@ -90,9 +90,14 @@ pub async fn forward( r#"{{"id":{},"keyValuePairs":{{"isAnonymous":true}}}}"#, form_id ); - let update_req = forge_from("/ocs/v2.php/apps/forms/api/v1/form/update", &req, &url, &client) - .set_header("content-length", forged_body.len()) - .set_header("content-type", "application/json;charset=utf-8"); + let update_req = forge_from( + "/ocs/v2.php/apps/forms/api/v1/form/update", + &req, + &url, + &client, + ) + .set_header("content-length", forged_body.len()) + .set_header("content-type", "application/json;charset=utf-8"); let res = update_req.send_body(forged_body).await.map_err(|e| { eprintln!("error_forward_isanon: {}", e); @@ -104,14 +109,14 @@ pub async fn forward( eprintln!("error_forward_clientresp_newform: {}", e); crash(get_lang(&req), "error_forward_clientresp_newform") })?) + } else { + Ok( + client_resp.body(res.body().limit(PAYLOAD_LIMIT).await.map_err(|e| { + eprintln!("error_forward_clientresp_newform: {}", e); + crash(get_lang(&req), "error_forward_clientresp_std") + })?), + ) } - else { - Ok(client_resp.body(res.body().limit(PAYLOAD_LIMIT).await.map_err(|e| { - eprintln!("error_forward_clientresp_newform: {}", e); - crash(get_lang(&req), "error_forward_clientresp_std") - })?)) - } - // check the response before returning it (unused) /*if check_response(route, &response_body) { @@ -202,14 +207,14 @@ pub async fn forward_register( .as_str(); // sanitize the token beforehand, cookies are unsafe if check_token(&admin_token) { - return Ok(web_redir( - &format!( - "{}/admin/{}", - CONFIG.sncf_url, &admin_token) - ).await.map_err(|e| { - eprintln!("error_redirect (admin): {}", e); - crash(get_lang(&req), "error_redirect") - })?); + return Ok( + web_redir(&format!("{}/admin/{}", CONFIG.sncf_url, &admin_token)) + .await + .map_err(|e| { + eprintln!("error_redirect (admin): {}", e); + crash(get_lang(&req), "error_redirect") + })?, + ); } else { debug("Incorrect admin token given in cookies."); debug(&format!("Token: {:#?}", &admin_token)); @@ -265,7 +270,9 @@ pub async fn forward_register( eprintln!("error_tplrender (TplLink): {}", e); crash(lang.clone(), "error_tplrender") })?, - ).await.map_err(|e| { + ) + .await + .map_err(|e| { eprintln!("error_tplrender_resp (TplLink): {}", e); crash(lang, "error_tplrender_resp") })?) @@ -304,16 +311,20 @@ fn web_redir(location: &str) -> HttpResponse { } pub async fn index(req: HttpRequest) -> Result { - Ok(HttpResponse::Ok().content_type("text/html").body( - TplIndex { - lang: &get_lang(&req), - } - .render() + Ok(HttpResponse::Ok() + .content_type("text/html") + .body( + TplIndex { + lang: &get_lang(&req), + } + .render() + .map_err(|e| { + eprintln!("error_tplrender (TplIndex): {}", e); + crash(get_lang(&req), "error_tplrender") + })?, + ) + .await .map_err(|e| { - eprintln!("error_tplrender (TplIndex): {}", e); - crash(get_lang(&req), "error_tplrender") - })?, - ).await.map_err(|e| { eprintln!("error_tplrender_resp (TplIndex): {}", e); crash(get_lang(&req), "error_tplrender_resp") })?) diff --git a/src/sniff.rs b/src/sniff.rs index 0aef0dc..01e6854 100644 --- a/src/sniff.rs +++ b/src/sniff.rs @@ -72,9 +72,7 @@ const BLOCKED_ROUTES: &[&str] = &[ ]; // ...except if they are in this list -const ALLOWED_ROUTES: &[&str] = &[ - "/ocs/v2.php/apps/forms/", -]; +const ALLOWED_ROUTES: &[&str] = &["/ocs/v2.php/apps/forms/"]; // checks if the accessed route is allowed for the user. // if it returns true, redirects elsewhere