ironflow_api/entities/
secret.rs1use chrono::{DateTime, Utc};
4use ironflow_store::entities::{Secret, SecretMetadata};
5use serde::{Deserialize, Serialize};
6use uuid::Uuid;
7use validator::Validate;
8
9#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
11#[derive(Debug, Serialize)]
12pub struct SecretResponse {
13 pub id: Uuid,
15 pub key: String,
17 pub created_at: DateTime<Utc>,
19 pub updated_at: DateTime<Utc>,
21}
22
23impl From<SecretMetadata> for SecretResponse {
24 fn from(meta: SecretMetadata) -> Self {
25 Self {
26 id: meta.id,
27 key: meta.key,
28 created_at: meta.created_at,
29 updated_at: meta.updated_at,
30 }
31 }
32}
33
34impl From<Secret> for SecretResponse {
35 fn from(secret: Secret) -> Self {
36 Self {
37 id: secret.id,
38 key: secret.key,
39 created_at: secret.created_at,
40 updated_at: secret.updated_at,
41 }
42 }
43}
44
45#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
47#[derive(Debug, Deserialize, Validate)]
48pub struct SetSecretRequest {
49 #[validate(length(min = 1, max = 512), custom(function = "validate_secret_key"))]
51 pub key: String,
52 #[validate(length(min = 1, max = 65536))]
54 pub value: String,
55}
56
57fn validate_secret_key(key: &str) -> Result<(), validator::ValidationError> {
61 if !key
62 .chars()
63 .all(|c| c.is_ascii_alphanumeric() || matches!(c, '/' | '-' | '_' | '.'))
64 {
65 let mut err = validator::ValidationError::new("invalid_characters");
66 err.message =
67 Some("key must only contain alphanumeric characters, '/', '-', '_', '.'".into());
68 return Err(err);
69 }
70 if key.starts_with('/') || key.ends_with('/') || key.contains("//") {
71 let mut err = validator::ValidationError::new("invalid_format");
72 err.message = Some("key must not start/end with '/' or contain '//'".into());
73 return Err(err);
74 }
75 Ok(())
76}