diff --git a/.sqlx/query-020c77db38a9e781283b6fc0268df744bd58e964b8203acefd0eb05210b317ba.json b/.sqlx/query-020c77db38a9e781283b6fc0268df744bd58e964b8203acefd0eb05210b317ba.json new file mode 100644 index 0000000..544b304 --- /dev/null +++ b/.sqlx/query-020c77db38a9e781283b6fc0268df744bd58e964b8203acefd0eb05210b317ba.json @@ -0,0 +1,12 @@ +{ + "db_name": "PostgreSQL", + "query": "\n CREATE TABLE IF NOT EXISTS DeletionReasons (\n reason TEXT NOT NULL,\n time TIMESTAMP NOT NULL\n );\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [] + }, + "nullable": [] + }, + "hash": "020c77db38a9e781283b6fc0268df744bd58e964b8203acefd0eb05210b317ba" +} diff --git a/.sqlx/query-229049e40b6afe47e05de851d8718c998706e7977a78d12762eab80ac8bb19f5.json b/.sqlx/query-229049e40b6afe47e05de851d8718c998706e7977a78d12762eab80ac8bb19f5.json new file mode 100644 index 0000000..a8661a3 --- /dev/null +++ b/.sqlx/query-229049e40b6afe47e05de851d8718c998706e7977a78d12762eab80ac8bb19f5.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO DeletionReasons VALUES ($1, $2);", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Timestamp" + ] + }, + "nullable": [] + }, + "hash": "229049e40b6afe47e05de851d8718c998706e7977a78d12762eab80ac8bb19f5" +} diff --git a/docs/README.md b/docs/README.md index 5fe77e7..9d4d76a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -29,5 +29,4 @@ The token for this can be aquired using the `/account/authenticate` endpoint. ## TODO - Password checking on registration - usage examples -- anonymized account deletion reason - account bound rate limit \ No newline at end of file diff --git a/src/api/account/calls.rs b/src/api/account/calls.rs index df7f3ba..0359fa1 100644 --- a/src/api/account/calls.rs +++ b/src/api/account/calls.rs @@ -61,8 +61,17 @@ async fn authenticate( } #[delete("/account/delete")] -async fn delete(data: web::Data, auth: BearerAuth, body: web::Json) -> impl Responder { - match handlers::delete(&data.pool, auth.token().to_string()).await { +async fn delete( + data: web::Data, + auth: BearerAuth, + body: Option>, +) -> impl Responder { + let req = match body { + Some(b) => Some(b.into_inner()), + None => None, + }; + + match handlers::delete(&data.pool, auth.token().to_string(), req).await { Ok(resp) => match resp { data::DeleteResponse::Success => HttpResponse::Ok().finish(), data::DeleteResponse::Unauthorized => HttpResponse::Unauthorized().finish(), diff --git a/src/api/account/data.rs b/src/api/account/data.rs index f580f10..353b2bc 100644 --- a/src/api/account/data.rs +++ b/src/api/account/data.rs @@ -56,7 +56,7 @@ pub enum AuthenticateResponse { #[derive(Debug, Deserialize)] pub struct DeleteRequest { - reaseon: String, + pub reason: Option, } #[derive(Debug)] diff --git a/src/api/account/handlers.rs b/src/api/account/handlers.rs index f8f040b..475d80b 100644 --- a/src/api/account/handlers.rs +++ b/src/api/account/handlers.rs @@ -142,7 +142,11 @@ pub async fn authenticate( )) } -pub async fn delete(pool: &PgPool, auth: String) -> Result { +pub async fn delete( + pool: &PgPool, + auth: String, + request: Option, +) -> Result { if !auth.is_alpha() { return Ok(data::DeleteResponse::Blocked); } @@ -152,6 +156,22 @@ pub async fn delete(pool: &PgPool, auth: String) -> Result None => return Ok(data::DeleteResponse::Unauthorized), }; + if let Some(req) = request { + if let Some(reason) = req.reason { + if is_sql_injection(&reason) { + return Ok(data::DeleteResponse::Blocked); + } + + sqlx::query!( + r#"INSERT INTO DeletionReasons VALUES ($1, $2);"#, + reason, + chrono::Utc::now().naive_utc() + ) + .execute(pool) + .await?; + } + } + match Account::from_id(pool, token.account).await? { Some(a) => a.delete(pool).await?, None => { diff --git a/src/api/mod.rs b/src/api/mod.rs index 916f1d2..1b4880a 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -71,6 +71,17 @@ pub async fn start(port: u16, pool: PgPool) -> Result<()> { .execute(&pool) .await?; + sqlx::query!( + r#" + CREATE TABLE IF NOT EXISTS DeletionReasons ( + reason TEXT NOT NULL, + time TIMESTAMP NOT NULL + ); + "# + ) + .execute(&pool) + .await?; + let _ = HttpServer::new(move || { App::new() .service(account::calls::register)