pub struct StandardResourceProvider<S: StorageProvider> { /* private fields */ }Expand description
Standard resource provider with pluggable storage backend.
This provider separates SCIM protocol logic from storage concerns by delegating data persistence to a StorageProvider implementation while handling all SCIM-specific business logic, validation, and metadata management.
Implementations§
Source§impl<S: StorageProvider> StandardResourceProvider<S>
impl<S: StorageProvider> StandardResourceProvider<S>
Sourcepub async fn clear(&self)
pub async fn clear(&self)
Clear all data from storage.
Removes all resources from all tenants by delegating to the storage backend’s clear operation. This method provides a consistent interface for clearing data regardless of the underlying storage implementation.
§Behavior
- Delegates to
StorageProvider::clearfor actual data removal - Logs warnings if the clear operation fails
- Primarily intended for testing scenarios
- After successful clearing,
get_statsshould report zero resources
§Examples
use scim_server::providers::StandardResourceProvider;
use scim_server::storage::InMemoryStorage;
let storage = InMemoryStorage::new();
let provider = StandardResourceProvider::new(storage);
// ... create some resources ...
provider.clear().await;
let stats = provider.get_stats().await;
assert_eq!(stats.total_resources, 0);Sourcepub async fn get_stats(&self) -> ProviderStats
pub async fn get_stats(&self) -> ProviderStats
Get comprehensive statistics about stored data across all tenants.
Dynamically discovers all tenants and resource types from storage to provide accurate statistics without relying on hardcoded patterns. This method uses the storage provider’s discovery capabilities to enumerate actual data.
§Returns
ProviderStats containing:
tenant_count: Number of tenants with at least one resourcetotal_resources: Sum of all resources across all tenants and typesresource_type_count: Number of distinct resource types foundresource_types: List of all resource type names
§Errors
This method handles storage errors gracefully by using default values (empty collections) when discovery operations fail.
§Examples
use scim_server::providers::StandardResourceProvider;
use scim_server::storage::InMemoryStorage;
use scim_server::resource::{RequestContext, TenantContext};
let storage = InMemoryStorage::new();
let provider = StandardResourceProvider::new(storage);
// ... create resources in multiple tenants ...
let stats = provider.get_stats().await;
println!("Total resources: {}", stats.total_resources);
println!("Active tenants: {}", stats.tenant_count);
println!("Resource types: {:?}", stats.resource_types);Trait Implementations§
Source§impl<S: Clone + StorageProvider> Clone for StandardResourceProvider<S>
impl<S: Clone + StorageProvider> Clone for StandardResourceProvider<S>
Source§fn clone(&self) -> StandardResourceProvider<S>
fn clone(&self) -> StandardResourceProvider<S>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<S: Debug + StorageProvider> Debug for StandardResourceProvider<S>
impl<S: Debug + StorageProvider> Debug for StandardResourceProvider<S>
Source§impl<S: StorageProvider> ResourceProvider for StandardResourceProvider<S>
impl<S: StorageProvider> ResourceProvider for StandardResourceProvider<S>
Source§type Error = ProviderError
type Error = ProviderError
Source§async fn create_resource(
&self,
resource_type: &str,
data: Value,
context: &RequestContext,
) -> Result<VersionedResource, Self::Error>
async fn create_resource( &self, resource_type: &str, data: Value, context: &RequestContext, ) -> Result<VersionedResource, Self::Error>
Source§async fn get_resource(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> Result<Option<VersionedResource>, Self::Error>
async fn get_resource( &self, resource_type: &str, id: &str, context: &RequestContext, ) -> Result<Option<VersionedResource>, Self::Error>
Source§async fn update_resource(
&self,
resource_type: &str,
id: &str,
data: Value,
expected_version: Option<&RawVersion>,
context: &RequestContext,
) -> Result<VersionedResource, Self::Error>
async fn update_resource( &self, resource_type: &str, id: &str, data: Value, expected_version: Option<&RawVersion>, context: &RequestContext, ) -> Result<VersionedResource, Self::Error>
Source§async fn delete_resource(
&self,
resource_type: &str,
id: &str,
expected_version: Option<&RawVersion>,
context: &RequestContext,
) -> Result<(), Self::Error>
async fn delete_resource( &self, resource_type: &str, id: &str, expected_version: Option<&RawVersion>, context: &RequestContext, ) -> Result<(), Self::Error>
Source§async fn list_resources(
&self,
resource_type: &str,
query: Option<&ListQuery>,
context: &RequestContext,
) -> Result<Vec<VersionedResource>, Self::Error>
async fn list_resources( &self, resource_type: &str, query: Option<&ListQuery>, context: &RequestContext, ) -> Result<Vec<VersionedResource>, Self::Error>
Source§async fn find_resources_by_attribute(
&self,
resource_type: &str,
attribute_name: &str,
attribute_value: &str,
context: &RequestContext,
) -> Result<Vec<VersionedResource>, Self::Error>
async fn find_resources_by_attribute( &self, resource_type: &str, attribute_name: &str, attribute_value: &str, context: &RequestContext, ) -> Result<Vec<VersionedResource>, Self::Error>
Source§async fn patch_resource(
&self,
resource_type: &str,
id: &str,
patch_request: &Value,
expected_version: Option<&RawVersion>,
context: &RequestContext,
) -> Result<VersionedResource, Self::Error>
async fn patch_resource( &self, resource_type: &str, id: &str, patch_request: &Value, expected_version: Option<&RawVersion>, context: &RequestContext, ) -> Result<VersionedResource, Self::Error>
Source§async fn resource_exists(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> Result<bool, Self::Error>
async fn resource_exists( &self, resource_type: &str, id: &str, context: &RequestContext, ) -> Result<bool, Self::Error>
Auto Trait Implementations§
impl<S> Freeze for StandardResourceProvider<S>where
S: Freeze,
impl<S> RefUnwindSafe for StandardResourceProvider<S>where
S: RefUnwindSafe,
impl<S> Send for StandardResourceProvider<S>
impl<S> Sync for StandardResourceProvider<S>
impl<S> Unpin for StandardResourceProvider<S>where
S: Unpin,
impl<S> UnwindSafe for StandardResourceProvider<S>where
S: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> ConditionalOperations for Twhere
T: ResourceProvider,
impl<T> ConditionalOperations for Twhere
T: ResourceProvider,
Source§fn conditional_update_resource(
&self,
resource_type: &str,
id: &str,
data: Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
fn conditional_update_resource(
&self,
resource_type: &str,
id: &str,
data: Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
Source§fn conditional_delete_resource(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<()>, Self::Error>> + Sendwhere
Self: Sync,
fn conditional_delete_resource(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<()>, Self::Error>> + Sendwhere
Self: Sync,
Source§fn conditional_patch_resource(
&self,
resource_type: &str,
id: &str,
patch_request: &Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
fn conditional_patch_resource(
&self,
resource_type: &str,
id: &str,
patch_request: &Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
Source§fn get_versioned_resource(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
fn get_versioned_resource(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
Source§fn create_versioned_resource(
&self,
resource_type: &str,
data: Value,
context: &RequestContext,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Sendwhere
Self: Sync,
fn create_versioned_resource(
&self,
resource_type: &str,
data: Value,
context: &RequestContext,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Sendwhere
Self: Sync,
Source§fn check_resource_version(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<Option<bool>, Self::Error>> + Sendwhere
Self: Sync,
fn check_resource_version(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<Option<bool>, Self::Error>> + Sendwhere
Self: Sync,
Source§fn get_resource_version(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<RawVersion>, Self::Error>> + Sendwhere
Self: Sync,
fn get_resource_version(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<RawVersion>, Self::Error>> + Sendwhere
Self: Sync,
Source§fn is_valid_version(&self, version: &RawVersion) -> bool
fn is_valid_version(&self, version: &RawVersion) -> bool
Source§fn create_version_conflict(
&self,
expected: RawVersion,
current: RawVersion,
resource_info: Option<&str>,
) -> VersionConflict
fn create_version_conflict( &self, expected: RawVersion, current: RawVersion, resource_info: Option<&str>, ) -> VersionConflict
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more