aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimshel <[email protected]>2024-09-01 15:55:41 +0200
committerGitHub <[email protected]>2024-09-01 15:55:41 +0200
commit248e561b3fe6a8172751374df980c6cd43c841d5 (patch)
treee8cffd2c008548b7cd183b2734478ad45fa491ca
parent55623ad9c67abba7f2136858226a08854ce0f050 (diff)
downloadvaultwarden-248e561b3fe6a8172751374df980c6cd43c841d5.tar.gz
vaultwarden-248e561b3fe6a8172751374df980c6cd43c841d5.zip
Add orgUserHasExistingUser parameters to org invite (#4827)
-rw-r--r--src/api/admin.rs4
-rw-r--r--src/api/core/organizations.rs9
-rw-r--r--src/api/core/public.rs11
-rw-r--r--src/mail.rs41
-rw-r--r--src/static/templates/email/send_org_invite.hbs4
-rw-r--r--src/static/templates/email/send_org_invite.html.hbs4
6 files changed, 41 insertions, 32 deletions
diff --git a/src/api/admin.rs b/src/api/admin.rs
index 03d86920..961bbdb3 100644
--- a/src/api/admin.rs
+++ b/src/api/admin.rs
@@ -298,7 +298,7 @@ async fn invite_user(data: Json<InviteData>, _token: AdminToken, mut conn: DbCon
async fn _generate_invite(user: &User, conn: &mut DbConn) -> EmptyResult {
if CONFIG.mail_enabled() {
- mail::send_invite(&user.email, &user.uuid, None, None, &CONFIG.invitation_org_name(), None).await
+ mail::send_invite(user, None, None, &CONFIG.invitation_org_name(), None).await
} else {
let invitation = Invitation::new(&user.email);
invitation.save(conn).await
@@ -474,7 +474,7 @@ async fn resend_user_invite(uuid: &str, _token: AdminToken, mut conn: DbConn) ->
}
if CONFIG.mail_enabled() {
- mail::send_invite(&user.email, &user.uuid, None, None, &CONFIG.invitation_org_name(), None).await
+ mail::send_invite(&user, None, None, &CONFIG.invitation_org_name(), None).await
} else {
Ok(())
}
diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs
index f1def030..e0c3f081 100644
--- a/src/api/core/organizations.rs
+++ b/src/api/core/organizations.rs
@@ -956,8 +956,7 @@ async fn send_invite(org_id: &str, data: Json<InviteData>, headers: AdminHeaders
};
mail::send_invite(
- &email,
- &user.uuid,
+ &user,
Some(String::from(org_id)),
Some(new_user.uuid),
&org_name,
@@ -1033,8 +1032,7 @@ async fn _reinvite_user(org_id: &str, user_org: &str, invited_by_email: &str, co
if CONFIG.mail_enabled() {
mail::send_invite(
- &user.email,
- &user.uuid,
+ &user,
Some(org_id.to_string()),
Some(user_org.uuid),
&org_name,
@@ -2037,8 +2035,7 @@ async fn import(org_id: &str, data: Json<OrgImportData>, headers: Headers, mut c
};
mail::send_invite(
- &user_data.email,
- &user.uuid,
+ &user,
Some(String::from(org_id)),
Some(new_org_user.uuid),
&org_name,
diff --git a/src/api/core/public.rs b/src/api/core/public.rs
index 0cdcbb63..32b64463 100644
--- a/src/api/core/public.rs
+++ b/src/api/core/public.rs
@@ -123,15 +123,8 @@ async fn ldap_import(data: Json<OrgImportData>, token: PublicToken, mut conn: Db
None => err!("Error looking up organization"),
};
- mail::send_invite(
- &user_data.email,
- &user.uuid,
- Some(org_id.clone()),
- Some(new_org_user.uuid),
- &org_name,
- Some(org_email),
- )
- .await?;
+ mail::send_invite(&user, Some(org_id.clone()), Some(new_org_user.uuid), &org_name, Some(org_email))
+ .await?;
}
}
}
diff --git a/src/mail.rs b/src/mail.rs
index 151554a1..ce570171 100644
--- a/src/mail.rs
+++ b/src/mail.rs
@@ -17,6 +17,7 @@ use crate::{
encode_jwt, generate_delete_claims, generate_emergency_access_invite_claims, generate_invite_claims,
generate_verify_email_claims,
},
+ db::models::User,
error::Error,
CONFIG,
};
@@ -229,37 +230,55 @@ pub async fn send_single_org_removed_from_org(address: &str, org_name: &str) ->
}
pub async fn send_invite(
- address: &str,
- uuid: &str,
+ user: &User,
org_id: Option<String>,
org_user_id: Option<String>,
org_name: &str,
invited_by_email: Option<String>,
) -> EmptyResult {
let claims = generate_invite_claims(
- uuid.to_string(),
- String::from(address),
+ user.uuid.clone(),
+ user.email.clone(),
org_id.clone(),
org_user_id.clone(),
invited_by_email,
);
let invite_token = encode_jwt(&claims);
+ let mut query = url::Url::parse("https://query.builder").unwrap();
+ {
+ let mut query_params = query.query_pairs_mut();
+ query_params
+ .append_pair("email", &user.email)
+ .append_pair("organizationName", org_name)
+ .append_pair("token", &invite_token);
+ if let Some(id) = org_id {
+ query_params.append_pair("organizationId", &id);
+ };
+ if let Some(id) = org_user_id {
+ query_params.append_pair("organizationUserId", &id);
+ };
+ if user.private_key.is_some() {
+ query_params.append_pair("orgUserHasExistingUser", "true");
+ }
+ }
+ let query_string = match query.query() {
+ None => err!(format!("Failed to build invite URL query parameters")),
+ Some(query) => query,
+ };
+
+ // `url.Url` would place the anchor `#` after the query parameters
+ let url = format!("{}/#/accept-organization/?{}", CONFIG.domain(), query_string);
let (subject, body_html, body_text) = get_text(
"email/send_org_invite",
json!({
- "url": CONFIG.domain(),
+ "url": url,
"img_src": CONFIG._smtp_img_src(),
- "org_id": org_id.as_deref().unwrap_or("_"),
- "org_user_id": org_user_id.as_deref().unwrap_or("_"),
- "email": percent_encode(address.as_bytes(), NON_ALPHANUMERIC).to_string(),
- "org_name_encoded": percent_encode(org_name.as_bytes(), NON_ALPHANUMERIC).to_string(),
"org_name": org_name,
- "token": invite_token,
}),
)?;
- send_email(address, &subject, body_html, body_text).await
+ send_email(&user.email, &subject, body_html, body_text).await
}
pub async fn send_emergency_access_invite(
diff --git a/src/static/templates/email/send_org_invite.hbs b/src/static/templates/email/send_org_invite.hbs
index be94d0e5..b2c46f50 100644
--- a/src/static/templates/email/send_org_invite.hbs
+++ b/src/static/templates/email/send_org_invite.hbs
@@ -3,8 +3,8 @@ Join {{{org_name}}}
You have been invited to join the *{{org_name}}* organization.
-Click here to join: {{url}}/#/accept-organization/?organizationId={{org_id}}&organizationUserId={{org_user_id}}&email={{email}}&organizationName={{org_name_encoded}}&token={{token}}
+Click here to join: {{url}}
If you do not wish to join this organization, you can safely ignore this email.
-{{> email/email_footer_text }} \ No newline at end of file
+{{> email/email_footer_text }}
diff --git a/src/static/templates/email/send_org_invite.html.hbs b/src/static/templates/email/send_org_invite.html.hbs
index 55b98145..a78a89e9 100644
--- a/src/static/templates/email/send_org_invite.html.hbs
+++ b/src/static/templates/email/send_org_invite.html.hbs
@@ -9,7 +9,7 @@ Join {{{org_name}}}
</tr>
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center">
- <a href="{{url}}/#/accept-organization/?organizationId={{org_id}}&organizationUserId={{org_user_id}}&email={{email}}&organizationName={{org_name_encoded}}&token={{token}}"
+ <a href="{{url}}"
clicktracking=off target="_blank" style="color: #ffffff; text-decoration: none; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; background-color: #3c8dbc; border-color: #3c8dbc; border-style: solid; border-width: 10px 20px; margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
Join Organization Now
</a>
@@ -21,4 +21,4 @@ Join {{{org_name}}}
</td>
</tr>
</table>
-{{> email/email_footer }} \ No newline at end of file
+{{> email/email_footer }}