manta_server/service/
group.rs1use manta_backend_dispatcher::error::Error;
4use manta_backend_dispatcher::interfaces::hsm::group::GroupTrait;
5use manta_backend_dispatcher::types::Group;
6
7use crate::server::common;
8use crate::server::common::app_context::InfraContext;
9use crate::server::common::authorization::get_groups_names_available;
10pub use manta_shared::shared::params::group::GetGroupParams;
11
12pub async fn get_available_group_names(
17 infra: &InfraContext<'_>,
18 token: &str,
19) -> Result<Vec<String>, Error> {
20 infra.backend.get_group_name_available(token).await
21}
22
23pub async fn get_all_groups(
29 infra: &InfraContext<'_>,
30 token: &str,
31) -> Result<Vec<Group>, Error> {
32 infra.backend.get_all_groups(token).await
33}
34
35pub async fn validate_hsm_group_access(
42 infra: &InfraContext<'_>,
43 token: &str,
44 group_name: &str,
45) -> Result<(), Error> {
46 let accessible = infra.backend.get_group_name_available(token).await?;
47 if !accessible.iter().any(|name| name == group_name) {
48 let mut accessible = accessible;
49 accessible.sort();
50 return Err(Error::BadRequest(format!(
51 "Can't access HSM group '{}'.\nPlease choose one from the list below:\n{}",
52 group_name,
53 accessible.join(", ")
54 )));
55 }
56 Ok(())
57}
58
59pub async fn get_groups(
61 infra: &InfraContext<'_>,
62 token: &str,
63 params: &GetGroupParams,
64) -> Result<Vec<Group>, Error> {
65 let target_hsm_group_vec = get_groups_names_available(
66 infra.backend,
67 token,
68 params.group_name.as_deref(),
69 params.settings_hsm_group_name.as_deref(),
70 )
71 .await?;
72
73 infra
74 .backend
75 .get_groups(token, Some(&target_hsm_group_vec))
76 .await
77}
78
79pub async fn validate_group_deletion(
81 infra: &InfraContext<'_>,
82 token: &str,
83 label: &str,
84) -> Result<(), Error> {
85 let xname_vec = infra
86 .backend
87 .get_member_vec_from_group_name_vec(token, &[label.to_string()])
88 .await?;
89
90 let xname_vec: Vec<&str> = xname_vec.iter().map(String::as_str).collect();
91
92 let mut xname_map = infra
93 .backend
94 .get_group_map_and_filter_by_group_vec(token, &xname_vec)
95 .await?;
96
97 xname_map.retain(|_xname, group_name_vec| {
98 group_name_vec.len() == 1
99 && group_name_vec.first().is_some_and(|name| name == label)
100 });
101
102 let mut members_orphan_if_group_deleted: Vec<String> =
103 xname_map.into_keys().collect();
104 members_orphan_if_group_deleted.sort();
105
106 if !members_orphan_if_group_deleted.is_empty() {
107 return Err(Error::Conflict(format!(
108 "The hosts below will become orphan if group '{}' gets deleted: {}",
109 label,
110 members_orphan_if_group_deleted.join(", ")
111 )));
112 }
113
114 Ok(())
115}
116
117pub async fn delete_group(
119 infra: &InfraContext<'_>,
120 token: &str,
121 label: &str,
122 force: bool,
123) -> Result<(), Error> {
124 if !force {
125 validate_group_deletion(infra, token, label).await?;
126 }
127 infra.backend.delete_group(token, label).await.map(|_| ())
128}
129
130pub async fn create_group(
132 infra: &InfraContext<'_>,
133 token: &str,
134 group: Group,
135) -> Result<(), Error> {
136 infra.backend.add_group(token, group).await.map(|_| ())
137}
138
139pub async fn add_nodes_to_group(
144 infra: &InfraContext<'_>,
145 token: &str,
146 target_hsm_name: &str,
147 hosts_expression: &str,
148) -> Result<(Vec<String>, Vec<String>), Error> {
149 let xname_to_move_vec = common::node_ops::resolve_hosts_expression(
150 infra.backend,
151 token,
152 hosts_expression,
153 false,
154 )
155 .await?;
156
157 if xname_to_move_vec.is_empty() {
158 return Err(Error::BadRequest(
159 "The list of nodes to move is empty. Nothing to do".to_string(),
160 ));
161 }
162
163 if infra
164 .backend
165 .get_group(token, target_hsm_name)
166 .await
167 .is_err()
168 {
169 return Err(Error::NotFound(format!(
170 "Target HSM group '{target_hsm_name}' does not exist"
171 )));
172 }
173
174 let xnames_to_move: Vec<&str> =
175 xname_to_move_vec.iter().map(String::as_str).collect();
176
177 let mut updated_members = infra
178 .backend
179 .add_members_to_group(token, target_hsm_name, &xnames_to_move)
180 .await?;
181
182 updated_members.sort();
183
184 Ok((xname_to_move_vec, updated_members))
185}