diff --git a/Cargo.lock b/Cargo.lock index eead819..707c64f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2527,7 +2527,6 @@ dependencies = [ "graphql_client 0.11.0", "hmac 0.12.1", "http 0.2.12", - "image", "itertools", "juniper", "jwt 0.16.0", @@ -2536,6 +2535,7 @@ dependencies = [ "ldap3_proto", "lettre", "lldap_auth", + "lldap_domain", "lldap_validation", "log", "mockall", @@ -2551,7 +2551,6 @@ dependencies = [ "sea-orm", "secstr", "serde", - "serde_bytes", "serde_json", "serial_test", "sha2 0.10.8", @@ -2625,6 +2624,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "lldap_domain" +version = "0.1.0" +dependencies = [ + "anyhow", + "base64 0.21.7", + "bincode", + "chrono", + "derive_more 1.0.0", + "image", + "juniper", + "lldap_auth", + "pretty_assertions", + "sea-orm", + "serde", + "serde_bytes", + "strum", + "uuid 1.11.0", +] + [[package]] name = "lldap_migration_tool" version = "0.4.2" diff --git a/Cargo.toml b/Cargo.toml index 936ba54..e3228ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,11 @@ [workspace] members = [ - "server", - "auth", - "app", - "migration-tool", - "set-password", + "crates/domain", + "server", + "auth", + "app", + "migration-tool", + "set-password", ] default-members = ["server"] diff --git a/crates/domain/Cargo.toml b/crates/domain/Cargo.toml new file mode 100644 index 0000000..357eecf --- /dev/null +++ b/crates/domain/Cargo.toml @@ -0,0 +1,59 @@ +[package] +authors = [ + "Valentin Tolmer ", + "Simon Broeng Jensen ", +] +name = "lldap_domain" +version = "0.1.0" +edition = "2021" + +[features] +test = [] + +[dependencies] +anyhow = "*" +base64 = "0.21" +bincode = "1.3" +juniper = "0.15" +serde = "*" +serde_bytes = "0.11" + +[dev-dependencies] +pretty_assertions = "1" + +[dependencies.chrono] +features = ["serde"] +version = "*" + +[dependencies.derive_more] +features = ["debug", "display", "from", "from_str"] +default-features = false +version = "1" + +[dependencies.image] +features = ["jpeg"] +default-features = false +version = "0.24" + +[dependencies.lldap_auth] +path = "../../auth" +features = ["opaque_server", "opaque_client", "sea_orm"] + +[dependencies.sea-orm] +version = "0.12" +default-features = false +features = [ + "macros", + "with-chrono", + "with-uuid", + "sqlx-all", + "runtime-actix-rustls", +] + +[dependencies.strum] +features = ["derive"] +version = "0.25" + +[dependencies.uuid] +features = ["v1", "v3"] +version = "1" diff --git a/crates/domain/src/lib.rs b/crates/domain/src/lib.rs new file mode 100644 index 0000000..4abd0d4 --- /dev/null +++ b/crates/domain/src/lib.rs @@ -0,0 +1,3 @@ +pub mod requests; +pub mod schema; +pub mod types; diff --git a/crates/domain/src/requests.rs b/crates/domain/src/requests.rs new file mode 100644 index 0000000..eefd6e7 --- /dev/null +++ b/crates/domain/src/requests.rs @@ -0,0 +1,53 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::{ + AttributeName, AttributeType, AttributeValue, Email, GroupId, GroupName, JpegPhoto, UserId, +}; + +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)] +pub struct CreateUserRequest { + // Same fields as User, but no creation_date, and with password. + pub user_id: UserId, + pub email: Email, + pub display_name: Option, + pub first_name: Option, + pub last_name: Option, + pub avatar: Option, + pub attributes: Vec, +} + +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)] +pub struct UpdateUserRequest { + // Same fields as CreateUserRequest, but no with an extra layer of Option. + pub user_id: UserId, + pub email: Option, + pub display_name: Option, + pub first_name: Option, + pub last_name: Option, + pub avatar: Option, + pub delete_attributes: Vec, + pub insert_attributes: Vec, +} + +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)] +pub struct CreateGroupRequest { + pub display_name: GroupName, + pub attributes: Vec, +} + +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] +pub struct UpdateGroupRequest { + pub group_id: GroupId, + pub display_name: Option, + pub delete_attributes: Vec, + pub insert_attributes: Vec, +} + +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] +pub struct CreateAttributeRequest { + pub name: AttributeName, + pub attribute_type: AttributeType, + pub is_list: bool, + pub is_visible: bool, + pub is_editable: bool, +} diff --git a/crates/domain/src/schema.rs b/crates/domain/src/schema.rs new file mode 100644 index 0000000..62c2110 --- /dev/null +++ b/crates/domain/src/schema.rs @@ -0,0 +1,39 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::{AttributeName, AttributeType, LdapObjectClass}; + +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] +pub struct Schema { + pub user_attributes: AttributeList, + pub group_attributes: AttributeList, + pub extra_user_object_classes: Vec, + pub extra_group_object_classes: Vec, +} + +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] +pub struct AttributeSchema { + pub name: AttributeName, + //TODO: pub aliases: Vec, + pub attribute_type: AttributeType, + pub is_list: bool, + pub is_visible: bool, + pub is_editable: bool, + pub is_hardcoded: bool, + pub is_readonly: bool, +} + +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] +pub struct AttributeList { + pub attributes: Vec, +} + +impl AttributeList { + pub fn get_attribute_schema(&self, name: &AttributeName) -> Option<&AttributeSchema> { + self.attributes.iter().find(|a| a.name == *name) + } + + pub fn get_attribute_type(&self, name: &AttributeName) -> Option<(AttributeType, bool)> { + self.get_attribute_schema(name) + .map(|a| (a.attribute_type, a.is_list)) + } +} diff --git a/server/src/domain/types.rs b/crates/domain/src/types.rs similarity index 98% rename from server/src/domain/types.rs rename to crates/domain/src/types.rs index 48e1be3..52d08e4 100644 --- a/server/src/domain/types.rs +++ b/crates/domain/src/types.rs @@ -11,7 +11,6 @@ use sea_orm::{ use serde::{Deserialize, Serialize}; use strum::{EnumString, IntoStaticStr}; -pub use super::model::UserColumn; pub use lldap_auth::types::UserId; #[derive( @@ -66,11 +65,11 @@ impl<'a> std::convert::TryFrom<&'a str> for Uuid { } } -#[cfg(test)] +#[cfg(feature = "test")] #[macro_export] macro_rules! uuid { ($s:literal) => { - <$crate::domain::types::Uuid as std::convert::TryFrom<_>>::try_from($s).unwrap() + >::try_from($s).unwrap() }; } @@ -372,7 +371,7 @@ impl JpegPhoto { self.0 } - #[cfg(test)] + #[cfg(any(feature = "test", test))] pub fn for_tests() -> Self { use image::{ImageOutputFormat, Rgb, RgbImage}; let img = RgbImage::from_fn(32, 32, |x, y| { @@ -424,7 +423,7 @@ pub struct User { pub attributes: Vec, } -#[cfg(test)] +#[cfg(feature = "test")] impl Default for User { fn default() -> Self { let epoch = chrono::Utc.timestamp_opt(0, 0).unwrap().naive_utc(); diff --git a/server/Cargo.toml b/server/Cargo.toml index ab79b85..5195085 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -40,7 +40,6 @@ orion = "0.17" rand_chacha = "0.3" rustls-pemfile = "1" serde = "*" -serde_bytes = "0.11" serde_json = "1" sha2 = "0.10" thiserror = "*" @@ -85,6 +84,13 @@ version = "0.10.1" path = "../auth" features = ["opaque_server", "opaque_client", "sea_orm"] +[dependencies.lldap_domain] +path = "../crates/domain" + +[dev-dependencies.lldap_domain] +path = "../crates/domain" +features = ["test"] + [dependencies.lldap_validation] path = "../validation" @@ -119,20 +125,15 @@ version = "^0.1.6" features = ["default", "rustls"] version = "3" -[dependencies.image] -features = ["jpeg"] -default-features = false -version = "0.24" - [dependencies.sea-orm] version = "0.12" default-features = false features = [ - "macros", - "with-chrono", - "with-uuid", - "sqlx-all", - "runtime-actix-rustls", + "macros", + "with-chrono", + "with-uuid", + "sqlx-all", + "runtime-actix-rustls", ] [dependencies.reqwest] diff --git a/server/src/domain/deserialize.rs b/server/src/domain/deserialize.rs index 834b0fd..07b6fab 100644 --- a/server/src/domain/deserialize.rs +++ b/server/src/domain/deserialize.rs @@ -1,5 +1,5 @@ -use crate::domain::types::{AttributeType, JpegPhoto, Serialized}; use anyhow::{bail, Context as AnyhowContext}; +use lldap_domain::types::{AttributeType, JpegPhoto, Serialized}; pub fn deserialize_attribute_value( value: &[String], diff --git a/server/src/domain/handler.rs b/server/src/domain/handler.rs index 21a9796..dead961 100644 --- a/server/src/domain/handler.rs +++ b/server/src/domain/handler.rs @@ -1,12 +1,16 @@ -use crate::domain::{ - error::Result, +use crate::domain::{error::Result, model::UserColumn}; +use async_trait::async_trait; +use lldap_domain::{ + requests::{ + CreateAttributeRequest, CreateGroupRequest, CreateUserRequest, UpdateGroupRequest, + UpdateUserRequest, + }, + schema::Schema, types::{ - AttributeName, AttributeType, AttributeValue, Email, Group, GroupDetails, GroupId, - GroupName, JpegPhoto, LdapObjectClass, Serialized, User, UserAndGroups, UserColumn, UserId, - Uuid, + AttributeName, Group, GroupDetails, GroupId, GroupName, LdapObjectClass, Serialized, User, + UserAndGroups, UserId, Uuid, }, }; -use async_trait::async_trait; use serde::{Deserialize, Serialize}; use std::collections::HashSet; @@ -99,90 +103,6 @@ impl From for GroupRequestFilter { } } -#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)] -pub struct CreateUserRequest { - // Same fields as User, but no creation_date, and with password. - pub user_id: UserId, - pub email: Email, - pub display_name: Option, - pub first_name: Option, - pub last_name: Option, - pub avatar: Option, - pub attributes: Vec, -} - -#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)] -pub struct UpdateUserRequest { - // Same fields as CreateUserRequest, but no with an extra layer of Option. - pub user_id: UserId, - pub email: Option, - pub display_name: Option, - pub first_name: Option, - pub last_name: Option, - pub avatar: Option, - pub delete_attributes: Vec, - pub insert_attributes: Vec, -} - -#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)] -pub struct CreateGroupRequest { - pub display_name: GroupName, - pub attributes: Vec, -} - -#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] -pub struct UpdateGroupRequest { - pub group_id: GroupId, - pub display_name: Option, - pub delete_attributes: Vec, - pub insert_attributes: Vec, -} - -#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] -pub struct AttributeSchema { - pub name: AttributeName, - //TODO: pub aliases: Vec, - pub attribute_type: AttributeType, - pub is_list: bool, - pub is_visible: bool, - pub is_editable: bool, - pub is_hardcoded: bool, - pub is_readonly: bool, -} - -#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] -pub struct CreateAttributeRequest { - pub name: AttributeName, - 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, -} - -impl AttributeList { - pub fn get_attribute_schema(&self, name: &AttributeName) -> Option<&AttributeSchema> { - self.attributes.iter().find(|a| a.name == *name) - } - - pub fn get_attribute_type(&self, name: &AttributeName) -> Option<(AttributeType, bool)> { - self.get_attribute_schema(name) - .map(|a| (a.attribute_type, a.is_list)) - } -} - -#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] -pub struct Schema { - pub user_attributes: AttributeList, - pub group_attributes: AttributeList, - pub extra_user_object_classes: Vec, - pub extra_group_object_classes: Vec, -} - #[async_trait] pub trait LoginHandler: Send + Sync { async fn bind(&self, request: BindRequest) -> Result<()>; @@ -257,6 +177,7 @@ pub trait BackendHandler: mod tests { use super::*; use base64::Engine; + use lldap_domain::types::JpegPhoto; use pretty_assertions::assert_ne; #[test] diff --git a/server/src/domain/ldap/group.rs b/server/src/domain/ldap/group.rs index a670293..e03e3b9 100644 --- a/server/src/domain/ldap/group.rs +++ b/server/src/domain/ldap/group.rs @@ -17,7 +17,9 @@ use crate::domain::{ }, }, schema::{PublicSchema, SchemaGroupAttributeExtractor}, - types::{AttributeName, AttributeType, Group, GroupId, LdapObjectClass, UserId, Uuid}, +}; +use lldap_domain::types::{ + AttributeName, AttributeType, Group, GroupId, LdapObjectClass, UserId, Uuid, }; pub fn get_group_attribute( diff --git a/server/src/domain/ldap/user.rs b/server/src/domain/ldap/user.rs index e5dc130..18de297 100644 --- a/server/src/domain/ldap/user.rs +++ b/server/src/domain/ldap/user.rs @@ -16,11 +16,11 @@ use crate::domain::{ LdapInfo, UserFieldType, }, }, + model::UserColumn, schema::{PublicSchema, SchemaUserAttributeExtractor}, - types::{ - AttributeName, AttributeType, GroupDetails, LdapObjectClass, User, UserAndGroups, - UserColumn, UserId, - }, +}; +use lldap_domain::types::{ + AttributeName, AttributeType, GroupDetails, LdapObjectClass, User, UserAndGroups, UserId, }; pub fn get_user_attribute( diff --git a/server/src/domain/ldap/utils.rs b/server/src/domain/ldap/utils.rs index 1f72422..5e0b4fa 100644 --- a/server/src/domain/ldap/utils.rs +++ b/server/src/domain/ldap/utils.rs @@ -7,10 +7,11 @@ use tracing::{debug, instrument, warn}; use crate::domain::{ handler::SubStringFilter, ldap::error::{LdapError, LdapResult}, + model::UserColumn, schema::{PublicSchema, SchemaAttributeExtractor}, - types::{ - AttributeName, AttributeType, AttributeValue, GroupName, JpegPhoto, UserColumn, UserId, - }, +}; +use lldap_domain::types::{ + AttributeName, AttributeType, AttributeValue, GroupName, JpegPhoto, UserId, }; impl From for SubStringFilter { diff --git a/server/src/domain/mod.rs b/server/src/domain/mod.rs index 9475249..80e5857 100644 --- a/server/src/domain/mod.rs +++ b/server/src/domain/mod.rs @@ -12,4 +12,3 @@ pub mod sql_opaque_handler; pub mod sql_schema_backend_handler; pub mod sql_tables; pub mod sql_user_backend_handler; -pub mod types; diff --git a/server/src/domain/model/group_attribute_schema.rs b/server/src/domain/model/group_attribute_schema.rs index 4529185..d9fd9e4 100644 --- a/server/src/domain/model/group_attribute_schema.rs +++ b/server/src/domain/model/group_attribute_schema.rs @@ -1,8 +1,8 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::{ - handler::AttributeSchema, +use lldap_domain::{ + schema::AttributeSchema, types::{AttributeName, AttributeType}, }; diff --git a/server/src/domain/model/group_attributes.rs b/server/src/domain/model/group_attributes.rs index eddc513..933c8e4 100644 --- a/server/src/domain/model/group_attributes.rs +++ b/server/src/domain/model/group_attributes.rs @@ -1,7 +1,7 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::types::{AttributeName, AttributeValue, GroupId, Serialized}; +use lldap_domain::types::{AttributeName, AttributeValue, GroupId, Serialized}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "group_attributes")] diff --git a/server/src/domain/model/group_object_classes.rs b/server/src/domain/model/group_object_classes.rs index 2f653c3..155f73d 100644 --- a/server/src/domain/model/group_object_classes.rs +++ b/server/src/domain/model/group_object_classes.rs @@ -1,7 +1,7 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::types::LdapObjectClass; +use lldap_domain::types::LdapObjectClass; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "group_object_classes")] diff --git a/server/src/domain/model/groups.rs b/server/src/domain/model/groups.rs index e0c960d..a44d10e 100644 --- a/server/src/domain/model/groups.rs +++ b/server/src/domain/model/groups.rs @@ -3,7 +3,7 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::types::{GroupId, GroupName, Uuid}; +use lldap_domain::types::{GroupId, GroupName, Uuid}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "groups")] @@ -30,7 +30,7 @@ impl Related for Entity { impl ActiveModelBehavior for ActiveModel {} -impl From for crate::domain::types::Group { +impl From for lldap_domain::types::Group { fn from(group: Model) -> Self { Self { id: group.group_id, @@ -43,7 +43,7 @@ impl From for crate::domain::types::Group { } } -impl From for crate::domain::types::GroupDetails { +impl From for lldap_domain::types::GroupDetails { fn from(group: Model) -> Self { Self { group_id: group.group_id, diff --git a/server/src/domain/model/jwt_refresh_storage.rs b/server/src/domain/model/jwt_refresh_storage.rs index ebca1b1..56afa5a 100644 --- a/server/src/domain/model/jwt_refresh_storage.rs +++ b/server/src/domain/model/jwt_refresh_storage.rs @@ -3,7 +3,7 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::types::UserId; +use lldap_domain::types::UserId; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "jwt_refresh_storage")] diff --git a/server/src/domain/model/jwt_storage.rs b/server/src/domain/model/jwt_storage.rs index 6ca9208..e8e0836 100644 --- a/server/src/domain/model/jwt_storage.rs +++ b/server/src/domain/model/jwt_storage.rs @@ -3,7 +3,7 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::types::UserId; +use lldap_domain::types::UserId; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "jwt_storage")] diff --git a/server/src/domain/model/memberships.rs b/server/src/domain/model/memberships.rs index a1fb5a7..9de4030 100644 --- a/server/src/domain/model/memberships.rs +++ b/server/src/domain/model/memberships.rs @@ -3,7 +3,7 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::types::{GroupId, UserId}; +use lldap_domain::types::{GroupId, UserId}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "memberships")] diff --git a/server/src/domain/model/password_reset_tokens.rs b/server/src/domain/model/password_reset_tokens.rs index a252b36..26d1ae7 100644 --- a/server/src/domain/model/password_reset_tokens.rs +++ b/server/src/domain/model/password_reset_tokens.rs @@ -3,7 +3,7 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::types::UserId; +use lldap_domain::types::UserId; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "password_reset_tokens")] diff --git a/server/src/domain/model/user_attribute_schema.rs b/server/src/domain/model/user_attribute_schema.rs index 434840e..7161b97 100644 --- a/server/src/domain/model/user_attribute_schema.rs +++ b/server/src/domain/model/user_attribute_schema.rs @@ -1,8 +1,8 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::{ - handler::AttributeSchema, +use lldap_domain::{ + schema::AttributeSchema, types::{AttributeName, AttributeType}, }; diff --git a/server/src/domain/model/user_attributes.rs b/server/src/domain/model/user_attributes.rs index d6b6aa2..7b2ccc2 100644 --- a/server/src/domain/model/user_attributes.rs +++ b/server/src/domain/model/user_attributes.rs @@ -1,7 +1,7 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::types::{AttributeName, AttributeValue, Serialized, UserId}; +use lldap_domain::types::{AttributeName, AttributeValue, Serialized, UserId}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "user_attributes")] diff --git a/server/src/domain/model/user_object_classes.rs b/server/src/domain/model/user_object_classes.rs index 9bdfe97..a3fb6ad 100644 --- a/server/src/domain/model/user_object_classes.rs +++ b/server/src/domain/model/user_object_classes.rs @@ -1,7 +1,7 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -use crate::domain::types::LdapObjectClass; +use lldap_domain::types::LdapObjectClass; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "user_object_classes")] diff --git a/server/src/domain/model/users.rs b/server/src/domain/model/users.rs index 6f7183a..6f17188 100644 --- a/server/src/domain/model/users.rs +++ b/server/src/domain/model/users.rs @@ -3,7 +3,7 @@ use sea_orm::{entity::prelude::*, sea_query::BlobSize}; use serde::{Deserialize, Serialize}; -use crate::domain::types::{Email, UserId, Uuid}; +use lldap_domain::types::{Email, UserId, Uuid}; #[derive(Copy, Clone, Default, Debug, DeriveEntity)] pub struct Entity; @@ -112,7 +112,7 @@ impl Related for Entity { impl ActiveModelBehavior for ActiveModel {} -impl From for crate::domain::types::User { +impl From for lldap_domain::types::User { fn from(user: Model) -> Self { Self { user_id: user.user_id, diff --git a/server/src/domain/opaque_handler.rs b/server/src/domain/opaque_handler.rs index 13ed81a..7e1cd1c 100644 --- a/server/src/domain/opaque_handler.rs +++ b/server/src/domain/opaque_handler.rs @@ -1,5 +1,6 @@ -use crate::domain::{error::Result, types::UserId}; +use crate::domain::error::Result; use async_trait::async_trait; +use lldap_domain::types::UserId; pub use lldap_auth::{login, registration}; diff --git a/server/src/domain/schema.rs b/server/src/domain/schema.rs index 8aad05c..2bf5ac0 100644 --- a/server/src/domain/schema.rs +++ b/server/src/domain/schema.rs @@ -1,5 +1,5 @@ -use crate::domain::{ - handler::{AttributeList, AttributeSchema, Schema}, +use lldap_domain::{ + schema::{AttributeList, AttributeSchema, Schema}, types::AttributeType, }; use serde::{Deserialize, Serialize}; diff --git a/server/src/domain/sql_backend_handler.rs b/server/src/domain/sql_backend_handler.rs index 5963e7d..2702771 100644 --- a/server/src/domain/sql_backend_handler.rs +++ b/server/src/domain/sql_backend_handler.rs @@ -23,15 +23,18 @@ pub mod tests { use crate::{ domain::{ handler::{ - CreateGroupRequest, CreateUserRequest, GroupBackendHandler, UserBackendHandler, - UserListerBackendHandler, UserRequestFilter, + GroupBackendHandler, UserBackendHandler, UserListerBackendHandler, + UserRequestFilter, }, sql_tables::init_table, - types::{GroupId, UserId}, }, infra::configuration::ConfigurationBuilder, }; use lldap_auth::{opaque, registration}; + use lldap_domain::{ + requests::{CreateGroupRequest, CreateUserRequest}, + types::{GroupId, UserId}, + }; use pretty_assertions::assert_eq; use sea_orm::Database; diff --git a/server/src/domain/sql_group_backend_handler.rs b/server/src/domain/sql_group_backend_handler.rs index ffa707a..911e43b 100644 --- a/server/src/domain/sql_group_backend_handler.rs +++ b/server/src/domain/sql_group_backend_handler.rs @@ -1,14 +1,14 @@ use crate::domain::{ error::{DomainError, Result}, - handler::{ - CreateGroupRequest, GroupBackendHandler, GroupListerBackendHandler, GroupRequestFilter, - UpdateGroupRequest, - }, + handler::{GroupBackendHandler, GroupListerBackendHandler, GroupRequestFilter}, model::{self, GroupColumn, MembershipColumn}, sql_backend_handler::SqlBackendHandler, - types::{AttributeName, AttributeValue, Group, GroupDetails, GroupId, Serialized, Uuid}, }; use async_trait::async_trait; +use lldap_domain::{ + requests::{CreateGroupRequest, UpdateGroupRequest}, + types::{AttributeName, AttributeValue, Group, GroupDetails, GroupId, Serialized, Uuid}, +}; use sea_orm::{ sea_query::{Alias, Cond, Expr, Func, IntoCondition, OnConflict, SimpleExpr}, ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, QueryFilter, QueryOrder, @@ -314,8 +314,11 @@ impl SqlBackendHandler { mod tests { use super::*; use crate::domain::{ - handler::{CreateAttributeRequest, SchemaBackendHandler, SubStringFilter}, + handler::{SchemaBackendHandler, SubStringFilter}, sql_backend_handler::tests::*, + }; + use lldap_domain::{ + requests::CreateAttributeRequest, types::{AttributeType, GroupName, Serialized, UserId}, }; use pretty_assertions::assert_eq; diff --git a/server/src/domain/sql_migrations.rs b/server/src/domain/sql_migrations.rs index 64630a1..82e4b8f 100644 --- a/server/src/domain/sql_migrations.rs +++ b/server/src/domain/sql_migrations.rs @@ -1,8 +1,6 @@ -use crate::domain::{ - sql_tables::{DbConnection, SchemaVersion, LAST_SCHEMA_VERSION}, - types::{AttributeType, GroupId, JpegPhoto, Serialized, UserId, Uuid}, -}; +use crate::domain::sql_tables::{DbConnection, SchemaVersion, LAST_SCHEMA_VERSION}; use itertools::Itertools; +use lldap_domain::types::{AttributeType, GroupId, JpegPhoto, Serialized, UserId, Uuid}; use sea_orm::{ sea_query::{ self, all, BinOper, BlobSize::Blob, ColumnDef, Expr, ForeignKey, ForeignKeyAction, Func, diff --git a/server/src/domain/sql_opaque_handler.rs b/server/src/domain/sql_opaque_handler.rs index 1aaedcb..14c6d30 100644 --- a/server/src/domain/sql_opaque_handler.rs +++ b/server/src/domain/sql_opaque_handler.rs @@ -4,11 +4,11 @@ use super::{ model::{self, UserColumn}, opaque_handler::{login, registration, OpaqueHandler}, sql_backend_handler::SqlBackendHandler, - types::UserId, }; use async_trait::async_trait; use base64::Engine; use lldap_auth::opaque; +use lldap_domain::types::UserId; use sea_orm::{ActiveModelTrait, ActiveValue, EntityTrait, QuerySelect}; use secstr::SecUtf8; use tracing::{debug, info, instrument, warn}; diff --git a/server/src/domain/sql_schema_backend_handler.rs b/server/src/domain/sql_schema_backend_handler.rs index bea2fbd..0aafeeb 100644 --- a/server/src/domain/sql_schema_backend_handler.rs +++ b/server/src/domain/sql_schema_backend_handler.rs @@ -1,14 +1,15 @@ use crate::domain::{ error::{DomainError, Result}, - handler::{ - AttributeList, AttributeSchema, CreateAttributeRequest, ReadSchemaBackendHandler, Schema, - SchemaBackendHandler, - }, + handler::{ReadSchemaBackendHandler, SchemaBackendHandler}, model, sql_backend_handler::SqlBackendHandler, - types::{AttributeName, LdapObjectClass}, }; use async_trait::async_trait; +use lldap_domain::{ + requests::CreateAttributeRequest, + schema::{AttributeList, AttributeSchema, Schema}, + types::{AttributeName, LdapObjectClass}, +}; use sea_orm::{ ActiveModelTrait, DatabaseTransaction, EntityTrait, QueryOrder, Set, TransactionTrait, }; @@ -175,10 +176,12 @@ impl SqlBackendHandler { mod tests { use super::*; use crate::domain::{ - handler::{AttributeList, UpdateUserRequest, UserBackendHandler, UserRequestFilter}, + handler::{UserBackendHandler, UserRequestFilter}, sql_backend_handler::tests::*, - types::{AttributeType, AttributeValue, Serialized}, }; + use lldap_domain::requests::UpdateUserRequest; + use lldap_domain::schema::AttributeList; + use lldap_domain::types::{AttributeType, AttributeValue, Serialized}; use pretty_assertions::assert_eq; #[tokio::test] diff --git a/server/src/domain/sql_tables.rs b/server/src/domain/sql_tables.rs index 6745e61..b297821 100644 --- a/server/src/domain/sql_tables.rs +++ b/server/src/domain/sql_tables.rs @@ -123,10 +123,8 @@ pub async fn set_private_key_info(pool: &DbConnection, info: PrivateKeyInfo) -> #[cfg(test)] mod tests { - use crate::domain::{ - sql_migrations, - types::{GroupId, JpegPhoto, Serialized, Uuid}, - }; + use crate::domain::sql_migrations; + use lldap_domain::types::{GroupId, JpegPhoto, Serialized, Uuid}; use pretty_assertions::assert_eq; use super::*; @@ -254,11 +252,11 @@ mod tests { vec![ SimpleUser { display_name: None, - uuid: crate::uuid!("a02eaf13-48a7-30f6-a3d4-040ff7c52b04") + uuid: lldap_domain::uuid!("a02eaf13-48a7-30f6-a3d4-040ff7c52b04") }, SimpleUser { display_name: Some("John Doe".to_owned()), - uuid: crate::uuid!("986765a5-3f03-389e-b47b-536b2d6e1bec") + uuid: lldap_domain::uuid!("986765a5-3f03-389e-b47b-536b2d6e1bec") } ] ); diff --git a/server/src/domain/sql_user_backend_handler.rs b/server/src/domain/sql_user_backend_handler.rs index a3768b5..fbbdf46 100644 --- a/server/src/domain/sql_user_backend_handler.rs +++ b/server/src/domain/sql_user_backend_handler.rs @@ -1,17 +1,17 @@ use crate::domain::{ error::{DomainError, Result}, - handler::{ - CreateUserRequest, UpdateUserRequest, UserBackendHandler, UserListerBackendHandler, - UserRequestFilter, - }, + handler::{UserBackendHandler, UserListerBackendHandler, UserRequestFilter}, model::{self, GroupColumn, UserColumn}, sql_backend_handler::SqlBackendHandler, +}; +use async_trait::async_trait; +use lldap_domain::{ + requests::{CreateUserRequest, UpdateUserRequest}, types::{ AttributeName, AttributeValue, GroupDetails, GroupId, Serialized, User, UserAndGroups, UserId, Uuid, }, }; -use async_trait::async_trait; use sea_orm::{ sea_query::{ query::OnConflict, Alias, Cond, Expr, Func, IntoColumnRef, IntoCondition, SimpleExpr, @@ -430,10 +430,9 @@ impl UserBackendHandler for SqlBackendHandler { mod tests { use super::*; use crate::domain::{ - handler::SubStringFilter, - sql_backend_handler::tests::*, - types::{JpegPhoto, UserColumn}, + handler::SubStringFilter, model::UserColumn, sql_backend_handler::tests::*, }; + use lldap_domain::types::JpegPhoto; use pretty_assertions::{assert_eq, assert_ne}; #[tokio::test] diff --git a/server/src/infra/access_control.rs b/server/src/infra/access_control.rs index 976df75..312fb19 100644 --- a/server/src/infra/access_control.rs +++ b/server/src/infra/access_control.rs @@ -6,12 +6,18 @@ use tracing::info; use crate::domain::{ error::Result, handler::{ - AttributeSchema, BackendHandler, CreateAttributeRequest, CreateGroupRequest, - CreateUserRequest, GroupBackendHandler, GroupListerBackendHandler, GroupRequestFilter, - ReadSchemaBackendHandler, Schema, SchemaBackendHandler, UpdateGroupRequest, - UpdateUserRequest, UserBackendHandler, UserListerBackendHandler, UserRequestFilter, + BackendHandler, GroupBackendHandler, GroupListerBackendHandler, GroupRequestFilter, + ReadSchemaBackendHandler, SchemaBackendHandler, UserBackendHandler, + UserListerBackendHandler, UserRequestFilter, }, schema::PublicSchema, +}; +use lldap_domain::{ + requests::{ + CreateAttributeRequest, CreateGroupRequest, CreateUserRequest, UpdateGroupRequest, + UpdateUserRequest, + }, + schema::{AttributeSchema, Schema}, types::{ AttributeName, Group, GroupDetails, GroupId, GroupName, LdapObjectClass, User, UserAndGroups, UserId, diff --git a/server/src/infra/auth_service.rs b/server/src/infra/auth_service.rs index 39e0e08..8846418 100644 --- a/server/src/infra/auth_service.rs +++ b/server/src/infra/auth_service.rs @@ -22,13 +22,14 @@ use time::ext::NumericalDuration; use tracing::{debug, info, instrument, warn}; use lldap_auth::{login, password_reset, registration, JWTClaims}; +use lldap_domain::types::{GroupDetails, GroupName, UserId}; use crate::{ domain::{ error::DomainError, handler::{BackendHandler, BindRequest, LoginHandler, UserRequestFilter}, + model::UserColumn, opaque_handler::OpaqueHandler, - types::{GroupDetails, GroupName, UserColumn, UserId}, }, infra::{ access_control::{ReadonlyBackendHandler, UserReadableBackendHandler, ValidationResults}, diff --git a/server/src/infra/configuration.rs b/server/src/infra/configuration.rs index 60c713d..421039c 100644 --- a/server/src/infra/configuration.rs +++ b/server/src/infra/configuration.rs @@ -1,10 +1,7 @@ use std::collections::HashSet; use crate::{ - domain::{ - sql_tables::{ConfigLocation, PrivateKeyHash, PrivateKeyInfo, PrivateKeyLocation}, - types::{AttributeName, UserId}, - }, + domain::sql_tables::{ConfigLocation, PrivateKeyHash, PrivateKeyInfo, PrivateKeyLocation}, infra::{ cli::{ GeneralConfigOpts, LdapsOpts, RunOpts, SmtpEncryption, SmtpOpts, TestEmailOpts, @@ -20,6 +17,7 @@ use figment::{ }; use figment_file_provider_adapter::FileAdapter; use lldap_auth::opaque::{server::ServerSetup, KeyPair}; +use lldap_domain::types::{AttributeName, UserId}; use secstr::SecUtf8; use serde::{Deserialize, Serialize}; use std::path::PathBuf; @@ -623,7 +621,7 @@ where Either set the `jwt_secret` config value or the `LLDAP_JWT_SECRET` environment variable. \ You can generate the value by running\n\ LC_ALL=C tr -dc 'A-Za-z0-9!#%&'\\''()*+,-./:;<=>?@[\\]^_{{|}}~' { diff --git a/server/src/infra/graphql/mutation.rs b/server/src/infra/graphql/mutation.rs index ef15aa1..ad51bdb 100644 --- a/server/src/infra/graphql/mutation.rs +++ b/server/src/infra/graphql/mutation.rs @@ -2,16 +2,7 @@ use std::sync::Arc; use crate::{ domain::{ - deserialize::deserialize_attribute_value, - handler::{ - AttributeList, BackendHandler, CreateAttributeRequest, CreateGroupRequest, - CreateUserRequest, UpdateGroupRequest, UpdateUserRequest, - }, - schema::PublicSchema, - types::{ - AttributeName, AttributeType, AttributeValue as DomainAttributeValue, Email, GroupId, - JpegPhoto, LdapObjectClass, UserId, - }, + deserialize::deserialize_attribute_value, handler::BackendHandler, schema::PublicSchema, }, infra::{ access_control::{ @@ -24,6 +15,17 @@ use crate::{ use anyhow::{anyhow, Context as AnyhowContext}; use base64::Engine; use juniper::{graphql_object, FieldError, FieldResult, GraphQLInputObject, GraphQLObject}; +use lldap_domain::{ + requests::{ + CreateAttributeRequest, CreateGroupRequest, CreateUserRequest, UpdateGroupRequest, + UpdateUserRequest, + }, + schema::AttributeList, + types::{ + AttributeName, AttributeType, AttributeValue as DomainAttributeValue, Email, GroupId, + JpegPhoto, LdapObjectClass, UserId, + }, +}; use lldap_validation::attributes::{validate_attribute_name, ALLOWED_CHARACTERS_DESCRIPTION}; use tracing::{debug, debug_span, Instrument, Span}; @@ -731,18 +733,16 @@ fn deserialize_attribute( mod tests { use super::*; - use crate::{ - domain::types::{AttributeName, AttributeType}, - infra::{ - access_control::{Permission, ValidationResults}, - graphql::query::Query, - test_utils::MockTestBackendHandler, - }, + use crate::infra::{ + access_control::{Permission, ValidationResults}, + graphql::query::Query, + test_utils::MockTestBackendHandler, }; use juniper::{ execute, graphql_value, DefaultScalarValue, EmptySubscription, GraphQLType, InputValue, RootNode, Variables, }; + use lldap_domain::types::{AttributeName, AttributeType}; use mockall::predicate::eq; use pretty_assertions::assert_eq; diff --git a/server/src/infra/graphql/query.rs b/server/src/infra/graphql/query.rs index 4265609..c9e481b 100644 --- a/server/src/infra/graphql/query.rs +++ b/server/src/infra/graphql/query.rs @@ -7,9 +7,6 @@ use crate::{ ldap::utils::{map_user_field, UserFieldType}, model::UserColumn, schema::PublicSchema, - types::{ - AttributeType, GroupDetails, GroupId, JpegPhoto, LdapObjectClass, Serialized, UserId, - }, }, infra::{ access_control::{ReadonlyBackendHandler, UserReadableBackendHandler}, @@ -19,16 +16,19 @@ use crate::{ use anyhow::Context as AnyhowContext; use chrono::{NaiveDateTime, TimeZone}; use juniper::{graphql_object, FieldResult, GraphQLInputObject}; +use lldap_domain::types::{ + AttributeType, GroupDetails, GroupId, JpegPhoto, LdapObjectClass, Serialized, UserId, +}; use serde::{Deserialize, Serialize}; use tracing::{debug, debug_span, Instrument, Span}; type DomainRequestFilter = crate::domain::handler::UserRequestFilter; -type DomainUser = crate::domain::types::User; -type DomainGroup = crate::domain::types::Group; -type DomainUserAndGroups = crate::domain::types::UserAndGroups; -type DomainAttributeList = crate::domain::handler::AttributeList; -type DomainAttributeSchema = crate::domain::handler::AttributeSchema; -type DomainAttributeValue = crate::domain::types::AttributeValue; +type DomainUser = lldap_domain::types::User; +type DomainGroup = lldap_domain::types::Group; +type DomainUserAndGroups = lldap_domain::types::UserAndGroups; +type DomainAttributeList = lldap_domain::schema::AttributeList; +type DomainAttributeSchema = lldap_domain::schema::AttributeSchema; +type DomainAttributeValue = lldap_domain::types::AttributeValue; #[derive(PartialEq, Eq, Debug, GraphQLInputObject)] /// A filter for requests, specifying a boolean expression based on field constraints. Only one of @@ -801,21 +801,19 @@ impl AttributeValue { #[cfg(test)] mod tests { use super::*; - use crate::{ - domain::{ - handler::AttributeList, - types::{AttributeName, AttributeType, LdapObjectClass, Serialized}, - }, - infra::{ - access_control::{Permission, ValidationResults}, - test_utils::{setup_default_schema, MockTestBackendHandler}, - }, + use crate::infra::{ + access_control::{Permission, ValidationResults}, + test_utils::{setup_default_schema, MockTestBackendHandler}, }; use chrono::TimeZone; use juniper::{ execute, graphql_value, DefaultScalarValue, EmptyMutation, EmptySubscription, GraphQLType, RootNode, Variables, }; + use lldap_domain::{ + schema::{AttributeList, Schema}, + types::{AttributeName, AttributeType, LdapObjectClass, Serialized}, + }; use mockall::predicate::eq; use pretty_assertions::assert_eq; use std::collections::HashSet; @@ -860,7 +858,7 @@ mod tests { let mut mock = MockTestBackendHandler::new(); mock.expect_get_schema().returning(|| { - Ok(crate::domain::handler::Schema { + Ok(Schema { user_attributes: DomainAttributeList { attributes: vec![ DomainAttributeSchema { @@ -908,7 +906,7 @@ mod tests { user_id: UserId::new("bob"), email: "bob@bobbers.on".into(), creation_date: chrono::Utc.timestamp_millis_opt(42).unwrap().naive_utc(), - uuid: crate::uuid!("b1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"), + uuid: lldap_domain::uuid!("b1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"), attributes: vec![ DomainAttributeValue { name: "first_name".into(), @@ -927,7 +925,7 @@ mod tests { group_id: GroupId(3), display_name: "Bobbersons".into(), creation_date: chrono::Utc.timestamp_nanos(42).naive_utc(), - uuid: crate::uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"), + uuid: lldap_domain::uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"), attributes: vec![DomainAttributeValue { name: "club_name".into(), value: Serialized::from("Gang of Four"), @@ -937,7 +935,7 @@ mod tests { group_id: GroupId(7), display_name: "Jefferees".into(), creation_date: chrono::Utc.timestamp_nanos(12).naive_utc(), - uuid: crate::uuid!("b1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"), + uuid: lldap_domain::uuid!("b1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"), attributes: Vec::new(), }); mock.expect_get_user_groups() @@ -1299,7 +1297,7 @@ mod tests { let mut mock = MockTestBackendHandler::new(); mock.expect_get_schema().times(1).return_once(|| { - Ok(crate::domain::handler::Schema { + Ok(Schema { user_attributes: AttributeList { attributes: vec![DomainAttributeSchema { name: "invisible".into(), diff --git a/server/src/infra/ldap_handler.rs b/server/src/infra/ldap_handler.rs index 7257c31..e943f7d 100644 --- a/server/src/infra/ldap_handler.rs +++ b/server/src/infra/ldap_handler.rs @@ -1,8 +1,6 @@ use crate::{ domain::{ - handler::{ - BackendHandler, BindRequest, CreateUserRequest, LoginHandler, ReadSchemaBackendHandler, - }, + handler::{BackendHandler, BindRequest, LoginHandler, ReadSchemaBackendHandler}, ldap::{ error::{LdapError, LdapResult}, group::{convert_groups_to_ldap_op, get_groups_list}, @@ -13,7 +11,6 @@ use crate::{ }, opaque_handler::OpaqueHandler, schema::PublicSchema, - types::{AttributeName, Email, Group, JpegPhoto, UserAndGroups, UserId}, }, infra::access_control::{ AccessControlledBackendHandler, AdminBackendHandler, UserAndGroupListerBackendHandler, @@ -28,6 +25,10 @@ use ldap3_proto::proto::{ LdapResult as LdapResultOp, LdapResultCode, LdapSearchRequest, LdapSearchResultEntry, LdapSearchScope, }; +use lldap_domain::{ + requests::CreateUserRequest, + types::{AttributeName, Email, Group, JpegPhoto, UserAndGroups, UserId}, +}; use std::collections::HashMap; use tracing::{debug, instrument, warn}; @@ -879,12 +880,15 @@ impl LdapHandler