openstack_sdk_identity/v3/role_assignment/list.rs
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// SPDX-License-Identifier: Apache-2.0
14//
15// WARNING: This file is automatically generated from OpenAPI schema using
16// `openstack-codegenerator`.
17
18//! Get a list of role assignments.
19//!
20//! If no query parameters are specified, then this API will return a list of
21//! all role assignments.
22//!
23//! Since this list is likely to be very long, this API would typically always
24//! be used with one of more of the filter queries. Some typical examples are:
25//!
26//! `GET /v3/role_assignments?user.id={user_id}` would list all role
27//! assignments involving the specified user.
28//!
29//! `GET /v3/role_assignments?scope.project.id={project_id}` would list all
30//! role assignments involving the specified project.
31//!
32//! It is also possible to list all role assignments within a tree of projects:
33//! `GET /v3/role_assignments?scope.project.id={project_id}&include_subtree=true`
34//! would list all role assignments involving the specified project and all
35//! sub-projects. `include_subtree=true` can only be specified in conjunction
36//! with `scope.project.id`, specifying it without this will result in an HTTP
37//! 400 Bad Request being returned.
38//!
39//! Each role assignment entity in the collection contains a link to the
40//! assignment that gave rise to this entity.
41//!
42//! The scope section in the list response is extended to allow the
43//! representation of role assignments that are inherited to projects.
44//!
45//! The query filter `scope.OS-INHERIT:inherited_to` can be used to filter
46//! based on role assignments that are inherited. The only value of
47//! `scope.OS-INHERIT:inherited_to` that is currently supported is `projects`,
48//! indicating that this role is inherited to all projects of the owning domain
49//! or parent project.
50//!
51//! If the query parameter `effective` is specified, rather than simply
52//! returning a list of role assignments that have been made, the API returns a
53//! list of effective assignments at the user, project and domain level, having
54//! allowed for the effects of group membership, role inference rules as well
55//! as inheritance from the parent domain or project. Since the effects of
56//! group membership have already been allowed for, the group role assignment
57//! entities themselves will not be returned in the collection. Likewise, since
58//! the effects of inheritance have already been allowed for, the role
59//! assignment entities themselves that specify the inheritance will also not
60//! be returned in the collection. This represents the effective role
61//! assignments that would be included in a scoped token. The same set of query
62//! parameters can also be used in combination with the `effective` parameter.
63//!
64//! For example:
65//!
66//! `GET /v3/role_assignments?user.id={user_id}&effective` would, in other
67//! words, answer the question “what can this user actually do?”.
68//!
69//! `GET /v3/role_assignments?user.id={user_id}&scope.project.id={project_id}&effective`
70//! would return the equivalent set of role assignments that would be included
71//! in the token response of a project scoped token.
72//!
73//! An example response for an API call with the query parameter `effective`
74//! specified is given below:
75//!
76//! The entity `links` section of a response using the `effective` query
77//! parameter also contains, for entities that are included by virtue of group
78//! membership, a url that can be used to access the membership of the group.
79//!
80//! If the query parameter `include_names` is specified, rather than simply
81//! returning the entity IDs in the role assignments, the collection will
82//! additionally include the names of the entities. For example:
83//!
84//! `GET /v3/role_assignments?user.id={user_id}&effective&include_names=true`
85//! would return:
86//!
87//! Relationship:
88//! `https://docs.openstack.org/api/openstack-identity/3/rel/role_assignments`
89//!
90use derive_builder::Builder;
91use http::{HeaderMap, HeaderName, HeaderValue};
92
93use openstack_sdk_core::api::rest_endpoint_prelude::*;
94
95use std::borrow::Cow;
96
97#[derive(Builder, Debug, Clone)]
98#[builder(setter(strip_option))]
99pub struct Request<'a> {
100 #[builder(default, setter(into))]
101 effective: Option<Cow<'a, str>>,
102
103 #[builder(default, setter(into))]
104 group_id: Option<Cow<'a, str>>,
105
106 #[builder(default, setter(into))]
107 include_names: Option<Cow<'a, str>>,
108
109 #[builder(default, setter(into))]
110 include_subtree: Option<Cow<'a, str>>,
111
112 #[builder(default, setter(into))]
113 role_id: Option<Cow<'a, str>>,
114
115 /// The ID of the domain.
116 #[builder(default, setter(into))]
117 scope_domain_id: Option<Cow<'a, str>>,
118
119 #[builder(default, setter(into))]
120 scope_os_inherit_inherited_to: Option<Cow<'a, str>>,
121
122 /// The ID of the project.
123 #[builder(default, setter(into))]
124 scope_project_id: Option<Cow<'a, str>>,
125
126 #[builder(default, setter(into))]
127 scope_system: Option<Cow<'a, str>>,
128
129 /// The ID of the user.
130 #[builder(default, setter(into))]
131 user_id: Option<Cow<'a, str>>,
132
133 #[builder(setter(name = "_headers"), default, private)]
134 _headers: Option<HeaderMap>,
135}
136impl<'a> Request<'a> {
137 /// Create a builder for the endpoint.
138 pub fn builder() -> RequestBuilder<'a> {
139 RequestBuilder::default()
140 }
141}
142
143impl<'a> RequestBuilder<'a> {
144 /// Add a single header to the Role_Assignment.
145 pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
146 where
147 K: Into<HeaderName>,
148 V: Into<HeaderValue>,
149 {
150 self._headers
151 .get_or_insert(None)
152 .get_or_insert_with(HeaderMap::new)
153 .insert(header_name.into(), header_value.into());
154 self
155 }
156
157 /// Add multiple headers.
158 pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
159 where
160 I: Iterator<Item = T>,
161 T: Into<(Option<HeaderName>, HeaderValue)>,
162 {
163 self._headers
164 .get_or_insert(None)
165 .get_or_insert_with(HeaderMap::new)
166 .extend(iter.map(Into::into));
167 self
168 }
169}
170
171impl RestEndpoint for Request<'_> {
172 fn method(&self) -> http::Method {
173 http::Method::GET
174 }
175
176 fn endpoint(&self) -> Cow<'static, str> {
177 "role_assignments".to_string().into()
178 }
179
180 fn parameters(&self) -> QueryParams<'_> {
181 let mut params = QueryParams::default();
182 params.push_opt("effective", self.effective.as_ref());
183 params.push_opt("group.id", self.group_id.as_ref());
184 params.push_opt("include_names", self.include_names.as_ref());
185 params.push_opt("include_subtree", self.include_subtree.as_ref());
186 params.push_opt("role.id", self.role_id.as_ref());
187 params.push_opt(
188 "scope.OS-INHERIT:inherited_to",
189 self.scope_os_inherit_inherited_to.as_ref(),
190 );
191 params.push_opt("scope.domain.id", self.scope_domain_id.as_ref());
192 params.push_opt("scope.project.id", self.scope_project_id.as_ref());
193 params.push_opt("scope.system", self.scope_system.as_ref());
194 params.push_opt("user.id", self.user_id.as_ref());
195
196 params
197 }
198
199 fn service_type(&self) -> ServiceType {
200 ServiceType::Identity
201 }
202
203 fn response_key(&self) -> Option<Cow<'static, str>> {
204 Some("role_assignments".into())
205 }
206
207 /// Returns headers to be set into the request
208 fn request_headers(&self) -> Option<&HeaderMap> {
209 self._headers.as_ref()
210 }
211
212 /// Returns required API version
213 fn api_version(&self) -> Option<ApiVersion> {
214 Some(ApiVersion::new(3, 0))
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221 use http::{HeaderName, HeaderValue};
222 use httpmock::MockServer;
223 #[cfg(feature = "sync")]
224 use openstack_sdk_core::api::Query;
225 use openstack_sdk_core::test::client::FakeOpenStackClient;
226 use openstack_sdk_core::types::ServiceType;
227 use serde_json::json;
228
229 #[test]
230 fn test_service_type() {
231 assert_eq!(
232 Request::builder().build().unwrap().service_type(),
233 ServiceType::Identity
234 );
235 }
236
237 #[test]
238 fn test_response_key() {
239 assert_eq!(
240 Request::builder().build().unwrap().response_key().unwrap(),
241 "role_assignments"
242 );
243 }
244
245 #[cfg(feature = "sync")]
246 #[test]
247 fn endpoint() {
248 let server = MockServer::start();
249 let client = FakeOpenStackClient::new(server.base_url());
250 let mock = server.mock(|when, then| {
251 when.method(httpmock::Method::GET)
252 .path("/role_assignments".to_string());
253
254 then.status(200)
255 .header("content-type", "application/json")
256 .json_body(json!({ "role_assignments": {} }));
257 });
258
259 let endpoint = Request::builder().build().unwrap();
260 let _: serde_json::Value = endpoint.query(&client).unwrap();
261 mock.assert();
262 }
263
264 #[cfg(feature = "sync")]
265 #[test]
266 fn endpoint_headers() {
267 let server = MockServer::start();
268 let client = FakeOpenStackClient::new(server.base_url());
269 let mock = server.mock(|when, then| {
270 when.method(httpmock::Method::GET)
271 .path("/role_assignments".to_string())
272 .header("foo", "bar")
273 .header("not_foo", "not_bar");
274 then.status(200)
275 .header("content-type", "application/json")
276 .json_body(json!({ "role_assignments": {} }));
277 });
278
279 let endpoint = Request::builder()
280 .headers(
281 [(
282 Some(HeaderName::from_static("foo")),
283 HeaderValue::from_static("bar"),
284 )]
285 .into_iter(),
286 )
287 .header(
288 HeaderName::from_static("not_foo"),
289 HeaderValue::from_static("not_bar"),
290 )
291 .build()
292 .unwrap();
293 let _: serde_json::Value = endpoint.query(&client).unwrap();
294 mock.assert();
295 }
296}