headless_lms_server/domain/oauth/
introspect_query.rs1use super::helpers::{oauth_invalid_client, oauth_invalid_request};
2use super::oauth_validate::OAuthValidate;
3use crate::prelude::*;
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(oauth_invalid_client("client_id is required"));
44 }
45
46 let token = self
47 .token
48 .as_ref()
49 .map(|t| t.expose_secret())
50 .unwrap_or_default();
51 if token.is_empty() {
52 return Err(oauth_invalid_request("token is required", None, None));
53 }
54
55 let token_type_hint = self.token_type_hint.as_deref().and_then(|h| {
59 match h {
60 "access_token" | "refresh_token" => Some(h.to_string()),
61 _ => None, }
63 });
64
65 Ok(IntrospectParams {
66 client_id: client_id.to_string(),
67 client_secret: self.client_secret.clone(),
68 token: SecretString::new(token.into()),
70 token_type_hint,
71 })
72 }
73}