Fix for issue #2566
This PR fixes #2566 If Organizational syncs returned a FolderId it would cause the web-vault to hide the cipher because there is a FolderId set. Upstream seems to not return FolderId and Favorite. When set to null/false it will behave the same. In this PR I have added a new CipherSyncType enum to select which type of sync to execute, and return an empty list for both Folders and Favorites if this is for Orgs. This also reduces the database load a bit since it will not execute those queries.
This commit is contained in:
parent
887e320e7f
commit
b71d9dd53e
|
@ -104,7 +104,7 @@ async fn sync(data: SyncData, headers: Headers, conn: DbConn) -> Json<Value> {
|
||||||
// Get all ciphers which are visible by the user
|
// Get all ciphers which are visible by the user
|
||||||
let ciphers = Cipher::find_by_user_visible(&headers.user.uuid, &conn).await;
|
let ciphers = Cipher::find_by_user_visible(&headers.user.uuid, &conn).await;
|
||||||
|
|
||||||
let cipher_sync_data = CipherSyncData::new(&headers.user.uuid, &ciphers, &conn).await;
|
let cipher_sync_data = CipherSyncData::new(&headers.user.uuid, &ciphers, CipherSyncType::User, &conn).await;
|
||||||
|
|
||||||
// Lets generate the ciphers_json using all the gathered info
|
// Lets generate the ciphers_json using all the gathered info
|
||||||
let ciphers_json: Vec<Value> = stream::iter(ciphers)
|
let ciphers_json: Vec<Value> = stream::iter(ciphers)
|
||||||
|
@ -154,7 +154,7 @@ async fn sync(data: SyncData, headers: Headers, conn: DbConn) -> Json<Value> {
|
||||||
#[get("/ciphers")]
|
#[get("/ciphers")]
|
||||||
async fn get_ciphers(headers: Headers, conn: DbConn) -> Json<Value> {
|
async fn get_ciphers(headers: Headers, conn: DbConn) -> Json<Value> {
|
||||||
let ciphers = Cipher::find_by_user_visible(&headers.user.uuid, &conn).await;
|
let ciphers = Cipher::find_by_user_visible(&headers.user.uuid, &conn).await;
|
||||||
let cipher_sync_data = CipherSyncData::new(&headers.user.uuid, &ciphers, &conn).await;
|
let cipher_sync_data = CipherSyncData::new(&headers.user.uuid, &ciphers, CipherSyncType::User, &conn).await;
|
||||||
|
|
||||||
let ciphers_json = stream::iter(ciphers)
|
let ciphers_json = stream::iter(ciphers)
|
||||||
.then(|c| async {
|
.then(|c| async {
|
||||||
|
@ -1486,25 +1486,39 @@ pub struct CipherSyncData {
|
||||||
pub user_collections: HashMap<String, CollectionUser>,
|
pub user_collections: HashMap<String, CollectionUser>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum CipherSyncType {
|
||||||
|
User,
|
||||||
|
Organization,
|
||||||
|
}
|
||||||
|
|
||||||
impl CipherSyncData {
|
impl CipherSyncData {
|
||||||
pub async fn new(user_uuid: &str, ciphers: &Vec<Cipher>, conn: &DbConn) -> Self {
|
pub async fn new(user_uuid: &str, ciphers: &Vec<Cipher>, sync_type: CipherSyncType, conn: &DbConn) -> Self {
|
||||||
// Generate a list of Cipher UUID's to be used during a query filter with an eq_any.
|
// Generate a list of Cipher UUID's to be used during a query filter with an eq_any.
|
||||||
let cipher_uuids = stream::iter(ciphers).map(|c| c.uuid.to_string()).collect::<Vec<String>>().await;
|
let cipher_uuids = stream::iter(ciphers).map(|c| c.uuid.to_string()).collect::<Vec<String>>().await;
|
||||||
|
|
||||||
|
let mut cipher_folders: HashMap<String, String> = HashMap::new();
|
||||||
|
let mut cipher_favorites: HashSet<String> = HashSet::new();
|
||||||
|
match sync_type {
|
||||||
|
// User Sync supports Folders and Favorits
|
||||||
|
CipherSyncType::User => {
|
||||||
|
// Generate a HashMap with the Cipher UUID as key and the Folder UUID as value
|
||||||
|
cipher_folders = stream::iter(FolderCipher::find_by_user(user_uuid, conn).await).collect().await;
|
||||||
|
|
||||||
|
// Generate a HashSet of all the Cipher UUID's which are marked as favorite
|
||||||
|
cipher_favorites =
|
||||||
|
stream::iter(Favorite::get_all_cipher_uuid_by_user(user_uuid, conn).await).collect().await;
|
||||||
|
}
|
||||||
|
// Organization Sync does not support Folders and Favorits.
|
||||||
|
// If these are set, it will cause issues in the web-vault.
|
||||||
|
CipherSyncType::Organization => {}
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a list of Cipher UUID's containing a Vec with one or more Attachment records
|
// Generate a list of Cipher UUID's containing a Vec with one or more Attachment records
|
||||||
let mut cipher_attachments: HashMap<String, Vec<Attachment>> = HashMap::new();
|
let mut cipher_attachments: HashMap<String, Vec<Attachment>> = HashMap::new();
|
||||||
for attachment in Attachment::find_all_by_ciphers(&cipher_uuids, conn).await {
|
for attachment in Attachment::find_all_by_ciphers(&cipher_uuids, conn).await {
|
||||||
cipher_attachments.entry(attachment.cipher_uuid.to_string()).or_default().push(attachment);
|
cipher_attachments.entry(attachment.cipher_uuid.to_string()).or_default().push(attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a HashMap with the Cipher UUID as key and the Folder UUID as value
|
|
||||||
let cipher_folders: HashMap<String, String> =
|
|
||||||
stream::iter(FolderCipher::find_by_user(user_uuid, conn).await).collect().await;
|
|
||||||
|
|
||||||
// Generate a HashSet of all the Cipher UUID's which are marked as favorite
|
|
||||||
let cipher_favorites: HashSet<String> =
|
|
||||||
stream::iter(Favorite::get_all_cipher_uuid_by_user(user_uuid, conn).await).collect().await;
|
|
||||||
|
|
||||||
// Generate a HashMap with the Cipher UUID as key and one or more Collection UUID's
|
// Generate a HashMap with the Cipher UUID as key and one or more Collection UUID's
|
||||||
let mut cipher_collections: HashMap<String, Vec<String>> = HashMap::new();
|
let mut cipher_collections: HashMap<String, Vec<String>> = HashMap::new();
|
||||||
for (cipher, collection) in Cipher::get_collections_with_cipher_by_user(user_uuid, conn).await {
|
for (cipher, collection) in Cipher::get_collections_with_cipher_by_user(user_uuid, conn).await {
|
||||||
|
|
|
@ -5,7 +5,10 @@ use serde_json::Value;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{core::CipherSyncData, EmptyResult, JsonResult, JsonUpcase, NumberOrString},
|
api::{
|
||||||
|
core::{CipherSyncData, CipherSyncType},
|
||||||
|
EmptyResult, JsonResult, JsonUpcase, NumberOrString,
|
||||||
|
},
|
||||||
auth::{decode_emergency_access_invite, Headers},
|
auth::{decode_emergency_access_invite, Headers},
|
||||||
db::{models::*, DbConn, DbPool},
|
db::{models::*, DbConn, DbPool},
|
||||||
mail, CONFIG,
|
mail, CONFIG,
|
||||||
|
@ -596,7 +599,8 @@ async fn view_emergency_access(emer_id: String, headers: Headers, conn: DbConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
let ciphers = Cipher::find_owned_by_user(&emergency_access.grantor_uuid, &conn).await;
|
let ciphers = Cipher::find_owned_by_user(&emergency_access.grantor_uuid, &conn).await;
|
||||||
let cipher_sync_data = CipherSyncData::new(&emergency_access.grantor_uuid, &ciphers, &conn).await;
|
let cipher_sync_data =
|
||||||
|
CipherSyncData::new(&emergency_access.grantor_uuid, &ciphers, CipherSyncType::User, &conn).await;
|
||||||
|
|
||||||
let ciphers_json = stream::iter(ciphers)
|
let ciphers_json = stream::iter(ciphers)
|
||||||
.then(|c| async {
|
.then(|c| async {
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod sends;
|
||||||
pub mod two_factor;
|
pub mod two_factor;
|
||||||
|
|
||||||
pub use ciphers::purge_trashed_ciphers;
|
pub use ciphers::purge_trashed_ciphers;
|
||||||
pub use ciphers::CipherSyncData;
|
pub use ciphers::{CipherSyncData, CipherSyncType};
|
||||||
pub use emergency_access::{emergency_notification_reminder_job, emergency_request_timeout_job};
|
pub use emergency_access::{emergency_notification_reminder_job, emergency_request_timeout_job};
|
||||||
pub use sends::purge_sends;
|
pub use sends::purge_sends;
|
||||||
pub use two_factor::send_incomplete_2fa_notifications;
|
pub use two_factor::send_incomplete_2fa_notifications;
|
||||||
|
|
|
@ -5,8 +5,8 @@ use serde_json::Value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{
|
api::{
|
||||||
core::CipherSyncData, EmptyResult, JsonResult, JsonUpcase, JsonUpcaseVec, Notify, NumberOrString, PasswordData,
|
core::{CipherSyncData, CipherSyncType},
|
||||||
UpdateType,
|
EmptyResult, JsonResult, JsonUpcase, JsonUpcaseVec, Notify, NumberOrString, PasswordData, UpdateType,
|
||||||
},
|
},
|
||||||
auth::{decode_invite, AdminHeaders, Headers, ManagerHeaders, ManagerHeadersLoose, OwnerHeaders},
|
auth::{decode_invite, AdminHeaders, Headers, ManagerHeaders, ManagerHeadersLoose, OwnerHeaders},
|
||||||
db::{models::*, DbConn},
|
db::{models::*, DbConn},
|
||||||
|
@ -487,7 +487,7 @@ struct OrgIdData {
|
||||||
#[get("/ciphers/organization-details?<data..>")]
|
#[get("/ciphers/organization-details?<data..>")]
|
||||||
async fn get_org_details(data: OrgIdData, headers: Headers, conn: DbConn) -> Json<Value> {
|
async fn get_org_details(data: OrgIdData, headers: Headers, conn: DbConn) -> Json<Value> {
|
||||||
let ciphers = Cipher::find_by_org(&data.organization_id, &conn).await;
|
let ciphers = Cipher::find_by_org(&data.organization_id, &conn).await;
|
||||||
let cipher_sync_data = CipherSyncData::new(&headers.user.uuid, &ciphers, &conn).await;
|
let cipher_sync_data = CipherSyncData::new(&headers.user.uuid, &ciphers, CipherSyncType::Organization, &conn).await;
|
||||||
|
|
||||||
let ciphers_json = stream::iter(ciphers)
|
let ciphers_json = stream::iter(ciphers)
|
||||||
.then(|c| async {
|
.then(|c| async {
|
||||||
|
|
Loading…
Reference in New Issue