Skip to main content

openstack_keystone_core/identity_mapping/
service.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//! # Identity mapping provider
16
17use async_trait::async_trait;
18use std::sync::Arc;
19
20use crate::config::Config;
21use crate::identity_mapping::{
22    IdentityMappingProviderError, backend::IdentityMappingBackend, types::*,
23};
24use crate::keystone::ServiceState;
25use crate::plugin_manager::PluginManagerApi;
26
27pub struct IdentityMappingService {
28    /// Backend driver.
29    backend_driver: Arc<dyn IdentityMappingBackend>,
30}
31
32impl IdentityMappingService {
33    pub fn new<P: PluginManagerApi>(
34        config: &Config,
35        plugin_manager: &P,
36    ) -> Result<Self, IdentityMappingProviderError> {
37        let backend_driver = plugin_manager
38            .get_identity_mapping_backend(config.identity_mapping.driver.clone())?
39            .clone();
40        Ok(Self { backend_driver })
41    }
42}
43
44#[async_trait]
45impl IdentityMappingApi for IdentityMappingService {
46    /// Get the `IdMapping` by the local data.
47    async fn get_by_local_id<'a>(
48        &self,
49        state: &ServiceState,
50        local_id: &'a str,
51        domain_id: &'a str,
52        entity_type: IdMappingEntityType,
53    ) -> Result<Option<IdMapping>, IdentityMappingProviderError> {
54        self.backend_driver
55            .get_by_local_id(state, local_id, domain_id, entity_type)
56            .await
57    }
58
59    /// Get the IdMapping by the public_id.
60    #[tracing::instrument(level = "info", skip(self, state))]
61    async fn get_by_public_id<'a>(
62        &self,
63        state: &ServiceState,
64        public_id: &'a str,
65    ) -> Result<Option<IdMapping>, IdentityMappingProviderError> {
66        self.backend_driver.get_by_public_id(state, public_id).await
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use std::sync::Arc;
73
74    use super::*;
75    use crate::identity_mapping::backend::MockIdentityMappingBackend;
76    use crate::tests::get_mocked_state;
77
78    #[tokio::test]
79    async fn test_get_by_local_id() {
80        let state = get_mocked_state(None, None);
81        let sot = IdMapping {
82            public_id: "pid".into(),
83            local_id: "lid".into(),
84            domain_id: "did".into(),
85            entity_type: IdMappingEntityType::User,
86        };
87        let mut backend = MockIdentityMappingBackend::default();
88        let sot_clone = sot.clone();
89        backend
90            .expect_get_by_local_id()
91            .withf(|_, lid: &'_ str, did: &'_ str, _et: &IdMappingEntityType| {
92                lid == "lid" && did == "did"
93            })
94            .returning(move |_, _, _, _| Ok(Some(sot_clone.clone())));
95        let provider = IdentityMappingService {
96            backend_driver: Arc::new(backend),
97        };
98
99        let res: IdMapping = provider
100            .get_by_local_id(&state, "lid", "did", IdMappingEntityType::User)
101            .await
102            .unwrap()
103            .expect("id mapping should be there");
104        assert_eq!(res, sot);
105    }
106
107    #[tokio::test]
108    async fn test_get_by_public_id() {
109        let state = get_mocked_state(None, None);
110        let sot = IdMapping {
111            public_id: "pid".into(),
112            local_id: "lid".into(),
113            domain_id: "did".into(),
114            entity_type: IdMappingEntityType::User,
115        };
116        let mut backend = MockIdentityMappingBackend::default();
117        let sot_clone = sot.clone();
118        backend
119            .expect_get_by_public_id()
120            .withf(|_, pid: &'_ str| pid == "pid")
121            .returning(move |_, _| Ok(Some(sot_clone.clone())));
122        let provider = IdentityMappingService {
123            backend_driver: Arc::new(backend),
124        };
125
126        let res: IdMapping = provider
127            .get_by_public_id(&state, "pid")
128            .await
129            .unwrap()
130            .expect("id mapping should be there");
131        assert_eq!(res, sot);
132    }
133}