Skip to main content

shared/domain/permission/
model.rs

1use chrono::{DateTime, Utc};
2use mongodb::bson;
3use serde::{Deserialize, Serialize};
4use sqlx::FromRow;
5use utoipa::ToSchema;
6
7use crate::domain::query::IntoBsonDocument;
8
9use super::super::serde::{deserialize_datetime, deserialize_object_id_as_string};
10
11#[derive(Default, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, FromRow, ToSchema)]
12#[schema(example = json!({"id": Some(String::default()), "name": String::default(), "created_at": "2026-02-19T22:42:23.467Z"}))]
13pub struct Permission {
14    #[serde(
15        rename = "_id",
16        default,
17        skip_serializing_if = "Option::is_none",
18        deserialize_with = "deserialize_object_id_as_string"
19    )]
20    pub id: Option<String>,
21
22    pub name: String,
23
24    #[sqlx(rename = "createdAt")]
25    #[serde(rename = "createdAt", deserialize_with = "deserialize_datetime")]
26    pub created_at: DateTime<Utc>,
27}
28
29impl Permission {
30    pub fn id(&self) -> Result<&str, crate::error::CoreError> {
31        self.id.as_deref().ok_or_else(|| {
32            tracing::error!(
33                error_code = "ValidationError::Malformed",
34                "Unexpected null/missing data"
35            );
36            crate::error::CoreError::Validation(crate::error::ValidationError::Malformed {
37                field: crate::error::CredentialField::ObjectId,
38            })
39        })
40    }
41}
42
43impl Permission {
44    pub fn new(name: &str) -> Self {
45        Self {
46            id: None,
47            name: name.into(),
48            created_at: Utc::now(),
49        }
50    }
51}
52
53impl IntoBsonDocument for Permission {
54    fn into_bson_document(self) -> Result<bson::Document, bson::ser::Error> {
55        let mut doc = bson::to_document(&self)?;
56
57        for key in &["createdAt"] {
58            if let Some(bson::Bson::String(s)) = doc.get(*key).cloned()
59                && let Ok(dt) = DateTime::parse_from_rfc3339(&s)
60            {
61                doc.insert(
62                    *key,
63                    bson::Bson::DateTime(bson::DateTime::from_millis(dt.timestamp_millis())),
64                );
65            }
66        }
67
68        Ok(doc)
69    }
70}