#2 API token authentication implemented. Login method implemented. Some refactoring. ApiTokenRepository::findUserByTokenKey() query bug fix.
This commit is contained in:
parent
84f2d5ece9
commit
b35da23e8e
|
@ -8,7 +8,7 @@ use Symfony\Component\HttpFoundation\{JsonResponse, Response};
|
|||
|
||||
abstract class AbstractApiController extends Controller
|
||||
{
|
||||
protected const DEFAULT_SERIALIZER_GROUPS = ['api_v1'];
|
||||
protected const DEFAULT_SERIALIZER_GROUPS = ['api'];
|
||||
|
||||
protected function createJsonResponse($data, array $groups = [], int $code = Response::HTTP_OK, string $message = null, string $status = ''): JsonResponse
|
||||
{
|
||||
|
|
|
@ -2,12 +2,42 @@
|
|||
|
||||
namespace App\Api\V1\Controller;
|
||||
|
||||
use App\Entity\{ApiToken, User};
|
||||
use App\Repository\{ApiTokenRepository, UserRepository};
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\{JsonResponse, Request};
|
||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||
|
||||
class SecurityController extends AbstractApiController
|
||||
{
|
||||
public function login(Request $request): JsonResponse
|
||||
{
|
||||
// @todo implement login procedure
|
||||
public function login(
|
||||
Request $request,
|
||||
EntityManagerInterface $em,
|
||||
UserRepository $userRepo,
|
||||
ApiTokenRepository $tokenRepo,
|
||||
UserPasswordEncoderInterface $passwordEncoder
|
||||
): JsonResponse {
|
||||
$username = $request->request->get('username');
|
||||
$password = $request->request->get('password');
|
||||
|
||||
/** @var User $user */
|
||||
if (null === $user = $userRepo->findOneBy(['username' => $username])) {
|
||||
return $this->createJsonResponse(null, [], JsonResponse::HTTP_UNAUTHORIZED, 'User not found');
|
||||
}
|
||||
|
||||
if (!$passwordEncoder->isPasswordValid($user, $password)) {
|
||||
return $this->createJsonResponse(null, [], JsonResponse::HTTP_UNAUTHORIZED, 'Invalid password');
|
||||
}
|
||||
|
||||
$apiToken = new ApiToken($user);
|
||||
$tokenRepo->add($apiToken);
|
||||
|
||||
try {
|
||||
$em->flush();
|
||||
} catch (\Exception $ex) {
|
||||
return $this->createJsonResponse(null, [], JsonResponse::HTTP_INTERNAL_SERVER_ERROR, 'Token persisting error');
|
||||
}
|
||||
|
||||
return $this->createJsonResponse($apiToken->getKey());
|
||||
}
|
||||
}
|
|
@ -15,28 +15,28 @@ class ApiResponse
|
|||
/**
|
||||
* @var int HTTP response status code
|
||||
*
|
||||
* @Groups({"api_v1"})
|
||||
* @Groups({"api"})
|
||||
*/
|
||||
private $code;
|
||||
|
||||
/**
|
||||
* @var string Status text: 'success' (1xx-3xx), 'error' (4xx), 'fail' (5xx) or 'unknown'
|
||||
*
|
||||
* @Groups({"api_v1"})
|
||||
* @Groups({"api"})
|
||||
*/
|
||||
private $status;
|
||||
|
||||
/**
|
||||
* @var string|null Used for 'fail' and 'error'
|
||||
*
|
||||
* @Groups({"api_v1"})
|
||||
* @Groups({"api"})
|
||||
*/
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* @var string|\object|array|null Response body. In case of 'error' or 'fail' contains cause or exception name.
|
||||
*
|
||||
* @Groups({"api_v1"})
|
||||
* @Groups({"api"})
|
||||
*/
|
||||
private $data;
|
||||
|
||||
|
|
|
@ -10,35 +10,35 @@ class ListPage
|
|||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Groups({"api_v1"})
|
||||
* @Serializer\Groups({"api"})
|
||||
*/
|
||||
private $numberOfPages;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Groups({"api_v1"})
|
||||
* @Serializer\Groups({"api"})
|
||||
*/
|
||||
private $currentPage;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Groups({"api_v1"})
|
||||
* @Serializer\Groups({"api"})
|
||||
*/
|
||||
private $numberOfResults;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Groups({"api_v1"})
|
||||
* @Serializer\Groups({"api"})
|
||||
*/
|
||||
private $maxPerPage;
|
||||
|
||||
/**
|
||||
* @var \Traversable
|
||||
*
|
||||
* @Serializer\Groups({"api_v1"})
|
||||
* @Serializer\Groups({"api"})
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @ORM\Table(name="api_tokens", schema="users")
|
||||
|
@ -21,6 +22,8 @@ class ApiToken
|
|||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Groups({"api", "api_v1_login"})
|
||||
*
|
||||
* @ORM\Id()
|
||||
* @ORM\Column(name="key", type="string", length=32)
|
||||
*/
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Repository;
|
|||
|
||||
use App\Entity\{ApiToken, User};
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Symfony\Bridge\Doctrine\RegistryInterface;
|
||||
|
||||
class ApiTokenRepository extends ServiceEntityRepository
|
||||
|
@ -20,9 +21,11 @@ class ApiTokenRepository extends ServiceEntityRepository
|
|||
|
||||
public function findUserByTokenKey(string $tokenKey): ?User
|
||||
{
|
||||
$qb = $this->createQueryBuilder('at');
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
$qb
|
||||
->select('at.user')
|
||||
->select('u')
|
||||
->from(User::class, 'u')
|
||||
->innerJoin(ApiToken::class, 'at', Join::WITH, 'at.user = u')
|
||||
->where('at.key = :tokenKey')
|
||||
->setParameter('tokenKey', $tokenKey)
|
||||
;
|
||||
|
|
Loading…
Reference in a new issue