bios_basic/spi/serv/
spi_bs_serv.rs

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            // SPI backend service is a global scope, and the permission is determined by its own binding relationship
56            //
57            // SPI后端服务都为全局作用域,通过自身的绑定关系判定权限
58            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        // Add certificate information
73        // 添加认证信息
74        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}