1use libsecp256k1::PublicKey;
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5use crate::LbResult;
6use crate::service::keychain::Keychain;
7
8use super::access_info::{EncryptedFolderAccessKey, UserAccessInfo, UserAccessMode};
9use super::account::Account;
10use super::clock::get_time;
11use super::crypto::AESKey;
12use super::file_metadata::{DocumentHmac, FileType, Owner};
13use super::secret_filename::SecretFileName;
14use super::signed_meta::SignedMeta;
15use super::{pubkey, symkey};
16
17#[derive(Serialize, Deserialize, Clone, Debug)]
18pub enum Meta {
19 V1 {
20 id: Uuid,
21 file_type: FileType,
22 parent: Uuid,
23 name: SecretFileName,
24 owner: Owner,
25 is_deleted: bool,
26 doc_size: Option<usize>,
27 doc_hmac: Option<DocumentHmac>,
28 user_access_keys: Vec<UserAccessInfo>,
29 folder_access_key: EncryptedFolderAccessKey,
30 },
31}
32
33impl Meta {
34 pub fn create_root(account: &Account) -> LbResult<Self> {
35 let id = Uuid::new_v4();
36 let key = symkey::generate_key();
37 let pub_key = account.public_key();
38
39 Ok(Meta::V1 {
40 id,
41 file_type: FileType::Folder,
42 parent: id,
43 name: SecretFileName::from_str(&account.username, &key, &key)?,
44 owner: Owner(pub_key),
45 is_deleted: false,
46 doc_hmac: None,
47 doc_size: None,
48 user_access_keys: vec![UserAccessInfo::encrypt(
49 account,
50 &pub_key,
51 &pub_key,
52 &key,
53 UserAccessMode::Write,
54 )?],
55 folder_access_key: symkey::encrypt(&key, &key)?,
56 })
57 }
58
59 pub fn create(
60 id: Uuid, key: AESKey, owner: &PublicKey, parent: Uuid, parent_key: &AESKey, name: &str,
61 file_type: FileType,
62 ) -> LbResult<Self> {
63 Ok(Meta::V1 {
64 id,
65 file_type,
66 parent,
67 name: SecretFileName::from_str(name, &key, parent_key)?,
68 owner: Owner(*owner),
69 is_deleted: false,
70 doc_hmac: None,
71 doc_size: None,
72 user_access_keys: Default::default(),
73 folder_access_key: symkey::encrypt(parent_key, &key)?,
74 })
75 }
76
77 pub fn set_parent(&mut self, new_parent: Uuid) {
78 match self {
79 Meta::V1 { parent, .. } => *parent = new_parent,
80 }
81 }
82
83 pub fn set_name(&mut self, new_name: SecretFileName) {
84 match self {
85 Meta::V1 { name, .. } => *name = new_name,
86 }
87 }
88
89 pub fn set_owner(&mut self, new_owner: Owner) {
90 match self {
91 Meta::V1 { owner, .. } => *owner = new_owner,
92 }
93 }
94
95 pub fn set_deleted(&mut self, new_is_deleted: bool) {
96 match self {
97 Meta::V1 { is_deleted, .. } => *is_deleted = new_is_deleted,
98 }
99 }
100
101 pub fn set_folder_access_keys(&mut self, new_keys: EncryptedFolderAccessKey) {
102 match self {
103 Meta::V1 { folder_access_key, .. } => *folder_access_key = new_keys,
104 }
105 }
106
107 pub fn user_access_keys_mut(&mut self) -> &mut Vec<UserAccessInfo> {
108 match self {
109 Meta::V1 { user_access_keys, .. } => user_access_keys,
110 }
111 }
112
113 pub fn set_hmac_and_size(&mut self, new_hmac: Option<DocumentHmac>, new_size: Option<usize>) {
114 match self {
115 Meta::V1 { doc_hmac, doc_size, .. } => {
116 *doc_hmac = new_hmac;
117 *doc_size = new_size;
118 }
119 }
120 }
121
122 pub fn set_type(&mut self, new_type: FileType) {
123 match self {
124 Meta::V1 { file_type, .. } => *file_type = new_type,
125 }
126 }
127
128 pub fn set_id(&mut self, new_id: Uuid) {
129 match self {
130 Meta::V1 { id, .. } => *id = new_id,
131 }
132 }
133
134 pub fn doc_size(&self) -> &Option<usize> {
136 match self {
137 Meta::V1 { doc_size, .. } => doc_size,
138 }
139 }
140
141 pub fn sign(self, keychain: &Keychain) -> LbResult<SignedMeta> {
142 pubkey::sign(&keychain.get_account()?.private_key, &keychain.get_pk()?, self, get_time)
143 }
144
145 pub fn sign_with(self, account: &Account) -> LbResult<SignedMeta> {
146 pubkey::sign(&account.private_key, &account.public_key(), self, get_time)
147 }
148}
149
150impl PartialEq for Meta {
152 fn eq(&self, other: &Self) -> bool {
153 match (self, other) {
154 (
155 Meta::V1 {
156 id,
157 file_type,
158 parent,
159 name,
160 owner,
161 is_deleted,
162 doc_hmac,
163 user_access_keys,
164 folder_access_key: _,
166 doc_size,
167 },
168 Meta::V1 {
169 id: other_id,
170 file_type: other_file_type,
171 parent: other_parent,
172 name: other_name,
173 owner: other_owner,
174 is_deleted: other_is_deleted,
175 doc_hmac: other_doc_hmac,
176 user_access_keys: other_user_access_keys,
177 folder_access_key: _other_folder_access_key,
179 doc_size: other_doc_size,
180 },
181 ) => {
182 id == other_id
183 && file_type == other_file_type
184 && parent == other_parent
185 && name == other_name
186 && owner == other_owner
187 && is_deleted == other_is_deleted
188 && doc_hmac == other_doc_hmac
189 && user_access_keys == other_user_access_keys
190 && doc_size == other_doc_size
191 }
192 }
193 }
194}