Sidebar

Using iTop

Creating your iTop

iTop Customization

"How to" examples
DataModel

User Interface

Automation & Ticket management

Portal Customization

:: Version 3.2.0 ::

Prevent User accidentally disabled

Prerequisite: You must be familiar with the Syntax used in Tutorials and have already created an extension.

learning:
Configure uniqueness rules
level:
Medium
domains:
PHP, Constrain, User
min version:
2.3.0

If you have a User with Allowed organizations defined, linked to a Person, it is mandatory that the Person's Organization is within the list of Allowed organizations if some are defined.

  • This check is not done by iTop out the box.
  • In iTop 3.0.0, the control was added to the User object creation/modification, and also on Person deletion
  • Nevertheless, there is still a corner case which is not protected, if you modify the organization of the Person to an Organization which is not in the list of the ''Allowed organizations“ of at least one of the associated User, in that case that User won't be able to connect to iTop anymore.

In this tutorial, you will learn how to add a protection against this unwanted situation. For this we will add/modify a few methods on the Person class:

DoCheckToWrite

You must overwrite this function

Person
public function DoCheckToWrite()
{
    if (array_key_exists('org_id',$this->ListChanges()) &&  ($this->HasUserAccount(true))) {
        // Do not let modify Person's organization if linked to active users with allowed organizations
        $iNewOrg = $this->Get('org_id');
        // Get the user org and all its parent organizations
        $aUserOrgs = [$iNewOrg];
        $sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization');
        if ($sHierarchicalKeyCode !== false) {
            $sOrgQuery = 'SELECT Org FROM Organization AS Org JOIN Organization AS Root ON Org.'
                         .$sHierarchicalKeyCode.' ABOVE Root.id WHERE Root.id = :id';
            $oOrgFilter = new DBObjectSearch::FromOQL_AllData($sOrgQuery);
            $oOrgFilter->AllowAllData(true);
            $oOrgSet = new DBObjectSet($oOrgFilter, [], ['id' => $iNewOrg]));
            while ($aRow = $oOrgSet->FetchAssoc()) {
                $oOrg = $aRow['Org'];
                $aUserOrgs[] = $oOrg->GetKey();
            }
        }
//CAUTIOUS: Copy the code of GetUsers() function here, if you don't create that function
        $oUserSet = $this->GetUsers(true);
 
        while($oUser = $oUserSet->Fetch())
        {
            if (!UserRights::IsAdministrator($oUser)) {
                // Allowed orgs must contains the user org (if any)
                $oSet = $oUser->get('allowed_org_list');
                if ($oSet->Count() > 0) {
                    $bFound = false;
                    while ($oOrg = $oSet->Fetch()) {
                        if (in_array($oOrg->Get('allowed_org_id'), $aUserOrgs)) {
                            $bFound = true;
                            break;
                        }
                    }
                    if (!$bFound) {
                        $this->m_aCheckErrors[] = $oUser->Get('login').": "
                                .Dict::S('Class:User/Error:AllowedOrgsMustContainUserOrg');
                    }
                }
            }
        }
    }
    return parent::DoCheckToWrite();
}

Helpers

You can create this Helper function (optional, otherwise insert this code within the above function)

Person
public function GetUsers($bActiveOnly=false)
{
    $sOQL = $bActiveOnly ? 'SELECT User WHERE contactid = :person' 
                : "SELECT User WHERE contactid = :person AND status='active'";
    $oFilter = DBSearch::FromOQL($sOQL, array('person' => $this->GetKey()));
    // As most users are not allowed to see objects of the class User, you need to explicitly allow it:
    $oFilter->AllowAllData(true); 
    $oUserSet = new DBObjectSet($oFilter);
    return $oUserSet;
}

You can redefine this function (optional, it's just to avoid code duplication)

Person
public function HasUserAccount($bActiveOnly=false)
{
    static $bHasUserAccount = null; // To avoid recomputing it multiple times
    if (is_null($bHasUserAccount)) {
        $bHasUserAccount = ($this->GetUsers(bActiveOnly)->Count() > 0);
    }
    return $bHasUserAccount;
}
3_2_0/customization/user-protection.txt · Last modified: 2024/06/20 17:28 (external edit)
Back to top
Contact us