Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Domain/ADR/Input.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ public function __invoke(RequestInterface $request): array
$query = $request->getQuery();
/** @var TRequestQuery $post */
$post = $request->getPost();
/** @var TRequestQuery $put */
$put = $request->getPut();

return array_merge($query, $post);
return array_merge($query, $post, $put);
}
}
67 changes: 66 additions & 1 deletion src/Domain/ADR/InputTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,75 @@
* email?: string,
* password?: string
* }
*
* @phpstan-type TLogoutInput array{
* token?: string
* }
*
* @phpstan-type TRefreshInput array{
* token?: string
* }
*
* @phpstan-type TUserInput array{
* userId?: int
* id?: int,
* status?: int,
* email?: string,
* password?: string,
* namePrefix?: string,
* nameFirst?: string,
* nameMiddle?: string,
* nameLast?: string,
* nameSuffix?: string,
* issuer?: string,
* tokenPassword?: string,
* tokenId?: string,
* preferences?: string,
* createdDate?: string,
* createdUserId?: int,
* updatedDate?: string,
* updatedUserId?: int,
* }
*
* @phpstan-type TUserSanitizedInsertInput array{
* status: int,
* email: string,
* password: string,
* namePrefix: string,
* nameFirst: string,
* nameMiddle: string,
* nameLast: string,
* nameSuffix: string,
* issuer: string,
* tokenPassword: string,
* tokenId: string,
* preferences: string,
* createdDate: string,
* createdUserId: int,
* updatedDate: string,
* updatedUserId: int,
* }
*
* @phpstan-type TUserSanitizedUpdateInput array{
* id: int,
* status: int,
* email: string,
* password: string,
* namePrefix: string,
* nameFirst: string,
* nameMiddle: string,
* nameLast: string,
* nameSuffix: string,
* issuer: string,
* tokenPassword: string,
* tokenId: string,
* preferences: string,
* updatedDate: string,
* updatedUserId: int,
* }
*
* @phpstan-type TRequestQuery array<array-key, bool|int|string>
*
* @phpstan-type TValidationErrors array<int, array<int, string>>
*/
final class InputTypes
{
Expand Down
44 changes: 43 additions & 1 deletion src/Domain/Components/Cache/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Phalcon\Api\Domain\Components\Constants\Dates;
use Phalcon\Api\Domain\Components\DataSource\User\UserTransport;
use Phalcon\Api\Domain\Components\Env\EnvManager;
use Phalcon\Cache\Adapter\Redis;
use Phalcon\Cache\Cache as PhalconCache;
use Psr\SimpleCache\InvalidArgumentException;

Expand Down Expand Up @@ -54,13 +55,54 @@ class Cache extends PhalconCache
*/
public function getCacheTokenKey(UserTransport $domainUser, string $token): string
{
$tokenString = '';
if (true !== empty($token)) {
$tokenString = sha1($token);
}

return sprintf(
self::MASK_TOKEN_USER,
$domainUser->getId(),
sha1($token)
$tokenString
);
}

/**
* @param EnvManager $env
* @param UserTransport $domainUser
*
* @return bool
* @throws InvalidArgumentException
*/
public function invalidateForUser(
EnvManager $env,
UserTransport $domainUser
): bool {
/**
* We could store the tokens in the database but this way is faster
* and Redis also has a TTL which auto expires elements.
*
* To get all the keys for a user, we use the underlying adapter
* of the cache which is Redis and call the `getKeys()` on it. The
* keys will come back with the prefix defined in the adapter. In order
* to delete them, we need to remove the prefix because `delete()` will
* automatically prepend each key with it.
*/
/** @var Redis $redis */
$redis = $this->getAdapter();
$pattern = $this->getCacheTokenKey($domainUser, '');
$keys = $redis->getKeys($pattern);
/** @var string $prefix */
$prefix = $env->get('CACHE_PREFIX', '-rest-', 'string');
$newKeys = [];
/** @var string $key */
foreach ($keys as $key) {
$newKeys[] = str_replace($prefix, '', $key);
}

return $this->deleteMultiple($newKeys);
}

/**
* @param EnvManager $env
* @param UserTransport $domainUser
Expand Down
76 changes: 50 additions & 26 deletions src/Domain/Components/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,16 @@
use Phalcon\Api\Domain\Components\Middleware\NotFoundMiddleware;
use Phalcon\Api\Domain\Components\Middleware\ValidateTokenClaimsMiddleware;
use Phalcon\Api\Domain\Components\Middleware\ValidateTokenPresenceMiddleware;
use Phalcon\Api\Domain\Components\Middleware\ValidateTokenRevokedMiddleware;
use Phalcon\Api\Domain\Components\Middleware\ValidateTokenStructureMiddleware;
use Phalcon\Api\Domain\Components\Middleware\ValidateTokenUserMiddleware;
use Phalcon\Api\Domain\Services\Auth\LoginPostService;
use Phalcon\Api\Domain\Services\Auth\LogoutPostService;
use Phalcon\Api\Domain\Services\Auth\RefreshPostService;
use Phalcon\Api\Domain\Services\User\UserDeleteService;
use Phalcon\Api\Domain\Services\User\UserGetService;
use Phalcon\Api\Domain\Services\User\UserPostService;
use Phalcon\Api\Domain\Services\User\UserPutService;
use Phalcon\Api\Responder\JsonResponder;
use Phalcon\Cache\AdapterFactory;
use Phalcon\DataMapper\Pdo\Connection;
Expand All @@ -45,10 +51,6 @@ class Container extends Di
{
/** @var string */
public const APPLICATION = 'application';
/**
* Services
*/
public const AUTH_LOGIN_POST_SERVICE = 'service.auth.login.post';
/** @var string */
public const CACHE = 'cache';
/** @var string */
Expand All @@ -63,36 +65,45 @@ class Container extends Di
public const JWT_TOKEN = 'jwt.token';
/** @var string */
public const LOGGER = 'logger';
/** @var string */
public const REQUEST = 'request';
/** @var string */
public const RESPONSE = 'response';
/** @var string */
public const ROUTER = 'router';
/** @var string */
public const SECURITY = Security::class;
/** @var string */
public const TIME = 'time';
/**
* Services
*/
public const AUTH_LOGIN_POST_SERVICE = 'service.auth.login.post';
public const AUTH_LOGOUT_POST_SERVICE = 'service.auth.logout.post';
public const AUTH_REFRESH_POST_SERVICE = 'service.auth.refresh.post';
public const USER_DELETE_SERVICE = 'service.user.delete';
public const USER_GET_SERVICE = 'service.user.get';
public const USER_POST_SERVICE = 'service.user.post';
public const USER_PUT_SERVICE = 'service.user.put';
/**
* Middleware
*/
public const MIDDLEWARE_HEALTH = HealthMiddleware::class;
public const MIDDLEWARE_NOT_FOUND = NotFoundMiddleware::class;
public const MIDDLEWARE_VALIDATE_TOKEN_CLAIMS = ValidateTokenClaimsMiddleware::class;
public const MIDDLEWARE_VALIDATE_TOKEN_PRESENCE = ValidateTokenPresenceMiddleware::class;
public const MIDDLEWARE_HEALTH = HealthMiddleware::class;
public const MIDDLEWARE_NOT_FOUND = NotFoundMiddleware::class;
public const MIDDLEWARE_VALIDATE_TOKEN_CLAIMS = ValidateTokenClaimsMiddleware::class;
public const MIDDLEWARE_VALIDATE_TOKEN_PRESENCE = ValidateTokenPresenceMiddleware::class;
public const MIDDLEWARE_VALIDATE_TOKEN_REVOKED = ValidateTokenRevokedMiddleware::class;
public const MIDDLEWARE_VALIDATE_TOKEN_STRUCTURE = ValidateTokenStructureMiddleware::class;
public const MIDDLEWARE_VALIDATE_TOKEN_USER = ValidateTokenUserMiddleware::class;
/**
* Repositories
*/
public const REPOSITORY = 'repository';
public const REPOSITORY_TRANSPORT = TransportRepository::class;
/** @var string */
public const REQUEST = 'request';
/**
* Responders
*/
public const RESPONDER_JSON = JsonResponder::class;
// public const MIDDLEWARE_VALIDATE_TOKEN_REVOKED = ValidateTokenRevokedMiddleware::class;
/** @var string */
public const RESPONSE = 'response';
/** @var string */
public const ROUTER = 'router';
/** @var string */
public const SECURITY = Security::class;
/** @var string */
public const TIME = 'time';
public const USER_GET_SERVICE = 'service.user.get';

public function __construct()
{
Expand All @@ -110,21 +121,28 @@ public function __construct()

self::REPOSITORY => $this->getServiceRepository(),

self::AUTH_LOGIN_POST_SERVICE => $this->getServiceAuthLoginPost(),
self::USER_GET_SERVICE => $this->getServiceUserGet(),
self::AUTH_LOGIN_POST_SERVICE => $this->getServiceAuthPost(LoginPostService::class),
self::AUTH_LOGOUT_POST_SERVICE => $this->getServiceAuthPost(LogoutPostService::class),
self::AUTH_REFRESH_POST_SERVICE => $this->getServiceAuthPost(RefreshPostService::class),
self::USER_DELETE_SERVICE => $this->getServiceUser(UserDeleteService::class),
self::USER_GET_SERVICE => $this->getServiceUser(UserGetService::class),
self::USER_POST_SERVICE => $this->getServiceUser(UserPostService::class),
self::USER_PUT_SERVICE => $this->getServiceUser(UserPutService::class),
];

parent::__construct();
}

/**
* @param class-string $className
*
* @return Service
*/
private function getServiceAuthLoginPost(): Service
private function getServiceAuthPost(string $className): Service
{
return new Service(
[
'className' => LoginPostService::class,
'className' => $className,
'arguments' => [
[
'type' => 'service',
Expand Down Expand Up @@ -368,13 +386,15 @@ private function getServiceRouter(): Service
}

/**
* @param class-string $className
*
* @return Service
*/
private function getServiceUserGet(): Service
private function getServiceUser(string $className): Service
{
return new Service(
[
'className' => UserGetService::class,
'className' => $className,
'arguments' => [
[
'type' => 'service',
Expand All @@ -388,6 +408,10 @@ private function getServiceUserGet(): Service
'type' => 'service',
'name' => self::FILTER,
],
[
'type' => 'service',
'name' => self::SECURITY,
],
],
]
);
Expand Down
Loading
Loading