<?php
namespace MedBrief\MSR\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use MedBrief\MSR\Controller\Firm\RotateSecret;
use MedBrief\MSR\Repository\FirmRepository;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* A Firm represents an over-arching company or business that comprises one or more
* Client Areas - referred to as Clients on the frontend and {@see Accounts} in the
* code - and is unique in that it has the capability to authenticate itself for
* Machine-to-Machine transactions such as consuming the external API.
*
* This is currently a very rudimentary entity but at a later point we can look at
* migrating some common data shared between multiple client areas to a single source
* of truth here within a Firm.
*
* @author S Honour <[email protected]>
*
* @ApiResource(
* itemOperations={
* "rotate_secret"={
* "method"="POST",
* "path"="/firm/rotate_secret",
* "controller"=RotateSecret::class,
* "deserialize"=false,
* "defaults"={"_api_receive"=false},
* "openapi_context"={
* "summary"="Rotate a Client Secret.",
* "description"="Rotates a client secret for the authenticated API user.",
* "responses"={
* "200"={
* "description"="The new client secret"
* },
* "400"={
* "description"="The authenticated user is not a valid Firm and cannot utilise this endpoint"
* }
* }
* }
* }
* }
* )
*
* @ORM\Entity(repositoryClass=FirmRepository::class)
*/
class Firm implements UserInterface
{
/**
* @ORM\Column(name="id", type="uuid")
*
* @ORM\Id
*
* @ORM\GeneratedValue(strategy="CUSTOM")
*
* @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
*/
private ?UuidInterface $id = null;
/**
* @ORM\Column
*/
private string $name;
/**
* @Gedmo\Slug(fields={"name"})
*
* @ORM\Column(length=128, unique=true)
*/
private ?string $slug;
/**
* @ORM\OneToMany(targetEntity=Account::class, mappedBy="firm", cascade={"persist"})
*/
private $clientAreas;
/**
* @ORM\Column
*/
private array $roles = [];
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private ?string $auth0ClientId;
public function __construct()
{
$this->clientAreas = new ArrayCollection();
}
/**
* @return UuidInterface|null
*/
public function getId(): ?UuidInterface
{
return $this->id;
}
/**
* @inheritDoc
*/
public function getRoles()
{
return $this->roles;
}
/**
* A Firm does not have an associated password. Instead, it is authenticated via
* Bearer tokens through an external authentication system.
*/
public function getPassword()
{
return null;
}
/**
* As a Firm does not have a password, there is no need for a salt either
*/
public function getSalt()
{
return null;
}
/**
* @inheritDoc
*/
public function getUsername()
{
return $this->auth0ClientId;
}
/**
* Imports antigravity
*/
public function eraseCredentials()
{
// https://xkcd.com/353/
}
/**
* @return Collection<int, Account>
*/
public function getClientAreas(): Collection
{
return $this->clientAreas;
}
public function addClientArea(Account $clientArea): self
{
if (!$this->clientAreas->contains($clientArea)) {
$this->clientAreas[] = $clientArea;
$clientArea->setFirm($this);
}
return $this;
}
public function removeClientArea(Account $clientArea): self
{
if ($this->clientAreas->removeElement($clientArea)) {
// set the owning side to null (unless already changed)
if ($clientArea->getFirm() === $this) {
$clientArea->setFirm(null);
}
}
return $this;
}
public function addRole(string $role): self
{
if (!in_array($role, $this->roles)) {
$this->roles[] = $role;
}
return $this;
}
public function removeRole(string $role): self
{
if (in_array($role, $this->roles)) {
$key = array_search($role, $this->roles);
unset($this->roles[$key]);
}
return $this;
}
public function getAuth0ClientId(): ?string
{
return $this->auth0ClientId;
}
public function setAuth0ClientId(?string $auth0ClientId): self
{
$this->auth0ClientId = $auth0ClientId;
return $this;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @param string $name
*
* @return Firm
*/
public function setName(string $name): Firm
{
$this->name = $name;
return $this;
}
/**
* @return string|null
*/
public function getSlug(): ?string
{
return $this->slug;
}
/**
* @param string|null $slug
*
* @return Firm
*/
public function setSlug(?string $slug): Firm
{
$this->slug = $slug;
return $this;
}
public function isApiEnabled(): bool
{
return (bool) $this->auth0ClientId;
}
}