Files
myep/src/Security/EmployeeDomainMatcher.php
T

59 lines
1.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Security;
/**
* Decides whether an account belongs to a member of staff, by its email domain.
*
* BusPro has no CRM selection expressing "works here", so the email address is the only signal
* available. The domains are configuration (%employee_email_domains%) rather than a constant
* because they are deployment-specific, in the same way the brand hosts and the CRM selection ids
* are.
*
* Matching is exact on the domain part and never on a suffix: "mail.ep-reisen.de" and
* "notep-reisen.de" are not "ep-reisen.de". A suffix match here would hand ROLE_EMPLOYEE to
* anybody able to register a domain ending in the configured one.
*/
final class EmployeeDomainMatcher
{
/**
* @var string[]
*/
private readonly array $domains;
/**
* @param string[] $domains
*/
public function __construct(array $domains)
{
$this->domains = array_values(array_filter(array_map(
static fn (string $domain): string => strtolower(trim($domain, " \t\n\r\0\x0B.@")),
$domains,
)));
}
/**
* A malformed or missing identifier is simply not an employee. It must not throw: this runs
* inside the authentication path, where an exception would turn a bad address into a failed
* login rather than a login without the role.
*/
public function isEmployee(?string $email): bool
{
if (null === $email || [] === $this->domains) {
return false;
}
$position = strrpos($email, '@');
if (false === $position) {
return false;
}
$domain = strtolower(substr($email, $position + 1));
return \in_array($domain, $this->domains, true);
}
}