1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7pub struct SecurityRequirement {
8 #[serde(flatten)]
10 pub schemes: std::collections::BTreeMap<String, Vec<String>>,
11}
12
13impl SecurityRequirement {
14 pub fn new() -> Self {
16 Self::default()
17 }
18
19 pub fn scheme(mut self, name: impl Into<String>, scopes: Vec<&str>) -> Self {
21 self.schemes.insert(name.into(), scopes.into_iter().map(String::from).collect());
22 self
23 }
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
28#[serde(rename_all = "lowercase")]
29pub enum SecuritySchemeType {
30 ApiKey,
32 Http,
34 OAuth2,
36 OpenIdConnect,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
42#[serde(rename_all = "lowercase")]
43pub enum ApiKeyLocation {
44 Query,
46 Header,
48 Cookie,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct SecurityScheme {
55 #[serde(rename = "type")]
57 pub scheme_type: SecuritySchemeType,
58 #[serde(skip_serializing_if = "Option::is_none")]
60 pub description: Option<String>,
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub name: Option<String>,
64 #[serde(rename = "in")]
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub location: Option<ApiKeyLocation>,
68 #[serde(skip_serializing_if = "Option::is_none")]
70 pub scheme: Option<String>,
71 #[serde(skip_serializing_if = "Option::is_none")]
73 pub bearer_format: Option<String>,
74 #[serde(skip_serializing_if = "Option::is_none")]
76 pub flows: Option<OAuthFlows>,
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub open_id_connect_url: Option<String>,
80}
81
82impl SecurityScheme {
83 pub fn api_key(name: impl Into<String>, location: ApiKeyLocation) -> Self {
85 Self {
86 scheme_type: SecuritySchemeType::ApiKey,
87 description: None,
88 name: Some(name.into()),
89 location: Some(location),
90 scheme: None,
91 bearer_format: None,
92 flows: None,
93 open_id_connect_url: None,
94 }
95 }
96
97 pub fn basic() -> Self {
99 Self {
100 scheme_type: SecuritySchemeType::Http,
101 description: None,
102 name: None,
103 location: None,
104 scheme: Some("basic".to_string()),
105 bearer_format: None,
106 flows: None,
107 open_id_connect_url: None,
108 }
109 }
110
111 pub fn bearer(format: Option<String>) -> Self {
113 Self {
114 scheme_type: SecuritySchemeType::Http,
115 description: None,
116 name: None,
117 location: None,
118 scheme: Some("bearer".to_string()),
119 bearer_format: format,
120 flows: None,
121 open_id_connect_url: None,
122 }
123 }
124
125 pub fn oauth2(flows: OAuthFlows) -> Self {
127 Self {
128 scheme_type: SecuritySchemeType::OAuth2,
129 description: None,
130 name: None,
131 location: None,
132 scheme: None,
133 bearer_format: None,
134 flows: Some(flows),
135 open_id_connect_url: None,
136 }
137 }
138
139 pub fn open_id_connect(url: impl Into<String>) -> Self {
141 Self {
142 scheme_type: SecuritySchemeType::OpenIdConnect,
143 description: None,
144 name: None,
145 location: None,
146 scheme: None,
147 bearer_format: None,
148 flows: None,
149 open_id_connect_url: Some(url.into()),
150 }
151 }
152
153 pub fn description(mut self, desc: impl Into<String>) -> Self {
155 self.description = Some(desc.into());
156 self
157 }
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct OAuthFlows {
163 #[serde(skip_serializing_if = "Option::is_none")]
165 pub implicit: Option<OAuthFlow>,
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub password: Option<OAuthFlow>,
169 #[serde(skip_serializing_if = "Option::is_none")]
171 pub client_credentials: Option<OAuthFlow>,
172 #[serde(skip_serializing_if = "Option::is_none")]
174 pub authorization_code: Option<OAuthFlow>,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct OAuthFlow {
180 #[serde(skip_serializing_if = "Option::is_none")]
182 pub authorization_url: Option<String>,
183 #[serde(skip_serializing_if = "Option::is_none")]
185 pub token_url: Option<String>,
186 #[serde(skip_serializing_if = "Option::is_none")]
188 pub refresh_url: Option<String>,
189 pub scopes: std::collections::BTreeMap<String, String>,
191}
192
193impl OAuthFlow {
194 pub fn new() -> Self {
196 Self { authorization_url: None, token_url: None, refresh_url: None, scopes: std::collections::BTreeMap::new() }
197 }
198
199 pub fn authorization_url(mut self, url: impl Into<String>) -> Self {
201 self.authorization_url = Some(url.into());
202 self
203 }
204
205 pub fn token_url(mut self, url: impl Into<String>) -> Self {
207 self.token_url = Some(url.into());
208 self
209 }
210
211 pub fn refresh_url(mut self, url: impl Into<String>) -> Self {
213 self.refresh_url = Some(url.into());
214 self
215 }
216
217 pub fn scope(mut self, name: impl Into<String>, description: impl Into<String>) -> Self {
219 self.scopes.insert(name.into(), description.into());
220 self
221 }
222}
223
224impl Default for OAuthFlow {
225 fn default() -> Self {
226 Self::new()
227 }
228}