N°8534 - Prevent Admin, SuperUser from loose of rights (#774)

* N°8534 - Prevent Admin & SuperUser from suicide
Prevent creation/modification of Administrator, SuperUser, REST User, combined with a Profile denying access to the backoffice
This commit is contained in:
Vincent Dumas
2025-11-17 14:17:18 +01:00
committed by GitHub
parent b8345de553
commit 53de040934
21 changed files with 201 additions and 88 deletions

View File

@@ -536,6 +536,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Cache
$this->m_aObjectActionGrants = [];
$this->m_aAdministrators = null;
$this->aUsersProfilesList = [];
}
public function LoadCache()

View File

@@ -404,14 +404,14 @@ abstract class User extends cmdbAbstractObject
}
if (!in_array(ADMIN_PROFILE_NAME, $aProfiles)) {
// Check if the user is yet allowed to modify Users
// Prevent a User to lose the right to modify Users
if (method_exists($oAddon, 'ResetCache')) {
$aCurrentProfiles = Session::Get('profile_list');
// Set the current profiles into a session variable (not yet in the database)
Session::Set('profile_list', $aProfiles);
$oAddon->ResetCache();
if (!$oAddon->IsActionAllowed($this, 'User', UR_ACTION_MODIFY, null)) {
if (!$oAddon->IsActionAllowed($this, get_class($this), UR_ACTION_MODIFY, null)) {
$this->m_aCheckIssues[] = Dict::S('Class:User/Error:CurrentProfilesHaveInsufficientRights');
}
$oAddon->ResetCache();
@@ -422,6 +422,20 @@ abstract class User extends cmdbAbstractObject
Session::Set('profile_list', $aCurrentProfiles);
}
}
// Prevent an administrator to remove their own admin profile
if (UserRights::IsAdministrator($this)) {
$this->m_aCheckIssues[] = Dict::S('Class:User/Error:AdminProfileCannotBeRemovedBySelf');
}
}
}
elseif ($this->IsPrivilegedUser()) {
// Prevent Privileged User to be saved with profiles denying the access to the backoffice
$oSet->Rewind();
while ($oUserProfile = $oSet->Fetch()) {
$sProfile = $oUserProfile->Get('profile');
if (in_array($sProfile, $aForbiddenProfiles)) {
$this->m_aCheckIssues[] = Dict::Format('Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice', $sProfile);
}
}
}
}
@@ -635,6 +649,21 @@ abstract class User extends cmdbAbstractObject
}
return UserRights::GetUserId() == $this->GetKey();
}
private function IsPrivilegedUser(): bool
{
$aPrivilegedProfiles = ['Administrator' => '1', 'REST Services User' => '1024', 'SuperUser' => '117'];
$oSet = $this->Get('profile_list');
$oSet->Rewind();
while ($oUserProfile = $oSet->Fetch()) {
$iProfile = $oUserProfile->Get('profileid');
if (in_array($iProfile, $aPrivilegedProfiles)) {
return true;
}
}
return false;
}
}
/**

View File

@@ -168,9 +168,11 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Class:User/Attribute:status/Value:disabled' => 'Neaktivní',
'Class:User/Error:LoginMustBeUnique' => 'Uživatelské jméno musí být jedinečné - "%1s" je již použito.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Uživateli musí být přidělen alespoň jeden profil.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Profil "%1$s" nemůže být přidán, byl by mu odepřen přístup do backoffice',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Změna není povolena pro vašeho vlastního uživatele',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Přístupné organizace musí obsahovat organizaci uživatele.',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'Aktuální seznam profilů neposkytuje dostatečná přístupová práva (uživatele již nelze upravovat)',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'Profil Portal power user neposkytuje dostatečná přístupová práva (je třeba přidat jiný profil)',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Uživatel musí být přiřazen minimálně do jedné organizace.',

View File

@@ -168,10 +168,12 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
'Class:User/Attribute:status/Value:disabled' => 'Disabled~~',
'Class:User/Error:LoginMustBeUnique' => 'Login skal være entydig - "%1s" er allerede i brug.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Mindst en profil skal knyttes til denne bruger.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Profile "%1$s" cannot be added it will deny the access to backoffice~~',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Changing status is not allowed for your own User~~',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Allowed organizations must contain User organization~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'The current list of profiles does not give sufficient access rights (Users are not modifiable anymore)~~',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'You cannot remove your own rights to edit Users~~',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)~~',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'At least one organization must be assigned to this user.~~',
'Class:User/Error:OrganizationNotAllowed' => 'Organization not allowed.~~',

View File

@@ -167,9 +167,11 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
'Class:User/Attribute:status/Value:disabled' => 'Inaktiv',
'Class:User/Error:LoginMustBeUnique' => 'Login-Namen müssen unterschiedlich sein - "%1s" benutzt diesen Login-Name bereits.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Mindestens ein Profil muss diesem Benutzer zugewiesen sein.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Profil "%1$s" kann nicht hinzugefügt werde, es verhindert den Zugriff auf das Backoffice.',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Statusänderungen sind für den eigenen Benutzer nicht erlaubt.',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Die Organisation des Benutzers muss in den erlaubten Organisationen enthalten sein.',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'Die aktuelle Liste an Profilen vergibt unzureichende Berechtigungen (Benutzer können nicht mehr geändert werden)',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'Das Profil des Portal-Power-Benutzers hat nicht ausreichend Zugriffsrechte (ein weiteres Profil muss hinzugefügt werden)',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Mindestens eine Organisation muss diesem Benutzer zugewiesen sein.',

View File

@@ -182,10 +182,12 @@ Dict::Add('EN US', 'English', 'English', [
'Class:User/Error:LoginMustBeUnique' => 'Login must be unique - "%1$s" is already being used.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'At least one profile must be assigned to this user.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)',
'Class:User/Error:ProfileNotAllowed' => 'Profile "%1$s" cannot be added it will deny the access to backoffice',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Changing status is not allowed for your own User',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Allowed organizations must contain User organization',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'The current list of profiles does not give sufficient access rights (Users are not modifiable anymore)',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'You cannot remove your own rights to edit Users',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'At least one organization must be assigned to this user.',
'Class:User/Error:OrganizationNotAllowed' => 'Organization not allowed.',

View File

@@ -182,9 +182,11 @@ Dict::Add('EN GB', 'British English', 'British English', [
'Class:User/Error:LoginMustBeUnique' => 'Login must be unique - "%1$s" is already being used.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'At least one profile must be assigned to this user.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Profile "%1$s" cannot be added as it will deny access to the back office.',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Changing status is not allowed for your own User',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Allowed organisations must contain User organisation',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'The current list of profiles does not give sufficient access rights (Users are not modifiable any more)',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'At least one organisation must be assigned to this user.',

View File

@@ -166,9 +166,11 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Class:User/Attribute:status/Value:disabled' => 'Deshabilitado',
'Class:User/Error:LoginMustBeUnique' => 'Usuario debe ser único - "%1s" ya se encuentra en uso.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Al menos un Perfil debe ser asignado a este usuario.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'No se puede agregar el perfil "%1$s"; denegará el acceso al backoffice',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Cambiar estatus no está permitido para su propio usuario',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Las organizaciones permitidas deben contener una organización de usuario',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'La lista actual de perfiles no otorga suficientes permisos de acceso (los usuarios ya no son modificables)',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'El perfil de usuario avanzado del Portal no otorga suficientes derechos de acceso (se debe agregar otro perfil)',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Al menos una organización debe ser asignada a este usuario.',

View File

@@ -173,10 +173,12 @@ Dict::Add('FR FR', 'French', 'Français', [
'Class:User/Attribute:status/Value:disabled' => 'Désactivé',
'Class:User/Error:LoginMustBeUnique' => 'Le login doit être unique - "%1s" est déjà utilisé.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'L\'utilisateur doit avoir au moins un profil.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Le profil "%1$s" ne peut pas être donné aux Administrateurs, SuperUsers et REST Services Users',
'Class:User/Error:ProfileNotAllowed' => 'Le profil "%1$s" ne peux pas être ajouté à son propre utilisateur, il interdit l\'accès à la console',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Impossible de changer l\'état de son propre utilisateur',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Les organisations permises doivent contenir l\'organisation de l\'utilisateur',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'Les profils existants ne permettent pas de modifier les utilisateurs',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'Vous ne pouvez pas supprimer votre propre profil Administrateur. Demandez à un autre Administrateur de le faire pour vous',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'Vous ne pouvez pas supprimer vos propres droits de modification des utilisateurs.',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'Le profil Portal power user ne donne pas suffisamment de droits à l\'utilisateur (un autre profil doit être ajouté)',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'L\'utilisateur doit avoir au moins une organisation.',
'Class:User/Error:OrganizationNotAllowed' => 'Organisation non autorisée.',

View File

@@ -168,9 +168,11 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Class:User/Attribute:status/Value:disabled' => 'Letiltott',
'Class:User/Error:LoginMustBeUnique' => 'A felhasználónévnek egyedinek kell lennie - "%1s" már létezik.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Legalább egy profilt a felhasználóhoz kell rendelni.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'A "%1$s" profil nem adható hozzá, le lesz tiltva',
'Class:User/Error:StatusChangeIsNotAllowed' => 'A saját felhasználó státuszának cseréje nem engedélyezett',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Az engedélyezett szervezeteknek tartalmazniuk kell a felhasználói szervezetet',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'A profilok jelenlegi listája nem ad elegendő hozzáférési jogot (a felhasználók már nem módosíthatók)',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)~~',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'A felhasználóhoz legalább egy szervezeti egységet hozzá kell rendelni',

View File

@@ -168,9 +168,11 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
'Class:User/Attribute:status/Value:disabled' => 'Disabilitato',
'Class:User/Error:LoginMustBeUnique' => 'Il Login deve essere unico - "%1s" già in uso',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'È necessario almeno un profilo assegnato all\'utente.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Il profilo "%1$s" non può essere aggiunto poiché nega l\'accesso al back office.',
'Class:User/Error:StatusChangeIsNotAllowed' => 'La modifica dello stato non è consentita per il proprio utente.',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Le organizzazioni consentite devono includere l\'organizzazione dell\'utente.',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'L\'elenco attuale dei profili non conferisce diritti di accesso sufficienti (gli utenti non sono più modificabili).',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'Il profilo utente con poteri del portale non concede diritti di accesso sufficienti (deve essere aggiunto un altro profilo)',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'È necessario assegnare almeno un\'organizzazione a questo utente.',

View File

@@ -168,10 +168,12 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
'Class:User/Attribute:status/Value:disabled' => 'Disabled~~',
'Class:User/Error:LoginMustBeUnique' => 'ログイン名は一意でないといけません。- "%1s" はすでに使われています。',
'Class:User/Error:AtLeastOneProfileIsNeeded' => '少なくとも1件のプロフィールがこのユーザに指定されなければなりません。',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Profile "%1$s" cannot be added it will deny the access to backoffice~~',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Changing status is not allowed for your own User~~',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Allowed organizations must contain User organization~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'The current list of profiles does not give sufficient access rights (Users are not modifiable anymore)~~',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'You cannot remove your own rights to edit Users~~',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)~~',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'At least one organization must be assigned to this user.~~',
'Class:User/Error:OrganizationNotAllowed' => 'Organization not allowed.~~',

View File

@@ -168,9 +168,11 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Class:User/Attribute:status/Value:disabled' => 'Uitgeschakeld',
'Class:User/Error:LoginMustBeUnique' => 'Login moet uniek zijn - "%1s" is al in gebruik',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Minstens één profiel moet toegewezen zijn aan deze gebruiker',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Profiel "%1$s" kan niet toegevoegd worden omdat het de toegang tot de backoffice zou ontzeggen.',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Je kan de status voor je eigen gebruikersaccount niet wijzigen.',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'De toegestande organisaties moeten minstens de organisatie bevatten waartoe de gebruikersaccount behoort.',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'De huidige lijst van profielen heeft niet voldoende toegangsrechten (gebruikersaccount zijn niet meer wijzigbaar).',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)~~',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Minstens één organisatie moet toegewezen zijn aan deze gebruiker',

View File

@@ -168,9 +168,11 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
'Class:User/Attribute:status/Value:disabled' => 'Wyłączone',
'Class:User/Error:LoginMustBeUnique' => 'Login musi być unikatowy - "%1s" jest już używany.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Do użytkownika musi być przypisany co najmniej jeden profil.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Nie można dodać profilu "%1$s" nie ma on dostępu do zaplecza',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Zmiana statusu nie jest dozwolona dla własnego użytkownika',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Dozwolone organizacje muszą zawierać organizację użytkownika',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'Aktualna lista profili nie daje wystarczających praw dostępu (Użytkowników nie można już modyfikować)',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'Profil użytkownika zaawansowanego Portalu nie zapewnia wystarczających praw dostępu (należy dodać kolejny profil)',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Do użytkownika musi być przypisana co najmniej jedna organizacja.',

View File

@@ -168,9 +168,11 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Class:User/Attribute:status/Value:disabled' => 'Inativa',
'Class:User/Error:LoginMustBeUnique' => 'Login deve ser único - "%1s" já existe',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Pelo menos um perfil deve ser atribuído a esse usuário',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'O perfil "%1$s" não pôde ser adicionado, ele negará o acesso ao backoffice',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Alterar o status da conta não é permitido para o seu próprio usuário',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'As organizações permitidas devem conter apenas usuários pertencentes a organização',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'A lista atual de perfis não fornece permissões de acesso suficientes (os usuários não são mais modificáveis)',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)~~',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Pelo menos uma organização deve ser atribuída a esse usuário',

View File

@@ -169,10 +169,12 @@ Dict::Add('RU RU', 'Russian', 'Русский', [
'Class:User/Attribute:status/Value:disabled' => 'Отключен',
'Class:User/Error:LoginMustBeUnique' => 'Логин должен быть уникальным - "%1s" уже используется.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Как минимум один профиль должен быть назначен данному пользователю.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Profile "%1$s" cannot be added it will deny the access to backoffice~~',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Changing status is not allowed for your own User~~',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Allowed organizations must contain User organization~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'The current list of profiles does not give sufficient access rights (Users are not modifiable anymore)~~',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'You cannot remove your own rights to edit Users~~',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)~~',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Этому пользователю должна быть назначена хотя бы одна организация.',
'Class:User/Error:OrganizationNotAllowed' => 'Организация не разрешена.',

View File

@@ -172,10 +172,12 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Class:User/Attribute:status/Value:disabled' => 'Disabled~~',
'Class:User/Error:LoginMustBeUnique' => 'Prihlasovacie meno musí byť jedinečné - "%1s" sa už používa.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Aspoň jeden profil musí byť priradený k profilu.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Profile "%1$s" cannot be added it will deny the access to backoffice~~',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Changing status is not allowed for your own User~~',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Allowed organizations must contain User organization~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'The current list of profiles does not give sufficient access rights (Users are not modifiable anymore)~~',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'You cannot remove your own rights to edit Users~~',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)~~',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'At least one organization must be assigned to this user.~~',
'Class:User/Error:OrganizationNotAllowed' => 'Organization not allowed.~~',

View File

@@ -168,10 +168,12 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Class:User/Attribute:status/Value:disabled' => 'Disabled~~',
'Class:User/Error:LoginMustBeUnique' => 'Kullanıcı adı tekil olmalı - "%1s" mevcut bir kullanıcıya ait.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => 'En az bir profil kullanıcıya atanmalı',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => 'Profile "%1$s" cannot be added it will deny the access to backoffice~~',
'Class:User/Error:StatusChangeIsNotAllowed' => 'Changing status is not allowed for your own User~~',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Allowed organizations must contain User organization~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'The current list of profiles does not give sufficient access rights (Users are not modifiable anymore)~~',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'You cannot remove your own rights to edit Users~~',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)~~',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'At least one organization must be assigned to this user.~~',
'Class:User/Error:OrganizationNotAllowed' => 'Organization not allowed.~~',

View File

@@ -170,9 +170,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:User/Attribute:status/Value:disabled' => '停用',
'Class:User/Error:LoginMustBeUnique' => '登录名必须唯一 - "%1s" 已经被使用.',
'Class:User/Error:AtLeastOneProfileIsNeeded' => '必须指定至少一个角色给此用户.',
'Class:User/Error:PrivilegedUserMustHaveAccessToBackOffice' => 'Profile "%1$s" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)~~',
'Class:User/Error:ProfileNotAllowed' => '无法添加角色 "%1$s" 因为这将导致禁止访问后台',
'Class:User/Error:StatusChangeIsNotAllowed' => '不允许更改您自己用户的状态',
'Class:User/Error:AllowedOrgsMustContainUserOrg' => '允许访问组织必须包含用户组织',
'Class:User/Error:AdminProfileCannotBeRemovedBySelf' => 'You cannot remove your own Administrator profile. Ask another Administrator to do it for you~~',
'Class:User/Error:CurrentProfilesHaveInsufficientRights' => '当前指定的角色列表没有提供足够的访问权限 (用户将无法被修改)',
'Class:User/Error:PortalPowerUserHasInsufficientRights' => 'The Portal power user profile does not give sufficient access rights (another profile must be added)~~',
'Class:User/Error:AtLeastOneOrganizationIsNeeded' => '必须为此用户指定一个组织.',

View File

@@ -650,6 +650,31 @@ abstract class ItopDataTestCase extends ItopTestCase
return $oUser;
}
/**
* @param \DBObject $oUser
* @param int $iProfileId
*
* @return \DBObject
* @throws Exception
*/
protected function RemoveProfileFromUser($oUser, $iProfileId)
{
/** @var \ormLinkSet $oSet */
$oSet = $oUser->Get('profile_list');
foreach ($oSet as $oUserProfile)
{
if ($oUserProfile->Get('profileid') == $iProfileId)
{
$oSet->RemoveItem($oUserProfile->GetKey());
break;
}
}
$oUser = $this->updateObject(User::class, $oUser->GetKey(), array(
'profile_list' => $oSet,
));
return $oUser;
}
/**
* Create a Hypervisor in database
*

View File

@@ -35,6 +35,7 @@ use DBObjectSearch;
use DBObjectSet;
use DeleteException;
use MetaModel;
use UserLocal;
use UserRights;
use utils;
@@ -80,6 +81,21 @@ class UserRightsTest extends ItopDataTestCase
return $oUser;
}
protected function GivenUserWithProfiles(string $sLogin, array $aProfileIds): DBObject
{
$oProfiles = new \ormLinkSet(\UserLocal::class, 'profile_list', \DBObjectSet::FromScratch(\URP_UserProfile::class));
foreach ($aProfileIds as $iProfileId) {
$oProfiles->AddItem(MetaModel::NewObject('URP_UserProfile', ['profileid' => $iProfileId, 'reason' => 'UNIT Tests']));
}
$oUser = MetaModel::NewObject('UserLocal', array(
'login' => $sLogin,
'password' => 'Password1!',
'expiration' => UserLocal::EXPIRE_NEVER,
'profile_list' => $oProfiles,
));
return $oUser;
}
public function testIsLoggedIn()
{
$this->assertFalse(UserRights::IsLoggedIn());
@@ -279,87 +295,79 @@ class UserRightsTest extends ItopDataTestCase
}
/**
* @dataProvider ProfileDenyingConsoleProvider
* @doesNotPerformAssertions
* @dataProvider UserCannotLoseConsoleAccessProvider
*
* @throws \CoreException
* @throws \DictExceptionUnknownLanguage
* @throws \OQLException
*/
public function testProfileDenyingConsole(int $iProfileId)
public function testUserCannotLoseConsoleAccess(int $iProfileId)
{
$oUser = $this->CreateUniqueUserAndLogin('test1', $iProfileId);
try {
$this->expectException(CoreCannotSaveObjectException::class);
$this->expectExceptionMessage('Profile "Portal user" cannot be added it will deny the access to backoffice');
$this->AddProfileToUser($oUser, 2);
$this->fail('Profile should not be added');
} catch (CoreCannotSaveObjectException $e) {
}
}
public function ProfileDenyingConsoleProvider(): array
public function UserCannotLoseConsoleAccessProvider(): array
{
return [
'Administrator' => [1],
'SuperUser' => [117],
];
}
/**
* @dataProvider ProfileCannotModifySelfProvider
* @doesNotPerformAssertions
* @dataProvider UserCannotElevateTheirOwnRightsProvider
*
* @throws \CoreException
* @throws \DictExceptionUnknownLanguage
* @throws \OQLException
*/
public function testProfileCannotModifySelf(int $iProfileId)
public function testUserCannotElevateTheirOwnRights(int $iCurrentProfileId, int $iElevatedProfileId)
{
$oUser = $this->CreateUniqueUserAndLogin('test1', $iProfileId);
$oUser = $this->CreateUniqueUserAndLogin('test1', $iCurrentProfileId);
try {
$this->AddProfileToUser($oUser, 1); // trying to become an admin
$this->fail('User should not modify self');
} catch (CoreException $e) {
}
$this->expectException(CoreCannotSaveObjectException::class);
$this->AddProfileToUser($oUser, $iElevatedProfileId);
}
public function ProfileCannotModifySelfProvider(): array
public function UserCannotElevateTheirOwnRightsProvider(): array
{
return [
'Configuration manager' => [3],
'Configuration manager to SuperUser' => ['current'=> 3, 'added' => 117],
'Configuration manager to Administrator' => ['current'=> 3, 'added' => 1],
'SuperUser to Administrator' => ['current'=> 117, 'added' => 1],
];
}
/**
* @dataProvider DeletingSelfUserProvider
* @doesNotPerformAssertions
* @dataProvider UserCannotDeleteOwnUserProvider
*
* @throws \CoreException
* @throws \DictExceptionUnknownLanguage
* @throws \OQLException
*/
public function testDeletingSelfUser(int $iProfileId)
public function testUserCannotDeleteOwnUser(int $iProfileId)
{
$oUser = $this->CreateUniqueUserAndLogin('test1', $iProfileId);
try {
$this->expectException(DeleteException::class);
$oUser->DBDelete();
$this->fail('Current User cannot be deleted');
} catch (DeleteException $e) {
}
}
public function DeletingSelfUserProvider(): array
public function UserCannotDeleteOwnUserProvider(): array
{
return [
'Administrator' => [1],
'Configuration manager' => [3],
'SuperUser' => [117],
];
}
/**
* @dataProvider RemovingOwnContactProvider
* @doesNotPerformAssertions
* @dataProvider UserCannotRemoveOwnContactProvider
*
* @param int $iProfileId
*
@@ -367,68 +375,84 @@ class UserRightsTest extends ItopDataTestCase
* @throws \DictExceptionUnknownLanguage
* @throws \OQLException
*/
public function testRemovingOwnContact(int $iProfileId)
public function testUserCannotRemoveOwnContact(int $iProfileId)
{
$oUser = $this->CreateUniqueUserAndLogin('test1', $iProfileId);
$oUser->Set('contactid', 0);
try {
$this->expectException(CoreCannotSaveObjectException::class);
$oUser->DBWrite();
$this->fail('Current User cannot remove his own contact');
} catch (CoreCannotSaveObjectException $e) {
}
}
public function RemovingOwnContactProvider(): array
public function UserCannotRemoveOwnContactProvider(): array
{
return [
'Administrator' => [1],
'Configuration manager' => [3],
'SuperUser' => [117],
];
}
public function testAdminCannotRemoveOwnAdminProfile()
{
$oUser = $this->CreateUniqueUserAndLogin('admin111', 1); // Administrator
// Keep only the SuperUser profile (remove Administrator profile)
$this->AddProfileToUser($oUser, 117); // SuperUser profile for the test
$this->expectException(CoreCannotSaveObjectException::class);
$this->expectExceptionMessage('You cannot remove your own Administrator profile. Ask another Administrator to do it for you');
$this->RemoveProfileFromUser($oUser, 1); // Remove admin profile
}
/**
* @dataProvider UserCannotLoseUserEditionRightsProvider
*/
public function testUserCannotLoseUserEditionRights(int $iProfileId)
{
$oUser = $this->CreateUniqueUserAndLogin('configmgr111', $iProfileId); // SuperUser
$this->AddProfileToUser($oUser, 3);
$this->expectException(CoreCannotSaveObjectException::class);
$this->expectExceptionMessage('You cannot remove your own rights to edit Users');
$this->RemoveProfileFromUser($oUser, $iProfileId);
}
public function UserCannotLoseUserEditionRightsProvider(): array
{
return [
'Administrator' => [1],
'SuperUser' => [117],
];
}
/**
* @doesNotPerformAssertions
*
* @throws \CoreException
* @throws \DictExceptionUnknownLanguage
* @throws \OQLException
* @dataProvider PrivilegedUsersMustHaveBackofficeAccessProvider
*/
public function testUpgradingToAdmin()
public function testPrivilegedUsersMustHaveBackofficeAccess(int $iProfileId)
{
$oUser = $this->CreateUniqueUserAndLogin('test1', 3);
$oUser = $this->GivenUserWithProfiles('test1', [$iProfileId, 2]);
try {
$this->AddProfileToUser($oUser, 1);
$this->fail('Should not be able to upgrade to Administrator');
} catch (CoreCannotSaveObjectException $e) {
} catch (CoreException $e) {
}
}
$this->expectException(CoreCannotSaveObjectException::class);
$this->expectExceptionMessage('Profile "Portal user" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)');
$oUser->DBInsert();
/**
* @doesNotPerformAssertions
*
* @throws \CoreException
* @throws \DictExceptionUnknownLanguage
* @throws \OQLException
*/
public function testDenyingUserModification()
}
public function PrivilegedUsersMustHaveBackofficeAccessProvider(): array
{
$oUser = $this->CreateUniqueUserAndLogin('test1', 1);
$this->AddProfileToUser($oUser, 3);
return [
'killing another administrator' => [1],
'killing superuser ' => [117],
'killing Rest User' => [1024],
// Keep only the profile 3 (remove profile 1)
$oSet = new \ormLinkSet(\UserLocal::class, 'profile_list', \DBObjectSet::FromScratch(\URP_UserProfile::class));
$oSet->AddItem(MetaModel::NewObject('URP_UserProfile', ['profileid' => 3, 'reason' => 'UNIT Tests']));
$oUser->Set('profile_list', $oSet);
try {
$oUser->DBWrite();
$this->fail('Should not be able to deny User modifications');
} catch (CoreCannotSaveObjectException $e) {
];
}
public function testNonPrivilegedUsersCanBeDeniedFromBackoffice()
{
$oUser = $this->GivenUserWithProfiles('test1', [5, 2]);
// No exception expected
$oUser->DBInsert();
$this->expectNotToPerformAssertions();
}
/**
@@ -471,18 +495,18 @@ class UserRightsTest extends ItopDataTestCase
$oSearch = new DBObjectSearch('URP_UserProfile');
$oSearch->AddCondition('userid', $oUserAdmin->GetKey());
$oSet = new DBObjectSet($oSearch);
$this->assertEquals($iExpectedCount, $oSet->Count());
$this->assertEquals($iExpectedCount, $oSet->Count(), 'Visibility on Link between User and Administrator Profiles should be controlled by hide_administrators setting');
// Get the Profiles as well
$oSearch = DBObjectSearch::FromOQL('SELECT URP_Profiles JOIN URP_UserProfile ON URP_UserProfile.profileid = URP_Profiles.id WHERE URP_UserProfile.userid='.$oUserAdmin->GetKey());
$oSet = new DBObjectSet($oSearch);
$this->assertEquals($iExpectedCount, $oSet->Count());
$this->assertEquals($iExpectedCount, $oSet->Count(), 'Visibility on Administrator Profiles should be controlled by hide_administrators setting');
}
public function NonAdminCannotListAdminProfilesProvider(): array
{
return [
'with Admins visible' => [false, 1],
'with Admins hidden' => [true, 0],
'with Admins visible' => ['hide_administrators' => false, 'visible_objects' => 1],
'with Admins hidden' => ['hide_administrators' => true, 'visible_objects' => 0],
];
}