mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
130 lines
2.8 KiB
Rust
130 lines
2.8 KiB
Rust
use axum::{Extension, Router, extract::State, routing::on};
|
|
use conduwuit_api::client::full_user_deactivate;
|
|
use futures::StreamExt;
|
|
use ruma::{OwnedRoomId, OwnedUserId, UserId};
|
|
use tower_sessions::Session;
|
|
use validator::{Validate, ValidationError, ValidationErrors};
|
|
|
|
use crate::{
|
|
extract::PostForm,
|
|
form,
|
|
pages::{
|
|
GET_POST, Result, TemplateContext,
|
|
components::{UserCard, form::Form},
|
|
},
|
|
response,
|
|
session::{LoginTarget, User},
|
|
template,
|
|
};
|
|
|
|
pub(crate) fn build() -> Router<crate::State> {
|
|
Router::new().route("/", on(GET_POST, route_deactivate))
|
|
}
|
|
|
|
template! {
|
|
struct Deactivate use "deactivate.html.j2" {
|
|
body: DeactivateBody
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[allow(clippy::large_enum_variant)]
|
|
enum DeactivateBody {
|
|
Unavailable,
|
|
Form {
|
|
user_id: OwnedUserId,
|
|
user_card: UserCard,
|
|
form: Form<'static>,
|
|
},
|
|
Success,
|
|
}
|
|
|
|
form! {
|
|
struct DeactivateForm {
|
|
password: String where {
|
|
input_type: "password",
|
|
label: "Enter your password to confirm",
|
|
autocomplete: "current-password"
|
|
},
|
|
#[validate(required(message = "This checkbox must be checked"))]
|
|
confirm: Option<String> where {
|
|
input_type: "checkbox",
|
|
label: "I understand that deactivating my account cannot be undone."
|
|
}
|
|
|
|
submit: "Deactivate my account",
|
|
slowdown: true
|
|
}
|
|
}
|
|
|
|
async fn route_deactivate(
|
|
State(services): State<crate::State>,
|
|
Extension(context): Extension<TemplateContext>,
|
|
user: User,
|
|
session: Session,
|
|
PostForm(form): PostForm<DeactivateForm>,
|
|
) -> Result {
|
|
let user_id = user.expect_recent(LoginTarget::Deactivate)?;
|
|
let user_card = UserCard::for_local_user(&services, user_id.clone()).await;
|
|
|
|
let body = {
|
|
if !services.config.allow_deactivation {
|
|
DeactivateBody::Unavailable
|
|
} else if let Some(form) = form {
|
|
if let Err(err) = validate_deactivate_form(&services, &user_id, form).await {
|
|
DeactivateBody::Form {
|
|
user_id,
|
|
user_card,
|
|
form: DeactivateForm::with_errors(context.clone(), err),
|
|
}
|
|
} else {
|
|
let all_joined_rooms: Vec<OwnedRoomId> = services
|
|
.rooms
|
|
.state_cache
|
|
.rooms_joined(&user_id)
|
|
.collect()
|
|
.await;
|
|
|
|
full_user_deactivate(&services, &user_id, &all_joined_rooms).await?;
|
|
|
|
session.clear().await;
|
|
|
|
DeactivateBody::Success
|
|
}
|
|
} else {
|
|
DeactivateBody::Form {
|
|
user_id,
|
|
user_card,
|
|
form: DeactivateForm::build(context.clone()),
|
|
}
|
|
}
|
|
};
|
|
|
|
response!(Deactivate::new(context, body))
|
|
}
|
|
|
|
async fn validate_deactivate_form(
|
|
services: &crate::State,
|
|
user_id: &UserId,
|
|
form: DeactivateForm,
|
|
) -> Result<(), ValidationErrors> {
|
|
form.validate()?;
|
|
|
|
if services
|
|
.users
|
|
.check_password(user_id, &form.password)
|
|
.await
|
|
.is_err()
|
|
{
|
|
let mut errors = ValidationErrors::new();
|
|
errors.add(
|
|
"password",
|
|
ValidationError::new("wrong").with_message("Incorrect password".into()),
|
|
);
|
|
|
|
return Err(errors);
|
|
}
|
|
|
|
Ok(())
|
|
}
|