From 2c398d0e8eab0f2b47d5ae356198fc0fbf5a861e Mon Sep 17 00:00:00 2001 From: Valentin Tolmer Date: Fri, 29 Sep 2023 01:01:05 +0200 Subject: [PATCH] server: Add domain support for creating/deleting attributes --- server/src/domain/handler.rs | 18 +++ .../src/domain/sql_schema_backend_handler.rs | 144 +++++++++++++++++- 2 files changed, 160 insertions(+), 2 deletions(-) diff --git a/server/src/domain/handler.rs b/server/src/domain/handler.rs index 47297e2..65d85fe 100644 --- a/server/src/domain/handler.rs +++ b/server/src/domain/handler.rs @@ -137,6 +137,15 @@ pub struct AttributeSchema { pub is_hardcoded: bool, } +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] +pub struct CreateAttributeRequest { + pub name: String, + pub attribute_type: AttributeType, + pub is_list: bool, + pub is_visible: bool, + pub is_editable: bool, +} + #[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] pub struct AttributeList { pub attributes: Vec, @@ -200,6 +209,15 @@ pub trait ReadSchemaBackendHandler { async fn get_schema(&self) -> Result; } +#[async_trait] +pub trait SchemaBackendHandler: ReadSchemaBackendHandler { + async fn add_user_attribute(&self, request: CreateAttributeRequest) -> Result<()>; + async fn add_group_attribute(&self, request: CreateAttributeRequest) -> Result<()>; + // Note: It's up to the caller to make sure that the attribute is not hardcoded. + async fn delete_user_attribute(&self, name: &str) -> Result<()>; + async fn delete_group_attribute(&self, name: &str) -> Result<()>; +} + #[async_trait] pub trait BackendHandler: Send diff --git a/server/src/domain/sql_schema_backend_handler.rs b/server/src/domain/sql_schema_backend_handler.rs index ee210d8..44a5436 100644 --- a/server/src/domain/sql_schema_backend_handler.rs +++ b/server/src/domain/sql_schema_backend_handler.rs @@ -1,11 +1,16 @@ use crate::domain::{ error::{DomainError, Result}, - handler::{AttributeList, AttributeSchema, ReadSchemaBackendHandler, Schema}, + handler::{ + AttributeList, AttributeSchema, CreateAttributeRequest, ReadSchemaBackendHandler, Schema, + SchemaBackendHandler, + }, model, sql_backend_handler::SqlBackendHandler, }; use async_trait::async_trait; -use sea_orm::{DatabaseTransaction, EntityTrait, QueryOrder, TransactionTrait}; +use sea_orm::{ + ActiveModelTrait, DatabaseTransaction, EntityTrait, QueryOrder, Set, TransactionTrait, +}; #[async_trait] impl ReadSchemaBackendHandler for SqlBackendHandler { @@ -19,6 +24,49 @@ impl ReadSchemaBackendHandler for SqlBackendHandler { } } +#[async_trait] +impl SchemaBackendHandler for SqlBackendHandler { + async fn add_user_attribute(&self, request: CreateAttributeRequest) -> Result<()> { + let new_attribute = model::user_attribute_schema::ActiveModel { + attribute_name: Set(request.name), + attribute_type: Set(request.attribute_type), + is_list: Set(request.is_list), + is_user_visible: Set(request.is_visible), + is_user_editable: Set(request.is_editable), + is_hardcoded: Set(false), + }; + new_attribute.insert(&self.sql_pool).await?; + Ok(()) + } + + async fn add_group_attribute(&self, request: CreateAttributeRequest) -> Result<()> { + let new_attribute = model::group_attribute_schema::ActiveModel { + attribute_name: Set(request.name), + attribute_type: Set(request.attribute_type), + is_list: Set(request.is_list), + is_group_visible: Set(request.is_visible), + is_group_editable: Set(request.is_editable), + is_hardcoded: Set(false), + }; + new_attribute.insert(&self.sql_pool).await?; + Ok(()) + } + + async fn delete_user_attribute(&self, name: &str) -> Result<()> { + model::UserAttributeSchema::delete_by_id(name) + .exec(&self.sql_pool) + .await?; + Ok(()) + } + + async fn delete_group_attribute(&self, name: &str) -> Result<()> { + model::GroupAttributeSchema::delete_by_id(name) + .exec(&self.sql_pool) + .await?; + Ok(()) + } +} + impl SqlBackendHandler { pub(crate) async fn get_schema_with_transaction( transaction: &DatabaseTransaction, @@ -106,4 +154,96 @@ mod tests { } ); } + + #[tokio::test] + async fn test_user_attribute_add_and_delete() { + let fixture = TestFixture::new().await; + let new_attribute = CreateAttributeRequest { + name: "new_attribute".to_owned(), + attribute_type: AttributeType::Integer, + is_list: true, + is_visible: false, + is_editable: false, + }; + fixture + .handler + .add_user_attribute(new_attribute) + .await + .unwrap(); + let expected_value = AttributeSchema { + name: "new_attribute".to_owned(), + attribute_type: AttributeType::Integer, + is_list: true, + is_visible: false, + is_editable: false, + is_hardcoded: false, + }; + assert!(fixture + .handler + .get_schema() + .await + .unwrap() + .user_attributes + .attributes + .contains(&expected_value)); + fixture + .handler + .delete_user_attribute("new_attribute") + .await + .unwrap(); + assert!(!fixture + .handler + .get_schema() + .await + .unwrap() + .user_attributes + .attributes + .contains(&expected_value)); + } + + #[tokio::test] + async fn test_group_attribute_add_and_delete() { + let fixture = TestFixture::new().await; + let new_attribute = CreateAttributeRequest { + name: "new_attribute".to_owned(), + attribute_type: AttributeType::JpegPhoto, + is_list: false, + is_visible: true, + is_editable: false, + }; + fixture + .handler + .add_group_attribute(new_attribute) + .await + .unwrap(); + let expected_value = AttributeSchema { + name: "new_attribute".to_owned(), + attribute_type: AttributeType::JpegPhoto, + is_list: false, + is_visible: true, + is_editable: false, + is_hardcoded: false, + }; + assert!(fixture + .handler + .get_schema() + .await + .unwrap() + .group_attributes + .attributes + .contains(&expected_value)); + fixture + .handler + .delete_group_attribute("new_attribute") + .await + .unwrap(); + assert!(!fixture + .handler + .get_schema() + .await + .unwrap() + .group_attributes + .attributes + .contains(&expected_value)); + } }