diff options
author | Timshel <[email protected]> | 2024-09-01 15:55:41 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2024-09-01 15:55:41 +0200 |
commit | 248e561b3fe6a8172751374df980c6cd43c841d5 (patch) | |
tree | e8cffd2c008548b7cd183b2734478ad45fa491ca | |
parent | 55623ad9c67abba7f2136858226a08854ce0f050 (diff) | |
download | vaultwarden-248e561b3fe6a8172751374df980c6cd43c841d5.tar.gz vaultwarden-248e561b3fe6a8172751374df980c6cd43c841d5.zip |
Add orgUserHasExistingUser parameters to org invite (#4827)
-rw-r--r-- | src/api/admin.rs | 4 | ||||
-rw-r--r-- | src/api/core/organizations.rs | 9 | ||||
-rw-r--r-- | src/api/core/public.rs | 11 | ||||
-rw-r--r-- | src/mail.rs | 41 | ||||
-rw-r--r-- | src/static/templates/email/send_org_invite.hbs | 4 | ||||
-rw-r--r-- | src/static/templates/email/send_org_invite.html.hbs | 4 |
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 }} |