use crate::error::ScimError;
use crate::provider_capabilities::{
CapabilityDiscovery, CapabilityIntrospectable, ProviderCapabilities,
};
use crate::resource::{ResourceHandler, ResourceProvider, ScimOperation};
use crate::schema::SchemaRegistry;
use crate::schema_discovery::ServiceProviderConfig;
use std::collections::HashMap;
use std::sync::Arc;
pub struct ScimServer<P> {
pub(super) provider: P,
pub(super) schema_registry: SchemaRegistry,
pub(super) resource_handlers: HashMap<String, Arc<ResourceHandler>>, pub(super) supported_operations: HashMap<String, Vec<ScimOperation>>, }
impl<P: ResourceProvider> ScimServer<P> {
pub fn new(provider: P) -> Result<Self, ScimError> {
let schema_registry = SchemaRegistry::new()
.map_err(|e| ScimError::internal(format!("Failed to create schema registry: {}", e)))?;
Ok(Self {
provider,
schema_registry,
resource_handlers: HashMap::new(),
supported_operations: HashMap::new(),
})
}
pub fn discover_capabilities(&self) -> Result<ProviderCapabilities, ScimError> {
CapabilityDiscovery::discover_capabilities(
&self.schema_registry,
&self.resource_handlers,
&self.supported_operations,
&self.provider,
)
}
pub fn discover_capabilities_with_introspection(
&self,
) -> Result<ProviderCapabilities, ScimError>
where
P: CapabilityIntrospectable,
{
CapabilityDiscovery::discover_capabilities_with_introspection(
&self.schema_registry,
&self.resource_handlers,
&self.supported_operations,
&self.provider,
)
}
pub fn get_service_provider_config(&self) -> Result<ServiceProviderConfig, ScimError> {
let capabilities = self.discover_capabilities()?;
Ok(CapabilityDiscovery::generate_service_provider_config(
&capabilities,
))
}
pub fn get_service_provider_config_with_introspection(
&self,
) -> Result<ServiceProviderConfig, ScimError>
where
P: CapabilityIntrospectable,
{
let capabilities = self.discover_capabilities_with_introspection()?;
Ok(CapabilityDiscovery::generate_service_provider_config(
&capabilities,
))
}
pub fn supports_operation(&self, resource_type: &str, operation: &ScimOperation) -> bool {
self.supported_operations
.get(resource_type)
.map(|ops| ops.contains(operation))
.unwrap_or(false)
}
pub fn provider(&self) -> &P {
&self.provider
}
}