1
0
Fork 1
Spiegel von https://github.com/dani-garcia/vaultwarden.git synchronisiert 2025-01-07 11:45:40 +01:00

use id names more consistently

Dieser Commit ist enthalten in:
Stefan Melmuk 2024-12-24 00:55:32 +01:00
Ursprung 1397392699
Commit 6355985539
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 817020C608FE9C09
21 geänderte Dateien mit 442 neuen und 424 gelöschten Zeilen

Datei anzeigen

@ -280,8 +280,8 @@ struct InviteData {
email: String,
}
async fn get_user_or_404(uuid: &UserId, conn: &mut DbConn) -> ApiResult<User> {
if let Some(user) = User::find_by_uuid(uuid, conn).await {
async fn get_user_or_404(user_id: &UserId, conn: &mut DbConn) -> ApiResult<User> {
if let Some(user) = User::find_by_uuid(user_id, conn).await {
Ok(user)
} else {
err_code!("User doesn't exist", Status::NotFound.code);
@ -381,21 +381,21 @@ async fn get_user_by_mail_json(mail: &str, _token: AdminToken, mut conn: DbConn)
}
}
#[get("/users/<uuid>")]
async fn get_user_json(uuid: UserId, _token: AdminToken, mut conn: DbConn) -> JsonResult {
let u = get_user_or_404(&uuid, &mut conn).await?;
#[get("/users/<user_id>")]
async fn get_user_json(user_id: UserId, _token: AdminToken, mut conn: DbConn) -> JsonResult {
let u = get_user_or_404(&user_id, &mut conn).await?;
let mut usr = u.to_json(&mut conn).await;
usr["userEnabled"] = json!(u.enabled);
usr["createdAt"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT));
Ok(Json(usr))
}
#[post("/users/<uuid>/delete")]
async fn delete_user(uuid: UserId, token: AdminToken, mut conn: DbConn) -> EmptyResult {
let user = get_user_or_404(&uuid, &mut conn).await?;
#[post("/users/<user_id>/delete")]
async fn delete_user(user_id: UserId, token: AdminToken, mut conn: DbConn) -> EmptyResult {
let user = get_user_or_404(&user_id, &mut conn).await?;
// Get the membership records before deleting the actual user
let memberships = Membership::find_any_state_by_user(&uuid, &mut conn).await;
let memberships = Membership::find_any_state_by_user(&user_id, &mut conn).await;
let res = user.delete(&mut conn).await;
for membership in memberships {
@ -414,9 +414,9 @@ async fn delete_user(uuid: UserId, token: AdminToken, mut conn: DbConn) -> Empty
res
}
#[post("/users/<uuid>/deauth")]
async fn deauth_user(uuid: UserId, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
let mut user = get_user_or_404(&uuid, &mut conn).await?;
#[post("/users/<user_id>/deauth")]
async fn deauth_user(user_id: UserId, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
let mut user = get_user_or_404(&user_id, &mut conn).await?;
nt.send_logout(&user, None).await;
@ -435,9 +435,9 @@ async fn deauth_user(uuid: UserId, _token: AdminToken, mut conn: DbConn, nt: Not
user.save(&mut conn).await
}
#[post("/users/<uuid>/disable")]
async fn disable_user(uuid: UserId, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
let mut user = get_user_or_404(&uuid, &mut conn).await?;
#[post("/users/<user_id>/disable")]
async fn disable_user(user_id: UserId, _token: AdminToken, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
let mut user = get_user_or_404(&user_id, &mut conn).await?;
Device::delete_all_by_user(&user.uuid, &mut conn).await?;
user.reset_security_stamp();
user.enabled = false;
@ -449,26 +449,26 @@ async fn disable_user(uuid: UserId, _token: AdminToken, mut conn: DbConn, nt: No
save_result
}
#[post("/users/<uuid>/enable")]
async fn enable_user(uuid: UserId, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
let mut user = get_user_or_404(&uuid, &mut conn).await?;
#[post("/users/<user_id>/enable")]
async fn enable_user(user_id: UserId, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
let mut user = get_user_or_404(&user_id, &mut conn).await?;
user.enabled = true;
user.save(&mut conn).await
}
#[post("/users/<uuid>/remove-2fa")]
async fn remove_2fa(uuid: UserId, token: AdminToken, mut conn: DbConn) -> EmptyResult {
let mut user = get_user_or_404(&uuid, &mut conn).await?;
#[post("/users/<user_id>/remove-2fa")]
async fn remove_2fa(user_id: UserId, token: AdminToken, mut conn: DbConn) -> EmptyResult {
let mut user = get_user_or_404(&user_id, &mut conn).await?;
TwoFactor::delete_all_by_user(&user.uuid, &mut conn).await?;
two_factor::enforce_2fa_policy(&user, ACTING_ADMIN_USER, 14, &token.ip.ip, &mut conn).await?;
user.totp_recover = None;
user.save(&mut conn).await
}
#[post("/users/<uuid>/invite/resend")]
async fn resend_user_invite(uuid: UserId, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
if let Some(user) = User::find_by_uuid(&uuid, &mut conn).await {
#[post("/users/<user_id>/invite/resend")]
async fn resend_user_invite(user_id: UserId, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
if let Some(user) = User::find_by_uuid(&user_id, &mut conn).await {
//TODO: replace this with user.status check when it will be available (PR#3397)
if !user.password_hash.is_empty() {
err_code!("User already accepted invitation", Status::BadRequest.code);
@ -570,9 +570,9 @@ async fn organizations_overview(_token: AdminToken, mut conn: DbConn) -> ApiResu
Ok(Html(text))
}
#[post("/organizations/<org_uuid>/delete")]
async fn delete_organization(org_uuid: OrganizationId, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
let org = Organization::find_by_uuid(&org_uuid, &mut conn).await.map_res("Organization doesn't exist")?;
#[post("/organizations/<org_id>/delete")]
async fn delete_organization(org_id: OrganizationId, _token: AdminToken, mut conn: DbConn) -> EmptyResult {
let org = Organization::find_by_uuid(&org_id, &mut conn).await.map_res("Organization doesn't exist")?;
org.delete(&mut conn).await
}

Datei anzeigen

@ -305,9 +305,9 @@ async fn put_avatar(data: Json<AvatarData>, headers: Headers, mut conn: DbConn)
Ok(Json(user.to_json(&mut conn).await))
}
#[get("/users/<uuid>/public-key")]
async fn get_public_keys(uuid: UserId, _headers: Headers, mut conn: DbConn) -> JsonResult {
let user = match User::find_by_uuid(&uuid, &mut conn).await {
#[get("/users/<user_id>/public-key")]
async fn get_public_keys(user_id: UserId, _headers: Headers, mut conn: DbConn) -> JsonResult {
let user = match User::find_by_uuid(&user_id, &mut conn).await {
Some(user) if user.public_key.is_some() => user,
Some(_) => err_code!("User has no public_key", Status::NotFound.code),
None => err_code!("User doesn't exist", Status::NotFound.code),
@ -549,17 +549,17 @@ async fn post_rotatekey(data: Json<KeyData>, headers: Headers, mut conn: DbConn,
// TODO: See if we can optimize the whole cipher adding/importing and prevent duplicate code and checks.
Cipher::validate_cipher_data(&data.ciphers)?;
let user_uuid = &headers.user.uuid;
let user_id = &headers.user.uuid;
// TODO: Ideally we'd do everything after this point in a single transaction.
let mut existing_ciphers = Cipher::find_owned_by_user(user_uuid, &mut conn).await;
let mut existing_folders = Folder::find_by_user(user_uuid, &mut conn).await;
let mut existing_emergency_access = EmergencyAccess::find_all_by_grantor_uuid(user_uuid, &mut conn).await;
let mut existing_memberships = Membership::find_by_user(user_uuid, &mut conn).await;
let mut existing_ciphers = Cipher::find_owned_by_user(user_id, &mut conn).await;
let mut existing_folders = Folder::find_by_user(user_id, &mut conn).await;
let mut existing_emergency_access = EmergencyAccess::find_all_by_grantor_uuid(user_id, &mut conn).await;
let mut existing_memberships = Membership::find_by_user(user_id, &mut conn).await;
// We only rotate the reset password key if it is set.
existing_memberships.retain(|m| m.reset_password_key.is_some());
let mut existing_sends = Send::find_by_user(user_uuid, &mut conn).await;
let mut existing_sends = Send::find_by_user(user_id, &mut conn).await;
validate_keydata(
&data,

Datei anzeigen

@ -191,9 +191,9 @@ async fn get_ciphers(headers: Headers, mut conn: DbConn) -> Json<Value> {
}))
}
#[get("/ciphers/<uuid>")]
async fn get_cipher(uuid: CipherId, headers: Headers, mut conn: DbConn) -> JsonResult {
let Some(cipher) = Cipher::find_by_uuid(&uuid, &mut conn).await else {
#[get("/ciphers/<cipher_id>")]
async fn get_cipher(cipher_id: CipherId, headers: Headers, mut conn: DbConn) -> JsonResult {
let Some(cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else {
err!("Cipher doesn't exist")
};
@ -204,15 +204,15 @@ async fn get_cipher(uuid: CipherId, headers: Headers, mut conn: DbConn) -> JsonR
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
}
#[get("/ciphers/<uuid>/admin")]
async fn get_cipher_admin(uuid: CipherId, headers: Headers, conn: DbConn) -> JsonResult {
#[get("/ciphers/<cipher_id>/admin")]
async fn get_cipher_admin(cipher_id: CipherId, headers: Headers, conn: DbConn) -> JsonResult {
// TODO: Implement this correctly
get_cipher(uuid, headers, conn).await
get_cipher(cipher_id, headers, conn).await
}
#[get("/ciphers/<uuid>/details")]
async fn get_cipher_details(uuid: CipherId, headers: Headers, conn: DbConn) -> JsonResult {
get_cipher(uuid, headers, conn).await
#[get("/ciphers/<cipher_id>/details")]
async fn get_cipher_details(cipher_id: CipherId, headers: Headers, conn: DbConn) -> JsonResult {
get_cipher(cipher_id, headers, conn).await
}
#[derive(Debug, Deserialize)]
@ -355,9 +355,9 @@ async fn enforce_personal_ownership_policy(
conn: &mut DbConn,
) -> EmptyResult {
if data.is_none() || data.unwrap().organization_id.is_none() {
let user_uuid = &headers.user.uuid;
let user_id = &headers.user.uuid;
let policy_type = OrgPolicyType::PersonalOwnership;
if OrgPolicy::is_applicable_to_user(user_uuid, policy_type, None, conn).await {
if OrgPolicy::is_applicable_to_user(user_id, policy_type, None, conn).await {
err!("Due to an Enterprise Policy, you are restricted from saving items to your personal vault.")
}
}
@ -428,8 +428,8 @@ pub async fn update_cipher_from_data(
cipher.user_uuid = Some(headers.user.uuid.clone());
}
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() {
if let Some(ref folder_id) = data.folder_id {
if Folder::find_by_uuid_and_user(folder_id, &headers.user.uuid, conn).await.is_none() {
err!("Invalid folder", "Folder does not exist or belongs to another user");
}
}
@ -513,7 +513,7 @@ pub async fn update_cipher_from_data(
if ut != UpdateType::None {
// Only log events for organizational ciphers
if let Some(org_uuid) = &cipher.organization_uuid {
if let Some(org_id) = &cipher.organization_uuid {
let event_type = match (&ut, transfer_cipher) {
(UpdateType::SyncCipherCreate, true) => EventType::CipherCreated,
(UpdateType::SyncCipherUpdate, true) => EventType::CipherShared,
@ -523,7 +523,7 @@ pub async fn update_cipher_from_data(
log_event(
event_type as i32,
&cipher.uuid,
org_uuid,
org_id,
&headers.user.uuid,
headers.device.atype,
&headers.ip.ip,
@ -583,7 +583,7 @@ async fn post_ciphers_import(
Folder::find_by_user(&headers.user.uuid, &mut conn).await.into_iter().map(|f| Some(f.uuid)).collect();
let mut folders: Vec<FolderId> = Vec::with_capacity(data.folders.len());
for folder in data.folders.into_iter() {
let folder_uuid = if existing_folders.contains(&folder.id) {
let folder_id = if existing_folders.contains(&folder.id) {
folder.id.unwrap()
} else {
let mut new_folder = Folder::new(headers.user.uuid.clone(), folder.name);
@ -591,7 +591,7 @@ async fn post_ciphers_import(
new_folder.uuid
};
folders.push(folder_uuid);
folders.push(folder_id);
}
// Read the relations between folders and ciphers
@ -603,8 +603,8 @@ async fn post_ciphers_import(
// Read and create the ciphers
for (index, mut cipher_data) in data.ciphers.into_iter().enumerate() {
let folder_uuid = relations_map.get(&index).map(|i| folders[*i].clone());
cipher_data.folder_id = folder_uuid;
let folder_id = relations_map.get(&index).map(|i| folders[*i].clone());
cipher_data.folder_id = folder_id;
let mut cipher = Cipher::new(cipher_data.r#type, cipher_data.name.clone());
update_cipher_from_data(&mut cipher, cipher_data, &headers, None, &mut conn, &nt, UpdateType::None).await?;
@ -618,42 +618,42 @@ async fn post_ciphers_import(
}
/// Called when an org admin modifies an existing org cipher.
#[put("/ciphers/<uuid>/admin", data = "<data>")]
#[put("/ciphers/<cipher_id>/admin", data = "<data>")]
async fn put_cipher_admin(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CipherData>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
put_cipher(uuid, data, headers, conn, nt).await
put_cipher(cipher_id, data, headers, conn, nt).await
}
#[post("/ciphers/<uuid>/admin", data = "<data>")]
#[post("/ciphers/<cipher_id>/admin", data = "<data>")]
async fn post_cipher_admin(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CipherData>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
post_cipher(uuid, data, headers, conn, nt).await
post_cipher(cipher_id, data, headers, conn, nt).await
}
#[post("/ciphers/<uuid>", data = "<data>")]
#[post("/ciphers/<cipher_id>", data = "<data>")]
async fn post_cipher(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CipherData>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
put_cipher(uuid, data, headers, conn, nt).await
put_cipher(cipher_id, data, headers, conn, nt).await
}
#[put("/ciphers/<uuid>", data = "<data>")]
#[put("/ciphers/<cipher_id>", data = "<data>")]
async fn put_cipher(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CipherData>,
headers: Headers,
mut conn: DbConn,
@ -661,7 +661,7 @@ async fn put_cipher(
) -> JsonResult {
let data: CipherData = data.into_inner();
let Some(mut cipher) = Cipher::find_by_uuid(&uuid, &mut conn).await else {
let Some(mut cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else {
err!("Cipher doesn't exist")
};
@ -679,32 +679,32 @@ async fn put_cipher(
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
}
#[post("/ciphers/<uuid>/partial", data = "<data>")]
#[post("/ciphers/<cipher_id>/partial", data = "<data>")]
async fn post_cipher_partial(
uuid: CipherId,
cipher_id: CipherId,
data: Json<PartialCipherData>,
headers: Headers,
conn: DbConn,
) -> JsonResult {
put_cipher_partial(uuid, data, headers, conn).await
put_cipher_partial(cipher_id, data, headers, conn).await
}
// Only update the folder and favorite for the user, since this cipher is read-only
#[put("/ciphers/<uuid>/partial", data = "<data>")]
#[put("/ciphers/<cipher_id>/partial", data = "<data>")]
async fn put_cipher_partial(
uuid: CipherId,
cipher_id: CipherId,
data: Json<PartialCipherData>,
headers: Headers,
mut conn: DbConn,
) -> JsonResult {
let data: PartialCipherData = data.into_inner();
let Some(cipher) = Cipher::find_by_uuid(&uuid, &mut conn).await else {
let Some(cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else {
err!("Cipher 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() {
if let Some(ref folder_id) = data.folder_id {
if Folder::find_by_uuid_and_user(folder_id, &headers.user.uuid, &mut conn).await.is_none() {
err!("Invalid folder", "Folder does not exist or belongs to another user");
}
}
@ -724,26 +724,26 @@ struct CollectionsAdminData {
collection_ids: Vec<CollectionId>,
}
#[put("/ciphers/<uuid>/collections_v2", data = "<data>")]
#[put("/ciphers/<cipher_id>/collections_v2", data = "<data>")]
async fn put_collections2_update(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CollectionsAdminData>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
post_collections2_update(uuid, data, headers, conn, nt).await
post_collections2_update(cipher_id, data, headers, conn, nt).await
}
#[post("/ciphers/<uuid>/collections_v2", data = "<data>")]
#[post("/ciphers/<cipher_id>/collections_v2", data = "<data>")]
async fn post_collections2_update(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CollectionsAdminData>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
let cipher_details = post_collections_update(uuid, data, headers, conn, nt).await?;
let cipher_details = post_collections_update(cipher_id, data, headers, conn, nt).await?;
Ok(Json(json!({ // AttachmentUploadDataResponseModel
"object": "optionalCipherDetails",
"unavailable": false,
@ -751,20 +751,20 @@ async fn post_collections2_update(
})))
}
#[put("/ciphers/<uuid>/collections", data = "<data>")]
#[put("/ciphers/<cipher_id>/collections", data = "<data>")]
async fn put_collections_update(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CollectionsAdminData>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
post_collections_update(uuid, data, headers, conn, nt).await
post_collections_update(cipher_id, data, headers, conn, nt).await
}
#[post("/ciphers/<uuid>/collections", data = "<data>")]
#[post("/ciphers/<cipher_id>/collections", data = "<data>")]
async fn post_collections_update(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CollectionsAdminData>,
headers: Headers,
mut conn: DbConn,
@ -772,7 +772,7 @@ async fn post_collections_update(
) -> JsonResult {
let data: CollectionsAdminData = data.into_inner();
let Some(cipher) = Cipher::find_by_uuid(&uuid, &mut conn).await else {
let Some(cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else {
err!("Cipher doesn't exist")
};
@ -828,20 +828,20 @@ async fn post_collections_update(
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
}
#[put("/ciphers/<uuid>/collections-admin", data = "<data>")]
#[put("/ciphers/<cipher_id>/collections-admin", data = "<data>")]
async fn put_collections_admin(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CollectionsAdminData>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> EmptyResult {
post_collections_admin(uuid, data, headers, conn, nt).await
post_collections_admin(cipher_id, data, headers, conn, nt).await
}
#[post("/ciphers/<uuid>/collections-admin", data = "<data>")]
#[post("/ciphers/<cipher_id>/collections-admin", data = "<data>")]
async fn post_collections_admin(
uuid: CipherId,
cipher_id: CipherId,
data: Json<CollectionsAdminData>,
headers: Headers,
mut conn: DbConn,
@ -849,7 +849,7 @@ async fn post_collections_admin(
) -> EmptyResult {
let data: CollectionsAdminData = data.into_inner();
let Some(cipher) = Cipher::find_by_uuid(&uuid, &mut conn).await else {
let Some(cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else {
err!("Cipher doesn't exist")
};
@ -914,9 +914,9 @@ struct ShareCipherData {
collection_ids: Vec<CollectionId>,
}
#[post("/ciphers/<uuid>/share", data = "<data>")]
#[post("/ciphers/<cipher_id>/share", data = "<data>")]
async fn post_cipher_share(
uuid: CipherId,
cipher_id: CipherId,
data: Json<ShareCipherData>,
headers: Headers,
mut conn: DbConn,
@ -924,12 +924,12 @@ async fn post_cipher_share(
) -> JsonResult {
let data: ShareCipherData = data.into_inner();
share_cipher_by_uuid(&uuid, data, &headers, &mut conn, &nt).await
share_cipher_by_uuid(&cipher_id, data, &headers, &mut conn, &nt).await
}
#[put("/ciphers/<uuid>/share", data = "<data>")]
#[put("/ciphers/<cipher_id>/share", data = "<data>")]
async fn put_cipher_share(
uuid: CipherId,
cipher_id: CipherId,
data: Json<ShareCipherData>,
headers: Headers,
mut conn: DbConn,
@ -937,7 +937,7 @@ async fn put_cipher_share(
) -> JsonResult {
let data: ShareCipherData = data.into_inner();
share_cipher_by_uuid(&uuid, data, &headers, &mut conn, &nt).await
share_cipher_by_uuid(&cipher_id, data, &headers, &mut conn, &nt).await
}
#[derive(Deserialize)]
@ -986,13 +986,13 @@ async fn put_cipher_share_selected(
}
async fn share_cipher_by_uuid(
uuid: &CipherId,
cipher_id: &CipherId,
data: ShareCipherData,
headers: &Headers,
conn: &mut DbConn,
nt: &Notify<'_>,
) -> JsonResult {
let mut cipher = match Cipher::find_by_uuid(uuid, conn).await {
let mut cipher = match Cipher::find_by_uuid(cipher_id, conn).await {
Some(cipher) => {
if cipher.is_write_accessible_to_user(&headers.user.uuid, conn).await {
cipher
@ -1005,9 +1005,9 @@ async fn share_cipher_by_uuid(
let mut shared_to_collections = vec![];
if let Some(organization_uuid) = &data.cipher.organization_id {
for uuid in &data.collection_ids {
match Collection::find_by_uuid_and_org(uuid, organization_uuid, conn).await {
if let Some(organization_id) = &data.cipher.organization_id {
for col_id in &data.collection_ids {
match Collection::find_by_uuid_and_org(col_id, organization_id, conn).await {
None => err!("Invalid collection ID provided"),
Some(collection) => {
if collection.is_writable_by_user(&headers.user.uuid, conn).await {
@ -1039,9 +1039,14 @@ async fn share_cipher_by_uuid(
/// Upstream added this v2 API to support direct download of attachments from
/// their object storage service. For self-hosted instances, it basically just
/// redirects to the same location as before the v2 API.
#[get("/ciphers/<uuid>/attachment/<attachment_id>")]
async fn get_attachment(uuid: CipherId, attachment_id: AttachmentId, headers: Headers, mut conn: DbConn) -> JsonResult {
let Some(cipher) = Cipher::find_by_uuid(&uuid, &mut conn).await else {
#[get("/ciphers/<cipher_id>/attachment/<attachment_id>")]
async fn get_attachment(
cipher_id: CipherId,
attachment_id: AttachmentId,
headers: Headers,
mut conn: DbConn,
) -> JsonResult {
let Some(cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else {
err!("Cipher doesn't exist")
};
@ -1050,7 +1055,7 @@ async fn get_attachment(uuid: CipherId, attachment_id: AttachmentId, headers: He
}
match Attachment::find_by_id(&attachment_id, &mut conn).await {
Some(attachment) if uuid == attachment.cipher_uuid => Ok(Json(attachment.to_json(&headers.host))),
Some(attachment) if cipher_id == attachment.cipher_uuid => Ok(Json(attachment.to_json(&headers.host))),
Some(_) => err!("Attachment doesn't belong to cipher"),
None => err!("Attachment doesn't exist"),
}
@ -1074,14 +1079,14 @@ enum FileUploadType {
/// This redirects the client to the API it should use to upload the attachment.
/// For upstream's cloud-hosted service, it's an Azure object storage API.
/// For self-hosted instances, it's another API on the local instance.
#[post("/ciphers/<uuid>/attachment/v2", data = "<data>")]
#[post("/ciphers/<cipher_id>/attachment/v2", data = "<data>")]
async fn post_attachment_v2(
uuid: CipherId,
cipher_id: CipherId,
data: Json<AttachmentRequestData>,
headers: Headers,
mut conn: DbConn,
) -> JsonResult {
let Some(cipher) = Cipher::find_by_uuid(&uuid, &mut conn).await else {
let Some(cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else {
err!("Cipher doesn't exist")
};
@ -1131,7 +1136,7 @@ struct UploadData<'f> {
/// database record, which is passed in as `attachment`.
async fn save_attachment(
mut attachment: Option<Attachment>,
cipher_uuid: CipherId,
cipher_id: CipherId,
data: Form<UploadData<'_>>,
headers: &Headers,
mut conn: DbConn,
@ -1146,7 +1151,7 @@ async fn save_attachment(
err!("Attachment size can't be negative")
}
let Some(cipher) = Cipher::find_by_uuid(&cipher_uuid, &mut conn).await else {
let Some(cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else {
err!("Cipher doesn't exist")
};
@ -1161,11 +1166,11 @@ async fn save_attachment(
Some(a) => a.file_size, // v2 API
};
let size_limit = if let Some(ref user_uuid) = cipher.user_uuid {
let size_limit = if let Some(ref user_id) = cipher.user_uuid {
match CONFIG.user_attachment_limit() {
Some(0) => err!("Attachments are disabled"),
Some(limit_kb) => {
let already_used = Attachment::size_by_user(user_uuid, &mut conn).await;
let already_used = Attachment::size_by_user(user_id, &mut conn).await;
let left = limit_kb
.checked_mul(1024)
.and_then(|l| l.checked_sub(already_used))
@ -1183,11 +1188,11 @@ async fn save_attachment(
}
None => None,
}
} else if let Some(ref org_uuid) = cipher.organization_uuid {
} else if let Some(ref org_id) = cipher.organization_uuid {
match CONFIG.org_attachment_limit() {
Some(0) => err!("Attachments are disabled"),
Some(limit_kb) => {
let already_used = Attachment::size_by_org(org_uuid, &mut conn).await;
let already_used = Attachment::size_by_org(org_id, &mut conn).await;
let left = limit_kb
.checked_mul(1024)
.and_then(|l| l.checked_sub(already_used))
@ -1260,11 +1265,11 @@ async fn save_attachment(
err!("No attachment key provided")
}
let attachment =
Attachment::new(file_id.clone(), cipher_uuid.clone(), encrypted_filename.unwrap(), size, data.key);
Attachment::new(file_id.clone(), cipher_id.clone(), encrypted_filename.unwrap(), size, data.key);
attachment.save(&mut conn).await.expect("Error saving attachment");
}
let folder_path = tokio::fs::canonicalize(&CONFIG.attachments_folder()).await?.join(cipher_uuid.as_ref());
let folder_path = tokio::fs::canonicalize(&CONFIG.attachments_folder()).await?.join(cipher_id.as_ref());
let file_path = folder_path.join(file_id.as_ref());
tokio::fs::create_dir_all(&folder_path).await?;
@ -1282,11 +1287,11 @@ async fn save_attachment(
)
.await;
if let Some(org_uuid) = &cipher.organization_uuid {
if let Some(org_id) = &cipher.organization_uuid {
log_event(
EventType::CipherAttachmentCreated as i32,
&cipher.uuid,
org_uuid,
org_id,
&headers.user.uuid,
headers.device.atype,
&headers.ip.ip,
@ -1300,11 +1305,11 @@ async fn save_attachment(
/// v2 API for uploading the actual data content of an attachment.
/// This route needs a rank specified so that Rocket prioritizes the
/// /ciphers/<uuid>/attachment/v2 route, which would otherwise conflict
/// /ciphers/<cipher_id>/attachment/v2 route, which would otherwise conflict
/// with this one.
#[post("/ciphers/<uuid>/attachment/<attachment_id>", format = "multipart/form-data", data = "<data>", rank = 1)]
#[post("/ciphers/<cipher_id>/attachment/<attachment_id>", format = "multipart/form-data", data = "<data>", rank = 1)]
async fn post_attachment_v2_data(
uuid: CipherId,
cipher_id: CipherId,
attachment_id: AttachmentId,
data: Form<UploadData<'_>>,
headers: Headers,
@ -1312,20 +1317,20 @@ async fn post_attachment_v2_data(
nt: Notify<'_>,
) -> EmptyResult {
let attachment = match Attachment::find_by_id(&attachment_id, &mut conn).await {
Some(attachment) if uuid == attachment.cipher_uuid => Some(attachment),
Some(attachment) if cipher_id == attachment.cipher_uuid => Some(attachment),
Some(_) => err!("Attachment doesn't belong to cipher"),
None => err!("Attachment doesn't exist"),
};
save_attachment(attachment, uuid, data, &headers, conn, nt).await?;
save_attachment(attachment, cipher_id, data, &headers, conn, nt).await?;
Ok(())
}
/// Legacy API for creating an attachment associated with a cipher.
#[post("/ciphers/<uuid>/attachment", format = "multipart/form-data", data = "<data>")]
#[post("/ciphers/<cipher_id>/attachment", format = "multipart/form-data", data = "<data>")]
async fn post_attachment(
uuid: CipherId,
cipher_id: CipherId,
data: Form<UploadData<'_>>,
headers: Headers,
conn: DbConn,
@ -1335,111 +1340,121 @@ async fn post_attachment(
// the attachment database record as well as saving the data to disk.
let attachment = None;
let (cipher, mut conn) = save_attachment(attachment, uuid, data, &headers, conn, nt).await?;
let (cipher, mut conn) = save_attachment(attachment, cipher_id, data, &headers, conn, nt).await?;
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
}
#[post("/ciphers/<uuid>/attachment-admin", format = "multipart/form-data", data = "<data>")]
#[post("/ciphers/<cipher_id>/attachment-admin", format = "multipart/form-data", data = "<data>")]
async fn post_attachment_admin(
uuid: CipherId,
cipher_id: CipherId,
data: Form<UploadData<'_>>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
post_attachment(uuid, data, headers, conn, nt).await
post_attachment(cipher_id, data, headers, conn, nt).await
}
#[post("/ciphers/<uuid>/attachment/<attachment_id>/share", format = "multipart/form-data", data = "<data>")]
#[post("/ciphers/<cipher_id>/attachment/<attachment_id>/share", format = "multipart/form-data", data = "<data>")]
async fn post_attachment_share(
uuid: CipherId,
cipher_id: CipherId,
attachment_id: AttachmentId,
data: Form<UploadData<'_>>,
headers: Headers,
mut conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
_delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &nt).await?;
post_attachment(uuid, data, headers, conn, nt).await
_delete_cipher_attachment_by_id(&cipher_id, &attachment_id, &headers, &mut conn, &nt).await?;
post_attachment(cipher_id, data, headers, conn, nt).await
}
#[post("/ciphers/<uuid>/attachment/<attachment_id>/delete-admin")]
#[post("/ciphers/<cipher_id>/attachment/<attachment_id>/delete-admin")]
async fn delete_attachment_post_admin(
uuid: CipherId,
cipher_id: CipherId,
attachment_id: AttachmentId,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> EmptyResult {
delete_attachment(uuid, attachment_id, headers, conn, nt).await
delete_attachment(cipher_id, attachment_id, headers, conn, nt).await
}
#[post("/ciphers/<uuid>/attachment/<attachment_id>/delete")]
#[post("/ciphers/<cipher_id>/attachment/<attachment_id>/delete")]
async fn delete_attachment_post(
uuid: CipherId,
cipher_id: CipherId,
attachment_id: AttachmentId,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> EmptyResult {
delete_attachment(uuid, attachment_id, headers, conn, nt).await
delete_attachment(cipher_id, attachment_id, headers, conn, nt).await
}
#[delete("/ciphers/<uuid>/attachment/<attachment_id>")]
#[delete("/ciphers/<cipher_id>/attachment/<attachment_id>")]
async fn delete_attachment(
uuid: CipherId,
cipher_id: CipherId,
attachment_id: AttachmentId,
headers: Headers,
mut conn: DbConn,
nt: Notify<'_>,
) -> EmptyResult {
_delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &nt).await
_delete_cipher_attachment_by_id(&cipher_id, &attachment_id, &headers, &mut conn, &nt).await
}
#[delete("/ciphers/<uuid>/attachment/<attachment_id>/admin")]
#[delete("/ciphers/<cipher_id>/attachment/<attachment_id>/admin")]
async fn delete_attachment_admin(
uuid: CipherId,
cipher_id: CipherId,
attachment_id: AttachmentId,
headers: Headers,
mut conn: DbConn,
nt: Notify<'_>,
) -> EmptyResult {
_delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &mut conn, &nt).await
_delete_cipher_attachment_by_id(&cipher_id, &attachment_id, &headers, &mut conn, &nt).await
}
#[post("/ciphers/<uuid>/delete")]
async fn delete_cipher_post(uuid: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &nt).await
#[post("/ciphers/<cipher_id>/delete")]
async fn delete_cipher_post(cipher_id: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&cipher_id, &headers, &mut conn, false, &nt).await
// permanent delete
}
#[post("/ciphers/<uuid>/delete-admin")]
async fn delete_cipher_post_admin(uuid: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &nt).await
#[post("/ciphers/<cipher_id>/delete-admin")]
async fn delete_cipher_post_admin(
cipher_id: CipherId,
headers: Headers,
mut conn: DbConn,
nt: Notify<'_>,
) -> EmptyResult {
_delete_cipher_by_uuid(&cipher_id, &headers, &mut conn, false, &nt).await
// permanent delete
}
#[put("/ciphers/<uuid>/delete")]
async fn delete_cipher_put(uuid: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&uuid, &headers, &mut conn, true, &nt).await
#[put("/ciphers/<cipher_id>/delete")]
async fn delete_cipher_put(cipher_id: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&cipher_id, &headers, &mut conn, true, &nt).await
// soft delete
}
#[put("/ciphers/<uuid>/delete-admin")]
async fn delete_cipher_put_admin(uuid: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&uuid, &headers, &mut conn, true, &nt).await
#[put("/ciphers/<cipher_id>/delete-admin")]
async fn delete_cipher_put_admin(
cipher_id: CipherId,
headers: Headers,
mut conn: DbConn,
nt: Notify<'_>,
) -> EmptyResult {
_delete_cipher_by_uuid(&cipher_id, &headers, &mut conn, true, &nt).await
}
#[delete("/ciphers/<uuid>")]
async fn delete_cipher(uuid: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &nt).await
#[delete("/ciphers/<cipher_id>")]
async fn delete_cipher(cipher_id: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&cipher_id, &headers, &mut conn, false, &nt).await
// permanent delete
}
#[delete("/ciphers/<uuid>/admin")]
async fn delete_cipher_admin(uuid: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&uuid, &headers, &mut conn, false, &nt).await
#[delete("/ciphers/<cipher_id>/admin")]
async fn delete_cipher_admin(cipher_id: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
_delete_cipher_by_uuid(&cipher_id, &headers, &mut conn, false, &nt).await
// permanent delete
}
@ -1503,14 +1518,19 @@ async fn delete_cipher_selected_put_admin(
_delete_multiple_ciphers(data, headers, conn, true, nt).await // soft delete
}
#[put("/ciphers/<uuid>/restore")]
async fn restore_cipher_put(uuid: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
_restore_cipher_by_uuid(&uuid, &headers, &mut conn, &nt).await
#[put("/ciphers/<cipher_id>/restore")]
async fn restore_cipher_put(cipher_id: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
_restore_cipher_by_uuid(&cipher_id, &headers, &mut conn, &nt).await
}
#[put("/ciphers/<uuid>/restore-admin")]
async fn restore_cipher_put_admin(uuid: CipherId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
_restore_cipher_by_uuid(&uuid, &headers, &mut conn, &nt).await
#[put("/ciphers/<cipher_id>/restore-admin")]
async fn restore_cipher_put_admin(
cipher_id: CipherId,
headers: Headers,
mut conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
_restore_cipher_by_uuid(&cipher_id, &headers, &mut conn, &nt).await
}
#[put("/ciphers/restore", data = "<data>")]
@ -1538,30 +1558,30 @@ async fn move_cipher_selected(
nt: Notify<'_>,
) -> EmptyResult {
let data = data.into_inner();
let user_uuid = headers.user.uuid;
let user_id = headers.user.uuid;
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() {
if let Some(ref folder_id) = data.folder_id {
if Folder::find_by_uuid_and_user(folder_id, &user_id, &mut conn).await.is_none() {
err!("Invalid folder", "Folder does not exist or belongs to another user");
}
}
for uuid in data.ids {
let Some(cipher) = Cipher::find_by_uuid(&uuid, &mut conn).await else {
for cipher_id in data.ids {
let Some(cipher) = Cipher::find_by_uuid(&cipher_id, &mut conn).await else {
err!("Cipher doesn't exist")
};
if !cipher.is_accessible_to_user(&user_uuid, &mut conn).await {
if !cipher.is_accessible_to_user(&user_id, &mut conn).await {
err!("Cipher is not accessible by user")
}
// Move cipher
cipher.move_to_folder(data.folder_id.clone(), &user_uuid, &mut conn).await?;
cipher.move_to_folder(data.folder_id.clone(), &user_id, &mut conn).await?;
nt.send_cipher_update(
UpdateType::SyncCipherUpdate,
&cipher,
&[user_uuid.clone()],
&[user_id.clone()],
&headers.device.uuid,
None,
&mut conn,
@ -1650,13 +1670,13 @@ async fn delete_all(
}
async fn _delete_cipher_by_uuid(
uuid: &CipherId,
cipher_id: &CipherId,
headers: &Headers,
conn: &mut DbConn,
soft_delete: bool,
nt: &Notify<'_>,
) -> EmptyResult {
let Some(mut cipher) = Cipher::find_by_uuid(uuid, conn).await else {
let Some(mut cipher) = Cipher::find_by_uuid(cipher_id, conn).await else {
err!("Cipher doesn't exist")
};
@ -1689,13 +1709,13 @@ async fn _delete_cipher_by_uuid(
.await;
}
if let Some(org_uuid) = cipher.organization_uuid {
if let Some(org_id) = cipher.organization_uuid {
let event_type = match soft_delete {
true => EventType::CipherSoftDeleted as i32,
false => EventType::CipherDeleted as i32,
};
log_event(event_type, &cipher.uuid, &org_uuid, &headers.user.uuid, headers.device.atype, &headers.ip.ip, conn)
log_event(event_type, &cipher.uuid, &org_id, &headers.user.uuid, headers.device.atype, &headers.ip.ip, conn)
.await;
}
@ -1717,8 +1737,8 @@ async fn _delete_multiple_ciphers(
) -> EmptyResult {
let data = data.into_inner();
for uuid in data.ids {
if let error @ Err(_) = _delete_cipher_by_uuid(&uuid, &headers, &mut conn, soft_delete, &nt).await {
for cipher_id in data.ids {
if let error @ Err(_) = _delete_cipher_by_uuid(&cipher_id, &headers, &mut conn, soft_delete, &nt).await {
return error;
};
}
@ -1726,8 +1746,13 @@ async fn _delete_multiple_ciphers(
Ok(())
}
async fn _restore_cipher_by_uuid(uuid: &CipherId, headers: &Headers, conn: &mut DbConn, nt: &Notify<'_>) -> JsonResult {
let Some(mut cipher) = Cipher::find_by_uuid(uuid, conn).await else {
async fn _restore_cipher_by_uuid(
cipher_id: &CipherId,
headers: &Headers,
conn: &mut DbConn,
nt: &Notify<'_>,
) -> JsonResult {
let Some(mut cipher) = Cipher::find_by_uuid(cipher_id, conn).await else {
err!("Cipher doesn't exist")
};
@ -1748,11 +1773,11 @@ async fn _restore_cipher_by_uuid(uuid: &CipherId, headers: &Headers, conn: &mut
)
.await;
if let Some(org_uuid) = &cipher.organization_uuid {
if let Some(org_id) = &cipher.organization_uuid {
log_event(
EventType::CipherRestored as i32,
&cipher.uuid.clone(),
org_uuid,
org_id,
&headers.user.uuid,
headers.device.atype,
&headers.ip.ip,
@ -1773,8 +1798,8 @@ async fn _restore_multiple_ciphers(
let data = data.into_inner();
let mut ciphers: Vec<Value> = Vec::new();
for uuid in data.ids {
match _restore_cipher_by_uuid(&uuid, headers, conn, nt).await {
for cipher_id in data.ids {
match _restore_cipher_by_uuid(&cipher_id, headers, conn, nt).await {
Ok(json) => ciphers.push(json.into_inner()),
err => return err,
}
@ -1788,7 +1813,7 @@ async fn _restore_multiple_ciphers(
}
async fn _delete_cipher_attachment_by_id(
uuid: &CipherId,
cipher_id: &CipherId,
attachment_id: &AttachmentId,
headers: &Headers,
conn: &mut DbConn,
@ -1798,11 +1823,11 @@ async fn _delete_cipher_attachment_by_id(
err!("Attachment doesn't exist")
};
if &attachment.cipher_uuid != uuid {
if &attachment.cipher_uuid != cipher_id {
err!("Attachment from other cipher")
}
let Some(cipher) = Cipher::find_by_uuid(uuid, conn).await else {
let Some(cipher) = Cipher::find_by_uuid(cipher_id, conn).await else {
err!("Cipher doesn't exist")
};
@ -1822,11 +1847,11 @@ async fn _delete_cipher_attachment_by_id(
)
.await;
if let Some(org_uuid) = cipher.organization_uuid {
if let Some(org_id) = cipher.organization_uuid {
log_event(
EventType::CipherAttachmentDeleted as i32,
&cipher.uuid,
&org_uuid,
&org_id,
&headers.user.uuid,
headers.device.atype,
&headers.ip.ip,
@ -1859,17 +1884,17 @@ pub enum CipherSyncType {
}
impl CipherSyncData {
pub async fn new(user_uuid: &UserId, sync_type: CipherSyncType, conn: &mut DbConn) -> Self {
pub async fn new(user_id: &UserId, sync_type: CipherSyncType, conn: &mut DbConn) -> Self {
let cipher_folders: HashMap<CipherId, FolderId>;
let cipher_favorites: HashSet<CipherId>;
match sync_type {
// User Sync supports Folders and Favorites
CipherSyncType::User => {
// Generate a HashMap with the Cipher UUID as key and the Folder UUID as value
cipher_folders = FolderCipher::find_by_user(user_uuid, conn).await.into_iter().collect();
cipher_folders = FolderCipher::find_by_user(user_id, conn).await.into_iter().collect();
// Generate a HashSet of all the Cipher UUID's which are marked as favorite
cipher_favorites = Favorite::get_all_cipher_uuid_by_user(user_uuid, conn).await.into_iter().collect();
cipher_favorites = Favorite::get_all_cipher_uuid_by_user(user_id, conn).await.into_iter().collect();
}
// Organization Sync does not support Folders and Favorites.
// If these are set, it will cause issues in the web-vault.
@ -1880,15 +1905,15 @@ impl CipherSyncData {
}
// Generate a list of Cipher UUID's containing a Vec with one or more Attachment records
let orgs = Membership::get_orgs_by_user(user_uuid, conn).await;
let attachments = Attachment::find_all_by_user_and_orgs(user_uuid, &orgs, conn).await;
let orgs = Membership::get_orgs_by_user(user_id, conn).await;
let attachments = Attachment::find_all_by_user_and_orgs(user_id, &orgs, conn).await;
let mut cipher_attachments: HashMap<CipherId, Vec<Attachment>> = HashMap::with_capacity(attachments.len());
for attachment in attachments {
cipher_attachments.entry(attachment.cipher_uuid.clone()).or_default().push(attachment);
}
// Generate a HashMap with the Cipher UUID as key and one or more Collection UUID's
let user_cipher_collections = Cipher::get_collections_with_cipher_by_user(user_uuid.clone(), conn).await;
let user_cipher_collections = Cipher::get_collections_with_cipher_by_user(user_id.clone(), conn).await;
let mut cipher_collections: HashMap<CipherId, Vec<CollectionId>> =
HashMap::with_capacity(user_cipher_collections.len());
for (cipher, collection) in user_cipher_collections {
@ -1897,10 +1922,10 @@ impl CipherSyncData {
// Generate a HashMap with the Organization UUID as key and the Membership record
let members: HashMap<OrganizationId, Membership> =
Membership::find_by_user(user_uuid, conn).await.into_iter().map(|m| (m.org_uuid.clone(), m)).collect();
Membership::find_by_user(user_id, conn).await.into_iter().map(|m| (m.org_uuid.clone(), m)).collect();
// Generate a HashMap with the User_Collections UUID as key and the CollectionUser record
let user_collections: HashMap<CollectionId, CollectionUser> = CollectionUser::find_by_user(user_uuid, conn)
let user_collections: HashMap<CollectionId, CollectionUser> = CollectionUser::find_by_user(user_id, conn)
.await
.into_iter()
.map(|uc| (uc.collection_uuid.clone(), uc))
@ -1908,7 +1933,7 @@ impl CipherSyncData {
// Generate a HashMap with the collections_uuid as key and the CollectionGroup record
let user_collections_groups: HashMap<CollectionId, CollectionGroup> = if CONFIG.org_groups_enabled() {
CollectionGroup::find_by_user(user_uuid, conn)
CollectionGroup::find_by_user(user_id, conn)
.await
.into_iter()
.map(|collection_group| (collection_group.collections_uuid.clone(), collection_group))
@ -1919,7 +1944,7 @@ impl CipherSyncData {
// Get all organizations that the given user has full access to via group assignment
let user_group_full_access_for_organizations: HashSet<OrganizationId> = if CONFIG.org_groups_enabled() {
Group::get_orgs_by_user_with_full_access(user_uuid, conn).await.into_iter().collect()
Group::get_orgs_by_user_with_full_access(user_id, conn).await.into_iter().collect()
} else {
HashSet::new()
};

Datei anzeigen

@ -701,11 +701,11 @@ async fn policies_emergency_access(emer_id: &str, headers: Headers, mut conn: Db
fn is_valid_request(
emergency_access: &EmergencyAccess,
requesting_user_uuid: &UserId,
requesting_user_id: &UserId,
requested_access_type: EmergencyAccessType,
) -> bool {
emergency_access.grantee_uuid.is_some()
&& emergency_access.grantee_uuid.as_ref().unwrap() == requesting_user_uuid
&& emergency_access.grantee_uuid.as_ref().unwrap() == requesting_user_id
&& emergency_access.status == EmergencyAccessStatus::RecoveryApproved as i32
&& emergency_access.atype == requested_access_type as i32
}

Datei anzeigen

@ -180,11 +180,11 @@ async fn post_events_collect(data: Json<Vec<EventCollection>>, headers: Headers,
.await;
}
1600..=1699 => {
if let Some(org_uuid) = &event.organization_id {
if let Some(org_id) = &event.organization_id {
_log_event(
event.r#type,
org_uuid,
org_uuid,
org_id,
org_id,
&headers.user.uuid,
headers.device.atype,
Some(event_date),
@ -197,11 +197,11 @@ async fn post_events_collect(data: Json<Vec<EventCollection>>, headers: Headers,
_ => {
if let Some(cipher_uuid) = &event.cipher_id {
if let Some(cipher) = Cipher::find_by_uuid(cipher_uuid, &mut conn).await {
if let Some(org_uuid) = cipher.organization_uuid {
if let Some(org_id) = cipher.organization_uuid {
_log_event(
event.r#type,
cipher_uuid,
&org_uuid,
&org_id,
&headers.user.uuid,
headers.device.atype,
Some(event_date),
@ -218,38 +218,38 @@ async fn post_events_collect(data: Json<Vec<EventCollection>>, headers: Headers,
Ok(())
}
pub async fn log_user_event(event_type: i32, user_uuid: &UserId, device_type: i32, ip: &IpAddr, conn: &mut DbConn) {
pub async fn log_user_event(event_type: i32, user_id: &UserId, device_type: i32, ip: &IpAddr, conn: &mut DbConn) {
if !CONFIG.org_events_enabled() {
return;
}
_log_user_event(event_type, user_uuid, device_type, None, ip, conn).await;
_log_user_event(event_type, user_id, device_type, None, ip, conn).await;
}
async fn _log_user_event(
event_type: i32,
user_uuid: &UserId,
user_id: &UserId,
device_type: i32,
event_date: Option<NaiveDateTime>,
ip: &IpAddr,
conn: &mut DbConn,
) {
let orgs = Membership::get_orgs_by_user(user_uuid, conn).await;
let orgs = Membership::get_orgs_by_user(user_id, conn).await;
let mut events: Vec<Event> = Vec::with_capacity(orgs.len() + 1); // We need an event per org and one without an org
// Upstream saves the event also without any org_uuid.
// Upstream saves the event also without any org_id.
let mut event = Event::new(event_type, event_date);
event.user_uuid = Some(user_uuid.clone());
event.act_user_uuid = Some(user_uuid.to_string());
event.user_uuid = Some(user_id.clone());
event.act_user_uuid = Some(user_id.to_string());
event.device_type = Some(device_type);
event.ip_address = Some(ip.to_string());
events.push(event);
// For each org a user is a member of store these events per org
for org_uuid in orgs {
for org_id in orgs {
let mut event = Event::new(event_type, event_date);
event.user_uuid = Some(user_uuid.clone());
event.org_uuid = Some(org_uuid);
event.act_user_uuid = Some(user_uuid.to_string());
event.user_uuid = Some(user_id.clone());
event.org_uuid = Some(org_id);
event.act_user_uuid = Some(user_id.to_string());
event.device_type = Some(device_type);
event.ip_address = Some(ip.to_string());
events.push(event);
@ -261,8 +261,8 @@ async fn _log_user_event(
pub async fn log_event(
event_type: i32,
source_uuid: &str,
org_uuid: &OrganizationId,
act_user_uuid: &str,
org_id: &OrganizationId,
act_user_id: &str,
device_type: i32,
ip: &IpAddr,
conn: &mut DbConn,
@ -270,15 +270,15 @@ pub async fn log_event(
if !CONFIG.org_events_enabled() {
return;
}
_log_event(event_type, source_uuid, org_uuid, act_user_uuid, device_type, None, ip, conn).await;
_log_event(event_type, source_uuid, org_id, act_user_id, device_type, None, ip, conn).await;
}
#[allow(clippy::too_many_arguments)]
async fn _log_event(
event_type: i32,
source_uuid: &str,
org_uuid: &OrganizationId,
act_user_uuid: &str,
org_id: &OrganizationId,
act_user_id: &str,
device_type: i32,
event_date: Option<NaiveDateTime>,
ip: &IpAddr,
@ -313,8 +313,8 @@ async fn _log_event(
_ => {}
}
event.org_uuid = Some(org_uuid.clone());
event.act_user_uuid = Some(String::from(act_user_uuid));
event.org_uuid = Some(org_id.clone());
event.act_user_uuid = Some(String::from(act_user_id));
event.device_type = Some(device_type);
event.ip_address = Some(ip.to_string());
event.save(conn).await.unwrap_or(());

Datei anzeigen

@ -23,9 +23,9 @@ async fn get_folders(headers: Headers, mut conn: DbConn) -> Json<Value> {
}))
}
#[get("/folders/<uuid>")]
async fn get_folder(uuid: FolderId, headers: Headers, mut conn: DbConn) -> JsonResult {
match Folder::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await {
#[get("/folders/<folder_id>")]
async fn get_folder(folder_id: FolderId, headers: Headers, mut conn: DbConn) -> JsonResult {
match Folder::find_by_uuid_and_user(&folder_id, &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"),
}
@ -50,20 +50,20 @@ async fn post_folders(data: Json<FolderData>, headers: Headers, mut conn: DbConn
Ok(Json(folder.to_json()))
}
#[post("/folders/<uuid>", data = "<data>")]
#[post("/folders/<folder_id>", data = "<data>")]
async fn post_folder(
uuid: FolderId,
folder_id: FolderId,
data: Json<FolderData>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
put_folder(uuid, data, headers, conn, nt).await
put_folder(folder_id, data, headers, conn, nt).await
}
#[put("/folders/<uuid>", data = "<data>")]
#[put("/folders/<folder_id>", data = "<data>")]
async fn put_folder(
uuid: FolderId,
folder_id: FolderId,
data: Json<FolderData>,
headers: Headers,
mut conn: DbConn,
@ -71,7 +71,7 @@ async fn put_folder(
) -> JsonResult {
let data: FolderData = data.into_inner();
let Some(mut folder) = Folder::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await else {
let Some(mut folder) = Folder::find_by_uuid_and_user(&folder_id, &headers.user.uuid, &mut conn).await else {
err!("Invalid folder", "Folder does not exist or belongs to another user")
};
@ -83,14 +83,14 @@ async fn put_folder(
Ok(Json(folder.to_json()))
}
#[post("/folders/<uuid>/delete")]
async fn delete_folder_post(uuid: FolderId, headers: Headers, conn: DbConn, nt: Notify<'_>) -> EmptyResult {
delete_folder(uuid, headers, conn, nt).await
#[post("/folders/<folder_id>/delete")]
async fn delete_folder_post(folder_id: FolderId, headers: Headers, conn: DbConn, nt: Notify<'_>) -> EmptyResult {
delete_folder(folder_id, headers, conn, nt).await
}
#[delete("/folders/<uuid>")]
async fn delete_folder(uuid: FolderId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
let Some(folder) = Folder::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await else {
#[delete("/folders/<folder_id>")]
async fn delete_folder(folder_id: FolderId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
let Some(folder) = Folder::find_by_uuid_and_user(&folder_id, &headers.user.uuid, &mut conn).await else {
err!("Invalid folder", "Folder does not exist or belongs to another user")
};

Datei anzeigen

@ -753,14 +753,13 @@ async fn get_org_details(data: OrgIdData, headers: Headers, mut conn: DbConn) ->
})))
}
async fn _get_org_details(org_id: &OrganizationId, host: &str, user_uuid: &UserId, conn: &mut DbConn) -> Value {
async fn _get_org_details(org_id: &OrganizationId, host: &str, user_id: &UserId, conn: &mut DbConn) -> Value {
let ciphers = Cipher::find_by_org(org_id, conn).await;
let cipher_sync_data = CipherSyncData::new(user_uuid, CipherSyncType::Organization, conn).await;
let cipher_sync_data = CipherSyncData::new(user_id, CipherSyncType::Organization, conn).await;
let mut ciphers_json = Vec::with_capacity(ciphers.len());
for c in ciphers {
ciphers_json
.push(c.to_json(host, user_uuid, Some(&cipher_sync_data), CipherSyncType::Organization, conn).await);
ciphers_json.push(c.to_json(host, user_id, Some(&cipher_sync_data), CipherSyncType::Organization, conn).await);
}
json!(ciphers_json)
}

Datei anzeigen

@ -219,11 +219,11 @@ impl<'r> FromRequest<'r> for PublicToken {
Outcome::Success(conn) => conn,
_ => err_handler!("Error getting DB"),
};
let Some(org_uuid) = claims.client_id.strip_prefix("organization.") else {
let Some(org_id) = claims.client_id.strip_prefix("organization.") else {
err_handler!("Malformed client_id")
};
let org_uuid: OrganizationId = org_uuid.to_string().into();
let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(&org_uuid, &conn).await else {
let org_id: OrganizationId = org_id.to_string().into();
let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(&org_id, &conn).await else {
err_handler!("Invalid client_id")
};
if org_api_key.org_uuid != claims.client_sub {

Datei anzeigen

@ -79,9 +79,9 @@ pub struct SendData {
/// There is also a Vaultwarden-specific `sends_allowed` config setting that
/// controls this policy globally.
async fn enforce_disable_send_policy(headers: &Headers, conn: &mut DbConn) -> EmptyResult {
let user_uuid = &headers.user.uuid;
let user_id = &headers.user.uuid;
if !CONFIG.sends_allowed()
|| OrgPolicy::is_applicable_to_user(user_uuid, OrgPolicyType::DisableSend, None, conn).await
|| OrgPolicy::is_applicable_to_user(user_id, OrgPolicyType::DisableSend, None, conn).await
{
err!("Due to an Enterprise Policy, you are only able to delete an existing Send.")
}
@ -95,9 +95,9 @@ async fn enforce_disable_send_policy(headers: &Headers, conn: &mut DbConn) -> Em
///
/// Ref: https://bitwarden.com/help/article/policies/#send-options
async fn enforce_disable_hide_email_policy(data: &SendData, headers: &Headers, conn: &mut DbConn) -> EmptyResult {
let user_uuid = &headers.user.uuid;
let user_id = &headers.user.uuid;
let hide_email = data.hide_email.unwrap_or(false);
if hide_email && OrgPolicy::is_hide_email_disabled(user_uuid, conn).await {
if hide_email && OrgPolicy::is_hide_email_disabled(user_id, conn).await {
err!(
"Due to an Enterprise Policy, you are not allowed to hide your email address \
from recipients when creating or editing a Send."
@ -106,7 +106,7 @@ async fn enforce_disable_hide_email_policy(data: &SendData, headers: &Headers, c
Ok(())
}
fn create_send(data: SendData, user_uuid: UserId) -> ApiResult<Send> {
fn create_send(data: SendData, user_id: UserId) -> ApiResult<Send> {
let data_val = if data.r#type == SendType::Text as i32 {
data.text
} else if data.r#type == SendType::File as i32 {
@ -129,7 +129,7 @@ fn create_send(data: SendData, user_uuid: UserId) -> ApiResult<Send> {
}
let mut send = Send::new(data.r#type, data.name, data_str, data.key, data.deletion_date.naive_utc());
send.user_uuid = Some(user_uuid);
send.user_uuid = Some(user_id);
send.notes = data.notes;
send.max_access_count = match data.max_access_count {
Some(m) => Some(m.into_i32()?),
@ -157,11 +157,11 @@ async fn get_sends(headers: Headers, mut conn: DbConn) -> Json<Value> {
}))
}
#[get("/sends/<uuid>")]
async fn get_send(uuid: SendId, headers: Headers, mut conn: DbConn) -> JsonResult {
match Send::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await {
#[get("/sends/<send_id>")]
async fn get_send(send_id: SendId, headers: Headers, mut conn: DbConn) -> JsonResult {
match Send::find_by_uuid_and_user(&send_id, &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"),
None => err!("Send not found", "Invalid send uuid or does not belong to user"),
}
}
@ -352,9 +352,9 @@ pub struct SendFileData {
}
// https://github.com/bitwarden/server/blob/66f95d1c443490b653e5a15d32977e2f5a3f9e32/src/Api/Tools/Controllers/SendsController.cs#L250
#[post("/sends/<uuid>/file/<file_id>", format = "multipart/form-data", data = "<data>")]
#[post("/sends/<send_id>/file/<file_id>", format = "multipart/form-data", data = "<data>")]
async fn post_send_file_v2_data(
uuid: SendId,
send_id: SendId,
file_id: SendFileId,
data: Form<UploadDataV2<'_>>,
headers: Headers,
@ -365,8 +365,8 @@ async fn post_send_file_v2_data(
let mut data = data.into_inner();
let Some(send) = Send::find_by_uuid_and_user(&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.")
let Some(send) = Send::find_by_uuid_and_user(&send_id, &headers.user.uuid, &mut conn).await else {
err!("Send not found. Unable to save the file.", "Invalid send uuid or does not belong to user.")
};
if send.atype != SendType::File as i32 {
@ -402,7 +402,7 @@ async fn post_send_file_v2_data(
err!("Send file size does not match.", format!("Expected a file size of {} got {size}", send_data.size));
}
let folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(uuid);
let folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(send_id);
let file_path = folder_path.join(file_id);
// Check if the file already exists, if that is the case do not overwrite it
@ -493,16 +493,16 @@ async fn post_access(
Ok(Json(send.to_json_access(&mut conn).await))
}
#[post("/sends/<uuid>/access/file/<file_id>", data = "<data>")]
#[post("/sends/<send_id>/access/file/<file_id>", data = "<data>")]
async fn post_access_file(
uuid: SendId,
send_id: SendId,
file_id: SendFileId,
data: Json<SendAccessData>,
host: Host,
mut conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
let Some(mut send) = Send::find_by_uuid(&uuid, &mut conn).await else {
let Some(mut send) = Send::find_by_uuid(&send_id, &mut conn).await else {
err_code!(SEND_INACCESSIBLE_MSG, 404)
};
@ -547,28 +547,28 @@ async fn post_access_file(
)
.await;
let token_claims = crate::auth::generate_send_claims(&uuid, &file_id);
let token_claims = crate::auth::generate_send_claims(&send_id, &file_id);
let token = crate::auth::encode_jwt(&token_claims);
Ok(Json(json!({
"object": "send-fileDownload",
"id": file_id,
"url": format!("{}/api/sends/{}/{}?t={}", &host.host, uuid, file_id, token)
"url": format!("{}/api/sends/{}/{}?t={}", &host.host, send_id, file_id, token)
})))
}
#[get("/sends/<uuid>/<file_id>?<t>")]
async fn download_send(uuid: SendId, file_id: SendFileId, t: &str) -> Option<NamedFile> {
#[get("/sends/<send_id>/<file_id>?<t>")]
async fn download_send(send_id: SendId, file_id: SendFileId, t: &str) -> Option<NamedFile> {
if let Ok(claims) = crate::auth::decode_send(t) {
if claims.sub == format!("{uuid}/{file_id}") {
return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(uuid).join(file_id)).await.ok();
if claims.sub == format!("{send_id}/{file_id}") {
return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(send_id).join(file_id)).await.ok();
}
}
None
}
#[put("/sends/<uuid>", data = "<data>")]
#[put("/sends/<send_id>", data = "<data>")]
async fn put_send(
uuid: SendId,
send_id: SendId,
data: Json<SendData>,
headers: Headers,
mut conn: DbConn,
@ -579,8 +579,8 @@ async fn put_send(
let data: SendData = data.into_inner();
enforce_disable_hide_email_policy(&data, &headers, &mut conn).await?;
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")
let Some(mut send) = Send::find_by_uuid_and_user(&send_id, &headers.user.uuid, &mut conn).await else {
err!("Send not found", "Send send_id is invalid or does not belong to user")
};
update_send_from_data(&mut send, data, &headers, &mut conn, &nt, UpdateType::SyncSendUpdate).await?;
@ -646,9 +646,9 @@ pub async fn update_send_from_data(
Ok(())
}
#[delete("/sends/<uuid>")]
async fn delete_send(uuid: SendId, 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 {
#[delete("/sends/<send_id>")]
async fn delete_send(send_id: SendId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
let Some(send) = Send::find_by_uuid_and_user(&send_id, &headers.user.uuid, &mut conn).await else {
err!("Send not found", "Invalid send uuid, or does not belong to user")
};
@ -665,11 +665,11 @@ async fn delete_send(uuid: SendId, headers: Headers, mut conn: DbConn, nt: Notif
Ok(())
}
#[put("/sends/<uuid>/remove-password")]
async fn put_remove_password(uuid: SendId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
#[put("/sends/<send_id>/remove-password")]
async fn put_remove_password(send_id: SendId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
enforce_disable_send_policy(&headers, &mut conn).await?;
let Some(mut send) = Send::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await else {
let Some(mut send) = Send::find_by_uuid_and_user(&send_id, &headers.user.uuid, &mut conn).await else {
err!("Send not found", "Invalid send uuid, or does not belong to user")
};

Datei anzeigen

@ -95,7 +95,7 @@ async fn activate_authenticator_put(data: Json<EnableAuthenticatorData>, headers
}
pub async fn validate_totp_code_str(
user_uuid: &UserId,
user_id: &UserId,
totp_code: &str,
secret: &str,
ip: &ClientIp,
@ -105,11 +105,11 @@ pub async fn validate_totp_code_str(
err!("TOTP code is not a number");
}
validate_totp_code(user_uuid, totp_code, secret, ip, conn).await
validate_totp_code(user_id, totp_code, secret, ip, conn).await
}
pub async fn validate_totp_code(
user_uuid: &UserId,
user_id: &UserId,
totp_code: &str,
secret: &str,
ip: &ClientIp,
@ -121,11 +121,11 @@ pub async fn validate_totp_code(
err!("Invalid TOTP secret")
};
let mut twofactor =
match TwoFactor::find_by_user_and_type(user_uuid, TwoFactorType::Authenticator as i32, conn).await {
Some(tf) => tf,
_ => TwoFactor::new(user_uuid.clone(), TwoFactorType::Authenticator, secret.to_string()),
};
let mut twofactor = match TwoFactor::find_by_user_and_type(user_id, TwoFactorType::Authenticator as i32, conn).await
{
Some(tf) => tf,
_ => TwoFactor::new(user_id.clone(), TwoFactorType::Authenticator, secret.to_string()),
};
// The amount of steps back and forward in time
// Also check if we need to disable time drifted TOTP codes.

Datei anzeigen

@ -228,11 +228,11 @@ const AUTH_PREFIX: &str = "AUTH";
const DUO_PREFIX: &str = "TX";
const APP_PREFIX: &str = "APP";
async fn get_user_duo_data(user_uuid: &UserId, conn: &mut DbConn) -> DuoStatus {
async fn get_user_duo_data(user_id: &UserId, conn: &mut DbConn) -> DuoStatus {
let type_ = TwoFactorType::Duo as i32;
// If the user doesn't have an entry, disabled
let Some(twofactor) = TwoFactor::find_by_user_and_type(user_uuid, type_, conn).await else {
let Some(twofactor) = TwoFactor::find_by_user_and_type(user_id, type_, conn).await else {
return DuoStatus::Disabled(DuoData::global().is_some());
};

Datei anzeigen

@ -59,10 +59,9 @@ async fn send_email_login(data: Json<SendEmailLoginData>, mut conn: DbConn) -> E
}
/// Generate the token, save the data for later verification and send email to user
pub async fn send_token(user_uuid: &UserId, conn: &mut DbConn) -> EmptyResult {
pub async fn send_token(user_id: &UserId, conn: &mut DbConn) -> EmptyResult {
let type_ = TwoFactorType::Email as i32;
let mut twofactor =
TwoFactor::find_by_user_and_type(user_uuid, type_, conn).await.map_res("Two factor not found")?;
let mut twofactor = TwoFactor::find_by_user_and_type(user_id, type_, conn).await.map_res("Two factor not found")?;
let generated_token = crypto::generate_email_token(CONFIG.email_token_size());
@ -198,9 +197,9 @@ async fn email(data: Json<EmailData>, headers: Headers, mut conn: DbConn) -> Jso
}
/// Validate the email code when used as TwoFactor token mechanism
pub async fn validate_email_code_str(user_uuid: &UserId, token: &str, data: &str, conn: &mut DbConn) -> EmptyResult {
pub async fn validate_email_code_str(user_id: &UserId, token: &str, data: &str, conn: &mut DbConn) -> EmptyResult {
let mut email_data = EmailTokenData::from_json(data)?;
let mut twofactor = TwoFactor::find_by_user_and_type(user_uuid, TwoFactorType::Email as i32, conn)
let mut twofactor = TwoFactor::find_by_user_and_type(user_id, TwoFactorType::Email as i32, conn)
.await
.map_res("Two factor not found")?;
let Some(issued_token) = &email_data.last_token else {
@ -327,8 +326,8 @@ pub fn obscure_email(email: &str) -> String {
format!("{}@{}", new_name, &domain)
}
pub async fn find_and_activate_email_2fa(user_uuid: &UserId, conn: &mut DbConn) -> EmptyResult {
if let Some(user) = User::find_by_uuid(user_uuid, conn).await {
pub async fn find_and_activate_email_2fa(user_id: &UserId, conn: &mut DbConn) -> EmptyResult {
if let Some(user) = User::find_by_uuid(user_id, conn).await {
activate_email_2fa(&user, conn).await
} else {
err!("User not found!");

Datei anzeigen

@ -173,7 +173,7 @@ async fn disable_twofactor_put(data: Json<DisableTwoFactorData>, headers: Header
pub async fn enforce_2fa_policy(
user: &User,
act_uuid: &str,
act_user_id: &str,
device_type: i32,
ip: &std::net::IpAddr,
conn: &mut DbConn,
@ -195,7 +195,7 @@ pub async fn enforce_2fa_policy(
EventType::OrganizationUserRevoked as i32,
&member.uuid,
&member.org_uuid,
act_uuid,
act_user_id,
device_type,
ip,
conn,
@ -208,14 +208,14 @@ pub async fn enforce_2fa_policy(
}
pub async fn enforce_2fa_policy_for_org(
org_uuid: &OrganizationId,
act_uuid: &str,
org_id: &OrganizationId,
act_user_id: &str,
device_type: i32,
ip: &std::net::IpAddr,
conn: &mut DbConn,
) -> EmptyResult {
let org = Organization::find_by_uuid(org_uuid, conn).await.unwrap();
for member in Membership::find_confirmed_by_org(org_uuid, conn).await.into_iter() {
let org = Organization::find_by_uuid(org_id, conn).await.unwrap();
for member in Membership::find_confirmed_by_org(org_id, conn).await.into_iter() {
// Don't enforce the policy for Admins and Owners.
if member.atype < MembershipType::Admin && TwoFactor::find_by_user(&member.user_uuid, conn).await.is_empty() {
if CONFIG.mail_enabled() {
@ -229,8 +229,8 @@ pub async fn enforce_2fa_policy_for_org(
log_event(
EventType::OrganizationUserRevoked as i32,
&member.uuid,
org_uuid,
act_uuid,
org_id,
act_user_id,
device_type,
ip,
conn,

Datei anzeigen

@ -104,11 +104,11 @@ async fn verify_otp(data: Json<ProtectedActionVerify>, headers: Headers, mut con
pub async fn validate_protected_action_otp(
otp: &str,
user_uuid: &UserId,
user_id: &UserId,
delete_if_valid: bool,
conn: &mut DbConn,
) -> EmptyResult {
let pa = TwoFactor::find_by_user_and_type(user_uuid, TwoFactorType::ProtectedActions as i32, conn)
let pa = TwoFactor::find_by_user_and_type(user_id, TwoFactorType::ProtectedActions as i32, conn)
.await
.map_res("Protected action token not found, try sending the code again or restart the process")?;
let mut pa_data = ProtectedActionData::from_json(&pa.data)?;

Datei anzeigen

@ -352,20 +352,20 @@ async fn delete_webauthn(data: Json<DeleteU2FData>, headers: Headers, mut conn:
}
pub async fn get_webauthn_registrations(
user_uuid: &UserId,
user_id: &UserId,
conn: &mut DbConn,
) -> Result<(bool, Vec<WebauthnRegistration>), Error> {
let type_ = TwoFactorType::Webauthn as i32;
match TwoFactor::find_by_user_and_type(user_uuid, type_, conn).await {
match TwoFactor::find_by_user_and_type(user_id, type_, conn).await {
Some(tf) => Ok((tf.enabled, serde_json::from_str(&tf.data)?)),
None => Ok((false, Vec::new())), // If no data, return empty list
}
}
pub async fn generate_webauthn_login(user_uuid: &UserId, conn: &mut DbConn) -> JsonResult {
pub async fn generate_webauthn_login(user_id: &UserId, conn: &mut DbConn) -> JsonResult {
// Load saved credentials
let creds: Vec<Credential> =
get_webauthn_registrations(user_uuid, conn).await?.1.into_iter().map(|r| r.credential).collect();
get_webauthn_registrations(user_id, conn).await?.1.into_iter().map(|r| r.credential).collect();
if creds.is_empty() {
err!("No Webauthn devices registered")
@ -376,7 +376,7 @@ pub async fn generate_webauthn_login(user_uuid: &UserId, conn: &mut DbConn) -> J
let (response, state) = WebauthnConfig::load().generate_challenge_authenticate_options(creds, Some(ext))?;
// Save the challenge state for later validation
TwoFactor::new(user_uuid.clone(), TwoFactorType::WebauthnLoginChallenge, serde_json::to_string(&state)?)
TwoFactor::new(user_id.clone(), TwoFactorType::WebauthnLoginChallenge, serde_json::to_string(&state)?)
.save(conn)
.await?;
@ -384,9 +384,9 @@ pub async fn generate_webauthn_login(user_uuid: &UserId, conn: &mut DbConn) -> J
Ok(Json(serde_json::to_value(response.public_key)?))
}
pub async fn validate_webauthn_login(user_uuid: &UserId, response: &str, conn: &mut DbConn) -> EmptyResult {
pub async fn validate_webauthn_login(user_id: &UserId, response: &str, conn: &mut DbConn) -> EmptyResult {
let type_ = TwoFactorType::WebauthnLoginChallenge as i32;
let state = match TwoFactor::find_by_user_and_type(user_uuid, type_, conn).await {
let state = match TwoFactor::find_by_user_and_type(user_id, type_, conn).await {
Some(tf) => {
let state: AuthenticationState = serde_json::from_str(&tf.data)?;
tf.delete(conn).await?;
@ -403,7 +403,7 @@ pub async fn validate_webauthn_login(user_uuid: &UserId, response: &str, conn: &
let rsp: PublicKeyCredentialCopy = serde_json::from_str(response)?;
let rsp: PublicKeyCredential = rsp.into();
let mut registrations = get_webauthn_registrations(user_uuid, conn).await?.1;
let mut registrations = get_webauthn_registrations(user_id, conn).await?.1;
// If the credential we received is migrated from U2F, enable the U2F compatibility
//let use_u2f = registrations.iter().any(|r| r.migrated && r.credential.cred_id == rsp.raw_id.0);
@ -413,7 +413,7 @@ pub async fn validate_webauthn_login(user_uuid: &UserId, response: &str, conn: &
if &reg.credential.cred_id == cred_id {
reg.credential.counter = auth_data.counter;
TwoFactor::new(user_uuid.clone(), TwoFactorType::Webauthn, serde_json::to_string(&registrations)?)
TwoFactor::new(user_id.clone(), TwoFactorType::Webauthn, serde_json::to_string(&registrations)?)
.save(conn)
.await?;
return Ok(());

Datei anzeigen

@ -92,10 +92,10 @@ async fn generate_yubikey(data: Json<PasswordOrOtpData>, headers: Headers, mut c
data.validate(&user, false, &mut conn).await?;
let user_uuid = &user.uuid;
let user_id = &user.uuid;
let yubikey_type = TwoFactorType::YubiKey as i32;
let r = TwoFactor::find_by_user_and_type(user_uuid, yubikey_type, &mut conn).await;
let r = TwoFactor::find_by_user_and_type(user_id, yubikey_type, &mut conn).await;
if let Some(r) = r {
let yubikey_metadata: YubikeyMetadata = serde_json::from_str(&r.data)?;

Datei anzeigen

@ -31,7 +31,7 @@ pub fn routes() -> Vec<Route> {
async fn login(data: Form<ConnectData>, client_header: ClientHeaders, mut conn: DbConn) -> JsonResult {
let data: ConnectData = data.into_inner();
let mut user_uuid: Option<UserId> = None;
let mut user_id: Option<UserId> = None;
let login_result = match data.grant_type.as_ref() {
"refresh_token" => {
@ -48,7 +48,7 @@ async fn login(data: Form<ConnectData>, client_header: ClientHeaders, mut conn:
_check_is_some(&data.device_name, "device_name cannot be blank")?;
_check_is_some(&data.device_type, "device_type cannot be blank")?;
_password_login(data, &mut user_uuid, &mut conn, &client_header.ip).await
_password_login(data, &mut user_id, &mut conn, &client_header.ip).await
}
"client_credentials" => {
_check_is_some(&data.client_id, "client_id cannot be blank")?;
@ -59,17 +59,17 @@ async fn login(data: Form<ConnectData>, client_header: ClientHeaders, mut conn:
_check_is_some(&data.device_name, "device_name cannot be blank")?;
_check_is_some(&data.device_type, "device_type cannot be blank")?;
_api_key_login(data, &mut user_uuid, &mut conn, &client_header.ip).await
_api_key_login(data, &mut user_id, &mut conn, &client_header.ip).await
}
t => err!("Invalid type", t),
};
if let Some(user_uuid) = user_uuid {
if let Some(user_id) = user_id {
match &login_result {
Ok(_) => {
log_user_event(
EventType::UserLoggedIn as i32,
&user_uuid,
&user_id,
client_header.device_type,
&client_header.ip.ip,
&mut conn,
@ -80,7 +80,7 @@ async fn login(data: Form<ConnectData>, client_header: ClientHeaders, mut conn:
if let Some(ev) = e.get_event() {
log_user_event(
ev.event as i32,
&user_uuid,
&user_id,
client_header.device_type,
&client_header.ip.ip,
&mut conn,
@ -141,7 +141,7 @@ struct MasterPasswordPolicy {
async fn _password_login(
data: ConnectData,
user_uuid: &mut Option<UserId>,
user_id: &mut Option<UserId>,
conn: &mut DbConn,
ip: &ClientIp,
) -> JsonResult {
@ -161,8 +161,8 @@ async fn _password_login(
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.
*user_uuid = Some(user.uuid.clone());
// Set the user_id here to be passed back used for event logging.
*user_id = Some(user.uuid.clone());
// Check if the user is disabled
if !user.enabled {
@ -359,7 +359,7 @@ async fn _password_login(
async fn _api_key_login(
data: ConnectData,
user_uuid: &mut Option<UserId>,
user_id: &mut Option<UserId>,
conn: &mut DbConn,
ip: &ClientIp,
) -> JsonResult {
@ -368,7 +368,7 @@ async fn _api_key_login(
// Validate scope
match data.scope.as_ref().unwrap().as_ref() {
"api" => _user_api_key_login(data, user_uuid, conn, ip).await,
"api" => _user_api_key_login(data, user_id, conn, ip).await,
"api.organization" => _organization_api_key_login(data, conn, ip).await,
_ => err!("Scope not supported"),
}
@ -376,22 +376,22 @@ async fn _api_key_login(
async fn _user_api_key_login(
data: ConnectData,
user_uuid: &mut Option<UserId>,
user_id: &mut Option<UserId>,
conn: &mut DbConn,
ip: &ClientIp,
) -> JsonResult {
// Get the user via the client_id
let client_id = data.client_id.as_ref().unwrap();
let Some(client_user_uuid) = client_id.strip_prefix("user.") else {
let Some(client_user_id) = client_id.strip_prefix("user.") else {
err!("Malformed client_id", format!("IP: {}.", ip.ip))
};
let client_user_uuid: UserId = client_user_uuid.into();
let Some(user) = User::find_by_uuid(&client_user_uuid, conn).await else {
let client_user_id: UserId = client_user_id.into();
let Some(user) = User::find_by_uuid(&client_user_id, conn).await else {
err!("Invalid client_id", format!("IP: {}.", ip.ip))
};
// Set the user_uuid here to be passed back used for event logging.
*user_uuid = Some(user.uuid.clone());
// Set the user_id here to be passed back used for event logging.
*user_id = Some(user.uuid.clone());
// Check if the user is disabled
if !user.enabled {
@ -470,11 +470,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 Some(org_uuid) = client_id.strip_prefix("organization.") else {
let Some(org_id) = client_id.strip_prefix("organization.") else {
err!("Malformed client_id", format!("IP: {}.", ip.ip))
};
let org_uuid: OrganizationId = org_uuid.to_string().into();
let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(&org_uuid, conn).await else {
let org_id: OrganizationId = org_id.to_string().into();
let Some(org_api_key) = OrganizationApiKey::find_by_org_uuid(&org_id, conn).await else {
err!("Invalid client_id", format!("IP: {}.", ip.ip))
};
@ -616,7 +616,7 @@ fn _selected_data(tf: Option<TwoFactor>) -> ApiResult<String> {
async fn _json_err_twofactor(
providers: &[i32],
user_uuid: &UserId,
user_id: &UserId,
data: &ConnectData,
conn: &mut DbConn,
) -> ApiResult<Value> {
@ -637,12 +637,12 @@ async fn _json_err_twofactor(
Some(TwoFactorType::Authenticator) => { /* Nothing to do for TOTP */ }
Some(TwoFactorType::Webauthn) if CONFIG.domain_set() => {
let request = webauthn::generate_webauthn_login(user_uuid, conn).await?;
let request = webauthn::generate_webauthn_login(user_id, conn).await?;
result["TwoFactorProviders2"][provider.to_string()] = request.0;
}
Some(TwoFactorType::Duo) => {
let email = match User::find_by_uuid(user_uuid, conn).await {
let email = match User::find_by_uuid(user_id, conn).await {
Some(u) => u.email,
None => err!("User does not exist"),
};
@ -674,7 +674,7 @@ async fn _json_err_twofactor(
}
Some(tf_type @ TwoFactorType::YubiKey) => {
let Some(twofactor) = TwoFactor::find_by_user_and_type(user_uuid, tf_type as i32, conn).await else {
let Some(twofactor) = TwoFactor::find_by_user_and_type(user_id, tf_type as i32, conn).await else {
err!("No YubiKey devices registered")
};
@ -686,13 +686,13 @@ async fn _json_err_twofactor(
}
Some(tf_type @ TwoFactorType::Email) => {
let Some(twofactor) = TwoFactor::find_by_user_and_type(user_uuid, tf_type as i32, conn).await else {
let Some(twofactor) = TwoFactor::find_by_user_and_type(user_id, tf_type as i32, conn).await else {
err!("No twofactor email registered")
};
// Send email immediately if email is the only 2FA option
if providers.len() == 1 {
email::send_token(user_uuid, conn).await?
email::send_token(user_id, conn).await?
}
let email_data = email::EmailTokenData::from_json(&twofactor.data)?;

Datei anzeigen

@ -328,8 +328,8 @@ pub struct WebSocketUsers {
}
impl WebSocketUsers {
async fn send_update(&self, user_uuid: &UserId, data: &[u8]) {
if let Some(user) = self.map.get(user_uuid.as_ref()).map(|v| v.clone()) {
async fn send_update(&self, user_id: &UserId, data: &[u8]) {
if let Some(user) = self.map.get(user_id.as_ref()).map(|v| v.clone()) {
for (_, sender) in user.iter() {
if let Err(e) = sender.send(Message::binary(data)).await {
error!("Error sending WS update {e}");
@ -413,7 +413,7 @@ impl WebSocketUsers {
&self,
ut: UpdateType,
cipher: &Cipher,
user_uuids: &[UserId],
user_ids: &[UserId],
acting_device_uuid: &DeviceId,
collection_uuids: Option<Vec<CollectionId>>,
conn: &mut DbConn,
@ -422,10 +422,10 @@ impl WebSocketUsers {
if *NOTIFICATIONS_DISABLED {
return;
}
let org_uuid = convert_option(cipher.organization_uuid.as_deref());
let org_id = convert_option(cipher.organization_uuid.as_deref());
// Depending if there are collections provided or not, we need to have different values for the following variables.
// The user_uuid should be `null`, and the revision date should be set to now, else the clients won't sync the collection change.
let (user_uuid, collection_uuids, revision_date) = if let Some(collection_uuids) = collection_uuids {
let (user_id, collection_uuids, revision_date) = if let Some(collection_uuids) = collection_uuids {
(
Value::Nil,
Value::Array(collection_uuids.into_iter().map(|v| v.to_string().into()).collect::<Vec<Value>>()),
@ -438,8 +438,8 @@ impl WebSocketUsers {
let data = create_update(
vec![
("Id".into(), cipher.uuid.to_string().into()),
("UserId".into(), user_uuid),
("OrganizationId".into(), org_uuid),
("UserId".into(), user_id),
("OrganizationId".into(), org_id),
("CollectionIds".into(), collection_uuids),
("RevisionDate".into(), revision_date),
],
@ -448,12 +448,12 @@ impl WebSocketUsers {
);
if CONFIG.enable_websocket() {
for uuid in user_uuids {
for uuid in user_ids {
self.send_update(uuid, &data).await;
}
}
if CONFIG.push_enabled() && user_uuids.len() == 1 {
if CONFIG.push_enabled() && user_ids.len() == 1 {
push_cipher_update(ut, cipher, acting_device_uuid, conn).await;
}
}
@ -462,7 +462,7 @@ impl WebSocketUsers {
&self,
ut: UpdateType,
send: &DbSend,
user_uuids: &[UserId],
user_ids: &[UserId],
acting_device_uuid: &DeviceId,
conn: &mut DbConn,
) {
@ -470,12 +470,12 @@ impl WebSocketUsers {
if *NOTIFICATIONS_DISABLED {
return;
}
let user_uuid = convert_option(send.user_uuid.as_deref());
let user_id = convert_option(send.user_uuid.as_deref());
let data = create_update(
vec![
("Id".into(), send.uuid.to_string().into()),
("UserId".into(), user_uuid),
("UserId".into(), user_id),
("RevisionDate".into(), serialize_date(send.revision_date)),
],
ut,
@ -483,18 +483,18 @@ impl WebSocketUsers {
);
if CONFIG.enable_websocket() {
for uuid in user_uuids {
for uuid in user_ids {
self.send_update(uuid, &data).await;
}
}
if CONFIG.push_enabled() && user_uuids.len() == 1 {
if CONFIG.push_enabled() && user_ids.len() == 1 {
push_send_update(ut, send, acting_device_uuid, conn).await;
}
}
pub async fn send_auth_request(
&self,
user_uuid: &UserId,
user_id: &UserId,
auth_request_uuid: &String,
acting_device_uuid: &DeviceId,
conn: &mut DbConn,
@ -504,22 +504,22 @@ impl WebSocketUsers {
return;
}
let data = create_update(
vec![("Id".into(), auth_request_uuid.clone().into()), ("UserId".into(), user_uuid.to_string().into())],
vec![("Id".into(), auth_request_uuid.clone().into()), ("UserId".into(), user_id.to_string().into())],
UpdateType::AuthRequest,
Some(acting_device_uuid.to_string()),
);
if CONFIG.enable_websocket() {
self.send_update(user_uuid, &data).await;
self.send_update(user_id, &data).await;
}
if CONFIG.push_enabled() {
push_auth_request(user_uuid.clone(), auth_request_uuid.to_string(), conn).await;
push_auth_request(user_id.clone(), auth_request_uuid.to_string(), conn).await;
}
}
pub async fn send_auth_response(
&self,
user_uuid: &UserId,
user_id: &UserId,
auth_response_uuid: &str,
approving_device_uuid: DeviceId,
conn: &mut DbConn,
@ -529,16 +529,16 @@ impl WebSocketUsers {
return;
}
let data = create_update(
vec![("Id".into(), auth_response_uuid.to_owned().into()), ("UserId".into(), user_uuid.to_string().into())],
vec![("Id".into(), auth_response_uuid.to_owned().into()), ("UserId".into(), user_id.to_string().into())],
UpdateType::AuthRequestResponse,
Some(approving_device_uuid.to_string()),
);
if CONFIG.enable_websocket() {
self.send_update(user_uuid, &data).await;
self.send_update(user_id, &data).await;
}
if CONFIG.push_enabled() {
push_auth_response(user_uuid.clone(), auth_response_uuid.to_string(), approving_device_uuid, conn).await;
push_auth_response(user_id.clone(), auth_response_uuid.to_string(), approving_device_uuid, conn).await;
}
}
}
@ -557,16 +557,16 @@ impl AnonymousWebSocketSubscriptions {
}
}
pub async fn send_auth_response(&self, user_uuid: &UserId, auth_response_uuid: &str) {
pub async fn send_auth_response(&self, user_id: &UserId, auth_response_uuid: &str) {
if !CONFIG.enable_websocket() {
return;
}
let data = create_anonymous_update(
vec![("Id".into(), auth_response_uuid.to_owned().into()), ("UserId".into(), user_uuid.to_string().into())],
vec![("Id".into(), auth_response_uuid.to_owned().into()), ("UserId".into(), user_id.to_string().into())],
UpdateType::AuthRequestResponse,
user_uuid.clone(),
user_id.clone(),
);
self.send_update(user_uuid, &data).await;
self.send_update(user_id, &data).await;
}
}

Datei anzeigen

@ -126,15 +126,15 @@ pub async fn register_push_device(device: &mut Device, conn: &mut crate::db::DbC
Ok(())
}
pub async fn unregister_push_device(push_uuid: Option<String>) -> EmptyResult {
if !CONFIG.push_enabled() || push_uuid.is_none() {
pub async fn unregister_push_device(push_id: Option<String>) -> EmptyResult {
if !CONFIG.push_enabled() || push_id.is_none() {
return Ok(());
}
let auth_push_token = get_auth_push_token().await?;
let auth_header = format!("Bearer {}", &auth_push_token);
match make_http_request(Method::DELETE, &(CONFIG.push_relay_uri() + "/push/" + &push_uuid.unwrap()))?
match make_http_request(Method::DELETE, &(CONFIG.push_relay_uri() + "/push/" + &push_id.unwrap()))?
.header(AUTHORIZATION, auth_header)
.send()
.await
@ -148,24 +148,24 @@ pub async fn unregister_push_device(push_uuid: Option<String>) -> EmptyResult {
pub async fn push_cipher_update(
ut: UpdateType,
cipher: &Cipher,
acting_device_uuid: &DeviceId,
acting_device_id: &DeviceId,
conn: &mut crate::db::DbConn,
) {
// We shouldn't send a push notification on cipher update if the cipher belongs to an organization, this isn't implemented in the upstream server too.
if cipher.organization_uuid.is_some() {
return;
};
let Some(user_uuid) = &cipher.user_uuid else {
let Some(user_id) = &cipher.user_uuid else {
debug!("Cipher has no uuid");
return;
};
if Device::check_user_has_push_device(user_uuid, conn).await {
if Device::check_user_has_push_device(user_id, conn).await {
send_to_push_relay(json!({
"userId": user_uuid,
"userId": user_id,
"organizationId": (),
"deviceId": acting_device_uuid,
"identifier": acting_device_uuid,
"deviceId": acting_device_id,
"identifier": acting_device_id,
"type": ut as i32,
"payload": {
"Id": cipher.uuid,
@ -178,14 +178,14 @@ pub async fn push_cipher_update(
}
}
pub fn push_logout(user: &User, acting_device_uuid: Option<String>) {
let acting_device_uuid: Value = acting_device_uuid.map(|v| v.into()).unwrap_or_else(|| Value::Null);
pub fn push_logout(user: &User, acting_device_id: Option<String>) {
let acting_device_id: Value = acting_device_id.map(|v| v.into()).unwrap_or_else(|| Value::Null);
tokio::task::spawn(send_to_push_relay(json!({
"userId": user.uuid,
"organizationId": (),
"deviceId": acting_device_uuid,
"identifier": acting_device_uuid,
"deviceId": acting_device_id,
"identifier": acting_device_id,
"type": UpdateType::LogOut as i32,
"payload": {
"UserId": user.uuid,
@ -211,15 +211,15 @@ pub fn push_user_update(ut: UpdateType, user: &User) {
pub async fn push_folder_update(
ut: UpdateType,
folder: &Folder,
acting_device_uuid: &DeviceId,
acting_device_id: &DeviceId,
conn: &mut crate::db::DbConn,
) {
if Device::check_user_has_push_device(&folder.user_uuid, conn).await {
tokio::task::spawn(send_to_push_relay(json!({
"userId": folder.user_uuid,
"organizationId": (),
"deviceId": acting_device_uuid,
"identifier": acting_device_uuid,
"deviceId": acting_device_id,
"identifier": acting_device_id,
"type": ut as i32,
"payload": {
"Id": folder.uuid,
@ -230,19 +230,14 @@ pub async fn push_folder_update(
}
}
pub async fn push_send_update(
ut: UpdateType,
send: &Send,
acting_device_uuid: &DeviceId,
conn: &mut crate::db::DbConn,
) {
pub async fn push_send_update(ut: UpdateType, send: &Send, acting_device_id: &DeviceId, conn: &mut crate::db::DbConn) {
if let Some(s) = &send.user_uuid {
if Device::check_user_has_push_device(s, conn).await {
tokio::task::spawn(send_to_push_relay(json!({
"userId": send.user_uuid,
"organizationId": (),
"deviceId": acting_device_uuid,
"identifier": acting_device_uuid,
"deviceId": acting_device_id,
"identifier": acting_device_id,
"type": ut as i32,
"payload": {
"Id": send.uuid,
@ -289,38 +284,38 @@ async fn send_to_push_relay(notification_data: Value) {
};
}
pub async fn push_auth_request(user_uuid: UserId, auth_request_uuid: String, conn: &mut crate::db::DbConn) {
if Device::check_user_has_push_device(&user_uuid, conn).await {
pub async fn push_auth_request(user_id: UserId, auth_request_id: String, conn: &mut crate::db::DbConn) {
if Device::check_user_has_push_device(&user_id, conn).await {
tokio::task::spawn(send_to_push_relay(json!({
"userId": user_uuid,
"userId": user_id,
"organizationId": (),
"deviceId": null,
"identifier": null,
"type": UpdateType::AuthRequest as i32,
"payload": {
"Id": auth_request_uuid,
"UserId": user_uuid,
"Id": auth_request_id,
"UserId": user_id,
}
})));
}
}
pub async fn push_auth_response(
user_uuid: UserId,
auth_request_uuid: String,
approving_device_uuid: DeviceId,
user_id: UserId,
auth_request_id: String,
approving_device_id: DeviceId,
conn: &mut crate::db::DbConn,
) {
if Device::check_user_has_push_device(&user_uuid, conn).await {
if Device::check_user_has_push_device(&user_id, conn).await {
tokio::task::spawn(send_to_push_relay(json!({
"userId": user_uuid,
"userId": user_id,
"organizationId": (),
"deviceId": approving_device_uuid,
"identifier": approving_device_uuid,
"deviceId": approving_device_id,
"identifier": approving_device_id,
"type": UpdateType::AuthRequestResponse as i32,
"payload": {
"Id": auth_request_uuid,
"UserId": user_uuid,
"Id": auth_request_id,
"UserId": user_id,
}
})));
}

Datei anzeigen

@ -196,16 +196,16 @@ async fn web_files(p: PathBuf) -> Cached<Option<NamedFile>> {
Cached::long(NamedFile::open(Path::new(&CONFIG.web_vault_folder()).join(p)).await.ok(), true)
}
#[get("/attachments/<uuid>/<file_id>?<token>")]
async fn attachments(uuid: CipherId, file_id: AttachmentId, token: String) -> Option<NamedFile> {
#[get("/attachments/<cipher_id>/<file_id>?<token>")]
async fn attachments(cipher_id: CipherId, file_id: AttachmentId, token: String) -> Option<NamedFile> {
let Ok(claims) = decode_file_download(&token) else {
return None;
};
if claims.sub != uuid || claims.file_id != file_id {
if claims.sub != cipher_id || claims.file_id != file_id {
return None;
}
NamedFile::open(Path::new(&CONFIG.attachments_folder()).join(uuid.as_ref()).join(file_id.as_ref())).await.ok()
NamedFile::open(Path::new(&CONFIG.attachments_folder()).join(cipher_id.as_ref()).join(file_id.as_ref())).await.ok()
}
// We use DbConn here to let the alive healthcheck also verify the database connection.

Datei anzeigen

@ -482,19 +482,19 @@ impl<'r> FromRequest<'r> for Headers {
err_handler!("Invalid claim")
};
let device_uuid = claims.device;
let user_uuid = claims.sub;
let device_id = claims.device;
let user_id = claims.sub;
let mut conn = match DbConn::from_request(request).await {
Outcome::Success(conn) => conn,
_ => err_handler!("Error getting DB"),
};
let Some(device) = Device::find_by_uuid_and_user(&device_uuid, &user_uuid, &mut conn).await else {
let Some(device) = Device::find_by_uuid_and_user(&device_id, &user_id, &mut conn).await else {
err_handler!("Invalid device id")
};
let Some(user) = User::find_by_uuid(&user_uuid, &mut conn).await else {
let Some(user) = User::find_by_uuid(&user_id, &mut conn).await else {
err_handler!("Device has no user associated")
};