headless_lms_server/domain/oauth/
introspect_query.rs1use super::oauth_validate::OAuthValidate;
2use crate::prelude::*;
3use domain::error::{OAuthErrorCode, OAuthErrorData};
4use secrecy::{ExposeSecret, SecretString};
5use serde::Deserialize;
6use std::collections::HashMap;
7
8#[derive(Debug, Deserialize)]
13pub struct IntrospectQuery {
14 pub client_id: Option<String>,
15 pub client_secret: Option<SecretString>,
16 pub token: Option<SecretString>,
18
19 pub token_type_hint: Option<String>,
23 #[serde(flatten)]
25 pub _extra: HashMap<String, String>,
26}
27
28#[derive(Debug)]
29pub struct IntrospectParams {
30 pub client_id: String,
31 pub client_secret: Option<SecretString>,
32 pub token: SecretString,
33 pub token_type_hint: Option<String>,
34}
35
36impl OAuthValidate for IntrospectQuery {
37 type Output = IntrospectParams;
38
39 fn validate(&self) -> Result<Self::Output, ControllerError> {
40 let client_id = self.client_id.as_deref().unwrap_or_default();
41
42 if client_id.is_empty() {
43 return Err(ControllerError::new(
44 ControllerErrorType::OAuthError(Box::new(OAuthErrorData {
45 error: OAuthErrorCode::InvalidClient.as_str().into(),
46 error_description: "client_id is required".into(),
47 redirect_uri: None,
48 state: None,
49 nonce: None,
50 })),
51 "Missing client_id",
52 None::<anyhow::Error>,
53 ));
54 }
55
56 let token = self
57 .token
58 .as_ref()
59 .map(|t| t.expose_secret())
60 .unwrap_or_default();
61 if token.is_empty() {
62 return Err(ControllerError::new(
63 ControllerErrorType::OAuthError(Box::new(OAuthErrorData {
64 error: OAuthErrorCode::InvalidRequest.as_str().into(),
65 error_description: "token is required".into(),
66 redirect_uri: None,
67 state: None,
68 nonce: None,
69 })),
70 "Missing token",
71 None::<anyhow::Error>,
72 ));
73 }
74
75 let token_type_hint = self.token_type_hint.as_deref().and_then(|h| {
79 match h {
80 "access_token" | "refresh_token" => Some(h.to_string()),
81 _ => None, }
83 });
84
85 Ok(IntrospectParams {
86 client_id: client_id.to_string(),
87 client_secret: self.client_secret.clone(),
88 token: SecretString::new(token.into()),
90 token_type_hint,
91 })
92 }
93}