diff --git a/src/main.rs b/src/main.rs index ddf9784..6a1d092 100644 --- a/src/main.rs +++ b/src/main.rs @@ -502,8 +502,9 @@ struct HomeQuery { user_error: Option, } -struct AliasPart { - mail: String, +#[derive(Deserialize, Debug)] +struct AliasRecipient { + alias: String, recipient: String, } @@ -545,9 +546,9 @@ async fn home( .await?; let mut alias_stream = sqlx::query_as!( - AliasPart, + AliasRecipient, r#" - SELECT alias_recipient.mail,recipient + SELECT alias_recipient.mail as alias,recipient FROM emails,alias_recipient WHERE id = $1 AND alias = true AND emails.mail = alias_recipient.mail "#, @@ -557,7 +558,7 @@ async fn home( let mut aliases: HashMap<_, _> = aliases.into_iter().map(|a| (a.mail, Vec::new())).collect(); while let Some(alias) = alias_stream.try_next().await? { - aliases.get_mut(&alias.mail).unwrap().push(alias.recipient); + aliases.get_mut(&alias.alias).unwrap().push(alias.recipient); } let aliases: Vec<_> = aliases @@ -685,17 +686,11 @@ async fn add_mail( } } -#[derive(Deserialize, Debug)] -struct AddRecipient { - alias: String, - recipient: String, -} - #[tracing::instrument(skip(state))] async fn add_recipient( state: State>, User(user): User, - Form(add): Form, + Form(add): Form, ) -> Result { let can_use_alias = sqlx::query!( "SELECT COUNT(*) FROM emails WHERE id = $1 AND mail = $2", @@ -724,6 +719,45 @@ async fn add_recipient( Ok(Redirect::to("/")) } +#[tracing::instrument(skip(state))] +async fn delete_recipient( + state: State>, + User(user): User, + Form(delete): Form, +) -> Result { + let can_use_alias = sqlx::query!( + "SELECT COUNT(*) FROM emails WHERE id = $1 AND mail = $2", + user, + delete.alias + ) + .fetch_one(&state.db) + .await? + .count + .expect("count should not be null") + > 0; + + if !can_use_alias { + tracing::error!("User is not authorized to use this alias"); + return Err(Error::InternalError); + } + + let rows_affected = sqlx::query!( + "DELETE FROM alias_recipient WHERE mail = $1 AND recipient = $2", + delete.alias, + delete.recipient, + ) + .execute(&state.db) + .await? + .rows_affected(); + + if rows_affected != 1 { + tracing::warn!("Invalid number of rows affected in delete: {rows_affected}"); + return Err(Error::InternalError); + } + + Ok(Redirect::to("/")) +} + #[tokio::main] async fn main() -> color_eyre::Result<()> { color_eyre::install()?; @@ -757,6 +791,7 @@ async fn main() -> color_eyre::Result<()> { .route("/mail/delete", post(delete_mail)) .route("/mail/add", post(add_mail)) .route("/alias/recipient/add", post(add_recipient)) + .route("/alias/recipient/delete", post(delete_recipient)) .route("/alias/delete", post(delete_alias)) .fallback(page_not_found) .with_state(Arc::new(AppState { diff --git a/templates/home.html b/templates/home.html index 25ec35f..0aa6ad1 100644 --- a/templates/home.html +++ b/templates/home.html @@ -132,7 +132,16 @@
    {% set alias_idx = loop.index %} - {% for recpt in alias.recipients %}
  • {{ recpt }}
  • {% endfor %} + {% for recpt in alias.recipients %} +
  • + {{ recpt }} + {{ self::delete_modal(modal_id="aliasRctDelete" ~ alias_idx ~ loop.index, + confirm_text="Delete recipient '" ~ recpt ~ "' for '" ~ alias.mail ~ "'", + action="/alias/recipient/delete", + payload=["alias", alias.mail, "recipient", recpt]) + }} +
  • + {% endfor %}
{{ self::add_modal(modal_id="addRecipient", add_button="Add Recipient",