Emergency Access cleanup

This commit contains mostly superficial user-facing cleanup, to be followed up
with more extensive cleanup and fixes in the API implementation.
pull/2044/head
Jeremy Lin 3 years ago
parent 016fe2269e
commit cee3fd5ba2

@ -61,6 +61,10 @@
## To control this on a per-org basis instead, use the "Disable Send" org policy. ## To control this on a per-org basis instead, use the "Disable Send" org policy.
# SENDS_ALLOWED=true # SENDS_ALLOWED=true
## Controls whether users can enable emergency access to their accounts.
## This setting applies globally to all users.
# EMERGENCY_ACCESS_ALLOWED=true
## Job scheduler settings ## Job scheduler settings
## ##
## Job schedules use a cron-like syntax (as parsed by https://crates.io/crates/cron), ## Job schedules use a cron-like syntax (as parsed by https://crates.io/crates/cron),
@ -78,13 +82,13 @@
## Defaults to daily (5 minutes after midnight). Set blank to disable this job. ## Defaults to daily (5 minutes after midnight). Set blank to disable this job.
# TRASH_PURGE_SCHEDULE="0 5 0 * * *" # TRASH_PURGE_SCHEDULE="0 5 0 * * *"
## ##
## Cron schedule of the job that sends expiration reminders to emergency request grantors. ## Cron schedule of the job that sends expiration reminders to emergency access grantors.
## Defaults to hourly (10 minutes after the hour). Set blank to disable this job. ## Defaults to hourly (5 minutes after the hour). Set blank to disable this job.
# EMERGENCY_NOTIFICATION_REMINDER_SCHEDULE="0 10 * * * *" # EMERGENCY_NOTIFICATION_REMINDER_SCHEDULE="0 5 * * * *"
## ##
## Cron schedule of the job that checks for expired (i.e granted by timeout) emergency requests. ## Cron schedule of the job that grants emergency access requests that have met the required wait time.
## Defaults to hourly (15 minutes after the hour). Set blank to disable this job. ## Defaults to hourly (5 minutes after the hour). Set blank to disable this job.
# EMERGENCY_REQUEST_TIMEOUT_SCHEDULE="0 15 * * * *" # EMERGENCY_REQUEST_TIMEOUT_SCHEDULE="0 5 * * * *"
## Enable extended logging, which shows timestamps and targets in the logs ## Enable extended logging, which shows timestamps and targets in the logs
# EXTENDED_LOGGING=true # EXTENDED_LOGGING=true
@ -320,9 +324,6 @@
## If sending the email fails the login attempt will fail!! ## If sending the email fails the login attempt will fail!!
# REQUIRE_DEVICE_EMAIL=false # REQUIRE_DEVICE_EMAIL=false
## Emergency access enable. Enable or disable the emergency access feature for all users
# EMERGENCY_ACCESS_ALLOWED=false
## HIBP Api Key ## HIBP Api Key
## HaveIBeenPwned API Key, request it here: https://haveibeenpwned.com/API/Key ## HaveIBeenPwned API Key, request it here: https://haveibeenpwned.com/API/Key
# HIBP_API_KEY= # HIBP_API_KEY=

@ -91,10 +91,9 @@ fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult {
user user
} else if CONFIG.is_signup_allowed(&email) { } else if CONFIG.is_signup_allowed(&email) {
// check if it's invited by emergency contact // check if it's invited by emergency contact
if EmergencyAccess::find_invited_by_grantee_email(&data.Email, &conn).is_some() { match EmergencyAccess::find_invited_by_grantee_email(&data.Email, &conn) {
user Some(_) => user,
} else { _ => err!("Account with this email already exists"),
err!("Account with this email already exists")
} }
} else { } else {
err!("Registration not allowed or user already exists") err!("Registration not allowed or user already exists")

@ -464,7 +464,7 @@ fn initiate_emergency_access(emer_id: String, headers: Headers, conn: DbConn) ->
mail::send_emergency_access_recovery_initiated( mail::send_emergency_access_recovery_initiated(
&grantor_user.email, &grantor_user.email,
&initiating_user.name, &initiating_user.name,
emergency_access.get_atype_as_str(), emergency_access.get_type_as_str(),
&emergency_access.wait_time_days.clone().to_string(), &emergency_access.wait_time_days.clone().to_string(),
)?; )?;
} }
@ -743,7 +743,7 @@ pub fn emergency_request_timeout_job(pool: DbPool) {
mail::send_emergency_access_recovery_timed_out( mail::send_emergency_access_recovery_timed_out(
&grantor_user.email, &grantor_user.email,
&grantee_user.name.clone(), &grantee_user.name.clone(),
emer.get_atype_as_str(), emer.get_type_as_str(),
) )
.expect("Error on sending email"); .expect("Error on sending email");
@ -792,8 +792,8 @@ pub fn emergency_notification_reminder_job(pool: DbPool) {
mail::send_emergency_access_recovery_reminder( mail::send_emergency_access_recovery_reminder(
&grantor_user.email, &grantor_user.email,
&grantee_user.name.clone(), &grantee_user.name.clone(),
emer.get_atype_as_str(), emer.get_type_as_str(),
&emer.wait_time_days.to_string(), &emer.wait_time_days.to_string(), // TODO(jjlin): This should be the number of days left.
) )
.expect("Error on sending email"); .expect("Error on sending email");
} }

