scim_server/resource/
mapper.rs

1//! Schema mapping functionality for converting between SCIM and implementation formats.
2//!
3//! This module provides traits and implementations for mapping between
4//! SCIM schema representations and backend implementation schemas,
5//! such as database column mappings.
6
7use crate::error::ScimError;
8use serde_json::Value;
9use std::collections::HashMap;
10
11/// Trait for mapping between SCIM schema and implementation schema (e.g., database)
12pub trait SchemaMapper: Send + Sync {
13    fn to_implementation(&self, scim_data: &Value) -> Result<Value, ScimError>;
14    fn from_implementation(&self, impl_data: &Value) -> Result<Value, ScimError>;
15}
16
17/// Database schema mapper for converting between SCIM and database formats
18pub struct DatabaseMapper {
19    pub table_name: String,
20    pub column_mappings: HashMap<String, String>, // SCIM attribute -> DB column
21}
22
23impl DatabaseMapper {
24    pub fn new(table_name: &str, mappings: HashMap<String, String>) -> Self {
25        Self {
26            table_name: table_name.to_string(),
27            column_mappings: mappings,
28        }
29    }
30}
31
32impl SchemaMapper for DatabaseMapper {
33    fn to_implementation(&self, scim_data: &Value) -> Result<Value, ScimError> {
34        let mut db_data = serde_json::Map::new();
35
36        if let Some(obj) = scim_data.as_object() {
37            for (scim_attr, db_column) in &self.column_mappings {
38                if let Some(value) = obj.get(scim_attr) {
39                    db_data.insert(db_column.clone(), value.clone());
40                }
41            }
42        }
43
44        Ok(Value::Object(db_data))
45    }
46
47    fn from_implementation(&self, impl_data: &Value) -> Result<Value, ScimError> {
48        let mut scim_data = serde_json::Map::new();
49
50        if let Some(obj) = impl_data.as_object() {
51            for (scim_attr, db_column) in &self.column_mappings {
52                if let Some(value) = obj.get(db_column) {
53                    scim_data.insert(scim_attr.clone(), value.clone());
54                }
55            }
56        }
57
58        Ok(Value::Object(scim_data))
59    }
60}