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}