darkwing/server/dtos/entities/
bookmark_dto.rs

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//! Data Transfer Objects for bookmark-related data structures.
//!
//! This module contains the DTO implementations for handling bookmarks,
//! specifically focusing on the transformation between encrypted database
//! records and their decrypted, application-ready representations.
//!
//! The main type provided is [`BookmarkFullData`], which represents a fully
//! processed bookmark with its decrypted URL and associated metadata.

use sqlx::types::JsonValue;

use crate::{
  database::browser_profile::{Bookmark, MainWebsite},
  server::{
    error::{AppResult, Error},
    services::database_encryption_services::DynDatabaseEncryption,
  },
};

/// Represents the complete data structure for a bookmark, including its
/// decrypted URL and associated main websites.
///
/// This struct is used to store bookmark information after processing
/// and decrypting the raw database data.
#[derive(Debug, Clone)]
pub struct BookmarkFullData {
  /// The name/title of the bookmark
  pub name: String,
  /// The decrypted URL of the bookmark
  pub url: String,
  /// A list of main websites associated with this bookmark
  pub main_website: Vec<MainWebsite>,
}

impl BookmarkFullData {
  /// Creates a new `BookmarkFullData` instance from a raw `Bookmark` and
  /// encryption service.
  ///
  /// This method handles the decryption of URLs and processing of main website
  /// data from the raw bookmark data stored in the database.
  ///
  /// # Arguments
  ///
  /// * `bookmark` - The raw bookmark data from the database
  /// * `database_encryption` - The encryption service used to decrypt the URL
  ///
  /// # Returns
  ///
  /// Returns a `Result` containing either the processed `BookmarkFullData` or
  /// an error
  ///
  /// # Errors
  ///
  /// This function will return an error in the following situations:
  /// * If the URL cannot be decoded as valid UTF-8
  /// * If the decrypted URL is empty
  /// * If the URL decryption process fails
  pub async fn new(
    bookmark: Bookmark,
    database_encryption: DynDatabaseEncryption,
  ) -> AppResult<Self> {
    let name = bookmark.name;

    let url = match bookmark.urlCrypt {
      Some(url) => {
        database_encryption
          .decrypt_string(
            bookmark.cryptoKeyId as usize,
            String::from_utf8(url).map_err(|_| {
              Error::ConfigForming(
                "URL cannot be decoded as its value is not valid UTF-8"
                  .to_string(),
              )
            })?,
          )
          .await?
      }
      None => bookmark.deletedUrl.unwrap_or_default(),
    };
    let url = url.trim().to_string();
    if url.is_empty() {
      return Err(Error::ConfigForming("URL cannot be empty".to_string()));
    }

    let empty_main_website: Vec<JsonValue> = vec![];

    let main_website_str: Vec<&str> = bookmark
      .mainWebsite
      .as_array()
      .unwrap_or(&empty_main_website)
      .iter()
      .map(|m| m.as_str().unwrap_or_default())
      .collect();

    let main_website = main_website_str
      .iter()
      .map(|item| MainWebsite::from(item.to_string()))
      .collect::<Vec<MainWebsite>>();

    Ok(Self {
      name,
      url,
      main_website,
    })
  }
}