Merge branch 'main' into future-web-vault

This commit is contained in:
Mathijs van Veluw
2021-07-15 21:43:23 +02:00
committed by GitHub
18 changed files with 256 additions and 99 deletions

View File

@ -580,24 +580,45 @@ struct PasswordHintData {
#[post("/accounts/password-hint", data = "<data>")]
fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> EmptyResult {
let data: PasswordHintData = data.into_inner().data;
let hint = match User::find_by_mail(&data.Email, &conn) {
Some(user) => user.password_hint,
None => return Ok(()),
};
if CONFIG.mail_enabled() {
mail::send_password_hint(&data.Email, hint)?;
} else if CONFIG.show_password_hint() {
if let Some(hint) = hint {
err!(format!("Your password hint is: {}", &hint));
} else {
err!("Sorry, you have no password hint...");
}
if !CONFIG.mail_enabled() && !CONFIG.show_password_hint() {
err!("This server is not configured to provide password hints.");
}
Ok(())
const NO_HINT: &str = "Sorry, you have no password hint...";
let data: PasswordHintData = data.into_inner().data;
let email = &data.Email;
match User::find_by_mail(email, &conn) {
None => {
// To prevent user enumeration, act as if the user exists.
if CONFIG.mail_enabled() {
// There is still a timing side channel here in that the code
// paths that send mail take noticeably longer than ones that
// don't. Add a randomized sleep to mitigate this somewhat.
use rand::{thread_rng, Rng};
let mut rng = thread_rng();
let base = 1000;
let delta: i32 = 100;
let sleep_ms = (base + rng.gen_range(-delta..=delta)) as u64;
std::thread::sleep(std::time::Duration::from_millis(sleep_ms));
Ok(())
} else {
err!(NO_HINT);
}
}
Some(user) => {
let hint: Option<String> = user.password_hint;
if CONFIG.mail_enabled() {
mail::send_password_hint(email, hint)?;
Ok(())
} else if let Some(hint) = hint {
err!(format!("Your password hint is: {}", hint));
} else {
err!(NO_HINT);
}
}
}
}
#[derive(Deserialize)]

View File

@ -871,7 +871,7 @@ fn save_attachment(
Some(limit_kb) => {
let left = (limit_kb * 1024) - Attachment::size_by_user(user_uuid, conn) + size_adjust;
if left <= 0 {
err_discard!("Attachment size limit reached! Delete some files to open space", data)
err_discard!("Attachment storage limit reached! Delete some attachments to free up space", data)
}
Some(left as u64)
}
@ -883,7 +883,7 @@ fn save_attachment(
Some(limit_kb) => {
let left = (limit_kb * 1024) - Attachment::size_by_org(org_uuid, conn) + size_adjust;
if left <= 0 {
err_discard!("Attachment size limit reached! Delete some files to open space", data)
err_discard!("Attachment storage limit reached! Delete some attachments to free up space", data)
}
Some(left as u64)
}
@ -937,7 +937,7 @@ fn save_attachment(
return;
}
SaveResult::Partial(_, reason) => {
error = Some(format!("Attachment size limit exceeded with this file: {:?}", reason));
error = Some(format!("Attachment storage limit exceeded with this file: {:?}", reason));
return;
}
SaveResult::Error(e) => {

View File

@ -687,6 +687,19 @@ fn accept_invite(_org_id: String, _org_user_id: String, data: JsonUpcase<AcceptD
err!("User already accepted the invitation")
}
let user_twofactor_disabled = TwoFactor::find_by_user(&user_org.user_uuid, &conn).is_empty();
let policy = OrgPolicyType::TwoFactorAuthentication as i32;
let org_twofactor_policy_enabled =
match OrgPolicy::find_by_org_and_type(&user_org.org_uuid, policy, &conn) {
Some(p) => p.enabled,
None => false,
};
if org_twofactor_policy_enabled && user_twofactor_disabled {
err!("You cannot join this organization until you enable two-step login on your user account.")
}
user_org.status = UserOrgStatus::Accepted as i32;
user_org.save(&conn)?;
}
@ -1039,6 +1052,24 @@ fn put_policy(
None => err!("Invalid policy type"),
};
if pol_type_enum == OrgPolicyType::TwoFactorAuthentication && data.enabled {
let org_list = UserOrganization::find_by_org(&org_id, &conn);
for user_org in org_list.into_iter() {
let user_twofactor_disabled = TwoFactor::find_by_user(&user_org.user_uuid, &conn).is_empty();
if user_twofactor_disabled && user_org.atype < UserOrgType::Admin {
if CONFIG.mail_enabled() {
let org = Organization::find_by_uuid(&user_org.org_uuid, &conn).unwrap();
let user = User::find_by_uuid(&user_org.user_uuid, &conn).unwrap();
mail::send_2fa_removed_from_org(&user.email, &org.name)?;
}
user_org.delete(&conn)?;
}
}
}
let mut policy = match OrgPolicy::find_by_org_and_type(&org_id, pol_type, &conn) {
Some(p) => p,
None => OrgPolicy::new(org_id, pol_type_enum, "{}".to_string()),

View File

@ -10,6 +10,7 @@ use crate::{
api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, Notify, UpdateType},
auth::{Headers, Host},
db::{models::*, DbConn, DbPool},
util::SafeString,
CONFIG,
};
@ -173,7 +174,7 @@ fn post_send_file(data: Data, content_type: &ContentType, headers: Headers, conn
Some(limit_kb) => {
let left = (limit_kb * 1024) - Attachment::size_by_user(&headers.user.uuid, &conn);
if left <= 0 {
err!("Attachment size limit reached! Delete some files to open space")
err!("Attachment storage limit reached! Delete some attachments to free up space")
}
std::cmp::Ord::max(left as u64, SIZE_525_MB)
}
@ -205,7 +206,7 @@ fn post_send_file(data: Data, content_type: &ContentType, headers: Headers, conn
}
SaveResult::Partial(_, reason) => {
std::fs::remove_file(&file_path).ok();
err!(format!("Attachment size limit exceeded with this file: {:?}", reason));
err!(format!("Attachment storage limit exceeded with this file: {:?}", reason));
}
SaveResult::Error(e) => {
std::fs::remove_file(&file_path).ok();
@ -335,7 +336,7 @@ fn post_access_file(
}
#[get("/sends/<send_id>/<file_id>?<t>")]
fn download_send(send_id: String, file_id: String, t: String) -> Option<NamedFile> {
fn download_send(send_id: SafeString, file_id: SafeString, t: String) -> Option<NamedFile> {
if let Ok(claims) = crate::auth::decode_send(&t) {
if claims.sub == format!("{}/{}", send_id, file_id) {
return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(send_id).join(file_id)).ok();

View File

@ -7,10 +7,8 @@ use crate::{
api::{JsonResult, JsonUpcase, NumberOrString, PasswordData},
auth::Headers,
crypto,
db::{
models::{TwoFactor, User},
DbConn,
},
db::{models::*, DbConn},
mail, CONFIG,
};
pub mod authenticator;
@ -130,6 +128,23 @@ fn disable_twofactor(data: JsonUpcase<DisableTwoFactorData>, headers: Headers, c
twofactor.delete(&conn)?;
}
let twofactor_disabled = TwoFactor::find_by_user(&user.uuid, &conn).is_empty();
if twofactor_disabled {
let policy_type = OrgPolicyType::TwoFactorAuthentication;
let org_list = UserOrganization::find_by_user_and_policy(&user.uuid, policy_type, &conn);
for user_org in org_list.into_iter() {
if user_org.atype < UserOrgType::Admin {
if CONFIG.mail_enabled() {
let org = Organization::find_by_uuid(&user_org.org_uuid, &conn).unwrap();
mail::send_2fa_removed_from_org(&user.email, &org.name)?;
}
user_org.delete(&conn)?;
}
}
}
Ok(Json(json!({
"Enabled": false,
"Type": type_,