Skip to main content

tuwunel_api/client/account/3pid/
add_3pid.rs

1use axum::extract::State;
2use ruma::{
3	MilliSecondsSinceUnixEpoch,
4	api::client::account::add_3pid::{self, v3::Response},
5};
6use tuwunel_core::{Err, Result};
7
8use crate::{ClientIp, Ruma, router::auth_uiaa};
9
10/// # `POST /_matrix/client/v3/account/3pid/add`
11///
12/// Bind a verified email address to this account.
13///
14/// - Requires UIAA to confirm account ownership
15/// - Consumes a previously validated email verification session
16#[tracing::instrument(skip_all, fields(%client), name = "add_3pid")]
17pub(crate) async fn add_3pid_route(
18	State(services): State<crate::State>,
19	ClientIp(client): ClientIp,
20	body: Ruma<add_3pid::v3::Request>,
21) -> Result<Response> {
22	if !services.sendmail.is_enabled() {
23		return Err!(Request(ThreepidDenied("Email verification is not configured")));
24	}
25
26	let ref sender_user = auth_uiaa(&services, &body).await?;
27
28	let association = services
29		.threepid
30		.consume_validated(body.sid.as_str(), body.client_secret.as_str())
31		.await?;
32
33	if services
34		.threepid
35		.user_id_for_email(&association.address)
36		.await?
37		.is_some_and(|bound| bound != *sender_user)
38	{
39		return Err!(Request(ThreepidInUse("That email address is already in use")));
40	}
41
42	let now = MilliSecondsSinceUnixEpoch::now();
43
44	services
45		.threepid
46		.put_binding(sender_user, &association.address, association.medium, now, now)
47		.await;
48
49	Ok(Response::new())
50}