file_storage/
lib.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
use file_storage_integrity::*;
use hdk::prelude::*;

fn file_storage_gateway_role() -> Option<RoleName> {
    let Some(role_name) = option_env!("FILE_STORAGE_GATEWAY_ROLE") else {
        return None;
    };
    Some(RoleName::from(role_name))
}

#[hdk_extern]
pub fn init() -> ExternResult<InitCallbackResult> {
    if let Some(gateway_role) = file_storage_gateway_role() {
        let response = call(
            CallTargetCell::OtherRole(gateway_role),
            ZomeName::from("file_storage_gateway"),
            "announce_as_provider".into(),
            None,
            (),
        )?;
        let ZomeCallResponse::Ok(_) = response else {
            return Ok(InitCallbackResult::Fail(format!(
                "Failed to announce as provider: {response:?}"
            )));
        };
    }

    Ok(InitCallbackResult::Pass)
}

#[hdk_extern]
pub fn create_file_chunk(file_chunk: FileChunk) -> ExternResult<EntryHash> {
    let file_chunk_hash = hash_entry(&file_chunk)?;

    create_relaxed(&EntryTypes::FileChunk(file_chunk))?;

    Ok(file_chunk_hash)
}

#[hdk_extern]
pub fn create_file_metadata(file_metadata: FileMetadata) -> ExternResult<EntryHash> {
    let hash = hash_entry(&file_metadata)?;
    create_relaxed(&EntryTypes::FileMetadata(file_metadata))?;

    Ok(hash)
}

#[hdk_extern]
pub fn get_file_metadata(file_metadata_hash: EntryHash) -> ExternResult<FileMetadata> {
    let record = get(file_metadata_hash, GetOptions::default())?
        .ok_or(wasm_error!(WasmErrorInner::Guest("File not found".into())))?;

    let file_metadata: FileMetadata = record
        .entry()
        .to_app_option()
        .map_err(|e| wasm_error!(e))?
        .ok_or(wasm_error!(WasmErrorInner::Guest(
            "Malformed file chunk".into()
        )))?;

    Ok(file_metadata)
}

#[hdk_extern]
pub fn get_file_chunk(file_chunk_hash: EntryHash) -> ExternResult<FileChunk> {
    let record = get(file_chunk_hash, GetOptions::default())?
        .ok_or(wasm_error!(WasmErrorInner::Guest("File not found".into())))?;

    let file_chunk: FileChunk = record
        .entry()
        .to_app_option()
        .map_err(|e| wasm_error!(e))?
        .ok_or(wasm_error!(WasmErrorInner::Guest(
            "Malformed file chunk".into()
        )))?;

    Ok(file_chunk)
}

pub fn create_relaxed<I, E, E2>(input: I) -> ExternResult<ActionHash>
where
    ScopedEntryDefIndex: for<'a> TryFrom<&'a I, Error = E2>,
    EntryVisibility: for<'a> From<&'a I>,
    Entry: TryFrom<I, Error = E>,
    WasmError: From<E>,
    WasmError: From<E2>,
{
    let ScopedEntryDefIndex {
        zome_index,
        zome_type: entry_def_index,
    } = (&input).try_into()?;
    let visibility = EntryVisibility::from(&input);
    let create_input = CreateInput::new(
        EntryDefLocation::app(zome_index, entry_def_index),
        visibility,
        input.try_into()?,
        ChainTopOrdering::Relaxed,
    );
    create(create_input)
}