Skip to content

Commit

Permalink
feat: 1. support governance canister as controller; 2. support file h…
Browse files Browse the repository at this point in the history
…ash as access token
  • Loading branch information
zensh committed Oct 20, 2024
1 parent 6e0edad commit cd7aacd
Show file tree
Hide file tree
Showing 28 changed files with 264 additions and 150 deletions.
130 changes: 64 additions & 66 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ strip = true
opt-level = 's'

[workspace.package]
version = "0.9.3"
version = "0.9.5"
edition = "2021"
repository = "https://github.com/ldclabs/ic-oss"
keywords = ["file", "storage", "oss", "s3", "icp"]
Expand Down Expand Up @@ -46,7 +46,7 @@ ic-cdk-timers = "0.10"
ic-stable-structures = "0.6"
icrc-ledger-types = "0.1"
ic-http-certification = { version = "2.6", features = ["serde"] }
ic-agent = "0.38"
ic-agent = "0.39"
anyhow = "1"
crc32fast = "1.4"
url = "2.5"
Expand Down
3 changes: 3 additions & 0 deletions src/declarations/ic_oss_bucket/ic_oss_bucket.did
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ type BucketInfo = record {
total_chunks : nat64;
trusted_eddsa_pub_keys : vec blob;
managers : vec principal;
governance_canister : opt principal;
name : text;
max_custom_data_size : nat16;
auditors : vec principal;
Expand Down Expand Up @@ -79,6 +80,7 @@ type FolderInfo = record {
};
type FolderName = record { id : nat32; name : text };
type InitArgs = record {
governance_canister : opt principal;
name : text;
max_custom_data_size : nat16;
max_children : nat16;
Expand Down Expand Up @@ -146,6 +148,7 @@ type UpdateFolderInput = record {
name : opt text;
};
type UpgradeArgs = record {
governance_canister : opt principal;
max_custom_data_size : opt nat16;
max_children : opt nat16;
enable_hash_index : opt bool;
Expand Down
3 changes: 3 additions & 0 deletions src/declarations/ic_oss_bucket/ic_oss_bucket.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface BucketInfo {
'total_chunks' : bigint,
'trusted_eddsa_pub_keys' : Array<Uint8Array | number[]>,
'managers' : Array<Principal>,
'governance_canister' : [] | [Principal],
'name' : string,
'max_custom_data_size' : number,
'auditors' : Array<Principal>,
Expand Down Expand Up @@ -86,6 +87,7 @@ export interface FolderInfo {
}
export interface FolderName { 'id' : number, 'name' : string }
export interface InitArgs {
'governance_canister' : [] | [Principal],
'name' : string,
'max_custom_data_size' : number,
'max_children' : number,
Expand Down Expand Up @@ -175,6 +177,7 @@ export interface UpdateFolderInput {
'name' : [] | [string],
}
export interface UpgradeArgs {
'governance_canister' : [] | [Principal],
'max_custom_data_size' : [] | [number],
'max_children' : [] | [number],
'enable_hash_index' : [] | [boolean],
Expand Down
5 changes: 5 additions & 0 deletions src/declarations/ic_oss_bucket/ic_oss_bucket.did.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
export const idlFactory = ({ IDL }) => {
const UpgradeArgs = IDL.Record({
'governance_canister' : IDL.Opt(IDL.Principal),
'max_custom_data_size' : IDL.Opt(IDL.Nat16),
'max_children' : IDL.Opt(IDL.Nat16),
'enable_hash_index' : IDL.Opt(IDL.Bool),
'max_file_size' : IDL.Opt(IDL.Nat64),
'max_folder_depth' : IDL.Opt(IDL.Nat8),
});
const InitArgs = IDL.Record({
'governance_canister' : IDL.Opt(IDL.Principal),
'name' : IDL.Text,
'max_custom_data_size' : IDL.Nat16,
'max_children' : IDL.Nat16,
Expand Down Expand Up @@ -66,6 +68,7 @@ export const idlFactory = ({ IDL }) => {
'total_chunks' : IDL.Nat64,
'trusted_eddsa_pub_keys' : IDL.Vec(IDL.Vec(IDL.Nat8)),
'managers' : IDL.Vec(IDL.Principal),
'governance_canister' : IDL.Opt(IDL.Principal),
'name' : IDL.Text,
'max_custom_data_size' : IDL.Nat16,
'auditors' : IDL.Vec(IDL.Principal),
Expand Down Expand Up @@ -365,13 +368,15 @@ export const idlFactory = ({ IDL }) => {
};
export const init = ({ IDL }) => {
const UpgradeArgs = IDL.Record({
'governance_canister' : IDL.Opt(IDL.Principal),
'max_custom_data_size' : IDL.Opt(IDL.Nat16),
'max_children' : IDL.Opt(IDL.Nat16),
'enable_hash_index' : IDL.Opt(IDL.Bool),
'max_file_size' : IDL.Opt(IDL.Nat64),
'max_folder_depth' : IDL.Opt(IDL.Nat8),
});
const InitArgs = IDL.Record({
'governance_canister' : IDL.Opt(IDL.Principal),
'name' : IDL.Text,
'max_custom_data_size' : IDL.Nat16,
'max_children' : IDL.Nat16,
Expand Down
3 changes: 3 additions & 0 deletions src/declarations/ic_oss_cluster/ic_oss_cluster.did
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type ClusterInfo = record {
bucket_wasm_total : nat64;
ecdsa_key_name : text;
managers : vec principal;
governance_canister : opt principal;
name : text;
bucket_deployed_total : nat64;
token_expiration : nat64;
Expand All @@ -26,6 +27,7 @@ type ClusterInfo = record {
type DeployWasmInput = record { args : opt blob; canister : principal };
type InitArgs = record {
ecdsa_key_name : text;
governance_canister : opt principal;
name : text;
token_expiration : nat64;
bucket_topup_threshold : nat;
Expand All @@ -48,6 +50,7 @@ type Token = record {
policies : text;
};
type UpgradeArgs = record {
governance_canister : opt principal;
name : opt text;
token_expiration : opt nat64;
bucket_topup_threshold : opt nat;
Expand Down
3 changes: 3 additions & 0 deletions src/declarations/ic_oss_cluster/ic_oss_cluster.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface ClusterInfo {
'bucket_wasm_total' : bigint,
'ecdsa_key_name' : string,
'managers' : Array<Principal>,
'governance_canister' : [] | [Principal],
'name' : string,
'bucket_deployed_total' : bigint,
'token_expiration' : bigint,
Expand All @@ -37,6 +38,7 @@ export interface DeployWasmInput {
}
export interface InitArgs {
'ecdsa_key_name' : string,
'governance_canister' : [] | [Principal],
'name' : string,
'token_expiration' : bigint,
'bucket_topup_threshold' : bigint,
Expand Down Expand Up @@ -69,6 +71,7 @@ export interface Token {
'policies' : string,
}
export interface UpgradeArgs {
'governance_canister' : [] | [Principal],
'name' : [] | [string],
'token_expiration' : [] | [bigint],
'bucket_topup_threshold' : [] | [bigint],
Expand Down
5 changes: 5 additions & 0 deletions src/declarations/ic_oss_cluster/ic_oss_cluster.did.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
export const idlFactory = ({ IDL }) => {
const UpgradeArgs = IDL.Record({
'governance_canister' : IDL.Opt(IDL.Principal),
'name' : IDL.Opt(IDL.Text),
'token_expiration' : IDL.Opt(IDL.Nat64),
'bucket_topup_threshold' : IDL.Opt(IDL.Nat),
'bucket_topup_amount' : IDL.Opt(IDL.Nat),
});
const InitArgs = IDL.Record({
'ecdsa_key_name' : IDL.Text,
'governance_canister' : IDL.Opt(IDL.Principal),
'name' : IDL.Text,
'token_expiration' : IDL.Nat64,
'bucket_topup_threshold' : IDL.Nat,
Expand Down Expand Up @@ -64,6 +66,7 @@ export const idlFactory = ({ IDL }) => {
'bucket_wasm_total' : IDL.Nat64,
'ecdsa_key_name' : IDL.Text,
'managers' : IDL.Vec(IDL.Principal),
'governance_canister' : IDL.Opt(IDL.Principal),
'name' : IDL.Text,
'bucket_deployed_total' : IDL.Nat64,
'token_expiration' : IDL.Nat64,
Expand Down Expand Up @@ -198,13 +201,15 @@ export const idlFactory = ({ IDL }) => {
};
export const init = ({ IDL }) => {
const UpgradeArgs = IDL.Record({
'governance_canister' : IDL.Opt(IDL.Principal),
'name' : IDL.Opt(IDL.Text),
'token_expiration' : IDL.Opt(IDL.Nat64),
'bucket_topup_threshold' : IDL.Opt(IDL.Nat),
'bucket_topup_amount' : IDL.Opt(IDL.Nat),
});
const InitArgs = IDL.Record({
'ecdsa_key_name' : IDL.Text,
'governance_canister' : IDL.Opt(IDL.Principal),
'name' : IDL.Text,
'token_expiration' : IDL.Nat64,
'bucket_topup_threshold' : IDL.Nat,
Expand Down
3 changes: 3 additions & 0 deletions src/ic_oss_bucket/ic_oss_bucket.did
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ type BucketInfo = record {
total_chunks : nat64;
trusted_eddsa_pub_keys : vec blob;
managers : vec principal;
governance_canister : opt principal;
name : text;
max_custom_data_size : nat16;
auditors : vec principal;
Expand Down Expand Up @@ -79,6 +80,7 @@ type FolderInfo = record {
};
type FolderName = record { id : nat32; name : text };
type InitArgs = record {
governance_canister : opt principal;
name : text;
max_custom_data_size : nat16;
max_children : nat16;
Expand Down Expand Up @@ -146,6 +148,7 @@ type UpdateFolderInput = record {
name : opt text;
};
type UpgradeArgs = record {
governance_canister : opt principal;
max_custom_data_size : opt nat16;
max_children : opt nat16;
enable_hash_index : opt bool;
Expand Down
71 changes: 36 additions & 35 deletions src/ic_oss_bucket/src/api_http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ static IC_CERTIFICATE_EXPRESSION_HEADER: &str = "ic-certificateexpression";
// https://mmrxu-fqaaa-aaaap-ahhna-cai.icp0.io/f/1
// http://mmrxu-fqaaa-aaaap-ahhna-cai.localhost:4943/f/1 // download file by id 1
// http://mmrxu-fqaaa-aaaap-ahhna-cai.localhost:4943/h/8546ffa4296a6960e9e64e95de178d40c231a0cd358a65477bc56a105dda1c1d //download file by hash 854...
// TODO: 1. support range request; 2. token verification; 3. cache control
#[ic_cdk::query(hidden = true)]
fn http_request(request: HttpRequest) -> HttpStreamingResponse {
let witness = store::state::http_tree_with(|t| {
Expand Down Expand Up @@ -124,26 +123,6 @@ fn http_request(request: HttpRequest) -> HttpStreamingResponse {
param.file
};

let canister = ic_cdk::id();
let ctx = match store::state::with(|s| {
s.read_permission(
ic_cdk::caller(),
&canister,
param.token,
ic_cdk::api::time() / SECONDS,
)
}) {
Ok(ctx) => ctx,
Err((status_code, err)) => {
return HttpStreamingResponse {
status_code,
headers,
body: ByteBuf::from(err.as_bytes()),
..Default::default()
};
}
};

match store::fs::get_file(id) {
None => HttpStreamingResponse {
status_code: 404,
Expand All @@ -152,22 +131,44 @@ fn http_request(request: HttpRequest) -> HttpStreamingResponse {
..Default::default()
},
Some(file) => {
if file.status < 0 && ctx.role < store::Role::Auditor {
return HttpStreamingResponse {
status_code: 403,
headers,
body: ByteBuf::from("file archived".as_bytes()),
..Default::default()
if !file.read_by_hash(&param.token) {
let canister = ic_cdk::id();
let ctx = match store::state::with(|s| {
s.read_permission(
ic_cdk::caller(),
&canister,
param.token,
ic_cdk::api::time() / SECONDS,
)
}) {
Ok(ctx) => ctx,
Err((status_code, err)) => {
return HttpStreamingResponse {
status_code,
headers,
body: ByteBuf::from(err.as_bytes()),
..Default::default()
};
}
};
}

if !permission::check_file_read(&ctx.ps, &canister, id, file.parent) {
return HttpStreamingResponse {
status_code: 403,
headers,
body: ByteBuf::from("permission denied".as_bytes()),
..Default::default()
};
if file.status < 0 && ctx.role < store::Role::Auditor {
return HttpStreamingResponse {
status_code: 403,
headers,
body: ByteBuf::from("file archived".as_bytes()),
..Default::default()
};
}

if !permission::check_file_read(&ctx.ps, &canister, id, file.parent) {
return HttpStreamingResponse {
status_code: 403,
headers,
body: ByteBuf::from("permission denied".as_bytes()),
..Default::default()
};
}
}

if file.size != file.filled {
Expand Down
8 changes: 7 additions & 1 deletion src/ic_oss_bucket/src/api_init.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use candid::CandidType;
use candid::{CandidType, Principal};
use ic_oss_types::file::MAX_FILE_SIZE;
use serde::Deserialize;

Expand All @@ -20,6 +20,7 @@ pub struct InitArgs {
max_custom_data_size: u16, // in bytes, default is 4KB
enable_hash_index: bool, // if enabled, indexing will be built using file hash, allowing files to be read by their hash and preventing duplicate hash for files. default is false
visibility: u8, // 0: private; 1: public, can be accessed by anyone, default is 0
governance_canister: Option<Principal>,
}

#[derive(Clone, Debug, CandidType, Deserialize)]
Expand All @@ -29,6 +30,7 @@ pub struct UpgradeArgs {
max_children: Option<u16>,
max_custom_data_size: Option<u16>,
enable_hash_index: Option<bool>,
governance_canister: Option<Principal>,
}

impl UpgradeArgs {
Expand Down Expand Up @@ -89,6 +91,7 @@ fn init(args: Option<CanisterArgs>) {
b.max_custom_data_size = args.max_custom_data_size
};
b.enable_hash_index = args.enable_hash_index;
b.governance_canister = args.governance_canister;
});
}
Some(CanisterArgs::Upgrade(_)) => {
Expand Down Expand Up @@ -133,6 +136,9 @@ fn post_upgrade(args: Option<CanisterArgs>) {
if let Some(enable_hash_index) = args.enable_hash_index {
s.enable_hash_index = enable_hash_index;
}
if let Some(governance_canister) = args.governance_canister {
s.governance_canister = Some(governance_canister);
}
});
}
Some(CanisterArgs::Init(_)) => {
Expand Down
Loading

0 comments on commit cd7aacd

Please sign in to comment.