aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock36
-rw-r--r--src/api/admin.rs15
-rw-r--r--src/api/core/accounts.rs96
-rw-r--r--src/api/core/ciphers.rs104
-rw-r--r--src/api/core/emergency_access.rs170
-rw-r--r--src/api/core/folders.rs30
-rw-r--r--src/api/core/organizations.rs296
-rw-r--r--src/api/core/public.rs15
-rw-r--r--src/api/core/sends.rs69
-rw-r--r--src/api/core/two_factor/authenticator.rs5
-rw-r--r--src/api/core/two_factor/duo.rs15
-rw-r--r--src/api/core/two_factor/email.rs17
-rw-r--r--src/api/core/two_factor/mod.rs5
-rw-r--r--src/api/core/two_factor/webauthn.rs15
-rw-r--r--src/api/identity.rs38
-rw-r--r--src/api/push.rs9
-rw-r--r--src/auth.rs20
-rw-r--r--src/db/models/auth_request.rs11
-rw-r--r--src/db/models/folder.rs3
-rw-r--r--src/db/models/group.rs3
-rw-r--r--src/db/models/org_policy.rs10
-rw-r--r--src/db/models/send.rs16
-rw-r--r--src/mail.rs10
23 files changed, 414 insertions, 594 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2107b75c..2f920b18 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -489,9 +489,9 @@ checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
[[package]]
name = "cc"
-version = "1.2.3"
+version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d"
+checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf"
dependencies = [
"shlex",
]
@@ -1524,7 +1524,7 @@ dependencies = [
"http 1.2.0",
"hyper 1.5.1",
"hyper-util",
- "rustls 0.23.19",
+ "rustls 0.23.20",
"rustls-pki-types",
"tokio",
"tokio-rustls 0.26.1",
@@ -2618,9 +2618,9 @@ dependencies = [
[[package]]
name = "quanta"
-version = "0.12.3"
+version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5"
+checksum = "773ce68d0bb9bc7ef20be3536ffe94e223e1f365bd374108b2659fac0c65cfe6"
dependencies = [
"crossbeam-utils",
"libc",
@@ -2704,9 +2704,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.5.7"
+version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
+checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [
"bitflags",
]
@@ -3031,9 +3031,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.23.19"
+version = "0.23.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1"
+checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b"
dependencies = [
"once_cell",
"rustls-pki-types",
@@ -3062,9 +3062,9 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
-version = "1.10.0"
+version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
+checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37"
[[package]]
name = "rustls-webpki"
@@ -3173,15 +3173,15 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.23"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
[[package]]
name = "serde"
-version = "1.0.215"
+version = "1.0.216"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
+checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
dependencies = [
"serde_derive",
]
@@ -3198,9 +3198,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.215"
+version = "1.0.216"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
+checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
dependencies = [
"proc-macro2",
"quote",
@@ -3652,7 +3652,7 @@ version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
dependencies = [
- "rustls 0.23.19",
+ "rustls 0.23.20",
"tokio",
]
diff --git a/src/api/admin.rs b/src/api/admin.rs
index 45eb5972..f49f6ed3 100644
--- a/src/api/admin.rs
+++ b/src/api/admin.rs
@@ -495,11 +495,11 @@ struct UserOrgTypeData {
async fn update_user_org_type(data: Json<UserOrgTypeData>, token: AdminToken, mut conn: DbConn) -> EmptyResult {
let data: UserOrgTypeData = data.into_inner();
- let mut user_to_edit =
- match UserOrganization::find_by_user_and_org(&data.user_uuid, &data.org_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("The specified user isn't member of the organization"),
- };
+ let Some(mut user_to_edit) =
+ UserOrganization::find_by_user_and_org(&data.user_uuid, &data.org_uuid, &mut conn).await
+ else {
+ err!("The specified user isn't member of the organization")
+ };
let new_type = match UserOrgType::from_str(&data.user_type.into_string()) {
Some(new_type) => new_type as i32,
@@ -602,9 +602,8 @@ async fn get_json_api<T: DeserializeOwned>(url: &str) -> Result<T, Error> {
}
async fn has_http_access() -> bool {
- let req = match make_http_request(Method::HEAD, "https://github.com/dani-garcia/vaultwarden") {
- Ok(r) => r,
- Err(_) => return false,
+ let Ok(req) = make_http_request(Method::HEAD, "https://github.com/dani-garcia/vaultwarden") else {
+ return false;
};
match req.send().await {
Ok(r) => r.status().is_success(),
diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs
index 87e44529..d95a50b8 100644
--- a/src/api/core/accounts.rs
+++ b/src/api/core/accounts.rs
@@ -574,9 +574,8 @@ async fn post_rotatekey(data: Json<KeyData>, headers: Headers, mut conn: DbConn,
// Skip `null` folder id entries.
// See: https://github.com/bitwarden/clients/issues/8453
if let Some(folder_id) = folder_data.id {
- let saved_folder = match existing_folders.iter_mut().find(|f| f.uuid == folder_id) {
- Some(folder) => folder,
- None => err!("Folder doesn't exist"),
+ let Some(saved_folder) = existing_folders.iter_mut().find(|f| f.uuid == folder_id) else {
+ err!("Folder doesn't exist")
};
saved_folder.name = folder_data.name;
@@ -586,11 +585,11 @@ async fn post_rotatekey(data: Json<KeyData>, headers: Headers, mut conn: DbConn,
// Update emergency access data
for emergency_access_data in data.emergency_access_keys {
- let saved_emergency_access =
- match existing_emergency_access.iter_mut().find(|ea| ea.uuid == emergency_access_data.id) {
- Some(emergency_access) => emergency_access,
- None => err!("Emergency access doesn't exist or is not owned by the user"),
- };
+ let Some(saved_emergency_access) =
+ existing_emergency_access.iter_mut().find(|ea| ea.uuid == emergency_access_data.id)
+ else {
+ err!("Emergency access doesn't exist or is not owned by the user")
+ };
saved_emergency_access.key_encrypted = Some(emergency_access_data.key_encrypted);
saved_emergency_access.save(&mut conn).await?
@@ -598,10 +597,10 @@ async fn post_rotatekey(data: Json<KeyData>, headers: Headers, mut conn: DbConn,
// Update reset password data
for reset_password_data in data.reset_password_keys {
- let user_org = match existing_user_orgs.iter_mut().find(|uo| uo.org_uuid == reset_password_data.organization_id)
- {
- Some(reset_password) => reset_password,
- None => err!("Reset password doesn't exist"),
+ let Some(user_org) =
+ existing_user_orgs.iter_mut().find(|uo| uo.org_uuid == reset_password_data.organization_id)
+ else {
+ err!("Reset password doesn't exist")
};
user_org.reset_password_key = Some(reset_password_data.reset_password_key);
@@ -610,9 +609,8 @@ async fn post_rotatekey(data: Json<KeyData>, headers: Headers, mut conn: DbConn,
// Update send data
for send_data in data.sends {
- let send = match existing_sends.iter_mut().find(|s| &s.uuid == send_data.id.as_ref().unwrap()) {
- Some(send) => send,
- None => err!("Send doesn't exist"),
+ let Some(send) = existing_sends.iter_mut().find(|s| &s.uuid == send_data.id.as_ref().unwrap()) else {
+ err!("Send doesn't exist")
};
update_send_from_data(send, send_data, &headers, &mut conn, &nt, UpdateType::None).await?;
@@ -623,9 +621,9 @@ async fn post_rotatekey(data: Json<KeyData>, headers: Headers, mut conn: DbConn,
for cipher_data in data.ciphers {
if cipher_data.organization_id.is_none() {
- let saved_cipher = match existing_ciphers.iter_mut().find(|c| &c.uuid == cipher_data.id.as_ref().unwrap()) {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(saved_cipher) = existing_ciphers.iter_mut().find(|c| &c.uuid == cipher_data.id.as_ref().unwrap())
+ else {
+ err!("Cipher doesn't exist")
};
// Prevent triggering cipher updates via WebSockets by settings UpdateType::None
@@ -802,14 +800,12 @@ struct VerifyEmailTokenData {
async fn post_verify_email_token(data: Json<VerifyEmailTokenData>, mut conn: DbConn) -> EmptyResult {
let data: VerifyEmailTokenData = data.into_inner();
- let mut user = match User::find_by_uuid(&data.user_id, &mut conn).await {
- Some(user) => user,
- None => err!("User doesn't exist"),
+ let Some(mut user) = User::find_by_uuid(&data.user_id, &mut conn).await else {
+ err!("User doesn't exist")
};
- let claims = match decode_verify_email(&data.token) {
- Ok(claims) => claims,
- Err(_) => err!("Invalid claim"),
+ let Ok(claims) = decode_verify_email(&data.token) else {
+ err!("Invalid claim")
};
if claims.sub != user.uuid {
err!("Invalid claim");
@@ -861,15 +857,14 @@ struct DeleteRecoverTokenData {
async fn post_delete_recover_token(data: Json<DeleteRecoverTokenData>, mut conn: DbConn) -> EmptyResult {
let data: DeleteRecoverTokenData = data.into_inner();
- let user = match User::find_by_uuid(&data.user_id, &mut conn).await {
- Some(user) => user,
- None => err!("User doesn't exist"),
+ let Ok(claims) = decode_delete(&data.token) else {
+ err!("Invalid claim")
};
- let claims = match decode_delete(&data.token) {
- Ok(claims) => claims,
- Err(_) => err!("Invalid claim"),
+ let Some(user) = User::find_by_uuid(&data.user_id, &mut conn).await else {
+ err!("User doesn't exist")
};
+
if claims.sub != user.uuid {
err!("Invalid claim");
}
@@ -1041,11 +1036,8 @@ impl<'r> FromRequest<'r> for KnownDevice {
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let email = if let Some(email_b64) = req.headers().get_one("X-Request-Email") {
- let email_bytes = match data_encoding::BASE64URL_NOPAD.decode(email_b64.as_bytes()) {
- Ok(bytes) => bytes,
- Err(_) => {
- return Outcome::Error((Status::BadRequest, "X-Request-Email value failed to decode as base64url"));
- }
+ let Ok(email_bytes) = data_encoding::BASE64URL_NOPAD.decode(email_b64.as_bytes()) else {
+ return Outcome::Error((Status::BadRequest, "X-Request-Email value failed to decode as base64url"));
};
match String::from_utf8(email_bytes) {
Ok(email) => email,
@@ -1086,9 +1078,9 @@ async fn put_device_token(uuid: &str, data: Json<PushToken>, headers: Headers, m
let data = data.into_inner();
let token = data.push_token;
- let mut device = match Device::find_by_uuid_and_user(&headers.device.uuid, &headers.user.uuid, &mut conn).await {
- Some(device) => device,
- None => err!(format!("Error: device {uuid} should be present before a token can be assigned")),
+ let Some(mut device) = Device::find_by_uuid_and_user(&headers.device.uuid, &headers.user.uuid, &mut conn).await
+ else {
+ err!(format!("Error: device {uuid} should be present before a token can be assigned"))
};
// if the device already has been registered
@@ -1159,9 +1151,8 @@ async fn post_auth_request(
) -> JsonResult {
let data = data.into_inner();
- let user = match User::find_by_mail(&data.email, &mut conn).await {
- Some(user) => user,
- None => err!("AuthRequest doesn't exist", "User not found"),
+ let Some(user) = User::find_by_mail(&data.email, &mut conn).await else {
+ err!("AuthRequest doesn't exist", "User not found")
};
// Validate device uuid and type
@@ -1199,15 +1190,10 @@ async fn post_auth_request(
#[get("/auth-requests/<uuid>")]
async fn get_auth_request(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
- let auth_request = match AuthRequest::find_by_uuid(uuid, &mut conn).await {
- Some(auth_request) => auth_request,
- None => err!("AuthRequest doesn't exist", "Record not found"),
+ let Some(auth_request) = AuthRequest::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
+ err!("AuthRequest doesn't exist", "Record not found or user uuid does not match")
};
- if headers.user.uuid != auth_request.user_uuid {
- err!("AuthRequest doesn't exist", "User uuid's do not match")
- }
-
let response_date_utc = auth_request.response_date.map(|response_date| format_date(&response_date));
Ok(Json(json!({
@@ -1244,15 +1230,10 @@ async fn put_auth_request(
nt: Notify<'_>,
) -> JsonResult {
let data = data.into_inner();
- let mut auth_request: AuthRequest = match AuthRequest::find_by_uuid(uuid, &mut conn).await {
- Some(auth_request) => auth_request,
- None => err!("AuthRequest doesn't exist", "Record not found"),
+ let Some(mut auth_request) = AuthRequest::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
+ err!("AuthRequest doesn't exist", "Record not found or user uuid does not match")
};
- if headers.user.uuid != auth_request.user_uuid {
- err!("AuthRequest doesn't exist", "User uuid's do not match")
- }
-
if auth_request.approved.is_some() {
err!("An authentication request with the same device already exists")
}
@@ -1297,9 +1278,8 @@ async fn get_auth_request_response(
client_headers: ClientHeaders,
mut conn: DbConn,
) -> JsonResult {
- let auth_request = match AuthRequest::find_by_uuid(uuid, &mut conn).await {
- Some(auth_request) => auth_request,
- None => err!("AuthRequest doesn't exist", "User not found"),
+ let Some(auth_request) = AuthRequest::find_by_uuid(uuid, &mut conn).await else {
+ err!("AuthRequest doesn't exist", "User not found")
};
if auth_request.device_type != client_headers.device_type
diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs
index 46d65b53..136b890a 100644
--- a/src/api/core/ciphers.rs
+++ b/src/api/core/ciphers.rs
@@ -193,9 +193,8 @@ async fn get_ciphers(headers: Headers, mut conn: DbConn) -> Json<Value> {
#[get("/ciphers/<uuid>")]
async fn get_cipher(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
- let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(cipher) = Cipher::find_by_uuid(uuid, &mut conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_accessible_to_user(&headers.user.uuid, &mut conn).await {
@@ -429,14 +428,9 @@ pub async fn update_cipher_from_data(
cipher.user_uuid = Some(headers.user.uuid.clone());
}
- if let Some(ref folder_id) = data.folder_id {
- match Folder::find_by_uuid(folder_id, conn).await {
- Some(folder) => {
- if folder.user_uuid != headers.user.uuid {
- err!("Folder is not owned by user")
- }
- }
- None => err!("Folder doesn't exist"),
+ if let Some(ref folder_uuid) = data.folder_id {
+ if Folder::find_by_uuid_and_user(folder_uuid, &headers.user.uuid, conn).await.is_none() {
+ err!("Invalid folder", "Folder does not exist or belongs to another user");
}
}
@@ -661,9 +655,8 @@ async fn put_cipher(
) -> JsonResult {
let data: CipherData = data.into_inner();
- let mut cipher = match Cipher::find_by_uuid(uuid, &mut conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(mut cipher) = Cipher::find_by_uuid(uuid, &mut conn).await else {
+ err!("Cipher doesn't exist")
};
// TODO: Check if only the folder ID or favorite status is being changed.
@@ -695,19 +688,13 @@ async fn put_cipher_partial(
) -> JsonResult {
let data: PartialCipherData = data.into_inner();
- let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(cipher) = Cipher::find_by_uuid(uuid, &mut conn).await else {
+ err!("Cipher doesn't exist")
};
- if let Some(ref folder_id) = data.folder_id {
- match Folder::find_by_uuid(folder_id, &mut conn).await {
- Some(folder) => {
- if folder.user_uuid != headers.user.uuid {
- err!("Folder is not owned by user")
- }
- }
- None => err!("Folder doesn't exist"),
+ if let Some(ref folder_uuid) = data.folder_id {
+ if Folder::find_by_uuid_and_user(folder_uuid, &headers.user.uuid, &mut conn).await.is_none() {
+ err!("Invalid folder", "Folder does not exist or belongs to another user");
}
}
@@ -774,9 +761,8 @@ async fn post_collections_update(
) -> JsonResult {
let data: CollectionsAdminData = data.into_inner();
- let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(cipher) = Cipher::find_by_uuid(uuid, &mut conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_write_accessible_to_user(&headers.user.uuid, &mut conn).await {
@@ -788,7 +774,8 @@ async fn post_collections_update(
HashSet::<String>::from_iter(cipher.get_collections(headers.user.uuid.clone(), &mut conn).await);
for collection in posted_collections.symmetric_difference(&current_collections) {
- match Collection::find_by_uuid(collection, &mut conn).await {
+ match Collection::find_by_uuid_and_org(collection, cipher.organization_uuid.as_ref().unwrap(), &mut conn).await
+ {
None => err!("Invalid collection ID provided"),
Some(collection) => {
if collection.is_writable_by_user(&headers.user.uuid, &mut conn).await {
@@ -851,9 +838,8 @@ async fn post_collections_admin(
) -> EmptyResult {
let data: CollectionsAdminData = data.into_inner();
- let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(cipher) = Cipher::find_by_uuid(uuid, &mut conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_write_accessible_to_user(&headers.user.uuid, &mut conn).await {
@@ -865,7 +851,8 @@ async fn post_collections_admin(
HashSet::<String>::from_iter(cipher.get_admin_collections(headers.user.uuid.clone(), &mut conn).await);
for collection in posted_collections.symmetric_difference(&current_collections) {
- match Collection::find_by_uuid(collection, &mut conn).await {
+ match Collection::find_by_uuid_and_org(collection, cipher.organization_uuid.as_ref().unwrap(), &mut conn).await
+ {
None => err!("Invalid collection ID provided"),
Some(collection) => {
if collection.is_writable_by_user(&headers.user.uuid, &mut conn).await {
@@ -1043,9 +1030,8 @@ async fn share_cipher_by_uuid(
/// redirects to the same location as before the v2 API.
#[get("/ciphers/<uuid>/attachment/<attachment_id>")]
async fn get_attachment(uuid: &str, attachment_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
- let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(cipher) = Cipher::find_by_uuid(uuid, &mut conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_accessible_to_user(&headers.user.uuid, &mut conn).await {
@@ -1084,9 +1070,8 @@ async fn post_attachment_v2(
headers: Headers,
mut conn: DbConn,
) -> JsonResult {
- let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(cipher) = Cipher::find_by_uuid(uuid, &mut conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_write_accessible_to_user(&headers.user.uuid, &mut conn).await {
@@ -1150,9 +1135,8 @@ async fn save_attachment(
err!("Attachment size can't be negative")
}
- let cipher = match Cipher::find_by_uuid(cipher_uuid, &mut conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(cipher) = Cipher::find_by_uuid(cipher_uuid, &mut conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_write_accessible_to_user(&headers.user.uuid, &mut conn).await {
@@ -1545,21 +1529,15 @@ async fn move_cipher_selected(
let data = data.into_inner();
let user_uuid = headers.user.uuid;
- if let Some(ref folder_id) = data.folder_id {
- match Folder::find_by_uuid(folder_id, &mut conn).await {
- Some(folder) => {
- if folder.user_uuid != user_uuid {
- err!("Folder is not owned by user")
- }
- }
- None => err!("Folder doesn't exist"),
+ if let Some(ref folder_uuid) = data.folder_id {
+ if Folder::find_by_uuid_and_user(folder_uuid, &user_uuid, &mut conn).await.is_none() {
+ err!("Invalid folder", "Folder does not exist or belongs to another user");
}
}
for uuid in data.ids {
- let cipher = match Cipher::find_by_uuid(&uuid, &mut conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(cipher) = Cipher::find_by_uuid(&uuid, &mut conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_accessible_to_user(&user_uuid, &mut conn).await {
@@ -1667,9 +1645,8 @@ async fn _delete_cipher_by_uuid(
soft_delete: bool,
nt: &Notify<'_>,
) -> EmptyResult {
- let mut cipher = match Cipher::find_by_uuid(uuid, conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(mut cipher) = Cipher::find_by_uuid(uuid, conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_write_accessible_to_user(&headers.user.uuid, conn).await {
@@ -1739,9 +1716,8 @@ async fn _delete_multiple_ciphers(
}
async fn _restore_cipher_by_uuid(uuid: &str, headers: &Headers, conn: &mut DbConn, nt: &Notify<'_>) -> JsonResult {
- let mut cipher = match Cipher::find_by_uuid(uuid, conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(mut cipher) = Cipher::find_by_uuid(uuid, conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_write_accessible_to_user(&headers.user.uuid, conn).await {
@@ -1807,18 +1783,16 @@ async fn _delete_cipher_attachment_by_id(
conn: &mut DbConn,
nt: &Notify<'_>,
) -> EmptyResult {
- let attachment = match Attachment::find_by_id(attachment_id, conn).await {
- Some(attachment) => attachment,
- None => err!("Attachment doesn't exist"),
+ let Some(attachment) = Attachment::find_by_id(attachment_id, conn).await else {
+ err!("Attachment doesn't exist")
};
if attachment.cipher_uuid != uuid {
err!("Attachment from other cipher")
}
- let cipher = match Cipher::find_by_uuid(uuid, conn).await {
- Some(cipher) => cipher,
- None => err!("Cipher doesn't exist"),
+ let Some(cipher) = Cipher::find_by_uuid(uuid, conn).await else {
+ err!("Cipher doesn't exist")
};
if !cipher.is_write_accessible_to_user(&headers.user.uuid, conn).await {
diff --git a/src/api/core/emergency_access.rs b/src/api/core/emergency_access.rs
index 1c29b774..8ed9e87a 100644
--- a/src/api/core/emergency_access.rs
+++ b/src/api/core/emergency_access.rs
@@ -137,11 +137,11 @@ async fn post_emergency_access(
let data: EmergencyAccessUpdateData = data.into_inner();
- let mut emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &headers.user.uuid, &mut conn).await {
- Some(emergency_access) => emergency_access,
- None => err!("Emergency access not valid."),
- };
+ let Some(mut emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &headers.user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
let new_type = match EmergencyAccessType::from_str(&data.r#type.into_string()) {
Some(new_type) => new_type as i32,
@@ -284,24 +284,22 @@ async fn send_invite(data: Json<EmergencyAccessInviteData>, headers: Headers, mu
async fn resend_invite(emer_id: &str, headers: Headers, mut conn: DbConn) -> EmptyResult {
check_emergency_access_enabled()?;
- let mut emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &headers.user.uuid, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(mut emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &headers.user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
if emergency_access.status != EmergencyAccessStatus::Invited as i32 {
err!("The grantee user is already accepted or confirmed to the organization");
}
- let email = match emergency_access.email.clone() {
- Some(email) => email,
- None => err!("Email not valid."),
+ let Some(email) = emergency_access.email.clone() else {
+ err!("Email not valid.")
};
- let grantee_user = match User::find_by_mail(&email, &mut conn).await {
- Some(user) => user,
- None => err!("Grantee user not found."),
+ let Some(grantee_user) = User::find_by_mail(&email, &mut conn).await else {
+ err!("Grantee user not found.")
};
let grantor_user = headers.user;
@@ -356,16 +354,15 @@ async fn accept_invite(emer_id: &str, data: Json<AcceptData>, headers: Headers,
// We need to search for the uuid in combination with the email, since we do not yet store the uuid of the grantee in the database.
// The uuid of the grantee gets stored once accepted.
- let mut emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantee_email(emer_id, &headers.user.email, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(mut emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantee_email(emer_id, &headers.user.email, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
// get grantor user to send Accepted email
- let grantor_user = match User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantor user not found."),
+ let Some(grantor_user) = User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await else {
+ err!("Grantor user not found.")
};
if emer_id == claims.emer_id
@@ -403,11 +400,11 @@ async fn confirm_emergency_access(
let data: ConfirmData = data.into_inner();
let key = data.key;
- let mut emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &confirming_user.uuid, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(mut emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &confirming_user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
if emergency_access.status != EmergencyAccessStatus::Accepted as i32
|| emergency_access.grantor_uuid != confirming_user.uuid
@@ -415,15 +412,13 @@ async fn confirm_emergency_access(
err!("Emergency access not valid.")
}
- let grantor_user = match User::find_by_uuid(&confirming_user.uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantor user not found."),
+ let Some(grantor_user) = User::find_by_uuid(&confirming_user.uuid, &mut conn).await else {
+ err!("Grantor user not found.")
};
if let Some(grantee_uuid) = emergency_access.grantee_uuid.as_ref() {
- let grantee_user = match User::find_by_uuid(grantee_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantee user not found."),
+ let Some(grantee_user) = User::find_by_uuid(grantee_uuid, &mut conn).await else {
+ err!("Grantee user not found.")
};
emergency_access.status = EmergencyAccessStatus::Confirmed as i32;
@@ -450,19 +445,18 @@ async fn initiate_emergency_access(emer_id: &str, headers: Headers, mut conn: Db
check_emergency_access_enabled()?;
let initiating_user = headers.user;
- let mut emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &initiating_user.uuid, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(mut emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &initiating_user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
if emergency_access.status != EmergencyAccessStatus::Confirmed as i32 {
err!("Emergency access not valid.")
}
- let grantor_user = match User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantor user not found."),
+ let Some(grantor_user) = User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await else {
+ err!("Grantor user not found.")
};
let now = Utc::now().naive_utc();
@@ -488,25 +482,23 @@ async fn initiate_emergency_access(emer_id: &str, headers: Headers, mut conn: Db
async fn approve_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
check_emergency_access_enabled()?;
- let mut emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &headers.user.uuid, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(mut emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &headers.user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
if emergency_access.status != EmergencyAccessStatus::RecoveryInitiated as i32 {
err!("Emergency access not valid.")
}
- let grantor_user = match User::find_by_uuid(&headers.user.uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantor user not found."),
+ let Some(grantor_user) = User::find_by_uuid(&headers.user.uuid, &mut conn).await else {
+ err!("Grantor user not found.")
};
if let Some(grantee_uuid) = emergency_access.grantee_uuid.as_ref() {
- let grantee_user = match User::find_by_uuid(grantee_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantee user not found."),
+ let Some(grantee_user) = User::find_by_uuid(grantee_uuid, &mut conn).await else {
+ err!("Grantee user not found.")
};
emergency_access.status = EmergencyAccessStatus::RecoveryApproved as i32;
@@ -525,11 +517,11 @@ async fn approve_emergency_access(emer_id: &str, headers: Headers, mut conn: DbC
async fn reject_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
check_emergency_access_enabled()?;
- let mut emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &headers.user.uuid, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(mut emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantor_uuid(emer_id, &headers.user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
if emergency_access.status != EmergencyAccessStatus::RecoveryInitiated as i32
&& emergency_access.status != EmergencyAccessStatus::RecoveryApproved as i32
@@ -538,9 +530,8 @@ async fn reject_emergency_access(emer_id: &str, headers: Headers, mut conn: DbCo
}
if let Some(grantee_uuid) = emergency_access.grantee_uuid.as_ref() {
- let grantee_user = match User::find_by_uuid(grantee_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantee user not found."),
+ let Some(grantee_user) = User::find_by_uuid(grantee_uuid, &mut conn).await else {
+ err!("Grantee user not found.")
};
emergency_access.status = EmergencyAccessStatus::Confirmed as i32;
@@ -563,11 +554,11 @@ async fn reject_emergency_access(emer_id: &str, headers: Headers, mut conn: DbCo
async fn view_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
check_emergency_access_enabled()?;
- let emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &headers.user.uuid, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &headers.user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
if !is_valid_request(&emergency_access, &headers.user.uuid, EmergencyAccessType::View) {
err!("Emergency access not valid.")
@@ -602,19 +593,18 @@ async fn takeover_emergency_access(emer_id: &str, headers: Headers, mut conn: Db
check_emergency_access_enabled()?;
let requesting_user = headers.user;
- let emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &requesting_user.uuid, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &requesting_user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
if !is_valid_request(&emergency_access, &requesting_user.uuid, EmergencyAccessType::Takeover) {
err!("Emergency access not valid.")
}
- let grantor_user = match User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantor user not found."),
+ let Some(grantor_user) = User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await else {
+ err!("Grantor user not found.")
};
let result = json!({
@@ -650,19 +640,18 @@ async fn password_emergency_access(
//let key = &data.Key;
let requesting_user = headers.user;
- let emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &requesting_user.uuid, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &requesting_user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
if !is_valid_request(&emergency_access, &requesting_user.uuid, EmergencyAccessType::Takeover) {
err!("Emergency access not valid.")
}
- let mut grantor_user = match User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantor user not found."),
+ let Some(mut grantor_user) = User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await else {
+ err!("Grantor user not found.")
};
// change grantor_user password
@@ -686,19 +675,18 @@ async fn password_emergency_access(
#[get("/emergency-access/<emer_id>/policies")]
async fn policies_emergency_access(emer_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
let requesting_user = headers.user;
- let emergency_access =
- match EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &requesting_user.uuid, &mut conn).await {
- Some(emer) => emer,
- None => err!("Emergency access not valid."),
- };
+ let Some(emergency_access) =
+ EmergencyAccess::find_by_uuid_and_grantee_uuid(emer_id, &requesting_user.uuid, &mut conn).await
+ else {
+ err!("Emergency access not valid.")
+ };
if !is_valid_request(&emergency_access, &requesting_user.uuid, EmergencyAccessType::Takeover) {
err!("Emergency access not valid.")
}
- let grantor_user = match User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("Grantor user not found."),
+ let Some(grantor_user) = User::find_by_uuid(&emergency_access.grantor_uuid, &mut conn).await else {
+ err!("Grantor user not found.")
};
let policies = OrgPolicy::find_confirmed_by_user(&grantor_user.uuid, &mut conn);
diff --git a/src/api/core/folders.rs b/src/api/core/folders.rs
index 9766d7a1..3daa2a06 100644
--- a/src/api/core/folders.rs
+++ b/src/api/core/folders.rs
@@ -25,16 +25,10 @@ async fn get_folders(headers: Headers, mut conn: DbConn) -> Json<Value> {
#[get("/folders/<uuid>")]
async fn get_folder(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
- let folder = match Folder::find_by_uuid(uuid, &mut conn).await {
- Some(folder) => folder,
- _ => err!("Invalid folder"),
- };
-
- if folder.user_uuid != headers.user.uuid {
- err!("Folder belongs to another user")
+ match Folder::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await {
+ Some(folder) => Ok(Json(folder.to_json())),
+ _ => err!("Invalid folder", "Folder does not exist or belongs to another user"),
}
-
- Ok(Json(folder.to_json()))
}
#[derive(Deserialize)]
@@ -71,15 +65,10 @@ async fn put_folder(
) -> JsonResult {
let data: FolderData = data.into_inner();
- let mut folder = match Folder::find_by_uuid(uuid, &mut conn).await {
- Some(folder) => folder,
- _ => err!("Invalid folder"),
+ let Some(mut folder) = Folder::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
+ err!("Invalid folder", "Folder does not exist or belongs to another user")
};
- if folder.user_uuid != headers.user.uuid {
- err!("Folder belongs to another user")
- }
-
folder.name = data.name;
folder.save(&mut conn).await?;
@@ -95,15 +84,10 @@ async fn delete_folder_post(uuid: &str, headers: Headers, conn: DbConn, nt: Noti
#[delete("/folders/<uuid>")]
async fn delete_folder(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
- let folder = match Folder::find_by_uuid(uuid, &mut conn).await {
- Some(folder) => folder,
- _ => err!("Invalid folder"),
+ let Some(folder) = Folder::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
+ err!("Invalid folder", "Folder does not exist or belongs to another user")
};
- if folder.user_uuid != headers.user.uuid {
- err!("Folder belongs to another user")
- }
-
// Delete the actual folder entry
folder.delete(&mut conn).await?;
diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs
index 2bff64b8..f3158536 100644
--- a/src/api/core/organizations.rs
+++ b/src/api/core/organizations.rs
@@ -267,9 +267,8 @@ async fn post_organization(
) -> JsonResult {
let data: OrganizationUpdateData = data.into_inner();
- let mut org = match Organization::find_by_uuid(org_id, &mut conn).await {
- Some(organization) => organization,
- None => err!("Can't find organization details"),
+ let Some(mut org) = Organization::find_by_uuid(org_id, &mut conn).await else {
+ err!("Can't find organization details")
};
org.name = data.name;
@@ -318,9 +317,8 @@ async fn get_org_collections(org_id: &str, _headers: ManagerHeadersLoose, mut co
async fn get_org_collections_details(org_id: &str, headers: ManagerHeadersLoose, mut conn: DbConn) -> JsonResult {
let mut data = Vec::new();
- let user_org = match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await {
- Some(u) => u,
- None => err!("User is not part of organization"),
+ let Some(user_org) = UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await else {
+ err!("User is not part of organization")
};
// get all collection memberships for the current organization
@@ -387,9 +385,8 @@ async fn post_organization_collections(
) -> JsonResult {
let data: NewCollectionData = data.into_inner();
- let org = match Organization::find_by_uuid(org_id, &mut conn).await {
- Some(organization) => organization,
- None => err!("Can't find organization details"),
+ let Some(org) = Organization::find_by_uuid(org_id, &mut conn).await else {
+ err!("Can't find organization details")
};
let collection = Collection::new(org.uuid, data.name, data.external_id);
@@ -413,9 +410,8 @@ async fn post_organization_collections(
}
for user in data.users {
- let org_user = match UserOrganization::find_by_uuid(&user.id, &mut conn).await {
- Some(u) => u,
- None => err!("User is not part of organization"),
+ let Some(org_user) = UserOrganization::find_by_uuid_and_org(&user.id, org_id, &mut conn).await else {
+ err!("User is not part of organization")
};
if org_user.access_all {
@@ -454,20 +450,14 @@ async fn post_organization_collection_update(
) -> JsonResult {
let data: NewCollectionData = data.into_inner();
- let org = match Organization::find_by_uuid(org_id, &mut conn).await {
- Some(organization) => organization,
- None => err!("Can't find organization details"),
+ if Organization::find_by_uuid(org_id, &mut conn).await.is_none() {
+ err!("Can't find organization details")
};
- let mut collection = match Collection::find_by_uuid(col_id, &mut conn).await {
- Some(collection) => collection,
- None => err!("Collection not found"),
+ let Some(mut collection) = Collection::find_by_uuid_and_org(col_id, org_id, &mut conn).await else {
+ err!("Collection not found")
};
- if collection.org_uuid != org.uuid {
- err!("Collection is not owned by organization");
- }
-
collection.name = data.name;
collection.external_id = match data.external_id {
Some(external_id) if !external_id.trim().is_empty() => Some(external_id),
@@ -498,9 +488,8 @@ async fn post_organization_collection_update(
CollectionUser::delete_all_by_collection(col_id, &mut conn).await?;
for user in data.users {
- let org_user = match UserOrganization::find_by_uuid(&user.id, &mut conn).await {
- Some(u) => u,
- None => err!("User is not part of organization"),
+ let Some(org_user) = UserOrganization::find_by_uuid_and_org(&user.id, org_id, &mut conn).await else {
+ err!("User is not part of organization")
};
if org_user.access_all {
@@ -521,15 +510,8 @@ async fn delete_organization_collection_user(
_headers: AdminHeaders,
mut conn: DbConn,
) -> EmptyResult {
- let collection = match Collection::find_by_uuid(col_id, &mut conn).await {
- None => err!("Collection not found"),
- Some(collection) => {
- if collection.org_uuid == org_id {
- collection
- } else {
- err!("Collection and Organization id do not match")
- }
- }
+ let Some(collection) = Collection::find_by_uuid_and_org(col_id, org_id, &mut conn).await else {
+ err!("Collection not found", "Collection does not exist or does not belong to this organization")
};
match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await {
@@ -560,26 +542,20 @@ async fn _delete_organization_collection(
headers: &ManagerHeaders,
conn: &mut DbConn,
) -> EmptyResult {
- match Collection::find_by_uuid(col_id, conn).await {
- None => err!("Collection not found"),
- Some(collection) => {
- if collection.org_uuid == org_id {
- log_event(
- EventType::CollectionDeleted as i32,
- &collection.uuid,
- org_id,
- &headers.user.uuid,
- headers.device.atype,
- &headers.ip.ip,
- conn,
- )
- .await;
- collection.delete(conn).await
- } else {
- err!("Collection and Organization id do not match")
- }
- }
- }
+ let Some(collection) = Collection::find_by_uuid_and_org(col_id, org_id, conn).await else {
+ err!("Collection not found", "Collection does not exist or does not belong to this organization")
+ };
+ log_event(
+ EventType::CollectionDeleted as i32,
+ &collection.uuid,
+ org_id,
+ &headers.user.uuid,
+ headers.device.atype,
+ &headers.ip.ip,
+ conn,
+ )
+ .await;
+ collection.delete(conn).await
}
#[delete("/organizations/<org_id>/collections/<col_id>")]
@@ -601,12 +577,11 @@ struct DeleteCollectionData {
org_id: String,
}
-#[post("/organizations/<org_id>/collections/<col_id>/delete", data = "<_data>")]
+#[post("/organizations/<org_id>/collections/<col_id>/delete")]
async fn post_organization_collection_delete(
org_id: &str,
col_id: &str,
headers: ManagerHeaders,
- _data: Json<DeleteCollectionData>,
mut conn: DbConn,
) -> EmptyResult {
_delete_organization_collection(org_id, col_id, &headers, &mut conn).await
@@ -651,9 +626,9 @@ async fn get_org_collection_detail(
err!("Collection is not owned by organization")
}
- let user_org = match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await {
- Some(u) => u,
- None => err!("User is not part of organization"),
+ let Some(user_org) = UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await
+ else {
+ err!("User is not part of organization")
};
let groups: Vec<Value> = if CONFIG.org_groups_enabled() {
@@ -695,9 +670,8 @@ async fn get_org_collection_detail(
#[get("/organizations/<org_id>/collections/<coll_id>/users")]
async fn get_collection_users(org_id: &str, coll_id: &str, _headers: ManagerHeaders, mut conn: DbConn) -> JsonResult {
// Get org and collection, check that collection is from org
- let collection = match Collection::find_by_uuid_and_org(coll_id, org_id, &mut conn).await {
- None => err!("Collection not found in Organization"),
- Some(collection) => collection,
+ let Some(collection) = Collection::find_by_uuid_and_org(coll_id, org_id, &mut conn).await else {
+ err!("Collection not found in Organization")
};
let mut user_list = Vec::new();
@@ -731,9 +705,8 @@ async fn put_collection_users(
// And then add all the received ones (except if the user has access_all)
for d in data.iter() {
- let user = match UserOrganization::find_by_uuid(&d.id, &mut conn).await {
- Some(u) => u,
- None => err!("User is not part of organization"),
+ let Some(user) = UserOrganization::find_by_uuid_and_org(&d.id, org_id, &mut conn).await else {
+ err!("User is not part of organization")
};
if user.access_all {
@@ -1007,18 +980,16 @@ async fn reinvite_user(org_id: &str, user_org: &str, headers: AdminHeaders, mut
}
async fn _reinvite_user(org_id: &str, user_org: &str, invited_by_email: &str, conn: &mut DbConn) -> EmptyResult {
- let user_org = match UserOrganization::find_by_uuid(user_org, conn).await {
- Some(user_org) => user_org,
- None => err!("The user hasn't been invited to the organization."),
+ let Some(user_org) = UserOrganization::find_by_uuid_and_org(user_org, org_id, conn).await else {
+ err!("The user hasn't been invited to the organization.")
};
if user_org.status != UserOrgStatus::Invited as i32 {
err!("The user is already accepted or confirmed to the organization")
}
- let user = match User::find_by_uuid(&user_org.user_uuid, conn).await {
- Some(user) => user,
- None => err!("User not found."),
+ let Some(user) = User::find_by_uuid(&user_org.user_uuid, conn).await else {
+ err!("User not found.")
};
if !CONFIG.invitations_allowed() && user.password_hash.is_empty() {
@@ -1059,20 +1030,25 @@ struct AcceptData {
reset_password_key: Option<String>,
}
-#[post("/organizations/<org_id>/users/<_org_user_id>/accept", data = "<data>")]
-async fn accept_invite(org_id: &str, _org_user_id: &str, data: Json<AcceptData>, mut conn: DbConn) -> EmptyResult {
+#[post("/organizations/<org_id>/users/<org_user_id>/accept", data = "<data>")]
+async fn accept_invite(org_id: &str, org_user_id: &str, data: Json<AcceptData>, mut conn: DbConn) -> EmptyResult {
// The web-vault passes org_id and org_user_id in the URL, but we are just reading them from the JWT instead
let data: AcceptData = data.into_inner();
let claims = decode_invite(&data.token)?;
+ // If a claim does not have a user_org_id or it does not match the one in from the URI, something is wrong.
+ match &claims.user_org_id {
+ Some(ou_id) if ou_id.eq(org_user_id) => {}
+ _ => err!("Error accepting the invitation", "Claim does not match the org_user_id"),
+ }
+
match User::find_by_mail(&claims.email, &mut conn).await {
Some(user) => {
Invitation::take(&claims.email, &mut conn).await;
if let (Some(user_org), Some(org)) = (&claims.user_org_id, &claims.org_id) {
- let mut user_org = match UserOrganization::find_by_uuid_and_org(user_org, org, &mut conn).await {
- Some(user_org) => user_org,
- None => err!("Error accepting the invitation"),
+ let Some(mut user_org) = UserOrganization::find_by_uuid_and_org(user_org, org, &mut conn).await else {
+ err!("Error accepting the invitation")
};
if user_org.status != UserOrgStatus::Invited as i32 {
@@ -1213,9 +1189,8 @@ async fn _confirm_invite(
err!("Key or UserId is not set, unable to process request");
}
- let mut user_to_confirm = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
- Some(user) => user,
- None => err!("The specified user isn't a member of the organization"),
+ let Some(mut user_to_confirm) = UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await else {
+ err!("The specified user isn't a member of the organization")
};
if user_to_confirm.atype != UserOrgType::User && headers.org_user_type != UserOrgType::Owner {
@@ -1287,9 +1262,8 @@ async fn get_user(
_headers: AdminHeaders,
mut conn: DbConn,
) -> JsonResult {
- let user = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await {
- Some(user) => user,
- None => err!("The specified user isn't a member of the organization"),
+ let Some(user) = UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await else {
+ err!("The specified user isn't a member of the organization")
};
// In this case, when groups are requested we also need to include collections.
@@ -1331,14 +1305,12 @@ async fn edit_user(
) -> EmptyResult {
let data: EditUserData = data.into_inner();
- let new_type = match UserOrgType::from_str(&data.r#type.into_string()) {
- Some(new_type) => new_type,
- None => err!("Invalid type"),
+ let Some(new_type) = UserOrgType::from_str(&data.r#type.into_string()) else {
+ err!("Invalid type")
};
- let mut user_to_edit = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await {
- Some(user) => user,
- None => err!("The specified user isn't member of the organization"),
+ let Some(mut user_to_edit) = UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await else {
+ err!("The specified user isn't member of the organization")
};
if new_type != user_to_edit.atype
@@ -1490,9 +1462,8 @@ async fn _delete_user(
conn: &mut DbConn,
nt: &Notify<'_>,
) -> EmptyResult {
- let user_to_delete = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
- Some(user) => user,
- None => err!("User to delete isn't member of the organization"),
+ let Some(user_to_delete) = UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await else {
+ err!("User to delete isn't member of the organization")
};
if user_to_delete.atype != UserOrgType::User && headers.org_user_type != UserOrgType::Owner {
@@ -1725,9 +1696,8 @@ async fn list_policies_token(org_id: &str, token: &str, mut conn: DbConn) -> Jso
let invite = decode_invite(token)?;
- let invite_org_id = match invite.org_id {
- Some(invite_org_id) => invite_org_id,
- None => err!("Invalid token"),
+ let Some(invite_org_id) = invite.org_id else {
+ err!("Invalid token")
};
if invite_org_id != org_id {
@@ -1747,9 +1717,8 @@ async fn list_policies_token(org_id: &str, token: &str, mut conn: DbConn) -> Jso
#[get("/organizations/<org_id>/policies/<pol_type>")]
async fn get_policy(org_id: &str, pol_type: i32, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
- let pol_type_enum = match OrgPolicyType::from_i32(pol_type) {
- Some(pt) => pt,
- None => err!("Invalid or unsupported policy type"),
+ let Some(pol_type_enum) = OrgPolicyType::from_i32(pol_type) else {
+ err!("Invalid or unsupported policy type")
};
let policy = match OrgPolicy::find_by_org_and_type(org_id, pol_type_enum, &mut conn).await {
@@ -1778,9 +1747,8 @@ async fn put_policy(
) -> JsonResult {
let data: PolicyData = data.into_inner();
- let pol_type_enum = match OrgPolicyType::from_i32(pol_type) {
- Some(pt) => pt,
- None => err!("Invalid or unsupported policy type"),
+ let Some(pol_type_enum) = OrgPolicyType::from_i32(pol_type) else {
+ err!("Invalid or unsupported policy type")
};
// Bitwarden only allows the Reset Password policy when Single Org policy is enabled
@@ -2437,9 +2405,8 @@ async fn put_group(
err!("Group support is disabled");
}
- let group = match Group::find_by_uuid(group_id, &mut conn).await {
- Some(group) => group,
- None => err!("Group not found"),
+ let Some(group) = Group::find_by_uuid_and_org(group_id, org_id, &mut conn).await else {
+ err!("Group not found", "Group uuid is invalid or does not belong to the organization")
};
let group_request = data.into_inner();
@@ -2502,15 +2469,14 @@ async fn add_update_group(
})))
}
-#[get("/organizations/<_org_id>/groups/<group_id>/details")]
-async fn get_group_details(_org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
+#[get("/organizations/<org_id>/groups/<group_id>/details")]
+async fn get_group_details(org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
- let group = match Group::find_by_uuid(group_id, &mut conn).await {
- Some(group) => group,
- _ => err!("Group could not be found!"),
+ let Some(group) = Group::find_by_uuid_and_org(group_id, org_id, &mut conn).await else {
+ err!("Group not found", "Group uuid is invalid or does not belong to the organization")
};
Ok(Json(group.to_json_details(&mut conn).await))
@@ -2531,9 +2497,8 @@ async fn _delete_group(org_id: &str, group_id: &str, headers: &AdminHeaders, con
err!("Group support is disabled");
}
- let group = match Group::find_by_uuid(group_id, conn).await {
- Some(group) => group,
- _ => err!("Group not found"),
+ let Some(group) = Group::find_by_uuid_and_org(group_id, org_id, conn).await else {
+ err!("Group not found", "Group uuid is invalid or does not belong to the organization")
};
log_event(
@@ -2569,29 +2534,27 @@ async fn bulk_delete_groups(
Ok(())
}
-#[get("/organizations/<_org_id>/groups/<group_id>")]
-async fn get_group(_org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
+#[get("/organizations/<org_id>/groups/<group_id>")]
+async fn get_group(org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
- let group = match Group::find_by_uuid(group_id, &mut conn).await {
- Some(group) => group,
- _ => err!("Group not found"),
+ let Some(group) = Group::find_by_uuid_and_org(group_id, org_id, &mut conn).await else {
+ err!("Group not found", "Group uuid is invalid or does not belong to the organization")
};
Ok(Json(group.to_json()))
}
-#[get("/organizations/<_org_id>/groups/<group_id>/users")]
-async fn get_group_users(_org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
+#[get("/organizations/<org_id>/groups/<group_id>/users")]
+async fn get_group_users(org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
- match Group::find_by_uuid(group_id, &mut conn).await {
- Some(_) => { /* Do nothing */ }
- _ => err!("Group could not be found!"),
+ if Group::find_by_uuid_and_org(group_id, org_id, &mut conn).await.is_none() {
+ err!("Group could not be found!", "Group uuid is invalid or does not belong to the organization")
};
let group_users: Vec<String> = GroupUser::find_by_group(group_id, &mut conn)
@@ -2615,9 +2578,8 @@ async fn put_group_users(
err!("Group support is disabled");
}
- match Group::find_by_uuid(group_id, &mut conn).await {
- Some(_) => { /* Do nothing */ }
- _ => err!("Group could not be found!"),
+ if Group::find_by_uuid_and_org(group_id, org_id, &mut conn).await.is_none() {
+ err!("Group could not be found!", "Group uuid is invalid or does not belong to the organization")
};
GroupUser::delete_all_by_group(group_id, &mut conn).await?;
@@ -2642,15 +2604,14 @@ async fn put_group_users(
Ok(())
}
-#[get("/organizations/<_org_id>/users/<user_id>/groups")]
-async fn get_user_groups(_org_id: &str, user_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
+#[get("/organizations/<org_id>/users/<user_id>/groups")]
+async fn get_user_groups(org_id: &str, user_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
- match UserOrganization::find_by_uuid(user_id, &mut conn).await {
- Some(_) => { /* Do nothing */ }
- _ => err!("User could not be found!"),
+ if UserOrganization::find_by_uuid_and_org(user_id, org_id, &mut conn).await.is_none() {
+ err!("User could not be found!")
};
let user_groups: Vec<String> =
@@ -2688,13 +2649,8 @@ async fn put_user_groups(
err!("Group support is disabled");
}
- let user_org = match UserOrganization::find_by_uuid(org_user_id, &mut conn).await {
- Some(uo) => uo,
- _ => err!("User could not be found!"),
- };
-
- if user_org.org_uuid != org_id {
- err!("Group doesn't belong to organization");
+ if UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await.is_none() {
+ err!("User could not be found or does not belong to the organization.");
}
GroupUser::delete_all_by_user(org_user_id, &mut conn).await?;
@@ -2742,22 +2698,12 @@ async fn delete_group_user(
err!("Group support is disabled");
}
- let user_org = match UserOrganization::find_by_uuid(org_user_id, &mut conn).await {
- Some(uo) => uo,
- _ => err!("User could not be found!"),
- };
-
- if user_org.org_uuid != org_id {
- err!("User doesn't belong to organization");
+ if UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await.is_none() {
+ err!("User could not be found or does not belong to the organization.");
}
- let group = match Group::find_by_uuid(group_id, &mut conn).await {
- Some(g) => g,
- _ => err!("Group could not be found!"),
- };
-
- if group.organizations_uuid != org_id {
- err!("Group doesn't belong to organization");
+ if Group::find_by_uuid_and_org(group_id, org_id, &mut conn).await.is_none() {
+ err!("Group could not be found or does not belong to the organization.");
}
log_event(
@@ -2794,9 +2740,8 @@ struct OrganizationUserResetPasswordRequest {
// Just add it here in case they will
#[get("/organizations/<org_id>/public-key")]
async fn get_organization_public_key(org_id: &str, _headers: Headers, mut conn: DbConn) -> JsonResult {
- let org = match Organization::find_by_uuid(org_id, &mut conn).await {
- Some(organization) => organization,
- None => err!("Organization not found"),
+ let Some(org) = Organization::find_by_uuid(org_id, &mut conn).await else {
+ err!("Organization not found")
};
Ok(Json(json!({
@@ -2821,19 +2766,16 @@ async fn put_reset_password(
mut conn: DbConn,
nt: Notify<'_>,
) -> EmptyResult {
- let org = match Organization::find_by_uuid(org_id, &mut conn).await {
- Some(org) => org,
- None => err!("Required organization not found"),
+ let Some(org) = Organization::find_by_uuid(org_id, &mut conn).await else {
+ err!("Required organization not found")
};
- let org_user = match UserOrganization::find_by_uuid_and_org(org_user_id, &org.uuid, &mut conn).await {
- Some(user) => user,
- None => err!("User to reset isn't member of required organization"),
+ let Some(org_user) = UserOrganization::find_by_uuid_and_org(org_user_id, &org.uuid, &mut conn).await else {
+ err!("User to reset isn't member of required organization")
};
- let user = match User::find_by_uuid(&org_user.user_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("User not found"),
+ let Some(user) = User::find_by_uuid(&org_user.user_uuid, &mut conn).await else {
+ err!("User not found")
};
check_reset_password_applicable_and_permissions(org_id, org_user_id, &headers, &mut conn).await?;
@@ -2880,19 +2822,16 @@ async fn get_reset_password_details(
headers: AdminHeaders,
mut conn: DbConn,
) -> JsonResult {
- let org = match Organization::find_by_uuid(org_id, &mut conn).await {
- Some(org) => org,
- None => err!("Required organization not found"),
+ let Some(org) = Organization::find_by_uuid(org_id, &mut conn).await else {
+ err!("Required organization not found")
};
- let org_user = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await {
- Some(user) => user,
- None => err!("User to reset isn't member of required organization"),
+ let Some(org_user) = UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await else {
+ err!("User to reset isn't member of required organization")
};
- let user = match User::find_by_uuid(&org_user.user_uuid, &mut conn).await {
- Some(user) => user,
- None => err!("User not found"),
+ let Some(user) = User::find_by_uuid(&org_user.user_uuid, &mut conn).await else {
+ err!("User not found")
};
check_reset_password_applicable_and_permissions(org_id, org_user_id, &headers, &mut conn).await?;
@@ -2918,9 +2857,8 @@ async fn check_reset_password_applicable_and_permissions(
) -> EmptyResult {
check_reset_password_applicable(org_id, conn).await?;
- let target_user = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
- Some(user) => user,
- None => err!("Reset target user not found"),
+ let Some(target_user) = UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await else {
+ err!("Reset target user not found")
};
// Resetting user must be higher/equal to user to reset
@@ -2936,9 +2874,8 @@ async fn check_reset_password_applicable(org_id: &str, conn: &mut DbConn) -> Emp
err!("Password reset is not supported on an email-disabled instance.");
}
- let policy = match OrgPolicy::find_by_org_and_type(org_id, OrgPolicyType::ResetPassword, conn).await {
- Some(p) => p,
- None => err!("Policy not found"),
+ let Some(policy) = OrgPolicy::find_by_org_and_type(org_id, OrgPolicyType::ResetPassword, conn).await else {
+ err!("Policy not found")
};
if !policy.enabled {
@@ -2956,9 +2893,8 @@ async fn put_reset_password_enrollment(
data: Json<OrganizationUserResetPasswordEnrollmentRequest>,
mut conn: DbConn,
) -> EmptyResult {
- let mut org_user = match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await {
- Some(u) => u,
- None => err!("User to enroll isn't member of required organization"),
+ let Some(mut org_user) = UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await else {
+ err!("User to enroll isn't member of required organization")
};
check_reset_password_applicable(org_id, &mut conn).await?;
diff --git a/src/api/core/public.rs b/src/api/core/public.rs
index 737d30dd..3b3e74cb 100644
--- a/src/api/core/public.rs
+++ b/src/api/core/public.rs
@@ -203,9 +203,8 @@ impl<'r> FromRequest<'r> for PublicToken {
None => err_handler!("No access token provided"),
};
// Check JWT token is valid and get device and user from it
- let claims = match auth::decode_api_org(access_token) {
- Ok(claims) => claims,
- Err(_) => err_handler!("Invalid claim"),
+ let Ok(claims) = auth::decode_api_org(access_token) else {
+ err_handler!("Invalid claim")
};
// Check if time is between claims.nbf and claims.exp
let time_now = Utc::now().timestamp();
@@ -227,13 +226,11 @@ impl<'r> FromRequest<'r> for PublicToken {
Outcome::Success(conn) => conn,
_ => err_handler!("Error getting DB"),
};
- let org_uuid = match claims.client_id.strip_prefix("organization.") {
- Some(uuid) => uuid,
- None => err_handler!("Malformed client_id"),
+ let Some(org_uuid) = claims.client_id.strip_prefix("organization.") else {
+ err_handler!("Malformed client_id")
};
- let org_api_key = match OrganizationApiKey::find_by_org_uuid(org_uuid, &conn).await {
- Some(org_api_key) => org_api_key,
- None => err_handler!("Invalid client_id"),
+ let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(org_uuid, &conn).await else {
+ err_handler!("Invalid client_id")
};
if org_api_key.org_uuid != claims.client_sub {
err_handler!("Token not issued for this org");
diff --git a/src/api/core/sends.rs b/src/api/core/sends.rs
index a7e5bcf0..b98ecf70 100644
--- a/src/api/core/sends.rs
+++ b/src/api/core/sends.rs
@@ -159,16 +159,10 @@ async fn get_sends(headers: Headers, mut conn: DbConn) -> Json<Value> {
#[get("/sends/<uuid>")]
async fn get_send(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
- let send = match Send::find_by_uuid(uuid, &mut conn).await {
- Some(send) => send,
- None => err!("Send not found"),
- };
-
- if send.user_uuid.as_ref() != Some(&headers.user.uuid) {
- err!("Send is not owned by user")
+ match Send::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await {
+ Some(send) => Ok(Json(send.to_json())),
+ None => err!("Send not found", "Invalid uuid or does not belong to user"),
}
-
- Ok(Json(send.to_json()))
}
#[post("/sends", data = "<data>")]
@@ -371,22 +365,14 @@ async fn post_send_file_v2_data(
let mut data = data.into_inner();
- let Some(send) = Send::find_by_uuid(send_uuid, &mut conn).await else {
- err!("Send not found. Unable to save the file.")
+ let Some(send) = Send::find_by_uuid_and_user(send_uuid, &headers.user.uuid, &mut conn).await else {
+ err!("Send not found. Unable to save the file.", "Invalid uuid or does not belong to user.")
};
if send.atype != SendType::File as i32 {
err!("Send is not a file type send.");
}
- let Some(send_user_id) = &send.user_uuid else {
- err!("Sends are only supported for users at the moment.")
- };
-
- if send_user_id != &headers.user.uuid {
- err!("Send doesn't belong to user.");
- }
-
let Ok(send_data) = serde_json::from_str::<SendFileData>(&send.data) else {
err!("Unable to decode send data as json.")
};
@@ -456,9 +442,8 @@ async fn post_access(
ip: ClientIp,
nt: Notify<'_>,
) -> JsonResult {
- let mut send = match Send::find_by_access_id(access_id, &mut conn).await {
- Some(s) => s,
- None => err_code!(SEND_INACCESSIBLE_MSG, 404),
+ let Some(mut send) = Send::find_by_access_id(access_id, &mut conn).await else {
+ err_code!(SEND_INACCESSIBLE_MSG, 404)
};
if let Some(max_access_count) = send.max_access_count {
@@ -517,9 +502,8 @@ async fn post_access_file(
mut conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
- let mut send = match Send::find_by_uuid(send_id, &mut conn).await {
- Some(s) => s,
- None => err_code!(SEND_INACCESSIBLE_MSG, 404),
+ let Some(mut send) = Send::find_by_uuid(send_id, &mut conn).await else {
+ err_code!(SEND_INACCESSIBLE_MSG, 404)
};
if let Some(max_access_count) = send.max_access_count {
@@ -582,16 +566,15 @@ async fn download_send(send_id: SafeString, file_id: SafeString, t: &str) -> Opt
None
}
-#[put("/sends/<id>", data = "<data>")]
-async fn put_send(id: &str, data: Json<SendData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
+#[put("/sends/<uuid>", data = "<data>")]
+async fn put_send(uuid: &str, data: Json<SendData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
enforce_disable_send_policy(&headers, &mut conn).await?;
let data: SendData = data.into_inner();
enforce_disable_hide_email_policy(&data, &headers, &mut conn).await?;
- let mut send = match Send::find_by_uuid(id, &mut conn).await {
- Some(s) => s,
- None => err!("Send not found"),
+ let Some(mut send) = Send::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
+ err!("Send not found", "Send uuid is invalid or does not belong to user")
};
update_send_from_data(&mut send, data, &headers, &mut conn, &nt, UpdateType::SyncSendUpdate).await?;
@@ -657,17 +640,12 @@ pub async fn update_send_from_data(
Ok(())
}
-#[delete("/sends/<id>")]
-async fn delete_send(id: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
- let send = match Send::find_by_uuid(id, &mut conn).await {
- Some(s) => s,
- None => err!("Send not found"),
+#[delete("/sends/<uuid>")]
+async fn delete_send(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
+ let Some(send) = Send::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
+ err!("Send not found", "Invalid send uuid, or does not belong to user")
};
- if send.user_uuid.as_ref() != Some(&headers.user.uuid) {
- err!("Send is not owned by user")
- }
-
send.delete(&mut conn).await?;
nt.send_send_update(
UpdateType::SyncSendDelete,
@@ -681,19 +659,14 @@ async fn delete_send(id: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_
Ok(())
}
-#[put("/sends/<id>/remove-password")]
-async fn put_remove_password(id: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
+#[put("/sends/<uuid>/remove-password")]
+async fn put_remove_password(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
enforce_disable_send_policy(&headers, &mut conn).await?;
- let mut send = match Send::find_by_uuid(id, &mut conn).await {
- Some(s) => s,
- None => err!("Send not found"),
+ let Some(mut send) = Send::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
+ err!("Send not found", "Invalid send uuid, or does not belong to user")
};
- if send.user_uuid.as_ref() != Some(&headers.user.uuid) {
- err!("Send is not owned by user")
- }
-
send.set_password(None);
send.save(&mut conn).await?;
nt.send_send_update(
diff --git a/src/api/core/two_factor/authenticator.rs b/src/api/core/two_factor/authenticator.rs
index 9d4bd480..64cc6486 100644
--- a/src/api/core/two_factor/authenticator.rs
+++ b/src/api/core/two_factor/authenticator.rs
@@ -117,9 +117,8 @@ pub async fn validate_totp_code(
) -> EmptyResult {
use totp_lite::{totp_custom, Sha1};
- let decoded_secret = match BASE32.decode(secret.as_bytes()) {
- Ok(s) => s,
- Err(_) => err!("Invalid TOTP secret"),
+ let Ok(decoded_secret) = BASE32.decode(secret.as_bytes()) else {
+ err!("Invalid TOTP secret")
};
let mut twofactor =
diff --git a/src/api/core/two_factor/duo.rs b/src/api/core/two_factor/duo.rs
index 6de2935d..76421043 100644
--- a/src/api/core/two_factor/duo.rs
+++ b/src/api/core/two_factor/duo.rs
@@ -232,9 +232,8 @@ async fn get_user_duo_data(uuid: &str, conn: &mut DbConn) -> DuoStatus {
let type_ = TwoFactorType::Duo as i32;
// If the user doesn't have an entry, disabled
- let twofactor = match TwoFactor::find_by_user_and_type(uuid, type_, conn).await {
- Some(t) => t,
- None => return DuoStatus::Disabled(DuoData::global().is_some()),
+ let Some(twofactor) = TwoFactor::find_by_user_and_type(uuid, type_, conn).await else {
+ return DuoStatus::Disabled(DuoData::global().is_some());
};
// If the user has the required values, we use those
@@ -333,14 +332,12 @@ fn parse_duo_values(key: &str, val: &str, ikey: &str, prefix: &str, time: i64) -
err!("Prefixes don't match")
}
- let cookie_vec = match BASE64.decode(u_b64.as_bytes()) {
- Ok(c) => c,
- Err(_) => err!("Invalid Duo cookie encoding"),
+ let Ok(cookie_vec) = BASE64.decode(u_b64.as_bytes()) else {
+ err!("Invalid Duo cookie encoding")
};
- let cookie = match String::from_utf8(cookie_vec) {
- Ok(c) => c,
- Err(_) => err!("Invalid Duo cookie encoding"),
+ let Ok(cookie) = String::from_utf8(cookie_vec) else {
+ err!("Invalid Duo cookie encoding")
};
let cookie_split: Vec<&str> = cookie.split('|').collect();
diff --git a/src/api/core/two_factor/email.rs b/src/api/core/two_factor/email.rs
index 293c0671..09f2f3b7 100644
--- a/src/api/core/two_factor/email.rs
+++ b/src/api/core/two_factor/email.rs
@@ -40,9 +40,8 @@ async fn send_email_login(data: Json<SendEmailLoginData>, mut conn: DbConn) -> E
use crate::db::models::User;
// Get the user
- let user = match User::find_by_mail(&data.email, &mut conn).await {
- Some(user) => user,
- None => err!("Username or password is incorrect. Try again."),
+ let Some(user) = User::find_by_mail(&data.email, &mut conn).await else {
+ err!("Username or password is incorrect. Try again.")
};
// Check password
@@ -174,9 +173,8 @@ async fn email(data: Json<EmailData>, headers: Headers, mut conn: DbConn) -> Jso
let mut email_data = EmailTokenData::from_json(&twofactor.data)?;
- let issued_token = match &email_data.last_token {
- Some(t) => t,
- _ => err!("No token available"),
+ let Some(issued_token) = &email_data.last_token else {
+ err!("No token available")
};
if !crypto::ct_eq(issued_token, data.token) {
@@ -205,14 +203,13 @@ pub async fn validate_email_code_str(user_uuid: &str, token: &str, data: &str, c
let mut twofactor = TwoFactor::find_by_user_and_type(user_uuid, TwoFactorType::Email as i32, conn)
.await
.map_res("Two factor not found")?;
- let issued_token = match &email_data.last_token {
- Some(t) => t,
- _ => err!(
+ let Some(issued_token) = &email_data.last_token else {
+ err!(
"No token available",
ErrorEvent {
event: EventType::UserFailedLogIn2fa
}
- ),
+ )
};
if !crypto::ct_eq(issued_token, token) {
diff --git a/src/api/core/two_factor/mod.rs b/src/api/core/two_factor/mod.rs
index e3795eb8..486b526a 100644
--- a/src/api/core/two_factor/mod.rs
+++ b/src/api/core/two_factor/mod.rs
@@ -85,9 +85,8 @@ async fn recover(data: Json<RecoverTwoFactor>, client_headers: ClientHeaders, mu
use crate::db::models::User;
// Get the user
- let mut user = match User::find_by_mail(&data.email, &mut conn).await {
- Some(user) => user,
- None => err!("Username or password is incorrect. Try again."),
+ let Some(mut user) = User::find_by_mail(&data.email, &mut conn).await else {
+ err!("Username or password is incorrect. Try again.")
};
// Check password
diff --git a/src/api/core/two_factor/webauthn.rs b/src/api/core/two_factor/webauthn.rs
index 52ca70c4..9ee83d38 100644
--- a/src/api/core/two_factor/webauthn.rs
+++ b/src/api/core/two_factor/webauthn.rs
@@ -309,17 +309,16 @@ async fn delete_webauthn(data: Json<DeleteU2FData>, headers: Headers, mut conn:
err!("Invalid password");
}
- let mut tf =
- match TwoFactor::find_by_user_and_type(&headers.user.uuid, TwoFactorType::Webauthn as i32, &mut conn).await {
- Some(tf) => tf,
- None => err!("Webauthn data not found!"),
- };
+ let Some(mut tf) =
+ TwoFactor::find_by_user_and_type(&headers.user.uuid, TwoFactorType::Webauthn as i32, &mut conn).await
+ else {
+ err!("Webauthn data not found!")
+ };
let mut data: Vec<WebauthnRegistration> = serde_json::from_str(&tf.data)?;
- let item_pos = match data.iter().position(|r| r.id == id) {
- Some(p) => p,
- None => err!("Webauthn entry not found"),
+ let Some(item_pos) = data.iter().position(|r| r.id == id) else {
+ err!("Webauthn entry not found")
};
let removed_item = data.remove(item_pos);
diff --git a/src/api/identity.rs b/src/api/identity.rs
index 445d61fd..13248f0a 100644
--- a/src/api/identity.rs
+++ b/src/api/identity.rs
@@ -157,9 +157,8 @@ async fn _password_login(
// Get the user
let username = data.username.as_ref().unwrap().trim();
- let mut user = match User::find_by_mail(username, conn).await {
- Some(user) => user,
- None => err!("Username or password is incorrect. Try again", format!("IP: {}. Username: {}.", ip.ip, username)),
+ let Some(mut user) = User::find_by_mail(username, conn).await else {
+ err!("Username or password is incorrect. Try again", format!("IP: {}. Username: {}.", ip.ip, username))
};
// Set the user_uuid here to be passed back used for event logging.
@@ -180,7 +179,8 @@ async fn _password_login(
// If we get an auth request, we don't check the user's password, but the access code of the auth request
if let Some(ref auth_request_uuid) = data.auth_request {
- let Some(auth_request) = AuthRequest::find_by_uuid(auth_request_uuid.as_str(), conn).await else {
+ let Some(auth_request) = AuthRequest::find_by_uuid_and_user(auth_request_uuid.as_str(), &user.uuid, conn).await
+ else {
err!(
"Auth request not found. Try again.",
format!("IP: {}. Username: {}.", ip.ip, username),
@@ -382,13 +382,11 @@ async fn _user_api_key_login(
) -> JsonResult {
// Get the user via the client_id
let client_id = data.client_id.as_ref().unwrap();
- let client_user_uuid = match client_id.strip_prefix("user.") {
- Some(uuid) => uuid,
- None => err!("Malformed client_id", format!("IP: {}.", ip.ip)),
+ let Some(client_user_uuid) = client_id.strip_prefix("user.") else {
+ err!("Malformed client_id", format!("IP: {}.", ip.ip))
};
- let user = match User::find_by_uuid(client_user_uuid, conn).await {
- Some(user) => user,
- None => err!("Invalid client_id", format!("IP: {}.", ip.ip)),
+ let Some(user) = User::find_by_uuid(client_user_uuid, conn).await else {
+ err!("Invalid client_id", format!("IP: {}.", ip.ip))
};
// Set the user_uuid here to be passed back used for event logging.
@@ -471,13 +469,11 @@ async fn _user_api_key_login(
async fn _organization_api_key_login(data: ConnectData, conn: &mut DbConn, ip: &ClientIp) -> JsonResult {
// Get the org via the client_id
let client_id = data.client_id.as_ref().unwrap();
- let org_uuid = match client_id.strip_prefix("organization.") {
- Some(uuid) => uuid,
- None => err!("Malformed client_id", format!("IP: {}.", ip.ip)),
+ let Some(org_uuid) = client_id.strip_prefix("organization.") else {
+ err!("Malformed client_id", format!("IP: {}.", ip.ip))
};
- let org_api_key = match OrganizationApiKey::find_by_org_uuid(org_uuid, conn).await {
- Some(org_api_key) => org_api_key,
- None => err!("Invalid client_id", format!("IP: {}.", ip.ip)),
+ let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(org_uuid, conn).await else {
+ err!("Invalid client_id", format!("IP: {}.", ip.ip))
};
// Check API key.
@@ -676,9 +672,8 @@ async fn _json_err_twofactor(
}
Some(tf_type @ TwoFactorType::YubiKey) => {
- let twofactor = match TwoFactor::find_by_user_and_type(user_uuid, tf_type as i32, conn).await {
- Some(tf) => tf,
- None => err!("No YubiKey devices registered"),
+ let Some(twofactor) = TwoFactor::find_by_user_and_type(user_uuid, tf_type as i32, conn).await else {
+ err!("No YubiKey devices registered")
};
let yubikey_metadata: yubikey::YubikeyMetadata = serde_json::from_str(&twofactor.data)?;
@@ -689,9 +684,8 @@ async fn _json_err_twofactor(
}
Some(tf_type @ TwoFactorType::Email) => {
- let twofactor = match TwoFactor::find_by_user_and_type(user_uuid, tf_type as i32, conn).await {
- Some(tf) => tf,
- None => err!("No twofactor email registered"),
+ let Some(twofactor) = TwoFactor::find_by_user_and_type(user_uuid, tf_type as i32, conn).await else {
+ err!("No twofactor email registered")
};
// Send email immediately if email is the only 2FA option
diff --git a/src/api/push.rs b/src/api/push.rs
index d6abfc49..7396a68d 100644
--- a/src/api/push.rs
+++ b/src/api/push.rs
@@ -155,12 +155,9 @@ pub async fn push_cipher_update(
if cipher.organization_uuid.is_some() {
return;
};
- let user_uuid = match &cipher.user_uuid {
- Some(c) => c,
- None => {
- debug!("Cipher has no uuid");
- return;
- }
+ let Some(user_uuid) = &cipher.user_uuid else {
+ debug!("Cipher has no uuid");
+ return;
};
if Device::check_user_has_push_device(user_uuid, conn).await {
diff --git a/src/auth.rs b/src/auth.rs
index 809ef9fd..15910679 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -471,9 +471,8 @@ impl<'r> FromRequest<'r> for Headers {
};
// Check JWT token is valid and get device and user from it
- let claims = match decode_login(access_token) {
- Ok(claims) => claims,
- Err(_) => err_handler!("Invalid claim"),
+ let Ok(claims) = decode_login(access_token) else {
+ err_handler!("Invalid claim")
};
let device_uuid = claims.device;
@@ -484,23 +483,20 @@ impl<'r> FromRequest<'r> for Headers {
_ => err_handler!("Error getting DB"),
};
- let device = match Device::find_by_uuid_and_user(&device_uuid, &user_uuid, &mut conn).await {
- Some(device) => device,
- None => err_handler!("Invalid device id"),
+ let Some(device) = Device::find_by_uuid_and_user(&device_uuid, &user_uuid, &mut conn).await else {
+ err_handler!("Invalid device id")
};
- let user = match User::find_by_uuid(&user_uuid, &mut conn).await {
- Some(user) => user,
- None => err_handler!("Device has no user associated"),
+ let Some(user) = User::find_by_uuid(&user_uuid, &mut conn).await else {
+ err_handler!("Device has no user associated")
};
if user.security_stamp != claims.sstamp {
if let Some(stamp_exception) =
user.stamp_exception.as_deref().and_then(|s| serde_json::from_str::<UserStampException>(s).ok())
{
- let current_route = match request.route().and_then(|r| r.name.as_deref()) {
- Some(name) => name,
- _ => err_handler!("Error getting current route for stamp exception"),
+ let Some(current_route) = request.route().and_then(|r| r.name.as_deref()) else {
+ err_handler!("Error getting current route for stamp exception")
};
// Check if the stamp exception has expired first.
diff --git a/src/db/models/auth_request.rs b/src/db/models/auth_request.rs
index 9388c71a..3aca20cb 100644
--- a/src/db/models/auth_request.rs
+++ b/src/db/models/auth_request.rs
@@ -111,6 +111,17 @@ impl AuthRequest {
}}
}
+ pub async fn find_by_uuid_and_user(uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Option<Self> {
+ db_run! {conn: {
+ auth_requests::table
+ .filter(auth_requests::uuid.eq(uuid))
+ .filter(auth_requests::user_uuid.eq(user_uuid))
+ .first::<AuthRequestDb>(conn)
+ .ok()
+ .from_db()
+ }}
+ }
+
pub async fn find_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
auth_requests::table
diff --git a/src/db/models/folder.rs b/src/db/models/folder.rs
index 5370c9dd..45460720 100644
--- a/src/db/models/folder.rs
+++ b/src/db/models/folder.rs
@@ -120,10 +120,11 @@ impl Folder {
Ok(())
}
- pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
+ pub async fn find_by_uuid_and_user(uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
folders::table
.filter(folders::uuid.eq(uuid))
+ .filter(folders::user_uuid.eq(user_uuid))
.first::<FolderDb>(conn)
.ok()
.from_db()
diff --git a/src/db/models/group.rs b/src/db/models/group.rs
index e226512d..d9a08970 100644
--- a/src/db/models/group.rs
+++ b/src/db/models/group.rs
@@ -191,10 +191,11 @@ impl Group {
}}
}
- pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
+ pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
groups::table
.filter(groups::uuid.eq(uuid))
+ .filter(groups::organizations_uuid.eq(org_uuid))
.first::<GroupDb>(conn)
.ok()
.from_db()
diff --git a/src/db/models/org_policy.rs b/src/db/models/org_policy.rs
index 23e583b4..14447c05 100644
--- a/src/db/models/org_policy.rs
+++ b/src/db/models/org_policy.rs
@@ -142,16 +142,6 @@ impl OrgPolicy {
}}
}
- pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
- db_run! { conn: {
- org_policies::table
- .filter(org_policies::uuid.eq(uuid))
- .first::<OrgPolicyDb>(conn)
- .ok()
- .from_db()
- }}
- }
-
pub async fn find_by_org(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
org_policies::table
diff --git a/src/db/models/send.rs b/src/db/models/send.rs
index 36944281..fb95f86b 100644
--- a/src/db/models/send.rs
+++ b/src/db/models/send.rs
@@ -268,9 +268,8 @@ impl Send {
use data_encoding::BASE64URL_NOPAD;
use uuid::Uuid;
- let uuid_vec = match BASE64URL_NOPAD.decode(access_id.as_bytes()) {
- Ok(v) => v,
- Err(_) => return None,
+ let Ok(uuid_vec) = BASE64URL_NOPAD.decode(access_id.as_bytes()) else {
+ return None;
};
let uuid = match Uuid::from_slice(&uuid_vec) {
@@ -291,6 +290,17 @@ impl Send {
}}
}
+ pub async fn find_by_uuid_and_user(uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Option<Self> {
+ db_run! {conn: {
+ sends::table
+ .filter(sends::uuid.eq(uuid))
+ .filter(sends::user_uuid.eq(user_uuid))
+ .first::<SendDb>(conn)
+ .ok()
+ .from_db()
+ }}
+ }
+
pub async fn find_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
sends::table
diff --git a/src/mail.rs b/src/mail.rs
index 5ce4a079..1a32ae25 100644
--- a/src/mail.rs
+++ b/src/mail.rs
@@ -286,9 +286,8 @@ pub async fn send_invite(
}
}
- let query_string = match query.query() {
- None => err!("Failed to build invite URL query parameters"),
- Some(query) => query,
+ let Some(query_string) = query.query() else {
+ err!("Failed to build invite URL query parameters")
};
let (subject, body_html, body_text) = get_text(
@@ -330,9 +329,8 @@ pub async fn send_emergency_access_invite(
.append_pair("token", &encode_jwt(&claims));
}
- let query_string = match query.query() {
- None => err!("Failed to build emergency invite URL query parameters"),
- Some(query) => query,
+ let Some(query_string) = query.query() else {
+ err!("Failed to build emergency invite URL query parameters")
};
let (subject, body_html, body_text) = get_text(