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