1use async_trait::async_trait;
2use bios_basic::rbum::{
3 dto::rbum_filer_dto::RbumBasicFilterReq,
4 serv::rbum_crud_serv::{RbumCrudOperation, RbumCrudQueryPackage},
5};
6use tardis::{
7 basic::{dto::TardisContext, result::TardisResult},
8 db::{
9 reldb_client::IdResp,
10 sea_orm::{sea_query::*, EntityName, Set},
11 },
12 TardisFuns, TardisFunsInst,
13};
14
15use crate::{
16 basic::{
17 domain::iam_config,
18 dto::{
19 iam_config_dto::{IamConfigAddReq, IamConfigAggOrModifyReq, IamConfigDetailResp, IamConfigModifyReq, IamConfigSummaryResp},
20 iam_filer_dto::IamConfigFilterReq,
21 },
22 },
23 iam_enumeration::IamConfigKind,
24};
25
26use super::clients::iam_log_client::{IamLogClient, LogParamTag};
27
28pub struct IamConfigServ;
29
30#[async_trait]
31impl RbumCrudOperation<iam_config::ActiveModel, IamConfigAddReq, IamConfigModifyReq, IamConfigSummaryResp, IamConfigDetailResp, IamConfigFilterReq> for IamConfigServ {
32 fn get_table_name() -> &'static str {
33 iam_config::Entity.table_name()
34 }
35
36 async fn package_add(add_req: &IamConfigAddReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<iam_config::ActiveModel> {
37 Ok(iam_config::ActiveModel {
38 id: Set(TardisFuns::field.nanoid()),
39 code: Set(add_req.code.to_string()),
40 name: Set(add_req.name.as_ref().unwrap_or(&"".to_string()).to_string()),
41 note: Set(add_req.note.as_ref().unwrap_or(&"".to_string()).to_string()),
42 value1: Set(add_req.value1.as_ref().unwrap_or(&"".to_string()).to_string()),
43 value2: Set(add_req.value2.as_ref().unwrap_or(&"".to_string()).to_string()),
44 ext: Set(add_req.ext.as_ref().unwrap_or(&"".to_string()).to_string()),
45 rel_item_id: Set(add_req.rel_item_id.to_string()),
46 disabled: Set(add_req.disabled.unwrap_or(false)),
47 data_type: Set(add_req.data_type.to_string()),
48 ..Default::default()
49 })
50 }
51
52 async fn before_add_rbum(add_req: &mut IamConfigAddReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> {
53 if Self::config_exist(&add_req.code, &add_req.rel_item_id, funs, ctx).await? {
54 return Err(funs.err().conflict(
55 Self::get_table_name(),
56 "add",
57 &format!("{}.{} config already exists", add_req.code, add_req.rel_item_id),
58 "409-iam-config-exist",
59 ));
60 }
61 Ok(())
62 }
63
64 async fn package_modify(id: &str, modify_req: &IamConfigModifyReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<iam_config::ActiveModel> {
65 let mut iam_config = iam_config::ActiveModel {
66 id: Set(id.to_string()),
67 ..Default::default()
68 };
69 if let Some(name) = &modify_req.name {
70 iam_config.name = Set(name.to_string());
71 }
72 if let Some(data_type) = &modify_req.data_type {
73 iam_config.data_type = Set(data_type.to_string());
74 }
75 if let Some(note) = &modify_req.note {
76 iam_config.note = Set(note.to_string());
77 }
78 if let Some(value1) = &modify_req.value1 {
79 iam_config.value1 = Set(value1.to_string());
80 }
81 if let Some(value2) = &modify_req.value2 {
82 iam_config.value2 = Set(value2.to_string());
83 }
84 if let Some(ext) = &modify_req.ext {
85 iam_config.ext = Set(ext.to_string());
86 }
87 if let Some(disabled) = &modify_req.disabled {
88 iam_config.disabled = Set(*disabled);
89 }
90 Ok(iam_config)
91 }
92
93 async fn package_query(is_detail: bool, filter: &IamConfigFilterReq, _: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<SelectStatement> {
94 let mut query = Query::select();
95 query
96 .columns(vec![
97 (iam_config::Entity, iam_config::Column::Id),
98 (iam_config::Entity, iam_config::Column::Code),
99 (iam_config::Entity, iam_config::Column::Name),
100 (iam_config::Entity, iam_config::Column::Note),
101 (iam_config::Entity, iam_config::Column::Value1),
102 (iam_config::Entity, iam_config::Column::Value2),
103 (iam_config::Entity, iam_config::Column::Ext),
104 (iam_config::Entity, iam_config::Column::Disabled),
105 (iam_config::Entity, iam_config::Column::DataType),
106 (iam_config::Entity, iam_config::Column::RelItemId),
107 (iam_config::Entity, iam_config::Column::OwnPaths),
108 (iam_config::Entity, iam_config::Column::Owner),
109 (iam_config::Entity, iam_config::Column::CreateTime),
110 (iam_config::Entity, iam_config::Column::UpdateTime),
111 ])
112 .from(iam_config::Entity);
113 if let Some(code) = &filter.code {
114 query.and_where(Expr::col(iam_config::Column::Code).eq(code));
115 }
116 if let Some(rel_item_id) = &filter.rel_item_id {
117 query.and_where(Expr::col(iam_config::Column::RelItemId).eq(rel_item_id));
118 }
119 if let Some(disabled) = &filter.disabled {
120 query.and_where(Expr::col(iam_config::Column::Disabled).eq(*disabled));
121 }
122 query.with_filter(Self::get_table_name(), &filter.basic, is_detail, false, ctx);
123 Ok(query)
124 }
125}
126
127impl IamConfigServ {
128 pub async fn add_or_modify_batch(rel_item_id: &str, reqs: Vec<IamConfigAggOrModifyReq>, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> {
129 for config in reqs {
130 let config_id = Self::get_config_id_by_code_and_item_id(&config.code, rel_item_id, funs).await?;
131 let (op_describe, op_kind) = match &config.code {
132 IamConfigKind::AccountInactivityLock => (
133 format!("设置{}个月未使用的账号进行锁定或将其转为休眠账号", config.value1.clone().unwrap_or(0.to_string())),
134 "SetUpUnusedAccountsToLock".to_string(),
135 ),
136 IamConfigKind::TokenExpire => (
137 format!("设置{}分钟不活动则会话失效", config.value1.clone().unwrap_or(0.to_string())),
138 "SetUpSessionInvalidation".to_string(),
139 ),
140 IamConfigKind::AccountTemporaryExpire => (
141 format!("设置临时账号使用期限为{}个月", config.value1.clone().unwrap_or(0.to_string())),
142 "SetUpUnusedAccountsToLock".to_string(),
143 ),
144 _ => ("".to_string(), "".to_string()),
145 };
146 if !op_describe.is_empty() {
147 let _ = IamLogClient::add_ctx_task(LogParamTag::SecurityAlarm, None, op_describe, Some(op_kind), ctx).await;
148 }
149 if let Some(id) = config_id {
150 Self::modify_rbum(
151 &id,
152 &mut IamConfigModifyReq {
153 name: config.name,
154 data_type: Some(config.data_type),
155 note: config.note,
156 value1: config.value1,
157 value2: config.value2,
158 ext: config.ext,
159 disabled: config.disabled,
160 },
161 funs,
162 ctx,
163 )
164 .await?;
165 } else {
166 Self::add_rbum(
167 &mut IamConfigAddReq {
168 code: config.code,
169 name: config.name,
170 data_type: config.data_type,
171 note: config.note,
172 value1: config.value1,
173 value2: config.value2,
174 ext: config.ext,
175 disabled: config.disabled,
176 rel_item_id: rel_item_id.to_string(),
177 },
178 funs,
179 ctx,
180 )
181 .await?;
182 }
183 }
184 Ok(())
185 }
186
187 pub async fn get_config_by_code_and_item_id(code: &IamConfigKind, rel_item_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<Option<IamConfigSummaryResp>> {
188 if let Some(config_id) = Self::get_config_id_by_code_and_item_id(code, rel_item_id, funs).await? {
189 let resp = Self::peek_rbum(
190 &config_id,
191 &IamConfigFilterReq {
192 basic: RbumBasicFilterReq {
193 own_paths: Some("".to_string()),
194 with_sub_own_paths: true,
195 ..Default::default()
196 },
197 ..Default::default()
198 },
199 funs,
200 ctx,
201 )
202 .await?;
203 Ok(Some(resp))
204 } else {
205 Ok(None)
206 }
207 }
208
209 pub async fn get_config_id_by_code_and_item_id(code: &IamConfigKind, rel_item_id: &str, funs: &TardisFunsInst) -> TardisResult<Option<String>> {
210 let resp = funs
211 .db()
212 .get_dto::<IdResp>(
213 Query::select()
214 .column(iam_config::Column::Id)
215 .from(iam_config::Entity)
216 .and_where(Expr::col(iam_config::Column::Code).eq(code.to_string()))
217 .and_where(Expr::col(iam_config::Column::RelItemId).eq(rel_item_id)),
218 )
219 .await?
220 .map(|r| r.id);
221 Ok(resp)
222 }
223
224 pub async fn config_exist(code: &IamConfigKind, rel_item_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<bool> {
225 Self::exist_rbum(
226 &IamConfigFilterReq {
227 code: Some(code.to_string()),
228 rel_item_id: Some(rel_item_id.to_string()),
229 ..Default::default()
230 },
231 funs,
232 ctx,
233 )
234 .await
235 }
236}