refactor: restructure domain crate by bounded context

This commit is contained in:
2026-05-31 04:44:48 +02:00
parent 2b62d1ec81
commit de93373b43
136 changed files with 2111 additions and 2096 deletions

View File

@@ -0,0 +1,84 @@
use domain::entities::permission::{
admin_permissions, contributor_permissions, viewer_permissions,
Permission, PermissionAction, ResourceType,
};
use domain::entities::{Group, Role, User};
use domain::errors::DomainError;
use domain::value_objects::{Email, PasswordHash, SystemId};
// --- Permission ---
#[test]
fn admin_is_superset_of_contributor() {
let admin = admin_permissions();
let contrib = contributor_permissions();
assert!(contrib.is_subset(&admin));
assert!(admin.len() > contrib.len());
}
#[test]
fn viewer_cannot_write() {
let viewer = viewer_permissions();
let write = Permission::new(PermissionAction::WriteMetadata, ResourceType::Global);
assert!(!viewer.contains(&write));
}
// --- Role ---
#[test]
fn role_checks_permission() {
let role = Role::new("viewer", viewer_permissions(), true);
assert!(role.has_permission(PermissionAction::ReadAsset, ResourceType::Global));
assert!(!role.has_permission(PermissionAction::DeleteAsset, ResourceType::Global));
}
// --- User ---
#[test]
fn creates_user_with_unique_id() {
let a = User::new("alice", Email::new("a@example.com").unwrap(), PasswordHash::from_hash("h".into()));
let b = User::new("bob", Email::new("b@example.com").unwrap(), PasswordHash::from_hash("h".into()));
assert_ne!(a.id, b.id);
assert_eq!(a.username, "alice");
assert_eq!(b.username, "bob");
}
// --- Group ---
#[test]
fn owner_auto_member() {
let owner = SystemId::new();
let g = Group::new("team", owner);
assert!(g.is_member(&owner));
assert_eq!(g.members.len(), 1);
}
#[test]
fn add_and_remove() {
let owner = SystemId::new();
let member = SystemId::new();
let mut g = Group::new("team", owner);
g.add_member(member).unwrap();
assert!(g.is_member(&member));
assert_eq!(g.members.len(), 2);
g.remove_member(member).unwrap();
assert!(!g.is_member(&member));
}
#[test]
fn cannot_remove_owner() {
let owner = SystemId::new();
let mut g = Group::new("team", owner);
let result = g.remove_member(owner);
assert!(matches!(result, Err(DomainError::Validation(_))));
}
#[test]
fn cannot_add_duplicate() {
let owner = SystemId::new();
let member = SystemId::new();
let mut g = Group::new("team", owner);
g.add_member(member).unwrap();
let result = g.add_member(member);
assert!(matches!(result, Err(DomainError::Conflict(_))));
}

View File

@@ -0,0 +1,2 @@
mod entities;
mod services;

View File

@@ -0,0 +1,41 @@
use domain::entities::{Permission, PermissionAction, ResourceType, Role};
use domain::entities::permission::{admin_permissions, viewer_permissions};
use domain::services::permission_service::PermissionChecker;
#[test]
fn viewer_can_read() {
let role = Role::new("viewer", viewer_permissions(), true);
assert!(PermissionChecker::has_permission(
&[role],
PermissionAction::ReadAsset,
ResourceType::Asset,
));
}
#[test]
fn viewer_cannot_delete() {
let role = Role::new("viewer", viewer_permissions(), true);
assert!(!PermissionChecker::has_permission(
&[role],
PermissionAction::DeleteAsset,
ResourceType::Asset,
));
}
#[test]
fn roles_additive() {
let r1 = Role::new("r1", [Permission::new(PermissionAction::ReadAsset, ResourceType::Global)].into(), false);
let r2 = Role::new("r2", [Permission::new(PermissionAction::WriteMetadata, ResourceType::Global)].into(), false);
let eff = PermissionChecker::effective_permissions(&[r1, r2]);
assert_eq!(eff.len(), 2);
}
#[test]
fn global_covers_specific() {
let role = Role::new("admin", admin_permissions(), true);
assert!(PermissionChecker::has_permission(
&[role],
PermissionAction::ReadAsset,
ResourceType::Album,
));
}