hyaenidae/accounts/src/forms/delete_user.rs

116 lines
2.8 KiB
Rust

use crate::{to_home, Authenticated, Error, State};
use actix_session::Session;
use actix_web::{error::BlockingError, web, HttpResponse};
pub type DeleteUserPageArgs = (Authenticated, web::Data<State>);
pub type DeleteUserArgs = (
Authenticated,
web::Data<State>,
Session,
web::Form<DeleteUserForm>,
);
#[derive(Debug, serde::Deserialize)]
pub struct DeleteUserForm {
password: String,
}
#[derive(Debug)]
pub struct DeleteUserState {
state: State,
form: Option<DeleteUserForm>,
error: Option<DeleteUserError>,
}
pub fn delete_user_page((_, state): DeleteUserPageArgs) -> Result<DeleteUserState, HttpResponse> {
Ok(DeleteUserState::empty(&state))
}
pub async fn delete_user(
(authenticated, state, session, form): DeleteUserArgs,
) -> Result<Result<DeleteUserState, HttpResponse>, Error> {
let form = form.into_inner();
match try_delete_user(session, authenticated, &form, &state).await? {
Ok(res) => Ok(Err(res)),
Err(e) => Ok(Ok(DeleteUserState::new_from_request(&state, form, e))),
}
}
impl DeleteUserState {
fn empty(state: &State) -> Self {
DeleteUserState {
state: state.clone(),
form: None,
error: None,
}
}
fn new_from_request(state: &State, form: DeleteUserForm, error: DeleteUserError) -> Self {
DeleteUserState {
state: state.clone(),
form: form.into(),
error: error.into(),
}
}
pub fn delete_user_path(&self) -> String {
self.state.pages.delete_user_path()
}
pub fn accounts_path(&self) -> String {
self.state.pages.accounts_path()
}
pub fn password(&self) -> Option<String> {
self.form.as_ref().map(|form| form.password.clone())
}
pub fn password_error(&self) -> Option<String> {
self.error.as_ref().and_then(|e| e.password())
}
}
#[derive(Debug)]
enum DeleteUserError {
Invalid,
}
impl DeleteUserError {
fn password(&self) -> Option<String> {
use DeleteUserError::*;
match self {
Invalid => Some("Supplied password is invalid".to_owned()),
}
}
}
async fn try_delete_user(
session: Session,
authenticated: Authenticated,
form: &DeleteUserForm,
state: &State,
) -> Result<Result<HttpResponse, DeleteUserError>, Error> {
let res = state
.user_store
.exec(crate::store::DeleteUser {
user: authenticated.user(),
password: form.password.clone(),
})
.await;
match res {
Ok(_) => (),
Err(BlockingError::Error(crate::store::StoreError::AuthenticationFailed)) => {
return Ok(Err(DeleteUserError::Invalid));
}
Err(e) => return Err(e.into()),
};
crate::extractors::UserData::remove(&session);
Ok(Ok(to_home(&state)))
}