-
Notifications
You must be signed in to change notification settings - Fork 1
/
passkey.rs
78 lines (66 loc) · 2.24 KB
/
passkey.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
use crux_core::capability::{CapabilityContext, Operation};
use crux_macros::Capability;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Error {
message: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum PasskeyOperation {
CreateCredential(Vec<u8>),
RequestCredential(Vec<u8>),
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum PasskeyOutput {
RegisterCredential(Vec<u8>),
Credential(Vec<u8>),
Error(String),
}
impl Operation for PasskeyOperation {
type Output = PasskeyOutput;
}
#[derive(Capability)]
pub struct Passkey<Ev> {
context: CapabilityContext<PasskeyOperation, Ev>,
}
impl<Ev> Passkey<Ev>
where
Ev: 'static,
{
pub fn new(context: CapabilityContext<PasskeyOperation, Ev>) -> Self {
Self { context }
}
pub fn create_credential<F, T>(&self, challenge: Vec<u8>, make_event: F)
where
F: FnOnce(Result<T>) -> Ev + Clone + Send + 'static,
T: DeserializeOwned,
{
self.perform_operation(PasskeyOperation::CreateCredential(challenge), make_event);
}
pub fn request_credential<F, T>(&self, challenge: Vec<u8>, make_event: F)
where
F: FnOnce(Result<T>) -> Ev + Clone + Send + 'static,
T: DeserializeOwned,
{
self.perform_operation(PasskeyOperation::RequestCredential(challenge), make_event);
}
fn perform_operation<F, T>(&self, op: PasskeyOperation, make_event: F)
where
F: FnOnce(Result<T>) -> Ev + Clone + Send + 'static,
T: DeserializeOwned,
{
let ctx = self.context.clone();
self.context.spawn(async move {
let output = ctx.request_from_shell(op).await;
let event = match output {
PasskeyOutput::RegisterCredential(cred) | PasskeyOutput::Credential(cred) => {
let cred = serde_json::from_slice(&cred).expect("Failed to deserialize cred");
make_event(Ok(cred))
}
PasskeyOutput::Error(e) => make_event(Err(Error { message: e })),
};
ctx.update_app(event);
});
}
}