<?php
namespace BigIdea\IdentityBundle\Entity;
use BigIdea\IdentityBundle\Service\TokenValueGenerator;
use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity]
#[ORM\Table(name: "identity_team_mates")]
/** @final */ class TeamMate implements UserInterface, PasswordAuthenticatedUserInterface
{
public const ROLE_ALLOWED_PASSWORD = 'ROLE_ALLOWED_PASSWORD';
#[ORM\Id, ORM\Column(name: "id", type: "integer"), ORM\GeneratedValue(strategy: "AUTO")]
private int $id;
#[ORM\Column(name: "sso_identifier", type: "string", length: 64, unique: true)]
private string $ssoIdentifier;
#[ORM\Column(name: "email", type: "string", length: 64)]
private string $email;
#[ORM\Column(name: "name", type: "string", length: 32)]
private string $name;
#[ORM\Column(name: "roles", type: "simple_array")]
private array $roles;
#[ORM\Column(name: "local_password", type: "string", length: 64, nullable: true)]
private ?string $localPassword;
#[ORM\Column(name: "created_at", type: "datetimetz_immutable")]
private DateTimeImmutable $createdAt;
#[ORM\Column(name: "updated_at", type: "datetimetz_immutable")]
private DateTimeImmutable $updatedAt;
#[ORM\OneToMany(mappedBy: "owner", targetEntity: PersonalAccessToken::class, cascade: ["all"], orphanRemoval: true)]
private iterable $accessTokens;
public static function ssoUser(string $ssoIdentifier, string $email, string $name, array $roles, DateTimeImmutable $createdAt): self
{
return new self($ssoIdentifier, $email, $name, $roles, $createdAt);
}
private function __construct(string $ssoIdentifier, string $email, string $name, array $roles, DateTimeImmutable $createdAt)
{
$this->ssoIdentifier = $ssoIdentifier;
$this->email = $email;
$this->name = $name;
$this->roles = $roles;
$this->localPassword = null;
$this->createdAt = $createdAt;
$this->updatedAt = $createdAt;
$this->accessTokens = new ArrayCollection();
}
public function update(string $email, string $name, array $roles, DateTimeImmutable $updatedAt): void
{
$this->email = $email;
$this->name = $name;
$this->roles = $roles;
$this->updatedAt = $updatedAt;
}
public function id(): int
{
return $this->id;
}
public function eraseCredentials(): void
{
}
public function getUserIdentifier(): string
{
return $this->ssoIdentifier;
}
public function getUsername(): string
{
return $this->email;
}
public function getSalt(): ?string
{
return null;
}
public function getRoles(): array
{
return $this->roles;
}
public function isAllowedPasswordAuthentication(): bool
{
return in_array(self::ROLE_ALLOWED_PASSWORD, $this->roles, true);
}
public function getPassword(): ?string
{
if (!$this->isAllowedPasswordAuthentication()) {
return null;
}
return $this->localPassword;
}
public function changeLocalPassword(string $plainPassword, UserPasswordHasherInterface $hasher): void
{
if (!$this->isAllowedPasswordAuthentication()) {
throw new \DomainException(sprintf('In order to set local password user must have role %s.', self::ROLE_ALLOWED_PASSWORD));
}
$this->localPassword = $hasher->hashPassword($this, $plainPassword);
}
public function createAccessToken(string $displayName, ?DateTimeImmutable $notBefore, ?DateTimeImmutable $expiry, TokenValueGenerator $generator): PersonalAccessToken
{
$accessToken = new PersonalAccessToken($this, $generator->generate(), $displayName, $notBefore, $expiry);
$this->accessTokens->add($accessToken);
return $accessToken;
}
}