Skip to content

Commit cc09017

Browse files
committed
Resolve #963 - forceDelete on User prevented by Foreign Key Constraints
1 parent b15166c commit cc09017

4 files changed

Lines changed: 101 additions & 7 deletions

File tree

app/sprinkles/account/src/Database/Models/User.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,11 @@ public function delete($hardDelete = false)
188188
// Remove all role associations
189189
$this->roles()->detach();
190190

191-
// Remove all user activities
192-
$classMapper->staticMethod('activity', 'where', 'user_id', $this->id)->delete();
193-
194191
// Remove all user tokens
195-
$classMapper->staticMethod('password_reset', 'where', 'user_id', $this->id)->delete();
192+
$this->activities()->delete();
193+
$this->passwordResets()->delete();
196194
$classMapper->staticMethod('verification', 'where', 'user_id', $this->id)->delete();
197-
198-
// TODO: remove any persistences
195+
$classMapper->staticMethod('persistence', 'where', 'user_id', $this->id)->delete();
199196

200197
// Delete the user
201198
$result = $this->forceDelete();

app/sprinkles/account/src/ServicesProvider/ServicesProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public function register(ContainerInterface $container)
6969
$classMapper->setClassMapping('activity', 'UserFrosting\Sprinkle\Account\Database\Models\Activity');
7070
$classMapper->setClassMapping('password_reset', 'UserFrosting\Sprinkle\Account\Database\Models\PasswordReset');
7171
$classMapper->setClassMapping('verification', 'UserFrosting\Sprinkle\Account\Database\Models\Verification');
72+
$classMapper->setClassMapping('persistence', 'UserFrosting\Sprinkle\Account\Database\Models\Persistence');
7273

7374
return $classMapper;
7475
});
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
/**
3+
* UserFrosting (http://www.userfrosting.com)
4+
*
5+
* @link https://github.com/userfrosting/UserFrosting
6+
* @copyright Copyright (c) 2019 Alexander Weissman
7+
* @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License)
8+
*/
9+
10+
namespace UserFrosting\Sprinkle\Account\Tests\Integration\Database\Models;
11+
12+
use UserFrosting\Sprinkle\Account\Database\Models\Role;
13+
use UserFrosting\Sprinkle\Account\Database\Models\User;
14+
use UserFrosting\Sprinkle\Account\Database\Models\Persistence;
15+
use UserFrosting\Sprinkle\Account\Database\Models\Verification;
16+
use UserFrosting\Sprinkle\Account\Tests\withTestUser;
17+
use UserFrosting\Sprinkle\Core\Tests\TestDatabase;
18+
use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase;
19+
use UserFrosting\Tests\TestCase;
20+
21+
/**
22+
* UserModelTest Class
23+
* Tests the User Model.
24+
*/
25+
class UserModelTest extends TestCase
26+
{
27+
use TestDatabase;
28+
use RefreshDatabase;
29+
use withTestUser;
30+
31+
/**
32+
* Setup the database schema.
33+
*/
34+
public function setUp()
35+
{
36+
parent::setUp();
37+
38+
// Setup test database
39+
$this->setupTestDatabase();
40+
$this->refreshDatabase();
41+
}
42+
43+
/**
44+
* Test user hard deletion with user relations.
45+
* This is not a totaly acurate test, as each relations are added manually
46+
* and new relations might not be added automatically to accuratly test
47+
*/
48+
public function testUserHardDeleteWithUserRelations()
49+
{
50+
$fm = $this->ci->factory;
51+
52+
// Create a user & make sure it exist
53+
$user = $this->createTestUser();
54+
$this->assertInstanceOf(User::class, User::withTrashed()->find($user->id));
55+
56+
//$user->activities - activities
57+
$this->ci->userActivityLogger->info("test", [
58+
'type' => 'group_create',
59+
'user_id' => $user->id
60+
]);
61+
$this->assertSame(1, $user->activities()->count());
62+
63+
//$user->passwordResets - password_resets
64+
$this->ci->repoPasswordReset->create($user, $this->ci->config['password_reset.timeouts.reset']);
65+
$this->assertSame(1, $user->passwordResets()->count());
66+
67+
//{no relations} - persistences
68+
$persistence = new Persistence([
69+
'user_id' => $user->id,
70+
'token' => '',
71+
'persistent_token' => '',
72+
'expires_at' => null
73+
]);
74+
$persistence->save();
75+
$this->assertSame(1, Persistence::where('user_id', $user->id)->count());
76+
77+
//$user->roles - role_users
78+
$role = $fm->create('UserFrosting\Sprinkle\Account\Database\Models\Role');
79+
$user->roles()->attach($role->id);
80+
$this->assertSame(1, $user->roles()->count());
81+
82+
//{no relations} - verification
83+
$this->ci->repoVerification->create($user, $this->ci->config['verification.timeout']);
84+
$this->assertSame(1, $this->ci->classMapper->staticMethod('verification', 'where', 'user_id', $user->id)->count());
85+
86+
// Force delete. Now user can't be found at all
87+
$this->assertTrue($user->delete(true));
88+
$this->assertNull(User::withTrashed()->find($user->id));
89+
90+
// Assert deletions worked
91+
$this->assertSame(0, $user->activities()->count());
92+
$this->assertSame(0, $user->passwordResets()->count());
93+
$this->assertSame(0, $user->roles()->count());
94+
$this->assertSame(0, Persistence::where('user_id', $user->id)->count());
95+
$this->assertSame(0, $this->ci->classMapper->staticMethod('verification', 'where', 'user_id', $user->id)->count());
96+
}
97+
}

app/sprinkles/account/tests/Unit/UserModelTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ public function testUserSoftDelete()
5454

5555
/**
5656
* Test user hard deletion.
57-
*
5857
*/
5958
public function testUserHardDelete()
6059
{

0 commit comments

Comments
 (0)