scim_server/operation_handler/
errors.rs1use crate::{
7 ScimError,
8 operation_handler::core::{OperationMetadata, ScimOperationResponse},
9 resource::version::VersionConflict,
10};
11use serde_json::Value;
12use std::collections::HashMap;
13
14pub fn create_error_response(error: ScimError, request_id: String) -> ScimOperationResponse {
16 let (error_message, error_code) = match &error {
17 ScimError::Validation(ve) => (
18 format!("Validation error: {}", ve),
19 Some("VALIDATION_ERROR"),
20 ),
21 ScimError::ResourceNotFound { resource_type, id } => (
22 format!("Resource not found: {} with ID {}", resource_type, id),
23 Some("RESOURCE_NOT_FOUND"),
24 ),
25 ScimError::SchemaNotFound { schema_id } => (
26 format!("Schema not found: {}", schema_id),
27 Some("SCHEMA_NOT_FOUND"),
28 ),
29 ScimError::UnsupportedResourceType(resource_type) => (
30 format!("Unsupported resource type: {}", resource_type),
31 Some("UNSUPPORTED_RESOURCE_TYPE"),
32 ),
33 ScimError::UnsupportedOperation {
34 resource_type,
35 operation,
36 } => (
37 format!(
38 "Unsupported operation {} for resource type {}",
39 operation, resource_type
40 ),
41 Some("UNSUPPORTED_OPERATION"),
42 ),
43 ScimError::InvalidRequest { message } => (
44 format!("Invalid request: {}", message),
45 Some("INVALID_REQUEST"),
46 ),
47 ScimError::Provider(provider_error) => (
48 format!("Provider error: {}", provider_error),
49 Some("PROVIDER_ERROR"),
50 ),
51 ScimError::Internal { message } => (
52 format!("Internal error: {}", message),
53 Some("INTERNAL_ERROR"),
54 ),
55 _ => (error.to_string(), Some("UNKNOWN_ERROR")),
56 };
57
58 ScimOperationResponse {
59 success: false,
60 data: None,
61 error: Some(error_message),
62 error_code: error_code.map(|s| s.to_string()),
63 metadata: OperationMetadata {
64 resource_type: None,
65 resource_id: None,
66 resource_count: None,
67 total_results: None,
68 request_id,
69 tenant_id: None,
70 schemas: None,
71 additional: HashMap::new(),
72 },
73 }
74}
75
76pub fn create_version_conflict_response(
78 conflict: VersionConflict,
79 request_id: String,
80 resource_type: Option<String>,
81 resource_id: Option<String>,
82) -> ScimOperationResponse {
83 let mut additional = HashMap::new();
84 additional.insert(
85 "expected_version".to_string(),
86 Value::String(conflict.expected.as_str().to_string()),
87 );
88 additional.insert(
89 "current_version".to_string(),
90 Value::String(conflict.current.as_str().to_string()),
91 );
92 additional.insert(
93 "expected_etag".to_string(),
94 Value::String(conflict.expected.to_http_header()),
95 );
96 additional.insert(
97 "current_etag".to_string(),
98 Value::String(conflict.current.to_http_header()),
99 );
100
101 ScimOperationResponse {
102 success: false,
103 data: None,
104 error: Some(conflict.message),
105 error_code: Some("version_mismatch".to_string()),
106 metadata: OperationMetadata {
107 resource_type,
108 resource_id,
109 resource_count: None,
110 total_results: None,
111 request_id,
112 tenant_id: None,
113 schemas: None,
114 additional,
115 },
116 }
117}