roles/
linked_devices.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
use hdk::prelude::*;
use roles_integrity::{
    utils::{deserialize_tag, serialize_tag},
    AssigneeRoleClaimLinkTag, AssigneeToRoleLinkTag, LinkTypes,
};
use serde::de::DeserializeOwned;

use crate::{
    assignees::get_roles_for_assignee, role_claim::query_undeleted_role_claims,
    utils::create_link_relaxed,
};

#[hdk_extern]
pub fn reassign_roles_to_linked_device(linked_device: AgentPubKey) -> ExternResult<()> {
    let roles_for_linked_device = get_roles_for_assignee(linked_device.clone())?;
    let role_to_assignee_create_link_hashes_already_claimed_by_linked_device: Vec<ActionHash> =
        roles_for_linked_device
            .into_iter()
            .filter_map(|link| link.target.into_action_hash())
            .collect();

    let undeleted_role_claims_links = query_undeleted_role_claims()?;

    for undeleted_role_claim in undeleted_role_claims_links {
        let assignee_role_claim_tag: AssigneeRoleClaimLinkTag =
            deserialize_tag(undeleted_role_claim.tag)?;
        let Some(target_role_to_assignee_create_link_hash) =
            undeleted_role_claim.target.into_action_hash()
        else {
            continue;
        };

        if role_to_assignee_create_link_hashes_already_claimed_by_linked_device
            .contains(&target_role_to_assignee_create_link_hash)
        {
            continue;
        }

        let tag = AssigneeToRoleLinkTag {
            role: assignee_role_claim_tag.role,
            mode: roles_integrity::AssignmentMode::LinkedDeviceReassignment,
        };

        create_link_relaxed(
            linked_device.clone(),
            target_role_to_assignee_create_link_hash,
            LinkTypes::AssigneeToRole,
            serialize_tag(tag)?,
        )?;
    }

    Ok(())
}

pub fn call_local_zome<P, R>(
    zome_name: ZomeName,
    fn_name: FunctionName,
    payload: P,
) -> ExternResult<R>
where
    P: serde::Serialize + std::fmt::Debug,
    R: DeserializeOwned + std::fmt::Debug,
{
    let response = call_remote(
        agent_info()?.agent_initial_pubkey,
        zome_name.clone(),
        fn_name.clone(),
        None,
        payload,
    )?;

    match response {
        ZomeCallResponse::Ok(result) => {
            let result: R = result.decode().map_err(|err| wasm_error!(err))?;
            Ok(result)
        }
        _ => Err(wasm_error!(
            "Failed to call {zome_name}/{fn_name}: {response:?}."
        )),
    }
}

pub fn linked_devices_zome_name() -> Option<ZomeName> {
    match std::option_env!("LINKED_DEVICES_COORDINATOR_ZOME_NAME") {
        Some(zome_name) => Some(zome_name.into()),
        None => None,
    }
}

pub fn get_linked_devices_for(
    linked_devices_zome_name: ZomeName,
    agent: AgentPubKey,
) -> ExternResult<Vec<AgentPubKey>> {
    let links: Vec<Link> = call_local_zome(
        linked_devices_zome_name,
        "get_linked_devices_for_agent".into(),
        agent,
    )?;
    let agents: Vec<AgentPubKey> = links
        .into_iter()
        .filter_map(|link| link.target.into_agent_pub_key())
        .collect();
    Ok(agents)
}

pub fn query_my_linked_devices(
    linked_devices_zome_name: ZomeName,
) -> ExternResult<Vec<AgentPubKey>> {
    let links: Vec<Link> = call_local_zome(
        linked_devices_zome_name,
        "query_my_linked_devices".into(),
        (),
    )?;
    let agents: Vec<AgentPubKey> = links
        .into_iter()
        .filter_map(|link| link.target.into_agent_pub_key())
        .collect();
    Ok(agents)
}

pub fn get_all_my_agents() -> ExternResult<Vec<AgentPubKey>> {
    let my_pub_key = agent_info()?.agent_initial_pubkey;
    let mut my_agents = get_my_other_devices()?;
    my_agents.push(my_pub_key);

    Ok(my_agents)
}

pub fn get_my_other_devices() -> ExternResult<Vec<AgentPubKey>> {
    let my_agents = match linked_devices_zome_name() {
        Some(name) => query_my_linked_devices(name)?,
        None => vec![],
    };

    Ok(my_agents)
}