Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion lib/BackgroundJob/OrganizationContactSyncJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ protected function run($argument): void
}

$this->logger->info('[OrganizationContactSyncJob] Starting scheduled organization sync');
$this->orgSyncService->performScheduledSync();
try {
$this->orgSyncService->performScheduledSync();
} catch (\Throwable $e) {
$this->logger->error(
'[OrganizationContactSyncJob] Fatal error during sync — cron pass protected',
[
'error' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
]
);
}//end try
}//end run()
}//end class
2 changes: 1 addition & 1 deletion lib/Controller/ContactpersonenController.php
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ public function updateUserGroups(string $username, array $groups=[]): JSONRespon
$curCatalogGroups = [];

foreach ($currentGroups as $group) {
if (in_array(needle: $group->getGID() === true, haystack: $allowedGroups) === true) {
if (in_array(needle: $group->getGID(), haystack: $allowedGroups) === true) {
$curCatalogGroups[] = $group->getGID();
}
}
Expand Down
27 changes: 10 additions & 17 deletions lib/Service/OrganizationSyncService.php
Original file line number Diff line number Diff line change
Expand Up @@ -426,11 +426,9 @@ public function performContactSync(int $batchSize=100, int $maxExecutionSeconds=
$contactEntityObject = $contactEntity->getObject();
$contactEntityObject['username'] = $contact['uid'];

// Temporarily remove organisatie field to avoid validation error.
// (schema expects object type but field stores a UUID string).
$savedOrganisatie = $contactEntityObject['organisatie'] ?? null;
unset($contactEntityObject['organisatie']);

// Keep organisatie in the object so it is never temporarily absent from the
// persisted record. The schema validation warning for a UUID-string value is
// benign compared to a data-corruption window where the field is missing.
$contactEntity->setObject($contactEntityObject);
$objectService->saveObject(
object: $contactEntity,
Expand All @@ -440,15 +438,6 @@ public function performContactSync(int $batchSize=100, int $maxExecutionSeconds=
_multitenancy: false
);

// Restore the organisatie field so the link is preserved.
if ($savedOrganisatie !== null) {
$restoredData = $contactEntity->getObject();
$restoredData['organisatie'] = $savedOrganisatie;
$contactEntity->setObject($restoredData);
$objectMapper = \OC::$server->get('OCA\OpenRegister\Db\MagicMapper');
$objectMapper->update($contactEntity);
}

$stats['contactPersonsProcessed']++;
} catch (\Exception $e) {
$stats['errors'][] = $contact['uuid'].': '.$e->getMessage();
Expand Down Expand Up @@ -493,8 +482,10 @@ public function performUserSync(): array
$platform = $this->db->getDatabasePlatform();
$isPostgres = $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQLPlatform;

$jsonContainsCheck = "JSON_CONTAINS(oo.users, CONCAT('\"', o.username, '\"')) = 0";
if ($isPostgres === true) {
$jsonContainsCheck = "NOT (oo.users::jsonb @> to_jsonb(o.username::text))";
} else {
$jsonContainsCheck = "JSON_CONTAINS(oo.users, CONCAT('\"', o.username, '\"')) = 0";
}

// Find contacts with a username whose username is NOT in their org's users array.
Expand All @@ -503,7 +494,7 @@ public function performUserSync(): array
->from($contactTableName, 'o')
->leftJoin('o', 'openregister_organisations', 'oo', 'oo.uuid = o.organisatie')
->where($qb->createFunction('o.username IS NOT NULL'))
->andWhere($qb->createFunction('o.username !== '.$qb->createNamedParameter('')))
->andWhere($qb->createFunction('o.username <> '.$qb->createNamedParameter('')))
->andWhere($qb->createFunction('o.organisatie IS NOT NULL'))
->andWhere($qb->createFunction($jsonContainsCheck));

Expand Down Expand Up @@ -2815,8 +2806,10 @@ public function performOptimizedManualSync(int $maxRounds=10, int $batchSize=100
*/
public function performScheduledSync(int $minutesBack=0): array
{
$syncModeValue = 'incremental';
if ($minutesBack === 0) {
$syncModeValue = 'full';
} else {
$syncModeValue = 'incremental';
}

$this->logger->info(
Expand Down