mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-24 13:49:03 +03:00
Implemented mechanism to add/remove roles from API keys
This commit is contained in:
parent
01b3c504f8
commit
041f231ff2
4 changed files with 82 additions and 5 deletions
|
@ -38,5 +38,8 @@ return static function (ClassMetadata $metadata, array $emConfig): void {
|
||||||
|
|
||||||
$builder->createOneToMany('roles', ApiKeyRole::class)
|
$builder->createOneToMany('roles', ApiKeyRole::class)
|
||||||
->mappedBy('apiKey')
|
->mappedBy('apiKey')
|
||||||
|
->setIndexBy('roleName')
|
||||||
|
->cascadePersist()
|
||||||
|
->orphanRemoval()
|
||||||
->build();
|
->build();
|
||||||
};
|
};
|
||||||
|
|
39
module/Rest/src/ApiKey/Model/RoleDefinition.php
Normal file
39
module/Rest/src/ApiKey/Model/RoleDefinition.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Rest\ApiKey\Model;
|
||||||
|
|
||||||
|
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
||||||
|
|
||||||
|
final class RoleDefinition
|
||||||
|
{
|
||||||
|
private string $roleName;
|
||||||
|
private array $meta;
|
||||||
|
|
||||||
|
private function __construct(string $roleName, array $meta)
|
||||||
|
{
|
||||||
|
$this->roleName = $roleName;
|
||||||
|
$this->meta = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function forAuthoredShortUrls(): self
|
||||||
|
{
|
||||||
|
return new self(Role::AUTHORED_SHORT_URLS, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function forDomain(string $domainId): self
|
||||||
|
{
|
||||||
|
return new self(Role::DOMAIN_SPECIFIC, ['domain_id' => $domainId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function roleName(): string
|
||||||
|
{
|
||||||
|
return $this->roleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function meta(): array
|
||||||
|
{
|
||||||
|
return $this->meta;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,10 +7,12 @@ namespace Shlinkio\Shlink\Rest\Entity;
|
||||||
use Cake\Chronos\Chronos;
|
use Cake\Chronos\Chronos;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
use Exception;
|
||||||
use Happyr\DoctrineSpecification\Spec;
|
use Happyr\DoctrineSpecification\Spec;
|
||||||
use Happyr\DoctrineSpecification\Specification\Specification;
|
use Happyr\DoctrineSpecification\Specification\Specification;
|
||||||
use Ramsey\Uuid\Uuid;
|
use Ramsey\Uuid\Uuid;
|
||||||
use Shlinkio\Shlink\Common\Entity\AbstractEntity;
|
use Shlinkio\Shlink\Common\Entity\AbstractEntity;
|
||||||
|
use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition;
|
||||||
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
||||||
|
|
||||||
class ApiKey extends AbstractEntity
|
class ApiKey extends AbstractEntity
|
||||||
|
@ -21,12 +23,20 @@ class ApiKey extends AbstractEntity
|
||||||
/** @var Collection|ApiKeyRole[] */
|
/** @var Collection|ApiKeyRole[] */
|
||||||
private Collection $roles;
|
private Collection $roles;
|
||||||
|
|
||||||
public function __construct(?Chronos $expirationDate = null)
|
/**
|
||||||
|
* @param RoleDefinition[] $roleDefinitions
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct(?Chronos $expirationDate = null, array $roleDefinitions = [])
|
||||||
{
|
{
|
||||||
$this->key = Uuid::uuid4()->toString();
|
$this->key = Uuid::uuid4()->toString();
|
||||||
$this->expirationDate = $expirationDate;
|
$this->expirationDate = $expirationDate;
|
||||||
$this->enabled = true;
|
$this->enabled = true;
|
||||||
$this->roles = new ArrayCollection();
|
$this->roles = new ArrayCollection();
|
||||||
|
|
||||||
|
foreach ($roleDefinitions as $roleDefinition) {
|
||||||
|
$this->registerRole($roleDefinition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExpirationDate(): ?Chronos
|
public function getExpirationDate(): ?Chronos
|
||||||
|
@ -81,13 +91,33 @@ class ApiKey extends AbstractEntity
|
||||||
|
|
||||||
public function hasRole(string $roleName): bool
|
public function hasRole(string $roleName): bool
|
||||||
{
|
{
|
||||||
return $this->roles->exists(fn ($key, ApiKeyRole $role) => $role->name() === $roleName);
|
return $this->roles->containsKey($roleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRoleMeta(string $roleName): array
|
public function getRoleMeta(string $roleName): array
|
||||||
{
|
{
|
||||||
/** @var ApiKeyRole|false $role */
|
/** @var ApiKeyRole|null $role */
|
||||||
$role = $this->roles->filter(fn (ApiKeyRole $role) => $role->name() === $roleName)->first();
|
$role = $this->roles->get($roleName);
|
||||||
return ! $role ? [] : $role->meta();
|
return $role === null ? [] : $role->meta();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function registerRole(RoleDefinition $roleDefinition): void
|
||||||
|
{
|
||||||
|
$roleName = $roleDefinition->roleName();
|
||||||
|
$meta = $roleDefinition->meta();
|
||||||
|
|
||||||
|
if ($this->hasRole($roleName)) {
|
||||||
|
/** @var ApiKeyRole $role */
|
||||||
|
$role = $this->roles->get($roleName);
|
||||||
|
$role->updateMeta($meta);
|
||||||
|
} else {
|
||||||
|
$role = new ApiKeyRole($roleDefinition->roleName(), $roleDefinition->meta(), $this);
|
||||||
|
$this->roles[$roleName] = $role;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeRole(string $roleName): void
|
||||||
|
{
|
||||||
|
$this->roles->remove($roleName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,11 @@ class ApiKeyRole extends AbstractEntity
|
||||||
return $this->meta;
|
return $this->meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function updateMeta(array $newMeta): void
|
||||||
|
{
|
||||||
|
$this->meta = $newMeta;
|
||||||
|
}
|
||||||
|
|
||||||
public function apiKey(): ApiKey
|
public function apiKey(): ApiKey
|
||||||
{
|
{
|
||||||
return $this->apiKey;
|
return $this->apiKey;
|
||||||
|
|
Loading…
Reference in a new issue