|
|
|
@ -1,5 +1,11 @@
|
|
|
|
|
use chrono::{NaiveDateTime, Utc};
|
|
|
|
|
use rocket::request::FromParam;
|
|
|
|
|
use serde_json::Value;
|
|
|
|
|
use std::{
|
|
|
|
|
borrow::Borrow,
|
|
|
|
|
fmt::{Display, Formatter},
|
|
|
|
|
ops::Deref,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use super::{CipherId, User, UserId};
|
|
|
|
|
|
|
|
|
@ -8,7 +14,7 @@ db_object! {
|
|
|
|
|
#[diesel(table_name = folders)]
|
|
|
|
|
#[diesel(primary_key(uuid))]
|
|
|
|
|
pub struct Folder {
|
|
|
|
|
pub uuid: String,
|
|
|
|
|
pub uuid: FolderId,
|
|
|
|
|
pub created_at: NaiveDateTime,
|
|
|
|
|
pub updated_at: NaiveDateTime,
|
|
|
|
|
pub user_uuid: UserId,
|
|
|
|
@ -20,7 +26,7 @@ db_object! {
|
|
|
|
|
#[diesel(primary_key(cipher_uuid, folder_uuid))]
|
|
|
|
|
pub struct FolderCipher {
|
|
|
|
|
pub cipher_uuid: CipherId,
|
|
|
|
|
pub folder_uuid: String,
|
|
|
|
|
pub folder_uuid: FolderId,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -30,7 +36,7 @@ impl Folder {
|
|
|
|
|
let now = Utc::now().naive_utc();
|
|
|
|
|
|
|
|
|
|
Self {
|
|
|
|
|
uuid: crate::util::get_uuid(),
|
|
|
|
|
uuid: FolderId(crate::util::get_uuid()),
|
|
|
|
|
created_at: now,
|
|
|
|
|
updated_at: now,
|
|
|
|
|
|
|
|
|
@ -52,10 +58,10 @@ impl Folder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl FolderCipher {
|
|
|
|
|
pub fn new(folder_uuid: &str, cipher_uuid: &CipherId) -> Self {
|
|
|
|
|
pub fn new(folder_uuid: FolderId, cipher_uuid: CipherId) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
folder_uuid: folder_uuid.to_string(),
|
|
|
|
|
cipher_uuid: cipher_uuid.clone(),
|
|
|
|
|
folder_uuid,
|
|
|
|
|
cipher_uuid,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -120,7 +126,7 @@ impl Folder {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn find_by_uuid_and_user(uuid: &str, user_uuid: &UserId, conn: &mut DbConn) -> Option<Self> {
|
|
|
|
|
pub async fn find_by_uuid_and_user(uuid: &FolderId, user_uuid: &UserId, conn: &mut DbConn) -> Option<Self> {
|
|
|
|
|
db_run! { conn: {
|
|
|
|
|
folders::table
|
|
|
|
|
.filter(folders::uuid.eq(uuid))
|
|
|
|
@ -185,7 +191,7 @@ impl FolderCipher {
|
|
|
|
|
}}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn delete_all_by_folder(folder_uuid: &str, conn: &mut DbConn) -> EmptyResult {
|
|
|
|
|
pub async fn delete_all_by_folder(folder_uuid: &FolderId, conn: &mut DbConn) -> EmptyResult {
|
|
|
|
|
db_run! { conn: {
|
|
|
|
|
diesel::delete(folders_ciphers::table.filter(folders_ciphers::folder_uuid.eq(folder_uuid)))
|
|
|
|
|
.execute(conn)
|
|
|
|
@ -194,7 +200,7 @@ impl FolderCipher {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn find_by_folder_and_cipher(
|
|
|
|
|
folder_uuid: &str,
|
|
|
|
|
folder_uuid: &FolderId,
|
|
|
|
|
cipher_uuid: &CipherId,
|
|
|
|
|
conn: &mut DbConn,
|
|
|
|
|
) -> Option<Self> {
|
|
|
|
@ -208,7 +214,7 @@ impl FolderCipher {
|
|
|
|
|
}}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn find_by_folder(folder_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
|
|
|
|
|
pub async fn find_by_folder(folder_uuid: &FolderId, conn: &mut DbConn) -> Vec<Self> {
|
|
|
|
|
db_run! { conn: {
|
|
|
|
|
folders_ciphers::table
|
|
|
|
|
.filter(folders_ciphers::folder_uuid.eq(folder_uuid))
|
|
|
|
@ -220,14 +226,62 @@ impl FolderCipher {
|
|
|
|
|
|
|
|
|
|
/// Return a vec with (cipher_uuid, folder_uuid)
|
|
|
|
|
/// This is used during a full sync so we only need one query for all folder matches.
|
|
|
|
|
pub async fn find_by_user(user_uuid: &UserId, conn: &mut DbConn) -> Vec<(CipherId, String)> {
|
|
|
|
|
pub async fn find_by_user(user_uuid: &UserId, conn: &mut DbConn) -> Vec<(CipherId, FolderId)> {
|
|
|
|
|
db_run! { conn: {
|
|
|
|
|
folders_ciphers::table
|
|
|
|
|
.inner_join(folders::table)
|
|
|
|
|
.filter(folders::user_uuid.eq(user_uuid))
|
|
|
|
|
.select(folders_ciphers::all_columns)
|
|
|
|
|
.load::<(CipherId, String)>(conn)
|
|
|
|
|
.load::<(CipherId, FolderId)>(conn)
|
|
|
|
|
.unwrap_or_default()
|
|
|
|
|
}}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(DieselNewType, FromForm, Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct FolderId(String);
|
|
|
|
|
|
|
|
|
|
impl AsRef<str> for FolderId {
|
|
|
|
|
fn as_ref(&self) -> &str {
|
|
|
|
|
&self.0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Deref for FolderId {
|
|
|
|
|
type Target = str;
|
|
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
|
&self.0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Borrow<str> for FolderId {
|
|
|
|
|
fn borrow(&self) -> &str {
|
|
|
|
|
&self.0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Display for FolderId {
|
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
write!(f, "{}", self.0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<String> for FolderId {
|
|
|
|
|
fn from(raw: String) -> Self {
|
|
|
|
|
Self(raw)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'r> FromParam<'r> for FolderId {
|
|
|
|
|
type Error = ();
|
|
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
fn from_param(param: &'r str) -> Result<Self, Self::Error> {
|
|
|
|
|
if param.chars().all(|c| matches!(c, 'a'..='z' | 'A'..='Z' |'0'..='9' | '-')) {
|
|
|
|
|
Ok(Self(param.to_string()))
|
|
|
|
|
} else {
|
|
|
|
|
Err(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|