From b1384818d22280682f5ba519dd46f225a8b6c1dd Mon Sep 17 00:00:00 2001 From: Valentin Tolmer Date: Tue, 27 Aug 2024 22:51:34 +0200 Subject: [PATCH] server: Add a is_readonly attribute to the schema --- schema.graphql | 1 + server/src/domain/handler.rs | 1 + server/src/domain/model/group_attribute_schema.rs | 1 + server/src/domain/model/user_attribute_schema.rs | 1 + server/src/domain/schema.rs | 9 +++++++++ server/src/domain/sql_schema_backend_handler.rs | 5 +++++ server/src/infra/graphql/mutation.rs | 7 +++++++ server/src/infra/graphql/query.rs | 9 ++++++++- server/src/infra/ldap_handler.rs | 2 ++ server/src/infra/test_utils.rs | 3 +++ 10 files changed, 38 insertions(+), 1 deletion(-) diff --git a/schema.graphql b/schema.graphql index e5ad39d..6627ebd 100644 --- a/schema.graphql +++ b/schema.graphql @@ -78,6 +78,7 @@ type AttributeSchema { isVisible: Boolean! isEditable: Boolean! isHardcoded: Boolean! + isReadonly: Boolean! } "The fields that can be updated for a user." diff --git a/server/src/domain/handler.rs b/server/src/domain/handler.rs index c5d5ad3..21a9796 100644 --- a/server/src/domain/handler.rs +++ b/server/src/domain/handler.rs @@ -147,6 +147,7 @@ pub struct AttributeSchema { pub is_visible: bool, pub is_editable: bool, pub is_hardcoded: bool, + pub is_readonly: bool, } #[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] diff --git a/server/src/domain/model/group_attribute_schema.rs b/server/src/domain/model/group_attribute_schema.rs index 2c33ef1..4529185 100644 --- a/server/src/domain/model/group_attribute_schema.rs +++ b/server/src/domain/model/group_attribute_schema.rs @@ -50,6 +50,7 @@ impl From for AttributeSchema { is_visible: value.is_group_visible, is_editable: value.is_group_editable, is_hardcoded: value.is_hardcoded, + is_readonly: false, } } } diff --git a/server/src/domain/model/user_attribute_schema.rs b/server/src/domain/model/user_attribute_schema.rs index aa4dbb8..434840e 100644 --- a/server/src/domain/model/user_attribute_schema.rs +++ b/server/src/domain/model/user_attribute_schema.rs @@ -50,6 +50,7 @@ impl From for AttributeSchema { is_visible: value.is_user_visible, is_editable: value.is_user_editable, is_hardcoded: value.is_hardcoded, + is_readonly: false, } } } diff --git a/server/src/domain/schema.rs b/server/src/domain/schema.rs index 665bc87..8aad05c 100644 --- a/server/src/domain/schema.rs +++ b/server/src/domain/schema.rs @@ -43,6 +43,7 @@ impl From for PublicSchema { is_visible: true, is_editable: false, is_hardcoded: true, + is_readonly: true, }, AttributeSchema { name: "creation_date".into(), @@ -51,6 +52,7 @@ impl From for PublicSchema { is_visible: true, is_editable: false, is_hardcoded: true, + is_readonly: true, }, AttributeSchema { name: "mail".into(), @@ -59,6 +61,7 @@ impl From for PublicSchema { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, AttributeSchema { name: "uuid".into(), @@ -67,6 +70,7 @@ impl From for PublicSchema { is_visible: true, is_editable: false, is_hardcoded: true, + is_readonly: true, }, AttributeSchema { name: "display_name".into(), @@ -75,6 +79,7 @@ impl From for PublicSchema { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, ]); schema @@ -89,6 +94,7 @@ impl From for PublicSchema { is_visible: true, is_editable: false, is_hardcoded: true, + is_readonly: true, }, AttributeSchema { name: "creation_date".into(), @@ -97,6 +103,7 @@ impl From for PublicSchema { is_visible: true, is_editable: false, is_hardcoded: true, + is_readonly: true, }, AttributeSchema { name: "uuid".into(), @@ -105,6 +112,7 @@ impl From for PublicSchema { is_visible: true, is_editable: false, is_hardcoded: true, + is_readonly: true, }, AttributeSchema { name: "display_name".into(), @@ -113,6 +121,7 @@ impl From for PublicSchema { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, ]); schema diff --git a/server/src/domain/sql_schema_backend_handler.rs b/server/src/domain/sql_schema_backend_handler.rs index 288055a..bea2fbd 100644 --- a/server/src/domain/sql_schema_backend_handler.rs +++ b/server/src/domain/sql_schema_backend_handler.rs @@ -196,6 +196,7 @@ mod tests { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, AttributeSchema { name: "first_name".into(), @@ -204,6 +205,7 @@ mod tests { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, AttributeSchema { name: "last_name".into(), @@ -212,6 +214,7 @@ mod tests { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, } ] }, @@ -246,6 +249,7 @@ mod tests { is_visible: false, is_editable: false, is_hardcoded: false, + is_readonly: false, }; assert!(fixture .handler @@ -329,6 +333,7 @@ mod tests { is_visible: true, is_editable: false, is_hardcoded: false, + is_readonly: false, }; assert!(fixture .handler diff --git a/server/src/infra/graphql/mutation.rs b/server/src/infra/graphql/mutation.rs index b0249c5..f8d414a 100644 --- a/server/src/infra/graphql/mutation.rs +++ b/server/src/infra/graphql/mutation.rs @@ -609,6 +609,13 @@ fn deserialize_attribute( let attribute_schema = attribute_schema .get_attribute_schema(&attribute_name) .ok_or_else(|| anyhow!("Attribute {} is not defined in the schema", attribute.name))?; + if attribute_schema.is_readonly { + return Err(anyhow!( + "Permission denied: Attribute {} is read-only", + attribute.name + ) + .into()); + } if !is_admin && !attribute_schema.is_editable { return Err(anyhow!( "Permission denied: Attribute {} is not editable by regular users", diff --git a/server/src/infra/graphql/query.rs b/server/src/infra/graphql/query.rs index 5332d70..19d8b97 100644 --- a/server/src/infra/graphql/query.rs +++ b/server/src/infra/graphql/query.rs @@ -498,6 +498,9 @@ impl AttributeSchema { fn is_hardcoded(&self) -> bool { self.schema.is_hardcoded } + fn is_readonly(&self) -> bool { + self.schema.is_readonly + } } impl Clone for AttributeSchema { @@ -745,6 +748,7 @@ mod tests { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, DomainAttributeSchema { name: "last_name".into(), @@ -753,6 +757,7 @@ mod tests { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, ], }, @@ -764,6 +769,7 @@ mod tests { is_visible: true, is_editable: true, is_hardcoded: false, + is_readonly: false, }], }, extra_user_object_classes: vec![ @@ -1125,13 +1131,14 @@ mod tests { mock.expect_get_schema().times(1).return_once(|| { Ok(crate::domain::handler::Schema { user_attributes: AttributeList { - attributes: vec![crate::domain::handler::AttributeSchema { + attributes: vec![DomainAttributeSchema { name: "invisible".into(), attribute_type: AttributeType::JpegPhoto, is_list: false, is_visible: false, is_editable: true, is_hardcoded: true, + is_readonly: false, }], }, group_attributes: AttributeList { diff --git a/server/src/infra/ldap_handler.rs b/server/src/infra/ldap_handler.rs index 42d2234..f2729a7 100644 --- a/server/src/infra/ldap_handler.rs +++ b/server/src/infra/ldap_handler.rs @@ -2884,6 +2884,7 @@ mod tests { is_visible: true, is_editable: true, is_hardcoded: false, + is_readonly: false, }], }, group_attributes: AttributeList { @@ -2894,6 +2895,7 @@ mod tests { is_visible: true, is_editable: true, is_hardcoded: false, + is_readonly: false, }], }, extra_user_object_classes: vec![ diff --git a/server/src/infra/test_utils.rs b/server/src/infra/test_utils.rs index 1beb7c1..b908111 100644 --- a/server/src/infra/test_utils.rs +++ b/server/src/infra/test_utils.rs @@ -84,6 +84,7 @@ pub fn setup_default_schema(mock: &mut MockTestBackendHandler) { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, AttributeSchema { name: "first_name".into(), @@ -92,6 +93,7 @@ pub fn setup_default_schema(mock: &mut MockTestBackendHandler) { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, AttributeSchema { name: "last_name".into(), @@ -100,6 +102,7 @@ pub fn setup_default_schema(mock: &mut MockTestBackendHandler) { is_visible: true, is_editable: true, is_hardcoded: true, + is_readonly: false, }, ], },