subgraph/graphql/schema/create_auth_service/finish_register/
mod.rs1use async_graphql::{
2 dynamic::{Field, FieldFuture, InputValue, TypeRef},
3 Value,
4};
5use log::error;
6use webauthn_rs::prelude::RegisterPublicKeyCredential;
7
8use crate::{data_sources::DataSources, graphql::schema::ServiceSchema};
9
10use super::ServiceUser;
11
12impl ServiceSchema {
13 pub fn create_register_finish(mut self) -> Self {
14 let auth_config = match self.subgraph_config.service.auth.clone() {
15 Some(auth) => auth,
16 None => {
17 panic!("Auth config not found.");
18 }
19 };
20
21 let resolver = Field::new(
22 "register_finish",
23 TypeRef::named_nn(TypeRef::BOOLEAN),
24 move |ctx| {
25 let auth_config = auth_config.clone();
26
27 FieldFuture::new(async move {
28 let data_sources = ctx.data_unchecked::<DataSources>().clone();
29
30 let data_source = DataSources::get_data_source_by_name(
31 &data_sources,
32 &auth_config.data_source,
33 );
34
35 let identifier = match ctx.args.try_get("identifier") {
36 Ok(input) => input
37 .deserialize::<String>()
38 .expect("Failed to deserialize."),
39 Err(e) => {
40 return Err(async_graphql::Error::new(format!(
41 "Failed to get input: {:?}",
42 e
43 )));
44 }
45 };
46
47 let pub_key = match ctx.args.try_get("public_key") {
48 Ok(input) => input
49 .deserialize::<String>()
50 .expect("Failed to deserialize."),
51 Err(e) => {
52 ServiceSchema::delete_user(&data_source, &identifier).await?;
53 return Err(async_graphql::Error::new(format!(
54 "Failed to get input: {:?}",
55 e
56 )));
57 }
58 };
59
60 let user = ServiceSchema::get_user(&data_source, &identifier).await;
61
62 let user = match user {
63 Ok(user) => user,
64 Err(e) => {
65 return Err(async_graphql::Error::new(format!(
66 "Failed to get user: {:?}",
67 e
68 )))
69 }
70 };
71
72 if user.is_none() {
73 error!("User Not Found: {:?}", &identifier);
74 return Err(async_graphql::Error::new(format!(
75 "User Not Found: {:?}",
76 &identifier
77 )));
78 }
79
80 let webauthn = match ServiceSchema::build_webauthn(&auth_config) {
81 Ok(w) => Ok(w),
82 Err(e) => {
83 ServiceSchema::delete_user(&data_source, &identifier).await?;
84 Err(async_graphql::Error::new(format!(
85 "something went wrong when building webauthn: {:?}",
86 e
87 )))
88 }
89 }?;
90
91 let pub_key: Result<RegisterPublicKeyCredential, async_graphql::Error> =
92 serde_json::from_str(&pub_key).map_err(|e| {
93 async_graphql::Error::new(format!("Failed to deserialize: {:?}", e))
94 });
95
96 let pub_key = match pub_key {
97 Ok(pk) => pk,
98 Err(error) => {
99 ServiceSchema::delete_user(&data_source, &identifier).await?;
100 return Err(error);
101 }
102 };
103
104 let passkey = webauthn
105 .finish_passkey_registration(
106 &pub_key,
107 &user.clone().unwrap().registration_state,
108 )
109 .map_err(|e| {
110 async_graphql::Error::new(format!(
111 "Failed to finish registration: {:?}",
112 e
113 ))
114 });
115 let passkey = match passkey {
116 Ok(pk) => pk,
117 Err(error) => {
118 ServiceSchema::delete_user(&data_source, &identifier).await?;
119 return Err(error);
120 }
121 };
122
123 let service_user = ServiceUser {
125 identifier: identifier.clone(),
126 registration_state: user.clone().unwrap().registration_state,
127 passkey: Some(passkey),
128 authentication_state: None,
129 uuid: user.unwrap().uuid,
130 };
131
132 let updated = ServiceSchema::update_user(&data_source, service_user).await;
133 match updated {
134 Ok(_) => (),
135 Err(e) => {
136 ServiceSchema::delete_user(&data_source, &identifier).await?;
137 return Err(e);
138 }
139 };
140
141 Ok(Some(Value::from(true)))
142 })
143 },
144 )
145 .argument(InputValue::new(
146 "identifier",
147 TypeRef::named_nn(TypeRef::STRING),
148 ))
149 .argument(InputValue::new(
150 "public_key",
151 TypeRef::named_nn(TypeRef::STRING),
152 ));
153
154 self.mutation = self.mutation.field(resolver);
155 self
156 }
157}