vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit 4e60df7a080872487945039860bc9ca3cb8d3225
parent 219a9d9f5ed9a374f2b0f7ad039bf57394b1852c
Author: Jeremy Lin <jeremy.lin@gmail.com>
Date:   Thu, 10 Dec 2020 00:17:34 -0800

Fix stale data check failure when cloning a cipher

Diffstat:
Msrc/api/core/ciphers.rs | 30++++++++++++++++++++++--------
1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs @@ -49,7 +49,7 @@ pub fn routes() -> Vec<Route> { post_cipher_admin, post_cipher_share, put_cipher_share, - put_cipher_share_seleted, + put_cipher_share_selected, post_cipher, put_cipher, delete_cipher_post, @@ -212,22 +212,35 @@ pub struct Attachments2Data { Key: String, } +/// Called when an org admin clones an org cipher. #[post("/ciphers/admin", data = "<data>")] fn post_ciphers_admin(data: JsonUpcase<ShareCipherData>, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult { - let data: ShareCipherData = data.into_inner().data; + post_ciphers_create(data, headers, conn, nt) +} + +/// Called when creating a new org-owned cipher, or cloning a cipher (whether +/// user- or org-owned). When cloning a cipher to a user-owned cipher, +/// `organizationId` is null. +#[post("/ciphers/create", data = "<data>")] +fn post_ciphers_create(data: JsonUpcase<ShareCipherData>, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult { + let mut data: ShareCipherData = data.into_inner().data; let mut cipher = Cipher::new(data.Cipher.Type, data.Cipher.Name.clone()); cipher.user_uuid = Some(headers.user.uuid.clone()); cipher.save(&conn)?; - share_cipher_by_uuid(&cipher.uuid, data, &headers, &conn, &nt) -} + // When cloning a cipher, the Bitwarden clients seem to set this field + // based on the cipher being cloned (when creating a new cipher, it's set + // to null as expected). However, `cipher.created_at` is initialized to + // the current time, so the stale data check will end up failing down the + // line. Since this function only creates new ciphers (whether by cloning + // or otherwise), we can just ignore this field entirely. + data.Cipher.LastKnownRevisionDate = None; -#[post("/ciphers/create", data = "<data>")] -fn post_ciphers_create(data: JsonUpcase<ShareCipherData>, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult { - post_ciphers_admin(data, headers, conn, nt) + share_cipher_by_uuid(&cipher.uuid, data, &headers, &conn, &nt) } +/// Called when creating a new user-owned cipher. #[post("/ciphers", data = "<data>")] fn post_ciphers(data: JsonUpcase<CipherData>, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult { let data: CipherData = data.into_inner().data; @@ -407,6 +420,7 @@ fn post_ciphers_import(data: JsonUpcase<ImportData>, headers: Headers, conn: DbC Ok(()) } +/// Called when an org admin modifies an existing org cipher. #[put("/ciphers/<uuid>/admin", data = "<data>")] fn put_cipher_admin( uuid: String, @@ -581,7 +595,7 @@ struct ShareSelectedCipherData { } #[put("/ciphers/share", data = "<data>")] -fn put_cipher_share_seleted( +fn put_cipher_share_selected( data: JsonUpcase<ShareSelectedCipherData>, headers: Headers, conn: DbConn,