1use core_identity::Identity;
2use core_policy::{Action, Policy, PolicyRule, Resource};
3use wasm_bindgen::prelude::*;
4
5#[wasm_bindgen]
7pub struct WasmIdentity {
8 inner: Identity,
9}
10
11#[wasm_bindgen]
12impl WasmIdentity {
13 #[wasm_bindgen(constructor)]
15 pub fn new() -> Result<WasmIdentity, JsValue> {
16 let mut rng = rand::thread_rng();
17 let identity = Identity::generate(&mut rng)
18 .map_err(|e| JsValue::from_str(&format!("Failed to generate identity: {}", e)))?;
19
20 Ok(WasmIdentity { inner: identity })
21 }
22
23 #[wasm_bindgen(js_name = publicKeyHash)]
25 pub fn public_key_hash(&self) -> String {
26 hex::encode(self.inner.public_key_hash())
27 }
28
29 #[wasm_bindgen(js_name = getDid)]
31 pub fn get_did(&self) -> String {
32 format!("did:p47h:{}", self.public_key_hash())
33 }
34}
35
36#[wasm_bindgen]
38pub struct WasmPolicy {
39 inner: Policy,
40}
41
42#[wasm_bindgen]
43impl WasmPolicy {
44 #[wasm_bindgen(constructor)]
46 pub fn new(name: &str, ttl_seconds: u64) -> Result<WasmPolicy, JsValue> {
47 let now = 0;
50
51 let policy = Policy::new(name, ttl_seconds, now)
52 .map_err(|e| JsValue::from_str(&format!("Failed to create policy: {}", e)))?;
53
54 Ok(WasmPolicy { inner: policy })
55 }
56
57 #[wasm_bindgen(js_name = addRule)]
59 pub fn add_rule(&mut self, peer_id: &str, action: &str, resource: &str) -> Result<(), JsValue> {
60 let action = match action {
61 "read" => Action::Read,
62 "write" => Action::Write,
63 "execute" => Action::Execute,
64 "all" => Action::All,
65 _ => return Err(JsValue::from_str(&format!("Invalid action: {}", action))),
66 };
67
68 let resource = if resource == "*" {
69 Resource::All
70 } else {
71 Resource::File(resource.to_string())
73 };
74
75 let rule = PolicyRule::new(peer_id.to_string(), action, resource);
76
77 let current_name = self.inner.name().to_string();
80 let current_issued_at = self.inner.issued_at();
81 let current_valid_until = self.inner.valid_until();
82 let ttl = current_valid_until.saturating_sub(current_issued_at);
83
84 let mut all_rules = self.inner.rules().to_vec();
86 all_rules.push(rule);
87
88 let mut new_policy = Policy::new(current_name, ttl, current_issued_at)
90 .map_err(|e| JsValue::from_str(&format!("Failed to create policy: {}", e)))?;
91
92 for r in all_rules {
94 new_policy = new_policy
95 .add_rule(r)
96 .map_err(|e| JsValue::from_str(&format!("Failed to add rule: {}", e)))?;
97 }
98
99 for (k, v) in self.inner.metadata() {
101 new_policy = new_policy.with_metadata(k.clone(), v.clone());
102 }
103
104 self.inner = new_policy;
105
106 Ok(())
107 }
108
109 #[wasm_bindgen(getter)]
111 pub fn name(&self) -> String {
112 self.inner.name().to_string()
113 }
114
115 #[wasm_bindgen(js_name = ruleCount)]
117 pub fn rule_count(&self) -> usize {
118 self.inner.rules().len()
119 }
120
121 #[wasm_bindgen(js_name = getRootHash)]
126 pub fn get_root_hash(&self) -> Result<String, JsValue> {
127 let toml = self
128 .inner
129 .to_toml()
130 .map_err(|e| JsValue::from_str(&format!("Failed to serialize policy: {}", e)))?;
131
132 let digest = core_identity::hash::hash(toml.as_bytes());
133 Ok(hex::encode(digest))
134 }
135}
136
137impl WasmPolicy {
138 pub fn get_inner(&self) -> &Policy {
140 &self.inner
141 }
142}