use crate::{to_home, Authenticated, Error, State}; use actix_session::Session; use actix_web::{error::BlockingError, web, HttpResponse}; pub type DeleteUserPageArgs = (Authenticated, web::Data); pub type DeleteUserArgs = ( Authenticated, web::Data, Session, web::Form, ); #[derive(Debug, serde::Deserialize)] pub struct DeleteUserForm { password: String, } #[derive(Debug)] pub struct DeleteUserState { state: State, form: Option, error: Option, pub(crate) dark: bool, } pub fn delete_user_page((_, state): DeleteUserPageArgs) -> Result { Ok(DeleteUserState::empty(&state)) } pub async fn delete_user( (authenticated, state, session, form): DeleteUserArgs, ) -> Result, 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, dark: false, } } fn new_from_request(state: &State, form: DeleteUserForm, error: DeleteUserError) -> Self { DeleteUserState { state: state.clone(), form: form.into(), error: error.into(), dark: false, } } pub fn dark(&mut self, dark: bool) { self.dark = dark; } pub(crate) fn delete_user_path(&self) -> String { self.state.pages.delete_user_path() } pub(crate) fn accounts_path(&self) -> String { self.state.pages.accounts_path() } pub(crate) fn password(&self) -> Option { self.form.as_ref().map(|form| form.password.clone()) } pub(crate) fn password_error(&self) -> Option { self.error.as_ref().and_then(|e| e.password()) } } #[derive(Debug)] enum DeleteUserError { Invalid, } impl DeleteUserError { fn password(&self) -> Option { 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, 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))) }