feat(api): implemented anonymized account deletion reasons

This commit is contained in:
antifallobst 2023-08-20 15:32:31 +02:00
parent 3a9a9fb2ca
commit 2d7091f5d8
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
7 changed files with 71 additions and 5 deletions

View File

@ -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"
}

View File

@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO DeletionReasons VALUES ($1, $2);",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Timestamp"
]
},
"nullable": []
},
"hash": "229049e40b6afe47e05de851d8718c998706e7977a78d12762eab80ac8bb19f5"
}

View File

@ -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

View File

@ -61,8 +61,17 @@ async fn authenticate(
}
#[delete("/account/delete")]
async fn delete(data: web::Data<ApiState>, auth: BearerAuth, body: web::Json<data::DeleteRequest>) -> impl Responder {
match handlers::delete(&data.pool, auth.token().to_string()).await {
async fn delete(
data: web::Data<ApiState>,
auth: BearerAuth,
body: Option<web::Json<data::DeleteRequest>>,
) -> 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(),

View File

@ -56,7 +56,7 @@ pub enum AuthenticateResponse {
#[derive(Debug, Deserialize)]
pub struct DeleteRequest {
reaseon: String,
pub reason: Option<String>,
}
#[derive(Debug)]

View File

@ -142,7 +142,11 @@ pub async fn authenticate(
))
}
pub async fn delete(pool: &PgPool, auth: String) -> Result<data::DeleteResponse> {
pub async fn delete(
pool: &PgPool,
auth: String,
request: Option<data::DeleteRequest>,
) -> Result<data::DeleteResponse> {
if !auth.is_alpha() {
return Ok(data::DeleteResponse::Blocked);
}
@ -152,6 +156,22 @@ pub async fn delete(pool: &PgPool, auth: String) -> Result<data::DeleteResponse>
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 => {

View File

@ -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)