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,
})
}
}