/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin */ use super::{format_form_error, hash_password}; use crate::{ database::Database, routes::ui::{ account::session::Session, error::MyResult, layout::{DynLayoutPage, LayoutPage}, }, uri, }; use rocket::{ form::{self, validate::len, Contextual, Form}, get, post, FromForm, State, }; use std::ops::Range; #[derive(FromForm)] pub struct SettingsForm { #[field(validate = option_len(4..64))] password: Option, #[field(validate = option_len(4..32))] display_name: Option, } fn option_len<'v>(value: &Option, range: Range) -> form::Result<'v, ()> { value.as_ref().map(|v| len(v, range)).unwrap_or(Ok(())) } fn settings_page(session: Session, flash: Option>) -> DynLayoutPage<'static> { LayoutPage { title: "Settings".to_string(), content: markup::new! { h1 { "Settings" } @if let Some(flash) = &flash { @match flash { Ok(mesg) => { section.message { p.success { @mesg } } } Err(err) => { section.message { p.error { @format!("{err}") } } } } } h2 { "Account" } form[method="POST", action=uri!(r_account_settings_post())] { label[for="username"] { "Username" } input[type="text", id="username", disabled, value=&session.user.name]; input[type="submit", disabled, value="Immutable"]; } form[method="POST", action=uri!(r_account_settings_post())] { label[for="display_name"] { "Display Name" } input[type="text", id="display_name", name="display_name", value=&session.user.display_name]; input[type="submit", value="Update"]; } form[method="POST", action=uri!(r_account_settings_post())] { label[for="password"] { "Password" } input[type="password", id="password", name="password"]; input[type="submit", value="Update"]; } h2 { "Appearance" } p.error { "TODO: theming" } }, ..Default::default() } } #[get("/account/settings")] pub fn r_account_settings(session: Session) -> DynLayoutPage<'static> { settings_page(session, None) } #[post("/account/settings", data = "
")] pub fn r_account_settings_post( session: Session, database: &State, form: Form>, ) -> MyResult> { let form = match &form.value { Some(v) => v, None => return Ok(settings_page(session, Some(Err(format_form_error(form))))), }; let mut out = String::new(); database.user.fetch_and_update(&session.user.name, |k| { k.map(|mut k| { if let Some(password) = &form.password { k.password = hash_password(&session.user.name, password); out += "Password updated\n"; } if let Some(display_name) = &form.display_name { k.display_name = display_name.clone(); out += "Display name updated\n"; } k }) })?; Ok(settings_page( session, Some(Ok(if out.is_empty() { "Nothing changed :)".to_string() } else { out })), )) }