oapi_codegen/lower/
security.rs1use openapiv3::APIKeyLocation;
12use openapiv3::ReferenceOr;
13use openapiv3::SecurityRequirement;
14use openapiv3::SecurityScheme as OasSecurityScheme;
15
16use crate::ir::SecurityScheme;
17use crate::ir::SecuritySchemeKind;
18use crate::loader::Spec;
19use crate::naming::Case;
20use crate::naming::to_ident;
21
22pub fn scheme_catalogue(spec: &Spec) -> Vec<SecurityScheme> {
30 let mut schemes = Vec::new();
31 for (key, entry) in spec.security_schemes() {
32 let (kind, doc) = match entry {
33 ReferenceOr::Item(scheme) => lower_scheme(scheme),
34 ReferenceOr::Reference { reference } => (
35 SecuritySchemeKind::Unsupported(format!(
36 "security scheme `{key}` is a `$ref` (`{reference}`), which is not supported"
37 )),
38 None,
39 ),
40 };
41 schemes.push(SecurityScheme {
42 key: key.clone(),
43 field: to_ident(key, Case::Snake),
44 kind,
45 doc,
46 });
47 }
48 return schemes;
49}
50
51fn lower_scheme(scheme: &OasSecurityScheme) -> (SecuritySchemeKind, Option<String>) {
53 match scheme {
54 OasSecurityScheme::HTTP {
55 scheme, description, ..
56 } => {
57 let kind = if scheme.eq_ignore_ascii_case("bearer") {
58 SecuritySchemeKind::HttpBearer
59 } else if scheme.eq_ignore_ascii_case("basic") {
60 SecuritySchemeKind::HttpBasic
61 } else {
62 SecuritySchemeKind::Unsupported(format!("HTTP authentication scheme `{scheme}` is not supported"))
63 };
64 return (kind, description.clone());
65 }
66 OasSecurityScheme::APIKey {
67 location,
68 name,
69 description,
70 ..
71 } => {
72 let kind = match location {
73 APIKeyLocation::Header => SecuritySchemeKind::ApiKeyHeader(name.clone()),
74 APIKeyLocation::Query => SecuritySchemeKind::ApiKeyQuery(name.clone()),
75 APIKeyLocation::Cookie => SecuritySchemeKind::ApiKeyCookie(name.clone()),
76 };
77 return (kind, description.clone());
78 }
79 OasSecurityScheme::OAuth2 { description, .. } => {
80 return (
81 SecuritySchemeKind::Unsupported("OAuth2 security is not supported by the client generator".to_owned()),
82 description.clone(),
83 );
84 }
85 OasSecurityScheme::OpenIDConnect { description, .. } => {
86 return (
87 SecuritySchemeKind::Unsupported(
88 "OpenID Connect security is not supported by the client generator".to_owned(),
89 ),
90 description.clone(),
91 );
92 }
93 }
94}
95
96pub fn effective_requirements<'a>(
100 operation_security: Option<&'a [SecurityRequirement]>,
101 global_security: Option<&'a [SecurityRequirement]>,
102) -> Option<&'a [SecurityRequirement]> {
103 return operation_security.or(global_security);
104}
105
106pub fn required_keys(requirements: &[SecurityRequirement]) -> Vec<String> {
113 let mut keys: Vec<String> = Vec::new();
114 for requirement in requirements {
115 for key in requirement.keys() {
116 if !keys.iter().any(|existing| return existing == key) {
117 keys.push(key.clone());
118 }
119 }
120 }
121 return keys;
122}