@ -374,6 +374,21 @@ async fn get_org_collections_details( 
				
			 
			
		
	
		
		
			
				
					 
					 
					         | |   ( CONFIG . org_groups_enabled ( )  
					 
					 
					         | |   ( CONFIG . org_groups_enabled ( )  
				
			 
			
		
	
		
		
			
				
					 
					 
					             & &   GroupUser ::has_full_access_by_member ( & org_id ,   & member . uuid ,   & mut   conn ) . await ) ;  
					 
					 
					             & &   GroupUser ::has_full_access_by_member ( & org_id ,   & member . uuid ,   & mut   conn ) . await ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     // Get all admins, owners and managers who can manage/access all
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     // Those are currently not listed in the col_users but need to be listed too.
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     let   manage_all_members : Vec < Value >   =   Membership ::find_confirmed_and_manage_all_by_org ( & org_id ,   & mut   conn )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         . await  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         . into_iter ( )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         . map ( | member |   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             json ! ( {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 "id" : member . uuid ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 "readOnly" : false ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 "hidePasswords" : false ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 "manage" : true ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             } )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         } )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         . collect ( ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					     for   col   in   Collection ::find_by_organization ( & org_id ,   & mut   conn ) . await   {  
					 
					 
					     for   col   in   Collection ::find_by_organization ( & org_id ,   & mut   conn ) . await   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         // check whether the current user has access to the given collection
  
					 
					 
					         // check whether the current user has access to the given collection
  
				
			 
			
		
	
		
		
			
				
					 
					 
					         let   assigned   =   has_full_access_to_org  
					 
					 
					         let   assigned   =   has_full_access_to_org  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					@ -382,7 +397,7 @@ async fn get_org_collections_details( 
				
			 
			
		
	
		
		
			
				
					 
					 
					                 & &   GroupUser ::has_access_to_collection_by_member ( & col . uuid ,   & member . uuid ,   & mut   conn ) . await ) ;  
					 
					 
					                 & &   GroupUser ::has_access_to_collection_by_member ( & col . uuid ,   & member . uuid ,   & mut   conn ) . await ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					         // get the users assigned directly to the given collection
  
					 
					 
					         // get the users assigned directly to the given collection
  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					         let   users : Vec < Value >   =   col_users  
					 
					 
					         let   mut   users : Vec < Value >   =   col_users  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					             . iter ( )  
					 
					 
					             . iter ( )  
				
			 
			
		
	
		
		
			
				
					 
					 
					             . filter ( | collection_member |   collection_member . collection_uuid   = =   col . uuid )  
					 
					 
					             . filter ( | collection_member |   collection_member . collection_uuid   = =   col . uuid )  
				
			 
			
		
	
		
		
			
				
					 
					 
					             . map ( | collection_member |   {  
					 
					 
					             . map ( | collection_member |   {  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					@ -391,6 +406,7 @@ async fn get_org_collections_details( 
				
			 
			
		
	
		
		
			
				
					 
					 
					                 )  
					 
					 
					                 )  
				
			 
			
		
	
		
		
			
				
					 
					 
					             } )  
					 
					 
					             } )  
				
			 
			
		
	
		
		
			
				
					 
					 
					             . collect ( ) ;  
					 
					 
					             . collect ( ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         users . extend_from_slice ( & manage_all_members ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					         // get the group details for the given collection
  
					 
					 
					         // get the group details for the given collection
  
				
			 
			
		
	
		
		
			
				
					 
					 
					         let   groups : Vec < Value >   =   if   CONFIG . org_groups_enabled ( )   {  
					 
					 
					         let   groups : Vec < Value >   =   if   CONFIG . org_groups_enabled ( )   {  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -681,6 +697,9 @@ async fn _delete_organization_collection( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     headers : & ManagerHeaders ,  
					 
					 
					     headers : & ManagerHeaders ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     conn : & mut   DbConn ,  
					 
					 
					     conn : & mut   DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   & headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   Some ( collection )   =   Collection ::find_by_uuid_and_org ( col_id ,   org_id ,   conn ) . await   else   {  
					 
					 
					     let   Some ( collection )   =   Collection ::find_by_uuid_and_org ( col_id ,   org_id ,   conn ) . await   else   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "Collection not found" ,   "Collection does not exist or does not belong to this organization" )  
					 
					 
					         err ! ( "Collection not found" ,   "Collection does not exist or does not belong to this organization" )  
				
			 
			
		
	
		
		
			
				
					 
					 
					     } ;  
					 
					 
					     } ;  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -893,7 +912,7 @@ struct OrgIdData { 
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					#[ get( " /ciphers/organization-details?<data..> " ) ]  
					 
					 
					#[ get( " /ciphers/organization-details?<data..> " ) ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					async   fn  get_org_details ( data : OrgIdData ,   headers : OrgMemberHeaders ,   mut   conn : DbConn )   -> JsonResult   {  
					 
					 
					async   fn  get_org_details ( data : OrgIdData ,   headers : OrgMemberHeaders ,   mut   conn : DbConn )   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					     if   data . organization_id   ! =   headers . org_id   {  
					 
					 
					     if   data . organization_id   ! =   headers . membership . org_uu id   {  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					         err_code ! ( "Resource not found." ,   "Organization id's do not match" ,   rocket ::http ::Status ::NotFound . code ) ;  
					 
					 
					         err_code ! ( "Resource not found." ,   "Organization id's do not match" ,   rocket ::http ::Status ::NotFound . code ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -1180,6 +1199,9 @@ async fn reinvite_member( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     headers : AdminHeaders ,  
					 
					 
					     headers : AdminHeaders ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     mut   conn : DbConn ,  
					 
					 
					     mut   conn : DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     _reinvite_member ( & org_id ,   & member_id ,   & headers . user . email ,   & mut   conn ) . await  
					 
					 
					     _reinvite_member ( & org_id ,   & member_id ,   & headers . user . email ,   & mut   conn ) . await  
				
			 
			
		
	
		
		
			
				
					 
					 
					}  
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -1397,6 +1419,9 @@ async fn _confirm_invite( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     conn : & mut   DbConn ,  
					 
					 
					     conn : & mut   DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     nt : & Notify < '_ > ,  
					 
					 
					     nt : & Notify < '_ > ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   & headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   key . is_empty ( )   | |   member_id . is_empty ( )   {  
					 
					 
					     if   key . is_empty ( )   | |   member_id . is_empty ( )   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "Key or UserId is not set, unable to process request" ) ;  
					 
					 
					         err ! ( "Key or UserId is not set, unable to process request" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -1460,7 +1485,7 @@ async fn _confirm_invite( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   save_result   =   member_to_confirm . save ( conn ) . await ;  
					 
					 
					     let   save_result   =   member_to_confirm . save ( conn ) . await ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   let   Some ( user )   =   User ::find_by_uuid ( & member_to_confirm . user_uuid ,   conn ) . await   {  
					 
					 
					     if   let   Some ( user )   =   User ::find_by_uuid ( & member_to_confirm . user_uuid ,   conn ) . await   {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					         nt . send_user_update ( UpdateType ::SyncOrgKeys ,   & user ) . await ;  
					 
					 
					         nt . send_user_update ( UpdateType ::SyncOrgKeys ,   & user ,   & headers . device . push_uuid ,   conn ) . await ;  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					     save_result  
					 
					 
					     save_result  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -1719,6 +1744,9 @@ async fn _delete_member( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     conn : & mut   DbConn ,  
					 
					 
					     conn : & mut   DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     nt : & Notify < '_ > ,  
					 
					 
					     nt : & Notify < '_ > ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   & headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   Some ( member_to_delete )   =   Membership ::find_by_uuid_and_org ( member_id ,   org_id ,   conn ) . await   else   {  
					 
					 
					     let   Some ( member_to_delete )   =   Membership ::find_by_uuid_and_org ( member_id ,   org_id ,   conn ) . await   else   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "User to delete isn't member of the organization" )  
					 
					 
					         err ! ( "User to delete isn't member of the organization" )  
				
			 
			
		
	
		
		
			
				
					 
					 
					     } ;  
					 
					 
					     } ;  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -1747,7 +1775,7 @@ async fn _delete_member( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     . await ;  
					 
					 
					     . await ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   let   Some ( user )   =   User ::find_by_uuid ( & member_to_delete . user_uuid ,   conn ) . await   {  
					 
					 
					     if   let   Some ( user )   =   User ::find_by_uuid ( & member_to_delete . user_uuid ,   conn ) . await   {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					         nt . send_user_update ( UpdateType ::SyncOrgKeys ,   & user ) . await ;  
					 
					 
					         nt . send_user_update ( UpdateType ::SyncOrgKeys ,   & user ,   & headers . device . push_uuid ,   conn ) . await ;  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					     member_to_delete . delete ( conn ) . await  
					 
					 
					     member_to_delete . delete ( conn ) . await  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -1813,16 +1841,20 @@ struct RelationsData { 
				
			 
			
		
	
		
		
			
				
					 
					 
					     value : usize ,  
					 
					 
					     value : usize ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					}  
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					// https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Api/Tools/Controllers/ImportCiphersController.cs#L62
  
				
			 
			
		
	
		
		
			
				
					 
					 
					#[ post( " /ciphers/import-organization?<query..> " , data =  " <data> " ) ]  
					 
					 
					#[ post( " /ciphers/import-organization?<query..> " , data =  " <data> " ) ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					async   fn  post_org_import (  
					 
					 
					async   fn  post_org_import (  
				
			 
			
		
	
		
		
			
				
					 
					 
					     query : OrgIdData ,  
					 
					 
					     query : OrgIdData ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     data : Json < ImportData > ,  
					 
					 
					     data : Json < ImportData > ,  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					     headers : Admin Headers,  
					 
					 
					     headers : OrgMember Headers,  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					     mut   conn : DbConn ,  
					 
					 
					     mut   conn : DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     nt : Notify < '_ > ,  
					 
					 
					     nt : Notify < '_ > ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   data : ImportData   =   data . into_inner ( ) ;  
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   org_id   =   query . organization_id ;  
					 
					 
					     let   org_id   =   query . organization_id ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   headers . membership . org_uuid   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     let   data : ImportData   =   data . into_inner ( ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					     // Validate the import before continuing
  
					 
					 
					     // Validate the import before continuing
  
				
			 
			
		
	
		
		
			
				
					 
					 
					     // Bitwarden does not process the import if there is one item invalid.
  
					 
					 
					     // Bitwarden does not process the import if there is one item invalid.
  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					@ -1835,8 +1867,20 @@ async fn post_org_import( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   mut   collections : Vec < CollectionId >   =   Vec ::with_capacity ( data . collections . len ( ) ) ;  
					 
					 
					     let   mut   collections : Vec < CollectionId >   =   Vec ::with_capacity ( data . collections . len ( ) ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     for   col   in   data . collections   {  
					 
					 
					     for   col   in   data . collections   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         let   collection_uuid   =   if   existing_collections . contains ( & col . id )   {  
					 
					 
					         let   collection_uuid   =   if   existing_collections . contains ( & col . id )   {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					             col . id . unwrap ( )  
					 
					 
					             let   col_id   =   col . id . unwrap ( ) ;  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             // When not an Owner or Admin, check if the member is allowed to access the collection.
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             if   headers . membership . atype   <   MembershipType ::Admin  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 & &   ! Collection ::can_access_collection ( & headers . membership ,   & col_id ,   & mut   conn ) . await  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 err ! ( Compact ,   "The current user isn't allowed to manage this collection" )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             }  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             col_id  
				
			 
			
		
	
		
		
			
				
					 
					 
					         }   else   {  
					 
					 
					         }   else   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             // We do not allow users or managers which can not manage all collections to create new collections
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             // If there is any collection other than an existing import collection, abort the import.
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             if   headers . membership . atype   < =   MembershipType ::Manager   & &   ! headers . membership . has_full_access ( )   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 err ! ( Compact ,   "The current user isn't allowed to create new collections" )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             }  
				
			 
			
		
	
		
		
			
				
					 
					 
					             let   new_collection   =   Collection ::new ( org_id . clone ( ) ,   col . name ,   col . external_id ) ;  
					 
					 
					             let   new_collection   =   Collection ::new ( org_id . clone ( ) ,   col . name ,   col . external_id ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					             new_collection . save ( & mut   conn ) . await ? ;  
					 
					 
					             new_collection . save ( & mut   conn ) . await ? ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					             new_collection . uuid  
					 
					 
					             new_collection . uuid  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					@ -1859,7 +1903,17 @@ async fn post_org_import( 
				
			 
			
		
	
		
		
			
				
					 
					 
					         // Always clear folder_id's via an organization import
  
					 
					 
					         // Always clear folder_id's via an organization import
  
				
			 
			
		
	
		
		
			
				
					 
					 
					         cipher_data . folder_id   =   None ;  
					 
					 
					         cipher_data . folder_id   =   None ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					         let   mut   cipher   =   Cipher ::new ( cipher_data . r#type ,   cipher_data . name . clone ( ) ) ;  
					 
					 
					         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 . ok ( ) ;  
					 
					 
					         update_cipher_from_data (  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             & mut   cipher ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             cipher_data ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             & headers ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             Some ( collections . clone ( ) ) ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             & mut   conn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             & nt ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             UpdateType ::None ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         . await  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         . ok ( ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					         ciphers . push ( cipher . uuid ) ;  
					 
					 
					         ciphers . push ( cipher . uuid ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -1890,12 +1944,6 @@ struct BulkCollectionsData { 
				
			 
			
		
	
		
		
			
				
					 
					 
					async   fn  post_bulk_collections ( data : Json < BulkCollectionsData > ,   headers : Headers ,   mut   conn : DbConn )   -> EmptyResult   {  
					 
					 
					async   fn  post_bulk_collections ( data : Json < BulkCollectionsData > ,   headers : Headers ,   mut   conn : DbConn )   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   data : BulkCollectionsData   =   data . into_inner ( ) ;  
					 
					 
					     let   data : BulkCollectionsData   =   data . into_inner ( ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					     // This feature does not seem to be active on all the clients
  
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					 
					 
					     // To prevent future issues, add a check to block a call when this is set to true
  
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   data . remove_collections   {  
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "Bulk removing of collections is not yet implemented" )  
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					 
					 
					     // Get all the collection available to the user in one query
  
					 
					 
					     // Get all the collection available to the user in one query
  
				
			 
			
		
	
		
		
			
				
					 
					 
					     // Also filter based upon the provided collections
  
					 
					 
					     // Also filter based upon the provided collections
  
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   user_collections : HashMap < CollectionId ,   Collection >   =  
					 
					 
					     let   user_collections : HashMap < CollectionId ,   Collection >   =  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -1924,10 +1972,18 @@ async fn post_bulk_collections(data: Json<BulkCollectionsData>, headers: Headers 
				
			 
			
		
	
		
		
			
				
					 
					 
					         // Do not abort the operation just ignore it, it could be a cipher was just deleted for example
  
					 
					 
					         // Do not abort the operation just ignore it, it could be a cipher was just deleted for example
  
				
			 
			
		
	
		
		
			
				
					 
					 
					         if   let   Some ( cipher )   =   Cipher ::find_by_uuid_and_org ( cipher_id ,   & data . organization_id ,   & mut   conn ) . await   {  
					 
					 
					         if   let   Some ( cipher )   =   Cipher ::find_by_uuid_and_org ( cipher_id ,   & data . organization_id ,   & mut   conn ) . await   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					             if   cipher . is_write_accessible_to_user ( & headers . user . uuid ,   & mut   conn ) . await   {  
					 
					 
					             if   cipher . is_write_accessible_to_user ( & headers . user . uuid ,   & mut   conn ) . await   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 // When selecting a specific collection from the left filter list, and use the bulk option, you can remove an item from that collection
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 // In these cases the client will call this endpoint twice, once for adding the new collections and a second for deleting.
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 if   data . remove_collections   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                     for   collection   in   & data . collection_ids   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                         CollectionCipher ::delete ( & cipher . uuid ,   collection ,   & mut   conn ) . await ? ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 }   else   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					                     for   collection   in   & data . collection_ids   {  
					 
					 
					                     for   collection   in   & data . collection_ids   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					                         CollectionCipher ::save ( & cipher . uuid ,   collection ,   & mut   conn ) . await ? ;  
					 
					 
					                         CollectionCipher ::save ( & cipher . uuid ,   collection ,   & mut   conn ) . await ? ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					                     }  
					 
					 
					                     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					                 }  
					 
					 
					                 }  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             }  
				
			 
			
		
	
		
		
			
				
					 
					 
					         } ;  
					 
					 
					         } ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -2402,6 +2458,9 @@ async fn _revoke_member( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     headers : & AdminHeaders ,  
					 
					 
					     headers : & AdminHeaders ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     conn : & mut   DbConn ,  
					 
					 
					     conn : & mut   DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   & headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     match   Membership ::find_by_uuid_and_org ( member_id ,   org_id ,   conn ) . await   {  
					 
					 
					     match   Membership ::find_by_uuid_and_org ( member_id ,   org_id ,   conn ) . await   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         Some ( mut   member )   if   member . status   >   MembershipStatus ::Revoked   as   i32   = >   {  
					 
					 
					         Some ( mut   member )   if   member . status   >   MembershipStatus ::Revoked   as   i32   = >   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					             if   member . user_uuid   = =   headers . user . uuid   {  
					 
					 
					             if   member . user_uuid   = =   headers . user . uuid   {  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -2509,6 +2568,9 @@ async fn _restore_member( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     headers : & AdminHeaders ,  
					 
					 
					     headers : & AdminHeaders ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     conn : & mut   DbConn ,  
					 
					 
					     conn : & mut   DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   & headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     match   Membership ::find_by_uuid_and_org ( member_id ,   org_id ,   conn ) . await   {  
					 
					 
					     match   Membership ::find_by_uuid_and_org ( member_id ,   org_id ,   conn ) . await   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         Some ( mut   member )   if   member . status   <   MembershipStatus ::Accepted   as   i32   = >   {  
					 
					 
					         Some ( mut   member )   if   member . status   <   MembershipStatus ::Accepted   as   i32   = >   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					             if   member . user_uuid   = =   headers . user . uuid   {  
					 
					 
					             if   member . user_uuid   = =   headers . user . uuid   {  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -2556,19 +2618,28 @@ async fn _restore_member( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     Ok ( ( ) )  
					 
					 
					     Ok ( ( ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					}  
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					#[ get( " /organizations/<org_id>/groups " ) ]  
					 
					 
					async   fn  get_groups_data (  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					async   fn  get_groups ( org_id : OrganizationId ,   headers : ManagerHeadersLoose ,   mut   conn : DbConn )   -> JsonResult   {  
					 
					 
					     details : bool ,  
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     org_id : OrganizationId ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     headers : ManagerHeadersLoose ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     mut   conn : DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					)   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   org_id   ! =   headers . membership . org_uuid   {  
					 
					 
					     if   org_id   ! =   headers . membership . org_uuid   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   groups : Vec < Value >   =   if   CONFIG . org_groups_enabled ( )   {  
					 
					 
					     let   groups : Vec < Value >   =   if   CONFIG . org_groups_enabled ( )   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         // Group::find_by_organization(&org_id, &mut conn).await.iter().map(Group::to_json).collect::<Value>()
  
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					 
					 
					         let   groups   =   Group ::find_by_organization ( & org_id ,   & mut   conn ) . await ;  
					 
					 
					         let   groups   =   Group ::find_by_organization ( & org_id ,   & mut   conn ) . await ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					         let   mut   groups_json   =   Vec ::with_capacity ( groups . len ( ) ) ;  
					 
					 
					         let   mut   groups_json   =   Vec ::with_capacity ( groups . len ( ) ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         if   details   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					             for   g   in   groups   {  
					 
					 
					             for   g   in   groups   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					                 groups_json . push ( g . to_json_details ( & mut   conn ) . await )  
					 
					 
					                 groups_json . push ( g . to_json_details ( & mut   conn ) . await )  
				
			 
			
		
	
		
		
			
				
					 
					 
					             }  
					 
					 
					             }  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         }   else   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             for   g   in   groups   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                 groups_json . push ( g . to_json ( ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					             }  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         }  
				
			 
			
		
	
		
		
			
				
					 
					 
					         groups_json  
					 
					 
					         groups_json  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }   else   {  
					 
					 
					     }   else   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         // The Bitwarden clients seem to call this API regardless of whether groups are enabled,
  
					 
					 
					         // The Bitwarden clients seem to call this API regardless of whether groups are enabled,
  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					@ -2583,9 +2654,14 @@ async fn get_groups(org_id: OrganizationId, headers: ManagerHeadersLoose, mut co 
				
			 
			
		
	
		
		
			
				
					 
					 
					     } ) ) )  
					 
					 
					     } ) ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					}  
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					#[ get( " /organizations/<org_id>/groups " ) ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					async   fn  get_groups ( org_id : OrganizationId ,   headers : ManagerHeadersLoose ,   conn : DbConn )   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     get_groups_data ( false ,   org_id ,   headers ,   conn ) . await  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					#[ get( " /organizations/<org_id>/groups/details " , rank = 1) ]  
					 
					 
					#[ get( " /organizations/<org_id>/groups/details " , rank = 1) ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					async   fn  get_groups_details ( org_id : OrganizationId ,   headers : ManagerHeadersLoose ,   conn : DbConn )   -> JsonResult   {  
					 
					 
					async   fn  get_groups_details ( org_id : OrganizationId ,   headers : ManagerHeadersLoose ,   conn : DbConn )   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					     get_groups ( org_id ,   headers ,   conn ) . await  
					 
					 
					     get_groups_data  ( true ,   org_id ,   headers ,   conn ) . await  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					}  
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					#[ derive(Deserialize) ]  
					 
					 
					#[ derive(Deserialize) ]  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -2647,6 +2723,9 @@ async fn post_groups( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     data : Json < GroupRequest > ,  
					 
					 
					     data : Json < GroupRequest > ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     mut   conn : DbConn ,  
					 
					 
					     mut   conn : DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> JsonResult   {  
					 
					 
					)   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "Group support is disabled" ) ;  
					 
					 
					         err ! ( "Group support is disabled" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -2676,6 +2755,9 @@ async fn put_group( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     headers : AdminHeaders ,  
					 
					 
					     headers : AdminHeaders ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     mut   conn : DbConn ,  
					 
					 
					     mut   conn : DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> JsonResult   {  
					 
					 
					)   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "Group support is disabled" ) ;  
					 
					 
					         err ! ( "Group support is disabled" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -2740,7 +2822,8 @@ async fn add_update_group( 
				
			 
			
		
	
		
		
			
				
					 
					 
					         "organizationId" : group . organizations_uuid ,  
					 
					 
					         "organizationId" : group . organizations_uuid ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					         "name" : group . name ,  
					 
					 
					         "name" : group . name ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					         "accessAll" : group . access_all ,  
					 
					 
					         "accessAll" : group . access_all ,  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					         "externalId" : group . external_id  
					 
					 
					         "externalId" : group . external_id ,  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         "object" : "group"  
				
			 
			
		
	
		
		
			
				
					 
					 
					     } ) ) )  
					 
					 
					     } ) ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					}  
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -2791,6 +2874,9 @@ async fn _delete_group( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     headers : & AdminHeaders ,  
					 
					 
					     headers : & AdminHeaders ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     conn : & mut   DbConn ,  
					 
					 
					     conn : & mut   DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   & headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "Group support is disabled" ) ;  
					 
					 
					         err ! ( "Group support is disabled" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -2820,6 +2906,9 @@ async fn bulk_delete_groups( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     headers : AdminHeaders ,  
					 
					 
					     headers : AdminHeaders ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     mut   conn : DbConn ,  
					 
					 
					     mut   conn : DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "Group support is disabled" ) ;  
					 
					 
					         err ! ( "Group support is disabled" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -2883,6 +2972,9 @@ async fn put_group_members( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     data : Json < Vec < MembershipId > > ,  
					 
					 
					     data : Json < Vec < MembershipId > > ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     mut   conn : DbConn ,  
					 
					 
					     mut   conn : DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> EmptyResult   {  
					 
					 
					)   -> EmptyResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
					 
					 
					     if   ! CONFIG . org_groups_enabled ( )   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         err ! ( "Group support is disabled" ) ;  
					 
					 
					         err ! ( "Group support is disabled" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -3067,7 +3159,7 @@ async fn get_organization_public_key( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     headers : OrgMemberHeaders ,  
					 
					 
					     headers : OrgMemberHeaders ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     mut   conn : DbConn ,  
					 
					 
					     mut   conn : DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> JsonResult   {  
					 
					 
					)   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					     if   org_id   ! =   headers . org_id   {  
					 
					 
					     if   org_id   ! =   headers . membership . org_uu id   {  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     }  
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   Some ( org )   =   Organization ::find_by_uuid ( & org_id ,   & mut   conn ) . await   else   {  
					 
					 
					     let   Some ( org )   =   Organization ::find_by_uuid ( & org_id ,   & mut   conn ) . await   else   {  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					@ -3081,7 +3173,7 @@ async fn get_organization_public_key( 
				
			 
			
		
	
		
		
			
				
					 
					 
					}  
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					// Obsolete - Renamed to public-key (2023.8), left for backwards compatibility with older clients
  
					 
					 
					// Obsolete - Renamed to public-key (2023.8), left for backwards compatibility with older clients
  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					// https://github.com/bitwarden/server/blob/25dc0c9178e3e3584074bbef0d4be827b7c89415/src/Api/AdminConsole/Controllers/OrganizationsController.cs#L463-L468 
  
					 
					 
					// https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Api/AdminConsole/Controllers/OrganizationsController.cs#L487-L492 
  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					#[ get( " /organizations/<org_id>/keys " ) ]  
					 
					 
					#[ get( " /organizations/<org_id>/keys " ) ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					async   fn  get_organization_keys ( org_id : OrganizationId ,   headers : OrgMemberHeaders ,   conn : DbConn )   -> JsonResult   {  
					 
					 
					async   fn  get_organization_keys ( org_id : OrganizationId ,   headers : OrgMemberHeaders ,   conn : DbConn )   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					     get_organization_public_key ( org_id ,   headers ,   conn ) . await  
					 
					 
					     get_organization_public_key ( org_id ,   headers ,   conn ) . await  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -3132,7 +3224,7 @@ async fn put_reset_password( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     user . set_password ( reset_request . new_master_password_hash . as_str ( ) ,   Some ( reset_request . key ) ,   true ,   None ) ;  
					 
					 
					     user . set_password ( reset_request . new_master_password_hash . as_str ( ) ,   Some ( reset_request . key ) ,   true ,   None ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     user . save ( & mut   conn ) . await ? ;  
					 
					 
					     user . save ( & mut   conn ) . await ? ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					     nt . send_logout ( & user ,   None ) . await ;  
					 
					 
					     nt . send_logout ( & user ,   None ,   & mut   conn ) . await ;  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					     log_event (  
					 
					 
					     log_event (  
				
			 
			
		
	
		
		
			
				
					 
					 
					         EventType ::OrganizationUserAdminResetPassword   as   i32 ,  
					 
					 
					         EventType ::OrganizationUserAdminResetPassword   as   i32 ,  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -3172,16 +3264,16 @@ async fn get_reset_password_details( 
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					     check_reset_password_applicable_and_permissions ( & org_id ,   & member_id ,   & headers ,   & mut   conn ) . await ? ;  
					 
					 
					     check_reset_password_applicable_and_permissions ( & org_id ,   & member_id ,   & headers ,   & mut   conn ) . await ? ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					     // https://github.com/bitwarden/server/blob/3b50ccb9f804efaacdc46bed5b60e5b28eddefcf/src/Api/Models/Response/Organizations/OrganizationUserResponseModel.cs#L111 
  
					 
					 
					     // https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Api/AdminConsole/Models/Response/Organizations/OrganizationUserResponseModel.cs#L190 
  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					     Ok ( Json ( json ! ( {  
					 
					 
					     Ok ( Json ( json ! ( {  
				
			 
			
		
	
		
		
			
				
					 
					 
					         "object" : "organizationUserResetPasswordDetails" ,  
					 
					 
					         "object" : "organizationUserResetPasswordDetails" ,  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					         "kdf" :user . client_kdf_type  ,  
					 
					 
					         "organizationUserId" : member_id  ,  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					         "kdfIterations " :user . client_kdf_i ter  ,  
					 
					 
					         "kdf" :  user . client_kdf_typ e ,  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					         "kdfMemory" :user . client_kdf_memory  ,  
					 
					 
					         "kdfIterations" : user . client_kdf_iter  ,  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					         "kdfParallelism" :user . client_kdf_parallelism  ,  
					 
					 
					         "kdfMemory" : user . client_kdf_memory  ,  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					         "resetPasswordKey" :member . reset_password_key  ,  
					 
					 
					         "kdfParallelism" : user . client_kdf_parallelism  ,  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					         "encryptedPrivateKey" :org . private _key ,  
					 
					 
					         "resetPasswordKey" : member . reset_password _key ,  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					
  
					 
					 
					         "encryptedPrivateKey" : org . private_key ,  
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 
					 
					     } ) ) )  
					 
					 
					     } ) ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					}  
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -3269,6 +3361,9 @@ async fn put_reset_password_enrollment( 
				
			 
			
		
	
		
		
			
				
					 
					 
					// NOTE: It seems clients can't handle uppercase-first keys!!
  
					 
					 
					// NOTE: It seems clients can't handle uppercase-first keys!!
  
				
			 
			
		
	
		
		
			
				
					 
					 
					//       We need to convert all keys so they have the first character to be a lowercase.
  
					 
					 
					//       We need to convert all keys so they have the first character to be a lowercase.
  
				
			 
			
		
	
		
		
			
				
					 
					 
					//       Else the export will be just an empty JSON file.
  
					 
					 
					//       Else the export will be just an empty JSON file.
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					// We currently only support exports by members of the Admin or Owner status.
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					// Vaultwarden does not yet support exporting only managed collections!
  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					// https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Api/Tools/Controllers/OrganizationExportController.cs#L52
  
				
			 
			
		
	
		
		
			
				
					 
					 
					#[ get( " /organizations/<org_id>/export " ) ]  
					 
					 
					#[ get( " /organizations/<org_id>/export " ) ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					async   fn  get_org_export ( org_id : OrganizationId ,   headers : AdminHeaders ,   mut   conn : DbConn )   -> JsonResult   {  
					 
					 
					async   fn  get_org_export ( org_id : OrganizationId ,   headers : AdminHeaders ,   mut   conn : DbConn )   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					     if   org_id   ! =   headers . org_id   {  
					 
					 
					     if   org_id   ! =   headers . org_id   {  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					@ -3288,6 +3383,9 @@ async fn _api_key( 
				
			 
			
		
	
		
		
			
				
					 
					 
					     headers : AdminHeaders ,  
					 
					 
					     headers : AdminHeaders ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					     mut   conn : DbConn ,  
					 
					 
					     mut   conn : DbConn ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					)   -> JsonResult   {  
					 
					 
					)   -> JsonResult   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     if   org_id   ! =   & headers . org_id   {  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					         err ! ( "Organization not found" ,   "Organization id's do not match" ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					     }  
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   data : PasswordOrOtpData   =   data . into_inner ( ) ;  
					 
					 
					     let   data : PasswordOrOtpData   =   data . into_inner ( ) ;  
				
			 
			
		
	
		
		
			
				
					 
					 
					     let   user   =   headers . user ;  
					 
					 
					     let   user   =   headers . user ;