zino_model/message/
mod.rs1use crate::{group::Group, resource::Resource, user::User};
4use serde::{Deserialize, Serialize};
5use zino_core::{
6 Map, Uuid,
7 datetime::DateTime,
8 error::Error,
9 extension::JsonObjectExt,
10 model::{Model, ModelHooks},
11 validation::Validation,
12};
13use zino_derive::{DecodeRow, Entity, ModelAccessor, Schema};
14
15#[cfg(feature = "tags")]
16use crate::tag::Tag;
17
18#[cfg(feature = "maintainer-id")]
19use zino_auth::UserSession;
20
21#[derive(
23 Debug, Clone, Default, Serialize, Deserialize, DecodeRow, Entity, Schema, ModelAccessor,
24)]
25#[serde(default)]
26#[schema(auto_rename)]
27pub struct Message {
28 #[schema(read_only)]
30 id: Uuid,
31 #[schema(not_null)]
32 name: String,
33 #[cfg(feature = "namespace")]
34 #[schema(default_value = "Message::model_namespace", index_type = "hash")]
35 namespace: String,
36 #[cfg(feature = "visibility")]
37 #[schema(default_value = "Internal")]
38 visibility: String,
39 #[schema(default_value = "Active", index_type = "hash")]
40 status: String,
41 description: String,
42
43 #[schema(reference = "User")]
45 producer_id: Uuid, #[schema(reference = "Resource")]
47 channel_id: Uuid, #[schema(reference = "Group")]
49 consumer_id: Option<Uuid>, message: String,
52 #[cfg(feature = "tags")]
53 #[schema(reference = "Tag", index_type = "gin")]
54 tags: Vec<Uuid>, extra: Map,
58
59 #[cfg(feature = "owner-id")]
61 #[schema(reference = "User")]
62 owner_id: Option<Uuid>, #[cfg(feature = "maintainer-id")]
64 #[schema(reference = "User")]
65 maintainer_id: Option<Uuid>, #[schema(read_only, default_value = "now", index_type = "btree")]
67 created_at: DateTime,
68 #[schema(default_value = "now", index_type = "btree")]
69 updated_at: DateTime,
70 version: u64,
71 #[cfg(feature = "edition")]
72 edition: u32,
73}
74
75impl Model for Message {
76 const MODEL_NAME: &'static str = "message";
77
78 #[inline]
79 fn new() -> Self {
80 Self {
81 id: Uuid::now_v7(),
82 ..Self::default()
83 }
84 }
85
86 fn read_map(&mut self, data: &Map) -> Validation {
87 let mut validation = Validation::new();
88 if let Some(result) = data.parse_uuid("id") {
89 match result {
90 Ok(id) => self.id = id,
91 Err(err) => validation.record_fail("id", err),
92 }
93 }
94 if let Some(name) = data.parse_string("name") {
95 self.name = name.into_owned();
96 }
97 if let Some(description) = data.parse_string("description") {
98 self.description = description.into_owned();
99 }
100 #[cfg(feature = "tags")]
101 if let Some(result) = data.parse_array("tags") {
102 match result {
103 Ok(tags) => self.tags = tags,
104 Err(err) => validation.record_fail("tags", err),
105 }
106 }
107 #[cfg(feature = "owner-id")]
108 if let Some(result) = data.parse_uuid("owner_id") {
109 match result {
110 Ok(owner_id) => self.owner_id = Some(owner_id),
111 Err(err) => validation.record_fail("owner_id", err),
112 }
113 }
114 #[cfg(feature = "maintainer-id")]
115 if let Some(result) = data.parse_uuid("maintainer_id") {
116 match result {
117 Ok(maintainer_id) => self.maintainer_id = Some(maintainer_id),
118 Err(err) => validation.record_fail("maintainer_id", err),
119 }
120 }
121 validation
122 }
123}
124
125impl ModelHooks for Message {
126 type Data = ();
127 #[cfg(feature = "maintainer-id")]
128 type Extension = UserSession<Uuid, String>;
129 #[cfg(not(feature = "maintainer-id"))]
130 type Extension = ();
131
132 #[cfg(feature = "maintainer-id")]
133 #[inline]
134 async fn after_extract(&mut self, session: Self::Extension) -> Result<(), Error> {
135 self.maintainer_id = Some(*session.user_id());
136 Ok(())
137 }
138
139 #[cfg(feature = "maintainer-id")]
140 #[inline]
141 async fn before_validation(
142 data: &mut Map,
143 extension: Option<&Self::Extension>,
144 ) -> Result<(), Error> {
145 if let Some(session) = extension {
146 data.upsert("maintainer_id", session.user_id().to_string());
147 }
148 Ok(())
149 }
150}