refactor(arch): enforce gateway compliance and remove service-wrapping gateways
This commit is contained in:
@@ -9,7 +9,6 @@ use MintyPHP\Repository\Access\RolePermissionRepository;
|
||||
use MintyPHP\Repository\Access\RoleRepository;
|
||||
use MintyPHP\Service\Access\AccessServicesFactory;
|
||||
use MintyPHP\Service\Access\AuthorizationService;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Access\RoleService;
|
||||
use MintyPHP\Service\Access\UiAccessService;
|
||||
@@ -19,7 +18,6 @@ final class AccessRegistrar implements ContainerRegistrar
|
||||
{
|
||||
public function register(AppContainer $container): void
|
||||
{
|
||||
$container->set(PermissionGateway::class, static fn (AppContainer $c): PermissionGateway => $c->get(AccessServicesFactory::class)->createPermissionGateway());
|
||||
$container->set(AuthorizationService::class, static fn (AppContainer $c): AuthorizationService => $c->get(AccessServicesFactory::class)->createAuthorizationService());
|
||||
$container->set(UiAccessService::class, static fn (AppContainer $c): UiAccessService => new UiAccessService(
|
||||
$c->get(AuthorizationService::class)
|
||||
|
||||
@@ -15,7 +15,7 @@ use MintyPHP\Http\SessionStoreInterface;
|
||||
use MintyPHP\Repository\Search\SearchQueryRepository;
|
||||
use MintyPHP\Repository\Stats\AdminStatsRepository;
|
||||
use MintyPHP\Repository\Tenant\UserTenantRepository;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\AddressBook\AddressBookService;
|
||||
use MintyPHP\Service\AddressBook\AddressBookServicesFactory;
|
||||
use MintyPHP\Service\Audit\ApiAuditService;
|
||||
@@ -49,7 +49,7 @@ final class AppServicesRegistrar implements ContainerRegistrar
|
||||
$c->get(AdminStatsRepository::class)
|
||||
));
|
||||
$container->set(SearchDataService::class, static fn (AppContainer $c): SearchDataService => new SearchDataService(
|
||||
$c->get(PermissionGateway::class),
|
||||
$c->get(PermissionService::class),
|
||||
$c->get(UserTenantRepository::class),
|
||||
$c->get(SearchQueryRepository::class)
|
||||
));
|
||||
|
||||
@@ -12,7 +12,6 @@ use MintyPHP\Repository\Tenant\TenantRepository;
|
||||
use MintyPHP\Service\Auth\ApiTokenEndpointService;
|
||||
use MintyPHP\Service\Auth\ApiTokenService;
|
||||
use MintyPHP\Service\Auth\AuthRepositoryFactory;
|
||||
use MintyPHP\Service\Auth\AuthScopeGateway;
|
||||
use MintyPHP\Service\Auth\AuthService;
|
||||
use MintyPHP\Service\Auth\AuthServicesFactory;
|
||||
use MintyPHP\Service\Auth\EmailVerificationService;
|
||||
@@ -32,14 +31,13 @@ final class AuthRegistrar implements ContainerRegistrar
|
||||
$container->set(ApiTokenEndpointService::class, static fn (AppContainer $c): ApiTokenEndpointService => new ApiTokenEndpointService(
|
||||
$c->get(AuthRepositoryFactory::class)->createApiTokenRepository(),
|
||||
$c->get(TenantRepository::class),
|
||||
$c->get(AuthScopeGateway::class)
|
||||
$c->get(\MintyPHP\Service\Tenant\TenantScopeService::class)
|
||||
));
|
||||
$container->set(PasswordResetService::class, static fn (AppContainer $c): PasswordResetService => $c->get(AuthServicesFactory::class)->createPasswordResetService());
|
||||
$container->set(EmailVerificationService::class, static fn (AppContainer $c): EmailVerificationService => $c->get(AuthServicesFactory::class)->createEmailVerificationService());
|
||||
$container->set(TenantSsoService::class, static fn (AppContainer $c): TenantSsoService => $c->get(AuthServicesFactory::class)->createTenantSsoService());
|
||||
$container->set(MicrosoftOidcService::class, static fn (AppContainer $c): MicrosoftOidcService => $c->get(AuthServicesFactory::class)->createMicrosoftOidcService());
|
||||
$container->set(SsoUserLinkService::class, static fn (AppContainer $c): SsoUserLinkService => $c->get(AuthServicesFactory::class)->createSsoUserLinkService());
|
||||
$container->set(AuthScopeGateway::class, static fn (AppContainer $c): AuthScopeGateway => $c->get(AuthServicesFactory::class)->createAuthScopeGateway());
|
||||
$container->set(TenantMicrosoftAuthRepository::class, static fn (AppContainer $c): TenantMicrosoftAuthRepository => $c->get(AuthRepositoryFactory::class)->createTenantMicrosoftAuthRepository());
|
||||
$container->set(ApiTokenRepository::class, static fn (AppContainer $c): ApiTokenRepository => $c->get(AuthRepositoryFactory::class)->createApiTokenRepository());
|
||||
$container->set(RememberTokenRepository::class, static fn (AppContainer $c): RememberTokenRepository => $c->get(AuthRepositoryFactory::class)->createRememberTokenRepository());
|
||||
|
||||
@@ -6,7 +6,6 @@ use MintyPHP\App\AppContainer;
|
||||
use MintyPHP\App\Container\ContainerRegistrar;
|
||||
use MintyPHP\Repository\Org\DepartmentRepository;
|
||||
use MintyPHP\Repository\Tenant\TenantRepository;
|
||||
use MintyPHP\Service\Directory\DirectoryScopeGateway;
|
||||
use MintyPHP\Service\Directory\DirectoryServicesFactory;
|
||||
use MintyPHP\Service\Directory\DirectorySettingsGateway;
|
||||
use MintyPHP\Service\Org\DepartmentService;
|
||||
@@ -23,7 +22,6 @@ final class DirectoryRegistrar implements ContainerRegistrar
|
||||
$container->set(TenantService::class, static fn (AppContainer $c): TenantService => $c->get(DirectoryServicesFactory::class)->createTenantService());
|
||||
$container->set(TenantScopeService::class, static fn (AppContainer $c): TenantScopeService => $c->get(TenantServicesFactory::class)->createTenantScopeService());
|
||||
$container->set(DepartmentService::class, static fn (AppContainer $c): DepartmentService => $c->get(DirectoryServicesFactory::class)->createDepartmentService());
|
||||
$container->set(DirectoryScopeGateway::class, static fn (AppContainer $c): DirectoryScopeGateway => $c->get(DirectoryServicesFactory::class)->createDirectoryScopeGateway());
|
||||
$container->set(DirectorySettingsGateway::class, static fn (AppContainer $c): DirectorySettingsGateway => $c->get(DirectoryServicesFactory::class)->createDirectorySettingsGateway());
|
||||
$container->set(TenantAvatarService::class, static fn (AppContainer $c): TenantAvatarService => $c->get(TenantServicesFactory::class)->createTenantAvatarService());
|
||||
$container->set(TenantFaviconService::class, static fn (AppContainer $c): TenantFaviconService => $c->get(TenantServicesFactory::class)->createTenantFaviconService());
|
||||
|
||||
@@ -13,7 +13,7 @@ use MintyPHP\Service\Access\AccessGatewayFactory;
|
||||
use MintyPHP\Service\Access\AccessPolicyFactory;
|
||||
use MintyPHP\Service\Access\AccessRepositoryFactory;
|
||||
use MintyPHP\Service\Access\AccessServicesFactory;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\AddressBook\AddressBookServicesFactory;
|
||||
use MintyPHP\Service\Audit\AuditRepositoryFactory;
|
||||
use MintyPHP\Service\Audit\AuditServicesFactory;
|
||||
@@ -24,7 +24,6 @@ use MintyPHP\Service\Branding\BrandingServicesFactory;
|
||||
use MintyPHP\Service\CustomField\CustomFieldServicesFactory;
|
||||
use MintyPHP\Service\Directory\DirectoryGatewayFactory;
|
||||
use MintyPHP\Service\Directory\DirectoryRepositoryFactory;
|
||||
use MintyPHP\Service\Directory\DirectoryScopeGateway;
|
||||
use MintyPHP\Service\Directory\DirectoryServicesFactory;
|
||||
use MintyPHP\Service\Import\ImportRepositoryFactory;
|
||||
use MintyPHP\Service\Import\ImportServicesFactory;
|
||||
@@ -41,7 +40,6 @@ use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\Tenant\TenantServicesFactory;
|
||||
use MintyPHP\Service\User\UserGatewayFactory;
|
||||
use MintyPHP\Service\User\UserRepositoryFactory;
|
||||
use MintyPHP\Service\User\UserScopeGateway;
|
||||
use MintyPHP\Service\User\UserServicesFactory;
|
||||
|
||||
final class ServiceFactoryRegistrar implements ContainerRegistrar
|
||||
@@ -69,10 +67,10 @@ final class ServiceFactoryRegistrar implements ContainerRegistrar
|
||||
));
|
||||
$container->set(CustomFieldServicesFactory::class, static fn (AppContainer $c): CustomFieldServicesFactory => new CustomFieldServicesFactory(
|
||||
$c->get(TenantRepository::class),
|
||||
$c->get(UserScopeGateway::class)
|
||||
$c->get(TenantScopeService::class)
|
||||
));
|
||||
$container->set(TenantServicesFactory::class, static fn (AppContainer $c): TenantServicesFactory => new TenantServicesFactory(
|
||||
$c->get(PermissionGateway::class),
|
||||
$c->get(PermissionService::class),
|
||||
$c->get(TenantRepositoryFactory::class)
|
||||
));
|
||||
$container->set(ImportServicesFactory::class, static fn (AppContainer $c): ImportServicesFactory => new ImportServicesFactory(
|
||||
@@ -81,6 +79,7 @@ final class ServiceFactoryRegistrar implements ContainerRegistrar
|
||||
$c->get(SettingServicesFactory::class),
|
||||
$c->get(DirectoryServicesFactory::class),
|
||||
$c->get(ImportRepositoryFactory::class),
|
||||
$c->get(TenantScopeService::class),
|
||||
$c->get(SessionStoreInterface::class)
|
||||
));
|
||||
$container->set(SchedulerServicesFactory::class, static fn (AppContainer $c): SchedulerServicesFactory => new SchedulerServicesFactory(
|
||||
@@ -92,7 +91,8 @@ final class ServiceFactoryRegistrar implements ContainerRegistrar
|
||||
$container->set(AddressBookServicesFactory::class, static fn (AppContainer $c): AddressBookServicesFactory => new AddressBookServicesFactory(
|
||||
$c->get(UserServicesFactory::class),
|
||||
$c->get(DirectoryServicesFactory::class),
|
||||
$c->get(CustomFieldServicesFactory::class)
|
||||
$c->get(CustomFieldServicesFactory::class),
|
||||
$c->get(TenantScopeService::class)
|
||||
));
|
||||
$container->set(DirectoryServicesFactory::class, static fn (AppContainer $c): DirectoryServicesFactory => new DirectoryServicesFactory(
|
||||
$c->get(UserServicesFactory::class),
|
||||
@@ -108,7 +108,7 @@ final class ServiceFactoryRegistrar implements ContainerRegistrar
|
||||
$c->get(AccessRepositoryFactory::class),
|
||||
$c->get(AccessGatewayFactory::class),
|
||||
// Wrapped in a second closure to break the circular dependency:
|
||||
// AccessServicesFactory <-> AccessPolicyFactory via PermissionGateway.
|
||||
// AccessServicesFactory <-> AccessPolicyFactory via PermissionService.
|
||||
static fn (): AccessPolicyFactory => $c->get(AccessPolicyFactory::class)
|
||||
));
|
||||
$container->set(AccessGatewayFactory::class, static fn (AppContainer $c): AccessGatewayFactory => new AccessGatewayFactory(
|
||||
@@ -117,8 +117,8 @@ final class ServiceFactoryRegistrar implements ContainerRegistrar
|
||||
$c->get(SessionStoreInterface::class)
|
||||
));
|
||||
$container->set(AccessPolicyFactory::class, static fn (AppContainer $c): AccessPolicyFactory => new AccessPolicyFactory(
|
||||
$c->get(PermissionGateway::class),
|
||||
$c->get(DirectoryScopeGateway::class)
|
||||
$c->get(PermissionService::class),
|
||||
$c->get(TenantScopeService::class)
|
||||
));
|
||||
$container->set(UserGatewayFactory::class, static fn (AppContainer $c): UserGatewayFactory => new UserGatewayFactory(
|
||||
$c->get(AccessServicesFactory::class),
|
||||
@@ -135,7 +135,6 @@ final class ServiceFactoryRegistrar implements ContainerRegistrar
|
||||
$container->set(AuthGatewayFactory::class, static fn (AppContainer $c): AuthGatewayFactory => new AuthGatewayFactory(
|
||||
$c->get(AuthRepositoryFactory::class),
|
||||
$c->get(AccessServicesFactory::class),
|
||||
$c->get(UserServicesFactory::class),
|
||||
$c->get(SettingServicesFactory::class),
|
||||
$c->get(TenantScopeService::class)
|
||||
));
|
||||
|
||||
@@ -26,7 +26,7 @@ use MintyPHP\Service\Settings\SettingsSessionGateway;
|
||||
use MintyPHP\Service\Settings\SettingsSmtpGateway;
|
||||
use MintyPHP\Service\Settings\SettingsSystemAuditGateway;
|
||||
use MintyPHP\Service\Settings\SettingsUserLifecycleGateway;
|
||||
use MintyPHP\Service\Settings\ThemeConfigService;
|
||||
use MintyPHP\Service\Settings\ThemeConfigGateway;
|
||||
use MintyPHP\Service\Tenant\TenantService;
|
||||
|
||||
final class SettingsRegistrar implements ContainerRegistrar
|
||||
@@ -65,7 +65,7 @@ final class SettingsRegistrar implements ContainerRegistrar
|
||||
$c->get(ApiTokenRepository::class),
|
||||
$c->get(SystemAuditService::class)
|
||||
));
|
||||
$container->set(ThemeConfigService::class, static fn (AppContainer $c): ThemeConfigService => $c->get(SettingServicesFactory::class)->createThemeConfigService());
|
||||
$container->set(ThemeConfigGateway::class, static fn (AppContainer $c): ThemeConfigGateway => $c->get(SettingServicesFactory::class)->createThemeConfigGateway());
|
||||
// Branding services are registered here because they depend on settings gateways
|
||||
// and are consumed alongside settings (e.g. in UserAccessPdfService and the admin UI).
|
||||
$container->set(BrandingLogoService::class, static fn (AppContainer $c): BrandingLogoService => $c->get(BrandingServicesFactory::class)->createBrandingLogoService());
|
||||
|
||||
@@ -24,7 +24,6 @@ use MintyPHP\Service\User\UserPasswordPolicyService;
|
||||
use MintyPHP\Service\User\UserPasswordService;
|
||||
use MintyPHP\Service\User\UserRepositoryFactory;
|
||||
use MintyPHP\Service\User\UserSavedFilterService;
|
||||
use MintyPHP\Service\User\UserScopeGateway;
|
||||
use MintyPHP\Service\User\UserServicesFactory;
|
||||
use MintyPHP\Service\User\UserTenantContextService;
|
||||
|
||||
@@ -37,7 +36,6 @@ final class UserRegistrar implements ContainerRegistrar
|
||||
$container->set(UserPasswordService::class, static fn (AppContainer $c): UserPasswordService => $c->get(UserServicesFactory::class)->createUserPasswordService());
|
||||
$container->set(UserAvatarService::class, static fn (AppContainer $c): UserAvatarService => $c->get(UserServicesFactory::class)->createUserAvatarService());
|
||||
$container->set(UserDirectoryGateway::class, static fn (AppContainer $c): UserDirectoryGateway => $c->get(UserServicesFactory::class)->createUserDirectoryGateway());
|
||||
$container->set(UserScopeGateway::class, static fn (AppContainer $c): UserScopeGateway => $c->get(UserServicesFactory::class)->createUserScopeGateway());
|
||||
$container->set(UserAccessTemplateService::class, static fn (AppContainer $c): UserAccessTemplateService => new UserAccessTemplateService(
|
||||
$c->get(TenantSsoService::class),
|
||||
$c->get(UserDirectoryGateway::class),
|
||||
|
||||
@@ -6,14 +6,14 @@ use MintyPHP\Repository\Access\RolePermissionRepository;
|
||||
use MintyPHP\Repository\Access\UserRoleRepository;
|
||||
use MintyPHP\Service\Access\AuthorizationService;
|
||||
use MintyPHP\Service\Auth\ApiTokenService;
|
||||
use MintyPHP\Service\Auth\AuthScopeGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserTenantContextService;
|
||||
|
||||
// Static facade for API authentication — state is set once per request during ApiBootstrap::init().
|
||||
// Dependencies are injected as lazy resolvers so services are only instantiated when actually needed.
|
||||
class ApiAuth
|
||||
{
|
||||
/** @var (callable(): AuthScopeGateway)|null */
|
||||
/** @var (callable(): TenantScopeService)|null */
|
||||
private static $authScopeGatewayResolver = null;
|
||||
|
||||
/** @var (callable(): ApiTokenService)|null */
|
||||
@@ -239,9 +239,9 @@ class ApiAuth
|
||||
}
|
||||
}
|
||||
|
||||
private static function scopeGateway(): AuthScopeGateway
|
||||
private static function scopeGateway(): TenantScopeService
|
||||
{
|
||||
return self::resolveDependency(self::$authScopeGatewayResolver, AuthScopeGateway::class, 'ApiAuth');
|
||||
return self::resolveDependency(self::$authScopeGatewayResolver, TenantScopeService::class, 'ApiAuth');
|
||||
}
|
||||
|
||||
private static function apiTokenService(): ApiTokenService
|
||||
|
||||
@@ -8,7 +8,6 @@ use MintyPHP\Service\Audit\AuditServicesFactory;
|
||||
class AccessGatewayFactory
|
||||
{
|
||||
private ?PermissionService $permissionService = null;
|
||||
private ?PermissionGateway $permissionGateway = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly AccessRepositoryFactory $accessRepositoryFactory,
|
||||
@@ -28,8 +27,4 @@ class AccessGatewayFactory
|
||||
);
|
||||
}
|
||||
|
||||
public function createPermissionGateway(): PermissionGateway
|
||||
{
|
||||
return $this->permissionGateway ??= new PermissionGateway($this->createPermissionService());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace MintyPHP\Service\Access;
|
||||
|
||||
use MintyPHP\Service\Directory\DirectoryScopeGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class AccessPolicyFactory
|
||||
{
|
||||
@@ -16,52 +16,52 @@ class AccessPolicyFactory
|
||||
private ?AuthorizationService $authorizationService = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway,
|
||||
private readonly DirectoryScopeGateway $directoryScopeGateway
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly TenantScopeService $tenantScopeService
|
||||
) {
|
||||
}
|
||||
|
||||
public function createUserAuthorizationPolicy(): UserAuthorizationPolicy
|
||||
{
|
||||
return $this->userAuthorizationPolicy ??= new UserAuthorizationPolicy(
|
||||
$this->permissionGateway,
|
||||
$this->directoryScopeGateway
|
||||
$this->permissionService,
|
||||
$this->tenantScopeService
|
||||
);
|
||||
}
|
||||
|
||||
public function createRoleAuthorizationPolicy(): RoleAuthorizationPolicy
|
||||
{
|
||||
return $this->roleAuthorizationPolicy ??= new RoleAuthorizationPolicy($this->permissionGateway);
|
||||
return $this->roleAuthorizationPolicy ??= new RoleAuthorizationPolicy($this->permissionService);
|
||||
}
|
||||
|
||||
public function createPermissionAuthorizationPolicy(): PermissionAuthorizationPolicy
|
||||
{
|
||||
return $this->permissionAuthorizationPolicy ??= new PermissionAuthorizationPolicy($this->permissionGateway);
|
||||
return $this->permissionAuthorizationPolicy ??= new PermissionAuthorizationPolicy($this->permissionService);
|
||||
}
|
||||
|
||||
public function createOperationsAuthorizationPolicy(): OperationsAuthorizationPolicy
|
||||
{
|
||||
return $this->operationsAuthorizationPolicy ??= new OperationsAuthorizationPolicy($this->permissionGateway);
|
||||
return $this->operationsAuthorizationPolicy ??= new OperationsAuthorizationPolicy($this->permissionService);
|
||||
}
|
||||
|
||||
public function createSettingsAuthorizationPolicy(): SettingsAuthorizationPolicy
|
||||
{
|
||||
return $this->settingsAuthorizationPolicy ??= new SettingsAuthorizationPolicy($this->permissionGateway);
|
||||
return $this->settingsAuthorizationPolicy ??= new SettingsAuthorizationPolicy($this->permissionService);
|
||||
}
|
||||
|
||||
public function createTenantAuthorizationPolicy(): TenantAuthorizationPolicy
|
||||
{
|
||||
return $this->tenantAuthorizationPolicy ??= new TenantAuthorizationPolicy(
|
||||
$this->permissionGateway,
|
||||
$this->directoryScopeGateway
|
||||
$this->permissionService,
|
||||
$this->tenantScopeService
|
||||
);
|
||||
}
|
||||
|
||||
public function createDepartmentAuthorizationPolicy(): DepartmentAuthorizationPolicy
|
||||
{
|
||||
return $this->departmentAuthorizationPolicy ??= new DepartmentAuthorizationPolicy(
|
||||
$this->permissionGateway,
|
||||
$this->directoryScopeGateway
|
||||
$this->permissionService,
|
||||
$this->tenantScopeService
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,6 @@ class AccessServicesFactory
|
||||
return $this->accessGatewayFactory->createPermissionService();
|
||||
}
|
||||
|
||||
public function createPermissionGateway(): PermissionGateway
|
||||
{
|
||||
return $this->accessGatewayFactory->createPermissionGateway();
|
||||
}
|
||||
|
||||
public function createUserAuthorizationPolicy(): UserAuthorizationPolicy
|
||||
{
|
||||
return $this->accessPolicyFactory()->createUserAuthorizationPolicy();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace MintyPHP\Service\Access;
|
||||
|
||||
use MintyPHP\Service\Directory\DirectoryScopeGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class DepartmentAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
{
|
||||
@@ -13,8 +13,8 @@ class DepartmentAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
public const ABILITY_ADMIN_DEPARTMENTS_DELETE = 'admin.departments.delete';
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway,
|
||||
private readonly DirectoryScopeGateway $scopeGateway
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly TenantScopeService $scopeGateway
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ class DepartmentAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
|
||||
private function hasPermission(int $userId, string $permissionKey): bool
|
||||
{
|
||||
return $userId > 0 && $this->permissionGateway->userHas($userId, $permissionKey);
|
||||
return $userId > 0 && $this->permissionService->userHas($userId, $permissionKey);
|
||||
}
|
||||
|
||||
private function capabilitiesFromDecision(AuthorizationDecision $decision): array
|
||||
|
||||
@@ -42,7 +42,7 @@ final class OperationsAuthorizationPolicy implements AuthorizationPolicyInterfac
|
||||
public const ABILITY_API_TOKENS_SELF_MANAGE = 'ops.api.tokens.self_manage';
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway
|
||||
private readonly PermissionService $permissionService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -138,10 +138,10 @@ final class OperationsAuthorizationPolicy implements AuthorizationPolicyInterfac
|
||||
|
||||
private function authorizeUsersCreateCustomFields(int $actorUserId): AuthorizationDecision
|
||||
{
|
||||
if (!$this->permissionGateway->userHas($actorUserId, PermissionService::CUSTOM_FIELDS_EDIT_VALUES)) {
|
||||
if (!$this->permissionService->userHas($actorUserId, PermissionService::CUSTOM_FIELDS_EDIT_VALUES)) {
|
||||
return AuthorizationDecision::deny(403, 'forbidden');
|
||||
}
|
||||
if (!$this->permissionGateway->userHas($actorUserId, PermissionService::USERS_UPDATE_ASSIGNMENTS)) {
|
||||
if (!$this->permissionService->userHas($actorUserId, PermissionService::USERS_UPDATE_ASSIGNMENTS)) {
|
||||
return AuthorizationDecision::deny(403, 'forbidden');
|
||||
}
|
||||
return AuthorizationDecision::allow();
|
||||
@@ -149,10 +149,10 @@ final class OperationsAuthorizationPolicy implements AuthorizationPolicyInterfac
|
||||
|
||||
private function authorizeApiTokensSelfManage(int $actorUserId): AuthorizationDecision
|
||||
{
|
||||
if ($this->permissionGateway->userHas($actorUserId, PermissionService::USERS_SELF_UPDATE)) {
|
||||
if ($this->permissionService->userHas($actorUserId, PermissionService::USERS_SELF_UPDATE)) {
|
||||
return AuthorizationDecision::allow();
|
||||
}
|
||||
if ($this->permissionGateway->userHas($actorUserId, PermissionService::API_TOKENS_MANAGE)) {
|
||||
if ($this->permissionService->userHas($actorUserId, PermissionService::API_TOKENS_MANAGE)) {
|
||||
return AuthorizationDecision::allow();
|
||||
}
|
||||
return AuthorizationDecision::deny(403, 'forbidden');
|
||||
@@ -160,7 +160,7 @@ final class OperationsAuthorizationPolicy implements AuthorizationPolicyInterfac
|
||||
|
||||
private function allowIfHas(int $actorUserId, string $permissionKey): AuthorizationDecision
|
||||
{
|
||||
if (!$this->permissionGateway->userHas($actorUserId, $permissionKey)) {
|
||||
if (!$this->permissionService->userHas($actorUserId, $permissionKey)) {
|
||||
return AuthorizationDecision::deny(403, 'forbidden');
|
||||
}
|
||||
return AuthorizationDecision::allow();
|
||||
|
||||
@@ -11,7 +11,7 @@ class PermissionAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
public const ABILITY_ADMIN_PERMISSIONS_DELETE = 'admin.permissions.delete';
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway
|
||||
private readonly PermissionService $permissionService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ class PermissionAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
|
||||
private function hasPermission(int $userId, string $permissionKey): bool
|
||||
{
|
||||
return $userId > 0 && $this->permissionGateway->userHas($userId, $permissionKey);
|
||||
return $userId > 0 && $this->permissionService->userHas($userId, $permissionKey);
|
||||
}
|
||||
|
||||
private function capabilitiesFromDecision(AuthorizationDecision $decision): array
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\Access;
|
||||
|
||||
class PermissionGateway
|
||||
{
|
||||
public function __construct(private readonly PermissionService $permissionService)
|
||||
{
|
||||
}
|
||||
|
||||
public function userHas(int $userId, string $permissionKey): bool
|
||||
{
|
||||
return $this->permissionService->userHas($userId, $permissionKey);
|
||||
}
|
||||
|
||||
public function getUserPermissions(int $userId, bool $refresh = false): array
|
||||
{
|
||||
return $this->permissionService->getUserPermissions($userId, $refresh);
|
||||
}
|
||||
|
||||
public function getCachedPermissions(int $userId): array
|
||||
{
|
||||
return $this->permissionService->getCachedPermissions($userId);
|
||||
}
|
||||
|
||||
public function clearUserCache(int $userId): void
|
||||
{
|
||||
$this->permissionService->clearUserCache($userId);
|
||||
}
|
||||
|
||||
public function listPaged(array $options): array
|
||||
{
|
||||
return $this->permissionService->listPaged($options);
|
||||
}
|
||||
|
||||
public function find(int $id): ?array
|
||||
{
|
||||
return $this->permissionService->find($id);
|
||||
}
|
||||
|
||||
public function createFromAdmin(array $input): array
|
||||
{
|
||||
return $this->permissionService->createFromAdmin($input);
|
||||
}
|
||||
|
||||
public function updateFromAdmin(int $id, array $input): array
|
||||
{
|
||||
return $this->permissionService->updateFromAdmin($id, $input);
|
||||
}
|
||||
|
||||
public function deleteById(int $id): array
|
||||
{
|
||||
return $this->permissionService->deleteById($id);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class RoleAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
public const ABILITY_ADMIN_ROLES_DELETE = 'admin.roles.delete';
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway
|
||||
private readonly PermissionService $permissionService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class RoleAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
|
||||
private function hasPermission(int $userId, string $permissionKey): bool
|
||||
{
|
||||
return $userId > 0 && $this->permissionGateway->userHas($userId, $permissionKey);
|
||||
return $userId > 0 && $this->permissionService->userHas($userId, $permissionKey);
|
||||
}
|
||||
|
||||
private function capabilitiesFromDecision(AuthorizationDecision $decision): array
|
||||
|
||||
@@ -11,7 +11,7 @@ class SettingsAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
public const ABILITY_ADMIN_SETTINGS_USER_LIFECYCLE_RUN = 'admin.settings.user_lifecycle.run';
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway
|
||||
private readonly PermissionService $permissionService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -70,6 +70,6 @@ class SettingsAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
|
||||
private function hasPermission(int $userId, string $permissionKey): bool
|
||||
{
|
||||
return $userId > 0 && $this->permissionGateway->userHas($userId, $permissionKey);
|
||||
return $userId > 0 && $this->permissionService->userHas($userId, $permissionKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace MintyPHP\Service\Access;
|
||||
|
||||
use MintyPHP\Service\Directory\DirectoryScopeGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class TenantAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
{
|
||||
@@ -16,8 +16,8 @@ class TenantAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
public const ABILITY_ADMIN_TENANTS_MEDIA_UPDATE = 'admin.tenants.media.update';
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway,
|
||||
private readonly DirectoryScopeGateway $scopeGateway
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly TenantScopeService $scopeGateway
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ class TenantAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
|
||||
private function hasPermission(int $userId, string $permissionKey): bool
|
||||
{
|
||||
return $userId > 0 && $this->permissionGateway->userHas($userId, $permissionKey);
|
||||
return $userId > 0 && $this->permissionService->userHas($userId, $permissionKey);
|
||||
}
|
||||
|
||||
private function capabilitiesFromDecision(AuthorizationDecision $decision): array
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace MintyPHP\Service\Access;
|
||||
|
||||
use MintyPHP\Service\Directory\DirectoryScopeGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class UserAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
{
|
||||
@@ -29,8 +29,8 @@ class UserAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
public const ABILITY_API_USERS_SHOW_DELETE = 'api.users.show.delete';
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway,
|
||||
private readonly DirectoryScopeGateway $scopeGateway
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly TenantScopeService $scopeGateway
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -357,7 +357,7 @@ class UserAuthorizationPolicy implements AuthorizationPolicyInterface
|
||||
|
||||
private function hasPermission(int $userId, string $permissionKey): bool
|
||||
{
|
||||
return $userId > 0 && $this->permissionGateway->userHas($userId, $permissionKey);
|
||||
return $userId > 0 && $this->permissionService->userHas($userId, $permissionKey);
|
||||
}
|
||||
|
||||
private function canEditUserForTarget(int $actorUserId, int $targetUserId): bool
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\AddressBook;
|
||||
|
||||
use MintyPHP\Service\User\UserAvatarService;
|
||||
|
||||
class AddressBookAvatarGateway
|
||||
{
|
||||
public function __construct(private readonly UserAvatarService $userAvatarService)
|
||||
{
|
||||
}
|
||||
|
||||
public function hasAvatar(string $userUuid): bool
|
||||
{
|
||||
return $this->userAvatarService->hasAvatar($userUuid);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\AddressBook;
|
||||
|
||||
use MintyPHP\Repository\CustomField\TenantCustomFieldOptionRepository;
|
||||
use MintyPHP\Service\CustomField\UserCustomFieldValueService;
|
||||
|
||||
class AddressBookCustomFieldGateway
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserCustomFieldValueService $userCustomFieldValueService
|
||||
) {
|
||||
}
|
||||
|
||||
public function extractFilterSpec(array $query, int $currentUserId): array
|
||||
{
|
||||
return $this->userCustomFieldValueService->extractAddressBookFilterSpec($query, $currentUserId);
|
||||
}
|
||||
|
||||
public function listOptionsByDefinitionIds(array $definitionIds, bool $activeOnly = true): array
|
||||
{
|
||||
return TenantCustomFieldOptionRepository::listByDefinitionIds($definitionIds, $activeOnly);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\AddressBook;
|
||||
|
||||
use MintyPHP\Service\Access\RoleService;
|
||||
use MintyPHP\Service\Directory\DirectoryScopeGateway;
|
||||
use MintyPHP\Service\Org\DepartmentService;
|
||||
use MintyPHP\Service\Tenant\TenantService;
|
||||
|
||||
class AddressBookDirectoryGateway
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TenantService $tenantService,
|
||||
private readonly DepartmentService $departmentService,
|
||||
private readonly RoleService $roleService,
|
||||
private readonly DirectoryScopeGateway $scopeGateway
|
||||
) {
|
||||
}
|
||||
|
||||
public function listTenants(): array
|
||||
{
|
||||
return $this->tenantService()->list();
|
||||
}
|
||||
|
||||
public function listDepartmentsByTenantIds(array $tenantIds): array
|
||||
{
|
||||
return $this->departmentService()->listByTenantIds($tenantIds);
|
||||
}
|
||||
|
||||
public function listDepartments(): array
|
||||
{
|
||||
return $this->departmentService()->list();
|
||||
}
|
||||
|
||||
public function listActiveRoles(): array
|
||||
{
|
||||
return $this->roleService()->listActive();
|
||||
}
|
||||
|
||||
public function getUserTenantIds(int $userId): array
|
||||
{
|
||||
return $this->scopeGateway()->getUserTenantIds($userId);
|
||||
}
|
||||
|
||||
public function isStrictScope(): bool
|
||||
{
|
||||
return $this->scopeGateway()->isStrict();
|
||||
}
|
||||
|
||||
public function canAccessUser(int $viewerUserId, int $targetUserId): bool
|
||||
{
|
||||
return $this->scopeGateway()->canAccess('users', $targetUserId, $viewerUserId);
|
||||
}
|
||||
|
||||
private function tenantService(): TenantService
|
||||
{
|
||||
return $this->tenantService;
|
||||
}
|
||||
|
||||
private function departmentService(): DepartmentService
|
||||
{
|
||||
return $this->departmentService;
|
||||
}
|
||||
|
||||
private function roleService(): RoleService
|
||||
{
|
||||
return $this->roleService;
|
||||
}
|
||||
|
||||
private function scopeGateway(): DirectoryScopeGateway
|
||||
{
|
||||
return $this->scopeGateway;
|
||||
}
|
||||
}
|
||||
@@ -2,17 +2,27 @@
|
||||
|
||||
namespace MintyPHP\Service\AddressBook;
|
||||
|
||||
use MintyPHP\Repository\CustomField\TenantCustomFieldOptionRepository;
|
||||
use MintyPHP\Service\Access\RoleService;
|
||||
use MintyPHP\Service\CustomField\UserCustomFieldValueService;
|
||||
use MintyPHP\Service\Org\DepartmentService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\Tenant\TenantService;
|
||||
use MintyPHP\Service\User\UserAccountService;
|
||||
use MintyPHP\Service\User\UserAssignmentService;
|
||||
use MintyPHP\Service\User\UserAvatarService;
|
||||
|
||||
class AddressBookService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserAccountService $userAccountService,
|
||||
private readonly UserAssignmentService $userAssignmentService,
|
||||
private readonly AddressBookDirectoryGateway $directoryGateway,
|
||||
private readonly AddressBookCustomFieldGateway $customFieldGateway,
|
||||
private readonly AddressBookAvatarGateway $avatarGateway
|
||||
private readonly TenantService $tenantService,
|
||||
private readonly DepartmentService $departmentService,
|
||||
private readonly RoleService $roleService,
|
||||
private readonly TenantScopeService $scopeGateway,
|
||||
private readonly UserCustomFieldValueService $customFieldValueService,
|
||||
private readonly UserAvatarService $avatarService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -22,8 +32,8 @@ class AddressBookService
|
||||
$activeRoles = $this->splitCommaValues($query['roles'] ?? '');
|
||||
$activeDepartments = $this->splitCommaValues($query['departments'] ?? '');
|
||||
|
||||
$tenantIds = $this->normalizeIds($this->directoryGateway->getUserTenantIds($currentUserId));
|
||||
$tenants = $this->directoryGateway->listTenants();
|
||||
$tenantIds = $this->normalizeIds($this->scopeGateway->getUserTenantIds($currentUserId));
|
||||
$tenants = $this->tenantService->list();
|
||||
if ($tenantIds) {
|
||||
$allowedTenantMap = array_fill_keys($tenantIds, true);
|
||||
$tenants = array_values(array_filter(
|
||||
@@ -33,7 +43,7 @@ class AddressBookService
|
||||
return $tenantId > 0 && isset($allowedTenantMap[$tenantId]);
|
||||
}
|
||||
));
|
||||
} elseif ($this->directoryGateway->isStrictScope()) {
|
||||
} elseif ($this->scopeGateway->isStrict()) {
|
||||
$tenants = [];
|
||||
}
|
||||
|
||||
@@ -46,12 +56,12 @@ class AddressBookService
|
||||
);
|
||||
|
||||
$departments = $tenantIds
|
||||
? $this->directoryGateway->listDepartmentsByTenantIds($tenantIds)
|
||||
: ($this->directoryGateway->isStrictScope() ? [] : $this->directoryGateway->listDepartments());
|
||||
? $this->departmentService->listByTenantIds($tenantIds)
|
||||
: ($this->scopeGateway->isStrict() ? [] : $this->departmentService->list());
|
||||
|
||||
$roles = $this->directoryGateway->listActiveRoles();
|
||||
$roles = $this->roleService->listActive();
|
||||
|
||||
$customFieldFilterSpec = $this->customFieldGateway->extractFilterSpec($query, $currentUserId);
|
||||
$customFieldFilterSpec = $this->customFieldValueService->extractAddressBookFilterSpec($query, $currentUserId);
|
||||
$customFieldFilterDefinitions = $this->normalizeDefinitions(
|
||||
$customFieldFilterSpec['definitions'] ?? []
|
||||
);
|
||||
@@ -68,7 +78,7 @@ class AddressBookService
|
||||
}
|
||||
$customFieldDefinitionIds = array_values(array_unique($customFieldDefinitionIds));
|
||||
|
||||
$customFieldOptions = $this->customFieldGateway->listOptionsByDefinitionIds(
|
||||
$customFieldOptions = TenantCustomFieldOptionRepository::listByDefinitionIds(
|
||||
$customFieldDefinitionIds,
|
||||
true
|
||||
);
|
||||
@@ -151,7 +161,7 @@ class AddressBookService
|
||||
$tenants = $query['tenants'] ?? '';
|
||||
$departments = $query['departments'] ?? '';
|
||||
$roles = $query['roles'] ?? '';
|
||||
$customFieldFilterSpec = $this->customFieldGateway->extractFilterSpec($query, $currentUserId);
|
||||
$customFieldFilterSpec = $this->customFieldValueService->extractAddressBookFilterSpec($query, $currentUserId);
|
||||
|
||||
$result = $this->userAccountService->listPaged([
|
||||
'limit' => $limit,
|
||||
@@ -195,7 +205,7 @@ class AddressBookService
|
||||
'tenants' => $tenantList,
|
||||
'departments' => $departmentList,
|
||||
'roles' => $roleList,
|
||||
'has_avatar' => $uuid !== '' && $this->avatarGateway->hasAvatar($uuid),
|
||||
'has_avatar' => $uuid !== '' && $this->avatarService->hasAvatar($uuid),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -225,12 +235,12 @@ class AddressBookService
|
||||
// Users can always view their own profile; others require scope access.
|
||||
if (
|
||||
$currentUserId !== $targetUserId
|
||||
&& !$this->directoryGateway->canAccessUser($currentUserId, $targetUserId)
|
||||
&& !$this->scopeGateway->canAccess('users', $targetUserId, $currentUserId)
|
||||
) {
|
||||
return ['status' => 'forbidden'];
|
||||
}
|
||||
|
||||
$viewerTenantIds = $this->normalizeIds($this->directoryGateway->getUserTenantIds($currentUserId));
|
||||
$viewerTenantIds = $this->normalizeIds($this->scopeGateway->getUserTenantIds($currentUserId));
|
||||
$assignments = $this->userAssignmentService->buildAssignmentsForUser($targetUserId);
|
||||
|
||||
$departmentMap = [];
|
||||
@@ -294,7 +304,7 @@ class AddressBookService
|
||||
$roleLabels = array_values($roleLabels);
|
||||
|
||||
$avatarUuid = (string) ($user['uuid'] ?? '');
|
||||
$user['has_avatar'] = $avatarUuid !== '' && $this->avatarGateway->hasAvatar($avatarUuid);
|
||||
$user['has_avatar'] = $avatarUuid !== '' && $this->avatarService->hasAvatar($avatarUuid);
|
||||
$user['tenant_groups'] = $tenantGroups;
|
||||
$user['role_labels'] = $roleLabels;
|
||||
|
||||
|
||||
@@ -4,19 +4,18 @@ namespace MintyPHP\Service\AddressBook;
|
||||
|
||||
use MintyPHP\Service\CustomField\CustomFieldServicesFactory;
|
||||
use MintyPHP\Service\Directory\DirectoryServicesFactory;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserServicesFactory;
|
||||
|
||||
class AddressBookServicesFactory
|
||||
{
|
||||
private ?AddressBookDirectoryGateway $addressBookDirectoryGateway = null;
|
||||
private ?AddressBookCustomFieldGateway $addressBookCustomFieldGateway = null;
|
||||
private ?AddressBookAvatarGateway $addressBookAvatarGateway = null;
|
||||
private ?AddressBookService $addressBookService = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly UserServicesFactory $userServicesFactory,
|
||||
private readonly DirectoryServicesFactory $directoryServicesFactory,
|
||||
private readonly CustomFieldServicesFactory $customFieldServicesFactory
|
||||
private readonly CustomFieldServicesFactory $customFieldServicesFactory,
|
||||
private readonly TenantScopeService $tenantScopeService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -27,41 +26,16 @@ class AddressBookServicesFactory
|
||||
}
|
||||
|
||||
$userFactory = $this->userServicesFactory;
|
||||
$directoryFactory = $this->directoryServicesFactory;
|
||||
return $this->addressBookService = new AddressBookService(
|
||||
$userFactory->createUserAccountService(),
|
||||
$userFactory->createUserAssignmentService(),
|
||||
$this->createAddressBookDirectoryGateway(),
|
||||
$this->createAddressBookCustomFieldGateway(),
|
||||
$this->createAddressBookAvatarGateway()
|
||||
);
|
||||
}
|
||||
|
||||
public function createAddressBookDirectoryGateway(): AddressBookDirectoryGateway
|
||||
{
|
||||
if ($this->addressBookDirectoryGateway !== null) {
|
||||
return $this->addressBookDirectoryGateway;
|
||||
}
|
||||
|
||||
$directoryFactory = $this->directoryServicesFactory;
|
||||
return $this->addressBookDirectoryGateway = new AddressBookDirectoryGateway(
|
||||
$directoryFactory->createTenantService(),
|
||||
$directoryFactory->createDepartmentService(),
|
||||
$directoryFactory->createRoleService(),
|
||||
$directoryFactory->createDirectoryScopeGateway()
|
||||
);
|
||||
}
|
||||
|
||||
public function createAddressBookCustomFieldGateway(): AddressBookCustomFieldGateway
|
||||
{
|
||||
return $this->addressBookCustomFieldGateway ??= new AddressBookCustomFieldGateway(
|
||||
$this->customFieldServicesFactory->createUserCustomFieldValueService()
|
||||
);
|
||||
}
|
||||
|
||||
public function createAddressBookAvatarGateway(): AddressBookAvatarGateway
|
||||
{
|
||||
return $this->addressBookAvatarGateway ??= new AddressBookAvatarGateway(
|
||||
$this->userServicesFactory->createUserAvatarService()
|
||||
$this->tenantScopeService,
|
||||
$this->customFieldServicesFactory->createUserCustomFieldValueService(),
|
||||
$userFactory->createUserAvatarService()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,14 @@ namespace MintyPHP\Service\Auth;
|
||||
|
||||
use MintyPHP\Repository\Auth\ApiTokenRepository;
|
||||
use MintyPHP\Repository\Tenant\TenantRepository;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class ApiTokenEndpointService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ApiTokenRepository $apiTokenRepository,
|
||||
private readonly TenantRepository $tenantRepository,
|
||||
private readonly AuthScopeGateway $authScopeGateway
|
||||
private readonly TenantScopeService $authScopeGateway
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use MintyPHP\Http\RequestRuntimeInterface;
|
||||
use MintyPHP\Repository\Auth\ApiTokenRepositoryInterface;
|
||||
use MintyPHP\Repository\Support\DatabaseSessionRepository;
|
||||
use MintyPHP\Repository\User\UserReadRepositoryInterface;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class ApiTokenService
|
||||
{
|
||||
@@ -15,7 +16,7 @@ class ApiTokenService
|
||||
private readonly UserReadRepositoryInterface $userReadRepository,
|
||||
private readonly ApiTokenRepositoryInterface $apiTokenRepository,
|
||||
private readonly AuthSettingsGateway $settingsGateway,
|
||||
private readonly AuthScopeGateway $scopeGateway,
|
||||
private readonly TenantScopeService $scopeGateway,
|
||||
private readonly DatabaseSessionRepository $databaseSessionRepository,
|
||||
private readonly RequestRuntimeInterface $requestRuntime
|
||||
) {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\Auth;
|
||||
|
||||
use MintyPHP\Service\User\UserAvatarService;
|
||||
|
||||
class AuthAvatarGateway
|
||||
{
|
||||
public function __construct(private readonly UserAvatarService $userAvatarService)
|
||||
{
|
||||
}
|
||||
|
||||
public function isValidUuid(string $uuid): bool
|
||||
{
|
||||
return $this->userAvatarService->isValidUuid($uuid);
|
||||
}
|
||||
|
||||
public function saveBinary(string $uuid, string $binary, string $mime): void
|
||||
{
|
||||
$this->userAvatarService->saveBinary($uuid, $binary, $mime);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace MintyPHP\Service\Auth;
|
||||
|
||||
use MintyPHP\Service\Access\AccessServicesFactory;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Settings\SettingsApiPolicyGateway;
|
||||
use MintyPHP\Service\Settings\SettingsAppGateway;
|
||||
use MintyPHP\Service\Settings\SettingsDefaultsGateway;
|
||||
@@ -11,7 +11,6 @@ use MintyPHP\Service\Settings\SettingServicesFactory;
|
||||
use MintyPHP\Service\Settings\SettingsLoginPersistenceGateway;
|
||||
use MintyPHP\Service\Settings\SettingsMicrosoftGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserServicesFactory;
|
||||
|
||||
class AuthGatewayFactory
|
||||
{
|
||||
@@ -20,21 +19,15 @@ class AuthGatewayFactory
|
||||
private ?SettingsDefaultsGateway $settingsDefaultsGateway = null;
|
||||
private ?SettingsAppGateway $settingsAppGateway = null;
|
||||
private ?SettingsLoginPersistenceGateway $settingsLoginPersistenceGateway = null;
|
||||
private ?PermissionGateway $permissionGateway = null;
|
||||
private ?PermissionService $permissionService = null;
|
||||
private ?AuthSettingsGateway $authSettingsGateway = null;
|
||||
private ?AuthScopeGateway $authScopeGateway = null;
|
||||
private ?AuthPermissionGateway $authPermissionGateway = null;
|
||||
private ?AuthTenantGateway $authTenantGateway = null;
|
||||
private ?AuthCryptoGateway $authCryptoGateway = null;
|
||||
private ?AuthTenantSsoGateway $authTenantSsoGateway = null;
|
||||
private ?AuthSavedFilterGateway $authSavedFilterGateway = null;
|
||||
private ?AuthAvatarGateway $authAvatarGateway = null;
|
||||
private ?AuthExternalIdentityGateway $authExternalIdentityGateway = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly AuthRepositoryFactory $authRepositoryFactory,
|
||||
private readonly AccessServicesFactory $accessServicesFactory,
|
||||
private readonly UserServicesFactory $userServicesFactory,
|
||||
private readonly SettingServicesFactory $settingServicesFactory,
|
||||
private readonly TenantScopeService $tenantScopeService
|
||||
) {
|
||||
@@ -51,14 +44,14 @@ class AuthGatewayFactory
|
||||
);
|
||||
}
|
||||
|
||||
public function createAuthScopeGateway(): AuthScopeGateway
|
||||
public function getTenantScopeService(): TenantScopeService
|
||||
{
|
||||
return $this->authScopeGateway ??= new AuthScopeGateway($this->tenantScopeService);
|
||||
return $this->tenantScopeService;
|
||||
}
|
||||
|
||||
public function createAuthPermissionGateway(): AuthPermissionGateway
|
||||
public function createPermissionService(): PermissionService
|
||||
{
|
||||
return $this->authPermissionGateway ??= new AuthPermissionGateway($this->createPermissionGateway());
|
||||
return $this->permissionService ??= $this->accessServicesFactory->createPermissionService();
|
||||
}
|
||||
|
||||
public function createAuthTenantGateway(): AuthTenantGateway
|
||||
@@ -73,25 +66,6 @@ class AuthGatewayFactory
|
||||
return $this->authCryptoGateway ??= new AuthCryptoGateway();
|
||||
}
|
||||
|
||||
public function createAuthTenantSsoGateway(TenantSsoService $tenantSsoService): AuthTenantSsoGateway
|
||||
{
|
||||
return $this->authTenantSsoGateway ??= new AuthTenantSsoGateway($tenantSsoService);
|
||||
}
|
||||
|
||||
public function createAuthSavedFilterGateway(): AuthSavedFilterGateway
|
||||
{
|
||||
return $this->authSavedFilterGateway ??= new AuthSavedFilterGateway(
|
||||
$this->userServicesFactory->createUserSavedFilterService()
|
||||
);
|
||||
}
|
||||
|
||||
public function createAuthAvatarGateway(): AuthAvatarGateway
|
||||
{
|
||||
return $this->authAvatarGateway ??= new AuthAvatarGateway(
|
||||
$this->userServicesFactory->createUserAvatarService()
|
||||
);
|
||||
}
|
||||
|
||||
public function createAuthExternalIdentityGateway(): AuthExternalIdentityGateway
|
||||
{
|
||||
return $this->authExternalIdentityGateway ??= new AuthExternalIdentityGateway(
|
||||
@@ -99,11 +73,6 @@ class AuthGatewayFactory
|
||||
);
|
||||
}
|
||||
|
||||
private function createPermissionGateway(): PermissionGateway
|
||||
{
|
||||
return $this->permissionGateway ??= $this->accessServicesFactory->createPermissionGateway();
|
||||
}
|
||||
|
||||
private function createSettingsMicrosoftGateway(): SettingsMicrosoftGateway
|
||||
{
|
||||
return $this->settingsMicrosoftGateway ??= $this->settingServicesFactory->createSettingsMicrosoftGateway();
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\Auth;
|
||||
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
|
||||
class AuthPermissionGateway
|
||||
{
|
||||
public function __construct(private readonly PermissionGateway $permissionGateway)
|
||||
{
|
||||
}
|
||||
|
||||
public function warmUserPermissions(int $userId, bool $forceRefresh = true): array
|
||||
{
|
||||
return $this->permissionGateway->getUserPermissions($userId, $forceRefresh);
|
||||
}
|
||||
|
||||
public function userHas(int $userId, string $permissionKey): bool
|
||||
{
|
||||
return $this->permissionGateway->userHas($userId, $permissionKey);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\Auth;
|
||||
|
||||
use MintyPHP\Service\User\UserSavedFilterService;
|
||||
|
||||
class AuthSavedFilterGateway
|
||||
{
|
||||
public function __construct(private readonly UserSavedFilterService $userSavedFilterService)
|
||||
{
|
||||
}
|
||||
|
||||
public function listAddressBookFilters(int $userId): array
|
||||
{
|
||||
return $this->userSavedFilterService->listForAddressBook($userId);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\Auth;
|
||||
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class AuthScopeGateway
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TenantScopeService $tenantScopeService
|
||||
) {
|
||||
}
|
||||
|
||||
public function hasGlobalAccess(int $userId): bool
|
||||
{
|
||||
return $this->tenantScopeService->hasGlobalAccess($userId);
|
||||
}
|
||||
|
||||
public function getUserTenantIds(int $userId): array
|
||||
{
|
||||
return $this->tenantScopeService->getUserTenantIds($userId);
|
||||
}
|
||||
|
||||
public function canAccess(string $resourceType, int $resourceId, int $userId): bool
|
||||
{
|
||||
return $this->tenantScopeService->canAccess($resourceType, $resourceId, $userId);
|
||||
}
|
||||
|
||||
public function resourceBelongsToTenant(string $resourceType, int $resourceId, int $tenantId): bool
|
||||
{
|
||||
return $this->tenantScopeService->resourceBelongsToTenant($resourceType, $resourceId, $tenantId);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use MintyPHP\Http\SessionStoreInterface;
|
||||
use MintyPHP\Repository\User\UserReadRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserWriteRepositoryInterface;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Audit\SystemAuditService;
|
||||
use MintyPHP\Service\User\UserAccountService;
|
||||
use MintyPHP\Service\User\UserTenantContextService;
|
||||
@@ -22,8 +23,8 @@ class AuthService
|
||||
private readonly UserTenantContextService $userTenantContextService,
|
||||
private readonly RememberMeService $rememberMeService,
|
||||
private readonly EmailVerificationService $emailVerificationService,
|
||||
private readonly AuthPermissionGateway $permissionGateway,
|
||||
private readonly AuthTenantSsoGateway $tenantSsoGateway,
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly TenantSsoService $tenantSsoService,
|
||||
private readonly AuthSessionTenantContextService $authSessionTenantContextService,
|
||||
private readonly SystemAuditService $systemAuditService,
|
||||
private readonly SessionStoreInterface $sessionStore
|
||||
@@ -92,7 +93,7 @@ class AuthService
|
||||
];
|
||||
}
|
||||
if ($userId > 0) {
|
||||
$this->permissionGateway->warmUserPermissions($userId, true);
|
||||
$this->permissionService->getUserPermissions($userId, true);
|
||||
$this->loadTenantDataIntoSession($userId);
|
||||
if ($this->noActiveTenant()) {
|
||||
Auth::logout();
|
||||
@@ -135,7 +136,7 @@ class AuthService
|
||||
if ($tenantId <= 0) {
|
||||
continue;
|
||||
}
|
||||
if ($this->tenantSsoGateway->isLocalPasswordLoginAllowed($tenantId)) {
|
||||
if ($this->tenantSsoService->isLocalPasswordLoginAllowed($tenantId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -184,7 +185,7 @@ class AuthService
|
||||
}
|
||||
}
|
||||
|
||||
$this->permissionGateway->warmUserPermissions($userId, true);
|
||||
$this->permissionService->getUserPermissions($userId, true);
|
||||
$this->loadTenantDataIntoSession($userId);
|
||||
if ($this->noActiveTenant()) {
|
||||
Auth::logout();
|
||||
@@ -336,7 +337,7 @@ class AuthService
|
||||
}
|
||||
|
||||
$this->sessionStore->set('user', $user);
|
||||
$this->permissionGateway->warmUserPermissions($userId, true);
|
||||
$this->permissionService->getUserPermissions($userId, true);
|
||||
$this->loadTenantDataIntoSession($userId);
|
||||
$refreshed = true;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class AuthServicesFactory
|
||||
$this->userServicesFactory->createUserReadRepository(),
|
||||
$this->authRepositoryFactory->createApiTokenRepository(),
|
||||
$this->authGatewayFactory->createAuthSettingsGateway(),
|
||||
$this->createAuthScopeGateway(),
|
||||
$this->authGatewayFactory->getTenantScopeService(),
|
||||
$this->databaseSessionRepository,
|
||||
$this->requestRuntime
|
||||
);
|
||||
@@ -75,7 +75,7 @@ class AuthServicesFactory
|
||||
$this->userServicesFactory->createUserReadRepository(),
|
||||
$this->userServicesFactory->createUserWriteRepository(),
|
||||
$this->authRepositoryFactory->createRememberTokenRepository(),
|
||||
$this->authGatewayFactory->createAuthPermissionGateway(),
|
||||
$this->authGatewayFactory->createPermissionService(),
|
||||
$this->createAuthSessionTenantContextService(),
|
||||
$this->sessionStore,
|
||||
$this->cookieStore,
|
||||
@@ -93,8 +93,8 @@ class AuthServicesFactory
|
||||
$this->userServicesFactory->createUserTenantContextService(),
|
||||
$this->createRememberMeService(),
|
||||
$this->createEmailVerificationService(),
|
||||
$this->authGatewayFactory->createAuthPermissionGateway(),
|
||||
$this->createAuthTenantSsoGateway(),
|
||||
$this->authGatewayFactory->createPermissionService(),
|
||||
$this->createTenantSsoService(),
|
||||
$this->createAuthSessionTenantContextService(),
|
||||
$this->auditServicesFactory->createSystemAuditService(),
|
||||
$this->sessionStore
|
||||
@@ -109,8 +109,8 @@ class AuthServicesFactory
|
||||
$this->userServicesFactory->createUserAssignmentService(),
|
||||
$this->userServicesFactory->createUserTenantRepository(),
|
||||
$this->authGatewayFactory->createAuthSettingsGateway(),
|
||||
$this->createAuthTenantSsoGateway(),
|
||||
$this->authGatewayFactory->createAuthAvatarGateway(),
|
||||
$this->createTenantSsoService(),
|
||||
$this->userServicesFactory->createUserAvatarService(),
|
||||
$this->authGatewayFactory->createAuthExternalIdentityGateway()
|
||||
);
|
||||
}
|
||||
@@ -140,16 +140,6 @@ class AuthServicesFactory
|
||||
);
|
||||
}
|
||||
|
||||
public function createAuthScopeGateway(): AuthScopeGateway
|
||||
{
|
||||
return $this->authGatewayFactory->createAuthScopeGateway();
|
||||
}
|
||||
|
||||
private function createAuthTenantSsoGateway(): AuthTenantSsoGateway
|
||||
{
|
||||
return $this->authGatewayFactory->createAuthTenantSsoGateway($this->createTenantSsoService());
|
||||
}
|
||||
|
||||
private function createOidcHttpGateway(): OidcHttpGateway
|
||||
{
|
||||
return new OidcHttpGateway();
|
||||
@@ -159,7 +149,7 @@ class AuthServicesFactory
|
||||
{
|
||||
return $this->authSessionTenantContextService ??= new AuthSessionTenantContextService(
|
||||
$this->userServicesFactory->createUserTenantContextService(),
|
||||
$this->authGatewayFactory->createAuthSavedFilterGateway(),
|
||||
$this->userServicesFactory->createUserSavedFilterService(),
|
||||
$this->sessionStore
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
namespace MintyPHP\Service\Auth;
|
||||
|
||||
use MintyPHP\Http\SessionStoreInterface;
|
||||
use MintyPHP\Service\User\UserSavedFilterService;
|
||||
use MintyPHP\Service\User\UserTenantContextService;
|
||||
|
||||
class AuthSessionTenantContextService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserTenantContextService $userTenantContextService,
|
||||
private readonly AuthSavedFilterGateway $savedFilterGateway,
|
||||
private readonly UserSavedFilterService $savedFilterService,
|
||||
private readonly SessionStoreInterface $sessionStore
|
||||
) {
|
||||
}
|
||||
@@ -23,7 +24,7 @@ class AuthSessionTenantContextService
|
||||
$availableTenants = $this->userTenantContextService->getAvailableTenants($userId);
|
||||
$this->sessionStore->set('available_tenants', $availableTenants);
|
||||
$this->sessionStore->set('available_departments_by_tenant', $this->userTenantContextService->getAvailableDepartmentsByTenant($userId));
|
||||
$this->sessionStore->set('address_book_saved_filters', $this->savedFilterGateway->listAddressBookFilters($userId));
|
||||
$this->sessionStore->set('address_book_saved_filters', $this->savedFilterService->listForAddressBook($userId));
|
||||
|
||||
if (!$availableTenants) {
|
||||
$this->sessionStore->set('no_active_tenant', true);
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\Auth;
|
||||
|
||||
class AuthTenantSsoGateway
|
||||
{
|
||||
public function __construct(private readonly TenantSsoService $tenantSsoService)
|
||||
{
|
||||
}
|
||||
|
||||
public function isLocalPasswordLoginAllowed(int $tenantId): bool
|
||||
{
|
||||
return $this->tenantSsoService->isLocalPasswordLoginAllowed($tenantId);
|
||||
}
|
||||
|
||||
public function normalizeProfileSyncFields($fields): array
|
||||
{
|
||||
return $this->tenantSsoService->normalizeProfileSyncFields($fields);
|
||||
}
|
||||
|
||||
public function defaultProfileSyncFields(): array
|
||||
{
|
||||
return $this->tenantSsoService->defaultProfileSyncFields();
|
||||
}
|
||||
|
||||
public function microsoftProviderKey(): string
|
||||
{
|
||||
return $this->tenantSsoService->microsoftProviderKey();
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use MintyPHP\I18n;
|
||||
use MintyPHP\Repository\Auth\RememberTokenRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserReadRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserWriteRepositoryInterface;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Session;
|
||||
|
||||
class RememberMeService
|
||||
@@ -21,7 +22,7 @@ class RememberMeService
|
||||
private readonly UserReadRepositoryInterface $userReadRepository,
|
||||
private readonly UserWriteRepositoryInterface $userWriteRepository,
|
||||
private readonly RememberTokenRepositoryInterface $rememberTokenRepository,
|
||||
private readonly AuthPermissionGateway $permissionGateway,
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly AuthSessionTenantContextService $authSessionTenantContextService,
|
||||
private readonly SessionStoreInterface $sessionStore,
|
||||
private readonly CookieStoreInterface $cookieStore,
|
||||
@@ -101,7 +102,7 @@ class RememberMeService
|
||||
}
|
||||
$userId = (int) $user['id'];
|
||||
if ($userId > 0) {
|
||||
$this->permissionGateway->warmUserPermissions($userId, true);
|
||||
$this->permissionService->getUserPermissions($userId, true);
|
||||
$this->authSessionTenantContextService->hydrateForUser($userId);
|
||||
if ((bool) $this->sessionStore->get('no_active_tenant', false)) {
|
||||
// Enforce the same tenant policy as interactive login.
|
||||
|
||||
@@ -6,6 +6,7 @@ use MintyPHP\Repository\Tenant\UserTenantRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserReadRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserWriteRepositoryInterface;
|
||||
use MintyPHP\Service\User\UserAssignmentService;
|
||||
use MintyPHP\Service\User\UserAvatarService;
|
||||
|
||||
class SsoUserLinkService
|
||||
{
|
||||
@@ -15,8 +16,8 @@ class SsoUserLinkService
|
||||
private readonly UserAssignmentService $userAssignmentService,
|
||||
private readonly UserTenantRepositoryInterface $userTenantRepository,
|
||||
private readonly AuthSettingsGateway $settingsGateway,
|
||||
private readonly AuthTenantSsoGateway $tenantSsoGateway,
|
||||
private readonly AuthAvatarGateway $avatarGateway,
|
||||
private readonly TenantSsoService $tenantSsoService,
|
||||
private readonly UserAvatarService $avatarService,
|
||||
private readonly AuthExternalIdentityGateway $externalIdentityGateway
|
||||
) {
|
||||
}
|
||||
@@ -34,7 +35,7 @@ class SsoUserLinkService
|
||||
return ['ok' => false, 'error' => 'identity_invalid'];
|
||||
}
|
||||
|
||||
$providerKey = $this->tenantSsoGateway->microsoftProviderKey();
|
||||
$providerKey = $this->tenantSsoService->microsoftProviderKey();
|
||||
// Look up by OID first (stable Microsoft object ID), fall back to issuer+subject
|
||||
// to handle tenants that migrated from an older OIDC setup without OID.
|
||||
$identity = $this->externalIdentityGateway->findByProviderTidOid(
|
||||
@@ -136,9 +137,9 @@ class SsoUserLinkService
|
||||
return;
|
||||
}
|
||||
|
||||
$syncFields = $this->tenantSsoGateway->normalizeProfileSyncFields($claims['sync_profile_fields'] ?? []);
|
||||
$syncFields = $this->tenantSsoService->normalizeProfileSyncFields($claims['sync_profile_fields'] ?? []);
|
||||
if (!$syncFields) {
|
||||
$syncFields = $this->tenantSsoGateway->defaultProfileSyncFields();
|
||||
$syncFields = $this->tenantSsoService->defaultProfileSyncFields();
|
||||
}
|
||||
if (!$syncFields) {
|
||||
return;
|
||||
@@ -202,12 +203,12 @@ class SsoUserLinkService
|
||||
return;
|
||||
}
|
||||
$userUuid = (string) ($user['uuid'] ?? '');
|
||||
if (!$this->avatarGateway->isValidUuid($userUuid)) {
|
||||
if (!$this->avatarService->isValidUuid($userUuid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep avatar current with Microsoft profile photo on each login.
|
||||
$this->avatarGateway->saveBinary($userUuid, $binary, $avatarMime);
|
||||
$this->avatarService->saveBinary($userUuid, $binary, $avatarMime);
|
||||
}
|
||||
|
||||
private function ensureTenantAssignment(int $userId, int $tenantId): void
|
||||
@@ -228,7 +229,7 @@ class SsoUserLinkService
|
||||
string $email
|
||||
): void {
|
||||
try {
|
||||
$providerKey = $this->tenantSsoGateway->microsoftProviderKey();
|
||||
$providerKey = $this->tenantSsoService->microsoftProviderKey();
|
||||
$this->externalIdentityGateway->createLink([
|
||||
'user_id' => $userId,
|
||||
'provider' => $providerKey,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace MintyPHP\Service\CustomField;
|
||||
|
||||
use MintyPHP\Repository\Tenant\TenantRepository;
|
||||
use MintyPHP\Service\User\UserScopeGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class CustomFieldServicesFactory
|
||||
{
|
||||
@@ -12,7 +12,7 @@ class CustomFieldServicesFactory
|
||||
|
||||
public function __construct(
|
||||
private readonly TenantRepository $tenantRepository,
|
||||
private readonly UserScopeGateway $userScopeGateway
|
||||
private readonly TenantScopeService $userScopeGateway
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ use MintyPHP\Repository\CustomField\TenantCustomFieldOptionRepository;
|
||||
use MintyPHP\Repository\CustomField\UserCustomFieldValueOptionRepository;
|
||||
use MintyPHP\Repository\CustomField\UserCustomFieldValueRepository;
|
||||
use MintyPHP\Repository\Support\RepoQuery;
|
||||
use MintyPHP\Service\User\UserScopeGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class UserCustomFieldValueService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserScopeGateway $userScopeGateway
|
||||
private readonly TenantScopeService $userScopeGateway
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ class UserCustomFieldValueService
|
||||
];
|
||||
}
|
||||
|
||||
private function userScopeGateway(): UserScopeGateway
|
||||
private function userScopeGateway(): TenantScopeService
|
||||
{
|
||||
return $this->userScopeGateway;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
class DirectoryGatewayFactory
|
||||
{
|
||||
private ?DirectorySettingsGateway $directorySettingsGateway = null;
|
||||
private ?DirectoryScopeGateway $directoryScopeGateway = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly SettingServicesFactory $settingServicesFactory,
|
||||
private readonly TenantScopeService $tenantScopeService
|
||||
@@ -23,8 +21,8 @@ class DirectoryGatewayFactory
|
||||
);
|
||||
}
|
||||
|
||||
public function createDirectoryScopeGateway(): DirectoryScopeGateway
|
||||
public function getTenantScopeService(): TenantScopeService
|
||||
{
|
||||
return $this->directoryScopeGateway ??= new DirectoryScopeGateway($this->tenantScopeService);
|
||||
return $this->tenantScopeService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\Directory;
|
||||
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class DirectoryScopeGateway
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TenantScopeService $tenantScopeService
|
||||
) {
|
||||
}
|
||||
|
||||
public function hasGlobalAccess(int $userId): bool
|
||||
{
|
||||
return $this->tenantScopeService->hasGlobalAccess($userId);
|
||||
}
|
||||
|
||||
public function getUserTenantIds(int $userId): array
|
||||
{
|
||||
return $this->tenantScopeService->getUserTenantIds($userId);
|
||||
}
|
||||
|
||||
public function isStrict(): bool
|
||||
{
|
||||
return $this->tenantScopeService->isStrict();
|
||||
}
|
||||
|
||||
public function canAccess(string $resourceType, int $resourceId, int $userId): bool
|
||||
{
|
||||
return $this->tenantScopeService->canAccess($resourceType, $resourceId, $userId);
|
||||
}
|
||||
|
||||
public function resourceBelongsToTenant(string $resourceType, int $resourceId, int $tenantId): bool
|
||||
{
|
||||
return $this->tenantScopeService->resourceBelongsToTenant($resourceType, $resourceId, $tenantId);
|
||||
}
|
||||
|
||||
public function filterTenantIdsForUser(array $tenantIds, int $userId): array
|
||||
{
|
||||
return $this->tenantScopeService->filterTenantIdsForUser($tenantIds, $userId);
|
||||
}
|
||||
|
||||
// When a scoped admin updates tenant assignments, they can't see tenants outside their scope.
|
||||
// This merges the requested IDs with any out-of-scope IDs from existing assignments so those
|
||||
// aren't silently dropped when the admin saves.
|
||||
public function mergeTenantIdsPreservingOutOfScope(
|
||||
array $requestedTenantIds,
|
||||
array $existingTenantIds,
|
||||
array $allowedTenantIds
|
||||
): array {
|
||||
return $this->tenantScopeService->mergeTenantIdsPreservingOutOfScope(
|
||||
$requestedTenantIds,
|
||||
$existingTenantIds,
|
||||
$allowedTenantIds
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use MintyPHP\Repository\Tenant\TenantRepositoryInterface;
|
||||
use MintyPHP\Service\Access\RoleService;
|
||||
use MintyPHP\Service\Audit\AuditServicesFactory;
|
||||
use MintyPHP\Service\Org\DepartmentService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\Tenant\TenantService;
|
||||
use MintyPHP\Service\User\UserServicesFactory;
|
||||
|
||||
@@ -41,7 +42,7 @@ class DirectoryServicesFactory
|
||||
$this->userServicesFactory,
|
||||
$this->createDepartmentRepository(),
|
||||
$this->createDirectorySettingsGateway(),
|
||||
$this->createDirectoryScopeGateway(),
|
||||
$this->directoryGatewayFactory->getTenantScopeService(),
|
||||
$this->auditServicesFactory->createSystemAuditService()
|
||||
);
|
||||
}
|
||||
@@ -76,8 +77,8 @@ class DirectoryServicesFactory
|
||||
return $this->directoryGatewayFactory->createDirectorySettingsGateway();
|
||||
}
|
||||
|
||||
public function createDirectoryScopeGateway(): DirectoryScopeGateway
|
||||
public function getTenantScopeService(): TenantScopeService
|
||||
{
|
||||
return $this->directoryGatewayFactory->createDirectoryScopeGateway();
|
||||
return $this->directoryGatewayFactory->getTenantScopeService();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
namespace MintyPHP\Service\Import;
|
||||
|
||||
use MintyPHP\Http\SessionStoreInterface;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Audit\ImportAuditService;
|
||||
use MintyPHP\Service\Import\Profile\ImportProfileInterface;
|
||||
use MintyPHP\Service\Settings\SettingsDefaultsGateway;
|
||||
use MintyPHP\Service\User\UserScopeGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class ImportService
|
||||
{
|
||||
@@ -28,9 +27,9 @@ class ImportService
|
||||
private readonly ImportAuditService $importAuditService,
|
||||
private readonly ImportStateStoreService $importStateStoreService,
|
||||
private readonly array $profiles,
|
||||
private readonly PermissionGateway $permissionGateway,
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly SettingsDefaultsGateway $settingsDefaultsGateway,
|
||||
private readonly UserScopeGateway $userScopeGateway,
|
||||
private readonly TenantScopeService $userScopeGateway,
|
||||
private readonly SessionStoreInterface $sessionStore
|
||||
) {
|
||||
}
|
||||
@@ -490,7 +489,7 @@ class ImportService
|
||||
|
||||
private function canImportAssignments(int $userId): bool
|
||||
{
|
||||
return $this->permissionGateway->userHas($userId, PermissionService::USERS_IMPORT_ASSIGNMENTS);
|
||||
return $this->permissionService->userHas($userId, PermissionService::USERS_IMPORT_ASSIGNMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace MintyPHP\Service\Import;
|
||||
use MintyPHP\Http\SessionStoreInterface;
|
||||
use MintyPHP\Repository\Audit\ImportAuditRunRepositoryInterface;
|
||||
use MintyPHP\Service\Access\AccessServicesFactory;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Audit\ImportAuditService;
|
||||
use MintyPHP\Service\Directory\DirectoryServicesFactory;
|
||||
use MintyPHP\Service\Import\Profile\DepartmentImportGateway;
|
||||
@@ -14,6 +14,7 @@ use MintyPHP\Service\Import\Profile\UserImportGateway;
|
||||
use MintyPHP\Service\Import\Profile\UserImportProfile;
|
||||
use MintyPHP\Service\Settings\SettingsDefaultsGateway;
|
||||
use MintyPHP\Service\Settings\SettingServicesFactory;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserServicesFactory;
|
||||
|
||||
class ImportServicesFactory
|
||||
@@ -22,7 +23,7 @@ class ImportServicesFactory
|
||||
private ?ImportTempFileService $importTempFileService = null;
|
||||
private ?ImportStateStoreService $importStateStoreService = null;
|
||||
private ?ImportAuditService $importAuditService = null;
|
||||
private ?PermissionGateway $permissionGateway = null;
|
||||
private ?PermissionService $permissionService = null;
|
||||
private ?SettingsDefaultsGateway $settingsDefaultsGateway = null;
|
||||
private ?ImportService $importService = null;
|
||||
|
||||
@@ -32,6 +33,7 @@ class ImportServicesFactory
|
||||
private readonly SettingServicesFactory $settingServicesFactory,
|
||||
private readonly DirectoryServicesFactory $directoryServicesFactory,
|
||||
private readonly ImportRepositoryFactory $importRepositoryFactory,
|
||||
private readonly TenantScopeService $tenantScopeService,
|
||||
private readonly SessionStoreInterface $sessionStore
|
||||
) {
|
||||
}
|
||||
@@ -43,18 +45,22 @@ class ImportServicesFactory
|
||||
}
|
||||
|
||||
$profiles = [
|
||||
'users' => new UserImportProfile(new UserImportGateway(
|
||||
$this->userServicesFactory->createUserReadRepository(),
|
||||
$this->userServicesFactory->createUserAccountService(),
|
||||
$this->directoryServicesFactory->createTenantRepository(),
|
||||
$this->directoryServicesFactory->createRoleRepository(),
|
||||
$this->directoryServicesFactory->createDepartmentRepository(),
|
||||
)),
|
||||
'departments' => new DepartmentImportProfile(new DepartmentImportGateway(
|
||||
$this->directoryServicesFactory->createDepartmentRepository(),
|
||||
$this->directoryServicesFactory->createTenantRepository(),
|
||||
'users' => new UserImportProfile(
|
||||
new UserImportGateway(
|
||||
$this->userServicesFactory->createUserReadRepository(),
|
||||
$this->directoryServicesFactory->createTenantRepository(),
|
||||
$this->directoryServicesFactory->createRoleRepository(),
|
||||
$this->directoryServicesFactory->createDepartmentRepository(),
|
||||
),
|
||||
$this->userServicesFactory->createUserAccountService()
|
||||
),
|
||||
'departments' => new DepartmentImportProfile(
|
||||
new DepartmentImportGateway(
|
||||
$this->directoryServicesFactory->createDepartmentRepository(),
|
||||
$this->directoryServicesFactory->createTenantRepository()
|
||||
),
|
||||
$this->directoryServicesFactory->createDepartmentService()
|
||||
)),
|
||||
),
|
||||
];
|
||||
|
||||
return $this->importService = new ImportService(
|
||||
@@ -63,9 +69,9 @@ class ImportServicesFactory
|
||||
$this->createImportAuditService(),
|
||||
$this->createImportStateStoreService(),
|
||||
$profiles,
|
||||
$this->createPermissionGateway(),
|
||||
$this->createPermissionService(),
|
||||
$this->createSettingsDefaultsGateway(),
|
||||
$this->userServicesFactory->createUserScopeGateway(),
|
||||
$this->tenantScopeService,
|
||||
$this->sessionStore
|
||||
);
|
||||
}
|
||||
@@ -98,9 +104,9 @@ class ImportServicesFactory
|
||||
return $this->importRepositoryFactory->createImportAuditRunRepository();
|
||||
}
|
||||
|
||||
private function createPermissionGateway(): PermissionGateway
|
||||
private function createPermissionService(): PermissionService
|
||||
{
|
||||
return $this->permissionGateway ??= $this->accessServicesFactory->createPermissionGateway();
|
||||
return $this->permissionService ??= $this->accessServicesFactory->createPermissionService();
|
||||
}
|
||||
|
||||
private function createSettingsDefaultsGateway(): SettingsDefaultsGateway
|
||||
|
||||
@@ -4,58 +4,32 @@ namespace MintyPHP\Service\Import\Profile;
|
||||
|
||||
use MintyPHP\Repository\Org\DepartmentRepositoryInterface;
|
||||
use MintyPHP\Repository\Tenant\TenantRepositoryInterface;
|
||||
use MintyPHP\Service\Org\DepartmentService;
|
||||
|
||||
class DepartmentImportGateway
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DepartmentRepositoryInterface $departmentRepository,
|
||||
private readonly TenantRepositoryInterface $tenantRepository,
|
||||
private readonly DepartmentService $departmentService
|
||||
private readonly TenantRepositoryInterface $tenantRepository
|
||||
) {
|
||||
}
|
||||
|
||||
public function findTenantByUuid(string $uuid): ?array
|
||||
{
|
||||
return $this->tenantRepository()->findByUuid($uuid);
|
||||
return $this->tenantRepository->findByUuid($uuid);
|
||||
}
|
||||
|
||||
public function findTenantById(int $id): ?array
|
||||
{
|
||||
return $this->tenantRepository()->find($id);
|
||||
return $this->tenantRepository->find($id);
|
||||
}
|
||||
|
||||
public function existsDepartmentCode(string $code): bool
|
||||
{
|
||||
return $this->departmentRepository()->existsByCode($code);
|
||||
return $this->departmentRepository->existsByCode($code);
|
||||
}
|
||||
|
||||
public function existsDepartmentByTenantAndDescription(int $tenantId, string $description): bool
|
||||
{
|
||||
return $this->departmentRepository()->existsByTenantAndDescription($tenantId, $description);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $input
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function createDepartmentFromAdmin(array $input, int $currentUserId): array
|
||||
{
|
||||
return $this->departmentService()->createFromAdmin($input, $currentUserId);
|
||||
}
|
||||
|
||||
private function departmentRepository(): DepartmentRepositoryInterface
|
||||
{
|
||||
return $this->departmentRepository;
|
||||
}
|
||||
|
||||
private function tenantRepository(): TenantRepositoryInterface
|
||||
{
|
||||
return $this->tenantRepository;
|
||||
}
|
||||
|
||||
private function departmentService(): DepartmentService
|
||||
{
|
||||
return $this->departmentService;
|
||||
return $this->departmentRepository->existsByTenantAndDescription($tenantId, $description);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
|
||||
namespace MintyPHP\Service\Import\Profile;
|
||||
|
||||
use MintyPHP\Service\Org\DepartmentService;
|
||||
|
||||
class DepartmentImportProfile implements ImportProfileInterface
|
||||
{
|
||||
public function __construct(private readonly DepartmentImportGateway $gateway)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DepartmentImportGateway $gateway,
|
||||
private readonly DepartmentService $departmentService
|
||||
) {
|
||||
}
|
||||
|
||||
public function key(): string
|
||||
@@ -139,7 +143,7 @@ class DepartmentImportProfile implements ImportProfileInterface
|
||||
return ['status' => 'skipped', 'code' => 'department_exists'];
|
||||
}
|
||||
|
||||
$result = $this->gateway->createDepartmentFromAdmin([
|
||||
$result = $this->departmentService->createFromAdmin([
|
||||
'description' => (string) ($normalized['description'] ?? ''),
|
||||
'tenant_id' => (int) ($normalized['tenant_id'] ?? 0),
|
||||
'code' => (string) ($normalized['code'] ?? ''),
|
||||
|
||||
@@ -6,13 +6,11 @@ use MintyPHP\Repository\Access\RoleRepositoryInterface;
|
||||
use MintyPHP\Repository\Org\DepartmentRepositoryInterface;
|
||||
use MintyPHP\Repository\Tenant\TenantRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserReadRepositoryInterface;
|
||||
use MintyPHP\Service\User\UserAccountService;
|
||||
|
||||
class UserImportGateway
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserReadRepositoryInterface $userReadRepository,
|
||||
private readonly UserAccountService $userAccountService,
|
||||
private readonly TenantRepositoryInterface $tenantRepository,
|
||||
private readonly RoleRepositoryInterface $roleRepository,
|
||||
private readonly DepartmentRepositoryInterface $departmentRepository,
|
||||
@@ -53,13 +51,4 @@ class UserImportGateway
|
||||
{
|
||||
return $this->departmentRepository->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $input
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function createUserFromAdmin(array $input, int $currentUserId): array
|
||||
{
|
||||
return $this->userAccountService->createFromAdmin($input, $currentUserId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace MintyPHP\Service\Import\Profile;
|
||||
|
||||
use MintyPHP\Service\User\UserAccountService;
|
||||
|
||||
class UserImportProfile implements ImportProfileInterface
|
||||
{
|
||||
/**
|
||||
@@ -9,8 +11,10 @@ class UserImportProfile implements ImportProfileInterface
|
||||
*/
|
||||
private ?array $allowedLocales = null;
|
||||
|
||||
public function __construct(private readonly UserImportGateway $gateway)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserImportGateway $gateway,
|
||||
private readonly UserAccountService $userAccountService
|
||||
) {
|
||||
}
|
||||
|
||||
public function key(): string
|
||||
@@ -203,7 +207,7 @@ class UserImportProfile implements ImportProfileInterface
|
||||
$input['active'] = null;
|
||||
}
|
||||
|
||||
$result = $this->gateway->createUserFromAdmin($input, (int) ($context['current_user_id'] ?? 0));
|
||||
$result = $this->userAccountService->createFromAdmin($input, (int) ($context['current_user_id'] ?? 0));
|
||||
if (!($result['ok'] ?? false)) {
|
||||
$errors = $result['errors'] ?? [];
|
||||
$message = is_array($errors) && isset($errors[0]) ? (string) $errors[0] : t('User can not be registered');
|
||||
|
||||
@@ -4,8 +4,8 @@ namespace MintyPHP\Service\Org;
|
||||
|
||||
use MintyPHP\Repository\Org\DepartmentRepositoryInterface;
|
||||
use MintyPHP\Service\Audit\SystemAuditService;
|
||||
use MintyPHP\Service\Directory\DirectoryScopeGateway;
|
||||
use MintyPHP\Service\Directory\DirectorySettingsGateway;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
use MintyPHP\Service\User\UserServicesFactory;
|
||||
|
||||
class DepartmentService
|
||||
@@ -14,7 +14,7 @@ class DepartmentService
|
||||
private readonly UserServicesFactory $userServicesFactory,
|
||||
private readonly DepartmentRepositoryInterface $departmentRepository,
|
||||
private readonly DirectorySettingsGateway $settingsGateway,
|
||||
private readonly DirectoryScopeGateway $scopeGateway,
|
||||
private readonly TenantScopeService $scopeGateway,
|
||||
private readonly SystemAuditService $systemAuditService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -4,14 +4,13 @@ namespace MintyPHP\Service\Search;
|
||||
|
||||
use MintyPHP\Repository\Search\SearchQueryRepository;
|
||||
use MintyPHP\Repository\Tenant\UserTenantRepository;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Support\SearchConfig;
|
||||
|
||||
class SearchDataService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway,
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly UserTenantRepository $userTenantRepository,
|
||||
private readonly SearchQueryRepository $searchQueryRepository
|
||||
) {
|
||||
@@ -37,7 +36,7 @@ class SearchDataService
|
||||
}
|
||||
|
||||
$perm = (string) ($resource['permission'] ?? '');
|
||||
if ($perm !== '' && !$this->permissionGateway->userHas($userId, $perm)) {
|
||||
if ($perm !== '' && !$this->permissionService->userHas($userId, $perm)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -68,7 +67,7 @@ class SearchDataService
|
||||
}
|
||||
|
||||
$items = array_merge($items, SearchConfig::hotkeyResultItems($query));
|
||||
if ($this->permissionGateway->userHas($userId, PermissionService::DOCS_VIEW)) {
|
||||
if ($this->permissionService->userHas($userId, PermissionService::DOCS_VIEW)) {
|
||||
$items = array_merge($items, SearchConfig::docsResultItems($query));
|
||||
}
|
||||
|
||||
@@ -145,7 +144,7 @@ class SearchDataService
|
||||
}
|
||||
|
||||
$perm = (string) ($resource['permission'] ?? '');
|
||||
if ($perm !== '' && !$this->permissionGateway->userHas($userId, $perm)) {
|
||||
if ($perm !== '' && !$this->permissionService->userHas($userId, $perm)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -193,7 +192,7 @@ class SearchDataService
|
||||
$results[] = $hotkeyResource;
|
||||
}
|
||||
|
||||
if ($this->permissionGateway->userHas($userId, PermissionService::DOCS_VIEW)) {
|
||||
if ($this->permissionService->userHas($userId, PermissionService::DOCS_VIEW)) {
|
||||
$docsResource = SearchConfig::docsPreviewResource($query);
|
||||
if ($docsResource !== null) {
|
||||
$results[] = $docsResource;
|
||||
@@ -210,7 +209,7 @@ class SearchDataService
|
||||
{
|
||||
if ($userId > 0) {
|
||||
// Prime cached permissions for the current request.
|
||||
$this->permissionGateway->getUserPermissions($userId);
|
||||
$this->permissionService->getUserPermissions($userId);
|
||||
}
|
||||
|
||||
$tenantIds = $userId > 0
|
||||
|
||||
@@ -9,7 +9,7 @@ use MintyPHP\Repository\Tenant\TenantRepositoryInterface;
|
||||
|
||||
class SettingServicesFactory
|
||||
{
|
||||
private ?ThemeConfigService $themeConfigService = null;
|
||||
private ?ThemeConfigGateway $themeConfigService = null;
|
||||
private ?SettingCacheService $settingCacheService = null;
|
||||
private ?SettingsCryptoGatewayInterface $settingsCryptoGateway = null;
|
||||
private ?SettingsMetadataGateway $settingsMetadataGateway = null;
|
||||
@@ -53,7 +53,7 @@ class SettingServicesFactory
|
||||
{
|
||||
return $this->settingsAppGateway ??= new SettingsAppGateway(
|
||||
$this->createSettingsMetadataGateway(),
|
||||
$this->createThemeConfigService(),
|
||||
$this->createThemeConfigGateway(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -105,9 +105,9 @@ class SettingServicesFactory
|
||||
return $this->settingCacheService ??= new SettingCacheService();
|
||||
}
|
||||
|
||||
public function createThemeConfigService(): ThemeConfigService
|
||||
public function createThemeConfigGateway(): ThemeConfigGateway
|
||||
{
|
||||
return $this->themeConfigService ??= new ThemeConfigService();
|
||||
return $this->themeConfigService ??= new ThemeConfigGateway();
|
||||
}
|
||||
|
||||
public function createSettingsCryptoGateway(): SettingsCryptoGatewayInterface
|
||||
|
||||
@@ -8,7 +8,7 @@ class SettingsAppGateway
|
||||
{
|
||||
public function __construct(
|
||||
private readonly SettingsMetadataGateway $settingsMetadataGateway,
|
||||
private readonly ThemeConfigService $themeConfigService
|
||||
private readonly ThemeConfigGateway $themeConfigService
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace MintyPHP\Service\Settings;
|
||||
|
||||
class ThemeConfigService
|
||||
class ThemeConfigGateway
|
||||
{
|
||||
private const DEFAULT_THEMES = [
|
||||
'light' => 'Light',
|
||||
@@ -5,7 +5,6 @@ namespace MintyPHP\Service\Tenant;
|
||||
use MintyPHP\Repository\Org\DepartmentRepositoryInterface;
|
||||
use MintyPHP\Repository\Tenant\TenantRepositoryInterface;
|
||||
use MintyPHP\Repository\Tenant\UserTenantRepositoryInterface;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
|
||||
class TenantScopeService
|
||||
@@ -14,7 +13,7 @@ class TenantScopeService
|
||||
private readonly TenantRepositoryInterface $tenantRepository,
|
||||
private readonly DepartmentRepositoryInterface $departmentRepository,
|
||||
private readonly UserTenantRepositoryInterface $userTenantRepository,
|
||||
private readonly PermissionGateway $permissionGateway
|
||||
private readonly PermissionService $permissionService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -167,6 +166,6 @@ class TenantScopeService
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->permissionGateway->userHas($userId, PermissionService::TENANT_SCOPE_GLOBAL);
|
||||
return $this->permissionService->userHas($userId, PermissionService::TENANT_SCOPE_GLOBAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace MintyPHP\Service\Tenant;
|
||||
use MintyPHP\Repository\Org\DepartmentRepositoryInterface;
|
||||
use MintyPHP\Repository\Tenant\TenantRepositoryInterface;
|
||||
use MintyPHP\Repository\Tenant\UserTenantRepositoryInterface;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
|
||||
class TenantServicesFactory
|
||||
{
|
||||
@@ -14,7 +14,7 @@ class TenantServicesFactory
|
||||
private ?TenantFaviconService $tenantFaviconService = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionGateway $permissionGateway,
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly TenantRepositoryFactory $tenantRepositoryFactory
|
||||
) {
|
||||
}
|
||||
@@ -25,7 +25,7 @@ class TenantServicesFactory
|
||||
$this->createTenantRepository(),
|
||||
$this->createDepartmentRepository(),
|
||||
$this->createUserTenantRepository(),
|
||||
$this->createPermissionGateway()
|
||||
$this->createPermissionService()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ class TenantServicesFactory
|
||||
return $this->tenantRepositoryFactory->createUserTenantRepository();
|
||||
}
|
||||
|
||||
public function createPermissionGateway(): PermissionGateway
|
||||
public function createPermissionService(): PermissionService
|
||||
{
|
||||
return $this->permissionGateway;
|
||||
return $this->permissionService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use MintyPHP\Repository\User\UserListQueryRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserReadRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserWriteRepositoryInterface;
|
||||
use MintyPHP\Service\Audit\SystemAuditService;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class UserAccountService
|
||||
{
|
||||
@@ -18,7 +19,7 @@ class UserAccountService
|
||||
private readonly UserAssignmentService $userAssignmentService,
|
||||
private readonly UserPasswordService $userPasswordService,
|
||||
private readonly UserSettingsGateway $settingsGateway,
|
||||
private readonly UserScopeGateway $scopeGateway,
|
||||
private readonly TenantScopeService $scopeGateway,
|
||||
private readonly UserDirectoryGateway $directoryGateway,
|
||||
private readonly SystemAuditService $systemAuditService,
|
||||
private readonly DatabaseSessionRepository $databaseSessionRepository
|
||||
|
||||
@@ -7,6 +7,7 @@ use MintyPHP\Repository\Org\UserDepartmentRepositoryInterface;
|
||||
use MintyPHP\Repository\Support\DatabaseSessionRepository;
|
||||
use MintyPHP\Repository\Tenant\UserTenantRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserWriteRepositoryInterface;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
|
||||
class UserAssignmentService
|
||||
{
|
||||
@@ -16,7 +17,7 @@ class UserAssignmentService
|
||||
private readonly UserRoleRepositoryInterface $userRoleRepository,
|
||||
private readonly UserDepartmentRepositoryInterface $userDepartmentRepository,
|
||||
private readonly UserDirectoryGateway $directoryGateway,
|
||||
private readonly UserPermissionGateway $permissionGateway,
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly DatabaseSessionRepository $databaseSessionRepository
|
||||
) {
|
||||
}
|
||||
@@ -181,7 +182,7 @@ class UserAssignmentService
|
||||
$ids = array_values(array_filter($ids, static fn ($id) => isset($validMap[$id])));
|
||||
}
|
||||
$result = $this->userRoleRepository->replaceForUser($userId, $ids);
|
||||
$this->permissionGateway->clearUserCache($userId);
|
||||
$this->permissionService->clearUserCache($userId);
|
||||
if ($result && $bumpAuthz) {
|
||||
$this->bumpAuthzVersion($userId);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace MintyPHP\Service\User;
|
||||
|
||||
use MintyPHP\Service\Access\AccessServicesFactory;
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
use MintyPHP\Service\Access\PermissionService;
|
||||
use MintyPHP\Service\Directory\DirectoryRepositoryFactory;
|
||||
use MintyPHP\Service\Settings\SettingsAppGateway;
|
||||
use MintyPHP\Service\Settings\SettingsDefaultsGateway;
|
||||
@@ -16,12 +16,9 @@ class UserGatewayFactory
|
||||
private ?SettingsDefaultsGateway $settingsDefaultsGateway = null;
|
||||
private ?SettingsAppGateway $settingsAppGateway = null;
|
||||
private ?SettingsUserLifecycleGateway $settingsUserLifecycleGateway = null;
|
||||
private ?PermissionGateway $permissionGateway = null;
|
||||
private ?PermissionService $permissionService = null;
|
||||
private ?UserSettingsGateway $userSettingsGateway = null;
|
||||
private ?UserScopeGateway $userScopeGateway = null;
|
||||
private ?UserDirectoryGateway $userDirectoryGateway = null;
|
||||
private ?UserPermissionGateway $userPermissionGateway = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly AccessServicesFactory $accessServicesFactory,
|
||||
private readonly SettingServicesFactory $settingServicesFactory,
|
||||
@@ -39,9 +36,9 @@ class UserGatewayFactory
|
||||
);
|
||||
}
|
||||
|
||||
public function createUserScopeGateway(): UserScopeGateway
|
||||
public function getTenantScopeService(): TenantScopeService
|
||||
{
|
||||
return $this->userScopeGateway ??= new UserScopeGateway($this->tenantScopeService);
|
||||
return $this->tenantScopeService;
|
||||
}
|
||||
|
||||
public function createUserDirectoryGateway(): UserDirectoryGateway
|
||||
@@ -53,14 +50,9 @@ class UserGatewayFactory
|
||||
);
|
||||
}
|
||||
|
||||
public function createUserPermissionGateway(): UserPermissionGateway
|
||||
public function createPermissionService(): PermissionService
|
||||
{
|
||||
return $this->userPermissionGateway ??= new UserPermissionGateway($this->createPermissionGateway());
|
||||
}
|
||||
|
||||
private function createPermissionGateway(): PermissionGateway
|
||||
{
|
||||
return $this->permissionGateway ??= $this->accessServicesFactory->createPermissionGateway();
|
||||
return $this->permissionService ??= $this->accessServicesFactory->createPermissionService();
|
||||
}
|
||||
|
||||
private function createSettingsDefaultsGateway(): SettingsDefaultsGateway
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\User;
|
||||
|
||||
use MintyPHP\Service\Access\PermissionGateway;
|
||||
|
||||
class UserPermissionGateway
|
||||
{
|
||||
public function __construct(private readonly PermissionGateway $permissionGateway)
|
||||
{
|
||||
}
|
||||
|
||||
public function clearUserCache(int $userId): void
|
||||
{
|
||||
$this->permissionGateway->clearUserCache($userId);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\User;
|
||||
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class UserScopeGateway
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TenantScopeService $tenantScopeService
|
||||
) {
|
||||
}
|
||||
|
||||
public function hasGlobalAccess(int $userId): bool
|
||||
{
|
||||
return $this->tenantScopeService->hasGlobalAccess($userId);
|
||||
}
|
||||
|
||||
public function canAccess(string $resourceType, int $resourceId, int $userId): bool
|
||||
{
|
||||
return $this->tenantScopeService->canAccess($resourceType, $resourceId, $userId);
|
||||
}
|
||||
|
||||
public function getUserTenantIds(int $userId): array
|
||||
{
|
||||
return $this->tenantScopeService->getUserTenantIds($userId);
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class UserServicesFactory
|
||||
$this->createUserAssignmentService(),
|
||||
$this->createUserPasswordService(),
|
||||
$this->createUserSettingsGateway(),
|
||||
$this->createUserScopeGateway(),
|
||||
$this->userGatewayFactory->getTenantScopeService(),
|
||||
$this->createUserDirectoryGateway(),
|
||||
$this->auditServicesFactory->createSystemAuditService(),
|
||||
$this->databaseSessionRepository
|
||||
@@ -58,7 +58,7 @@ class UserServicesFactory
|
||||
$this->createUserRoleRepository(),
|
||||
$this->createUserDepartmentRepository(),
|
||||
$this->createUserDirectoryGateway(),
|
||||
$this->createUserPermissionGateway(),
|
||||
$this->userGatewayFactory->createPermissionService(),
|
||||
$this->databaseSessionRepository
|
||||
);
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class UserServicesFactory
|
||||
$this->createUserReadRepository(),
|
||||
$this->createUserWriteRepository(),
|
||||
$this->createUserTenantRepository(),
|
||||
$this->createUserScopeGateway(),
|
||||
$this->userGatewayFactory->getTenantScopeService(),
|
||||
$this->createUserDirectoryGateway()
|
||||
);
|
||||
}
|
||||
@@ -139,21 +139,11 @@ class UserServicesFactory
|
||||
return $this->userGatewayFactory->createUserSettingsGateway();
|
||||
}
|
||||
|
||||
public function createUserScopeGateway(): UserScopeGateway
|
||||
{
|
||||
return $this->userGatewayFactory->createUserScopeGateway();
|
||||
}
|
||||
|
||||
public function createUserDirectoryGateway(): UserDirectoryGateway
|
||||
{
|
||||
return $this->userGatewayFactory->createUserDirectoryGateway();
|
||||
}
|
||||
|
||||
public function createUserPermissionGateway(): UserPermissionGateway
|
||||
{
|
||||
return $this->userGatewayFactory->createUserPermissionGateway();
|
||||
}
|
||||
|
||||
public function createUserLifecycleService(): UserLifecycleService
|
||||
{
|
||||
return $this->userLifecycleService ??= new UserLifecycleService(
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace MintyPHP\Service\User;
|
||||
use MintyPHP\Repository\Tenant\UserTenantRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserReadRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserWriteRepositoryInterface;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class UserTenantContextService
|
||||
{
|
||||
@@ -12,7 +13,7 @@ class UserTenantContextService
|
||||
private readonly UserReadRepositoryInterface $userReadRepository,
|
||||
private readonly UserWriteRepositoryInterface $userWriteRepository,
|
||||
private readonly UserTenantRepositoryInterface $userTenantRepository,
|
||||
private readonly UserScopeGateway $scopeGateway,
|
||||
private readonly TenantScopeService $scopeGateway,
|
||||
private readonly UserDirectoryGateway $directoryGateway
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ function setAppContainer(\MintyPHP\App\AppContainer $container): void
|
||||
$GLOBALS['minty_app_container'] = $container;
|
||||
|
||||
\MintyPHP\Http\ApiAuth::configure(
|
||||
static fn (): \MintyPHP\Service\Auth\AuthScopeGateway => $container->get(\MintyPHP\Service\Auth\AuthScopeGateway::class),
|
||||
static fn (): \MintyPHP\Service\Tenant\TenantScopeService => $container->get(\MintyPHP\Service\Tenant\TenantScopeService::class),
|
||||
static fn (): \MintyPHP\Service\Auth\ApiTokenService => $container->get(\MintyPHP\Service\Auth\ApiTokenService::class),
|
||||
static fn (): \MintyPHP\Repository\Access\UserRoleRepository => $container->get(\MintyPHP\Repository\Access\UserRoleRepository::class),
|
||||
static fn (): \MintyPHP\Repository\Access\RolePermissionRepository => $container->get(\MintyPHP\Repository\Access\RolePermissionRepository::class),
|
||||
@@ -192,14 +192,14 @@ function appSetting(string $key): ?string
|
||||
*/
|
||||
function appThemes(): array
|
||||
{
|
||||
if (!class_exists('MintyPHP\\Service\\Settings\\ThemeConfigService')) {
|
||||
if (!class_exists('MintyPHP\\Service\\Settings\\ThemeConfigGateway')) {
|
||||
return [
|
||||
'light' => 'Light',
|
||||
'dark' => 'Dark',
|
||||
];
|
||||
}
|
||||
|
||||
return app(\MintyPHP\Service\Settings\ThemeConfigService::class)->all();
|
||||
return app(\MintyPHP\Service\Settings\ThemeConfigGateway::class)->all();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user