Added API endpoint to get info about the API token currently used to authenticate the user

This commit is contained in:
Jan Böhmer 2023-08-17 00:36:25 +02:00
parent 8dad143f8d
commit 040e86ea6d
2 changed files with 72 additions and 0 deletions

View file

@ -23,18 +23,34 @@ declare(strict_types=1);
namespace App\Entity\UserSystem; namespace App\Entity\UserSystem;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Serializer\Filter\PropertyFilter;
use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractNamedDBElement;
use App\Entity\Base\TimestampTrait; use App\Entity\Base\TimestampTrait;
use App\Repository\UserSystem\ApiTokenRepository; use App\Repository\UserSystem\ApiTokenRepository;
use App\State\CurrentApiTokenProvider;
use App\State\PartDBInfoProvider;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotBlank;
#[ORM\Entity(repositoryClass: ApiTokenRepository::class)] #[ORM\Entity(repositoryClass: ApiTokenRepository::class)]
#[ORM\Table(name: 'api_tokens')] #[ORM\Table(name: 'api_tokens')]
#[ORM\HasLifecycleCallbacks] #[ORM\HasLifecycleCallbacks]
#[UniqueEntity(fields: ['name', 'user'])] #[UniqueEntity(fields: ['name', 'user'])]
#[ApiResource(
uriTemplate: '/current.{_format}',
description: 'A token used to authenticate API requests.',
operations: [new Get(openapiContext: ['summary' => 'Get information about the API token that is currently used.'])],
normalizationContext: ['groups' => ['token:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'],
provider: CurrentApiTokenProvider::class,
)]
#[ApiFilter(PropertyFilter::class)]
class ApiToken class ApiToken
{ {
@ -47,21 +63,26 @@ class ApiToken
#[ORM\Column(type: Types::STRING)] #[ORM\Column(type: Types::STRING)]
#[NotBlank] #[NotBlank]
#[Groups('token:read')]
protected string $name = ''; protected string $name = '';
#[ORM\ManyToOne(inversedBy: 'api_tokens')] #[ORM\ManyToOne(inversedBy: 'api_tokens')]
#[Groups('token:read')]
private ?User $user = null; private ?User $user = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
#[Groups('token:read')]
private ?\DateTimeInterface $valid_until = null; private ?\DateTimeInterface $valid_until = null;
#[ORM\Column(length: 68, unique: true)] #[ORM\Column(length: 68, unique: true)]
private string $token; private string $token;
#[ORM\Column(type: Types::SMALLINT, enumType: ApiTokenLevel::class)] #[ORM\Column(type: Types::SMALLINT, enumType: ApiTokenLevel::class)]
#[Groups('token:read')]
private ApiTokenLevel $level = ApiTokenLevel::READ_ONLY; private ApiTokenLevel $level = ApiTokenLevel::READ_ONLY;
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
#[Groups('token:read')]
private ?\DateTimeInterface $last_time_used = null; private ?\DateTimeInterface $last_time_used = null;
public function __construct(ApiTokenType $tokenType = ApiTokenType::PERSONAL_ACCESS_TOKEN) public function __construct(ApiTokenType $tokenType = ApiTokenType::PERSONAL_ACCESS_TOKEN)

View file

@ -0,0 +1,51 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Serializer\Filter\PropertyFilter;
use ApiPlatform\State\ProviderInterface;
use App\Security\ApiTokenAuthenticatedToken;
use Symfony\Bundle\SecurityBundle\Security;
class CurrentApiTokenProvider implements ProviderInterface
{
public function __construct(private readonly Security $security)
{
}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
$securityToken = $this->security->getToken();
if (!$securityToken instanceof ApiTokenAuthenticatedToken) {
return null;
}
return $securityToken->getApiToken();
}
}