1use anyhow::Result;
2use iroh::{EndpointId, SecretKey};
3use iroh_services_proto::caps::{
4 Caps as ProtoCaps, NetDiagnosticsCap as ProtoNetDiagnosticsCap, RelayCap as ProtoRelayCap,
5};
6use n0_future::time::Duration;
7use rcan::{Expires, Rcan};
8
9use crate::ApiToken;
10
11#[derive(Debug, Eq, PartialEq, Clone)]
16pub struct Caps(pub(crate) ProtoCaps);
17
18impl Caps {
19 pub fn client() -> Self {
21 Self(ProtoCaps::for_shared_secret())
22 }
23
24 pub fn relay_use() -> Self {
26 Self(ProtoCaps::new([ProtoRelayCap::Use]))
27 }
28
29 pub fn net_diagnostics_get_any() -> Self {
31 Self(ProtoCaps::new([ProtoNetDiagnosticsCap::GetAny]))
32 }
33}
34
35pub(crate) const DEFAULT_CAP_EXPIRY: Duration = Duration::from_hours(24 * 30); #[cfg(not(wasm_browser))]
40pub fn create_api_token_from_openssh_pem(
41 pem: &str,
42 local_id: EndpointId,
43 max_age: Duration,
44 capability: Caps,
45) -> Result<ApiToken> {
46 let seed = crate::openssh::parse_ed25519_private_key(pem)?;
47 let issuer = ed25519_dalek::SigningKey::from_bytes(&seed);
48 let audience = local_id.as_verifying_key();
49 let can =
50 Rcan::issuing_builder(&issuer, audience, capability.0).sign(Expires::valid_for(max_age));
51 Ok(ApiToken::new(can))
52}
53
54pub fn create_grant_token(
58 local_secret: SecretKey,
59 remote_id: EndpointId,
60 max_age: Duration,
61 capability: Caps,
62) -> Result<ApiToken> {
63 let issuer = ed25519_dalek::SigningKey::from_bytes(&local_secret.to_bytes());
64 let audience = remote_id.as_verifying_key();
65 let can =
66 Rcan::issuing_builder(&issuer, audience, capability.0).sign(Expires::valid_for(max_age));
67 Ok(ApiToken::new(can))
68}
69
70pub fn create_api_token_from_secret_key(
72 private_key: SecretKey,
73 local_id: EndpointId,
74 max_age: Duration,
75 capability: Caps,
76) -> Result<ApiToken> {
77 let issuer = ed25519_dalek::SigningKey::from_bytes(&private_key.to_bytes());
78 let audience = local_id.as_verifying_key();
79 let can =
80 Rcan::issuing_builder(&issuer, audience, capability.0).sign(Expires::valid_for(max_age));
81 Ok(ApiToken::new(can))
82}