Skip to content

Commit

Permalink
WIP: Defer creating users until after mail
Browse files Browse the repository at this point in the history
WIP Prevent saving user/org-member to database until after mail has been sent

Signed-off-by: BlackDex <[email protected]>
  • Loading branch information
BlackDex committed Jan 5, 2025
1 parent ef4bff0 commit 3ff5bf7
Showing 1 changed file with 52 additions and 41 deletions.
93 changes: 52 additions & 41 deletions src/api/core/organizations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,8 @@ async fn send_invite(org_id: &str, data: Json<InviteData>, headers: AdminHeaders
data.access_all = true;
}

let mut invitation: Option<Invitation> = None;
let mut user_created: bool = false;
for email in data.emails.iter() {
let mut user_org_status = UserOrgStatus::Invited as i32;
let user = match User::find_by_mail(email, &mut conn).await {
Expand All @@ -908,13 +910,11 @@ async fn send_invite(org_id: &str, data: Json<InviteData>, headers: AdminHeaders
}

if !CONFIG.mail_enabled() {
let invitation = Invitation::new(email);
invitation.save(&mut conn).await?;
invitation = Some(Invitation::new(email));
}

let mut user = User::new(email.clone());
user.save(&mut conn).await?;
user
user_created = true;
User::new(email.clone())
}
Some(user) => {
if UserOrganization::find_by_user_and_org(&user.uuid, org_id, &mut conn).await.is_some() {
Expand All @@ -929,11 +929,11 @@ async fn send_invite(org_id: &str, data: Json<InviteData>, headers: AdminHeaders
}
};

let mut new_user = UserOrganization::new(user.uuid.clone(), String::from(org_id));
let mut new_member = UserOrganization::new(user.uuid.clone(), String::from(org_id));
let access_all = data.access_all;
new_user.access_all = access_all;
new_user.atype = new_type;
new_user.status = user_org_status;
new_member.access_all = access_all;
new_member.atype = new_type;
new_member.status = user_org_status;

// If no accessAll, add the collections received
if !access_all {
Expand All @@ -954,16 +954,25 @@ async fn send_invite(org_id: &str, data: Json<InviteData>, headers: AdminHeaders
}
}

new_user.save(&mut conn).await?;
if CONFIG.mail_enabled() {
let org_name = match Organization::find_by_uuid(org_id, &mut conn).await {
Some(org) => org.name,
None => err!("Error looking up organization"),
};

for group in data.groups.iter() {
let mut group_entry = GroupUser::new(String::from(group), new_user.uuid.clone());
group_entry.save(&mut conn).await?;
mail::send_invite(
&user,
Some(String::from(org_id)),
Some(new_member.uuid.clone()),
&org_name,
Some(headers.user.email.clone()),
)
.await?;
}

log_event(
EventType::OrganizationUserInvited as i32,
&new_user.uuid,
&new_member.uuid,
org_id,
&headers.user.uuid,
headers.device.atype,
Expand All @@ -972,20 +981,20 @@ async fn send_invite(org_id: &str, data: Json<InviteData>, headers: AdminHeaders
)
.await;

if CONFIG.mail_enabled() {
let org_name = match Organization::find_by_uuid(org_id, &mut conn).await {
Some(org) => org.name,
None => err!("Error looking up organization"),
};
// Save all database objects if everything went ok
// This prevents creating a user if sending the invite mail fails for example
if let Some(ref invite) = invitation {
invite.save(&mut conn).await?;
}
if user_created {
let mut user = user;
user.save(&mut conn).await?;
}
new_member.save(&mut conn).await?;

mail::send_invite(
&user,
Some(String::from(org_id)),
Some(new_user.uuid),
&org_name,
Some(headers.user.email.clone()),
)
.await?;
for group in data.groups.iter() {
let mut group_entry = GroupUser::new(String::from(group), new_member.uuid.clone());
group_entry.save(&mut conn).await?;
}
}

Expand Down Expand Up @@ -2074,19 +2083,6 @@ async fn import(org_id: &str, data: Json<OrgImportData>, headers: Headers, mut c
new_org_user.atype = UserOrgType::User as i32;
new_org_user.status = user_org_status;

new_org_user.save(&mut conn).await?;

log_event(
EventType::OrganizationUserInvited as i32,
&new_org_user.uuid,
org_id,
&headers.user.uuid,
headers.device.atype,
&headers.ip.ip,
&mut conn,
)
.await;

if CONFIG.mail_enabled() {
let org_name = match Organization::find_by_uuid(org_id, &mut conn).await {
Some(org) => org.name,
Expand All @@ -2096,12 +2092,27 @@ async fn import(org_id: &str, data: Json<OrgImportData>, headers: Headers, mut c
mail::send_invite(
&user,
Some(String::from(org_id)),
Some(new_org_user.uuid),
Some(new_org_user.uuid.clone()),
&org_name,
Some(headers.user.email.clone()),
)
.await?;
}

// Save the user after sending an email
// If sending fails the user will not be saved to the database, and will not result in the admin needing to reinvite the users manually
new_org_user.save(&mut conn).await?;

log_event(
EventType::OrganizationUserInvited as i32,
&new_org_user.uuid,
org_id,
&headers.user.uuid,
headers.device.atype,
&headers.ip.ip,
&mut conn,
)
.await;
}
}
}
Expand Down

0 comments on commit 3ff5bf7

Please sign in to comment.