diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index 899e5dda..3faf1aea 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -3,7 +3,7 @@ use serde_json::Value as JsonValue; use uuid::Uuid; -use super::{User, Organization, Attachment, FolderCipher, CollectionCipher, UserOrgType, UserOrgStatus}; +use super::{User, Organization, Attachment, FolderCipher, CollectionCipher, UserOrganization, UserOrgType, UserOrgStatus}; #[derive(Debug, Identifiable, Queryable, Insertable, Associations)] #[table_name = "ciphers"] @@ -122,7 +122,23 @@ impl Cipher { json_object } + pub fn update_users_revision(&self, conn: &DbConn) { + match self.user_uuid { + Some(ref user_uuid) => User::update_uuid_revision(&user_uuid, conn), + None => { // Belongs to Organization, need to update affected users + if let Some(ref org_uuid) = self.organization_uuid { + UserOrganization::find_by_cipher_and_org(&self.uuid, &org_uuid, conn) + .iter() + .for_each(|user_org| { + User::update_uuid_revision(&user_org.user_uuid, conn) + }); + } + } + }; + } + pub fn save(&mut self, conn: &DbConn) -> bool { + self.update_users_revision(conn); self.updated_at = Utc::now().naive_utc(); match diesel::replace_into(ciphers::table) @@ -134,6 +150,8 @@ impl Cipher { } pub fn delete(self, conn: &DbConn) -> QueryResult<()> { + self.update_users_revision(conn); + FolderCipher::delete_all_by_cipher(&self.uuid, &conn)?; CollectionCipher::delete_all_by_cipher(&self.uuid, &conn)?; Attachment::delete_all_by_cipher(&self.uuid, &conn)?; @@ -157,6 +175,7 @@ impl Cipher { None => { match folder_uuid { Some(new_folder) => { + self.update_users_revision(conn); let folder_cipher = FolderCipher::new(&new_folder, &self.uuid); folder_cipher.save(&conn).or(Err("Couldn't save folder setting")) }, @@ -169,6 +188,7 @@ impl Cipher { if current_folder == new_folder { Ok(()) //nothing to do } else { + self.update_users_revision(conn); match FolderCipher::find_by_folder_and_cipher(¤t_folder, &self.uuid, &conn) { Some(current_folder) => { current_folder.delete(&conn).or(Err("Failed removing old folder mapping")) @@ -181,6 +201,7 @@ impl Cipher { } }, None => { + self.update_users_revision(conn); match FolderCipher::find_by_folder_and_cipher(¤t_folder, &self.uuid, &conn) { Some(current_folder) => { current_folder.delete(&conn).or(Err("Failed removing old folder mapping")) diff --git a/src/db/models/folder.rs b/src/db/models/folder.rs index d9b90bf0..701a7da9 100644 --- a/src/db/models/folder.rs +++ b/src/db/models/folder.rs @@ -71,6 +71,7 @@ use db::schema::{folders, folders_ciphers}; /// Database methods impl Folder { pub fn save(&mut self, conn: &DbConn) -> bool { + User::update_uuid_revision(&self.user_uuid, conn); self.updated_at = Utc::now().naive_utc(); match diesel::replace_into(folders::table) @@ -82,6 +83,7 @@ impl Folder { } pub fn delete(self, conn: &DbConn) -> QueryResult<()> { + User::update_uuid_revision(&self.user_uuid, conn); FolderCipher::delete_all_by_folder(&self.uuid, &conn)?; diesel::delete( diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index 78e381fa..d46d15da 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -109,8 +109,7 @@ impl UserOrganization { use diesel; use diesel::prelude::*; use db::DbConn; -use db::schema::organizations; -use db::schema::users_organizations; +use db::schema::{organizations, users_organizations, users_collections, ciphers_collections}; /// Database methods impl Organization { @@ -297,6 +296,26 @@ impl UserOrganization { .filter(users_organizations::org_uuid.eq(org_uuid)) .first::(&**conn).ok() } + + pub fn find_by_cipher_and_org(cipher_uuid: &str, org_uuid: &str, conn: &DbConn) -> Vec { + users_organizations::table + .filter(users_organizations::org_uuid.eq(org_uuid)) + .left_join(users_collections::table.on( + users_collections::user_uuid.eq(users_organizations::user_uuid) + )) + .left_join(ciphers_collections::table.on( + ciphers_collections::collection_uuid.eq(users_collections::collection_uuid).and( + ciphers_collections::cipher_uuid.eq(&cipher_uuid) + ) + )) + .filter( + users_organizations::access_all.eq(true).or( // AccessAll.. + ciphers_collections::cipher_uuid.eq(&cipher_uuid) // ..or access to collection with cipher + ) + ) + .select(users_organizations::all_columns) + .load::(&**conn).expect("Error loading user organizations") + } }