1use serde::{Deserialize, Serialize};
8
9use crate::errors::ParseEnumError;
10use std::collections::HashMap;
11
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
13pub enum SecurityScheme {
14 #[serde(rename = "apiKeySecurityScheme")]
15 ApiKey(ApiKeySecurityScheme),
16 #[serde(rename = "httpAuthSecurityScheme")]
17 HttpAuth(HttpAuthSecurityScheme),
18 #[serde(rename = "oauth2SecurityScheme")]
19 OAuth2(OAuth2SecurityScheme),
20 #[serde(rename = "openIdConnectSecurityScheme")]
21 OpenIdConnect(OpenIdConnectSecurityScheme),
22 #[serde(rename = "mtlsSecurityScheme")]
23 MutualTls(MutualTlsSecurityScheme),
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
27#[serde(rename_all = "camelCase")]
28pub struct ApiKeySecurityScheme {
29 #[serde(default, skip_serializing_if = "Option::is_none")]
30 pub description: Option<String>,
31 pub location: ApiKeyLocation,
32 pub name: String,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
36#[serde(rename_all = "camelCase")]
37pub struct HttpAuthSecurityScheme {
38 #[serde(default, skip_serializing_if = "Option::is_none")]
39 pub description: Option<String>,
40 pub scheme: String,
41 #[serde(default, skip_serializing_if = "Option::is_none")]
42 pub bearer_format: Option<String>,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
46#[serde(rename_all = "camelCase")]
47pub struct OAuth2SecurityScheme {
48 #[serde(default, skip_serializing_if = "Option::is_none")]
49 pub description: Option<String>,
50 pub flows: OAuthFlows,
51 #[serde(
52 default,
53 rename = "oauth2MetadataUrl",
54 skip_serializing_if = "Option::is_none"
55 )]
56 pub oauth2_metadata_url: Option<String>,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
60#[serde(rename_all = "camelCase")]
61pub struct OpenIdConnectSecurityScheme {
62 #[serde(default, skip_serializing_if = "Option::is_none")]
63 pub description: Option<String>,
64 pub open_id_connect_url: String,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
68#[serde(rename_all = "camelCase")]
69pub struct MutualTlsSecurityScheme {
70 #[serde(default, skip_serializing_if = "Option::is_none")]
71 pub description: Option<String>,
72}
73
74#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
75#[serde(rename_all = "camelCase")]
76pub enum ApiKeyLocation {
77 Query,
78 Header,
79 Cookie,
80}
81
82impl std::fmt::Display for ApiKeyLocation {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 match self {
85 Self::Query => write!(f, "query"),
86 Self::Header => write!(f, "header"),
87 Self::Cookie => write!(f, "cookie"),
88 }
89 }
90}
91
92impl std::str::FromStr for ApiKeyLocation {
93 type Err = ParseEnumError;
94
95 fn from_str(s: &str) -> Result<Self, Self::Err> {
96 match s {
97 "query" => Ok(Self::Query),
98 "header" => Ok(Self::Header),
99 "cookie" => Ok(Self::Cookie),
100 _ => Err(ParseEnumError::new("API key location", s)),
101 }
102 }
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
106#[serde(rename_all = "camelCase")]
107pub enum OAuthFlows {
108 AuthorizationCode(AuthorizationCodeOAuthFlow),
109 ClientCredentials(ClientCredentialsOAuthFlow),
110 DeviceCode(DeviceCodeOAuthFlow),
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
114#[serde(rename_all = "camelCase")]
115pub struct AuthorizationCodeOAuthFlow {
116 pub authorization_url: String,
117 pub token_url: String,
118 #[serde(default, skip_serializing_if = "Option::is_none")]
119 pub refresh_url: Option<String>,
120 #[serde(default)]
121 pub scopes: HashMap<String, String>,
122 #[serde(default)]
123 pub pkce_required: bool,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
127#[serde(rename_all = "camelCase")]
128pub struct ClientCredentialsOAuthFlow {
129 pub token_url: String,
130 #[serde(default, skip_serializing_if = "Option::is_none")]
131 pub refresh_url: Option<String>,
132 #[serde(default)]
133 pub scopes: HashMap<String, String>,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
137#[serde(rename_all = "camelCase")]
138pub struct DeviceCodeOAuthFlow {
139 pub device_authorization_url: String,
140 pub token_url: String,
141 #[serde(default, skip_serializing_if = "Option::is_none")]
142 pub refresh_url: Option<String>,
143 #[serde(default)]
144 pub scopes: HashMap<String, String>,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
148pub struct SecurityRequirement {
149 #[serde(default)]
150 pub schemes: HashMap<String, StringList>,
151}
152
153impl SecurityRequirement {
154 #[must_use]
155 pub fn scheme(name: impl Into<String>, scopes: Vec<String>) -> Self {
156 Self {
157 schemes: HashMap::from([(name.into(), StringList { list: scopes })]),
158 }
159 }
160}
161
162#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
163pub struct StringList {
164 #[serde(default)]
165 pub list: Vec<String>,
166}