1use itertools::Itertools;
2use tardis::basic::error::TardisError;
3use tardis::futures::future::join_all;
4use tardis::web::context_extractor::TardisContextExtractor;
5use tardis::web::poem::Request;
6use tardis::web::poem_openapi;
7use tardis::web::poem_openapi::{param::Path, param::Query, payload::Json};
8use tardis::web::web_resp::{TardisApiResult, TardisPage, TardisResp, Void};
9
10use bios_basic::helper::request_helper::try_set_real_ip_from_req_to_ctx;
11use bios_basic::process::task_processor::TaskProcessor;
12use bios_basic::rbum::dto::rbum_filer_dto::{RbumBasicFilterReq, RbumItemRelFilterReq};
13use bios_basic::rbum::dto::rbum_rel_dto::RbumRelBoneResp;
14use bios_basic::rbum::rbum_enumeration::RbumRelFromKind;
15use bios_basic::rbum::serv::rbum_item_serv::RbumItemCrudOperation;
16
17use crate::basic::dto::iam_filer_dto::{IamAccountFilterReq, IamRoleFilterReq};
18use crate::basic::dto::iam_role_dto::{IamRoleAggAddReq, IamRoleAggCopyReq, IamRoleAggModifyReq, IamRoleDetailResp, IamRoleSummaryResp};
19use crate::basic::serv::iam_account_serv::IamAccountServ;
20use crate::basic::serv::iam_app_serv::IamAppServ;
21use crate::basic::serv::iam_role_serv::IamRoleServ;
22use crate::iam_constants;
23use crate::iam_constants::RBUM_SCOPE_LEVEL_APP;
24use crate::iam_enumeration::{IamRelKind, IamRoleKind};
25
26#[derive(Clone, Default)]
27pub struct IamCaRoleApi;
28
29#[poem_openapi::OpenApi(prefix_path = "/ca/role", tag = "bios_basic::ApiTag::App")]
32impl IamCaRoleApi {
33 #[oai(path = "/", method = "post")]
36 async fn add(&self, mut add_req: Json<IamRoleAggAddReq>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<String> {
37 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
38 let mut funs = iam_constants::get_tardis_inst();
39 funs.begin().await?;
40 add_req.0.role.kind = Some(IamRoleKind::App);
41 let result = IamRoleServ::add_role_agg(&mut add_req.0, &funs, &ctx.0).await?;
42 funs.commit().await?;
43 ctx.0.execute_task().await?;
44 TardisResp::ok(result)
45 }
46
47 #[oai(path = "/copy", method = "post")]
50 async fn copy(&self, mut copy_req: Json<IamRoleAggCopyReq>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<String> {
51 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
52 let mut funs = iam_constants::get_tardis_inst();
53 funs.begin().await?;
54 copy_req.0.role.kind = Some(IamRoleKind::App);
55 let result = IamRoleServ::copy_role_agg(&mut copy_req.0, &funs, &ctx.0).await?;
56 funs.commit().await?;
57 ctx.0.execute_task().await?;
58 TardisResp::ok(result)
59 }
60
61 #[oai(path = "/:id", method = "put")]
67 async fn modify(&self, id: Path<String>, mut modify_req: Json<IamRoleAggModifyReq>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<Option<String>> {
68 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
69 let mut funs = iam_constants::get_tardis_inst();
70 funs.begin().await?;
71 IamRoleServ::modify_role_agg(&id.0, &mut modify_req.0, &funs, &ctx.0).await?;
72 funs.commit().await?;
73 ctx.0.execute_task().await?;
74 if let Some(task_id) = TaskProcessor::get_task_id_with_ctx(&ctx.0).await? {
75 TardisResp::accepted(Some(task_id))
76 } else {
77 TardisResp::ok(None)
78 }
79 }
80
81 #[oai(path = "/:id", method = "get")]
84 async fn get(&self, id: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<IamRoleDetailResp> {
85 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
86 let funs = iam_constants::get_tardis_inst();
87 let result = IamRoleServ::get_item(
88 &id.0,
89 &IamRoleFilterReq {
90 basic: RbumBasicFilterReq { ..Default::default() },
91 kind: Some(IamRoleKind::App),
93 ..Default::default()
94 },
95 &funs,
96 &ctx.0,
97 )
98 .await?;
99 ctx.0.execute_task().await?;
100 TardisResp::ok(result)
101 }
102
103 #[oai(path = "/", method = "get")]
106 async fn paginate(
107 &self,
108 id: Query<Option<String>>,
109 name: Query<Option<String>>,
110 in_base: Query<Option<bool>>,
111 in_embed: Query<Option<bool>>,
112 extend_role_id: Query<Option<String>>,
113 page_number: Query<u32>,
114 page_size: Query<u32>,
115 desc_by_create: Query<Option<bool>>,
116 desc_by_update: Query<Option<bool>>,
117 ctx: TardisContextExtractor,
118 request: &Request,
119 ) -> TardisApiResult<TardisPage<IamRoleSummaryResp>> {
120 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
121 let funs = iam_constants::get_tardis_inst();
122 let result = IamRoleServ::paginate_items(
123 &IamRoleFilterReq {
124 basic: RbumBasicFilterReq {
125 ids: id.0.map(|id| vec![id]),
128 name: name.0,
129 ..Default::default()
130 },
131 kind: Some(IamRoleKind::App),
132 in_base: in_base.0,
133 in_embed: in_embed.0,
134 extend_role_id: extend_role_id.0,
135 ..Default::default()
136 },
137 page_number.0,
138 page_size.0,
139 desc_by_create.0,
140 desc_by_update.0,
141 &funs,
142 &ctx.0,
143 )
144 .await?;
145 ctx.0.execute_task().await?;
146 TardisResp::ok(result)
147 }
148
149 #[oai(path = "/:id", method = "delete")]
152 async fn delete(&self, id: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<Option<String>> {
153 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
154 let mut funs = iam_constants::get_tardis_inst();
155 funs.begin().await?;
156 let app_role = IamRoleServ::get_item(
157 &id.0,
158 &IamRoleFilterReq {
159 basic: RbumBasicFilterReq {
160 with_sub_own_paths: true,
161 ..Default::default()
162 },
163 ..Default::default()
164 },
165 &funs,
166 &ctx.0,
167 )
168 .await?;
169 if app_role.kind != IamRoleKind::App {
170 Err(funs.err().conflict(
171 &IamRoleServ::get_obj_name(),
172 "delete",
173 "This role is not an app role, cannot be deleted",
174 "409-role-is-not-app",
175 ))?;
176 }
177 if app_role.extend_role_id != *"" {
178 Err(funs.err().conflict(&IamRoleServ::get_obj_name(), "delete", "This role is extend role, cannot be deleted", "409-role-is-extend"))?;
179 }
180 IamRoleServ::delete_item_with_all_rels(&id.0, &funs, &ctx.0).await?;
181 funs.commit().await?;
182 ctx.0.execute_task().await?;
183 if let Some(task_id) = TaskProcessor::get_task_id_with_ctx(&ctx.0).await? {
184 TardisResp::accepted(Some(task_id))
185 } else {
186 TardisResp::ok(None)
187 }
188 }
189
190 #[oai(path = "/:id/account/:account_id", method = "put")]
193 async fn add_rel_account(&self, id: Path<String>, account_id: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<Void> {
194 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
195 let mut funs = iam_constants::get_tardis_inst();
196 funs.begin().await?;
197 let app_id = IamAppServ::get_id_by_ctx(&ctx.0, &funs)?;
198 IamAppServ::add_rel_account(&app_id, &account_id.0, true, &funs, &ctx.0).await?;
199 IamRoleServ::add_rel_account(&id.0, &account_id.0, Some(RBUM_SCOPE_LEVEL_APP), &funs, &ctx.0).await?;
200 funs.commit().await?;
201 ctx.0.execute_task().await?;
202 TardisResp::ok(Void {})
203 }
204
205 #[oai(path = "/:id/account/batch/:account_ids", method = "put")]
208 async fn batch_add_rel_account(&self, id: Path<String>, account_ids: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<Void> {
209 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
210 let mut funs = iam_constants::get_tardis_inst();
211 funs.begin().await?;
212 let app_id = IamAppServ::get_id_by_ctx(&ctx.0, &funs)?;
213 join_all(
215 account_ids
216 .0
217 .split(',')
218 .map(|account_id| async {
219 IamAppServ::add_rel_account(&app_id, account_id, true, &funs, &ctx.0).await?;
220 IamRoleServ::add_rel_account(&id.0, account_id, Some(RBUM_SCOPE_LEVEL_APP), &funs, &ctx.0).await
221 })
222 .collect_vec(),
223 )
224 .await
225 .into_iter()
226 .collect::<Result<Vec<()>, TardisError>>()?;
227 funs.commit().await?;
232 ctx.0.execute_task().await?;
233 TardisResp::ok(Void {})
234 }
235
236 #[oai(path = "/:id/account/:account_id", method = "delete")]
239 async fn delete_rel_account(&self, id: Path<String>, account_id: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<Void> {
240 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
241 let mut funs = iam_constants::get_tardis_inst();
242 funs.begin().await?;
243 IamRoleServ::delete_rel_account(&id.0, &account_id.0, Some(RBUM_SCOPE_LEVEL_APP), &funs, &ctx.0).await?;
244 funs.commit().await?;
245 ctx.0.execute_task().await?;
246 TardisResp::ok(Void {})
247 }
248
249 #[oai(path = "/:id/account/batch/:account_ids", method = "delete")]
252 async fn batch_delete_rel_account(&self, id: Path<String>, account_ids: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<Void> {
253 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
254 let mut funs = iam_constants::get_tardis_inst();
255 funs.begin().await?;
256 let split = account_ids.0.split(',').collect::<Vec<_>>();
257 for s in split {
258 IamRoleServ::delete_rel_account(&id.0, s, Some(RBUM_SCOPE_LEVEL_APP), &funs, &ctx.0).await?;
259 }
260 funs.commit().await?;
261 ctx.0.execute_task().await?;
262 TardisResp::ok(Void {})
263 }
264
265 #[oai(path = "/:id/account/total", method = "get")]
268 async fn count_rel_accounts(&self, id: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<u64> {
269 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
270 let funs = iam_constants::get_tardis_inst();
271 let result = IamAccountServ::count_items(
272 &IamAccountFilterReq {
273 rel: IamAppServ::with_app_rel_filter(&ctx.0, &funs)?,
274 rel2: Some(RbumItemRelFilterReq {
275 rel_by_from: true,
276 tag: Some(IamRelKind::IamAccountRole.to_string()),
277 from_rbum_kind: Some(RbumRelFromKind::Item),
278 rel_item_id: Some(id.0.to_string()),
279 ..Default::default()
280 }),
281 ..Default::default()
282 },
283 &funs,
284 &ctx.0,
285 )
286 .await?;
287 ctx.0.execute_task().await?;
288 TardisResp::ok(result)
289 }
290
291 #[oai(path = "/:id/res/:res_id", method = "put")]
294 async fn add_rel_res(&self, id: Path<String>, res_id: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<Void> {
295 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
296 let mut funs = iam_constants::get_tardis_inst();
297 funs.begin().await?;
298 IamRoleServ::add_rel_res(&id.0, &res_id.0, &funs, &ctx.0).await?;
299 funs.commit().await?;
300 ctx.0.execute_task().await?;
301 TardisResp::ok(Void {})
302 }
303
304 #[oai(path = "/:id/res/:res_id", method = "delete")]
307 async fn delete_rel_res(&self, id: Path<String>, res_id: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<Void> {
308 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
309 let mut funs = iam_constants::get_tardis_inst();
310 funs.begin().await?;
311 IamRoleServ::delete_rel_res(&id.0, &res_id.0, &funs, &ctx.0).await?;
312 funs.commit().await?;
313 ctx.0.execute_task().await?;
314 TardisResp::ok(Void {})
315 }
316
317 #[oai(path = "/:id/res/total", method = "get")]
320 async fn count_rel_res(&self, id: Path<String>, ctx: TardisContextExtractor, request: &Request) -> TardisApiResult<u64> {
321 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
322 let funs = iam_constants::get_tardis_inst();
323 let result = IamRoleServ::count_rel_res(&id.0, &funs, &ctx.0).await?;
324 ctx.0.execute_task().await?;
325 TardisResp::ok(result)
326 }
327
328 #[oai(path = "/:id/res", method = "get")]
331 async fn find_rel_res(
332 &self,
333 id: Path<String>,
334 desc_by_create: Query<Option<bool>>,
335 desc_by_update: Query<Option<bool>>,
336 ctx: TardisContextExtractor,
337 request: &Request,
338 ) -> TardisApiResult<Vec<RbumRelBoneResp>> {
339 try_set_real_ip_from_req_to_ctx(request, &ctx.0).await?;
340 let funs = iam_constants::get_tardis_inst();
341 let result = IamRoleServ::find_simple_rel_res(&id.0, desc_by_create.0, desc_by_update.0, &funs, &ctx.0).await?;
342 ctx.0.execute_task().await?;
343 TardisResp::ok(result)
344 }
345}