From e58973d366a14a22b55c522b11b7dee0560e15fa Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Sun, 8 Jun 2025 21:54:03 +0200 Subject: [PATCH] frontend: Add form to create addressbook --- .../frontend/public/templates/pages/user.html | 110 +++++++++++------- crates/frontend/src/lib.rs | 6 +- crates/frontend/src/routes/addressbook.rs | 50 +++++++- crates/frontend/src/routes/calendar.rs | 4 +- 4 files changed, 124 insertions(+), 46 deletions(-) diff --git a/crates/frontend/public/templates/pages/user.html b/crates/frontend/public/templates/pages/user.html index c8ff8a2..c1e8765 100644 --- a/crates/frontend/public/templates/pages/user.html +++ b/crates/frontend/public/templates/pages/user.html @@ -108,48 +108,51 @@ {% endif %} -

Create calendar

-
- -
- -
- -
- -
- -
- - - -
- -
+
+

Create calendar

+
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +
+
+
@@ -186,6 +189,29 @@ {% endfor %} {% endif %} + +
+

Create addressbook

+
+ +
+ +
+ +
+ +
+
+
{% endblock %} diff --git a/crates/frontend/src/lib.rs b/crates/frontend/src/lib.rs index 4378b89..b739d9c 100644 --- a/crates/frontend/src/lib.rs +++ b/crates/frontend/src/lib.rs @@ -32,7 +32,7 @@ use oidc_user_store::OidcUserStore; use crate::{ assets::{Assets, EmbedService}, routes::{ - addressbook::{route_addressbook, route_addressbook_restore}, + addressbook::{route_addressbook, route_addressbook_restore, route_create_addressbook}, app_token::{route_delete_app_token, route_post_app_token}, calendar::{route_calendar, route_calendar_restore, route_create_calendar}, login::{route_get_login, route_post_login, route_post_logout}, @@ -76,6 +76,10 @@ pub fn frontend_router< post(route_calendar_restore::), ) // Addressbook + .route( + "/user/{user}/addressbook", + post(route_create_addressbook::), + ) .route( "/user/{user}/addressbook/{addressbook}", get(route_addressbook::), diff --git a/crates/frontend/src/routes/addressbook.rs b/crates/frontend/src/routes/addressbook.rs index 91f6809..d4eada0 100644 --- a/crates/frontend/src/routes/addressbook.rs +++ b/crates/frontend/src/routes/addressbook.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use askama::Template; use askama_web::WebTemplate; use axum::{ - Extension, + Extension, Form, extract::Path, response::{IntoResponse, Redirect, Response}, }; @@ -11,6 +11,7 @@ use axum_extra::TypedHeader; use headers::Referer; use http::StatusCode; use rustical_store::{Addressbook, AddressbookStore, auth::User}; +use serde::{Deserialize, Deserializer}; #[derive(Template, WebTemplate)] #[template(path = "pages/addressbook.html")] @@ -32,6 +33,53 @@ pub async fn route_addressbook( .into_response()) } +fn empty_to_none<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let val: Option = Deserialize::deserialize(deserializer)?; + Ok(val.filter(|val| !val.is_empty())) +} + +#[derive(Deserialize, Clone)] +pub struct PutAddressbookForm { + id: String, + #[serde(deserialize_with = "empty_to_none")] + displayname: Option, + #[serde(deserialize_with = "empty_to_none")] + description: Option, +} + +pub async fn route_create_addressbook( + Path(owner): Path, + Extension(store): Extension>, + user: User, + Form(PutAddressbookForm { + id, + displayname, + description, + }): Form, +) -> Result { + if !user.is_principal(&owner) { + return Ok(StatusCode::UNAUTHORIZED.into_response()); + } + + assert!(!id.is_empty()); + + let addressbook = Addressbook { + id: id.to_owned(), + displayname, + description, + principal: user.id.to_owned(), + synctoken: 0, + deleted_at: None, + push_topic: uuid::Uuid::new_v4().to_string(), + }; + + store.insert_addressbook(addressbook).await?; + Ok(Redirect::to(&format!("/frontend/user/{}/addressbook/{}", user.id, id)).into_response()) +} + pub async fn route_addressbook_restore( Path((owner, addressbook_id)): Path<(String, String)>, Extension(store): Extension>, diff --git a/crates/frontend/src/routes/calendar.rs b/crates/frontend/src/routes/calendar.rs index db596e7..fe69f21 100644 --- a/crates/frontend/src/routes/calendar.rs +++ b/crates/frontend/src/routes/calendar.rs @@ -96,7 +96,7 @@ pub async fn route_create_calendar( description, color, subscription_url, - principal: user.id, + principal: user.id.to_owned(), components: comps, order: 0, timezone_id: None, @@ -107,7 +107,7 @@ pub async fn route_create_calendar( }; store.insert_calendar(cal).await?; - Ok(Redirect::to(&id).into_response()) + Ok(Redirect::to(&format!("/frontend/user/{}/calendar/{}", user.id, id)).into_response()) } pub async fn route_calendar_restore(