94 lines
2.8 KiB
PHP
94 lines
2.8 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controller\Api;
|
|
|
|
use Authentication\Authenticator\FormAuthenticator;
|
|
use Cake\Core\Configure;
|
|
use Cake\Event\EventInterface;
|
|
use Cake\Http\Exception\UnauthorizedException;
|
|
use Cake\Http\Response;
|
|
use Cake\I18n\DateTime;
|
|
use Firebase\JWT\JWT;
|
|
|
|
/**
|
|
* Authentication endpoints: login (JWT issue) and own profile.
|
|
*/
|
|
class AuthController extends ApiController
|
|
{
|
|
/**
|
|
* @param \Cake\Event\EventInterface<\Cake\Controller\Controller> $event Event
|
|
* @return void
|
|
*/
|
|
public function beforeFilter(EventInterface $event): void
|
|
{
|
|
parent::beforeFilter($event);
|
|
$this->Authentication->allowUnauthenticated(['login']);
|
|
}
|
|
|
|
/**
|
|
* POST /api/auth/login - exchange email + password for a JWT.
|
|
*
|
|
* @return \Cake\Http\Response
|
|
*/
|
|
public function login(): Response
|
|
{
|
|
$this->request->allowMethod(['post']);
|
|
|
|
// A token is issued only for email/password credentials, never in exchange for another token.
|
|
$result = $this->Authentication->getResult();
|
|
$provider = $this->Authentication->getAuthenticationService()->getAuthenticationProvider();
|
|
if ($result === null || !$result->isValid() || !$provider instanceof FormAuthenticator) {
|
|
throw new UnauthorizedException('Invalid email or password.');
|
|
}
|
|
|
|
/** @var \App\Model\Entity\User $user */
|
|
$user = $result->getData();
|
|
$user->last_login = DateTime::now();
|
|
$this->fetchTable('Users')->saveOrFail($user);
|
|
|
|
$ttl = (int)Configure::read('Jwt.ttl', 3600);
|
|
$now = time();
|
|
$token = JWT::encode([
|
|
'iss' => 'testRestApi',
|
|
'sub' => $user->id,
|
|
'role' => $user->role,
|
|
'iat' => $now,
|
|
'exp' => $now + $ttl,
|
|
], (string)Configure::read('Jwt.secret'), 'HS256');
|
|
|
|
return $this->respond([
|
|
'token' => $token,
|
|
'token_type' => 'Bearer',
|
|
'expires_in' => $ttl,
|
|
'user' => $user,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* GET /api/auth/me - current user's profile.
|
|
* PUT|PATCH /api/auth/me - update own profile (name, email, password).
|
|
*
|
|
* @return \Cake\Http\Response
|
|
*/
|
|
public function me(): Response
|
|
{
|
|
$this->request->allowMethod(['get', 'put', 'patch']);
|
|
$usersTable = $this->fetchTable('Users');
|
|
$user = $usersTable->get($this->currentUser()->id);
|
|
|
|
if ($this->request->is('get')) {
|
|
return $this->respond($user);
|
|
}
|
|
|
|
$user = $usersTable->patchEntity($user, (array)$this->request->getData(), [
|
|
'fields' => ['email', 'password', 'first_name', 'last_name'],
|
|
]);
|
|
if (!$usersTable->save($user)) {
|
|
return $this->respondValidationError($user);
|
|
}
|
|
|
|
return $this->respond($user);
|
|
}
|
|
}
|