1use std::net::IpAddr;
13
14use mas_data_model::{Client, User};
15use oauth2_types::{registration::VerifiedClientMetadata, scope::Scope};
16use schemars::JsonSchema;
17use serde::{Deserialize, Serialize};
18
19#[derive(Deserialize, Debug, Clone, Copy, JsonSchema)]
21#[serde(rename_all = "kebab-case")]
22pub enum Code {
23 UsernameTooShort,
25
26 UsernameTooLong,
28
29 UsernameInvalidChars,
31
32 UsernameAllNumeric,
34
35 UsernameBanned,
37
38 UsernameNotAllowed,
40
41 EmailDomainNotAllowed,
43
44 EmailDomainBanned,
46
47 EmailNotAllowed,
49
50 EmailBanned,
52}
53
54impl Code {
55 #[must_use]
57 pub fn as_str(&self) -> &'static str {
58 match self {
59 Self::UsernameTooShort => "username-too-short",
60 Self::UsernameTooLong => "username-too-long",
61 Self::UsernameInvalidChars => "username-invalid-chars",
62 Self::UsernameAllNumeric => "username-all-numeric",
63 Self::UsernameBanned => "username-banned",
64 Self::UsernameNotAllowed => "username-not-allowed",
65 Self::EmailDomainNotAllowed => "email-domain-not-allowed",
66 Self::EmailDomainBanned => "email-domain-banned",
67 Self::EmailNotAllowed => "email-not-allowed",
68 Self::EmailBanned => "email-banned",
69 }
70 }
71}
72
73#[derive(Deserialize, Debug, JsonSchema)]
75pub struct Violation {
76 pub msg: String,
77 pub redirect_uri: Option<String>,
78 pub field: Option<String>,
79 pub code: Option<Code>,
80}
81
82#[derive(Deserialize, Debug)]
84pub struct EvaluationResult {
85 #[serde(rename = "result")]
86 pub violations: Vec<Violation>,
87}
88
89impl std::fmt::Display for EvaluationResult {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 let mut first = true;
92 for violation in &self.violations {
93 if first {
94 first = false;
95 } else {
96 write!(f, ", ")?;
97 }
98 write!(f, "{}", violation.msg)?;
99 }
100 Ok(())
101 }
102}
103
104impl EvaluationResult {
105 #[must_use]
107 pub fn valid(&self) -> bool {
108 self.violations.is_empty()
109 }
110}
111
112#[derive(Serialize, Debug, Default, JsonSchema)]
114#[serde(rename_all = "snake_case")]
115pub struct Requester {
116 pub ip_address: Option<IpAddr>,
118
119 pub user_agent: Option<String>,
121}
122
123#[derive(Serialize, Debug, JsonSchema)]
124pub enum RegistrationMethod {
125 #[serde(rename = "password")]
126 Password,
127
128 #[serde(rename = "upstream-oauth2")]
129 UpstreamOAuth2,
130}
131
132#[derive(Serialize, Debug, JsonSchema)]
134#[serde(tag = "registration_method")]
135pub struct RegisterInput<'a> {
136 pub registration_method: RegistrationMethod,
137
138 pub username: &'a str,
139
140 #[serde(skip_serializing_if = "Option::is_none")]
141 pub email: Option<&'a str>,
142
143 pub requester: Requester,
144}
145
146#[derive(Serialize, Debug, JsonSchema)]
148#[serde(rename_all = "snake_case")]
149pub struct ClientRegistrationInput<'a> {
150 #[schemars(with = "std::collections::HashMap<String, serde_json::Value>")]
151 pub client_metadata: &'a VerifiedClientMetadata,
152 pub requester: Requester,
153}
154
155#[derive(Serialize, Debug, JsonSchema)]
156#[serde(rename_all = "snake_case")]
157pub enum GrantType {
158 AuthorizationCode,
159 ClientCredentials,
160 #[serde(rename = "urn:ietf:params:oauth:grant-type:device_code")]
161 DeviceCode,
162}
163
164#[derive(Serialize, Debug, JsonSchema)]
166#[serde(rename_all = "snake_case")]
167pub struct AuthorizationGrantInput<'a> {
168 #[schemars(with = "Option<std::collections::HashMap<String, serde_json::Value>>")]
169 pub user: Option<&'a User>,
170
171 #[schemars(with = "std::collections::HashMap<String, serde_json::Value>")]
172 pub client: &'a Client,
173
174 #[schemars(with = "String")]
175 pub scope: &'a Scope,
176
177 pub grant_type: GrantType,
178
179 pub requester: Requester,
180}
181
182#[derive(Serialize, Debug, JsonSchema)]
184#[serde(rename_all = "snake_case")]
185pub struct EmailInput<'a> {
186 pub email: &'a str,
187
188 pub requester: Requester,
189}