mirror of
https://github.com/dani-garcia/vaultwarden
synced 2024-11-21 19:33:11 +00:00
Add orgUserHasExistingUser parameters to org invite (#4827)
This commit is contained in:
parent
55623ad9c6
commit
248e561b3f
6 changed files with 41 additions and 32 deletions
|
@ -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 {
|
async fn _generate_invite(user: &User, conn: &mut DbConn) -> EmptyResult {
|
||||||
if CONFIG.mail_enabled() {
|
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 {
|
} else {
|
||||||
let invitation = Invitation::new(&user.email);
|
let invitation = Invitation::new(&user.email);
|
||||||
invitation.save(conn).await
|
invitation.save(conn).await
|
||||||
|
@ -474,7 +474,7 @@ async fn resend_user_invite(uuid: &str, _token: AdminToken, mut conn: DbConn) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
if CONFIG.mail_enabled() {
|
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 {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -956,8 +956,7 @@ async fn send_invite(org_id: &str, data: Json<InviteData>, headers: AdminHeaders
|
||||||
};
|
};
|
||||||
|
|
||||||
mail::send_invite(
|
mail::send_invite(
|
||||||
&email,
|
&user,
|
||||||
&user.uuid,
|
|
||||||
Some(String::from(org_id)),
|
Some(String::from(org_id)),
|
||||||
Some(new_user.uuid),
|
Some(new_user.uuid),
|
||||||
&org_name,
|
&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() {
|
if CONFIG.mail_enabled() {
|
||||||
mail::send_invite(
|
mail::send_invite(
|
||||||
&user.email,
|
&user,
|
||||||
&user.uuid,
|
|
||||||
Some(org_id.to_string()),
|
Some(org_id.to_string()),
|
||||||
Some(user_org.uuid),
|
Some(user_org.uuid),
|
||||||
&org_name,
|
&org_name,
|
||||||
|
@ -2037,8 +2035,7 @@ async fn import(org_id: &str, data: Json<OrgImportData>, headers: Headers, mut c
|
||||||
};
|
};
|
||||||
|
|
||||||
mail::send_invite(
|
mail::send_invite(
|
||||||
&user_data.email,
|
&user,
|
||||||
&user.uuid,
|
|
||||||
Some(String::from(org_id)),
|
Some(String::from(org_id)),
|
||||||
Some(new_org_user.uuid),
|
Some(new_org_user.uuid),
|
||||||
&org_name,
|
&org_name,
|
||||||
|
|
|
@ -123,15 +123,8 @@ async fn ldap_import(data: Json<OrgImportData>, token: PublicToken, mut conn: Db
|
||||||
None => err!("Error looking up organization"),
|
None => err!("Error looking up organization"),
|
||||||
};
|
};
|
||||||
|
|
||||||
mail::send_invite(
|
mail::send_invite(&user, Some(org_id.clone()), Some(new_org_user.uuid), &org_name, Some(org_email))
|
||||||
&user_data.email,
|
.await?;
|
||||||
&user.uuid,
|
|
||||||
Some(org_id.clone()),
|
|
||||||
Some(new_org_user.uuid),
|
|
||||||
&org_name,
|
|
||||||
Some(org_email),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
41
src/mail.rs
41
src/mail.rs
|
@ -17,6 +17,7 @@ use crate::{
|
||||||
encode_jwt, generate_delete_claims, generate_emergency_access_invite_claims, generate_invite_claims,
|
encode_jwt, generate_delete_claims, generate_emergency_access_invite_claims, generate_invite_claims,
|
||||||
generate_verify_email_claims,
|
generate_verify_email_claims,
|
||||||
},
|
},
|
||||||
|
db::models::User,
|
||||||
error::Error,
|
error::Error,
|
||||||
CONFIG,
|
CONFIG,
|
||||||
};
|
};
|
||||||
|
@ -229,37 +230,55 @@ pub async fn send_single_org_removed_from_org(address: &str, org_name: &str) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_invite(
|
pub async fn send_invite(
|
||||||
address: &str,
|
user: &User,
|
||||||
uuid: &str,
|
|
||||||
org_id: Option<String>,
|
org_id: Option<String>,
|
||||||
org_user_id: Option<String>,
|
org_user_id: Option<String>,
|
||||||
org_name: &str,
|
org_name: &str,
|
||||||
invited_by_email: Option<String>,
|
invited_by_email: Option<String>,
|
||||||
) -> EmptyResult {
|
) -> EmptyResult {
|
||||||
let claims = generate_invite_claims(
|
let claims = generate_invite_claims(
|
||||||
uuid.to_string(),
|
user.uuid.clone(),
|
||||||
String::from(address),
|
user.email.clone(),
|
||||||
org_id.clone(),
|
org_id.clone(),
|
||||||
org_user_id.clone(),
|
org_user_id.clone(),
|
||||||
invited_by_email,
|
invited_by_email,
|
||||||
);
|
);
|
||||||
let invite_token = encode_jwt(&claims);
|
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(
|
let (subject, body_html, body_text) = get_text(
|
||||||
"email/send_org_invite",
|
"email/send_org_invite",
|
||||||
json!({
|
json!({
|
||||||
"url": CONFIG.domain(),
|
"url": url,
|
||||||
"img_src": CONFIG._smtp_img_src(),
|
"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,
|
"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(
|
pub async fn send_emergency_access_invite(
|
||||||
|
|
|
@ -3,8 +3,8 @@ Join {{{org_name}}}
|
||||||
You have been invited to join the *{{org_name}}* organization.
|
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.
|
If you do not wish to join this organization, you can safely ignore this email.
|
||||||
{{> email/email_footer_text }}
|
{{> email/email_footer_text }}
|
||||||
|
|
|
@ -9,7 +9,7 @@ Join {{{org_name}}}
|
||||||
</tr>
|
</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;">
|
<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">
|
<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;">
|
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
|
Join Organization Now
|
||||||
</a>
|
</a>
|
||||||
|
@ -21,4 +21,4 @@ Join {{{org_name}}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
{{> email/email_footer }}
|
{{> email/email_footer }}
|
||||||
|
|
Loading…
Reference in a new issue