1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
//! [`GroupTrait`] impl for [`StaticBackendDispatcher`].
//!
//! Forwards to HSM's `/apis/smd/hsm/v2/groups` endpoints plus the
//! per-group `/members` subresource. Both CSM and Ochami implement
//! this trait natively.
//!
//! Method names come from the external `manta-backend-dispatcher`
//! crate's `GroupTrait`. Can't be renamed locally; cleaner names
//! would have to land upstream first.
use super::*;
impl GroupTrait for StaticBackendDispatcher {
/// RBAC-filtered group listing: the subset of HSM groups the
/// caller's JWT roles grant access to. Returns full `Group`
/// objects.
async fn get_group_available(
&self,
auth_token: &str,
) -> Result<Vec<Group>, Error> {
dispatch!(self, get_group_available, auth_token)
}
/// RBAC-filtered group listing, names only — faster path used when
/// the caller only needs the group label set (e.g. to validate a
/// filter argument).
async fn get_group_name_available(
&self,
jwt_token: &str,
) -> Result<Vec<String>, Error> {
dispatch!(self, get_group_name_available, jwt_token)
}
/// `POST /groups` — create a group. Returns the persisted group
/// echoed back by HSM.
async fn add_group(
&self,
auth_token: &str,
group_name: Group,
) -> Result<Group, Error> {
dispatch!(self, add_group, auth_token, group_name)
}
/// Union of `/groups/{name}/members` across `group_name_vec`,
/// deduplicated.
async fn get_member_vec_from_group_name_vec(
&self,
auth_token: &str,
group_name_vec: &[String],
) -> Result<Vec<String>, Error> {
dispatch!(
self,
get_member_vec_from_group_name_vec,
auth_token,
group_name_vec
)
}
/// Map of `group_name -> [member xnames]` restricted to the groups
/// named in `group_name_vec`. One HSM call per group plus a
/// merge.
async fn get_group_map_and_filter_by_group_vec(
&self,
auth_token: &str,
group_name_vec: &[&str],
) -> Result<HashMap<String, Vec<String>>, Error> {
dispatch!(
self,
get_group_map_and_filter_by_group_vec,
auth_token,
group_name_vec
)
}
/// Map of `group_name -> [member xnames]` restricted to groups
/// that contain any xname in `member_vec`. The dual of
/// `get_group_map_and_filter_by_group_vec`.
async fn get_group_map_and_filter_by_member_vec(
&self,
auth_token: &str,
member_vec: &[&str],
) -> Result<HashMap<String, Vec<String>>, Error> {
dispatch!(
self,
get_group_map_and_filter_by_member_vec,
auth_token,
member_vec
)
}
/// `GET /groups/{name}` — one group by exact label.
async fn get_group(
&self,
auth_token: &str,
group_name: &str,
) -> Result<Group, Error> {
dispatch!(self, get_group, auth_token, group_name)
}
/// `GET /groups` — every group when `group_name_vec` is `None`,
/// otherwise the named subset.
async fn get_groups(
&self,
auth_token: &str,
group_name_vec: Option<&[String]>,
) -> Result<Vec<Group>, Error> {
dispatch!(self, get_groups, auth_token, group_name_vec)
}
/// `DELETE /groups/{name}`. Returns HSM's action-summary
/// (records affected).
async fn delete_group(
&self,
auth_token: &str,
group_name: &str,
) -> Result<HsmActionResponse, Error> {
dispatch!(self, delete_group, auth_token, group_name)
}
/// Alias for `get_group_map_and_filter_by_group_vec` kept for
/// upstream-trait shape compatibility.
async fn get_group_map_and_filter_by_group_name_vec(
&self,
auth_token: &str,
group_name_vec: &[&str],
) -> Result<HashMap<String, Vec<String>>, Error> {
dispatch!(
self,
get_group_map_and_filter_by_group_name_vec,
auth_token,
group_name_vec
)
}
/// `POST /groups/{name}/members` — add one xname.
async fn post_member(
&self,
auth_token: &str,
group_name: &str,
xname: &str,
) -> Result<HsmActionResponse, Error> {
dispatch!(self, post_member, auth_token, group_name, xname)
}
/// Batched [`post_member`](Self::post_member). Returns the xnames
/// the backend reported as successfully added (some entries may
/// be skipped if already members).
async fn add_members_to_group(
&self,
auth_token: &str,
group_name: &str,
xnames: &[&str],
) -> Result<Vec<String>, Error> {
dispatch!(self, add_members_to_group, auth_token, group_name, xnames)
}
/// `DELETE /groups/{name}/members/{xname}`.
async fn delete_member_from_group(
&self,
auth_token: &str,
group_name: &str,
xname: &str,
) -> Result<(), Error> {
dispatch!(
self,
delete_member_from_group,
auth_token,
group_name,
xname
)
}
/// Move `new_target_group_members` from `parent_group_name` into
/// `target_group_name`. Returns `(added, removed)` xname lists.
/// When `dryrun` the backend computes the diff without mutating
/// either group.
async fn migrate_group_members(
&self,
auth_token: &str,
target_group_name: &str,
parent_group_name: &str,
new_target_group_members: &[&str],
dryrun: bool,
) -> Result<(Vec<String>, Vec<String>), Error> {
dispatch!(
self,
migrate_group_members,
auth_token,
target_group_name,
parent_group_name,
new_target_group_members,
dryrun
)
}
/// In-place edit of a single group's membership — applies
/// `members_to_remove` then `members_to_add` to `group_name` as
/// two HSM calls. Used by the `manta group set-members` path
/// where the caller has pre-computed the diff.
async fn update_group_members(
&self,
auth_token: &str,
group_name: &str,
members_to_remove: &[&str],
members_to_add: &[&str],
) -> Result<(), Error> {
dispatch!(
self,
update_group_members,
auth_token,
group_name,
members_to_remove,
members_to_add
)
}
}