1use async_trait::async_trait;
2use tardis::{
3 basic::{dto::TardisContext, result::TardisResult},
4 db::sea_orm::{sea_query::*, EntityName, Set},
5 TardisFunsInst,
6};
7
8use crate::{
9 rbum::{
10 domain::{rbum_cert, rbum_domain, rbum_item, rbum_kind},
11 dto::{
12 rbum_cert_dto::{RbumCertAddReq, RbumCertModifyReq},
13 rbum_filer_dto::{RbumBasicFilterReq, RbumCertFilterReq, RbumItemRelFilterReq, RbumRelFilterReq},
14 rbum_item_dto::{RbumItemKernelAddReq, RbumItemKernelModifyReq},
15 rbum_rel_agg_dto::{RbumRelAggAddReq, RbumRelAttrAggAddReq, RbumRelEnvAggAddReq},
16 rbum_rel_dto::{RbumRelAddReq, RbumRelSimpleFindReq},
17 },
18 rbum_enumeration::{RbumCertRelKind, RbumCertStatusKind, RbumRelFromKind, RbumScopeLevelKind},
19 serv::{
20 rbum_cert_serv::RbumCertServ, rbum_crud_serv::RbumCrudOperation, rbum_domain_serv::RbumDomainServ, rbum_item_serv::RbumItemCrudOperation, rbum_rel_serv::RbumRelServ,
21 },
22 },
23 spi::{
24 domain::spi_bs,
25 dto::spi_bs_dto::{SpiBsAddReq, SpiBsCertResp, SpiBsDetailResp, SpiBsFilterReq, SpiBsModifyReq, SpiBsSummaryResp},
26 spi_constants::{SPI_CERT_KIND, SPI_IDENT_REL_TAG},
27 },
28};
29
30pub struct SpiBsServ;
31
32#[async_trait]
33impl RbumItemCrudOperation<spi_bs::ActiveModel, SpiBsAddReq, SpiBsModifyReq, SpiBsSummaryResp, SpiBsSummaryResp, SpiBsFilterReq> for SpiBsServ {
34 fn get_ext_table_name() -> &'static str {
35 spi_bs::Entity.table_name()
36 }
37
38 fn get_rbum_kind_id() -> Option<String> {
39 None
40 }
41
42 fn get_rbum_domain_id() -> Option<String> {
43 None
44 }
45
46 async fn package_item_add(add_req: &SpiBsAddReq, funs: &TardisFunsInst, _: &TardisContext) -> TardisResult<RbumItemKernelAddReq> {
47 let domain_id = RbumDomainServ::get_rbum_domain_id_by_code(funs.module_code(), funs)
48 .await?
49 .ok_or_else(|| funs.err().not_found(&Self::get_obj_name(), "add_bs", "not found domain", "404-rbum-*-obj-not-exist"))?;
50 Ok(RbumItemKernelAddReq {
51 name: add_req.name.clone(),
52 rel_rbum_kind_id: Some(add_req.kind_id.to_string()),
53 rel_rbum_domain_id: Some(domain_id),
54 disabled: add_req.disabled,
55 scope_level: Some(RbumScopeLevelKind::Root),
59 ..Default::default()
60 })
61 }
62
63 async fn package_ext_add(id: &str, add_req: &SpiBsAddReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<spi_bs::ActiveModel> {
64 Ok(spi_bs::ActiveModel {
65 id: Set(id.to_string()),
66 private: Set(add_req.private),
67 ..Default::default()
68 })
69 }
70
71 async fn after_add_item(id: &str, add_req: &mut SpiBsAddReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> {
72 RbumCertServ::add_rbum(
75 &mut RbumCertAddReq {
76 ak: add_req.ak.clone(),
77 sk: Some(add_req.sk.clone()),
78 sk_invisible: Some(false),
79 kind: Some(SPI_CERT_KIND.to_string()),
80 supplier: Some(id.to_string()),
81 conn_uri: Some(add_req.conn_uri.clone()),
82 ext: Some(add_req.ext.clone()),
83 rel_rbum_kind: RbumCertRelKind::Item,
84 rel_rbum_id: id.to_string(),
85 status: RbumCertStatusKind::Enabled,
86 vcode: None,
87 rel_rbum_cert_conf_id: None,
88 start_time: None,
89 end_time: None,
90 is_outside: false,
91 ignore_check_sk: false,
92 },
93 funs,
94 ctx,
95 )
96 .await?;
97 Ok(())
98 }
99
100 async fn package_item_modify(_: &str, modify_req: &SpiBsModifyReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<Option<RbumItemKernelModifyReq>> {
101 if modify_req.name.is_none() && modify_req.disabled.is_none() {
102 return Ok(None);
103 }
104 Ok(Some(RbumItemKernelModifyReq {
105 code: None,
106 name: modify_req.name.clone(),
107 scope_level: None,
108 disabled: modify_req.disabled,
109 }))
110 }
111
112 async fn package_ext_modify(id: &str, modify_req: &SpiBsModifyReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<Option<spi_bs::ActiveModel>> {
113 if modify_req.private.is_none() {
114 return Ok(None);
115 }
116 let mut spi_bs = spi_bs::ActiveModel {
117 id: Set(id.to_string()),
118 ..Default::default()
119 };
120 if let Some(private) = modify_req.private {
121 spi_bs.private = Set(private);
122 }
123 Ok(Some(spi_bs))
124 }
125
126 async fn after_modify_item(id: &str, modify_req: &mut SpiBsModifyReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> {
127 if let Some(cert) = RbumCertServ::find_one_rbum(
128 &RbumCertFilterReq {
129 kind: Some(SPI_CERT_KIND.to_string()),
130 suppliers: Some(vec![id.to_string()]),
131 rel_rbum_kind: Some(RbumCertRelKind::Item),
132 rel_rbum_id: Some(id.to_string()),
133 ..Default::default()
134 },
135 funs,
136 ctx,
137 )
138 .await?
139 {
140 RbumCertServ::modify_rbum(
141 &cert.id,
142 &mut RbumCertModifyReq {
143 ak: modify_req.ak.clone(),
144 sk: modify_req.sk.clone(),
145 ignore_check_sk: false,
146 conn_uri: modify_req.conn_uri.clone(),
147 ext: modify_req.ext.clone(),
148 status: None,
149 start_time: None,
150 end_time: None,
151 sk_invisible: None,
152 },
153 funs,
154 ctx,
155 )
156 .await?;
157 }
158 Ok(())
159 }
160
161 async fn package_ext_query(query: &mut SelectStatement, _: bool, filter: &SpiBsFilterReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<()> {
162 query
163 .column((spi_bs::Entity, spi_bs::Column::Private))
164 .expr_as(Expr::col((rbum_kind::Entity, rbum_kind::Column::Id)), Alias::new("kind_id"))
165 .expr_as(Expr::col((rbum_kind::Entity, rbum_kind::Column::Code)), Alias::new("kind_code"))
166 .expr_as(Expr::col((rbum_kind::Entity, rbum_kind::Column::Name)), Alias::new("kind_name"))
167 .column((rbum_cert::Entity, rbum_cert::Column::ConnUri))
168 .column((rbum_cert::Entity, rbum_cert::Column::Ak))
169 .column((rbum_cert::Entity, rbum_cert::Column::Sk))
170 .column((rbum_cert::Entity, rbum_cert::Column::SkInvisible))
171 .column((rbum_cert::Entity, rbum_cert::Column::Ext))
172 .left_join(
173 rbum_kind::Entity,
174 Expr::col((rbum_kind::Entity, rbum_kind::Column::Id)).equals((rbum_item::Entity, rbum_item::Column::RelRbumKindId)),
175 )
176 .left_join(
177 rbum_cert::Entity,
178 Condition::all()
179 .add(Expr::col((rbum_cert::Entity, rbum_cert::Column::Kind)).eq(SPI_CERT_KIND))
180 .add(Expr::col((rbum_cert::Entity, rbum_cert::Column::RelRbumKind)).eq(RbumCertRelKind::Item.to_int()))
181 .add(Expr::col((rbum_cert::Entity, rbum_cert::Column::Supplier)).equals((spi_bs::Entity, spi_bs::Column::Id)))
182 .add(Expr::col((rbum_cert::Entity, rbum_cert::Column::RelRbumId)).equals((spi_bs::Entity, spi_bs::Column::Id))),
183 );
184 if let Some(private) = filter.private {
185 query.and_where(Expr::col((spi_bs::Entity, spi_bs::Column::Private)).eq(private));
186 }
187 if let Some(kind_code) = &filter.kind_code {
188 query.and_where(Expr::col((rbum_kind::Entity, rbum_kind::Column::Code)).eq(kind_code.to_string()));
189 }
190 if let Some(kind_codes) = &filter.kind_codes {
191 if kind_codes.len() == 1 {
192 query.and_where(Expr::col((rbum_kind::Entity, rbum_kind::Column::Code)).eq(kind_codes.first().expect("ignore").to_string()));
193 } else if !kind_codes.is_empty() {
194 query.and_where(Expr::col((rbum_kind::Entity, rbum_kind::Column::Code)).is_in(kind_codes));
195 }
196 }
197 if let Some(kind_id) = &filter.kind_id {
198 query.and_where(Expr::col((rbum_kind::Entity, rbum_kind::Column::Id)).eq(kind_id.to_string()));
199 }
200 if let Some(domain_code) = &filter.domain_code {
201 query.left_join(
202 rbum_domain::Entity,
203 Expr::col((rbum_domain::Entity, rbum_domain::Column::Id)).equals((rbum_item::Entity, rbum_item::Column::RelRbumDomainId)),
204 );
205 query.and_where(Expr::col((rbum_domain::Entity, rbum_domain::Column::Code)).eq(domain_code.to_string()));
206 }
207 Ok(())
208 }
209}
210
211impl SpiBsServ {
212 pub async fn get_bs(id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<SpiBsDetailResp> {
213 let bs = Self::peek_item(id, &SpiBsFilterReq::default(), funs, ctx).await?;
214 let app_tenant_ids = RbumRelServ::find_rbums(
215 &RbumRelFilterReq {
216 tag: Some(SPI_IDENT_REL_TAG.to_string()),
217 from_rbum_kind: Some(RbumRelFromKind::Item),
218 from_rbum_id: Some(id.to_string()),
219 ..Default::default()
220 },
221 None,
222 None,
223 funs,
224 ctx,
225 )
226 .await?
227 .into_iter()
228 .map(|rel| rel.to_rbum_item_id)
229 .collect::<Vec<String>>();
230 Ok(SpiBsDetailResp {
231 id: bs.id,
232 name: bs.name,
233 kind_id: bs.kind_id,
234 kind_code: bs.kind_code,
235 kind_name: bs.kind_name,
236 conn_uri: bs.conn_uri,
237 ak: bs.ak,
238 sk: bs.sk,
239 ext: bs.ext,
240 private: bs.private,
241 disabled: bs.disabled,
242 create_time: bs.create_time,
243 update_time: bs.update_time,
244 rel_app_tenant_ids: app_tenant_ids,
245 })
246 }
247
248 pub async fn add_rel(bs_id: &str, app_tenant_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> {
249 Self::add_rel_agg(bs_id, app_tenant_id, None, None, funs, ctx).await
250 }
251
252 pub async fn add_rel_agg(
253 bs_id: &str,
254 app_tenant_id: &str,
255 attrs: Option<Vec<RbumRelAttrAggAddReq>>,
256 envs: Option<Vec<RbumRelEnvAggAddReq>>,
257 funs: &TardisFunsInst,
258 ctx: &TardisContext,
259 ) -> TardisResult<()> {
260 if !RbumRelServ::check_simple_rel(
261 &RbumRelSimpleFindReq {
262 tag: Some(SPI_IDENT_REL_TAG.to_string()),
263 from_rbum_kind: Some(RbumRelFromKind::Item),
264 from_rbum_id: Some(bs_id.to_string()),
265 to_rbum_item_id: Some(app_tenant_id.to_string()),
266 ..Default::default()
267 },
268 funs,
269 ctx,
270 )
271 .await?
272 {
273 let attrs = attrs.unwrap_or_default();
274 let envs = envs.unwrap_or_default();
275 RbumRelServ::add_rel(
276 &mut RbumRelAggAddReq {
277 rel: RbumRelAddReq {
278 tag: SPI_IDENT_REL_TAG.to_string(),
279 note: None,
280 from_rbum_kind: RbumRelFromKind::Item,
281 from_rbum_id: bs_id.to_string(),
282 to_rbum_item_id: app_tenant_id.to_string(),
283 to_own_paths: ctx.own_paths.to_string(),
284 to_is_outside: true,
285 ext: None,
286 },
287 attrs,
288 envs,
289 },
290 funs,
291 ctx,
292 )
293 .await?;
294 }
295 Ok(())
296 }
297
298 pub async fn delete_rel(bs_id: &str, app_tenant_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> {
299 let ids = RbumRelServ::find_id_rbums(
300 &RbumRelFilterReq {
301 tag: Some(SPI_IDENT_REL_TAG.to_string()),
302 from_rbum_kind: Some(RbumRelFromKind::Item),
303 from_rbum_id: Some(bs_id.to_string()),
304 to_rbum_item_id: Some(app_tenant_id.to_string()),
305 ..Default::default()
306 },
307 None,
308 None,
309 funs,
310 ctx,
311 )
312 .await?;
313 for id in ids {
314 RbumRelServ::delete_rel_with_ext(&id, funs, ctx).await?;
315 }
316 Ok(())
317 }
318
319 pub async fn get_bs_by_rel(app_tenant_id: &str, kind_code: Option<String>, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<SpiBsCertResp> {
320 let bs = Self::find_one_item(
321 &SpiBsFilterReq {
322 basic: RbumBasicFilterReq {
323 enabled: Some(true),
324 ..Default::default()
325 },
326 rel: Some(RbumItemRelFilterReq {
327 rel_by_from: true,
328 tag: Some(SPI_IDENT_REL_TAG.to_string()),
329 from_rbum_kind: Some(RbumRelFromKind::Item),
330 rel_item_id: Some(app_tenant_id.to_string()),
331 ..Default::default()
332 }),
333 kind_code,
334 domain_code: Some(funs.module_code().to_string()),
335 ..Default::default()
336 },
337 funs,
338 ctx,
339 )
340 .await?
341 .ok_or_else(|| funs.err().not_found(&Self::get_obj_name(), "get_bs_by_rel", "not found backend service", "404-spi-bs-not-exist"))?;
342 Ok(SpiBsCertResp {
343 kind_code: bs.kind_code,
344 conn_uri: bs.conn_uri,
345 ak: bs.ak,
346 sk: bs.sk,
347 ext: bs.ext,
348 private: bs.private,
349 })
350 }
351}