diff --git a/src/assignment/backend/sql/assignment/list.rs b/src/assignment/backend/sql/assignment/list.rs index 5d941fc6..aaf174c1 100644 --- a/src/assignment/backend/sql/assignment/list.rs +++ b/src/assignment/backend/sql/assignment/list.rs @@ -151,7 +151,7 @@ pub async fn list_for_multiple_actors_and_targets( for target in params.targets.iter() { cond = cond.add( Condition::all() - .add(db_assignment::Column::TargetId.eq(&target.target_id)) + .add(db_assignment::Column::TargetId.eq(&target.id)) .add_option( target .inherited @@ -438,7 +438,8 @@ mod tests { &RoleAssignmentListForMultipleActorTargetParameters { actors: vec!["uid1".into(), "gid1".into(), "gid2".into()], targets: vec![RoleAssignmentTarget { - target_id: "pid1".into(), + id: "pid1".into(), + r#type: RoleAssignmentTargetType::Project, inherited: None }], role_id: Some("rid".into()) @@ -516,11 +517,13 @@ mod tests { actors: vec!["uid1".into(), "gid1".into(), "gid2".into()], targets: vec![ RoleAssignmentTarget { - target_id: "pid1".into(), + id: "pid1".into(), + r#type: RoleAssignmentTargetType::Project, inherited: None }, RoleAssignmentTarget { - target_id: "pid2".into(), + id: "pid2".into(), + r#type: RoleAssignmentTargetType::Project, inherited: Some(true) } ], @@ -635,11 +638,13 @@ mod tests { actors: vec![], targets: vec![ RoleAssignmentTarget { - target_id: "pid1".into(), + id: "pid1".into(), + r#type: RoleAssignmentTargetType::Project, inherited: None }, RoleAssignmentTarget { - target_id: "pid2".into(), + id: "pid2".into(), + r#type: RoleAssignmentTargetType::Project, inherited: Some(true) } ], @@ -692,11 +697,13 @@ mod tests { actors: vec![], targets: vec![ RoleAssignmentTarget { - target_id: "pid1".into(), + id: "pid1".into(), + r#type: RoleAssignmentTargetType::Project, inherited: Some(false) }, RoleAssignmentTarget { - target_id: "pid2".into(), + id: "pid2".into(), + r#type: RoleAssignmentTargetType::Project, inherited: Some(true) } ], diff --git a/src/assignment/error.rs b/src/assignment/error.rs index dbc2cd07..989f8608 100644 --- a/src/assignment/error.rs +++ b/src/assignment/error.rs @@ -79,6 +79,13 @@ pub enum AssignmentProviderError { #[from] source: RoleBuilderError, }, + + #[error("request validation error: {}", source)] + Validation { + /// The source of the error. + #[from] + source: validator::ValidationErrors, + }, } impl From for AssignmentProviderError { diff --git a/src/assignment/mod.rs b/src/assignment/mod.rs index caabdcb1..875d09ee 100644 --- a/src/assignment/mod.rs +++ b/src/assignment/mod.rs @@ -12,6 +12,7 @@ // SPDX-License-Identifier: Apache-2.0 use async_trait::async_trait; +use validator::Validate; pub mod backend; pub mod error; @@ -23,7 +24,8 @@ use crate::assignment::backend::{AssignmentBackend, SqlBackend}; use crate::assignment::error::AssignmentProviderError; use crate::assignment::types::{ Assignment, Role, RoleAssignmentListForMultipleActorTargetParametersBuilder, - RoleAssignmentListParameters, RoleAssignmentTarget, RoleListParameters, + RoleAssignmentListParameters, RoleAssignmentTarget, RoleAssignmentTargetType, + RoleListParameters, }; use crate::config::Config; use crate::identity::IdentityApi; @@ -93,6 +95,7 @@ impl AssignmentApi for AssignmentProvider { state: &ServiceState, params: &RoleAssignmentListParameters, ) -> Result, AssignmentProviderError> { + params.validate()?; let mut request = RoleAssignmentListForMultipleActorTargetParametersBuilder::default(); let mut actors: Vec = Vec::new(); let mut targets: Vec = Vec::new(); @@ -114,7 +117,8 @@ impl AssignmentApi for AssignmentProvider { }; if let Some(val) = ¶ms.project_id { targets.push(RoleAssignmentTarget { - target_id: val.clone(), + id: val.clone(), + r#type: RoleAssignmentTargetType::Project, inherited: Some(false), }); if let Some(parents) = state @@ -125,14 +129,16 @@ impl AssignmentApi for AssignmentProvider { { parents.iter().for_each(|parent_project| { targets.push(RoleAssignmentTarget { - target_id: parent_project.id.clone(), + id: parent_project.id.clone(), + r#type: RoleAssignmentTargetType::Project, inherited: Some(true), }); }); } } else if let Some(val) = ¶ms.domain_id { targets.push(RoleAssignmentTarget { - target_id: val.clone(), + id: val.clone(), + r#type: RoleAssignmentTargetType::Domain, inherited: Some(false), }); } diff --git a/src/assignment/types.rs b/src/assignment/types.rs index 056a161c..86722e39 100644 --- a/src/assignment/types.rs +++ b/src/assignment/types.rs @@ -20,13 +20,7 @@ use async_trait::async_trait; use crate::assignment::AssignmentProviderError; use crate::keystone::ServiceState; -pub use crate::assignment::types::assignment::{ - Assignment, AssignmentBuilder, AssignmentBuilderError, AssignmentType, - RoleAssignmentListForMultipleActorTargetParameters, - RoleAssignmentListForMultipleActorTargetParametersBuilder, RoleAssignmentListParameters, - RoleAssignmentListParametersBuilder, RoleAssignmentListParametersBuilderError, - RoleAssignmentTarget, -}; +pub use crate::assignment::types::assignment::*; pub use crate::assignment::types::role::{Role, RoleBuilder, RoleBuilderError, RoleListParameters}; #[async_trait] diff --git a/src/assignment/types/assignment.rs b/src/assignment/types/assignment.rs index 2e1c6e1c..218eabb5 100644 --- a/src/assignment/types/assignment.rs +++ b/src/assignment/types/assignment.rs @@ -15,19 +15,24 @@ use derive_builder::Builder; use serde::{Deserialize, Serialize}; use std::fmt; +use validator::Validate; -/// Role -#[derive(Builder, Clone, Debug, Deserialize, PartialEq, Serialize)] +/// The assignment object. +#[derive(Builder, Clone, Debug, Deserialize, PartialEq, Serialize, Validate)] #[builder(setter(strip_option, into))] pub struct Assignment { /// The role ID. + #[validate(length(max = 64))] pub role_id: String, - /// The role ID. + /// The role name. #[builder(default)] + #[validate(length(max = 64))] pub role_name: Option, /// The actor id. + #[validate(length(max = 64))] pub actor_id: String, /// The target id. + #[validate(length(max = 64))] pub target_id: String, /// The assignment type. pub r#type: AssignmentType, @@ -35,14 +40,20 @@ pub struct Assignment { pub inherited: bool, } -/// Role assignment type +/// Role assignment type. #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub enum AssignmentType { + /// Group to the domain. GroupDomain, + /// Group to the project. GroupProject, + /// User to the domain. UserDomain, + /// User to the project. UserProject, + /// User to the system. UserSystem, + /// Group to the system. GroupSystem, } @@ -60,28 +71,35 @@ impl fmt::Display for AssignmentType { } /// Parameters for listing role assignments for role/target/actor. -#[derive(Builder, Clone, Debug, Default, Deserialize, PartialEq, Serialize)] +#[derive(Builder, Clone, Debug, Default, Deserialize, PartialEq, Serialize, Validate)] #[builder(setter(strip_option, into))] pub struct RoleAssignmentListParameters { /// Query role assignments filtering results by the role #[builder(default)] + #[validate(length(max = 64))] pub role_id: Option, - /// Get role assignments for the user + /// Get role assignments for the user. #[builder(default)] + #[validate(length(max = 64))] pub user_id: Option, - /// Get role assignments for the group + + /// Get role assignments for the group. #[builder(default)] + #[validate(length(max = 64))] pub group_id: Option, - /// Query role assignments on the project + /// Query role assignments on the project. #[builder(default)] + #[validate(length(max = 64))] pub project_id: Option, - /// Query role assignments on the domain + /// Query role assignments on the domain. #[builder(default)] + #[validate(length(max = 64))] pub domain_id: Option, - /// Query role assignments on the system + /// Query role assignments on the system. #[builder(default)] + #[validate(length(max = 64))] pub system: Option, // #[builder(default)] @@ -101,26 +119,45 @@ pub struct RoleAssignmentListParameters { /// Querying effective role assignments for list of actors (typically user with /// all groups user is member of) on list of targets (exactl project + inherited /// from uppoer projects/domain). -#[derive(Builder, Clone, Debug, Default, Deserialize, PartialEq, Serialize)] +#[derive(Builder, Clone, Debug, Default, Deserialize, PartialEq, Serialize, Validate)] #[builder(setter(strip_option, into))] pub struct RoleAssignmentListForMultipleActorTargetParameters { /// List of actors for which assignments are looked up. #[builder(default)] + #[validate(length(max = 64))] pub actors: Vec, /// Optionally filter for the concrete role ID. #[builder(default)] + #[validate(length(max = 64))] pub role_id: Option, /// List of targets for which assignments are looked up. #[builder(default)] + #[validate(nested)] pub targets: Vec, } /// Role assignment target which is either target_id or target_id with explicit /// inherited parameter. -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Validate)] pub struct RoleAssignmentTarget { - pub target_id: String, + /// The role assignment target ID. + #[validate(length(max = 64))] + pub id: String, + /// The role assignment target type. + pub r#type: RoleAssignmentTargetType, + /// Specifies whether the target is only considered for inherited assignments. pub inherited: Option, } + +/// Role assignment target as Project(id), Domain(id) or System(id). +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +pub enum RoleAssignmentTargetType { + /// Project ID. + Project, + /// Domain ID. + Domain, + /// System ID. + System, +}