webringer 1.0.3

A bin/lib crate for a webring site
Documentation
use askama::Template;
use axum::{
	Form,
	http::StatusCode,
	response::{Html, IntoResponse, Redirect},
};
use axum_messages::{Message, Messages};
use serde::Deserialize;
use tracing::{debug, error, info};

use crate::ring::{RingError, auth::AuthSession};

#[derive(Template)]
#[template(path = "admin/account/change-password.html")]
pub struct ChangePasswordTemplate {
	messages: Vec<Message>,
}

pub(super) async fn get(messages: Messages) -> impl IntoResponse {
	match {
		ChangePasswordTemplate {
			messages: messages.into_iter().collect(),
		}
	}
	.render()
	{
		Ok(s) => {
			debug!("Successfully rendered change password html");
			Html(s).into_response()
		}
		Err(e) => {
			error!("Error when rendering change password html: {e}");
			StatusCode::INTERNAL_SERVER_ERROR.into_response()
		}
	}
}

#[derive(Clone, Deserialize)]
pub struct ChangePasswordForm {
	pub current: String,
	pub new: String,
	pub confirm_new: String,
}

pub(super) async fn post(
	mut auth_session: AuthSession,
	messages: Messages,
	Form(input): Form<ChangePasswordForm>,
) -> impl IntoResponse {
	let Some(ref admin) = auth_session.user else {
		error!("Tried to alter an admin account when not logged in");
		return StatusCode::UNAUTHORIZED.into_response();
	};
	if input.new != input.confirm_new {
		messages.error("New password and Confirmed new password do not match");
		return Redirect::to("./change-password").into_response();
	}
	match auth_session
		.backend
		.change_password(admin, input.current, input.new)
		.await
	{
		Ok(()) => {
			info!("Successfully changed admin password");
			// TODO: Make this an actual page
			Html(
				"Your password has successfully been changed. Please <a href=\"/login\">login</a> again.",
			)
			.into_response()
		}
		Err(RingError::UnauthorisedAdmin) => {
			messages.error("Current password not valid.");
			Redirect::to("./change-password").into_response()
		}
		Err(e) => {
			error!("Error when trying to change the users password: {e}");
			StatusCode::INTERNAL_SERVER_ERROR.into_response()
		}
	}
}