ic_oss_types/
bucket.rs

1use candid::{CandidType, Principal};
2use serde::{Deserialize, Serialize};
3use serde_bytes::{ByteArray, ByteBuf};
4use std::collections::BTreeSet;
5
6use crate::file::MAX_FILE_SIZE;
7
8#[derive(CandidType, Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
9pub struct BucketInfo {
10    pub name: String,
11    pub file_id: u32,
12    pub folder_id: u32,
13    pub max_file_size: u64,
14    pub max_folder_depth: u8,
15    pub max_children: u16,
16    pub max_custom_data_size: u16,
17    pub enable_hash_index: bool,
18    pub status: i8,     // -1: archived; 0: readable and writable; 1: readonly
19    pub visibility: u8, // 0: private; 1: public
20    pub total_files: u64,
21    pub total_chunks: u64,
22    pub total_folders: u64,
23    pub managers: BTreeSet<Principal>, // managers can read and write
24    // auditors can read and list even if the bucket is private
25    pub auditors: BTreeSet<Principal>,
26    // used to verify the request token signed with SECP256K1
27    pub trusted_ecdsa_pub_keys: Vec<ByteBuf>,
28    // used to verify the request token signed with ED25519
29    pub trusted_eddsa_pub_keys: Vec<ByteArray<32>>,
30    pub governance_canister: Option<Principal>,
31}
32
33#[derive(CandidType, Clone, Debug, Default, Deserialize, Serialize)]
34pub struct UpdateBucketInput {
35    pub name: Option<String>,
36    pub max_file_size: Option<u64>,
37    pub max_folder_depth: Option<u8>,
38    pub max_children: Option<u16>,
39    pub max_custom_data_size: Option<u16>,
40    pub enable_hash_index: Option<bool>,
41    pub status: Option<i8>, // -1: archived; 0: readable and writable; 1: readonly
42    pub visibility: Option<u8>, // 0: private; 1: public
43    pub trusted_ecdsa_pub_keys: Option<Vec<ByteBuf>>,
44    pub trusted_eddsa_pub_keys: Option<Vec<ByteArray<32>>>,
45}
46
47impl UpdateBucketInput {
48    pub fn validate(&self) -> Result<(), String> {
49        if let Some(name) = &self.name {
50            if name.trim().is_empty() {
51                return Err("invalid bucket name".to_string());
52            }
53        }
54        if let Some(max_file_size) = self.max_file_size {
55            if max_file_size == 0 {
56                return Err("max_file_size should be greater than 0".to_string());
57            }
58            if max_file_size < MAX_FILE_SIZE {
59                return Err(format!(
60                    "max_file_size should be greater than or equal to {}",
61                    MAX_FILE_SIZE
62                ));
63            }
64        }
65
66        if let Some(max_folder_depth) = self.max_folder_depth {
67            if max_folder_depth == 0 {
68                return Err("max_folder_depth should be greater than 0".to_string());
69            }
70        }
71
72        if let Some(max_children) = self.max_children {
73            if max_children == 0 {
74                return Err("max_children should be greater than 0".to_string());
75            }
76        }
77
78        if let Some(max_custom_data_size) = self.max_custom_data_size {
79            if max_custom_data_size == 0 {
80                return Err("max_custom_data_size should be greater than 0".to_string());
81            }
82        }
83
84        if let Some(status) = self.status {
85            if !(-1i8..=1i8).contains(&status) {
86                return Err("status should be -1, 0 or 1".to_string());
87            }
88        }
89
90        if let Some(visibility) = self.visibility {
91            if visibility != 0 && visibility != 1 {
92                return Err("visibility should be 0 or 1".to_string());
93            }
94        }
95        Ok(())
96    }
97}