mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-21 16:22:20 +02:00
Merge branch 'feature/5324-powerportaluser-repairprofiles' into saas/3.1.0
This commit is contained in:
@@ -41,19 +41,27 @@ class UserProfilesEventListener implements iEventServiceSetup
|
||||
return;
|
||||
}
|
||||
|
||||
$callback = [$this, 'OnUserProfileLinkChange'];
|
||||
$aEventSource = [\User::class, \UserExternal::class, \UserInternal::class];
|
||||
|
||||
EventService::RegisterListener(
|
||||
EVENT_DB_BEFORE_WRITE,
|
||||
$callback,
|
||||
[$this, 'OnUserEdition'],
|
||||
$aEventSource
|
||||
);
|
||||
|
||||
EventService::RegisterListener(
|
||||
EVENT_DB_LINKS_CHANGED,
|
||||
$callback,
|
||||
$aEventSource
|
||||
EVENT_DB_BEFORE_WRITE,
|
||||
[ $this, 'OnUserProfileEdition' ],
|
||||
[ \URP_UserProfile::class ],
|
||||
[],
|
||||
null
|
||||
);
|
||||
|
||||
EventService::RegisterListener(
|
||||
EVENT_DB_CHECK_TO_DELETE,
|
||||
[ $this, 'OnUserProfileLinkDeletion' ],
|
||||
[ \URP_UserProfile::class ],
|
||||
[],
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -62,12 +70,13 @@ class UserProfilesEventListener implements iEventServiceSetup
|
||||
return $this->bIsRepairmentEnabled;
|
||||
}
|
||||
|
||||
public function OnUserProfileLinkChange(EventData $oEventData): void {
|
||||
|
||||
public function OnUserEdition(EventData $oEventData): void {
|
||||
/** @var \User $oObject */
|
||||
$oUser = $oEventData->Get('object');
|
||||
|
||||
try {
|
||||
$this->RepairProfiles($oUser);
|
||||
$this->ValidateThenRepairOrWarn($oUser);
|
||||
} catch (Exception $e) {
|
||||
IssueLog::Error('Exception occurred on RepairProfiles', LogChannels::DM_CRUD, [
|
||||
'user_class' => get_class($oUser),
|
||||
@@ -75,9 +84,119 @@ class UserProfilesEventListener implements iEventServiceSetup
|
||||
'exception_message' => $e->getMessage(),
|
||||
'exception_stacktrace' => $e->getTraceAsString(),
|
||||
]);
|
||||
if ($e instanceof \CoreCannotSaveObjectException){
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function OnUserProfileEdition(EventData $oEventData): void {
|
||||
$oURP_UserProfile = $oEventData->Get('object');
|
||||
|
||||
try {
|
||||
$iUserId = $oURP_UserProfile->Get('userid');
|
||||
$oUser = \MetaModel::GetReentranceObjectByChildClass(\User::class, $iUserId);
|
||||
if (false !== $oUser){
|
||||
//user edition: handled by other event
|
||||
return;
|
||||
}
|
||||
|
||||
$oUser = \MetaModel::GetObject(\User::class, $iUserId);
|
||||
$aChanges = $oURP_UserProfile->ListChanges();
|
||||
if (array_key_exists('userid', $aChanges)) {
|
||||
$iUserId = $oURP_UserProfile->GetOriginal('userid');
|
||||
$oPreviousUser = \MetaModel::GetObject(\User::class, $iUserId);
|
||||
|
||||
$oProfileLinkSet = $oPreviousUser->Get('profile_list');
|
||||
$oProfileLinkSet->Rewind();
|
||||
$iCount = 0;
|
||||
while ($oCurrentURP_UserProfile = $oProfileLinkSet->Fetch()) {
|
||||
if ($oCurrentURP_UserProfile->Get('userid') !== $oCurrentURP_UserProfile->GetOriginal('userid')) {
|
||||
$sRemovedProfileId = $oCurrentURP_UserProfile->GetOriginal('profileid');
|
||||
continue;
|
||||
}
|
||||
|
||||
$iCount++;
|
||||
if ($iCount > 1){
|
||||
//more than one profile: no repairment needed
|
||||
return;
|
||||
}
|
||||
$sSingleProfileName = $oCurrentURP_UserProfile->Get('profile');
|
||||
}
|
||||
$this->RepairProfileChangesOrWarn($oPreviousUser, $sSingleProfileName, $oURP_UserProfile, $sRemovedProfileId);
|
||||
} else if (array_key_exists('profileid', $aChanges)){
|
||||
$oCurrentUserProfileSet = $oUser->Get('profile_list');
|
||||
if ($oCurrentUserProfileSet->Count() === 1){
|
||||
$oProfile = $oCurrentUserProfileSet->Fetch();
|
||||
|
||||
$this->RepairProfileChangesOrWarn($oUser, $oProfile->Get('profile'), $oURP_UserProfile, $oProfile->GetOriginal("profileid"));
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
IssueLog::Error('OnUserProfileEdition Exception', LogChannels::DM_CRUD, [
|
||||
'user_id' => $iUserId,
|
||||
'lnk_id' => $oURP_UserProfile->GetKey(),
|
||||
'exception_message' => $e->getMessage(),
|
||||
'exception_stacktrace' => $e->getTraceAsString(),
|
||||
]);
|
||||
if ($e instanceof \CoreCannotSaveObjectException){
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function OnUserProfileLinkDeletion(EventData $oEventData): void {
|
||||
$oURP_UserProfile = $oEventData->Get('object');
|
||||
|
||||
try {
|
||||
$iUserId = $oURP_UserProfile->Get('userid');
|
||||
$oUser = \MetaModel::GetReentranceObjectByChildClass(\User::class, $iUserId);
|
||||
if (false !== $oUser){
|
||||
//user edition: handled by other event
|
||||
return;
|
||||
}
|
||||
|
||||
$oUser = \MetaModel::GetObject(\User::class, $iUserId);
|
||||
|
||||
/** @var \DeletionPlan $oDeletionPlan */
|
||||
$oDeletionPlan = $oEventData->Get('deletion_plan');
|
||||
$aDeletedURP_UserProfiles = [];
|
||||
if (! is_null($oDeletionPlan)){
|
||||
$aListDeletes = $oDeletionPlan->ListDeletes();
|
||||
if (array_key_exists(\URP_UserProfile::class, $aListDeletes)) {
|
||||
foreach ($aListDeletes[\URP_UserProfile::class] as $iId => $aDeletes) {
|
||||
$aDeletedURP_UserProfiles []= $iId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oProfileLinkSet = $oUser->Get('profile_list');
|
||||
$oProfileLinkSet->Rewind();
|
||||
$iCount = 0;
|
||||
while ($oCurrentURP_UserProfile = $oProfileLinkSet->Fetch()) {
|
||||
if (in_array($oCurrentURP_UserProfile->GetKey(), $aDeletedURP_UserProfiles)) {
|
||||
continue;
|
||||
}
|
||||
$iCount++;
|
||||
if ($iCount > 1){
|
||||
//more than one profile: no repairment needed
|
||||
return;
|
||||
}
|
||||
$sSingleProfileName = $oCurrentURP_UserProfile->Get('profile');
|
||||
}
|
||||
|
||||
$this->RepairProfileChangesOrWarn($oUser, $sSingleProfileName, $oURP_UserProfile, $oURP_UserProfile->Get('profileid'), true);
|
||||
} catch (Exception $e) {
|
||||
IssueLog::Error('OnUserProfileLinkDeletion Exception', LogChannels::DM_CRUD, [
|
||||
'user_id' => $iUserId,
|
||||
'profile_id' => $oURP_UserProfile->Get('profileid'),
|
||||
'exception_message' => $e->getMessage(),
|
||||
'exception_stacktrace' => $e->getTraceAsString(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $aPortalDispatcherData: passed only for testing purpose
|
||||
*
|
||||
@@ -125,83 +244,113 @@ class UserProfilesEventListener implements iEventServiceSetup
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$this->FetchRepairingProfileIds($aNonStandaloneProfiles);
|
||||
}
|
||||
|
||||
public function FetchRepairingProfileIds(array $aNonStandaloneProfiles) : void {
|
||||
$aProfiles = [];
|
||||
try {
|
||||
$this->FetchRepairingProfileIds($aNonStandaloneProfiles);
|
||||
$aProfilesToSearch = array_unique(array_values($aNonStandaloneProfiles));
|
||||
if(($iIndex = array_search(null, $aProfilesToSearch)) !== false) {
|
||||
unset($aProfilesToSearch[$iIndex]);
|
||||
}
|
||||
|
||||
if (1 === count($aProfilesToSearch)){
|
||||
$sInCondition = sprintf('"%s"', array_pop($aProfilesToSearch));
|
||||
} else {
|
||||
$sInCondition = sprintf('"%s"', implode('","', $aProfilesToSearch));
|
||||
}
|
||||
|
||||
$sOql = "SELECT URP_Profiles WHERE name IN ($sInCondition)";
|
||||
$oSearch = \DBSearch::FromOQL($sOql);
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new \DBObjectSet($oSearch);
|
||||
while(($oProfile = $oSet->Fetch()) != null) {
|
||||
$sProfileName = $oProfile->Get('name');
|
||||
$aProfiles[$sProfileName] = $oProfile->GetKey();
|
||||
}
|
||||
|
||||
$this->aNonStandaloneProfilesMap = [];
|
||||
foreach ($aNonStandaloneProfiles as $sNonStandaloneProfileName => $sRepairProfileName) {
|
||||
if (is_null($sRepairProfileName)) {
|
||||
$this->aNonStandaloneProfilesMap[$sNonStandaloneProfileName] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! array_key_exists($sRepairProfileName, $aProfiles)) {
|
||||
throw new \Exception(sprintf("%s is badly configured. profile $sRepairProfileName does not exist.", self::USERPROFILE_REPAIR_ITOP_PARAM_NAME));
|
||||
}
|
||||
|
||||
$this->aNonStandaloneProfilesMap[$sNonStandaloneProfileName] = $aProfiles[$sRepairProfileName];
|
||||
}
|
||||
|
||||
$this->bIsRepairmentEnabled = true;
|
||||
} catch (\Exception $e) {
|
||||
IssueLog::Error('Exception when searching user portal profile', LogChannels::DM_CRUD, [
|
||||
'exception_message' => $e->getMessage(),
|
||||
'exception_stacktrace' => $e->getTraceAsString(),
|
||||
'aProfiles' => $aProfiles,
|
||||
'aNonStandaloneProfiles' => $aNonStandaloneProfiles,
|
||||
]);
|
||||
$this->bIsRepairmentEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->bIsRepairmentEnabled = true;
|
||||
}
|
||||
|
||||
public function FetchRepairingProfileIds(array $aNonStandaloneProfiles) : void {
|
||||
$aProfilesToSearch = array_unique(array_values($aNonStandaloneProfiles));
|
||||
if(($iIndex = array_search(null, $aProfilesToSearch)) !== false) {
|
||||
unset($aProfilesToSearch[$iIndex]);
|
||||
}
|
||||
|
||||
if (1 === count($aProfilesToSearch)){
|
||||
$sInCondition = sprintf('"%s"', array_pop($aProfilesToSearch));
|
||||
} else {
|
||||
$sInCondition = sprintf('"%s"', implode('","', $aProfilesToSearch));
|
||||
}
|
||||
|
||||
$sOql = "SELECT URP_Profiles WHERE name IN ($sInCondition)";
|
||||
$oSearch = \DBSearch::FromOQL($sOql);
|
||||
$oSearch->AllowAllData();
|
||||
$oSet = new \DBObjectSet($oSearch);
|
||||
$aProfiles = [];
|
||||
while(($oProfile = $oSet->Fetch()) != null) {
|
||||
$sProfileName = $oProfile->Get('name');
|
||||
$aProfiles[$sProfileName] = $oProfile->GetKey();
|
||||
}
|
||||
|
||||
$this->aNonStandaloneProfilesMap = [];
|
||||
foreach ($aNonStandaloneProfiles as $sNonStandaloneProfileName => $sRepairProfileName) {
|
||||
if (is_null($sRepairProfileName)) {
|
||||
$this->aNonStandaloneProfilesMap[$sNonStandaloneProfileName] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!array_key_exists($sRepairProfileName, $aProfiles)) {
|
||||
throw new \Exception(sprintf("%s is badly configured. profile $sRepairProfileName does not exist.", self::USERPROFILE_REPAIR_ITOP_PARAM_NAME));
|
||||
}
|
||||
|
||||
$this->aNonStandaloneProfilesMap[$sNonStandaloneProfileName] = $aProfiles[$sRepairProfileName];
|
||||
}
|
||||
}
|
||||
|
||||
public function RepairProfiles(?\User $oUser) : void
|
||||
public function ValidateThenRepairOrWarn(\User $oUser) : void
|
||||
{
|
||||
if (!is_null($oUser))
|
||||
{
|
||||
$oCurrentUserProfileSet = $oUser->Get('profile_list');
|
||||
if ($oCurrentUserProfileSet->Count() === 1){
|
||||
$oProfile = $oCurrentUserProfileSet->Fetch();
|
||||
$sSingleProfileName = $oProfile->Get('profile');
|
||||
$oCurrentUserProfileSet = $oUser->Get('profile_list');
|
||||
if ($oCurrentUserProfileSet->Count() === 1){
|
||||
$oProfile = $oCurrentUserProfileSet->Fetch();
|
||||
|
||||
if (array_key_exists($sSingleProfileName, $this->aNonStandaloneProfilesMap)) {
|
||||
$sRepairingProfileId = $this->aNonStandaloneProfilesMap[$sSingleProfileName];
|
||||
if (is_null($sRepairingProfileId)){
|
||||
//Notify current user via session messages that there will be an issue
|
||||
//Without preventing from commiting
|
||||
$sMessage = \Dict::Format("Class:User/NonStandaloneProfileWarning", $sSingleProfileName);
|
||||
$oUser::SetSessionMessage(get_class($oUser), $oUser->GetKey(), 1, $sMessage, 'WARNING', 1);
|
||||
} else {
|
||||
//Completing profiles profiles by adding repairing one : by default portal user to a power portal user
|
||||
$oUserProfile = new \URP_UserProfile();
|
||||
$oUserProfile->Set('profileid', $sRepairingProfileId);
|
||||
$oCurrentUserProfileSet->AddItem($oUserProfile);
|
||||
$oUser->Set('profile_list', $oCurrentUserProfileSet);
|
||||
}
|
||||
}
|
||||
$this->RepairUserChangesOrWarn($oUser, $oProfile->Get('profile'));
|
||||
}
|
||||
}
|
||||
|
||||
public function RepairUserChangesOrWarn(\User $oUser, string $sSingleProfileName) : void {
|
||||
if (array_key_exists($sSingleProfileName, $this->aNonStandaloneProfilesMap)) {
|
||||
$sRepairingProfileId = $this->aNonStandaloneProfilesMap[$sSingleProfileName];
|
||||
if (is_null($sRepairingProfileId)){
|
||||
//Notify current user via session messages that there will be an issue
|
||||
//Without preventing from commiting
|
||||
$sMessage = \Dict::Format("Class:User/NonStandaloneProfileWarning", $sSingleProfileName);
|
||||
//$oUser::SetSessionMessage(get_class($oUser), $oUser->GetKey(), 1, $sMessage, 'WARNING', 1);
|
||||
throw new \CoreCannotSaveObjectException(array('issues' => [$sMessage], 'class' => get_class($oUser), 'id' => $oUser->GetKey()));
|
||||
} else {
|
||||
//Completing profiles profiles by adding repairing one : by default portal user to a power portal user
|
||||
$oUserProfile = new \URP_UserProfile();
|
||||
$oUserProfile->Set('profileid', $sRepairingProfileId);
|
||||
$oCurrentUserProfileSet = $oUser->Get('profile_list');
|
||||
$oCurrentUserProfileSet->AddItem($oUserProfile);
|
||||
$oUser->Set('profile_list', $oCurrentUserProfileSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function RepairProfileChangesOrWarn(\User $oUser, string $sSingleProfileName, \URP_UserProfile $oURP_UserProfile, string $sRemovedProfileId, $bIsRemoval=false) : void {
|
||||
if (array_key_exists($sSingleProfileName, $this->aNonStandaloneProfilesMap)) {
|
||||
$sRepairingProfileId = $this->aNonStandaloneProfilesMap[$sSingleProfileName];
|
||||
if (is_null($sRepairingProfileId)
|
||||
|| ($sRepairingProfileId === $sRemovedProfileId) //cannot repair by readding same remove profile as it will raise uniqueness rule
|
||||
){
|
||||
//Notify current user via session messages that there will be an issue
|
||||
//Without preventing from commiting
|
||||
$sMessage = \Dict::Format("Class:User/NonStandaloneProfileWarning", $sSingleProfileName);
|
||||
//$oURP_UserProfile::SetSessionMessage(get_class($oURP_UserProfile), $oURP_UserProfile->GetKey(), 1, $sMessage, 'WARNING', 1);
|
||||
if ($bIsRemoval){
|
||||
$oURP_UserProfile->AddDeleteIssue($sMessage);
|
||||
} else {
|
||||
throw new \CoreCannotSaveObjectException(array('issues' => [$sMessage], 'class' => get_class($oURP_UserProfile), 'id' => $oURP_UserProfile->GetKey()));
|
||||
}
|
||||
} else {
|
||||
//Completing profiles profiles by adding repairing one : by default portal user to a power portal user
|
||||
$oUserProfile = new \URP_UserProfile();
|
||||
$oUserProfile->Set('profileid', $sRepairingProfileId);
|
||||
$oCurrentUserProfileSet = $oUser->Get('profile_list');
|
||||
$oCurrentUserProfileSet->AddItem($oUserProfile);
|
||||
$oUser->Set('profile_list', $oCurrentUserProfileSet);
|
||||
$oUser->DBWrite();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user