aboutsummaryrefslogtreecommitdiff
path: root/src/db/models/favorite.rs
blob: 4ff31939d20619488f3c23e35cb9a0620655ee98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use super::{Cipher, User};

db_object! {
    #[derive(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 async 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 async 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).await, favorite);
        match (old, new) {
            (false, true) => {
                User::update_uuid_revision(user_uuid, conn).await;
                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).await;
                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 async 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 async 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")
        }}
    }
}