TASK-290 Fix the group sync in the ldap cron

This commit is contained in:
Brayan Pereyra
2025-10-07 11:13:49 -04:00
parent 0b0a176058
commit b6b7103624
3 changed files with 379 additions and 26 deletions

View File

@@ -8,6 +8,7 @@ use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use ProcessMaker\Model\Department;
use ProcessMaker\Model\Groupwf;
use ProcessMaker\Model\GroupUser;
use ProcessMaker\BusinessModel\User as BusinessUser;
use \RbacUsers as RbacUsersModel;
use \Roles as RolesModel;
@@ -1876,6 +1877,346 @@ class LdapSource
}
}
public function setArrayGroupUsers($groupUid)
{
try {
$this->arrayGroupUsersByUid = [];
$this->arrayGroupUsersByUsername = [];
$groupUser = new GroupUser();
$filters = [
'fields' => ['GROUP_USER.GRP_UID', 'GROUP_USER.USR_UID', 'USERS.USR_USERNAME', 'USERS.USR_REPORTS_TO'],
'limit' => 10000,
'orderBy' => ['USERS.USR_USERNAME', 'ASC'],
'conditions' => [['GRP_UID', '=', $groupUid], ['USR_STATUS', '!=', 'CLOSED']]
];
$groupUserData = $groupUser->getUsersByGroupId($filters);
foreach ($groupUserData['data'] ?? [] as $userData) {
$this->arrayGroupUsersByUid[$userData['USR_UID']] = $userData;
$this->arrayGroupUsersByUsername[$userData['USR_USERNAME']] = $userData;
}
} catch (Exception $e) {
throw $e;
}
}
public function ldapGetUsersFromGroup($option, array $arrayGroupData, array $arrayData = [])
{
try {
$this->debugLog("class.ldapAdvanced.php > function ldapGetUsersFromGroup() > START");
$this->debugLog("class.ldapAdvanced.php > function ldapGetUsersFromGroup() > \$arrayGroupData ---->\n" . print_r($arrayGroupData, true));
$totalUser = 0;
$countUser = 0;
//Set variables
$dn = trim($arrayGroupData["GRP_LDAP_DN"]);
$rbac = RBAC::getSingleton();
if (is_null($rbac->authSourcesObj)) {
$rbac->authSourcesObj = new AuthenticationSource();
}
$filters = ['conditions' => ['AUTH_SOURCE_UID'=> $this->authSourceUid]];
$rbacAuthenticationSource = new RbacAuthenticationSource();
$authSourceReturn = $rbacAuthenticationSource->show($filters);
$authenticationSourceData = $authSourceReturn['data'][0];
$authenticationSourceData['AUTH_SOURCE_DATA'] = json_decode($authenticationSourceData['AUTH_SOURCE_DATA'], true);
$authenticationSourceData['AUTH_SOURCE_PASSWORD'] = G::decrypt($authenticationSourceData['AUTH_SOURCE_PASSWORD'], URL_KEY);
if (is_null($this->ldapcnn)) {
$ldapcnn = $this->ldapConnection($authenticationSourceData);
$this->ldapcnn = $ldapcnn['connection'];
}
$ldapcnn = $this->ldapcnn;
//Get Group members
$memberAttribute = $this->arrayAttributes[$authenticationSourceData["AUTH_SOURCE_DATA"]["LDAP_TYPE"]]["member"];
$filter = "(" . $this->arrayObjectClassFilter["group"] . ")";
$this->debugLog("class.ldapAdvanced.php > function ldapGetUsersFromGroup() > \$filter ----> $filter");
$searchResult = @ldap_search($ldapcnn, $dn, $filter, array($memberAttribute));
$context = [
"baseDN" => $dn,
"filter" => $filter,
"attributes" => [$memberAttribute]
];
$this->stdLog($ldapcnn, "ldap_search", $context);
if ($error = ldap_errno($ldapcnn)) {
$this->debugLog("class.ldapAdvanced.php > function ldapGetUsersFromGroup() > ldap_search > ERROR > \$error ---->\n" . print_r($error, true));
} else {
$this->debugLog("class.ldapAdvanced.php > function ldapGetUsersFromGroup() > ldap_search > OK1");
if ($searchResult) {
$this->debugLog("class.ldapAdvanced.php > function ldapGetUsersFromGroup() > ldap_search > OK2");
$numEntries = ldap_count_entries($ldapcnn, $searchResult);
$this->stdLog($ldapcnn, "ldap_count_entries");
$this->debugLog("class.ldapAdvanced.php > function ldapGetUsersFromGroup() > ldap_search > OK2 > \$numEntries ----> $numEntries");
if ($numEntries > 0) {
$entry = ldap_first_entry($ldapcnn, $searchResult);
$this->stdLog($ldapcnn, "ldap_first_entry");
$arrayGroupLdap = $this->ldapGetAttributes($ldapcnn, $entry);
// Syncronize members
$flagMemberRange = false;
$memberAttribute2 = $memberAttribute;
if (isset($arrayGroupLdap[$memberAttribute]) && empty($arrayGroupLdap[$memberAttribute])) {
foreach ($arrayGroupLdap as $key => $value) {
if (preg_match('/^member;range=\d+\-\d+$/i', $key)) {
$memberAttribute2 = $key;
$flagMemberRange = true;
break;
}
}
}
$arrayData = $this->ldapGroupSynchronizeMembers(
$ldapcnn,
$authenticationSourceData,
$arrayGroupData['GRP_UID'],
$arrayGroupLdap,
$memberAttribute2,
array_merge($arrayData, ['totalUser' => $totalUser, 'countUser' => $countUser])
);
$totalUser = $arrayData['totalUser'];
$countUser = $arrayData['countUser'];
$limitMemberRange = (isset($arrayData['countMembers'])) ? $arrayData['countMembers'] : 0;
if ($flagMemberRange) {
for ($start = $limitMemberRange; true; $start += $limitMemberRange) {
$end = $start + $limitMemberRange - 1;
$memberAttribute2 = $memberAttribute . ';range=' . $start . '-' . $end;
$searchResult = @ldap_search($ldapcnn, $dn, $filter, [$memberAttribute2]);
$context = [
"baseDN" => $dn,
"filter" => $filter,
"attributes" => [$memberAttribute2]
];
$this->stdLog($ldapcnn, "ldap_search", $context);
if ($error = ldap_errno($ldapcnn)) {
break;
} else {
if ($searchResult) {
if (ldap_count_entries($ldapcnn, $searchResult) > 0) {
$this->stdLog($ldapcnn, "ldap_count_entries");
$entry = ldap_first_entry($ldapcnn, $searchResult);
$this->stdLog($ldapcnn, "ldap_first_entry");
$arrayGroupLdap = $this->ldapGetAttributes($ldapcnn, $entry);
foreach ($arrayGroupLdap as $key => $value) {
if (preg_match('/^member;range=\d+\-\*$/i', $key)) {
$memberAttribute2 = $key;
break;
}
}
$arrayData = $this->ldapGroupSynchronizeMembers(
$ldapcnn,
$authenticationSourceData,
$arrayGroupData['GRP_UID'],
$arrayGroupLdap,
$memberAttribute2,
array_merge($arrayData, ['totalUser' => $totalUser, 'countUser' => $countUser])
);
$totalUser = $arrayData['totalUser'];
$countUser = $arrayData['countUser'];
}
}
}
}
}
}
}
}
$this->log($ldapcnn, "Found $totalUser users in group $dn");
$this->debugLog("class.ldapAdvanced.php > function ldapGetUsersFromGroup() > END");
//Return
return $arrayData;
} catch (Exception $e) {
throw $e;
}
}
private function ldapGroupSynchronizeMembers($ldapcnn, array $arrayAuthSourceData, $groupUid, array $arrayGroupLdap, $memberAttribute, array $arrayData = [])
{
try {
unset($arrayData['countMembers']);
//Get members
if (!isset($arrayAuthSourceData['AUTH_SOURCE_DATA']['AUTH_SOURCE_USERS_FILTER'])) {
$arrayAuthSourceData['AUTH_SOURCE_DATA']['AUTH_SOURCE_USERS_FILTER'] = '';
}
$uidUserIdentifier = (isset($arrayAuthSourceData['AUTH_SOURCE_DATA']['AUTH_SOURCE_IDENTIFIER_FOR_USER'])) ?
$arrayAuthSourceData['AUTH_SOURCE_DATA']['AUTH_SOURCE_IDENTIFIER_FOR_USER'] : 'uid';
$filterUsers = trim($arrayAuthSourceData['AUTH_SOURCE_DATA']['AUTH_SOURCE_USERS_FILTER']);
$filter = ($filterUsers != '') ? $filterUsers : '(' . $this->arrayObjectClassFilter['user'] . ')';
if (isset($arrayGroupLdap[$memberAttribute])) {
if (!is_array($arrayGroupLdap[$memberAttribute])) {
$arrayGroupLdap[$memberAttribute] = [$arrayGroupLdap[$memberAttribute]];
}
$arrayData['countMembers'] = count($arrayGroupLdap[$memberAttribute]);
$arrayData['totalUser'] += $arrayData['countMembers'];
//Synchronize members
foreach ($arrayGroupLdap[$memberAttribute] as $value) {
$member = $value; //User DN
$searchResult = @ldap_search($ldapcnn, $member, $filter, $this->arrayAttributesForUser);
$context = [
"baseDN" => $member,
"filter" => $filter,
"attributes" => $this->arrayAttributesForUser
];
$this->stdLog($ldapcnn, "ldap_search", $context);
if ($error = ldap_errno($ldapcnn)) {
//
} else {
if ($searchResult) {
if (ldap_count_entries($ldapcnn, $searchResult) > 0) {
$this->stdLog($ldapcnn, "ldap_count_entries");
$entry = ldap_first_entry($ldapcnn, $searchResult);
$this->stdLog($ldapcnn, "ldap_first_entry");
$arrayUserLdap = $this->ldapGetAttributes($ldapcnn, $entry);
$username = (isset($arrayUserLdap[$uidUserIdentifier])) ? $arrayUserLdap[$uidUserIdentifier] : '';
$arrayData['countUser']++;
if ((is_array($username) && !empty($username)) || trim($username) != '') {
$dataUserLdap = $this->getUserDataFromAttribute($username, $arrayUserLdap);
$dataUserLdap["usrRole"] = "";
if (!empty($arrayAuthSourceData['AUTH_SOURCE_DATA']['USR_ROLE'])) {
$dataUserLdap["usrRole"] = $arrayAuthSourceData['AUTH_SOURCE_DATA']['USR_ROLE'];
}
$arrayData = $this->groupSynchronizeUser(
$groupUid,
$dataUserLdap,
$arrayData
);
}
//Progress bar
$this->frontEndShow(
'BAR',
'Groups: ' . $arrayData['i'] . '/' . $arrayData['n'] . ' ' .
$this->progressBar($arrayData['totalUser'], $arrayData['countUser'])
);
}
}
}
}
}
// Return
return $arrayData;
} catch (Exception $e) {
throw $e;
}
}
public function groupSynchronizeUser($groupUid, array $arrayUserLdap, array $arrayData)
{
try {
$this->debugLog("class.ldapAdvanced.php > function groupSynchronizeUser() > START");
$this->debugLog("class.ldapAdvanced.php > function groupSynchronizeUser() > \$arrayUserLdap[sUsername] ----> " . $arrayUserLdap["sUsername"]);
$group = new Groups();
$userUid = "";
$found = false;
$arrayUserData = $this->groupGetUserDataIfUsernameExists($arrayUserLdap["sUsername"]);
if (!empty($arrayUserData)) {
//User already exists in this group and there is nothing to do
//User already exists
$userUid = $arrayUserData["USR_UID"];
$found = true;
$arrayData["already"]++;
$arrayData["alreadyUsers"] .= $arrayUserData["USR_USERNAME"] . " ";
}
if (!$found) {
//If user DO NOT exists in this group.. do:
//If exists with another AuthSource -> impossible
//If exists in another group, but in PM and for this authsource, we need to move it
//$arrayNewUserData = $this->searchUserByUid($arrayUserLdap["sUsername"]);
$arrayNewUserData = $arrayUserLdap;
$arrayUserData = $this->authenticationSourceGetUserDataIfUsernameExists($arrayNewUserData["sUsername"]);
if (!empty($arrayUserData)) {
//User exists in this Authentication Source
//Move User
$userUid = $arrayUserData["USR_UID"];
$this->activateUser($arrayUserData["USR_UID"], $arrayNewUserData["sDN"]);
$group->addUserToGroup($groupUid, $userUid);
$arrayData["moved"]++;
$arrayData["movedUsers"] .= $arrayUserData["USR_USERNAME"] . " ";
$this->setArrayAuthenticationSourceUser($userUid, $arrayNewUserData); //INITIALIZE DATA //Update User
} else {
$arrayUserData = $this->getUserFromPM($arrayNewUserData["sUsername"]);
if (!empty($arrayUserData)) {
//User exists in another Authentication Source and another Group
//Impossible
$userUid = $arrayUserData["USR_UID"];
$arrayData["impossible"]++;
$arrayData["impossibleUsers"] .= $arrayUserData["USR_USERNAME"] . " ";
} else {
//User not exists
//Create User
$userUid = $this->createUserAndActivate($arrayNewUserData, "");
$group->addUserToGroup($groupUid, $userUid);
$arrayData["created"]++;
$arrayData["createdUsers"] .= $arrayNewUserData["sUsername"] . " ";
$this->setArrayAuthenticationSourceUser($userUid, $arrayNewUserData); //INITIALIZE DATA //Add User
}
}
}
if ($userUid != "") {
$arrayData["arrayUserUid"][] = $userUid;
if (isset($arrayUserLdap["sManagerDN"]) && $arrayUserLdap["sManagerDN"] != "") {
if (!isset($arrayData["managersHierarchy"][$arrayUserLdap["sManagerDN"]])) {
$arrayData["managersHierarchy"][$arrayUserLdap["sManagerDN"]] = [];
}
$arrayData["managersHierarchy"][$arrayUserLdap["sManagerDN"]][$userUid] = $userUid;
}
}
$this->debugLog("class.ldapAdvanced.php > function groupSynchronizeUser() > \$userUid ----> $userUid");
$this->debugLog("class.ldapAdvanced.php > function groupSynchronizeUser() > END");
//Return
return $arrayData;
} catch (Exception $e) {
throw $e;
}
}
public function authenticationSourceGetUserDataIfUsernameExists($username)
{
try {
@@ -1986,6 +2327,18 @@ class LdapSource
}
}
public function groupGetUserDataIfUsernameExists($username)
{
try {
if (isset($this->arrayGroupUsersByUsername[$username])) {
return $this->arrayGroupUsersByUsername[$username];
}
// Return
return [];
} catch (Exception $e) {
throw $e;
}
}
public function setArrayAuthenticationSourceUsers($authSourceUid = '')
{

View File

@@ -1,26 +1,8 @@
<?php
/**
* users_ViewPhoto.php
*
* ProcessMaker Open Source Edition
* Copyright (C) 2004 - 2008 Colosa Inc.23
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
*/
use ProcessMaker\Model\User;
if (($RBAC_Response = $RBAC->userCanAccess( "PM_LOGIN" )) != 1)
return $RBAC_Response;
@@ -30,8 +12,23 @@ $direction = PATH_IMAGES_ENVIRONMENT_USERS . $_REQUEST['pUID'] . ".gif";
if (! file_exists( $direction )) {
$user = new User();
$filters = array(
'limit' => 1,
'fields' => ['USR_UID'],
'conditions' => [['USR_ID', '=', $_REQUEST['pUID']]]
);
$result = $user->show($filters);
if ($result['total'] == 1){
$direction = PATH_IMAGES_ENVIRONMENT_USERS . $result['data'][0]['USR_UID'] . ".gif";
if (! file_exists( $direction )) {
$direction = PATH_HOME . 'public_html/images/user.gif';
}
} else {
$direction = PATH_HOME . 'public_html/images/user.gif';
}
}
G::sendHeaders( $direction );
DumpHeaders( $direction );

View File

@@ -170,7 +170,7 @@ class GroupUser extends Model
}
}
public static function getUsersByGroupId($groupUid, $filters = [])
public static function getUsersByGroupId($filters = [])
{
$query = static::query();
@@ -178,8 +178,11 @@ class GroupUser extends Model
$query->select($filters['fields']);
}
$query->where('GROUP_USER.GRP_UID', $groupUid);
$query->innerJoin('GROUP_USER.USR_UID', '=', 'USERS.USR_UID');
if (!empty($filters['conditions']) && is_array($filters['conditions'])) {
$query->where($filters['conditions']);
}
$query->leftJoin('USERS', 'GROUP_USER.USR_UID', '=', 'USERS.USR_UID');
$total = $query->count();