diff --git a/ProcessMaker/Events/TemplateDeleted.php b/ProcessMaker/Events/TemplateDeleted.php index 473ddc2520..8537137524 100644 --- a/ProcessMaker/Events/TemplateDeleted.php +++ b/ProcessMaker/Events/TemplateDeleted.php @@ -31,7 +31,7 @@ public function __construct(ProcessTemplates $template) public function getData(): array { return [ - 'template_name' => $this->template->name, + 'name' => $this->template->name, 'deleted_at' => Carbon::now(), ]; } @@ -45,7 +45,6 @@ public function getChanges(): array { return [ 'id' => $this->template->id, - 'template_name' => $this->template->name, ]; } diff --git a/ProcessMaker/Events/TemplateUpdated.php b/ProcessMaker/Events/TemplateUpdated.php index e86f0404a8..5cb6380a28 100644 --- a/ProcessMaker/Events/TemplateUpdated.php +++ b/ProcessMaker/Events/TemplateUpdated.php @@ -6,7 +6,9 @@ use Illuminate\Foundation\Events\Dispatchable; use ProcessMaker\Contracts\SecurityLogEventInterface; use ProcessMaker\Helpers\ArrayHelper; +use ProcessMaker\Models\Process; use ProcessMaker\Models\ProcessCategory; +use ProcessMaker\Models\ProcessTemplates; use ProcessMaker\Traits\FormatSecurityLogChanges; class TemplateUpdated implements SecurityLogEventInterface @@ -14,6 +16,7 @@ class TemplateUpdated implements SecurityLogEventInterface use Dispatchable; use FormatSecurityLogChanges; + private Process|ProcessTemplates $process; private array $changes; private array $original; @@ -25,11 +28,16 @@ class TemplateUpdated implements SecurityLogEventInterface * * @return void */ - public function __construct(array $changes, array $original, bool $processType) - { + public function __construct( + array $changes, + array $original, + bool $processType, + Process|ProcessTemplates $process = null + ) { $this->changes = $changes; $this->original = $original; $this->processType = $processType; + $this->process = $process; // Get category name $this->original['category'] = isset($original['process_category_id']) @@ -49,9 +57,7 @@ public function getData(): array { if ($this->processType) { return [ - 'name' => [ - 'label' => $this->processType, - ], + 'name' => $this->process->name ?? '', 'last_modified' => $this->changes['updated_at'] ?? Carbon::now(), ]; } else { @@ -59,9 +65,7 @@ public function getData(): array $newData = array_diff_assoc($this->changes, $this->original); return array_merge([ - 'name' => [ - 'label' => $this->processType, - ], + 'name' => $this->process->name ?? '', 'last_modified' => $this->changes['updated_at'] ?? Carbon::now(), ], ArrayHelper::getArrayDifferencesWithFormat($newData, $oldData)); } @@ -74,7 +78,9 @@ public function getData(): array */ public function getChanges(): array { - return []; + return [ + 'id' => $this->process->id ?? '' + ]; } /** diff --git a/ProcessMaker/Events/TokenCreated.php b/ProcessMaker/Events/TokenCreated.php index 16898038e6..cf813ada20 100644 --- a/ProcessMaker/Events/TokenCreated.php +++ b/ProcessMaker/Events/TokenCreated.php @@ -2,37 +2,42 @@ namespace ProcessMaker\Events; -use Carbon\Carbon; use Illuminate\Foundation\Events\Dispatchable; use Laravel\Passport\Token; use ProcessMaker\Contracts\SecurityLogEventInterface; +use ProcessMaker\Models\User; class TokenCreated implements SecurityLogEventInterface { use Dispatchable; - private array $data; + private Token $data; + private User $user; + private string $name; /** * Create a new event instance. * * @return void */ - public function __construct(Token $token) + public function __construct(Token $token, User $user, string $name = '') { - $this->data = [ - 'token_id' => $token->getKey(), - 'created_at' => Carbon::now(), - ]; + $this->data = $token; + $this->user = $user; + $this->name = $name; } /** - * Return event data * Return event data */ public function getData(): array { - return $this->data; + return [ + 'name' => $this->name, + 'id' => substr($this->data->getAttribute('id'), 0, 5), + 'user' => $this->user->username, + 'created_at' => $this->data->getAttribute('created_at'), + ]; } /** @@ -40,7 +45,9 @@ public function getData(): array */ public function getChanges(): array { - return []; + return [ + 'client_id' => $this->data->getAttribute('client_id'), + ]; } /** diff --git a/ProcessMaker/Events/TokenDeleted.php b/ProcessMaker/Events/TokenDeleted.php index 45b68c6ac2..cb0eb3bf60 100644 --- a/ProcessMaker/Events/TokenDeleted.php +++ b/ProcessMaker/Events/TokenDeleted.php @@ -2,28 +2,30 @@ namespace ProcessMaker\Events; +use Carbon\Carbon; use Illuminate\Foundation\Events\Dispatchable; use Laravel\Passport\Token; use ProcessMaker\Contracts\SecurityLogEventInterface; +use ProcessMaker\Models\User; class TokenDeleted implements SecurityLogEventInterface { use Dispatchable; - private array $data; - - private array $changes; + private Token $data; + private User $user; + private string $name; /** * Create a new event instance. * * @return void */ - public function __construct(Token $token) + public function __construct(Token $token, User $user, string $name = '') { - $this->data = [ - 'token_id' => $token->getKey(), - ]; + $this->data = $token; + $this->user = $user; + $this->name = $name; } /** @@ -31,7 +33,12 @@ public function __construct(Token $token) */ public function getData(): array { - return $this->data; + return [ + 'name' => $this->name, + 'id' => substr($this->data->getAttribute('id'), 0, 5), + 'user' => $this->user->username, + 'deleted_at' => Carbon::now(), + ]; } /** @@ -39,7 +46,9 @@ public function getData(): array */ public function getChanges(): array { - return $this->data; + return [ + 'client_id' => $this->data->getAttribute('client_id'), + ]; } /** diff --git a/ProcessMaker/Http/Controllers/Api/ProcessController.php b/ProcessMaker/Http/Controllers/Api/ProcessController.php index ccef8a4673..470c3a5935 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessController.php @@ -370,7 +370,7 @@ public function update(Request $request, Process $process) $response = (new TemplateController(new Template()))->updateTemplateManifest('process', $process->id, $request); //Call Event to Log Template Changes - TemplateUpdated::dispatch([], [], true); + TemplateUpdated::dispatch([], [], true, $process); return new Resource($process->refresh()); } catch (\Exception $error) { diff --git a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php index 5cc20161ec..d829254bf0 100644 --- a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php +++ b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php @@ -245,10 +245,10 @@ public function delete(Request $request, ScriptExecutor $scriptExecutor) } } - ScriptExecutorDeleted::dispatch($scriptExecutor->getAttributes()); - ScriptExecutor::destroy($scriptExecutor->id); + ScriptExecutorDeleted::dispatch($scriptExecutor->getAttributes()); + return ['status' => 'done']; } diff --git a/ProcessMaker/Http/Controllers/Api/TemplateController.php b/ProcessMaker/Http/Controllers/Api/TemplateController.php index 9e3d34f1d4..2ea5efd5b1 100644 --- a/ProcessMaker/Http/Controllers/Api/TemplateController.php +++ b/ProcessMaker/Http/Controllers/Api/TemplateController.php @@ -110,11 +110,12 @@ public function updateTemplate(string $type, Request $request) public function updateTemplateConfigs(string $type, Request $request) { $request->validate(Template::rules($request->id, $this->types[$type][4])); + $proTemplates = ProcessTemplates::select()->find($request->id)->getOriginal(); $changes = $request->all(); - $original = ProcessTemplates::select(array_keys($changes))->find($request->id)->getOriginal(); + $original = array_intersect_key($proTemplates->getOriginal(), $changes); $response = $this->template->updateTemplateConfigs($type, $request); //Call event to log Template Config changes - TemplateUpdated::dispatch($changes, $original, false); + TemplateUpdated::dispatch($changes, $original, false, $proTemplates); return $response; } diff --git a/ProcessMaker/Http/Controllers/Api/UserTokenController.php b/ProcessMaker/Http/Controllers/Api/UserTokenController.php index 1030dc9a12..a3f6e437cf 100644 --- a/ProcessMaker/Http/Controllers/Api/UserTokenController.php +++ b/ProcessMaker/Http/Controllers/Api/UserTokenController.php @@ -155,7 +155,7 @@ public function store(Request $request, User $user) $request->scopes ?: [] ); - event(new TokenCreated($token->token)); + event(new TokenCreated($token->token, $user, $request->name)); return new UserTokenResource($token); } @@ -264,7 +264,7 @@ public function destroy(Request $request, User $user, $tokenId) $token->revoke(); - event(new TokenDeleted($token)); + event(new TokenDeleted($token, $user, $token->name)); return response([], 204); } diff --git a/tests/Feature/Api/SecurityLogsTest.php b/tests/Feature/Api/SecurityLogsTest.php index 6cf81c1695..c762be907d 100644 --- a/tests/Feature/Api/SecurityLogsTest.php +++ b/tests/Feature/Api/SecurityLogsTest.php @@ -22,12 +22,28 @@ use ProcessMaker\Events\ScreenCreated; use ProcessMaker\Events\ScreenDeleted; use ProcessMaker\Events\ScreenUpdated; +use ProcessMaker\Events\ScriptCreated; +use ProcessMaker\Events\ScriptDeleted; +use ProcessMaker\Events\ScriptDuplicated; +use ProcessMaker\Events\ScriptExecutorCreated; +use ProcessMaker\Events\ScriptExecutorDeleted; +use ProcessMaker\Events\ScriptExecutorUpdated; +use ProcessMaker\Events\ScriptUpdated; use ProcessMaker\Events\SettingsUpdated; +use ProcessMaker\Events\SignalCreated; +use ProcessMaker\Events\SignalDeleted; +use ProcessMaker\Events\SignalUpdated; use ProcessMaker\Events\TemplateCreated; +use ProcessMaker\Events\TemplateDeleted; +use ProcessMaker\Events\TemplatePublished; +use ProcessMaker\Events\TemplateUpdated; +use ProcessMaker\Events\TokenCreated; +use ProcessMaker\Events\TokenDeleted; use ProcessMaker\Events\UserCreated; use ProcessMaker\Events\UserDeleted; use ProcessMaker\Events\UserRestored; use ProcessMaker\Events\UserUpdated; +use ProcessMaker\Managers\SignalManager; use ProcessMaker\Models\EnvironmentVariable; use ProcessMaker\Models\Group; use ProcessMaker\Models\Permission; @@ -37,9 +53,13 @@ use ProcessMaker\Models\Screen; use ProcessMaker\Models\SecurityLog; use ProcessMaker\Models\Setting; +use ProcessMaker\Models\Script; +use ProcessMaker\Models\ScriptExecutor; +use ProcessMaker\Models\SignalData; use ProcessMaker\Models\User; use ProcessMaker\Providers\AuthServiceProvider; use Tests\Feature\Shared\RequestHelper; +use Tests\Feature\Templates\HelperTrait; use Tests\TestCase; /** @@ -47,6 +67,7 @@ */ class SecurityLogsTest extends TestCase { + use HelperTrait; use RequestHelper; protected function withUserSetup() @@ -457,6 +478,281 @@ public function testScreenUpdated() $this->checkAssertsSegurityLog('ScreenUpdated', 'last_modified'); } + /** + * This test Script Created + */ + public function testScriptCreated() + { + $script = Script::factory()->create(); + $changes = $script->getChanges(); + ScriptCreated::dispatch($script, $changes); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('ScriptCreated', 'created_at'); + } + + /** + * This test Script Deleted + */ + public function testScriptDeleted() + { + $script = Script::factory()->create(); + $script->delete(); + ScriptDeleted::dispatch($script); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('ScriptDeleted', 'deleted_at'); + } + + /** + * This test Script Duplicated + */ + public function testScriptDuplicated() + { + $script = Script::factory()->create(); + $changes = $script->getChanges(); + ScriptDuplicated::dispatch($script, $changes); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('ScriptDuplicated', 'created_at'); + } + + /** + * This test Script Updated + */ + public function testScriptUpdated() + { + $script = Script::factory()->create(); + $original = array_intersect_key($script->getOriginal(), $script->getDirty()); + $script->fill(['description' => 'screen description']); + $script->saveOrFail(); + $changes = $script->getChanges(); + ScriptUpdated::dispatch($script, $changes, $original); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('ScriptUpdated', 'last_modified'); + } + + /** + * This test Script Executor Created + */ + public function testScriptExecutorCreated() + { + $fields = [ + 'id' => 999, + 'uuid' => '999fa7a8-893c-4eaf-test-389777b979a3', + 'title' => 'scriptexecutors_1', + 'description' => 'description_1', + 'language' => 'php', + ]; + $scriptExecutor = ScriptExecutor::create($fields); + ScriptExecutorCreated::dispatch($scriptExecutor->getAttributes()); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('ScriptExecutorCreated', 'created_at'); + } + + /** + * This test Script Executor Deleted + */ + public function testScriptExecutorDeleted() + { + $fields = [ + 'id' => 99999, + 'title' => 'scriptexecutors_3', + 'description' => 'description_3', + 'language' => 'php', + ]; + $scriptExecutor = ScriptExecutor::create($fields); + ScriptExecutor::destroy($scriptExecutor->id); + ScriptExecutorDeleted::dispatch($scriptExecutor->getAttributes()); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('ScriptExecutorDeleted', 'deleted_at'); + } + + /** + * This test Script Executor Updated + */ + public function testScriptExecutorUpdated() + { + $fields = [ + 'id' => 9999, + 'uuid' => '999fa7a8-test-test-test-389777b979a3', + 'title' => 'scriptexecutors_2', + 'description' => 'description_2', + 'language ' => 'php', + ]; + $scriptExecutor = ScriptExecutor::create($fields); + $original = $scriptExecutor->getAttributes(); + $scriptExecutor->update(['description' => 'scriptexecutors description']); + ScriptExecutorUpdated::dispatch($scriptExecutor->id, $original, $scriptExecutor->getChanges()); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('ScriptExecutorUpdated', 'last_modified'); + } + + /** + * This test Signal Created + */ + public function testSignalCreated() + { + $this->addGlobalSignalProcess(); + $fields = [ + 'id' => 'id test', + 'name' => 'name test', + 'detail' => 'detail test', + ]; + $signal = new SignalData($fields['id'], $fields['name'], $fields['detail']); + SignalManager::addSignal($signal, $fields['detail']); + SignalCreated::dispatch($fields); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('SignalCreated', 'created_at'); + } + + /** + * This test Signal Deleted + */ + public function testSignalDeleted() + { + $this->addGlobalSignalProcess(); + $fields = [ + 'id' => 'id test', + 'name' => 'name test', + 'detail' => 'detail test', + ]; + $signal = new SignalData($fields['id'], $fields['name'], $fields['detail']); + SignalManager::addSignal($signal, $fields['detail']); + SignalManager::removeSignal($signal); + SignalDeleted::dispatch($fields); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('SignalDeleted', 'deleted_at'); + } + + /** + * This test Signal Updated + */ + public function testSignalUpdated() + { + $this->addGlobalSignalProcess(); + $oldSignal = [ + 'id' => 'id test', + 'name' => 'name test', + 'detail' => 'detail test', + ]; + $signal = new SignalData($oldSignal['id'], $oldSignal['name'], $oldSignal['detail']); + SignalManager::addSignal($signal, $oldSignal['detail']); + $oldSignal = SignalManager::findSignal($oldSignal['id']); + $newSignal = [ + 'id' => 'id test_1', + 'name' => 'name test_1', + 'detail' => 'detail test_1', + ]; + $newSignal = new SignalData($newSignal['id'], $newSignal['name'], $newSignal['detail']); + SignalManager::replaceSignal($newSignal, $oldSignal, 'detail test_1'); + SignalUpdated::dispatch( + [ + 'id' => $newSignal->getId() ?? '', + 'name' => $newSignal->getName() ?? '', + 'detail' => $newSignal->getDetail() ?? '', + ], + [ + 'id' => $oldSignal->getId() ?? '', + 'name' => $oldSignal->getName() ?? '', + 'detail' => $oldSignal->getDetail() ?? '', + ] + ); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('SignalUpdated', 'last_modified'); + } + + /** + * This test Template Created + */ + public function testTemplateCreated() + { + $this->addGlobalSignalProcess(); + $fields = [ + 'name' => 'template_1', + 'description' => 'description_1', + ]; + ProcessTemplates::factory()->create($fields); + TemplateCreated::dispatch($fields); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('TemplateCreated', 'created_at'); + } + + /** + * This test Template Deleted + */ + public function testTemplateDeleted() + { + $this->addGlobalSignalProcess(); + $templates = ProcessTemplates::factory()->create(); + TemplateDeleted::dispatch($templates); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('TemplateDeleted', 'deleted_at'); + } + + /** + * This test Template Published + */ + public function testTemplatePublished() + { + $this->addGlobalSignalProcess(); + $fields = [ + 'name' => 'template_1', + 'description' => 'description_1', + ]; + ProcessTemplates::factory()->create($fields); + TemplatePublished::dispatch($fields); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('TemplatePublished', 'created_at'); + } + + /** + * This test Template Updated + */ + public function testTemplateUpdated() + { + $this->addGlobalSignalProcess(); + // When the template is a process + $process = Process::factory()->create([ + 'is_template' => 1 + ]); + TemplateUpdated::dispatch([], [], true, $process); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('TemplateUpdated', 'last_modified'); + // When the template is a process + $process = ProcessTemplates::factory()->create(); + TemplateUpdated::dispatch([], [], true, $process); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('TemplateUpdated', 'last_modified', 2); + } + + /** + * This test Token Created + */ + public function testTokenCreated() + { + $user = User::factory()->create([ + 'status' => 'ACTIVE', + 'is_administrator' => true + ]); + $token = $user->createToken('API Token'); + TokenCreated::dispatch($token->token, $user, 'API token'); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('TokenCreated', 'created_at', 1); + } + + /** + * This test Token Deleted + */ + public function testTokenDeleted() + { + $user = User::factory()->create([ + 'status' => 'ACTIVE', + 'is_administrator' => true + ]); + $token = $user->createToken('API Token'); + TokenDeleted::dispatch($token->token, $user, 'API token'); + // Review the asserts about the response of Security Log + $this->checkAssertsSegurityLog('TokenDeleted', 'deleted_at', 1); + } + /** * This test User Created */