|
2 | 2 |
|
3 | 3 | declare(strict_types=1); |
4 | 4 | use Carbon\CarbonImmutable; |
| 5 | +use Contexts\Authorization\Domain\Role\Models\RoleId; |
5 | 6 | use Contexts\Authorization\Domain\UserIdentity\Exceptions\UserNotFoundException; |
6 | 7 | use Contexts\Authorization\Domain\UserIdentity\Models\Email; |
7 | 8 | use Contexts\Authorization\Domain\UserIdentity\Models\Password; |
| 9 | +use Contexts\Authorization\Domain\UserIdentity\Models\RoleIdCollection; |
8 | 10 | use Contexts\Authorization\Domain\UserIdentity\Models\UserId; |
9 | 11 | use Contexts\Authorization\Domain\UserIdentity\Models\UserIdentity; |
10 | 12 | use Contexts\Authorization\Domain\UserIdentity\Models\UserStatus; |
| 13 | +use Contexts\Authorization\Infrastructure\Records\RoleRecord; |
11 | 14 | use Contexts\Authorization\Infrastructure\Records\UserRecord; |
12 | 15 | use Contexts\Authorization\Infrastructure\Repositories\UserRepository; |
13 | 16 |
|
|
251 | 254 | expect($retrievedUser->getPassword()->verify('oldpassword123'))->toBeFalse(); |
252 | 255 | expect($retrievedUser->getPassword()->verify('newpassword123'))->toBeTrue(); |
253 | 256 | }); |
| 257 | + |
| 258 | +it('can sync user roles when updating user', function () { |
| 259 | + // Create a test user in the database |
| 260 | + $email = new Email('role-test@example.com'); |
| 261 | + $password = Password::createFromPlainText('password123'); |
| 262 | + $createdUser = UserIdentity::create(UserId::null(), $email, $password, 'Role Test User'); |
| 263 | + $userRepository = new UserRepository(); |
| 264 | + $savedUser = $userRepository->create($createdUser); |
| 265 | + |
| 266 | + // Create test roles |
| 267 | + $role1 = RoleRecord::create(['name' => 'Editor', 'description' => 'Editor role']); |
| 268 | + $role2 = RoleRecord::create(['name' => 'Author', 'description' => 'Author role']); |
| 269 | + $role3 = RoleRecord::create(['name' => 'Admin', 'description' => 'Admin role']); |
| 270 | + |
| 271 | + // Create a RoleIdCollection with the first two roles |
| 272 | + $roleIds = new RoleIdCollection([ |
| 273 | + RoleId::fromInt($role1->id), |
| 274 | + RoleId::fromInt($role2->id) |
| 275 | + ]); |
| 276 | + |
| 277 | + // Retrieve the user and assign roles |
| 278 | + $retrievedUser = $userRepository->getById($savedUser->getId()); |
| 279 | + $retrievedUser->syncRoles($roleIds); |
| 280 | + |
| 281 | + // Update the user with the roles |
| 282 | + $updatedUser = $userRepository->update($retrievedUser); |
| 283 | + |
| 284 | + // Verify the roles were assigned correctly - use query builder to avoid ambiguous column issue |
| 285 | + $userRoles = \DB::table('pivot_user_role') |
| 286 | + ->where('user_id', $updatedUser->getId()->getValue()) |
| 287 | + ->pluck('role_id') |
| 288 | + ->toArray(); |
| 289 | + |
| 290 | + expect(count($userRoles))->toBe(2); |
| 291 | + expect($userRoles)->toContain($role1->id, $role2->id); |
| 292 | + |
| 293 | + // Now update with a different set of roles |
| 294 | + $newRoleIds = new RoleIdCollection([ |
| 295 | + RoleId::fromInt($role2->id), |
| 296 | + RoleId::fromInt($role3->id) |
| 297 | + ]); |
| 298 | + |
| 299 | + $updatedUser->syncRoles($newRoleIds); |
| 300 | + $userRepository->update($updatedUser); |
| 301 | + |
| 302 | + // Verify the roles were updated correctly |
| 303 | + $userRoles = \DB::table('pivot_user_role') |
| 304 | + ->where('user_id', $updatedUser->getId()->getValue()) |
| 305 | + ->pluck('role_id') |
| 306 | + ->toArray(); |
| 307 | + |
| 308 | + expect(count($userRoles))->toBe(2); |
| 309 | + expect($userRoles)->toContain($role2->id, $role3->id); |
| 310 | + expect($userRoles)->not->toContain($role1->id); |
| 311 | +}); |
| 312 | + |
| 313 | +it('can sync user roles to empty collection', function () { |
| 314 | + // Create a test user in the database |
| 315 | + $email = new Email('empty-roles@example.com'); |
| 316 | + $password = Password::createFromPlainText('password123'); |
| 317 | + $createdUser = UserIdentity::create(UserId::null(), $email, $password, 'No Roles User'); |
| 318 | + $userRepository = new UserRepository(); |
| 319 | + $savedUser = $userRepository->create($createdUser); |
| 320 | + |
| 321 | + // Create roles and assign them |
| 322 | + $role1 = RoleRecord::create(['name' => 'Manager', 'description' => 'Manager role']); |
| 323 | + $role2 = RoleRecord::create(['name' => 'Staff', 'description' => 'Staff role']); |
| 324 | + |
| 325 | + $roleIds = new RoleIdCollection([ |
| 326 | + RoleId::fromInt($role1->id), |
| 327 | + RoleId::fromInt($role2->id) |
| 328 | + ]); |
| 329 | + |
| 330 | + // Assign roles and update |
| 331 | + $retrievedUser = $userRepository->getById($savedUser->getId()); |
| 332 | + $retrievedUser->syncRoles($roleIds); |
| 333 | + $userRepository->update($retrievedUser); |
| 334 | + |
| 335 | + // Verify roles were assigned |
| 336 | + $userRoles = \DB::table('pivot_user_role') |
| 337 | + ->where('user_id', $retrievedUser->getId()->getValue()) |
| 338 | + ->count(); |
| 339 | + expect($userRoles)->toBe(2); |
| 340 | + |
| 341 | + // Now remove all roles |
| 342 | + $emptyRoleIds = new RoleIdCollection([]); |
| 343 | + $retrievedUser->syncRoles($emptyRoleIds); |
| 344 | + $userRepository->update($retrievedUser); |
| 345 | + |
| 346 | + // Verify all roles were removed |
| 347 | + $userRoles = \DB::table('pivot_user_role') |
| 348 | + ->where('user_id', $retrievedUser->getId()->getValue()) |
| 349 | + ->count(); |
| 350 | + expect($userRoles)->toBe(0); |
| 351 | +}); |
| 352 | + |
| 353 | +it('preserves existing user roles when updating other attributes', function () { |
| 354 | + // Create a test user in the database |
| 355 | + $email = new Email('preserve-roles@example.com'); |
| 356 | + $password = Password::createFromPlainText('password123'); |
| 357 | + $createdUser = UserIdentity::create(UserId::null(), $email, $password, 'Preserve Roles User'); |
| 358 | + $userRepository = new UserRepository(); |
| 359 | + $savedUser = $userRepository->create($createdUser); |
| 360 | + |
| 361 | + // Create roles and assign them |
| 362 | + $role1 = RoleRecord::create(['name' => 'Subscriber', 'description' => 'Subscriber role']); |
| 363 | + $role2 = RoleRecord::create(['name' => 'Member', 'description' => 'Member role']); |
| 364 | + |
| 365 | + $roleIds = new RoleIdCollection([ |
| 366 | + RoleId::fromInt($role1->id), |
| 367 | + RoleId::fromInt($role2->id) |
| 368 | + ]); |
| 369 | + |
| 370 | + // Assign roles |
| 371 | + $user = $userRepository->getById($savedUser->getId()); |
| 372 | + $user->syncRoles($roleIds); |
| 373 | + $userRepository->update($user); |
| 374 | + |
| 375 | + // Get fresh instance with roles loaded |
| 376 | + $user = $userRepository->getById($savedUser->getId()); |
| 377 | + |
| 378 | + // Update only the user's display name |
| 379 | + $user->modify(null, 'Updated Display Name', null); |
| 380 | + $userRepository->update($user); |
| 381 | + |
| 382 | + // Verify roles are still present after the update |
| 383 | + $userRecord = UserRecord::find($user->getId()->getValue()); |
| 384 | + expect($userRecord->display_name)->toBe('Updated Display Name'); |
| 385 | + |
| 386 | + $userRoles = \DB::table('pivot_user_role') |
| 387 | + ->where('user_id', $user->getId()->getValue()) |
| 388 | + ->pluck('role_id') |
| 389 | + ->toArray(); |
| 390 | + |
| 391 | + expect(count($userRoles))->toBe(2); |
| 392 | + expect($userRoles)->toContain($role1->id, $role2->id); |
| 393 | +}); |
| 394 | + |
| 395 | +it('updates roles correctly even with empty initial role collection', function () { |
| 396 | + // Create a test user without roles |
| 397 | + $email = new Email('no-roles@example.com'); |
| 398 | + $password = Password::createFromPlainText('password123'); |
| 399 | + $createdUser = UserIdentity::create(UserId::null(), $email, $password, 'No Initial Roles'); |
| 400 | + $userRepository = new UserRepository(); |
| 401 | + $savedUser = $userRepository->create($createdUser); |
| 402 | + |
| 403 | + // Create a role to assign |
| 404 | + $role = RoleRecord::create(['name' => 'Guest', 'description' => 'Guest role']); |
| 405 | + |
| 406 | + // Assign role to user that previously had no roles |
| 407 | + $user = $userRepository->getById($savedUser->getId()); |
| 408 | + $roleIds = new RoleIdCollection([RoleId::fromInt($role->id)]); |
| 409 | + $user->syncRoles($roleIds); |
| 410 | + $userRepository->update($user); |
| 411 | + |
| 412 | + // Verify role was assigned |
| 413 | + $userRoles = \DB::table('pivot_user_role') |
| 414 | + ->where('user_id', $user->getId()->getValue()) |
| 415 | + ->count(); |
| 416 | + expect($userRoles)->toBe(1); |
| 417 | + |
| 418 | + $roleId = \DB::table('pivot_user_role') |
| 419 | + ->where('user_id', $user->getId()->getValue()) |
| 420 | + ->value('role_id'); |
| 421 | + expect($roleId)->toBe($role->id); |
| 422 | +}); |
0 commit comments