Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/api-types/src/v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ pub mod user;

#[cfg(feature = "conv")]
mod token_restriction_conv;
#[cfg(feature = "conv")]
mod user_conv;
49 changes: 47 additions & 2 deletions crates/api-types/src/v4/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,52 @@
// SPDX-License-Identifier: Apache-2.0
//! User resource types.

use serde::{Deserialize, Serialize};

pub use crate::v3::user::{
Federation, FederationProtocol, User, UserCreate, UserCreateRequest, UserList,
UserListParameters, UserOptions, UserResponse, UserUpdateRequest,
Federation, FederationProtocol, User, UserCreate, UserCreateRequest, UserList, UserOptions,
UserResponse, UserUpdateRequest,
};

/// User list parameters.
///
/// V4 extends the v3 listing with a `type` filter; this is intentionally a
/// v4-only parameter (Python Keystone does not support it on v3).
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[cfg_attr(feature = "openapi", derive(utoipa::IntoParams))]
#[cfg_attr(feature = "validate", derive(validator::Validate))]
pub struct UserListParameters {
/// Filter users by Domain ID.
#[cfg_attr(feature = "validate", validate(length(max = 64)))]
pub domain_id: Option<String>,

/// Filter users by Name.
#[cfg_attr(feature = "validate", validate(length(max = 255)))]
pub name: Option<String>,

/// Filter users by the federated unique ID.
#[cfg_attr(feature = "validate", validate(length(max = 64)))]
pub unique_id: Option<String>,

/// Filter users by type (`local`, `federated`, `nonlocal`, `all`).
#[serde(rename = "type")]
pub user_type: Option<UserType>,
}

/// User type filter for listing users.
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[serde(rename_all = "lowercase")]
pub enum UserType {
/// All users (default behavior).
All,
/// Federated users only.
Federated,
/// Local users only.
Local,
/// Non-local users only.
NonLocal,
/// Service account users only.
#[serde(rename = "service_account")]
ServiceAccount,
}
40 changes: 40 additions & 0 deletions crates/api-types/src/v4/user_conv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

use openstack_keystone_core_types::identity as provider_types;

use crate::v4::user as api_types;

impl From<api_types::UserType> for provider_types::UserType {
fn from(value: api_types::UserType) -> Self {
match value {
api_types::UserType::All => Self::All,
api_types::UserType::Federated => Self::Federated,
api_types::UserType::Local => Self::Local,
api_types::UserType::NonLocal => Self::NonLocal,
api_types::UserType::ServiceAccount => Self::ServiceAccount,
}
}
}

impl From<api_types::UserListParameters> for provider_types::UserListParameters {
fn from(value: api_types::UserListParameters) -> Self {
Self {
domain_id: value.domain_id,
name: value.name,
unique_id: value.unique_id,
user_type: value.user_type.map(Into::into),
}
}
}
35 changes: 35 additions & 0 deletions crates/keystone/src/api/v4/user/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,41 @@ mod tests {
let _res: UserList = serde_json::from_slice(&body).unwrap();
}

#[tokio::test]
async fn test_list_qp_type() {
let vsc = test_fixture_scoped();
let mut identity_mock = MockIdentityProvider::default();
identity_mock
.expect_list_users()
.withf(|_, qp: &UserListParameters| qp.user_type == Some(UserType::Local))
.returning(|_, _| Ok(Vec::new()));

let state = get_mocked_state(
Provider::mocked_builder().mock_identity(identity_mock),
true,
None,
)
.await;

let mut api = openapi_router()
.layer(TraceLayer::new_for_http())
.with_state(state);

let response = api
.as_service()
.oneshot(
Request::builder()
.uri("/?type=local")
.extension(vsc)
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();

assert_eq!(response.status(), StatusCode::OK);
}

#[tokio::test]
async fn test_list_unauth() {
let state = get_mocked_state(Provider::mocked_builder(), false, None).await;
Expand Down
5 changes: 3 additions & 2 deletions crates/keystone/src/api/v4/user/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//! User resource types.

pub use crate::api::v3::user::types::{
Federation, FederationProtocol, User, UserCreate, UserCreateRequest, UserList,
UserListParameters, UserOptions, UserResponse, UserUpdateRequest,
Federation, FederationProtocol, User, UserCreate, UserCreateRequest, UserList, UserOptions,
UserResponse, UserUpdateRequest,
};
pub use openstack_keystone_api_types::v4::user::UserListParameters;
Loading