diff --git a/ProcessMaker/Models/User.php b/ProcessMaker/Models/User.php index c13c133659..41229368b3 100644 --- a/ProcessMaker/Models/User.php +++ b/ProcessMaker/Models/User.php @@ -156,12 +156,13 @@ public static function boot() static::deleting(function ($user) { $user->status = 'INACTIVE'; - $user->save(); + // Persist the inactive status without treating the delete as a user update. + $user->saveQuietly(); }); static::restoring(function ($user) { + // SoftDeletes::restore() saves this with deleted_at=null; avoid a second updated event. $user->status = 'ACTIVE'; - $user->save(); }); static::deleted(function ($user) { diff --git a/tests/Feature/Api/UsersTest.php b/tests/Feature/Api/UsersTest.php index c1dacd9e18..4c58a444b5 100644 --- a/tests/Feature/Api/UsersTest.php +++ b/tests/Feature/Api/UsersTest.php @@ -644,6 +644,67 @@ public function testRestoreSoftDeletedUser() $response->assertJsonFragment(['id' => $id]); } + public function testRestoreSoftDeletedUserDispatchesOneUpdatedEvent() + { + $deletedUser = null; + User::withoutEvents(function () use (&$deletedUser) { + $deletedUser = User::factory()->create([ + 'deleted_at' => now(), + 'status' => 'INACTIVE', + ]); + }); + + $updatedEventCount = 0; + User::updated(function () use (&$updatedEventCount) { + $updatedEventCount++; + }); + + $response = $this->apiCall('PUT', self::API_TEST_URL . '/restore', [ + 'id' => $deletedUser->id, + ]); + + $response->assertStatus(200); + + $restoredUser = User::find($deletedUser->id); + $this->assertSame('ACTIVE', $restoredUser->status); + $this->assertNull($restoredUser->deleted_at); + $this->assertFalse($restoredUser->trashed()); + $this->assertSame(1, $updatedEventCount); + } + + public function testDeleteUserDispatchesDeletedWithoutUpdatedEvent() + { + $user = User::factory()->create(); + $group = Group::factory()->create(); + $user->groups()->attach($group->id); + + $updatedEventCount = 0; + $deletedEventCount = 0; + User::updated(function () use (&$updatedEventCount) { + $updatedEventCount++; + }); + User::deleted(function () use (&$deletedEventCount) { + $deletedEventCount++; + }); + + $response = $this->apiCall('DELETE', self::API_TEST_URL . '/' . $user->id); + + $response->assertStatus(204); + + $deletedUser = User::withTrashed()->findOrFail($user->id); + $this->assertSame('INACTIVE', $deletedUser->status); + $this->assertNotNull($deletedUser->deleted_at); + $this->assertTrue($deletedUser->trashed()); + $this->assertSame(0, $updatedEventCount); + $this->assertSame(1, $deletedEventCount); + + $this->assertDatabaseMissing('group_members', [ + 'group_id' => $group->id, + 'member_id' => $user->id, + 'member_type' => User::class, + ]); + } + public function testCreateWithoutPassword() { $payload = [