instances added god may help

This commit is contained in:
2026-02-23 12:58:19 +01:00
parent 25370a1a55
commit 99db252f60
290 changed files with 9858 additions and 4914 deletions

View File

@@ -1,49 +1,58 @@
<?php
use MintyPHP\Buffer;
use MintyPHP\Support\Flash;
use MintyPHP\Support\Guard;
use MintyPHP\I18n;
use MintyPHP\Router;
use MintyPHP\DB;
use MintyPHP\Repository\Access\UserRoleRepository;
use MintyPHP\Repository\Tenant\UserTenantRepository;
use MintyPHP\Repository\Org\UserDepartmentRepository;
use MintyPHP\Repository\Access\RolePermissionRepository;
use MintyPHP\I18n;
use MintyPHP\Repository\Auth\PasswordResetRepository;
use MintyPHP\Repository\Auth\RememberTokenRepository;
use MintyPHP\Service\Auth\AuthService;
use MintyPHP\Service\CustomField\UserCustomFieldValueService;
use MintyPHP\Service\Org\DepartmentService;
use MintyPHP\Service\Access\RoleService;
use MintyPHP\Service\Tenant\TenantService;
use MintyPHP\Service\User\UserService;
use MintyPHP\Router;
use MintyPHP\Service\Access\AccessServicesFactory;
use MintyPHP\Service\Access\PermissionService;
use MintyPHP\Service\Tenant\TenantScopeService;
use MintyPHP\Service\Auth\AuthServicesFactory;
use MintyPHP\Service\CustomField\UserCustomFieldValueService;
use MintyPHP\Service\User\UserServicesFactory;
use MintyPHP\Support\Flash;
use MintyPHP\Support\Guard;
Guard::requireLogin();
$userServicesFactory = new UserServicesFactory();
$userAccountService = $userServicesFactory->createUserAccountService();
$userAssignmentService = $userServicesFactory->createUserAssignmentService();
$userTenantRepository = $userServicesFactory->createUserTenantRepository();
$userRoleRepository = $userServicesFactory->createUserRoleRepository();
$userDepartmentRepository = $userServicesFactory->createUserDepartmentRepository();
$userPasswordPolicyService = $userServicesFactory->createUserPasswordPolicyService();
$authServiceFactory = new AuthServicesFactory();
$accessServicesFactory = new AccessServicesFactory();
$rolePermissionRepository = $accessServicesFactory->createRolePermissionRepository();
$authService = $authServiceFactory->createAuthService();
$apiTokenService = $authServiceFactory->createApiTokenService();
$passwordResetRepository = new PasswordResetRepository();
$rememberTokenRepository = new RememberTokenRepository();
$passwordMinLength = $userPasswordPolicyService->minLength();
$passwordHints = $userPasswordPolicyService->hints();
$currentUserId = (int) ($_SESSION['user']['id'] ?? 0);
if ($currentUserId > 0) {
PermissionService::getUserPermissions($currentUserId, true);
permissionGateway()->getUserPermissions($currentUserId, true);
}
$uuid = trim((string) ($id ?? ''));
$user = $uuid !== '' ? UserService::findByUuid($uuid) : null;
$user = $uuid !== '' ? $userAccountService->findByUuid($uuid) : null;
if (!$user) {
Flash::error('User not found', 'admin/users', 'user_not_found');
Router::redirect('admin/users');
}
$userId = (int) ($user['id'] ?? 0);
$canViewUsers = PermissionService::userHas($currentUserId, PermissionService::USERS_VIEW);
$canUpdateUser = PermissionService::userHas($currentUserId, PermissionService::USERS_UPDATE);
$canUpdateSelf = PermissionService::userHas($currentUserId, PermissionService::USERS_SELF_UPDATE);
$canUpdateAssignments = PermissionService::userHas($currentUserId, PermissionService::USERS_UPDATE_ASSIGNMENTS);
$canViewUsers = permissionGateway()->userHas($currentUserId, PermissionService::USERS_VIEW);
$canUpdateUser = permissionGateway()->userHas($currentUserId, PermissionService::USERS_UPDATE);
$canUpdateSelf = permissionGateway()->userHas($currentUserId, PermissionService::USERS_SELF_UPDATE);
$canUpdateAssignments = permissionGateway()->userHas($currentUserId, PermissionService::USERS_UPDATE_ASSIGNMENTS);
$isOwnAccount = $currentUserId === $userId;
$canEditUser = $isOwnAccount ? ($canUpdateUser || $canUpdateSelf) : $canUpdateUser;
$canEditAssignments = $canEditUser && $canUpdateAssignments;
if (!$isOwnAccount && !TenantScopeService::canAccess('users', $userId, $currentUserId)) {
if (!$isOwnAccount && !directoryServicesFactory()->createDirectoryScopeGateway()->canAccess('users', $userId, $currentUserId)) {
Router::redirect('error/forbidden');
return;
}
@@ -53,7 +62,7 @@ if (!$canViewUsers && !$canEditUser) {
}
$creatorId = (int) ($user['created_by'] ?? 0);
if ($creatorId > 0) {
$creator = UserService::findById($creatorId);
$creator = $userAccountService->findById($creatorId);
if ($creator) {
$creatorName = trim(($creator['first_name'] ?? '') . ' ' . ($creator['last_name'] ?? ''));
$user['created_by_label'] = $creatorName !== '' ? $creatorName : ($creator['email'] ?? '');
@@ -62,7 +71,7 @@ if ($creatorId > 0) {
}
$modifierId = (int) ($user['modified_by'] ?? 0);
if ($modifierId > 0) {
$modifier = UserService::findById($modifierId);
$modifier = $userAccountService->findById($modifierId);
if ($modifier) {
$modifierName = trim(($modifier['first_name'] ?? '') . ' ' . ($modifier['last_name'] ?? ''));
$user['modified_by_label'] = $modifierName !== '' ? $modifierName : ($modifier['email'] ?? '');
@@ -71,7 +80,7 @@ if ($modifierId > 0) {
}
$activeChangedById = (int) ($user['active_changed_by'] ?? 0);
if ($activeChangedById > 0) {
$activeChanger = UserService::findById($activeChangedById);
$activeChanger = $userAccountService->findById($activeChangedById);
if ($activeChanger) {
$activeChangerName = trim(($activeChanger['first_name'] ?? '') . ' ' . ($activeChanger['last_name'] ?? ''));
$user['active_changed_by_label'] = $activeChangerName !== '' ? $activeChangerName : ($activeChanger['email'] ?? '');
@@ -81,19 +90,19 @@ if ($activeChangedById > 0) {
$errors = [];
$form = $user;
// Users with tenants.update permission can see ALL tenants (to assign new tenants to users)
$canManageTenants = PermissionService::userHas($currentUserId, PermissionService::TENANTS_UPDATE);
$allowedTenantIds = $canManageTenants ? null : TenantScopeService::getUserTenantIds($currentUserId);
$canManageTenants = permissionGateway()->userHas($currentUserId, PermissionService::TENANTS_UPDATE);
$allowedTenantIds = $canManageTenants ? null : directoryServicesFactory()->createDirectoryScopeGateway()->getUserTenantIds($currentUserId);
$tenants = TenantService::list();
$tenants = directoryServicesFactory()->createTenantService()->list();
if ($allowedTenantIds) {
$tenants = array_values(array_filter($tenants, static function (array $tenant) use ($allowedTenantIds): bool {
$tenantId = (int) ($tenant['id'] ?? 0);
return $tenantId > 0 && in_array($tenantId, $allowedTenantIds, true);
}));
} elseif (!$canManageTenants && TenantScopeService::isStrict()) {
} elseif (!$canManageTenants && directoryServicesFactory()->createDirectoryScopeGateway()->isStrict()) {
$tenants = [];
}
$selectedTenantIds = UserTenantRepository::listTenantIdsByUserId($userId);
$selectedTenantIds = $userTenantRepository->listTenantIdsByUserId($userId);
if ($allowedTenantIds) {
$selectedTenantIds = array_values(array_intersect($selectedTenantIds, $allowedTenantIds));
}
@@ -102,13 +111,13 @@ if (!$primaryTenantId && count($selectedTenantIds) === 1) {
$primaryTenantId = (int) $selectedTenantIds[0];
$user['primary_tenant_id'] = $primaryTenantId;
}
$roles = RoleService::listActive();
$selectedRoleIds = UserRoleRepository::listRoleIdsByUserId($userId);
$permissionRows = RolePermissionRepository::listPermissionsWithRolesByRoleIds($selectedRoleIds);
$selectedDepartmentIds = UserDepartmentRepository::listDepartmentIdsByUserId($userId);
$departmentOptionsByTenant = DepartmentService::groupActiveByTenantIds($selectedTenantIds);
$roles = directoryServicesFactory()->createRoleService()->listActive();
$selectedRoleIds = $userRoleRepository->listRoleIdsByUserId($userId);
$permissionRows = $rolePermissionRepository->listPermissionsWithRolesByRoleIds($selectedRoleIds);
$selectedDepartmentIds = $userDepartmentRepository->listDepartmentIdsByUserId($userId);
$departmentOptionsByTenant = directoryServicesFactory()->createDepartmentService()->groupActiveByTenantIds($selectedTenantIds);
$canEditCustomFieldValues = $canEditUser
&& (PermissionService::userHas($currentUserId, PermissionService::CUSTOM_FIELDS_EDIT_VALUES)
&& (permissionGateway()->userHas($currentUserId, PermissionService::CUSTOM_FIELDS_EDIT_VALUES)
|| ($isOwnAccount && $canUpdateSelf));
$customFieldDefinitionsByTenant = UserCustomFieldValueService::buildDefinitionsByTenant($selectedTenantIds);
$customFieldDefinitionIds = [];
@@ -127,17 +136,17 @@ $customFieldPostedValues = [
];
$passwordResets = [];
if ($canViewUsers || $canEditUser) {
$passwordResets = PasswordResetRepository::listByUserId($userId, 25);
$passwordResets = $passwordResetRepository->listByUserId($userId, 25);
}
$rememberTokens = [];
if ($canViewUsers || $canEditUser) {
$rememberTokens = RememberTokenRepository::listByUserId($userId, 25);
$rememberTokens = $rememberTokenRepository->listByUserId($userId, 25);
}
$apiTokens = [];
$canManageApiTokens = $canEditUser
&& PermissionService::userHas($currentUserId, PermissionService::API_TOKENS_MANAGE);
&& permissionGateway()->userHas($currentUserId, PermissionService::API_TOKENS_MANAGE);
if ($canViewUsers || $canEditUser) {
$apiTokens = \MintyPHP\Service\Auth\ApiTokenService::listForUser($userId);
$apiTokens = $apiTokenService->listForUser($userId);
}
$showApiTokens = !empty($apiTokens) || $canManageApiTokens;
// Keep initial $isOwnAccount/$canEditUser values for view permissions.
@@ -147,25 +156,25 @@ if (isset($_POST['email'])) {
Router::redirect('error/forbidden');
return;
}
$result = UserService::updateFromAdmin($userId, $_POST, $currentUserId);
$result = $userAccountService->updateFromAdmin($userId, $_POST, $currentUserId);
$form = $result['form'] ?? $form;
$errors = $result['errors'] ?? [];
$tenantIds = UserService::normalizeIdInput($_POST['tenant_ids'] ?? []);
$existingTenantIds = UserTenantRepository::listTenantIdsByUserId($userId);
$tenantIds = $userAssignmentService->normalizeIdInput($_POST['tenant_ids'] ?? []);
$existingTenantIds = $userTenantRepository->listTenantIdsByUserId($userId);
$tenantIdsForSync = $tenantIds;
if ($canEditAssignments && $allowedTenantIds) {
$tenantIds = array_values(array_intersect($tenantIds, $allowedTenantIds));
$tenantIdsForSync = TenantScopeService::mergeTenantIdsPreservingOutOfScope(
$tenantIdsForSync = directoryServicesFactory()->createDirectoryScopeGateway()->mergeTenantIdsPreservingOutOfScope(
$tenantIds,
$existingTenantIds,
$allowedTenantIds
);
} elseif ($canEditAssignments && !$canManageTenants && TenantScopeService::isStrict()) {
} elseif ($canEditAssignments && !$canManageTenants && directoryServicesFactory()->createDirectoryScopeGateway()->isStrict()) {
$tenantIds = [];
$tenantIdsForSync = $existingTenantIds;
}
if (!$canEditAssignments) {
$tenantIds = UserTenantRepository::listTenantIdsByUserId($userId);
$tenantIds = $userTenantRepository->listTenantIdsByUserId($userId);
if ($allowedTenantIds) {
$tenantIds = array_values(array_intersect($tenantIds, $allowedTenantIds));
}
@@ -173,9 +182,9 @@ if (isset($_POST['email'])) {
}
$selectedTenantIds = $tenantIds;
$primaryTenantId = (int) ($_POST['primary_tenant_id'] ?? 0);
$selectedRoleIds = UserService::normalizeIdInput($_POST['role_ids'] ?? []);
$selectedDepartmentIds = UserService::normalizeIdInput($_POST['department_ids'] ?? []);
$departmentOptionsByTenant = DepartmentService::groupActiveByTenantIds($selectedTenantIds);
$selectedRoleIds = $userAssignmentService->normalizeIdInput($_POST['role_ids'] ?? []);
$selectedDepartmentIds = $userAssignmentService->normalizeIdInput($_POST['department_ids'] ?? []);
$departmentOptionsByTenant = directoryServicesFactory()->createDepartmentService()->groupActiveByTenantIds($selectedTenantIds);
$customFieldDefinitionsByTenant = UserCustomFieldValueService::buildDefinitionsByTenant($selectedTenantIds);
$customFieldDefinitionIds = [];
foreach ($customFieldDefinitionsByTenant as $tenantDefinitions) {
@@ -197,10 +206,10 @@ if (isset($_POST['email'])) {
$db = DB::handle();
$db->begin_transaction();
try {
UserService::syncTenants($userId, $tenantIdsForSync, false);
UserService::syncRoles($userId, $selectedRoleIds, false);
UserService::syncDepartments($userId, $selectedDepartmentIds, false);
UserService::bumpAuthzVersion($userId);
$userAssignmentService->syncTenants($userId, $tenantIdsForSync, false);
$userAssignmentService->syncRoles($userId, $selectedRoleIds, false);
$userAssignmentService->syncDepartments($userId, $selectedDepartmentIds, false);
$userAssignmentService->bumpAuthzVersion($userId);
$db->commit();
} catch (\Throwable $exception) {
$db->rollback();
@@ -209,7 +218,7 @@ if (isset($_POST['email'])) {
// Update session if editing own account (tenant assignments changed)
if ($currentUserId === $userId && !$errors) {
AuthService::loadTenantDataIntoSession($userId);
$authService->loadTenantDataIntoSession($userId);
}
}
$customFieldSyncResult = UserCustomFieldValueService::syncForUser(