Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the web-vault v2023.2.0 API calls #3281

Merged
merged 1 commit into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/api/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, mut conn: DbConn)
"latest_release": latest_release,
"latest_commit": latest_commit,
"web_vault_enabled": &CONFIG.web_vault_enabled(),
"web_vault_version": web_vault_version.version,
"web_vault_version": web_vault_version.version.trim_start_matches('v'),
"latest_web_build": latest_web_build,
"running_within_docker": running_within_docker,
"docker_base_image": if running_within_docker { docker_base_image() } else { "Not applicable" },
Expand Down
3 changes: 3 additions & 0 deletions src/api/core/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,8 @@ async fn _api_key(
headers: Headers,
mut conn: DbConn,
) -> JsonResult {
use crate::util::format_date;

let data: SecretVerificationRequest = data.into_inner().data;
let mut user = headers.user;

Expand All @@ -855,6 +857,7 @@ async fn _api_key(

Ok(Json(json!({
"ApiKey": user.api_key,
"RevisionDate": format_date(&user.updated_at),
"Object": "apiKey",
})))
}
Expand Down
78 changes: 69 additions & 9 deletions src/api/core/ciphers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ pub fn routes() -> Vec<Route> {
put_cipher_share,
put_cipher_share_selected,
post_cipher,
post_cipher_partial,
put_cipher,
put_cipher_partial,
delete_cipher_post,
delete_cipher_post_admin,
delete_cipher_put,
Expand Down Expand Up @@ -109,7 +111,10 @@ async fn sync(data: SyncData, headers: Headers, mut conn: DbConn) -> Json<Value>
// Lets generate the ciphers_json using all the gathered info
let mut ciphers_json = Vec::with_capacity(ciphers.len());
for c in ciphers {
ciphers_json.push(c.to_json(&headers.host, &headers.user.uuid, Some(&cipher_sync_data), &mut conn).await);
ciphers_json.push(
c.to_json(&headers.host, &headers.user.uuid, Some(&cipher_sync_data), CipherSyncType::User, &mut conn)
.await,
);
}

let collections = Collection::find_by_user_uuid(headers.user.uuid.clone(), &mut conn).await;
Expand Down Expand Up @@ -153,7 +158,10 @@ async fn get_ciphers(headers: Headers, mut conn: DbConn) -> Json<Value> {

let mut ciphers_json = Vec::with_capacity(ciphers.len());
for c in ciphers {
ciphers_json.push(c.to_json(&headers.host, &headers.user.uuid, Some(&cipher_sync_data), &mut conn).await);
ciphers_json.push(
c.to_json(&headers.host, &headers.user.uuid, Some(&cipher_sync_data), CipherSyncType::User, &mut conn)
.await,
);
}

Json(json!({
Expand All @@ -174,7 +182,7 @@ async fn get_cipher(uuid: String, headers: Headers, mut conn: DbConn) -> JsonRes
err!("Cipher is not owned by user")
}

Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, &mut conn).await))
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
}

#[get("/ciphers/<uuid>/admin")]
Expand Down Expand Up @@ -235,6 +243,13 @@ pub struct CipherData {
LastKnownRevisionDate: Option<String>,
}

#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
pub struct PartialCipherData {
FolderId: Option<String>,
Favorite: bool,
}

#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
pub struct Attachments2Data {
Expand Down Expand Up @@ -314,7 +329,7 @@ async fn post_ciphers(
update_cipher_from_data(&mut cipher, data, &headers, false, &mut conn, &ip, &nt, UpdateType::SyncCipherCreate)
.await?;

Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, &mut conn).await))
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
}

/// Enforces the personal ownership policy on user-owned ciphers, if applicable.
Expand Down Expand Up @@ -646,7 +661,51 @@ async fn put_cipher(
update_cipher_from_data(&mut cipher, data, &headers, false, &mut conn, &ip, &nt, UpdateType::SyncCipherUpdate)
.await?;

Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, &mut conn).await))
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
}

#[post("/ciphers/<uuid>/partial", data = "<data>")]
async fn post_cipher_partial(
uuid: String,
data: JsonUpcase<PartialCipherData>,
headers: Headers,
conn: DbConn,
) -> JsonResult {
put_cipher_partial(uuid, 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>")]
async fn put_cipher_partial(
uuid: String,
data: JsonUpcase<PartialCipherData>,
headers: Headers,
mut conn: DbConn,
) -> JsonResult {
let data: PartialCipherData = data.into_inner().data;

let cipher = match Cipher::find_by_uuid(&uuid, &mut conn).await {
Some(cipher) => cipher,
None => err!("Cipher doesn't exist"),
};

if let Some(ref folder_id) = data.FolderId {
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"),
}
}

// Move cipher
cipher.move_to_folder(data.FolderId.clone(), &headers.user.uuid, &mut conn).await?;
// Update favorite
cipher.set_favorite(Some(data.Favorite), &headers.user.uuid, &mut conn).await?;

Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await))
}

#[derive(Deserialize)]
Expand Down Expand Up @@ -873,7 +932,7 @@ async fn share_cipher_by_uuid(

update_cipher_from_data(&mut cipher, data.Cipher, headers, shared_to_collection, conn, ip, nt, ut).await?;

Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, conn).await))
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, conn).await))
}

/// v2 API for downloading an attachment. This just redirects the client to
Expand Down Expand Up @@ -942,7 +1001,7 @@ async fn post_attachment_v2(
"AttachmentId": attachment_id,
"Url": url,
"FileUploadType": FileUploadType::Direct as i32,
response_key: cipher.to_json(&headers.host, &headers.user.uuid, None, &mut conn).await,
response_key: cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await,
})))
}

Expand Down Expand Up @@ -1135,7 +1194,7 @@ async fn post_attachment(

let (cipher, mut conn) = save_attachment(attachment, uuid, data, &headers, conn, ip, nt).await?;

Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, &mut conn).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>")]
Expand Down Expand Up @@ -1616,7 +1675,7 @@ async fn _restore_cipher_by_uuid(
.await;
}

Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, conn).await))
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, conn).await))
}

async fn _restore_multiple_ciphers(
Expand Down Expand Up @@ -1716,6 +1775,7 @@ pub struct CipherSyncData {
pub user_group_full_access_for_organizations: HashSet<String>,
}

#[derive(Eq, PartialEq)]
pub enum CipherSyncType {
User,
Organization,
Expand Down
12 changes: 10 additions & 2 deletions src/api/core/emergency_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,8 +590,16 @@ async fn view_emergency_access(emer_id: String, headers: Headers, mut conn: DbCo

let mut ciphers_json = Vec::with_capacity(ciphers.len());
for c in ciphers {
ciphers_json
.push(c.to_json(&headers.host, &emergency_access.grantor_uuid, Some(&cipher_sync_data), &mut conn).await);
ciphers_json.push(
c.to_json(
&headers.host,
&emergency_access.grantor_uuid,
Some(&cipher_sync_data),
CipherSyncType::User,
&mut conn,
)
.await,
);
}

Ok(Json(json!({
Expand Down
1 change: 1 addition & 0 deletions src/api/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ fn config() -> Json<Value> {
"notifications": format!("{domain}/notifications"),
"sso": "",
},
"object": "config",
}))
}

Expand Down
Loading