Skip to main content

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}