(
store: &Store,
mut provider: Provider,
)
| 64 | } |
| 65 | |
| 66 | pub(super) async fn create_provider_record( |
| 67 | store: &Store, |
| 68 | mut provider: Provider, |
| 69 | ) -> Result<Provider, Status> { |
| 70 | use crate::persistence::{ObjectName, current_time_ms}; |
| 71 | |
| 72 | // Initialize metadata if not present |
| 73 | if provider.metadata.is_none() { |
| 74 | let now_ms = current_time_ms(); |
| 75 | provider.metadata = Some(openshell_core::proto::datamodel::v1::ObjectMeta { |
| 76 | id: uuid::Uuid::new_v4().to_string(), |
| 77 | name: generate_name(), |
| 78 | created_at_ms: now_ms, |
| 79 | labels: std::collections::HashMap::new(), |
| 80 | resource_version: 0, |
| 81 | }); |
| 82 | } |
| 83 | |
| 84 | // Auto-generate name if empty |
| 85 | if let Some(metadata) = provider.metadata.as_mut() { |
| 86 | if metadata.name.is_empty() { |
| 87 | metadata.name = generate_name(); |
| 88 | } |
| 89 | if metadata.id.is_empty() { |
| 90 | metadata.id = uuid::Uuid::new_v4().to_string(); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | // Ensure metadata is present and valid (must be non-None with non-empty id/name) |
| 95 | super::validation::validate_object_metadata(provider.metadata.as_ref(), "provider")?; |
| 96 | |
| 97 | if provider.r#type.trim().is_empty() { |
| 98 | return Err(Status::invalid_argument("provider.type is required")); |
| 99 | } |
| 100 | if provider.credentials.is_empty() |
| 101 | && !provider_type_allows_empty_credentials(store, &provider.r#type).await? |
| 102 | { |
| 103 | return Err(Status::invalid_argument( |
| 104 | "provider.credentials must not be empty", |
| 105 | )); |
| 106 | } |
| 107 | |
| 108 | // Validate field sizes before any I/O. |
| 109 | validate_provider_fields(&provider)?; |
| 110 | |
| 111 | // Generate UUID for database row and update metadata.id to match |
| 112 | let provider_id = uuid::Uuid::new_v4().to_string(); |
| 113 | let mut provider = provider; |
| 114 | if let Some(metadata) = provider.metadata.as_mut() { |
| 115 | metadata.id.clone_from(&provider_id); |
| 116 | } |
| 117 | |
| 118 | // Create with MustCreate condition to prevent duplicate creation race |
| 119 | let result = store |
| 120 | .put_if( |
| 121 | Provider::object_type(), |
| 122 | &provider_id, |
| 123 | provider.object_name(), |
no test coverage detected