diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 4176e4b53..bee8d1f05 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -9,7 +9,7 @@ Any PRs not following the guidelines or with missing information will not be con ## Base information | Question | Answer |---------------------------------------------------------------|-------- -| Related to a SourceForge thead / Another PR / Combodo ticket? | +| Related to a SourceForge thread / Another PR / Combodo ticket? | | Type of change? | Bug fix / Enhancement / Translations diff --git a/addons/userrights/userrightsprofile.class.inc.php b/addons/userrights/userrightsprofile.class.inc.php index d2560bbe8..5952ece3e 100644 --- a/addons/userrights/userrightsprofile.class.inc.php +++ b/addons/userrights/userrightsprofile.class.inc.php @@ -536,6 +536,7 @@ class UserRightsProfile extends UserRightsAddOnAPI // Cache $this->m_aObjectActionGrants = []; $this->m_aAdministrators = null; + $this->aUsersProfilesList = []; } public function LoadCache() diff --git a/application/audit.category.class.inc.php b/application/audit.category.class.inc.php index d5549b8f8..ef02210cb 100644 --- a/application/audit.category.class.inc.php +++ b/application/audit.category.class.inc.php @@ -48,7 +48,7 @@ class AuditCategory extends cmdbAbstractObject MetaModel::Init_AddAttribute(new AttributeString("name", ["description" => "Short name for this category", "allowed_values" => null, "sql" => "name", "default_value" => "", "is_null_allowed" => false, "depends_on" => []])); MetaModel::Init_AddAttribute(new AttributeString("description", ["allowed_values" => null, "sql" => "description", "default_value" => "", "is_null_allowed" => true, "depends_on" => []])); MetaModel::Init_AddAttribute(new AttributeOQL("definition_set", ["allowed_values" => null, "sql" => "definition_set", "default_value" => "", "is_null_allowed" => false, "depends_on" => []])); - MetaModel::Init_AddAttribute(new AttributeLinkedSet("rules_list", ["linked_class" => "AuditRule", "ext_key_to_me" => "category_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => [], "edit_mode" => LINKSET_EDITMODE_INPLACE, "tracking_level" => LINKSET_TRACKING_ALL])); + MetaModel::Init_AddAttribute(new AttributeLinkedSet("rules_list", ["linked_class" => "AuditRule", "ext_key_to_me" => "category_id", "allowed_values" => null, "count_min" => 0, "count_max" => 0, "depends_on" => [], "edit_mode" => LINKSET_EDITMODE_INPLACE, "edit_when" => LINKSET_EDITWHEN_ALWAYS, "tracking_level" => LINKSET_TRACKING_ALL])); MetaModel::Init_AddAttribute(new AttributeInteger("ok_error_tolerance", ["allowed_values" => null, "sql" => "ok_error_tolerance", "default_value" => 5, "is_null_allowed" => true, "depends_on" => []])); MetaModel::Init_AddAttribute(new AttributeInteger("warning_error_tolerance", ["allowed_values" => null, "sql" => "warning_error_tolerance", "default_value" => 25, "is_null_allowed" => true, "depends_on" => []])); MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect( diff --git a/application/audit.rule.class.inc.php b/application/audit.rule.class.inc.php index 2da2e28ef..e442a1953 100644 --- a/application/audit.rule.class.inc.php +++ b/application/audit.rule.class.inc.php @@ -52,13 +52,14 @@ class AuditRule extends cmdbAbstractObject MetaModel::Init_AddAttribute(new AttributeEnum("valid_flag", ["allowed_values" => new ValueSetEnum('true,false'), "sql" => "valid_flag", "default_value" => "true", "is_null_allowed" => false, "depends_on" => []])); MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", ["allowed_values" => null, "sql" => "category_id", "targetclass" => "AuditCategory", "is_null_allowed" => false, "on_target_delete" => DEL_MANUAL, "depends_on" => []])); MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", ["allowed_values" => null, "extkey_attcode" => 'category_id', "target_attcode" => "name"])); - + MetaModel::Init_AddAttribute(new AttributeExternalKey("contact_id", ["allowed_values" => null, "sql" => "contact_id", "targetclass" => "Contact", "is_null_allowed" => true, "on_target_delete" => DEL_MANUAL, "depends_on" => []])); + MetaModel::Init_AddAttribute(new AttributeHTML("process", ["allowed_values" => null, "sql" => "process", "default_value" => "", "is_null_allowed" => true, "depends_on" => []])); // Display lists - MetaModel::Init_SetZListItems('details', ['category_id', 'name', 'description', 'query', 'valid_flag']); // Attributes to be displayed for the complete details - MetaModel::Init_SetZListItems('list', ['category_id', 'description', 'valid_flag']); // Attributes to be displayed for a list + MetaModel::Init_SetZListItems('details', ['category_id', 'name', 'description', 'query', 'valid_flag', 'process', 'contact_id']); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', ['category_id', 'description', 'query']); // Attributes to be displayed for a list // Search criteria MetaModel::Init_SetZListItems('standard_search', ['category_id', 'name', 'description', 'valid_flag', 'query']); // Criteria of the std search form - MetaModel::Init_SetZListItems('default_search', ['name', 'description', 'category_id']); // Criteria of the advanced search form + MetaModel::Init_SetZListItems('default_search', ['name', 'description', 'category_id', 'contact_id', 'query']); // Criteria of the advanced search form } public static function GetShortcutActions($sFinalClass) diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index 223703024..aa139d892 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -2000,13 +2000,13 @@ class MenuBlock extends DisplayBlock $this->AddMenuSeparator($aRegularActions); foreach ($aRelations as $sRelationCode => $aRelationInfo) { if (array_key_exists('down', $aRelationInfo)) { - $aRegularActions[$sRelationCode.'_down'] = [ + $aRegularActions['UI:Menu:'.$sRelationCode.'_down'] = [ 'label' => $aRelationInfo['down'], 'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=down&class=$sClass&id=$id{$sContext}", ] + $aActionParams; } if (array_key_exists('up', $aRelationInfo)) { - $aRegularActions[$sRelationCode.'_up'] = [ + $aRegularActions['UI:Menu:'.$sRelationCode.'_up'] = [ 'label' => $aRelationInfo['up'], 'url' => "{$sRootUrl}pages/$sUIPage?operation=view_relations&relation=$sRelationCode&direction=up&class=$sClass&id=$id{$sContext}", ] + $aActionParams; @@ -2251,6 +2251,16 @@ class MenuBlock extends DisplayBlock $sIconClass = 'fas fa-file-pdf fa-lg'; $sLabel = ''; break; + case 'UI:Menu:impacts_up': + $sIconClass = 'fas fa-sitemap fa-rotate-180'; + $sLabel = ''; + $aAction['tooltip'] = Dict::S('Relation:impacts/UpStream'); + break; + case 'UI:Menu:impacts_down': + $sIconClass = 'fas fa-sitemap'; + $sLabel = ''; + $aAction['tooltip'] = Dict::S('Relation:impacts/DownStream'); + break; default: if (isset($aAction['icon_class']) && (strlen($aAction['icon_class']) > 0)) { diff --git a/application/exceptions/oql/CoreOqlException.php b/application/exceptions/oql/CoreOqlException.php index c9cbdf2e0..c59b50d37 100644 --- a/application/exceptions/oql/CoreOqlException.php +++ b/application/exceptions/oql/CoreOqlException.php @@ -1,4 +1,5 @@ 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,19 @@ 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 +648,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; + } } /** diff --git a/dictionaries/cs.dictionary.itop.ui.php b/dictionaries/cs.dictionary.itop.ui.php index c9336120c..ba5d234df 100755 --- a/dictionaries/cs.dictionary.itop.ui.php +++ b/dictionaries/cs.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [ 'Class:AuditRule/Attribute:name+' => 'Krátký název pro toto pravidlo', 'Class:AuditRule/Attribute:description' => 'Popis pravidla', 'Class:AuditRule/Attribute:description+' => 'Dlouhý popis tohoto pravidla auditu', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Dotaz ke spuštění', 'Class:AuditRule/Attribute:query+' => 'OQL výraz ke spuštění', 'Class:AuditRule/Attribute:valid_flag' => 'Interpretace', @@ -52,7 +54,9 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [ 'Class:AuditRule/Attribute:category_id+' => 'Kategorie pro toto pravidlo', 'Class:AuditRule/Attribute:category_name' => 'Kategorie', 'Class:AuditRule/Attribute:category_name+' => 'Název kategorie pro toto pravidlo', -]); + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', + ]); // // Class: AuditDomain @@ -164,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.', diff --git a/dictionaries/da.dictionary.itop.ui.php b/dictionaries/da.dictionary.itop.ui.php index 9211abedf..9821f83a6 100644 --- a/dictionaries/da.dictionary.itop.ui.php +++ b/dictionaries/da.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [ 'Class:AuditRule/Attribute:name+' => 'Kort navn for denne regel', 'Class:AuditRule/Attribute:description' => 'Audit-regel beskrivelse', 'Class:AuditRule/Attribute:description+' => 'Udførlig beskrivelse af denne Audit-regel', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Søgning at udføre', 'Class:AuditRule/Attribute:query+' => 'Den OQL forespørgsel, der skal udføres', 'Class:AuditRule/Attribute:valid_flag' => 'Gyldige objekter?', @@ -52,6 +54,8 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [ 'Class:AuditRule/Attribute:category_id+' => 'Kategori for denne regel', 'Class:AuditRule/Attribute:category_name' => 'Kategori', 'Class:AuditRule/Attribute:category_name+' => 'Kategorinavn for denne regel', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -164,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.~~', diff --git a/dictionaries/de.dictionary.itop.ui.php b/dictionaries/de.dictionary.itop.ui.php index bbff18973..041837829 100644 --- a/dictionaries/de.dictionary.itop.ui.php +++ b/dictionaries/de.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', [ 'Class:AuditRule/Attribute:name+' => 'Kurzname für diese Regel', 'Class:AuditRule/Attribute:description' => 'Beschreibung der Audit-Regel', 'Class:AuditRule/Attribute:description+' => 'Ausführliche Beschreibung dieser Audit-Regel', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Durchzuführende Abfrage', 'Class:AuditRule/Attribute:query+' => 'Die auszuführende OQL-Abfrage', 'Class:AuditRule/Attribute:valid_flag' => 'Gültiges Objekt?', @@ -52,6 +54,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', [ 'Class:AuditRule/Attribute:category_id+' => 'Kategorie für diese Regel', 'Class:AuditRule/Attribute:category_name' => 'Kategorie', 'Class:AuditRule/Attribute:category_name+' => 'Kategoriename für diese Regel', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -163,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.', diff --git a/dictionaries/en.dictionary.itop.ui.php b/dictionaries/en.dictionary.itop.ui.php index ead392ba0..690fd57d2 100644 --- a/dictionaries/en.dictionary.itop.ui.php +++ b/dictionaries/en.dictionary.itop.ui.php @@ -50,7 +50,9 @@ It is applied on the scope of objects defined by the audit category', 'Class:AuditRule/Attribute:name' => 'Rule name', 'Class:AuditRule/Attribute:name+' => 'Short name for this rule', 'Class:AuditRule/Attribute:description' => 'Description', - 'Class:AuditRule/Attribute:description+' => 'What is checked? How should it be fixed? Who should do it? ...', + 'Class:AuditRule/Attribute:description+' => 'What is checked?', + 'Class:AuditRule/Attribute:process' => 'Correction process', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...', 'Class:AuditRule/Attribute:query' => 'Query to run', 'Class:AuditRule/Attribute:query+' => 'The OQL expression to run. Returned classes must be aligned with those of the category\'s scope', 'Class:AuditRule/Attribute:valid_flag' => 'Returned objects: ', @@ -65,6 +67,8 @@ It is applied on the scope of objects defined by the audit category', 'Class:AuditRule/Attribute:category_id+' => 'The category of this rule', 'Class:AuditRule/Attribute:category_name' => 'Category name', 'Class:AuditRule/Attribute:category_name+' => 'Name of the category of this rule', + 'Class:AuditRule/Attribute:contact_id' => 'Owner', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule', ]); // @@ -173,15 +177,17 @@ Dict::Add('EN US', 'English', 'English', [ 'Class:User/Attribute:allowed_org_list+' => 'The end user is allowed to see data belonging to the following organizations. If no organization is specified, there is no restriction.', 'Class:User/Attribute:status' => 'Status', 'Class:User/Attribute:status+' => 'Whether the user account is enabled or disabled.', - 'Class:User/Attribute:status/Value:enabled' => 'Enabled', + 'Class:User/Attribute:status/Value:enabled' => 'Enabled', 'Class:User/Attribute:status/Value:disabled' => 'Disabled', '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.', diff --git a/dictionaries/en_gb.dictionary.itop.ui.php b/dictionaries/en_gb.dictionary.itop.ui.php index 073f04e7d..c54e33c0b 100644 --- a/dictionaries/en_gb.dictionary.itop.ui.php +++ b/dictionaries/en_gb.dictionary.itop.ui.php @@ -50,7 +50,9 @@ It is applied on the scope of objects defined by the audit category', 'Class:AuditRule/Attribute:name' => 'Rule name', 'Class:AuditRule/Attribute:name+' => 'Short name for this rule', 'Class:AuditRule/Attribute:description' => 'Description', - 'Class:AuditRule/Attribute:description+' => 'What is checked? How should it be fixed? Who should do it? ...', + 'Class:AuditRule/Attribute:description+' => 'What is checked?~~', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Query to run', 'Class:AuditRule/Attribute:query+' => 'The OQL expression to run. Returned classes must be aligned with those of the category\'s scope', 'Class:AuditRule/Attribute:valid_flag' => 'Returned objects: ', @@ -65,6 +67,8 @@ It is applied on the scope of objects defined by the audit category', 'Class:AuditRule/Attribute:category_id+' => 'The category of this rule', 'Class:AuditRule/Attribute:category_name' => 'Category name', 'Class:AuditRule/Attribute:category_name+' => 'Name of the category of this rule', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -178,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.', diff --git a/dictionaries/es_cr.dictionary.itop.ui.php b/dictionaries/es_cr.dictionary.itop.ui.php index 616e26988..032df260f 100644 --- a/dictionaries/es_cr.dictionary.itop.ui.php +++ b/dictionaries/es_cr.dictionary.itop.ui.php @@ -38,6 +38,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [ 'Class:AuditRule/Attribute:name+' => 'Nombre corto para esta regla', 'Class:AuditRule/Attribute:description' => 'Descripción de regla de auditoría', 'Class:AuditRule/Attribute:description+' => 'Descripción larga para esta regla de auditoría', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Consulta a Ejecutar', 'Class:AuditRule/Attribute:query+' => 'Expresión OQL a ejecutar', 'Class:AuditRule/Attribute:valid_flag' => '¿Objetos Válidos?', @@ -50,6 +52,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [ 'Class:AuditRule/Attribute:category_id+' => 'La categoría para esta regla', 'Class:AuditRule/Attribute:category_name' => 'Categoría', 'Class:AuditRule/Attribute:category_name+' => 'Nombre de la categoría para esta regla', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -162,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.', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index 5065fb5ef..1cde8e66d 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -41,7 +41,9 @@ Elle s\'applique à tous les objets dans le périmètre de sa catégorie d\'audi 'Class:AuditRule/Attribute:name' => 'Nom', 'Class:AuditRule/Attribute:name+' => 'Une vérification particulière', 'Class:AuditRule/Attribute:description' => 'Description', - 'Class:AuditRule/Attribute:description+' => 'Qu\'est ce qu\'on vérifie ? Comment le corriger ? Qui doit le faire ? ...', + 'Class:AuditRule/Attribute:description+' => 'Qu\'est ce qu\'on vérifie ?', + 'Class:AuditRule/Attribute:process' => 'Processus de correction', + 'Class:AuditRule/Attribute:process+' => 'Comment le corriger ? Qui doit le faire ? ...', 'Class:AuditRule/Attribute:query' => 'Requête', 'Class:AuditRule/Attribute:query+' => 'Requête OQL à executer. Les classes retournées doivent être cohérentes avec celles définies dans le périmètre de la catégorie', 'Class:AuditRule/Attribute:valid_flag' => 'Objets retournés :', @@ -56,6 +58,8 @@ Elle s\'applique à tous les objets dans le périmètre de sa catégorie d\'audi 'Class:AuditRule/Attribute:category_id+' => '', 'Class:AuditRule/Attribute:category_name' => 'Nom de la catégorie', 'Class:AuditRule/Attribute:category_name+' => '', + 'Class:AuditRule/Attribute:contact_id' => 'Responsable', + 'Class:AuditRule/Attribute:contact_id+' => 'Personne ou équipe responsable de la correction des erreurs détectées par cette règle', ]); // @@ -164,15 +168,17 @@ Dict::Add('FR FR', 'French', 'Français', [ 'Class:User/Attribute:allowed_org_list' => 'Organisations permises', 'Class:User/Attribute:allowed_org_list+' => 'L\'utilisateur a le droit de voir les données des organisations listées ici. Si aucune organisation n\'est spécifiée, alors aucune restriction ne s\'applique.', 'Class:User/Attribute:status' => 'Etat', - 'Class:User/Attribute:status+' => 'Est-ce que ce compte utilisateur est actif, ou non?', + 'Class:User/Attribute:status+' => 'Est-ce que ce compte utilisateur est actif, ou non ?', 'Class:User/Attribute:status/Value:enabled' => 'Actif', '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.', diff --git a/dictionaries/hu.dictionary.itop.ui.php b/dictionaries/hu.dictionary.itop.ui.php index 8e18eefab..0425e600f 100755 --- a/dictionaries/hu.dictionary.itop.ui.php +++ b/dictionaries/hu.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [ 'Class:AuditRule/Attribute:name+' => '', 'Class:AuditRule/Attribute:description' => 'Leírás', 'Class:AuditRule/Attribute:description+' => '', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Lekérdezés', 'Class:AuditRule/Attribute:query+' => '', 'Class:AuditRule/Attribute:valid_flag' => 'Érvényes objektum?', @@ -52,6 +54,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [ 'Class:AuditRule/Attribute:category_id+' => '', 'Class:AuditRule/Attribute:category_name' => 'Kategórianév', 'Class:AuditRule/Attribute:category_name+' => '', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -164,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', diff --git a/dictionaries/it.dictionary.itop.ui.php b/dictionaries/it.dictionary.itop.ui.php index ece2d2103..075e089e8 100644 --- a/dictionaries/it.dictionary.itop.ui.php +++ b/dictionaries/it.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [ 'Class:AuditRule/Attribute:name+' => '', 'Class:AuditRule/Attribute:description' => 'Descrizione della regola di Audit', 'Class:AuditRule/Attribute:description+' => 'Descrizione dettagliata per questa regola di audit ', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Query da eseguire', 'Class:AuditRule/Attribute:query+' => 'Espressio OQL da eseguire', 'Class:AuditRule/Attribute:valid_flag' => 'Oggetti validi?', @@ -52,6 +54,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [ 'Class:AuditRule/Attribute:category_id+' => 'Categoria per questa regola', 'Class:AuditRule/Attribute:category_name' => 'Categoria', 'Class:AuditRule/Attribute:category_name+' => 'Nome della categoria per questa regola', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -164,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.', diff --git a/dictionaries/ja.dictionary.itop.ui.php b/dictionaries/ja.dictionary.itop.ui.php index 70505084b..90ed99b52 100644 --- a/dictionaries/ja.dictionary.itop.ui.php +++ b/dictionaries/ja.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', [ 'Class:AuditRule/Attribute:name+' => 'ルールの短縮名', 'Class:AuditRule/Attribute:description' => '監査ルール説明', 'Class:AuditRule/Attribute:description+' => 'この監査ルールの長い説明', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => '実行するクエリ', 'Class:AuditRule/Attribute:query+' => '実行するOQL式', 'Class:AuditRule/Attribute:valid_flag' => '有効なオブジェクト', @@ -52,6 +54,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', [ 'Class:AuditRule/Attribute:category_id+' => 'このルールのカテゴリ', 'Class:AuditRule/Attribute:category_name' => 'カテゴリ', 'Class:AuditRule/Attribute:category_name+' => 'このルールのカテゴリ名', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -164,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.~~', diff --git a/dictionaries/nl.dictionary.itop.ui.php b/dictionaries/nl.dictionary.itop.ui.php index 5c5856c47..14496f6a6 100644 --- a/dictionaries/nl.dictionary.itop.ui.php +++ b/dictionaries/nl.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [ 'Class:AuditRule/Attribute:name+' => 'Naam van de regel', 'Class:AuditRule/Attribute:description' => 'Beschrijving', 'Class:AuditRule/Attribute:description+' => 'Uitgebreide beschrijving van deze Auditregel', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Query om uit te voeren', 'Class:AuditRule/Attribute:query+' => 'De OQL-expressie voor het uitvoeren', 'Class:AuditRule/Attribute:valid_flag' => 'Geldige objecten?', @@ -52,6 +54,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [ 'Class:AuditRule/Attribute:category_id+' => 'De categorie voor deze regel', 'Class:AuditRule/Attribute:category_name' => 'Categorie', 'Class:AuditRule/Attribute:category_name+' => 'Naam van de categorie voor deze regel', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -164,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', diff --git a/dictionaries/pl.dictionary.itop.ui.php b/dictionaries/pl.dictionary.itop.ui.php index 4d484f87d..7d3490900 100644 --- a/dictionaries/pl.dictionary.itop.ui.php +++ b/dictionaries/pl.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('PL PL', 'Polish', 'Polski', [ 'Class:AuditRule/Attribute:name+' => 'Krótka nazwa reguły', 'Class:AuditRule/Attribute:description' => 'Opis reguły audytu', 'Class:AuditRule/Attribute:description+' => 'Długi opis reguły inspekcji', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Zapytanie do wykonania', 'Class:AuditRule/Attribute:query+' => 'Wyrażenie OQL do wykonania', 'Class:AuditRule/Attribute:valid_flag' => 'Prawidłowe obiekty?', @@ -52,6 +54,8 @@ Dict::Add('PL PL', 'Polish', 'Polski', [ 'Class:AuditRule/Attribute:category_id+' => 'Kategoria dla reguły', 'Class:AuditRule/Attribute:category_name' => 'Kategoria', 'Class:AuditRule/Attribute:category_name+' => 'Nazwa kategorii dla reguły', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -164,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.', diff --git a/dictionaries/pt_br.dictionary.itop.ui.php b/dictionaries/pt_br.dictionary.itop.ui.php index cfce7e213..5a7e30a96 100644 --- a/dictionaries/pt_br.dictionary.itop.ui.php +++ b/dictionaries/pt_br.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [ 'Class:AuditRule/Attribute:name+' => 'Nome curto para esta regra', 'Class:AuditRule/Attribute:description' => 'Descrição', 'Class:AuditRule/Attribute:description+' => 'Descrição longa para essa regra', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Executar consulta', 'Class:AuditRule/Attribute:query+' => 'Executar a expressão OQL', 'Class:AuditRule/Attribute:valid_flag' => 'Objetos válidos?', @@ -52,6 +54,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [ 'Class:AuditRule/Attribute:category_id+' => 'A categoria para esta regra', 'Class:AuditRule/Attribute:category_name' => 'Categoria', 'Class:AuditRule/Attribute:category_name+' => 'Nome da categoria para essa regra', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -164,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', diff --git a/dictionaries/ru.dictionary.itop.ui.php b/dictionaries/ru.dictionary.itop.ui.php index 4a2be25d5..4240845b0 100644 --- a/dictionaries/ru.dictionary.itop.ui.php +++ b/dictionaries/ru.dictionary.itop.ui.php @@ -41,6 +41,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', [ 'Class:AuditRule/Attribute:name+' => 'Краткое название этого правила', 'Class:AuditRule/Attribute:description' => 'Описание правила аудита', 'Class:AuditRule/Attribute:description+' => 'Полное описание этого правила аудита', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Запрос для выполнения', 'Class:AuditRule/Attribute:query+' => 'OQL выражение, выполняющее проверку набора объектов категории аудита', 'Class:AuditRule/Attribute:valid_flag' => 'Валидные объекты?', @@ -53,6 +55,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', [ 'Class:AuditRule/Attribute:category_id+' => 'Категория для этого правила', 'Class:AuditRule/Attribute:category_name' => 'Категория', 'Class:AuditRule/Attribute:category_name+' => 'Категория для этого правила', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -165,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' => 'Организация не разрешена.', diff --git a/dictionaries/sk.dictionary.itop.ui.php b/dictionaries/sk.dictionary.itop.ui.php index 9df9ac142..50d911df6 100644 --- a/dictionaries/sk.dictionary.itop.ui.php +++ b/dictionaries/sk.dictionary.itop.ui.php @@ -41,7 +41,9 @@ It is applied on the scope of objects defined by the audit category~~', 'Class:AuditRule/Attribute:name' => 'Názov pravidla', 'Class:AuditRule/Attribute:name+' => 'Short name for this rule~~', 'Class:AuditRule/Attribute:description' => 'Popis pravidla auditu', - 'Class:AuditRule/Attribute:description+' => 'What is checked? How should it be fixed? Who should do it? ...~~', + 'Class:AuditRule/Attribute:description+' => 'What is checked?~~', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Spustenie dopytu', 'Class:AuditRule/Attribute:query+' => 'The OQL expression to run. Returned classes must be aligned with those of the category\'s scope~~', 'Class:AuditRule/Attribute:valid_flag' => 'Platný objekt?', @@ -56,6 +58,8 @@ It is applied on the scope of objects defined by the audit category~~', 'Class:AuditRule/Attribute:category_id+' => 'The category of this rule~~', 'Class:AuditRule/Attribute:category_name' => 'Kategória', 'Class:AuditRule/Attribute:category_name+' => 'Name of the category of this rule~~', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -168,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.~~', diff --git a/dictionaries/tr.dictionary.itop.ui.php b/dictionaries/tr.dictionary.itop.ui.php index 51cdd89f9..b690896ae 100644 --- a/dictionaries/tr.dictionary.itop.ui.php +++ b/dictionaries/tr.dictionary.itop.ui.php @@ -40,6 +40,8 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [ 'Class:AuditRule/Attribute:name+' => 'Kural Adı', 'Class:AuditRule/Attribute:description' => 'Kural tanımlaması', 'Class:AuditRule/Attribute:description+' => 'Kural tanımlaması', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => 'Çalıştırılacak Sorgu', 'Class:AuditRule/Attribute:query+' => 'Çalıştırılcak OQL ifadesi', 'Class:AuditRule/Attribute:valid_flag' => 'Geçerli nesneler?', @@ -52,6 +54,8 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [ 'Class:AuditRule/Attribute:category_id+' => 'Kuralın kategorisi', 'Class:AuditRule/Attribute:category_name' => 'Kategori', 'Class:AuditRule/Attribute:category_name+' => 'Kural için kategori adı', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -164,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.~~', diff --git a/dictionaries/zh_cn.dictionary.itop.ui.php b/dictionaries/zh_cn.dictionary.itop.ui.php index 720f21be4..6c0e70726 100644 --- a/dictionaries/zh_cn.dictionary.itop.ui.php +++ b/dictionaries/zh_cn.dictionary.itop.ui.php @@ -42,6 +42,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [ 'Class:AuditRule/Attribute:name+' => '规则名称', 'Class:AuditRule/Attribute:description' => '描述', 'Class:AuditRule/Attribute:description+' => '检查什么? 如何修复? 谁去做? ...', + 'Class:AuditRule/Attribute:process' => 'Correction process~~', + 'Class:AuditRule/Attribute:process+' => 'How should it be fixed? Who should do it? ...~~', 'Class:AuditRule/Attribute:query' => '要运行的查询', 'Class:AuditRule/Attribute:query+' => '要运行的OQL表达式', 'Class:AuditRule/Attribute:valid_flag' => '是否有效?', @@ -54,6 +56,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [ 'Class:AuditRule/Attribute:category_id+' => '该规则对应的类别', 'Class:AuditRule/Attribute:category_name' => '类别', 'Class:AuditRule/Attribute:category_name+' => '该规则对应的类名称', + 'Class:AuditRule/Attribute:contact_id' => 'Owner~~', + 'Class:AuditRule/Attribute:contact_id+' => 'Team or person in charge of fixing the errors detected by this rule~~', ]); // @@ -166,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' => '必须为此用户指定一个组织.', diff --git a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php index dd5807084..af0e8fb89 100644 --- a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php +++ b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php @@ -650,6 +650,29 @@ 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(), [ + 'profile_list' => $oSet, + ]); + return $oUser; + } + /** * Create a Hypervisor in database * diff --git a/tests/php-unit-tests/unitary-tests/core/UserRightsTest.php b/tests/php-unit-tests/unitary-tests/core/UserRightsTest.php index cecdd4b7f..8bdabd4f4 100644 --- a/tests/php-unit-tests/unitary-tests/core/UserRightsTest.php +++ b/tests/php-unit-tests/unitary-tests/core/UserRightsTest.php @@ -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', [ + '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->AddProfileToUser($oUser, 2); - $this->fail('Profile should not be added'); - } catch (CoreCannotSaveObjectException $e) { - } + $this->expectException(CoreCannotSaveObjectException::class); + $this->expectExceptionMessage('Profile "Portal user" cannot be added it will deny the access to backoffice'); + $this->AddProfileToUser($oUser, 2); } - 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 { - $oUser->DBDelete(); - $this->fail('Current User cannot be deleted'); - } catch (DeleteException $e) { - } + $this->expectException(DeleteException::class); + $oUser->DBDelete(); } - 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,83 @@ 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 { - $oUser->DBWrite(); - $this->fail('Current User cannot remove his own contact'); - } catch (CoreCannotSaveObjectException $e) { - } + $this->expectException(CoreCannotSaveObjectException::class); + $oUser->DBWrite(); } - 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]); + + $this->expectException(CoreCannotSaveObjectException::class); + $this->expectExceptionMessage('Profile "Portal user" cannot be given to privileged Users (Administrators, SuperUsers and REST Services Users)'); + $oUser->DBInsert(); - try { - $this->AddProfileToUser($oUser, 1); - $this->fail('Should not be able to upgrade to Administrator'); - } catch (CoreCannotSaveObjectException $e) { - } catch (CoreException $e) { - } } - - /** - * @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 +494,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], ]; }