diff --git a/ProcessMaker/Http/Controllers/Api/ProcessController.php b/ProcessMaker/Http/Controllers/Api/ProcessController.php index e8b29b9e25..8080fa53c9 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessController.php @@ -601,6 +601,11 @@ public function update(Request $request, Process $process) } } + // Non-administrators cannot change retention metadata: persist pre-request values. + if (!auth()->user()->is_administrator) { + $this->restoreProcessRetentionPropertiesFromOriginal($process, $original); + } + // Catch errors to send more specific status try { $process->saveOrFail(); @@ -670,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. *