@ -333,12 +333,12 @@ make_config! {
/// Trash purge schedule |> Cron schedule of the job that checks for trashed items to delete permanently. /// Trash purge schedule |> Cron schedule of the job that checks for trashed items to delete permanently.
/// Defaults to daily. Set blank to disable this job. /// Defaults to daily. Set blank to disable this job.
trash_purge_schedule: String, false, def, "0 5 0 * * *".to_string(); trash_purge_schedule: String, false, def, "0 5 0 * * *".to_string();
/// Emergency notification reminder schedule |> Cron schedule of the job that sends expiration reminders to emergency request grantors. /// Emergency notification reminder schedule |> Cron schedule of the job that sends expiration reminders to emergency access grantors.
/// Defaults to hourly. Set blank to disable this job. /// Defaults to hourly. Set blank to disable this job.
emergency_notification_reminder_schedule: String, false, def, "0 10 * * * *".to_string(); emergency_notification_reminder_schedule: String, false, def, "0 5 * * * *".to_string();
/// Emergency request timeout schedule |> Cron schedule of the job that checks for expired (i.e granted by timeout) emergency requests. /// Emergency request timeout schedule |> Cron schedule of the job that grants emergency access requests that have met the required wait time.
/// Defaults to hourly. Set blank to disable this job. /// Defaults to hourly. Set blank to disable this job.
emergency_request_timeout_schedule: String, false, def, "0 15 * * * *".to_string(); emergency_request_timeout_schedule: String, false, def, "0 5 * * * *".to_string();
}, },
/// General settings /// General settings
@ -391,7 +391,7 @@ make_config! {
org_creation_users: String, true, def, "".to_string(); org_creation_users: String, true, def, "".to_string();
/// Allow invitations |> Controls whether users can be invited by organization admins, even when signups are otherwise disabled /// Allow invitations |> Controls whether users can be invited by organization admins, even when signups are otherwise disabled
invitations_allowed: bool, true, def, true; invitations_allowed: bool, true, def, true;
/// Allow emergency access |> Controls whether users can enable emergency access to their accounts /// Allow emergency access |> Controls whether users can enable emergency access to their accounts. This setting applies globally to all users.
emergency_access_allowed: bool, true, def, true; emergency_access_allowed: bool, true, def, true;
/// Password iterations |> Number of server-side passwords hashing iterations. /// Password iterations |> Number of server-side passwords hashing iterations.
/// The changes only apply when a user changes their password. Not recommended to lower the value /// The changes only apply when a user changes their password. Not recommended to lower the value

@ -47,7 +47,7 @@ impl EmergencyAccess {
} }
} }
pub fn get_atype_as_str(&self) -> &'static str { pub fn get_type_as_str(&self) -> &'static str {
if self.atype == EmergencyAccessType::View as i32 { if self.atype == EmergencyAccessType::View as i32 {
"View" "View"
} else { } else {
@ -55,6 +55,14 @@ impl EmergencyAccess {
} }
} }
pub fn has_type(&self, access_type: EmergencyAccessType) -> bool {
self.atype == access_type as i32
}
pub fn has_status(&self, status: EmergencyAccessStatus) -> bool {
self.status == status as i32
}
pub fn to_json(&self) -> Value { pub fn to_json(&self) -> Value {
json!({ json!({
"Id": self.uuid, "Id": self.uuid,
@ -66,55 +74,40 @@ impl EmergencyAccess {
} }
pub fn to_json_grantor_details(&self, conn: &DbConn) -> Value { pub fn to_json_grantor_details(&self, conn: &DbConn) -> Value {
// find grantor let grantor_user = User::find_by_uuid(&self.grantor_uuid, conn).expect("Grantor user not found.");
let grantor_user = User::find_by_uuid(&self.grantor_uuid, conn).unwrap();
json!({ json!({
"Id": self.uuid, "Id": self.uuid,
"Status": self.status, "Status": self.status,
"Type": self.atype, "Type": self.atype,
"WaitTimeDays": self.wait_time_days, "WaitTimeDays": self.wait_time_days,
"GrantorId": grantor_user.uuid, "GrantorId": grantor_user.uuid,
"Email": grantor_user.email, "Email": grantor_user.email,
"Name": grantor_user.name, "Name": grantor_user.name,
"Object": "emergencyAccessGrantorDetails",}) "Object": "emergencyAccessGrantorDetails",
})
} }
#[allow(clippy::manual_map)]
pub fn to_json_grantee_details(&self, conn: &DbConn) -> Value { pub fn to_json_grantee_details(&self, conn: &DbConn) -> Value {
if self.grantee_uuid.is_some() { let grantee_user = if let Some(grantee_uuid) = self.grantee_uuid.as_deref() {
let grantee_user = Some(User::find_by_uuid(grantee_uuid, conn).expect("Grantee user not found."))
User::find_by_uuid(&self.grantee_uuid.clone().unwrap(), conn).expect("Grantee user not found."); } else if let Some(email) = self.email.as_deref() {
Some(User::find_by_mail(email, conn).expect("Grantee user not found."))
json!({
"Id": self.uuid,
"Status": self.status,
"Type": self.atype,
"WaitTimeDays": self.wait_time_days,
"GranteeId": grantee_user.uuid,
"Email": grantee_user.email,
"Name": grantee_user.name,
"Object": "emergencyAccessGranteeDetails",})
} else if self.email.is_some() {
let grantee_user = User::find_by_mail(&self.email.clone().unwrap(), conn).expect("Grantee user not found.");
json!({
"Id": self.uuid,
"Status": self.status,
"Type": self.atype,
"WaitTimeDays": self.wait_time_days,
"GranteeId": grantee_user.uuid,
"Email": grantee_user.email,
"Name": grantee_user.name,
"Object": "emergencyAccessGranteeDetails",})
} else { } else {
json!({ None
"Id": self.uuid, };
"Status": self.status,
"Type": self.atype, json!({
"WaitTimeDays": self.wait_time_days, "Id": self.uuid,
"GranteeId": "", "Status": self.status,
"Email": "", "Type": self.atype,
"Name": "", "WaitTimeDays": self.wait_time_days,
"Object": "emergencyAccessGranteeDetails",}) "GranteeId": grantee_user.as_ref().map_or("", |u| &u.uuid),
} "Email": grantee_user.as_ref().map_or("", |u| &u.email),
"Name": grantee_user.as_ref().map_or("", |u| &u.name),
"Object": "emergencyAccessGranteeDetails",
})
} }
} }
@ -198,11 +191,11 @@ impl EmergencyAccess {
} }
pub fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult { pub fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
for user_org in Self::find_all_by_grantor_uuid(user_uuid, conn) { for ea in Self::find_all_by_grantor_uuid(user_uuid, conn) {
user_org.delete(conn)?; ea.delete(conn)?;
} }
for user_org in Self::find_all_by_grantee_uuid(user_uuid, conn) { for ea in Self::find_all_by_grantee_uuid(user_uuid, conn) {
user_org.delete(conn)?; ea.delete(conn)?;
} }
Ok(()) Ok(())
} }
@ -213,7 +206,7 @@ impl EmergencyAccess {
db_run! { conn: { db_run! { conn: {
diesel::delete(emergency_access::table.filter(emergency_access::uuid.eq(self.uuid))) diesel::delete(emergency_access::table.filter(emergency_access::uuid.eq(self.uuid)))
.execute(conn) .execute(conn)
.map_res("Error removing user from organization") .map_res("Error removing user from emergency access")
}} }}
} }
@ -246,7 +239,6 @@ impl EmergencyAccess {
emergency_access::table emergency_access::table
.filter(emergency_access::status.eq(EmergencyAccessStatus::RecoveryInitiated as i32)) .filter(emergency_access::status.eq(EmergencyAccessStatus::RecoveryInitiated as i32))
.load::<EmergencyAccessDb>(conn).expect("Error loading emergency_access").from_db() .load::<EmergencyAccessDb>(conn).expect("Error loading emergency_access").from_db()
}} }}
} }

