Skip to main content

openstack_sdk_identity/v4/federation/identity_provider/
create.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// SPDX-License-Identifier: Apache-2.0
14//
15// WARNING: This file is automatically generated from OpenAPI schema using
16// `openstack-codegenerator`.
17
18//! Create the identity provider with the specified properties.
19//!
20//! It is expected that only admin user is able to create global identity
21//! providers.
22//!
23use derive_builder::Builder;
24use http::{HeaderMap, HeaderName, HeaderValue};
25
26use openstack_sdk_core::api::rest_endpoint_prelude::*;
27
28use serde::Deserialize;
29use serde::Serialize;
30use serde_json::Value;
31use std::borrow::Cow;
32use std::collections::BTreeMap;
33
34/// Identity provider data.
35#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
36#[builder(setter(strip_option))]
37pub struct IdentityProvider<'a> {
38    /// The bound issuer that is verified when using the identity provider.
39    #[serde(skip_serializing_if = "Option::is_none")]
40    #[builder(default, setter(into))]
41    pub(crate) bound_issuer: Option<Cow<'a, str>>,
42
43    /// Default attribute mapping name which is automatically used when no
44    /// mapping is explicitly requested. The referred attribute mapping must
45    /// exist.
46    #[serde(skip_serializing_if = "Option::is_none")]
47    #[builder(default, setter(into))]
48    pub(crate) default_mapping_name: Option<Cow<'a, str>>,
49
50    /// The ID of the domain this identity provider belongs to. Empty value
51    /// identifies that the identity provider can be used by other domains as
52    /// well.
53    #[serde(skip_serializing_if = "Option::is_none")]
54    #[builder(default, setter(into))]
55    pub(crate) domain_id: Option<Cow<'a, str>>,
56
57    /// Identity provider `enabled` property. Inactive Identity Providers can
58    /// not be used for login.
59    #[serde(skip_serializing_if = "Option::is_none")]
60    #[builder(default, setter(into))]
61    pub(crate) enabled: Option<bool>,
62
63    /// Optional URL to fetch JsonWebKeySet. Must be specified for JWT
64    /// authentication when discovery for the provider is not available or not
65    /// standard compliant.
66    #[serde(skip_serializing_if = "Option::is_none")]
67    #[builder(default, setter(into))]
68    pub(crate) jwks_url: Option<Cow<'a, str>>,
69
70    /// List of the jwt validation public keys.
71    #[serde(skip_serializing_if = "Option::is_none")]
72    #[builder(default, setter(into))]
73    pub(crate) jwt_validation_pubkeys: Option<Vec<Cow<'a, str>>>,
74
75    /// Identity provider name.
76    #[serde()]
77    #[builder(setter(into))]
78    pub(crate) name: Cow<'a, str>,
79
80    /// The oidc `client_id` to use for the private client.
81    #[serde(skip_serializing_if = "Option::is_none")]
82    #[builder(default, setter(into))]
83    pub(crate) oidc_client_id: Option<Cow<'a, str>>,
84
85    /// The oidc `client_secret` to use for the private client. It is never
86    /// returned back.
87    #[serde(skip_serializing_if = "Option::is_none")]
88    #[builder(default, setter(into))]
89    pub(crate) oidc_client_secret: Option<Cow<'a, str>>,
90
91    /// OIDC discovery endpoint for the identity provider.
92    #[serde(skip_serializing_if = "Option::is_none")]
93    #[builder(default, setter(into))]
94    pub(crate) oidc_discovery_url: Option<Cow<'a, str>>,
95
96    /// The oidc response mode.
97    #[serde(skip_serializing_if = "Option::is_none")]
98    #[builder(default, setter(into))]
99    pub(crate) oidc_response_mode: Option<Cow<'a, str>>,
100
101    /// List of supported response types.
102    #[serde(skip_serializing_if = "Option::is_none")]
103    #[builder(default, setter(into))]
104    pub(crate) oidc_response_types: Option<Vec<Cow<'a, str>>>,
105
106    /// Additional special provider specific configuration.
107    #[serde(skip_serializing_if = "Option::is_none")]
108    #[builder(default, private, setter(into, name = "_provider_config"))]
109    pub(crate) provider_config: Option<BTreeMap<Cow<'a, str>, Value>>,
110}
111
112impl<'a> IdentityProviderBuilder<'a> {
113    /// Additional special provider specific configuration.
114    pub fn provider_config<I, K, V>(&mut self, iter: I) -> &mut Self
115    where
116        I: Iterator<Item = (K, V)>,
117        K: Into<Cow<'a, str>>,
118        V: Into<Value>,
119    {
120        self.provider_config
121            .get_or_insert(None)
122            .get_or_insert_with(BTreeMap::new)
123            .extend(iter.map(|(k, v)| (k.into(), v.into())));
124        self
125    }
126}
127
128#[derive(Builder, Debug, Clone)]
129#[builder(setter(strip_option))]
130pub struct Request<'a> {
131    /// Identity provider data.
132    #[builder(setter(into))]
133    pub(crate) identity_provider: IdentityProvider<'a>,
134
135    #[builder(setter(name = "_headers"), default, private)]
136    _headers: Option<HeaderMap>,
137}
138impl<'a> Request<'a> {
139    /// Create a builder for the endpoint.
140    pub fn builder() -> RequestBuilder<'a> {
141        RequestBuilder::default()
142    }
143}
144
145impl<'a> RequestBuilder<'a> {
146    /// Add a single header to the Identity_Provider.
147    pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
148    where
149        K: Into<HeaderName>,
150        V: Into<HeaderValue>,
151    {
152        self._headers
153            .get_or_insert(None)
154            .get_or_insert_with(HeaderMap::new)
155            .insert(header_name.into(), header_value.into());
156        self
157    }
158
159    /// Add multiple headers.
160    pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
161    where
162        I: Iterator<Item = T>,
163        T: Into<(Option<HeaderName>, HeaderValue)>,
164    {
165        self._headers
166            .get_or_insert(None)
167            .get_or_insert_with(HeaderMap::new)
168            .extend(iter.map(Into::into));
169        self
170    }
171}
172
173impl RestEndpoint for Request<'_> {
174    fn method(&self) -> http::Method {
175        http::Method::POST
176    }
177
178    fn endpoint(&self) -> Cow<'static, str> {
179        "federation/identity_providers".to_string().into()
180    }
181
182    fn parameters(&self) -> QueryParams<'_> {
183        QueryParams::default()
184    }
185
186    fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
187        let mut params = JsonBodyParams::default();
188
189        params.push(
190            "identity_provider",
191            serde_json::to_value(&self.identity_provider)?,
192        );
193
194        params.into_body()
195    }
196
197    fn service_type(&self) -> ServiceType {
198        ServiceType::Identity
199    }
200
201    fn response_key(&self) -> Option<Cow<'static, str>> {
202        Some("identity_provider".into())
203    }
204
205    /// Returns headers to be set into the request
206    fn request_headers(&self) -> Option<&HeaderMap> {
207        self._headers.as_ref()
208    }
209
210    /// Returns required API version
211    fn api_version(&self) -> Option<ApiVersion> {
212        Some(ApiVersion::new(4, 0))
213    }
214}
215
216#[cfg(test)]
217mod tests {
218    use super::*;
219    use http::{HeaderName, HeaderValue};
220    use httpmock::MockServer;
221    #[cfg(feature = "sync")]
222    use openstack_sdk_core::api::Query;
223    use openstack_sdk_core::test::client::FakeOpenStackClient;
224    use openstack_sdk_core::types::ServiceType;
225    use serde_json::json;
226
227    #[test]
228    fn test_service_type() {
229        assert_eq!(
230            Request::builder()
231                .identity_provider(
232                    IdentityProviderBuilder::default()
233                        .name("foo")
234                        .build()
235                        .unwrap()
236                )
237                .build()
238                .unwrap()
239                .service_type(),
240            ServiceType::Identity
241        );
242    }
243
244    #[test]
245    fn test_response_key() {
246        assert_eq!(
247            Request::builder()
248                .identity_provider(
249                    IdentityProviderBuilder::default()
250                        .name("foo")
251                        .build()
252                        .unwrap()
253                )
254                .build()
255                .unwrap()
256                .response_key()
257                .unwrap(),
258            "identity_provider"
259        );
260    }
261
262    #[cfg(feature = "sync")]
263    #[test]
264    fn endpoint() {
265        let server = MockServer::start();
266        let client = FakeOpenStackClient::new(server.base_url());
267        let mock = server.mock(|when, then| {
268            when.method(httpmock::Method::POST)
269                .path("/federation/identity_providers".to_string());
270
271            then.status(200)
272                .header("content-type", "application/json")
273                .json_body(json!({ "identity_provider": {} }));
274        });
275
276        let endpoint = Request::builder()
277            .identity_provider(
278                IdentityProviderBuilder::default()
279                    .name("foo")
280                    .build()
281                    .unwrap(),
282            )
283            .build()
284            .unwrap();
285        let _: serde_json::Value = endpoint.query(&client).unwrap();
286        mock.assert();
287    }
288
289    #[cfg(feature = "sync")]
290    #[test]
291    fn endpoint_headers() {
292        let server = MockServer::start();
293        let client = FakeOpenStackClient::new(server.base_url());
294        let mock = server.mock(|when, then| {
295            when.method(httpmock::Method::POST)
296                .path("/federation/identity_providers".to_string())
297                .header("foo", "bar")
298                .header("not_foo", "not_bar");
299            then.status(200)
300                .header("content-type", "application/json")
301                .json_body(json!({ "identity_provider": {} }));
302        });
303
304        let endpoint = Request::builder()
305            .identity_provider(
306                IdentityProviderBuilder::default()
307                    .name("foo")
308                    .build()
309                    .unwrap(),
310            )
311            .headers(
312                [(
313                    Some(HeaderName::from_static("foo")),
314                    HeaderValue::from_static("bar"),
315                )]
316                .into_iter(),
317            )
318            .header(
319                HeaderName::from_static("not_foo"),
320                HeaderValue::from_static("not_bar"),
321            )
322            .build()
323            .unwrap();
324        let _: serde_json::Value = endpoint.query(&client).unwrap();
325        mock.assert();
326    }
327}