chain_of_custody_integrity/
custody_transfer.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use hdi::prelude::*;

#[derive(Clone, PartialEq)]
#[hdk_entry_helper]
pub struct CustodyTransfer {
    pub current_custodian: AgentPubKey,
    pub custodied_resource_hash: ActionHash,
    pub location: Option<String>,
    pub notes: Option<String>,
    pub images_hashes: Vec<EntryHash>,
    pub previous_custody_transfer_hash: Option<EntryHash>,
}

pub fn validate_create_custody_transfer(
    _action: EntryCreationAction,
    custody_transfer: CustodyTransfer,
) -> ExternResult<ValidateCallbackResult> {
    let _record = must_get_valid_record(custody_transfer.custodied_resource_hash.clone())?;

    // TODO: validate record?

    if let Some(entry_hash) = custody_transfer.previous_custody_transfer_hash.clone() {
        validate_custody_transfer(entry_hash)
    } else {
        // TODO: add the appropriate validation rules
        Ok(ValidateCallbackResult::Valid)
    }
}

pub fn validate_update_custody_transfer(
    _action: Update,
    _custody_transfer: CustodyTransfer,
    _original_action: EntryCreationAction,
    _original_custody_transfer: CustodyTransfer,
) -> ExternResult<ValidateCallbackResult> {
    Ok(ValidateCallbackResult::Invalid(
        "Custody Transfers cannot be updated".to_string(),
    ))
}

pub fn validate_delete_custody_transfer(
    _action: Delete,
    _original_action: EntryCreationAction,
    _original_custody_transfer: CustodyTransfer,
) -> ExternResult<ValidateCallbackResult> {
    Ok(ValidateCallbackResult::Invalid(
        "Custody Transfers cannot be deleted".to_string(),
    ))
}

pub fn validate_create_link_resource_to_custody_transfers(
    _action: CreateLink,
    base_address: AnyLinkableHash,
    target_address: AnyLinkableHash,
    _tag: LinkTag,
) -> ExternResult<ValidateCallbackResult> {
    let action_hash = base_address
        .into_action_hash()
        .ok_or(wasm_error!(WasmErrorInner::Guest(
            "No action hash associated with link".to_string()
        )))?;
    let _record = must_get_valid_record(action_hash)?;
    // TODO: validate record?

    let entry_hash = target_address
        .into_entry_hash()
        .ok_or(wasm_error!(WasmErrorInner::Guest(
            "No action hash associated with link".to_string()
        )))?;

    validate_custody_transfer(entry_hash)
}

fn validate_custody_transfer(entry_hash: EntryHash) -> ExternResult<ValidateCallbackResult> {
    let entry = must_get_entry(entry_hash)?;

    let Entry::CounterSign(_, bytes) = entry.content else {
        return Ok(ValidateCallbackResult::Invalid(
            "Custody transfer entry is not a countersigned entry.".into(),
        ));
    };

    let Ok(_custody_transfer) = crate::CustodyTransfer::try_from(bytes.0) else {
        return Ok(ValidateCallbackResult::Invalid(
            "ResourceToCustodyTransfers links points to an entry that is not a CustodyTransfer"
                .into(),
        ));
    };
    Ok(ValidateCallbackResult::Valid)
}

pub fn validate_delete_link_resource_to_custody_transfers(
    _action: DeleteLink,
    _original_action: CreateLink,
    _base: AnyLinkableHash,
    _target: AnyLinkableHash,
    _tag: LinkTag,
) -> ExternResult<ValidateCallbackResult> {
    Ok(ValidateCallbackResult::Invalid(
        "ResourceToCustodyTransfers links cannot be deleted".to_string(),
    ))
}

pub fn validate_create_link_custody_transfer_to_custody_transfers(
    _action: CreateLink,
    base_address: AnyLinkableHash,
    target_address: AnyLinkableHash,
    _tag: LinkTag,
) -> ExternResult<ValidateCallbackResult> {
    let entry_hash = base_address
        .into_entry_hash()
        .ok_or(wasm_error!(WasmErrorInner::Guest(
            "No entry hash associated with link".to_string()
        )))?;

    let valid = validate_custody_transfer(entry_hash)?;

    let ValidateCallbackResult::Valid = valid else {
        return Ok(valid);
    };

    let entry_hash = target_address
        .into_entry_hash()
        .ok_or(wasm_error!(WasmErrorInner::Guest(
            "No entry hash associated with link".to_string()
        )))?;

    validate_custody_transfer(entry_hash)
}

pub fn validate_delete_link_custody_transfer_to_custody_transfers(
    _action: DeleteLink,
    _original_action: CreateLink,
    _base: AnyLinkableHash,
    _target: AnyLinkableHash,
    _tag: LinkTag,
) -> ExternResult<ValidateCallbackResult> {
    Ok(ValidateCallbackResult::Invalid(
        "CustodyTransferToCustodyTransfers links cannot be deleted".to_string(),
    ))
}