@ -329,7 +329,7 @@ pub fn send_emergency_access_recovery_reminder(
address: &str, address: &str,
grantee_name: &str, grantee_name: &str,
atype: &str, atype: &str,
wait_time_days: &str, days_left: &str,
) -> EmptyResult { ) -> EmptyResult {
let (subject, body_html, body_text) = get_text( let (subject, body_html, body_text) = get_text(
"email/emergency_access_recovery_reminder", "email/emergency_access_recovery_reminder",
@ -337,7 +337,7 @@ pub fn send_emergency_access_recovery_reminder(
"url": CONFIG.domain(), "url": CONFIG.domain(),
"grantee_name": grantee_name, "grantee_name": grantee_name,
"atype": atype, "atype": atype,
"wait_time_days": wait_time_days, "days_left": days_left,
}), }),
)?; )?;

@ -345,12 +345,17 @@ fn schedule_jobs(pool: db::DbPool) {
})); }));
} }
// Grant emergency access requests that have met the required wait time.
// This job should run before the emergency access reminders job to avoid
// sending reminders for requests that are about to be granted anyway.
if !CONFIG.emergency_request_timeout_schedule().is_empty() { if !CONFIG.emergency_request_timeout_schedule().is_empty() {
sched.add(Job::new(CONFIG.emergency_request_timeout_schedule().parse().unwrap(), || { sched.add(Job::new(CONFIG.emergency_request_timeout_schedule().parse().unwrap(), || {
api::emergency_request_timeout_job(pool.clone()); api::emergency_request_timeout_job(pool.clone());
})); }));
} }
// Send reminders to emergency access grantors that there are pending
// emergency access requests.
if !CONFIG.emergency_notification_reminder_schedule().is_empty() { if !CONFIG.emergency_notification_reminder_schedule().is_empty() {
sched.add(Job::new(CONFIG.emergency_notification_reminder_schedule().parse().unwrap(), || { sched.add(Job::new(CONFIG.emergency_notification_reminder_schedule().parse().unwrap(), || {
api::emergency_notification_reminder_job(pool.clone()); api::emergency_notification_reminder_job(pool.clone());
@ -362,6 +367,10 @@ fn schedule_jobs(pool: db::DbPool) {
// interval of 30 seconds should be sufficient. Users who want to // interval of 30 seconds should be sufficient. Users who want to
// schedule jobs to run more frequently for some reason can reduce // schedule jobs to run more frequently for some reason can reduce
// the poll interval accordingly. // the poll interval accordingly.
//
// Note that the scheduler checks jobs in the order in which they
// were added, so if two jobs are both eligible to run at a given
// tick, the one that was added earlier will run first.
loop { loop {
sched.tick(); sched.tick();
thread::sleep(Duration::from_millis(CONFIG.job_poll_interval_ms())); thread::sleep(Duration::from_millis(CONFIG.job_poll_interval_ms()));

@ -1,8 +1,8 @@
Emergency contact {{{grantee_email}}} accepted Emergency access contact {{{grantee_email}}} accepted
<!----------------> <!---------------->
This email is to notify you that {{grantee_email}} has accepted your invitation to become an emergency access contact. This email is to notify you that {{grantee_email}} has accepted your invitation to become an emergency access contact.
To confirm this user, Log into {{url}} the Bitwarden web vault, go to settings and confirm the user. To confirm this user, log into the web vault ({{url}}), go to settings and confirm the user.
If you do not wish to confirm this user, you can also remove them on the same page. If you do not wish to confirm this user, you can also remove them on the same page.
{{> email/email_footer_text }} {{> email/email_footer_text }}

@ -1,4 +1,4 @@
Emergency contact {{{grantee_email}}} accepted Emergency access contact {{{grantee_email}}} accepted
<!----------------> <!---------------->
{{> email/email_header }} {{> email/email_header }}
<table width="100%" cellpadding="0" cellspacing="0" 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;"> <table width="100%" cellpadding="0" cellspacing="0" 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;">
@ -9,7 +9,7 @@ Emergency contact {{{grantee_email}}} accepted
</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;" valign="top"> <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;" valign="top">
To confirm this user, <a href="{{url}}/">log into</a> the vaultwarden web vault, go to settings and confirm the user. To confirm this user, log into the <a href="{{url}}/">web vault</a>, go to settings and confirm the user.
</td> </td>
</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;">

@ -1,6 +1,6 @@
Emergency contact for {{{grantor_name}}} confirmed Emergency access contact for {{{grantor_name}}} confirmed
<!----------------> <!---------------->
This email is to notify you that you have been confirmed as an emergency access contact for *{{grantor_name}}* was confirmed. This email is to notify you that you have been confirmed as an emergency access contact for *{{grantor_name}}*.
You can now initiate emergency access requests from the web vault. Log in {{url}}. You can now initiate emergency access requests from the web vault ({{url}}).
{{> email/email_footer_text }} {{> email/email_footer_text }}

@ -1,16 +1,15 @@
Emergency contact for {{{grantor_name}}} confirmed Emergency access contact for {{{grantor_name}}} confirmed
<!----------------> <!---------------->
{{> email/email_header }} {{> email/email_header }}
<table width="100%" cellpadding="0" cellspacing="0" 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;"> <table width="100%" cellpadding="0" cellspacing="0" 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;"> <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;" valign="top"> <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;" valign="top">
This email is to notify you that you have been confirmed as an emergency access contact for <b 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;">{{grantor_name}}</b> was confirmed. This email is to notify you that you have been confirmed as an emergency access contact for <b 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;">{{grantor_name}}</b>.
</td> </td>
</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 last" 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; -webkit-text-size-adjust: none;" valign="top"> <td class="content-block last" 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; -webkit-text-size-adjust: none;" valign="top">
You can now initiate emergency access requests from the web vault. <br> You can now initiate emergency access requests from the <a href="{{url}}/">web vault</a>.
<a href="{{url}}/">Log in</a>
</td> </td>
</tr> </tr>
</table> </table>

@ -1,4 +1,4 @@
Emergency contact request for {{{grantor_name}}} approved Emergency access request for {{{grantor_name}}} approved
<!----------------> <!---------------->
{{grantor_name}} has approved your emergency request. You may now login {{url}} on the web vault and access their account. {{grantor_name}} has approved your emergency access request. You may now login on the web vault ({{url}}) and access their account.
{{> email/email_footer_text }} {{> email/email_footer_text }}

@ -1,10 +1,10 @@
Emergency contact for {{{grantor_name}}} approved Emergency access request for {{{grantor_name}}} approved
<!----------------> <!---------------->
{{> email/email_header }} {{> email/email_header }}
<table width="100%" cellpadding="0" cellspacing="0" 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;"> <table width="100%" cellpadding="0" cellspacing="0" 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;"> <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;" valign="top"> <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;" valign="top">
<b 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;">{{grantor_name}}</b> has approved your emergency request. You may now <a href="{{url}}/">login</a> on the web vault and access their account. <b 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;">{{grantor_name}}</b> has approved your emergency access request. You may now login on the <a href="{{url}}/">web vault</a> and access their account.
</td> </td>
</tr> </tr>
</table> </table>

@ -1,6 +1,6 @@
Emergency access request by {{{grantee_name}}} initiated Emergency access request by {{{grantee_name}}} initiated
<!----------------> <!---------------->
{{grantee_name}} has initiated an emergency request to *{{atype}}* your account. You may login on the web vault and manually approve or reject this request. {{grantee_name}} has initiated an emergency access request to {{atype}} your account. You may login on the web vault ({{url}}) and manually approve or reject this request.
If you do nothing, the request will automatically be approved after {{wait_time_days}} day(s). If you do nothing, the request will automatically be approved after {{wait_time_days}} day(s).
{{> email/email_footer_text }} {{> email/email_footer_text }}

@ -4,7 +4,7 @@ Emergency access request by {{{grantee_name}}} initiated
<table width="100%" cellpadding="0" cellspacing="0" 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;"> <table width="100%" cellpadding="0" cellspacing="0" 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;"> <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;" valign="top"> <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;" valign="top">
<b 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;">{{grantee_name}}</b> has initiated an emergency request to <b 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;">{{atype}}</b> your account. You may login on the web vault and manually approve or reject this request. <b 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;">{{grantee_name}}</b> has initiated an emergency access request to <b 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;">{{atype}}</b> your account. You may login on the <a href="{{url}}/">web vault</a> and manually approve or reject this request.
</td> </td>
</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;">

@ -1,4 +1,4 @@
Emergency access request to {{{grantor_name}}} rejected Emergency access request to {{{grantor_name}}} rejected
<!----------------> <!---------------->
{{grantor_name}} has rejected your emergency request. {{grantor_name}} has rejected your emergency access request.
{{> email/email_footer_text }} {{> email/email_footer_text }}

@ -4,7 +4,7 @@ Emergency access request to {{{grantor_name}}} rejected
<table width="100%" cellpadding="0" cellspacing="0" 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;"> <table width="100%" cellpadding="0" cellspacing="0" 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;"> <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;" valign="top"> <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;" valign="top">
<b 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;">{{grantor_name}}</b> has rejected your emergency request. <b 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;">{{grantor_name}}</b> has rejected your emergency access request.
</td> </td>
</tr> </tr>
</table> </table>

@ -1,6 +1,6 @@
Emergency access request by {{{grantee_name}}} is pending Emergency access request by {{{grantee_name}}} is pending
<!----------------> <!---------------->
{{grantee_name}} has a pending emergency request to *{{atype}}* your account. You may login on the web vault and manually approve or reject this request. {{grantee_name}} has a pending emergency access request to {{atype}} your account. You may login on the web vault ({{url}}) and manually approve or reject this request.
If you do nothing, the request will automatically be approved after {{wait_time_days}} day(s). If you do nothing, the request will automatically be approved after {{days_left}} day(s).
{{> email/email_footer_text }} {{> email/email_footer_text }}

@ -4,12 +4,12 @@ Emergency access request by {{{grantee_name}}} is pending
<table width="100%" cellpadding="0" cellspacing="0" 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;"> <table width="100%" cellpadding="0" cellspacing="0" 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;"> <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;" valign="top"> <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;" valign="top">
<b 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;">{{grantee_name}}</b> has a pending emergency request to <b 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;">{{atype}}</b> your account. You may login on the web vault and manually approve or reject this request. <b 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;">{{grantee_name}}</b> has a pending emergency access request to <b 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;">{{atype}}</b> your account. You may login on the <a href="{{url}}/">web vault</a> and manually approve or reject this request.
</td> </td>
</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 last" 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; -webkit-text-size-adjust: none;" valign="top"> <td class="content-block last" 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; -webkit-text-size-adjust: none;" valign="top">
If you do nothing, the request will automatically be approved after <b 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;">{{wait_time_days}}</b> day(s). If you do nothing, the request will automatically be approved after <b 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;">{{days_left}}</b> day(s).
</td> </td>
</tr> </tr>
</table> </table>

@ -1,4 +1,4 @@
Emergency access request by {{{grantee_name}}} granted Emergency access request by {{{grantee_name}}} granted
<!----------------> <!---------------->
{{grantee_name}} has been granted emergency request to *{{atype}}* your account. You may login on the web vault and manually revoke this request. {{grantee_name}} has been granted emergency access to {{atype}} your account. You may login on the web vault ({{url}}) and manually revoke this request.
{{> email/email_footer_text }} {{> email/email_footer_text }}

@ -4,7 +4,7 @@ Emergency access request by {{{grantee_name}}} granted
<table width="100%" cellpadding="0" cellspacing="0" 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;"> <table width="100%" cellpadding="0" cellspacing="0" 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;"> <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;" valign="top"> <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;" valign="top">
<b 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;">{{grantee_name}}</b> has been granted emergency request to <b 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;">{{atype}}</b> your account. You may login on the web vault and manually revoke this request. <b 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;">{{grantee_name}}</b> has been granted emergency access to <b 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;">{{atype}}</b> your account. You may login on the <a href="{{url}}/">web vault</a> and manually revoke this request.
</td> </td>
</tr> </tr>
</table> </table>

Loading…
Cancel
Save