1use crate::common::OpType;
2use crate::Oauth2ClaimMapJoin;
3use crate::{handle_client_error, Oauth2Opt, OutputMode};
4use anyhow::{Context, Error};
5use kanidm_proto::internal::{ImageValue, Oauth2ClaimMapJoin as ProtoOauth2ClaimMapJoin};
6use std::fs::read;
7use std::process::exit;
8
9impl Oauth2Opt {
10 pub fn debug(&self) -> bool {
11 match self {
12 Oauth2Opt::List(copt) => copt.debug,
13 Oauth2Opt::Get(nopt) => nopt.copt.debug,
14 Oauth2Opt::UpdateScopeMap(cbopt) => cbopt.nopt.copt.debug,
15 Oauth2Opt::DeleteScopeMap(cbopt) => cbopt.nopt.copt.debug,
16 Oauth2Opt::UpdateSupScopeMap(cbopt) => cbopt.nopt.copt.debug,
17 Oauth2Opt::DeleteSupScopeMap(cbopt) => cbopt.nopt.copt.debug,
18 Oauth2Opt::ResetSecrets(cbopt) => cbopt.copt.debug,
19 Oauth2Opt::ShowBasicSecret(nopt) => nopt.copt.debug,
21 Oauth2Opt::Delete(nopt) => nopt.copt.debug,
22 Oauth2Opt::SetDisplayname(cbopt) => cbopt.nopt.copt.debug,
23 Oauth2Opt::SetName { nopt, .. } => nopt.copt.debug,
24 Oauth2Opt::SetLandingUrl { nopt, .. } => nopt.copt.debug,
25 Oauth2Opt::SetImage { nopt, .. } => nopt.copt.debug,
26 Oauth2Opt::RemoveImage(nopt) => nopt.copt.debug,
27 Oauth2Opt::EnablePkce(nopt) => nopt.copt.debug,
28 Oauth2Opt::DisablePkce(nopt) => nopt.copt.debug,
29 Oauth2Opt::EnableLegacyCrypto(nopt) => nopt.copt.debug,
30 Oauth2Opt::DisableLegacyCrypto(nopt) => nopt.copt.debug,
31 Oauth2Opt::PreferShortUsername(nopt) => nopt.copt.debug,
32 Oauth2Opt::PreferSPNUsername(nopt) => nopt.copt.debug,
33
34 #[cfg(feature = "dev-oauth2-device-flow")]
35 Oauth2Opt::DeviceFlowDisable(nopt) => nopt.copt.debug,
36
37 #[cfg(feature = "dev-oauth2-device-flow")]
38 Oauth2Opt::DeviceFlowEnable(nopt) => nopt.copt.debug,
39 Oauth2Opt::CreateBasic { copt, .. }
40 | Oauth2Opt::CreatePublic { copt, .. }
41 | Oauth2Opt::UpdateClaimMap { copt, .. }
42 | Oauth2Opt::UpdateClaimMapJoin { copt, .. }
43 | Oauth2Opt::DeleteClaimMap { copt, .. }
44 | Oauth2Opt::EnablePublicLocalhost { copt, .. }
45 | Oauth2Opt::DisablePublicLocalhost { copt, .. }
46 | Oauth2Opt::EnableStrictRedirectUri { copt, .. }
47 | Oauth2Opt::DisableStrictRedirectUri { copt, .. }
48 | Oauth2Opt::AddOrigin { copt, .. }
49 | Oauth2Opt::RemoveOrigin { copt, .. }
50 | Oauth2Opt::RotateCryptographicKeys { copt, .. }
51 | Oauth2Opt::RevokeCryptographicKey { copt, .. } => copt.debug,
52 }
53 }
54
55 pub async fn exec(&self) {
56 match self {
57 #[cfg(feature = "dev-oauth2-device-flow")]
58 Oauth2Opt::DeviceFlowDisable(nopt) => {
59 let client = nopt.copt.to_client(OpType::Write).await;
61 match client
62 .idm_oauth2_client_device_flow_update(&nopt.name, true)
63 .await
64 {
65 Ok(_) => println!("Success"),
66 Err(e) => handle_client_error(e, nopt.copt.output_mode),
67 }
68 }
69 #[cfg(feature = "dev-oauth2-device-flow")]
70 Oauth2Opt::DeviceFlowEnable(nopt) => {
71 let client = nopt.copt.to_client(OpType::Write).await;
73 match client
74 .idm_oauth2_client_device_flow_update(&nopt.name, true)
75 .await
76 {
77 Ok(_) => println!("Success"),
78 Err(e) => handle_client_error(e, nopt.copt.output_mode),
79 }
80 }
81 Oauth2Opt::List(copt) => {
82 let client = copt.to_client(OpType::Read).await;
83 match client.idm_oauth2_rs_list().await {
84 Ok(r) => match copt.output_mode {
85 OutputMode::Json => {
86 let r_attrs: Vec<_> = r.iter().map(|entry| &entry.attrs).collect();
87 println!(
88 "{}",
89 serde_json::to_string(&r_attrs).expect("Failed to serialise json")
90 );
91 }
92 OutputMode::Text => r.iter().for_each(|ent| println!("{}", ent)),
93 },
94 Err(e) => handle_client_error(e, copt.output_mode),
95 }
96 }
97 Oauth2Opt::Get(nopt) => {
98 let client = nopt.copt.to_client(OpType::Read).await;
99 match client.idm_oauth2_rs_get(nopt.name.as_str()).await {
100 Ok(Some(e)) => println!("{}", e),
101 Ok(None) => println!("No matching entries"),
102 Err(e) => handle_client_error(e, nopt.copt.output_mode),
103 }
104 }
105 Oauth2Opt::CreateBasic {
106 name,
107 displayname,
108 origin,
109 copt,
110 } => {
111 let client = copt.to_client(OpType::Write).await;
112 match client
113 .idm_oauth2_rs_basic_create(
114 name.as_str(),
115 displayname.as_str(),
116 origin.as_str(),
117 )
118 .await
119 {
120 Ok(_) => println!("Success"),
121 Err(e) => handle_client_error(e, copt.output_mode),
122 }
123 }
124 Oauth2Opt::CreatePublic {
125 name,
126 displayname,
127 origin,
128 copt,
129 } => {
130 let client = copt.to_client(OpType::Write).await;
131 match client
132 .idm_oauth2_rs_public_create(
133 name.as_str(),
134 displayname.as_str(),
135 origin.as_str(),
136 )
137 .await
138 {
139 Ok(_) => println!("Success"),
140 Err(e) => handle_client_error(e, copt.output_mode),
141 }
142 }
143 Oauth2Opt::UpdateScopeMap(cbopt) => {
144 let client = cbopt.nopt.copt.to_client(OpType::Write).await;
145 match client
146 .idm_oauth2_rs_update_scope_map(
147 cbopt.nopt.name.as_str(),
148 cbopt.group.as_str(),
149 cbopt.scopes.iter().map(|s| s.as_str()).collect(),
150 )
151 .await
152 {
153 Ok(_) => println!("Success"),
154 Err(e) => handle_client_error(e, cbopt.nopt.copt.output_mode),
155 }
156 }
157 Oauth2Opt::DeleteScopeMap(cbopt) => {
158 let client = cbopt.nopt.copt.to_client(OpType::Write).await;
159 match client
160 .idm_oauth2_rs_delete_scope_map(cbopt.nopt.name.as_str(), cbopt.group.as_str())
161 .await
162 {
163 Ok(_) => println!("Success"),
164 Err(e) => handle_client_error(e, cbopt.nopt.copt.output_mode),
165 }
166 }
167 Oauth2Opt::UpdateSupScopeMap(cbopt) => {
168 let client = cbopt.nopt.copt.to_client(OpType::Write).await;
169 match client
170 .idm_oauth2_rs_update_sup_scope_map(
171 cbopt.nopt.name.as_str(),
172 cbopt.group.as_str(),
173 cbopt.scopes.iter().map(|s| s.as_str()).collect(),
174 )
175 .await
176 {
177 Ok(_) => println!("Success"),
178 Err(e) => {
179 error!("Error -> {:?}", e);
180 exit(1)
181 }
182 }
183 }
184 Oauth2Opt::DeleteSupScopeMap(cbopt) => {
185 let client = cbopt.nopt.copt.to_client(OpType::Write).await;
186 match client
187 .idm_oauth2_rs_delete_sup_scope_map(
188 cbopt.nopt.name.as_str(),
189 cbopt.group.as_str(),
190 )
191 .await
192 {
193 Ok(_) => println!("Success"),
194 Err(e) => handle_client_error(e, cbopt.nopt.copt.output_mode),
195 }
196 }
197 Oauth2Opt::ResetSecrets(cbopt) => {
198 let client = cbopt.copt.to_client(OpType::Write).await;
199 match client
200 .idm_oauth2_rs_update(cbopt.name.as_str(), None, None, None, true)
201 .await
202 {
203 Ok(_) => println!("Success"),
204 Err(e) => handle_client_error(e, cbopt.copt.output_mode),
205 }
206 }
207 Oauth2Opt::ShowBasicSecret(nopt) => {
208 let client = nopt.copt.to_client(OpType::Read).await;
209 match client
210 .idm_oauth2_rs_get_basic_secret(nopt.name.as_str())
211 .await
212 {
213 Ok(Some(secret)) => {
214 match nopt.copt.output_mode {
215 OutputMode::Text => println!("{}", secret),
216 OutputMode::Json => println!("{{\"secret\": \"{}\"}}", secret),
217 }
218 eprintln!("Success");
219 }
220 Ok(None) => {
221 eprintln!("No secret configured");
222 }
223 Err(e) => handle_client_error(e, nopt.copt.output_mode),
224 }
225 }
226 Oauth2Opt::Delete(nopt) => {
227 let client = nopt.copt.to_client(OpType::Write).await;
228 match client.idm_oauth2_rs_delete(nopt.name.as_str()).await {
229 Ok(_) => println!("Success"),
230 Err(e) => handle_client_error(e, nopt.copt.output_mode),
231 }
232 }
233 Oauth2Opt::SetDisplayname(cbopt) => {
234 let client = cbopt.nopt.copt.to_client(OpType::Write).await;
235 match client
236 .idm_oauth2_rs_update(
237 cbopt.nopt.name.as_str(),
238 None,
239 Some(cbopt.displayname.as_str()),
240 None,
241 false,
242 )
243 .await
244 {
245 Ok(_) => println!("Success"),
246 Err(e) => handle_client_error(e, cbopt.nopt.copt.output_mode),
247 }
248 }
249 Oauth2Opt::SetName { nopt, name } => {
250 let client = nopt.copt.to_client(OpType::Write).await;
251 match client
252 .idm_oauth2_rs_update(
253 nopt.name.as_str(),
254 Some(name.as_str()),
255 None,
256 None,
257 false,
258 )
259 .await
260 {
261 Ok(_) => println!("Success"),
262 Err(e) => handle_client_error(e, nopt.copt.output_mode),
263 }
264 }
265 Oauth2Opt::SetLandingUrl { nopt, url } => {
266 let client = nopt.copt.to_client(OpType::Write).await;
267 match client
268 .idm_oauth2_rs_update(nopt.name.as_str(), None, None, Some(url.as_str()), false)
269 .await
270 {
271 Ok(_) => println!("Success"),
272 Err(e) => handle_client_error(e, nopt.copt.output_mode),
273 }
274 }
275 Oauth2Opt::SetImage {
276 nopt,
277 path,
278 image_type,
279 } => {
280 let img_res: Result<ImageValue, Error> = (move || {
281 let file_name = path
282 .file_name()
283 .context("Please pass a file")?
284 .to_str()
285 .context("Path contains non utf-8")?
286 .to_string();
287
288 let image_type = match image_type {
289 Some(val) => val.clone(),
290 None => {
291 path
292 .extension().context("Path has no extension so we can't infer the imageType, or you could pass the optional imageType argument yourself.")?
293 .to_str().context("Path contains invalid utf-8")?
294 .try_into()
295 .map_err(Error::msg)?
296 }
297 };
298
299 let read_res = read(path);
300 match read_res {
301 Ok(data) => Ok(ImageValue::new(file_name, image_type, data)),
302 Err(err) => {
303 if nopt.copt.debug {
304 eprintln!(
305 "{}",
306 kanidm_lib_file_permissions::diagnose_path(path.as_ref())
307 );
308 }
309 Err(err).context(format!("Failed to read file at '{}'", path.display()))
310 }
311 }
312 })();
313
314 let img = match img_res {
315 Ok(img) => img,
316 Err(err) => {
317 eprintln!("{:?}", err);
318 return;
319 }
320 };
321
322 let client = nopt.copt.to_client(OpType::Write).await;
323
324 match client
325 .idm_oauth2_rs_update_image(nopt.name.as_str(), img)
326 .await
327 {
328 Ok(_) => println!("Success"),
329 Err(e) => handle_client_error(e, nopt.copt.output_mode),
330 }
331 }
332 Oauth2Opt::RemoveImage(nopt) => {
333 let client = nopt.copt.to_client(OpType::Write).await;
334
335 match client.idm_oauth2_rs_delete_image(nopt.name.as_str()).await {
336 Ok(_) => println!("Success"),
337 Err(e) => handle_client_error(e, nopt.copt.output_mode),
338 }
339 }
340 Oauth2Opt::EnablePkce(nopt) => {
341 let client = nopt.copt.to_client(OpType::Write).await;
342 match client.idm_oauth2_rs_enable_pkce(nopt.name.as_str()).await {
343 Ok(_) => println!("Success"),
344 Err(e) => handle_client_error(e, nopt.copt.output_mode),
345 }
346 }
347 Oauth2Opt::DisablePkce(nopt) => {
348 let client = nopt.copt.to_client(OpType::Write).await;
349 match client.idm_oauth2_rs_disable_pkce(nopt.name.as_str()).await {
350 Ok(_) => println!("Success"),
351 Err(e) => handle_client_error(e, nopt.copt.output_mode),
352 }
353 }
354 Oauth2Opt::EnableLegacyCrypto(nopt) => {
355 let client = nopt.copt.to_client(OpType::Write).await;
356 match client
357 .idm_oauth2_rs_enable_legacy_crypto(nopt.name.as_str())
358 .await
359 {
360 Ok(_) => println!("Success"),
361 Err(e) => handle_client_error(e, nopt.copt.output_mode),
362 }
363 }
364 Oauth2Opt::DisableLegacyCrypto(nopt) => {
365 let client = nopt.copt.to_client(OpType::Write).await;
366 match client
367 .idm_oauth2_rs_disable_legacy_crypto(nopt.name.as_str())
368 .await
369 {
370 Ok(_) => println!("Success"),
371 Err(e) => handle_client_error(e, nopt.copt.output_mode),
372 }
373 }
374 Oauth2Opt::PreferShortUsername(nopt) => {
375 let client = nopt.copt.to_client(OpType::Write).await;
376 match client
377 .idm_oauth2_rs_prefer_short_username(nopt.name.as_str())
378 .await
379 {
380 Ok(_) => println!("Success"),
381 Err(e) => handle_client_error(e, nopt.copt.output_mode),
382 }
383 }
384 Oauth2Opt::PreferSPNUsername(nopt) => {
385 let client = nopt.copt.to_client(OpType::Write).await;
386 match client
387 .idm_oauth2_rs_prefer_spn_username(nopt.name.as_str())
388 .await
389 {
390 Ok(_) => println!("Success"),
391 Err(e) => handle_client_error(e, nopt.copt.output_mode),
392 }
393 }
394
395 Oauth2Opt::AddOrigin { name, origin, copt } => {
396 let client = copt.to_client(OpType::Write).await;
397 match client.idm_oauth2_client_add_origin(name, origin).await {
398 Ok(_) => println!("Success"),
399 Err(e) => handle_client_error(e, copt.output_mode),
400 }
401 }
402 Oauth2Opt::RemoveOrigin { name, origin, copt } => {
403 let client = copt.to_client(OpType::Write).await;
404 match client.idm_oauth2_client_remove_origin(name, origin).await {
405 Ok(_) => println!("Success"),
406 Err(e) => handle_client_error(e, copt.output_mode),
407 }
408 }
409 Oauth2Opt::UpdateClaimMap {
410 copt,
411 name,
412 group,
413 claim_name,
414 values,
415 } => {
416 let client = copt.to_client(OpType::Write).await;
417 match client
418 .idm_oauth2_rs_update_claim_map(
419 name.as_str(),
420 claim_name.as_str(),
421 group.as_str(),
422 values,
423 )
424 .await
425 {
426 Ok(_) => println!("Success"),
427 Err(e) => handle_client_error(e, copt.output_mode),
428 }
429 }
430 Oauth2Opt::UpdateClaimMapJoin {
431 copt,
432 name,
433 claim_name,
434 join,
435 } => {
436 let client = copt.to_client(OpType::Write).await;
437
438 let join = match join {
439 Oauth2ClaimMapJoin::Csv => ProtoOauth2ClaimMapJoin::Csv,
440 Oauth2ClaimMapJoin::Ssv => ProtoOauth2ClaimMapJoin::Ssv,
441 Oauth2ClaimMapJoin::Array => ProtoOauth2ClaimMapJoin::Array,
442 };
443
444 match client
445 .idm_oauth2_rs_update_claim_map_join(name.as_str(), claim_name.as_str(), join)
446 .await
447 {
448 Ok(_) => println!("Success"),
449 Err(e) => handle_client_error(e, copt.output_mode),
450 }
451 }
452 Oauth2Opt::DeleteClaimMap {
453 copt,
454 name,
455 claim_name,
456 group,
457 } => {
458 let client = copt.to_client(OpType::Write).await;
459 match client
460 .idm_oauth2_rs_delete_claim_map(
461 name.as_str(),
462 claim_name.as_str(),
463 group.as_str(),
464 )
465 .await
466 {
467 Ok(_) => println!("Success"),
468 Err(e) => handle_client_error(e, copt.output_mode),
469 }
470 }
471
472 Oauth2Opt::EnablePublicLocalhost { copt, name } => {
473 let client = copt.to_client(OpType::Write).await;
474 match client
475 .idm_oauth2_rs_enable_public_localhost_redirect(name.as_str())
476 .await
477 {
478 Ok(_) => println!("Success"),
479 Err(e) => handle_client_error(e, copt.output_mode),
480 }
481 }
482
483 Oauth2Opt::DisablePublicLocalhost { copt, name } => {
484 let client = copt.to_client(OpType::Write).await;
485 match client
486 .idm_oauth2_rs_disable_public_localhost_redirect(name.as_str())
487 .await
488 {
489 Ok(_) => println!("Success"),
490 Err(e) => handle_client_error(e, copt.output_mode),
491 }
492 }
493 Oauth2Opt::EnableStrictRedirectUri { copt, name } => {
494 let client = copt.to_client(OpType::Write).await;
495 match client
496 .idm_oauth2_rs_enable_strict_redirect_uri(name.as_str())
497 .await
498 {
499 Ok(_) => println!("Success"),
500 Err(e) => handle_client_error(e, copt.output_mode),
501 }
502 }
503
504 Oauth2Opt::DisableStrictRedirectUri { copt, name } => {
505 let client = copt.to_client(OpType::Write).await;
506 match client
507 .idm_oauth2_rs_disable_strict_redirect_uri(name.as_str())
508 .await
509 {
510 Ok(_) => println!("Success"),
511 Err(e) => handle_client_error(e, copt.output_mode),
512 }
513 }
514 Oauth2Opt::RotateCryptographicKeys {
515 copt,
516 name,
517 rotate_at,
518 } => {
519 let client = copt.to_client(OpType::Write).await;
520 match client
521 .idm_oauth2_rs_rotate_keys(name.as_str(), *rotate_at)
522 .await
523 {
524 Ok(_) => println!("Success"),
525 Err(e) => handle_client_error(e, copt.output_mode),
526 }
527 }
528 Oauth2Opt::RevokeCryptographicKey { copt, name, key_id } => {
529 let client = copt.to_client(OpType::Write).await;
530 match client
531 .idm_oauth2_rs_revoke_key(name.as_str(), key_id.as_str())
532 .await
533 {
534 Ok(_) => println!("Success"),
535 Err(e) => handle_client_error(e, copt.output_mode),
536 }
537 }
538 }
539 }
540}