Skip to main content

junobuild_cdn/proposals/workflows/
submit.rs

1use crate::proposals::errors::{
2    JUNO_CDN_PROPOSALS_ERROR_CANNOT_SUBMIT, JUNO_CDN_PROPOSALS_ERROR_CANNOT_SUBMIT_INVALID_STATUS,
3};
4use crate::proposals::workflows::assert::assert_known_proposal_type;
5use crate::proposals::{get_proposal, insert_proposal};
6use crate::proposals::{Proposal, ProposalId, ProposalStatus};
7use crate::storage::stable::get_assets;
8use crate::strategies::CdnStableStrategy;
9use candid::Principal;
10use junobuild_shared::types::core::{Hash, Hashable};
11use junobuild_shared::utils::principal_not_equal;
12use sha2::{Digest, Sha256};
13
14pub fn submit_proposal(
15    cdn_stable: &impl CdnStableStrategy,
16    caller: Principal,
17    proposal_id: &ProposalId,
18) -> Result<(ProposalId, Proposal), String> {
19    let proposal = get_proposal(cdn_stable, proposal_id);
20
21    match proposal {
22        None => Err(JUNO_CDN_PROPOSALS_ERROR_CANNOT_SUBMIT.to_string()),
23        Some(proposal) => secure_submit_proposal(cdn_stable, caller, proposal_id, &proposal),
24    }
25}
26
27fn secure_submit_proposal(
28    cdn_stable: &impl CdnStableStrategy,
29    caller: Principal,
30    proposal_id: &ProposalId,
31    proposal: &Proposal,
32) -> Result<(ProposalId, Proposal), String> {
33    // The one that started the upload should be the one that propose it.
34    if principal_not_equal(caller, proposal.owner) {
35        return Err(JUNO_CDN_PROPOSALS_ERROR_CANNOT_SUBMIT.to_string());
36    }
37
38    if proposal.status != ProposalStatus::Initialized {
39        return Err(format!(
40            "{} ({:?})",
41            JUNO_CDN_PROPOSALS_ERROR_CANNOT_SUBMIT_INVALID_STATUS, proposal.status
42        ));
43    }
44
45    assert_known_proposal_type(proposal)?;
46
47    let assets = get_assets(cdn_stable, proposal_id);
48
49    let mut hasher = Sha256::new();
50
51    for (key, asset) in assets {
52        hasher.update(key.hash());
53        hasher.update(asset.hash());
54
55        for (_, encoding) in asset.encodings {
56            hasher.update(encoding.hash());
57        }
58    }
59
60    let hash: Hash = hasher.finalize().into();
61
62    let proposal: Proposal = Proposal::open(proposal, hash);
63
64    insert_proposal(cdn_stable, proposal_id, &proposal);
65
66    Ok((*proposal_id, proposal))
67}