From 6762c1dadbe855892a3b8d9bc6d3b347f6ab9b67 Mon Sep 17 00:00:00 2001 From: sanja <52755494+sanjacornelius@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:07:08 -0700 Subject: [PATCH 1/3] Restrict retention fields to administrators Remove retention-related properties (retention_period, retention_updated_by, retention_updated_at) from the change set if the current user is not an administrator. This ensures only administrators can modify retention settings when publishing a process. --- ProcessMaker/Http/Controllers/Api/ProcessController.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ProcessMaker/Http/Controllers/Api/ProcessController.php b/ProcessMaker/Http/Controllers/Api/ProcessController.php index e8b29b9e25..1fdb711e1f 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessController.php @@ -615,6 +615,13 @@ public function update(Request $request, Process $process) $changes = $process->getChanges(); $changes['tmp_process_category_id'] = $request->input('process_category_id'); + // Prevent non-administrators from updating the retention period + if (!auth()->user()->is_administrator) { + unset($changes['properties']['retention_updated_by']); + unset($changes['properties']['retention_updated_at']); + unset($changes['properties']['retention_period']); + } + // Register the Event ProcessPublished::dispatch($process->refresh(), $changes, $original); From 419213888c2593b7629e21b5df0d5e63ac5e17c3 Mon Sep 17 00:00:00 2001 From: sanja <52755494+sanjacornelius@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:42:13 -0700 Subject: [PATCH 2/3] Restrict retention updates to administrators Prevent non-administrators from modifying retention fields by unsetting retention_updated_by, retention_updated_at and retention_period from the process properties before save. --- .../Http/Controllers/Api/ProcessController.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/ProcessController.php b/ProcessMaker/Http/Controllers/Api/ProcessController.php index 1fdb711e1f..16d561a10b 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessController.php @@ -601,6 +601,13 @@ public function update(Request $request, Process $process) } } + // Prevent non-administrators from updating the retention period + if (!auth()->user()->is_administrator) { + unset($process->properties['retention_updated_by']); + unset($process->properties['retention_updated_at']); + unset($process->properties['retention_period']); + } + // Catch errors to send more specific status try { $process->saveOrFail(); @@ -615,13 +622,6 @@ public function update(Request $request, Process $process) $changes = $process->getChanges(); $changes['tmp_process_category_id'] = $request->input('process_category_id'); - // Prevent non-administrators from updating the retention period - if (!auth()->user()->is_administrator) { - unset($changes['properties']['retention_updated_by']); - unset($changes['properties']['retention_updated_at']); - unset($changes['properties']['retention_period']); - } - // Register the Event ProcessPublished::dispatch($process->refresh(), $changes, $original); From 0dcaa1db5d5aaf41793603ee8754b7ec9542a820 Mon Sep 17 00:00:00 2001 From: sanja <52755494+sanjacornelius@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:50:18 -0700 Subject: [PATCH 3/3] Preserve retention metadata for non-admins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace inline unsets with restoreProcessRetentionPropertiesFromOriginal. For non-administrator updates, reapply retention-related keys (retention_updated_by, retention_updated_at, retention_period) from the original model snapshot—decoding string-encoded properties if needed—and restore or remove keys to match the original state. This prevents non-admins from adding or modifying retention metadata and handles different properties formats robustly. --- .../Controllers/Api/ProcessController.php | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/ProcessController.php b/ProcessMaker/Http/Controllers/Api/ProcessController.php index 16d561a10b..8080fa53c9 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessController.php @@ -601,11 +601,9 @@ public function update(Request $request, Process $process) } } - // Prevent non-administrators from updating the retention period + // Non-administrators cannot change retention metadata: persist pre-request values. if (!auth()->user()->is_administrator) { - unset($process->properties['retention_updated_by']); - unset($process->properties['retention_updated_at']); - unset($process->properties['retention_period']); + $this->restoreProcessRetentionPropertiesFromOriginal($process, $original); } // Catch errors to send more specific status @@ -677,6 +675,40 @@ private function validateMaxManagers(Request $request) return $managerIds; } + /** + * Re-apply retention-related keys on $process->properties from the model snapshot taken before fill(). + * Non-admins cannot add these keys if absent originally, or change values if present. + * + * @param array $original + */ + private function restoreProcessRetentionPropertiesFromOriginal(Process $process, array $original): void + { + $originalProperties = $original['properties'] ?? null; + if (is_string($originalProperties)) { + $decoded = json_decode($originalProperties, true); + $originalProperties = is_array($decoded) ? $decoded : []; + } + if (!is_array($originalProperties)) { + $originalProperties = []; + } + + $properties = $process->properties; + if (!is_array($properties)) { + $properties = []; + } + + $keys = ['retention_updated_by', 'retention_updated_at', 'retention_period']; + foreach ($keys as $key) { + if (array_key_exists($key, $originalProperties)) { + $properties[$key] = $originalProperties[$key]; + } else { + unset($properties[$key]); + } + } + + $process->properties = $properties; + } + /** * Validate the structure of stages. *