#2 API token authentication implemented. Login method implemented. Some refactoring. ApiTokenRepository::findUserByTokenKey() query bug fix.

This commit is contained in:
Alexey Skobkin 2018-06-27 01:28:42 +03:00
parent 84f2d5ece9
commit b35da23e8e
6 changed files with 51 additions and 15 deletions

View File

@ -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
{

View File

@ -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());
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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)
*/

View File

@ -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)
;