@ -91,7 +91,8 @@ fn sync(data: Form<SyncData>, headers: Headers, conn: DbConn) -> Json<Value> {
let folders_json : Vec < Value > = folders . iter ( ) . map ( Folder ::to_json ) . collect ( ) ;
let folders_json : Vec < Value > = folders . iter ( ) . map ( Folder ::to_json ) . collect ( ) ;
let collections = Collection ::find_by_user_uuid ( & headers . user . uuid , & conn ) ;
let collections = Collection ::find_by_user_uuid ( & headers . user . uuid , & conn ) ;
let collections_json : Vec < Value > = collections . iter ( )
let collections_json : Vec < Value > = collections
. iter ( )
. map ( | c | c . to_json_details ( & headers . user . uuid , & conn ) )
. map ( | c | c . to_json_details ( & headers . user . uuid , & conn ) )
. collect ( ) ;
. collect ( ) ;
@ -105,10 +106,7 @@ fn sync(data: Form<SyncData>, headers: Headers, conn: DbConn) -> Json<Value> {
. collect ( ) ;
. collect ( ) ;
let sends = Send ::find_by_user ( & headers . user . uuid , & conn ) ;
let sends = Send ::find_by_user ( & headers . user . uuid , & conn ) ;
let sends_json : Vec < Value > = sends
let sends_json : Vec < Value > = sends . iter ( ) . map ( | s | s . to_json ( ) ) . collect ( ) ;
. iter ( )
. map ( | s | s . to_json ( ) )
. collect ( ) ;
let domains_json = if data . exclude_domains {
let domains_json = if data . exclude_domains {
Value ::Null
Value ::Null
@ -278,17 +276,15 @@ fn post_ciphers(data: JsonUpcase<CipherData>, headers: Headers, conn: DbConn, nt
/// allowed to delete or share such ciphers to an org, however.
/// allowed to delete or share such ciphers to an org, however.
///
///
/// Ref: https://bitwarden.com/help/article/policies/#personal-ownership
/// Ref: https://bitwarden.com/help/article/policies/#personal-ownership
fn enforce_personal_ownership_policy (
fn enforce_personal_ownership_policy ( data : & CipherData , headers : & Headers , conn : & DbConn ) -> EmptyResult {
data : & CipherData ,
headers : & Headers ,
conn : & DbConn
) -> EmptyResult {
if data . OrganizationId . is_none ( ) {
if data . OrganizationId . is_none ( ) {
let user_uuid = & headers . user . uuid ;
let user_uuid = & headers . user . uuid ;
let policy_type = OrgPolicyType ::PersonalOwnership ;
let policy_type = OrgPolicyType ::PersonalOwnership ;
if OrgPolicy ::is_applicable_to_user ( user_uuid , policy_type , conn ) {
if OrgPolicy ::is_applicable_to_user ( user_uuid , policy_type , conn ) {
err ! ( " Due to an Enterprise Policy , you are restricted from \
err ! (
saving items to your personal vault . " )
" Due to an Enterprise Policy , you are restricted from \
saving items to your personal vault . "
)
}
}
}
}
Ok ( ( ) )
Ok ( ( ) )
@ -307,11 +303,12 @@ pub fn update_cipher_from_data(
// Check that the client isn't updating an existing cipher with stale data.
// Check that the client isn't updating an existing cipher with stale data.
if let Some ( dt ) = data . LastKnownRevisionDate {
if let Some ( dt ) = data . LastKnownRevisionDate {
match NaiveDateTime ::parse_from_str ( & dt , "%+" ) { // ISO 8601 format
match NaiveDateTime ::parse_from_str ( & dt , "%+" ) {
Err ( err ) = >
// ISO 8601 format
warn ! ( "Error parsing LastKnownRevisionDate '{}': {}" , dt , err ) ,
Err ( err ) = > warn ! ( "Error parsing LastKnownRevisionDate '{}': {}" , dt , err ) ,
Ok ( dt ) if cipher . updated_at . signed_duration_since ( dt ) . num_seconds ( ) > 1 = >
Ok ( dt ) if cipher . updated_at . signed_duration_since ( dt ) . num_seconds ( ) > 1 = > {
err ! ( "The client copy of this cipher is out of date. Resync the client and try again." ) ,
err ! ( "The client copy of this cipher is out of date. Resync the client and try again." )
}
Ok ( _ ) = > ( ) ,
Ok ( _ ) = > ( ) ,
}
}
}
}
@ -384,10 +381,7 @@ pub fn update_cipher_from_data(
// But, we at least know we do not need to store and return this specific key.
// But, we at least know we do not need to store and return this specific key.
fn _clean_cipher_data ( mut json_data : Value ) -> Value {
fn _clean_cipher_data ( mut json_data : Value ) -> Value {
if json_data . is_array ( ) {
if json_data . is_array ( ) {
json_data . as_array_mut ( )
json_data . as_array_mut ( ) . unwrap ( ) . iter_mut ( ) . for_each ( | ref mut f | {
. unwrap ( )
. iter_mut ( )
. for_each ( | ref mut f | {
f . as_object_mut ( ) . unwrap ( ) . remove ( "Response" ) ;
f . as_object_mut ( ) . unwrap ( ) . remove ( "Response" ) ;
} ) ;
} ) ;
} ;
} ;
@ -411,13 +405,13 @@ pub fn update_cipher_from_data(
data [ "Uris" ] = _clean_cipher_data ( data [ "Uris" ] . clone ( ) ) ;
data [ "Uris" ] = _clean_cipher_data ( data [ "Uris" ] . clone ( ) ) ;
}
}
data
data
} ,
}
None = > err ! ( "Data missing" ) ,
None = > err ! ( "Data missing" ) ,
} ;
} ;
cipher . name = data . Name ;
cipher . name = data . Name ;
cipher . notes = data . Notes ;
cipher . notes = data . Notes ;
cipher . fields = data . Fields . map ( | f | _clean_cipher_data ( f ) . to_string ( ) ) ;
cipher . fields = data . Fields . map ( | f | _clean_cipher_data ( f ) . to_string ( ) ) ;
cipher . data = type_data . to_string ( ) ;
cipher . data = type_data . to_string ( ) ;
cipher . password_history = data . PasswordHistory . map ( | f | f . to_string ( ) ) ;
cipher . password_history = data . PasswordHistory . map ( | f | f . to_string ( ) ) ;
@ -832,7 +826,13 @@ fn post_attachment(
let file_name = HEXLOWER . encode ( & crypto ::get_random ( vec ! [ 0 ; 10 ] ) ) ;
let file_name = HEXLOWER . encode ( & crypto ::get_random ( vec ! [ 0 ; 10 ] ) ) ;
let path = base_path . join ( & file_name ) ;
let path = base_path . join ( & file_name ) ;
let size = match field . data . save ( ) . memory_threshold ( 0 ) . size_limit ( size_limit ) . with_path ( path . clone ( ) ) {
let size = match field
. data
. save ( )
. memory_threshold ( 0 )
. size_limit ( size_limit )
. with_path ( path . clone ( ) )
{
SaveResult ::Full ( SavedData ::File ( _ , size ) ) = > size as i32 ,
SaveResult ::Full ( SavedData ::File ( _ , size ) ) = > size as i32 ,
SaveResult ::Full ( other ) = > {
SaveResult ::Full ( other ) = > {
std ::fs ::remove_file ( path ) . ok ( ) ;
std ::fs ::remove_file ( path ) . ok ( ) ;
@ -881,7 +881,11 @@ fn post_attachment_admin(
post_attachment ( uuid , data , content_type , headers , conn , nt )
post_attachment ( uuid , data , content_type , headers , conn , nt )
}
}
#[ post( " /ciphers/<uuid>/attachment/<attachment_id>/share " , format = " multipart/form-data " , data = " <data> " ) ]
#[ post(
"/ciphers/<uuid>/attachment/<attachment_id>/share" ,
format = "multipart/form-data" ,
data = "<data>"
) ]
fn post_attachment_share (
fn post_attachment_share (
uuid : String ,
uuid : String ,
attachment_id : String ,
attachment_id : String ,
@ -984,12 +988,22 @@ fn delete_cipher_selected_admin(data: JsonUpcase<Value>, headers: Headers, conn:
}
}
#[ post( " /ciphers/delete-admin " , data = " <data> " ) ]
#[ post( " /ciphers/delete-admin " , data = " <data> " ) ]
fn delete_cipher_selected_post_admin ( data : JsonUpcase < Value > , headers : Headers , conn : DbConn , nt : Notify ) -> EmptyResult {
fn delete_cipher_selected_post_admin (
data : JsonUpcase < Value > ,
headers : Headers ,
conn : DbConn ,
nt : Notify ,
) -> EmptyResult {
delete_cipher_selected_post ( data , headers , conn , nt )
delete_cipher_selected_post ( data , headers , conn , nt )
}
}
#[ put( " /ciphers/delete-admin " , data = " <data> " ) ]
#[ put( " /ciphers/delete-admin " , data = " <data> " ) ]
fn delete_cipher_selected_put_admin ( data : JsonUpcase < Value > , headers : Headers , conn : DbConn , nt : Notify ) -> EmptyResult {
fn delete_cipher_selected_put_admin (
data : JsonUpcase < Value > ,
headers : Headers ,
conn : DbConn ,
nt : Notify ,
) -> EmptyResult {
delete_cipher_selected_put ( data , headers , conn , nt )
delete_cipher_selected_put ( data , headers , conn , nt )
}
}
@ -1140,7 +1154,13 @@ fn _delete_cipher_by_uuid(uuid: &str, headers: &Headers, conn: &DbConn, soft_del
Ok ( ( ) )
Ok ( ( ) )
}
}
fn _delete_multiple_ciphers ( data : JsonUpcase < Value > , headers : Headers , conn : DbConn , soft_delete : bool , nt : Notify ) -> EmptyResult {
fn _delete_multiple_ciphers (
data : JsonUpcase < Value > ,
headers : Headers ,
conn : DbConn ,
soft_delete : bool ,
nt : Notify ,
) -> EmptyResult {
let data : Value = data . into_inner ( ) . data ;
let data : Value = data . into_inner ( ) . data ;
let uuids = match data . get ( "Ids" ) {
let uuids = match data . get ( "Ids" ) {
@ -1192,7 +1212,7 @@ fn _restore_multiple_ciphers(data: JsonUpcase<Value>, headers: &Headers, conn: &
for uuid in uuids {
for uuid in uuids {
match _restore_cipher_by_uuid ( uuid , headers , conn , nt ) {
match _restore_cipher_by_uuid ( uuid , headers , conn , nt ) {
Ok ( json ) = > ciphers . push ( json . into_inner ( ) ) ,
Ok ( json ) = > ciphers . push ( json . into_inner ( ) ) ,
err = > return err
err = > return err ,
}
}
}
}