scim_server/providers/
error.rs

1//! Error types for resource provider implementations.
2//!
3//! This module provides error types that are shared across different resource
4//! provider implementations, independent of the underlying storage backend.
5//!
6//! # Key Types
7//!
8//! - [`ProviderError`] - Generic provider error type for resource operations
9//!
10//! # Usage
11//!
12//! This error type is used with `StandardResourceProvider<T>` regardless of storage backend:
13//!
14//! ```rust
15//! use scim_server::providers::StandardResourceProvider;
16//! use scim_server::storage::InMemoryStorage;
17//!
18//! let storage = InMemoryStorage::new();
19//! let provider = StandardResourceProvider::new(storage);
20//! ```
21
22use thiserror::Error;
23
24/// Errors that can occur during resource provider operations.
25///
26/// This error type is used by resource providers to represent various failure
27/// conditions during SCIM operations, independent of the underlying storage backend.
28#[derive(Debug, Clone, Error)]
29pub enum ProviderError {
30    #[error("Resource not found: {resource_type} with id '{id}' in tenant '{tenant_id}'")]
31    ResourceNotFound {
32        /// The type of resource that was not found
33        resource_type: String,
34        /// The ID of the resource that was not found
35        id: String,
36        /// The tenant ID where the resource was not found
37        tenant_id: String,
38    },
39
40    #[error(
41        "Duplicate attribute '{attribute}' with value '{value}' for {resource_type} in tenant '{tenant_id}'"
42    )]
43    DuplicateAttribute {
44        /// The type of resource with duplicate attribute
45        resource_type: String,
46        /// The name of the duplicate attribute
47        attribute: String,
48        /// The duplicate value
49        value: String,
50        /// The tenant ID where the duplicate was found
51        tenant_id: String,
52    },
53
54    #[error("Invalid resource data: {message}")]
55    InvalidData {
56        /// Description of the invalid data
57        message: String,
58    },
59
60    #[error("Query error: {message}")]
61    QueryError {
62        /// Description of the query error
63        message: String,
64    },
65
66    #[error("Storage error: {message}")]
67    Storage {
68        /// Description of the storage error
69        message: String,
70    },
71
72    #[error("Internal error: {message}")]
73    Internal {
74        /// Description of the internal error
75        message: String,
76    },
77
78    #[error("Invalid input: {message}")]
79    InvalidInput {
80        /// Description of what input was invalid
81        message: String,
82    },
83
84    #[error("Resource not found: {resource_type} with id '{id}'")]
85    NotFound {
86        /// The type of resource that was not found
87        resource_type: String,
88        /// The ID of the resource that was not found
89        id: String,
90    },
91
92    #[error("Precondition failed: {message}")]
93    PreconditionFailed {
94        /// Description of the precondition failure
95        message: String,
96    },
97
98    #[error(
99        "Duplicate resource: {resource_type} with userName '{username}' already exists in tenant '{tenant_id}'"
100    )]
101    DuplicateUserName {
102        /// The resource type that had the duplicate
103        resource_type: String,
104        /// The duplicate userName
105        username: String,
106        /// The tenant where the duplicate was found
107        tenant_id: String,
108    },
109
110    #[error("Patch operation failed: {message}")]
111    PatchOperationFailed {
112        /// Description of why the patch operation failed
113        message: String,
114    },
115
116    #[error("Version conflict: {conflict}")]
117    VersionConflict {
118        /// Details of the version conflict
119        #[from]
120        conflict: crate::resource::version::VersionConflict,
121    },
122}
123
124impl From<String> for ProviderError {
125    fn from(message: String) -> Self {
126        ProviderError::Internal { message }
127    }
128}