diff options
author | Jeremy Lin <[email protected]> | 2020-08-26 01:27:38 -0700 |
---|---|---|
committer | Jeremy Lin <[email protected]> | 2020-08-26 01:27:38 -0700 |
commit | 175d647e47fbd9abec4134c708199ba8aa1ec682 (patch) | |
tree | d33c7269c118a669d28214004ad9404f1b9d4a2e /src/db/models/favorite.rs | |
parent | 4c324e11606b25b8bec7396af56d5c252c3f04e8 (diff) | |
download | vaultwarden-175d647e47fbd9abec4134c708199ba8aa1ec682.tar.gz vaultwarden-175d647e47fbd9abec4134c708199ba8aa1ec682.zip |
Delete associated favorites when deleting a cipher or user
This prevents foreign key constraint violations.
Diffstat (limited to 'src/db/models/favorite.rs')
-rw-r--r-- | src/db/models/favorite.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/db/models/favorite.rs b/src/db/models/favorite.rs new file mode 100644 index 00000000..f419e07d --- /dev/null +++ b/src/db/models/favorite.rs @@ -0,0 +1,83 @@ +use super::{Cipher, User}; + +db_object! { + #[derive(Debug, Identifiable, Queryable, Insertable, Associations)] + #[table_name = "favorites"] + #[belongs_to(User, foreign_key = "user_uuid")] + #[belongs_to(Cipher, foreign_key = "cipher_uuid")] + #[primary_key(user_uuid, cipher_uuid)] + pub struct Favorite { + pub user_uuid: String, + pub cipher_uuid: String, + } +} + +use crate::db::DbConn; + +use crate::api::EmptyResult; +use crate::error::MapResult; + +impl Favorite { + // Returns whether the specified cipher is a favorite of the specified user. + pub fn is_favorite(cipher_uuid: &str, user_uuid: &str, conn: &DbConn) -> bool { + db_run!{ conn: { + let query = favorites::table + .filter(favorites::cipher_uuid.eq(cipher_uuid)) + .filter(favorites::user_uuid.eq(user_uuid)) + .count(); + + query.first::<i64>(conn).ok().unwrap_or(0) != 0 + }} + } + + // Sets whether the specified cipher is a favorite of the specified user. + pub fn set_favorite(favorite: bool, cipher_uuid: &str, user_uuid: &str, conn: &DbConn) -> EmptyResult { + let (old, new) = (Self::is_favorite(cipher_uuid, user_uuid, &conn), favorite); + match (old, new) { + (false, true) => { + User::update_uuid_revision(user_uuid, &conn); + db_run!{ conn: { + diesel::insert_into(favorites::table) + .values(( + favorites::user_uuid.eq(user_uuid), + favorites::cipher_uuid.eq(cipher_uuid), + )) + .execute(conn) + .map_res("Error adding favorite") + }} + } + (true, false) => { + User::update_uuid_revision(user_uuid, &conn); + db_run!{ conn: { + diesel::delete( + favorites::table + .filter(favorites::user_uuid.eq(user_uuid)) + .filter(favorites::cipher_uuid.eq(cipher_uuid)) + ) + .execute(conn) + .map_res("Error removing favorite") + }} + } + // Otherwise, the favorite status is already what it should be. + _ => Ok(()) + } + } + + // Delete all favorite entries associated with the specified cipher. + pub fn delete_all_by_cipher(cipher_uuid: &str, conn: &DbConn) -> EmptyResult { + db_run! { conn: { + diesel::delete(favorites::table.filter(favorites::cipher_uuid.eq(cipher_uuid))) + .execute(conn) + .map_res("Error removing favorites by cipher") + }} + } + + // Delete all favorite entries associated with the specified user. + pub fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult { + db_run! { conn: { + diesel::delete(favorites::table.filter(favorites::user_uuid.eq(user_uuid))) + .execute(conn) + .map_res("Error removing favorites by user") + }} + } +} |