1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-20 12:02:22 +03:00

Ability to set the primary email and cleanup the email lists

This commit is contained in:
Quentin Gliech
2023-04-28 18:49:08 +02:00
parent 741873b84e
commit 63d4bfd0d4
11 changed files with 451 additions and 61 deletions

View File

@@ -16,7 +16,7 @@ use anyhow::Context as _;
use async_graphql::{Context, Description, Enum, InputObject, Object, ID};
use mas_storage::{
job::{JobRepositoryExt, ProvisionUserJob, VerifyEmailJob},
user::UserRepository,
user::{UserEmailRepository, UserRepository},
RepositoryAccess,
};
@@ -304,6 +304,51 @@ impl RemoveEmailPayload {
}
}
/// The input for the `setPrimaryEmail` mutation
#[derive(InputObject)]
struct SetPrimaryEmailInput {
/// The ID of the email address to set as primary
user_email_id: ID,
}
/// The status of the `setPrimaryEmail` mutation
#[derive(Enum, Copy, Clone, Eq, PartialEq)]
enum SetPrimaryEmailStatus {
/// The email address was set as primary
Set,
/// The email address was not found
NotFound,
/// Can't make an unverified email address primary
Unverified,
}
/// The payload of the `setPrimaryEmail` mutation
#[derive(Description)]
enum SetPrimaryEmailPayload {
Set(mas_data_model::User),
NotFound,
Unverified,
}
#[Object(use_type_description)]
impl SetPrimaryEmailPayload {
async fn status(&self) -> SetPrimaryEmailStatus {
match self {
SetPrimaryEmailPayload::Set(_) => SetPrimaryEmailStatus::Set,
SetPrimaryEmailPayload::NotFound => SetPrimaryEmailStatus::NotFound,
SetPrimaryEmailPayload::Unverified => SetPrimaryEmailStatus::Unverified,
}
}
/// The user to whom the email address belongs
async fn user(&self) -> Option<User> {
match self {
SetPrimaryEmailPayload::Set(user) => Some(User(user.clone())),
SetPrimaryEmailPayload::NotFound | SetPrimaryEmailPayload::Unverified => None,
}
}
}
#[Object]
impl UserEmailMutations {
/// Add an email address to the specified user
@@ -506,4 +551,40 @@ impl UserEmailMutations {
Ok(RemoveEmailPayload::Removed(user_email))
}
/// Set an email address as primary
async fn set_primary_email(
&self,
ctx: &Context<'_>,
input: SetPrimaryEmailInput,
) -> Result<SetPrimaryEmailPayload, async_graphql::Error> {
let state = ctx.state();
let user_email_id = NodeType::UserEmail.extract_ulid(&input.user_email_id)?;
let requester = ctx.requester();
let user = requester.user().context("Unauthorized")?;
let mut repo = state.repository().await?;
let user_email = repo.user_email().lookup(user_email_id).await?;
let Some(user_email) = user_email else {
return Ok(SetPrimaryEmailPayload::NotFound);
};
if user_email.user_id != user.id {
return Err(async_graphql::Error::new("Unauthorized"));
}
if user_email.confirmed_at.is_none() {
return Ok(SetPrimaryEmailPayload::Unverified);
}
repo.user_email().set_as_primary(&user_email).await?;
repo.save().await?;
let mut user = user.clone();
user.primary_user_email_id = Some(user_email.id);
Ok(SetPrimaryEmailPayload::Set(user))
}
}