-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUserRepository.php
More file actions
86 lines (75 loc) · 2.97 KB
/
Copy pathUserRepository.php
File metadata and controls
86 lines (75 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<?php
namespace App\Repository;
use App\Entity\User;
use App\Enum\UserStatus;
use App\Security\EmailDomain;
use App\Security\Roles;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
/**
* @extends ServiceEntityRepository<User>
*/
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
/**
* Used to upgrade (rehash) the user's password automatically over time.
*/
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
}
$user->setPassword($newHashedPassword);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
}
/**
* Find users visible to the acting user, optionally filtered by status.
*
* Decision flow mirrors {@see \App\Security\Voter\ManageUserVoter}:
*
* 1. Site admins (`ROLE_ADMIN`) see every user.
* 2. Domain managers (`ROLE_DOMAIN_MANAGER` without admin) see only
* users whose email domain matches their own.
* 3. Everyone else gets an empty result — the caller must still
* gate the route via `IsGranted` first, this is a belt-and-
* braces filter for query-level scoping.
*
* @param User $actor the acting user (whose role + email determine the scope)
* @param UserStatus|null $statusFilter optional status filter for #64's approval-queue view
*
* @return list<User> users sorted by id ascending
*/
public function findVisibleTo(User $actor, ?UserStatus $statusFilter = null): array
{
$qb = $this->createQueryBuilder('u')
->orderBy('u.id', 'ASC');
$roles = $actor->getRoles();
if (\in_array(Roles::ADMIN, $roles, true)) {
// Admin sees everyone — no domain filter.
} elseif (\in_array(Roles::DOMAIN_MANAGER, $roles, true)) {
$domain = EmailDomain::of($actor);
if (null === $domain) {
return [];
}
$qb->andWhere('LOWER(u.email) LIKE :domainSuffix')
->setParameter('domainSuffix', '%@'.$domain);
} else {
return [];
}
if (null !== $statusFilter) {
$qb->andWhere('u.status = :status')
->setParameter('status', $statusFilter->value);
}
/** @var list<User> $result */
$result = $qb->getQuery()->getResult();
return $result;
}
}