1use crate::{
8 dto::{
9 metadata::CanicMetadataResponse,
10 role::{RoleCapability, RoleOverviewResponse},
11 state::BootstrapStatusResponse,
12 },
13 ids::CanisterRole,
14 role_contract::RoleCapabilityKey,
15};
16use std::collections::BTreeSet;
17
18pub struct RoleOverviewApi;
20
21impl RoleOverviewApi {
22 #[must_use]
24 pub fn overview(
25 role: CanisterRole,
26 capabilities: &BTreeSet<RoleCapabilityKey>,
27 protocol_profile_digest: [u8; 32],
28 metadata: CanicMetadataResponse,
29 bootstrap: BootstrapStatusResponse,
30 ) -> RoleOverviewResponse {
31 let mut capabilities = capabilities
32 .iter()
33 .copied()
34 .filter_map(capability_view)
35 .collect::<Vec<_>>();
36 capabilities.sort_unstable();
37
38 RoleOverviewResponse {
39 role,
40 capabilities,
41 protocol_profile_digest,
42 metadata,
43 bootstrap,
44 }
45 }
46}
47
48const fn capability_view(capability: RoleCapabilityKey) -> Option<RoleCapability> {
49 Some(match capability {
50 RoleCapabilityKey::AutomaticTopup => RoleCapability::AutomaticTopup,
51 RoleCapabilityKey::ChildProvisioning => RoleCapability::ChildProvisioning,
52 RoleCapabilityKey::DelegatedTokenIssuer => RoleCapability::DelegatedTokenIssuer,
53 RoleCapabilityKey::DelegatedTokenVerifier => RoleCapability::DelegatedTokenVerifier,
54 RoleCapabilityKey::FleetAdmissionProjection => RoleCapability::FleetAdmissionProjection,
55 RoleCapabilityKey::FleetCoordinator => RoleCapability::FleetCoordinator,
56 RoleCapabilityKey::Index => RoleCapability::Index,
57 RoleCapabilityKey::Icrc21 => RoleCapability::Icrc21,
58 RoleCapabilityKey::LocalApplicationAuthorization => return None,
59 RoleCapabilityKey::RoleAttestationSigner => RoleCapability::RoleAttestationSigner,
60 RoleCapabilityKey::RoleAttestationVerifier => RoleCapability::RoleAttestationVerifier,
61 RoleCapabilityKey::Root => RoleCapability::Root,
62 RoleCapabilityKey::RootControlPlane => RoleCapability::RootControlPlane,
63 RoleCapabilityKey::RootDelegation => RoleCapability::RootDelegation,
64 RoleCapabilityKey::Runtime => RoleCapability::Runtime,
65 RoleCapabilityKey::Scaling => RoleCapability::Scaling,
66 RoleCapabilityKey::Sharding => RoleCapability::Sharding,
67 RoleCapabilityKey::WasmStore => RoleCapability::WasmStore,
68 })
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn overview_projects_public_capabilities_in_lexical_order() {
77 let capabilities = BTreeSet::from([
78 RoleCapabilityKey::AutomaticTopup,
79 RoleCapabilityKey::ChildProvisioning,
80 RoleCapabilityKey::DelegatedTokenIssuer,
81 RoleCapabilityKey::DelegatedTokenVerifier,
82 RoleCapabilityKey::FleetAdmissionProjection,
83 RoleCapabilityKey::FleetCoordinator,
84 RoleCapabilityKey::Index,
85 RoleCapabilityKey::Icrc21,
86 RoleCapabilityKey::LocalApplicationAuthorization,
87 RoleCapabilityKey::RoleAttestationSigner,
88 RoleCapabilityKey::RoleAttestationVerifier,
89 RoleCapabilityKey::Root,
90 RoleCapabilityKey::RootControlPlane,
91 RoleCapabilityKey::Runtime,
92 RoleCapabilityKey::Scaling,
93 RoleCapabilityKey::Sharding,
94 RoleCapabilityKey::WasmStore,
95 ]);
96 let overview = RoleOverviewApi::overview(
97 CanisterRole::new("app"),
98 &capabilities,
99 [9; 32],
100 CanicMetadataResponse {
101 package_name: "app".to_string(),
102 package_version: "0.1.0".to_string(),
103 package_description: "test".to_string(),
104 canic_version: "0.103.0".to_string(),
105 canister_version: 4,
106 },
107 BootstrapStatusResponse {
108 ready: true,
109 phase: "ready".to_string(),
110 last_error: None,
111 },
112 );
113
114 assert_eq!(
115 overview.capabilities,
116 vec![
117 RoleCapability::AutomaticTopup,
118 RoleCapability::ChildProvisioning,
119 RoleCapability::DelegatedTokenIssuer,
120 RoleCapability::DelegatedTokenVerifier,
121 RoleCapability::FleetAdmissionProjection,
122 RoleCapability::FleetCoordinator,
123 RoleCapability::Icrc21,
124 RoleCapability::Index,
125 RoleCapability::RoleAttestationSigner,
126 RoleCapability::RoleAttestationVerifier,
127 RoleCapability::Root,
128 RoleCapability::RootControlPlane,
129 RoleCapability::Runtime,
130 RoleCapability::Scaling,
131 RoleCapability::Sharding,
132 RoleCapability::WasmStore,
133 ]
134 );
135 assert_eq!(overview.protocol_profile_digest, [9; 32]);
136 }
137}