fix(security): enforce atomic role/permission writes and user assignment rollback

This commit is contained in:
2026-03-09 19:54:58 +01:00
parent 11ca546eae
commit 01c05d997f
5 changed files with 228 additions and 73 deletions

View File

@@ -221,9 +221,14 @@ class UserAccountService
$createdUser = $this->userReadRepository->findByEmail($form['email']);
$uuid = $createdUser['uuid'] ?? null;
$userId = (int) ($createdUser['id'] ?? 0);
if ($userId <= 0) {
$this->rollbackQuietly();
return ['ok' => false, 'errors' => [t('User can not be registered')], 'form' => $form];
}
if ($userId > 0 && $tenantIds) {
$this->userAssignmentService->syncTenants($userId, $tenantIds);
if ($tenantIds && !$this->userAssignmentService->syncTenants($userId, $tenantIds)) {
$this->rollbackQuietly();
return ['ok' => false, 'errors' => [t('User can not be registered')], 'form' => $form];
}
$roleIds = $this->userAssignmentService->normalizeIdInput($input['role_ids'] ?? []);
@@ -233,8 +238,9 @@ class UserAccountService
$roleIds = [$defaultRoleId];
}
}
if ($userId > 0 && $roleIds) {
$this->userAssignmentService->syncRoles($userId, $roleIds);
if ($roleIds && !$this->userAssignmentService->syncRoles($userId, $roleIds)) {
$this->rollbackQuietly();
return ['ok' => false, 'errors' => [t('User can not be registered')], 'form' => $form];
}
$departmentIds = $this->userAssignmentService->normalizeIdInput($input['department_ids'] ?? []);
@@ -244,8 +250,9 @@ class UserAccountService
$departmentIds = [$defaultDepartmentId];
}
}
if ($userId > 0 && $departmentIds) {
$this->userAssignmentService->syncDepartments($userId, $departmentIds);
if ($departmentIds && !$this->userAssignmentService->syncDepartments($userId, $departmentIds)) {
$this->rollbackQuietly();
return ['ok' => false, 'errors' => [t('User can not be registered')], 'form' => $form];
}
$this->databaseSessionRepository->commitTransaction();
@@ -260,7 +267,7 @@ class UserAccountService
$this->systemAuditService->record('admin.users.create', 'success', [
'actor_user_id' => $currentUserId > 0 ? $currentUserId : null,
'target_type' => 'user',
'target_id' => $userId > 0 ? $userId : null,
'target_id' => $userId,
'target_uuid' => is_string($uuid) ? $uuid : '',
'metadata' => [
'assigned_tenant_ids' => $tenantIds,
@@ -522,18 +529,24 @@ class UserAccountService
$createdUser = $this->userReadRepository->findByEmail($form['email']);
$userId = (int) ($createdUser['id'] ?? 0);
if ($userId > 0) {
if ($defaultTenantId) {
$this->userAssignmentService->syncTenants($userId, [$defaultTenantId]);
}
$defaultRoleId = $this->settingsGateway->getDefaultRoleId();
if ($defaultRoleId) {
$this->userAssignmentService->syncRoles($userId, [$defaultRoleId]);
}
$defaultDepartmentId = $this->settingsGateway->getDefaultDepartmentId();
if ($defaultDepartmentId) {
$this->userAssignmentService->syncDepartments($userId, [$defaultDepartmentId]);
}
if ($userId <= 0) {
$this->rollbackQuietly();
return ['ok' => false, 'error' => t('User can not be registered')];
}
if ($defaultTenantId && !$this->userAssignmentService->syncTenants($userId, [$defaultTenantId])) {
$this->rollbackQuietly();
return ['ok' => false, 'error' => t('User can not be registered')];
}
$defaultRoleId = $this->settingsGateway->getDefaultRoleId();
if ($defaultRoleId && !$this->userAssignmentService->syncRoles($userId, [$defaultRoleId])) {
$this->rollbackQuietly();
return ['ok' => false, 'error' => t('User can not be registered')];
}
$defaultDepartmentId = $this->settingsGateway->getDefaultDepartmentId();
if ($defaultDepartmentId && !$this->userAssignmentService->syncDepartments($userId, [$defaultDepartmentId])) {
$this->rollbackQuietly();
return ['ok' => false, 'error' => t('User can not be registered')];
}
$this->databaseSessionRepository->commitTransaction();