1 use super::{Cipher, User};
2 
3 db_object! {
4     #[derive(Identifiable, Queryable, Insertable, Associations)]
5     #[table_name = "favorites"]
6     #[belongs_to(User, foreign_key = "user_uuid")]
7     #[belongs_to(Cipher, foreign_key = "cipher_uuid")]
8     #[primary_key(user_uuid, cipher_uuid)]
9     pub struct Favorite {
10         pub user_uuid: String,
11         pub cipher_uuid: String,
12     }
13 }
14 
15 use crate::db::DbConn;
16 
17 use crate::api::EmptyResult;
18 use crate::error::MapResult;
19 
20 impl Favorite {
21     // Returns whether the specified cipher is a favorite of the specified user.
is_favorite(cipher_uuid: &str, user_uuid: &str, conn: &DbConn) -> bool22     pub fn is_favorite(cipher_uuid: &str, user_uuid: &str, conn: &DbConn) -> bool {
23         db_run! { conn: {
24             let query = favorites::table
25                 .filter(favorites::cipher_uuid.eq(cipher_uuid))
26                 .filter(favorites::user_uuid.eq(user_uuid))
27                 .count();
28 
29             query.first::<i64>(conn).ok().unwrap_or(0) != 0
30         }}
31     }
32 
33     // Sets whether the specified cipher is a favorite of the specified user.
set_favorite(favorite: bool, cipher_uuid: &str, user_uuid: &str, conn: &DbConn) -> EmptyResult34     pub fn set_favorite(favorite: bool, cipher_uuid: &str, user_uuid: &str, conn: &DbConn) -> EmptyResult {
35         let (old, new) = (Self::is_favorite(cipher_uuid, user_uuid, conn), favorite);
36         match (old, new) {
37             (false, true) => {
38                 User::update_uuid_revision(user_uuid, conn);
39                 db_run! { conn: {
40                 diesel::insert_into(favorites::table)
41                     .values((
42                         favorites::user_uuid.eq(user_uuid),
43                         favorites::cipher_uuid.eq(cipher_uuid),
44                     ))
45                     .execute(conn)
46                     .map_res("Error adding favorite")
47                 }}
48             }
49             (true, false) => {
50                 User::update_uuid_revision(user_uuid, conn);
51                 db_run! { conn: {
52                     diesel::delete(
53                         favorites::table
54                             .filter(favorites::user_uuid.eq(user_uuid))
55                             .filter(favorites::cipher_uuid.eq(cipher_uuid))
56                     )
57                     .execute(conn)
58                     .map_res("Error removing favorite")
59                 }}
60             }
61             // Otherwise, the favorite status is already what it should be.
62             _ => Ok(()),
63         }
64     }
65 
66     // Delete all favorite entries associated with the specified cipher.
delete_all_by_cipher(cipher_uuid: &str, conn: &DbConn) -> EmptyResult67     pub fn delete_all_by_cipher(cipher_uuid: &str, conn: &DbConn) -> EmptyResult {
68         db_run! { conn: {
69             diesel::delete(favorites::table.filter(favorites::cipher_uuid.eq(cipher_uuid)))
70                 .execute(conn)
71                 .map_res("Error removing favorites by cipher")
72         }}
73     }
74 
75     // Delete all favorite entries associated with the specified user.
delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult76     pub fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
77         db_run! { conn: {
78             diesel::delete(favorites::table.filter(favorites::user_uuid.eq(user_uuid)))
79                 .execute(conn)
80                 .map_res("Error removing favorites by user")
81         }}
82     }
83 }
84