From 471eacbe68e2efded350b8793de9f8969b7298ec Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:56:04 +0200 Subject: [PATCH 1/7] Added screen status endpoint and registration --- CHANGELOG.md | 2 + config/api_platform/screen.yaml | 32 +++++++++ config/packages/cache.yaml | 6 ++ config/packages/test/cache.yaml | 3 + src/Controller/ScreenStatusController.php | 40 +++++++++++ .../ScreenUserRequestSubscriber.php | 68 +++++++++++++++++++ 6 files changed, 151 insertions(+) create mode 100644 src/Controller/ScreenStatusController.php create mode 100644 src/EventSubscriber/ScreenUserRequestSubscriber.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 656af09f..4be5c5ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- Added screen status to cache and endpoint for exposing screen status. + ## [2.0.3] - 2024-04-10 - [#203](https://github.com/os2display/display-api-service/pull/203) diff --git a/config/api_platform/screen.yaml b/config/api_platform/screen.yaml index 38521e43..94057bca 100644 --- a/config/api_platform/screen.yaml +++ b/config/api_platform/screen.yaml @@ -114,6 +114,38 @@ resources: tags: - Screens + _api_Screen_get_status: + class: ApiPlatform\Metadata\Get + method: GET + uriTemplate: '/screens/{id}/status' + read: false + controller: App\Controller\ScreenStatusController + openapiContext: + description: Get status for a screen. + summary: Get status for a screen. + operationId: get-v2-screen-id-status + tags: + - Screens + parameters: + - schema: + type: string + format: ulid + pattern: "^[A-Za-z0-9]{26}$" + name: id + in: path + required: true + responses: + '200': + content: + application/json: + examples: + example1: + value: + - {key1: 'latestRequestDateTime', key2: 'date-value'} + - {key1: 'releaseVersion', key2: '1.0.0'} + - {key1: 'releaseTimestamp', key2: '1234567890'} + headers: {} + # Our DTO must be a resource. App\Dto\Screen: provider: App\State\ScreenProvider diff --git a/config/packages/cache.yaml b/config/packages/cache.yaml index 1ebaec98..44179376 100644 --- a/config/packages/cache.yaml +++ b/config/packages/cache.yaml @@ -22,3 +22,9 @@ framework: adapter: cache.adapter.redis # Default expire set to 1 day default_lifetime: 86400 + + # Creates a "screen.status.cache" service ($screenStatusCache) + screen.status.cache: + adapter: cache.adapter.redis + # Default expire set to infinity + default_lifetime: 0 diff --git a/config/packages/test/cache.yaml b/config/packages/test/cache.yaml index 7b2c8b41..ed6d6823 100644 --- a/config/packages/test/cache.yaml +++ b/config/packages/test/cache.yaml @@ -7,3 +7,6 @@ framework: auth.screen.cache: adapter: cache.adapter.filesystem default_lifetime: 3600 + screen.status.cache: + adapter: cache.adapter.filesystem + default_lifetime: 0 diff --git a/src/Controller/ScreenStatusController.php b/src/Controller/ScreenStatusController.php new file mode 100644 index 00000000..c5f5b348 --- /dev/null +++ b/src/Controller/ScreenStatusController.php @@ -0,0 +1,40 @@ +getId()?->jsonSerialize() ?? null; + + if ($key === null) { + return new JsonResponse([]); + } + + return new JsonResponse($this->screenStatusCache->get($key, function (CacheItemInterface $cacheItem) { + $cacheItem->expiresAfter(1); + return null; + })); + } +} diff --git a/src/EventSubscriber/ScreenUserRequestSubscriber.php b/src/EventSubscriber/ScreenUserRequestSubscriber.php new file mode 100644 index 00000000..c4037461 --- /dev/null +++ b/src/EventSubscriber/ScreenUserRequestSubscriber.php @@ -0,0 +1,68 @@ +security->getUser(); + + if ($user instanceof ScreenUser) { + $key = $user->getScreen()?->getId()->jsonSerialize() ?? null; + + if ($key === null) { + return; + } + + $this->screenStatusCache->delete($key); + $this->screenStatusCache->get($key, fn() => $this->getCacheData($event)); + } + } + + private function getCacheData(RequestEvent $event): array + { + $requestDateTime = new \DateTime(); + + $request = $event->getRequest(); + $referer = $request->headers->get('referer') ?? ''; + $url = parse_url($referer); + $queryString = $url['query'] ?? ""; + $queryArray = []; + + if (!empty($queryString)) { + parse_str($queryString, $queryArray); + } + + $releaseVersion = $queryArray['releaseVersion'] ?? null; + $releaseTimestamp = $queryArray['releaseTimestamp'] ?? null; + + return [ + 'latestRequestDateTime' => $requestDateTime->format('c'), + 'releaseVersion' => $releaseVersion, + 'releaseTimestamp' => $releaseTimestamp, + ]; + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::REQUEST => 'onKernelRequest', + ]; + } +} From 1c2c0fcb5adbab883c9c16ebd8724b2ae1c8f0d5 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Mon, 6 May 2024 11:33:45 +0200 Subject: [PATCH 2/7] 1241: Added fields for tracking client info --- .env | 2 + config/services.yaml | 2 + migrations/Version20240506084815.php | 29 +++++++++ src/Entity/ScreenUser.php | 61 +++++++++++++++++++ .../ScreenUserRequestSubscriber.php | 50 ++++++++++++--- 5 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 migrations/Version20240506084815.php diff --git a/.env b/.env index 1cb563d6..f934c992 100644 --- a/.env +++ b/.env @@ -41,6 +41,8 @@ CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$' ###> App ### APP_DEFAULT_DATE_FORMAT='Y-m-d\TH:i:s.v\Z' APP_ACTIVATION_CODE_EXPIRE_INTERNAL=P2D +APP_TRACK_SCREEN_INFO=false +APP_TRACK_SCREEN_INFO_UPDATE_INTERVAL_SECONDS=300 ###< App ### ###> lexik/jwt-authentication-bundle ### diff --git a/config/services.yaml b/config/services.yaml index 534e8b54..e1573347 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -17,6 +17,8 @@ services: # @see https://api-platform.com/docs/core/state-processors/#hooking-into-the-built-in-state-processors $persistProcessor: '@api_platform.doctrine.orm.state.persist_processor' $removeProcessor: '@api_platform.doctrine.orm.state.remove_processor' + $trackScreenInfo: '%env(bool:APP_TRACK_SCREEN_INFO)%' + $trackScreenInfoUpdateIntervalSeconds: '%env(APP_TRACK_SCREEN_INFO_UPDATE_INTERVAL_SECONDS)%' _instanceof: App\Feed\FeedTypeInterface: diff --git a/migrations/Version20240506084815.php b/migrations/Version20240506084815.php new file mode 100644 index 00000000..67a04e37 --- /dev/null +++ b/migrations/Version20240506084815.php @@ -0,0 +1,29 @@ +addSql('ALTER TABLE screen_user ADD release_timestamp INT DEFAULT NULL, ADD release_version VARCHAR(255) DEFAULT NULL, ADD latest_request DATETIME DEFAULT NULL, ADD client_meta JSON DEFAULT NULL COMMENT \'(DC2Type:json)\''); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE screen_user DROP release_timestamp, DROP release_version, DROP latest_request, DROP client_meta'); + } +} diff --git a/src/Entity/ScreenUser.php b/src/Entity/ScreenUser.php index 9c229fa6..1728f882 100644 --- a/src/Entity/ScreenUser.php +++ b/src/Entity/ScreenUser.php @@ -12,6 +12,7 @@ use App\Utils\Roles; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; @@ -29,6 +30,18 @@ class ScreenUser extends AbstractTenantScopedEntity implements UserInterface, Te #[ORM\OneToOne(inversedBy: 'screenUser', targetEntity: Screen::class)] private Screen $screen; + #[ORM\Column(nullable: true)] + private ?int $releaseTimestamp = null; + + #[ORM\Column(length: 255, nullable: true)] + private ?string $releaseVersion = null; + + #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + private ?\DateTimeInterface $latestRequest = null; + + #[ORM\Column(nullable: true)] + private ?array $clientMeta = null; + /** * @deprecated since Symfony 5.3, use getUserIdentifier instead */ @@ -152,4 +165,52 @@ public function getBlamableIdentifier(): string { return 'Screen-'.$this->screen->getId()?->jsonSerialize(); } + + public function getReleaseTimestamp(): ?int + { + return $this->releaseTimestamp; + } + + public function setReleaseTimestamp(?int $releaseTimestamp): static + { + $this->releaseTimestamp = $releaseTimestamp; + + return $this; + } + + public function getReleaseVersion(): ?string + { + return $this->releaseVersion; + } + + public function setReleaseVersion(?string $releaseVersion): static + { + $this->releaseVersion = $releaseVersion; + + return $this; + } + + public function getLatestRequest(): ?\DateTimeInterface + { + return $this->latestRequest; + } + + public function setLatestRequest(?\DateTimeInterface $latestRequest): static + { + $this->latestRequest = $latestRequest; + + return $this; + } + + public function getClientMeta(): ?array + { + return $this->clientMeta; + } + + public function setClientMeta(?array $clientMeta): static + { + $this->clientMeta = $clientMeta; + + return $this; + } } diff --git a/src/EventSubscriber/ScreenUserRequestSubscriber.php b/src/EventSubscriber/ScreenUserRequestSubscriber.php index c4037461..e9a5be73 100644 --- a/src/EventSubscriber/ScreenUserRequestSubscriber.php +++ b/src/EventSubscriber/ScreenUserRequestSubscriber.php @@ -3,6 +3,8 @@ namespace App\EventSubscriber; use App\Entity\ScreenUser; +use Doctrine\ORM\EntityManagerInterface; +use Psr\Cache\CacheItemInterface; use Psr\Cache\InvalidArgumentException; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -12,7 +14,13 @@ class ScreenUserRequestSubscriber implements EventSubscriberInterface { - public function __construct(private readonly Security $security, private readonly CacheInterface $screenStatusCache) + public function __construct( + private readonly Security $security, + private readonly CacheInterface $screenStatusCache, + private readonly EntityManagerInterface $entityManager, + private readonly bool $trackScreenInfo = false, + private readonly int $trackScreenInfoUpdateIntervalSeconds = 5 * 60, + ) { } @@ -21,22 +29,27 @@ public function __construct(private readonly Security $security, private readonl */ public function onKernelRequest(RequestEvent $event): void { - $user = $this->security->getUser(); + $pathInfo = $event->getRequest()->getPathInfo(); - if ($user instanceof ScreenUser) { - $key = $user->getScreen()?->getId()->jsonSerialize() ?? null; + if ($this->trackScreenInfo && preg_match("/^\/v2\/screens\/[A-Za-z0-9]{26}$/i", $pathInfo)) { + $user = $this->security->getUser(); - if ($key === null) { - return; - } + if ($user instanceof ScreenUser) { + $key = $user->getScreen()?->getId()->jsonSerialize() ?? null; + + if ($key === null) { + return; + } - $this->screenStatusCache->delete($key); - $this->screenStatusCache->get($key, fn() => $this->getCacheData($event)); + $this->screenStatusCache->get($key, fn(CacheItemInterface $item) => $this->createCacheEntry($item, $event, $user)); + } } } - private function getCacheData(RequestEvent $event): array + private function createCacheEntry(CacheItemInterface $item, RequestEvent $event, ScreenUser $screenUser): array { + $item->expiresAfter($this->trackScreenInfoUpdateIntervalSeconds); + $requestDateTime = new \DateTime(); $request = $event->getRequest(); @@ -52,6 +65,23 @@ private function getCacheData(RequestEvent $event): array $releaseVersion = $queryArray['releaseVersion'] ?? null; $releaseTimestamp = $queryArray['releaseTimestamp'] ?? null; + // Update screen user fields. + $screenUser->setReleaseTimestamp($releaseTimestamp); + $screenUser->setReleaseVersion($releaseVersion); + $screenUser->setLatestRequest($requestDateTime); + + $userAgent = $request->headers->get('user-agent') ?? ''; + $ip = $request->getClientIp(); + + $clientMeta = [ + 'userAgent' => $userAgent, + 'ip' => $ip, + ]; + + $screenUser->setClientMeta($clientMeta); + + $this->entityManager->flush(); + return [ 'latestRequestDateTime' => $requestDateTime->format('c'), 'releaseVersion' => $releaseVersion, From d3e51530f7b7c97be68a10dcf71a5bb28ba27947 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 8 May 2024 13:06:53 +0200 Subject: [PATCH 3/7] 1241: Added screen status --- config/api_platform/screen.yaml | 32 ----------- public/api-spec-v2.json | 54 +++++++++++++++++++ public/api-spec-v2.yaml | 36 +++++++++++++ src/Controller/ScreenStatusController.php | 40 -------------- src/Dto/Screen.php | 3 ++ .../ScreenUserRequestSubscriber.php | 20 ++++++- src/State/ScreenProvider.php | 24 +++++++++ 7 files changed, 135 insertions(+), 74 deletions(-) delete mode 100644 src/Controller/ScreenStatusController.php diff --git a/config/api_platform/screen.yaml b/config/api_platform/screen.yaml index 94057bca..38521e43 100644 --- a/config/api_platform/screen.yaml +++ b/config/api_platform/screen.yaml @@ -114,38 +114,6 @@ resources: tags: - Screens - _api_Screen_get_status: - class: ApiPlatform\Metadata\Get - method: GET - uriTemplate: '/screens/{id}/status' - read: false - controller: App\Controller\ScreenStatusController - openapiContext: - description: Get status for a screen. - summary: Get status for a screen. - operationId: get-v2-screen-id-status - tags: - - Screens - parameters: - - schema: - type: string - format: ulid - pattern: "^[A-Za-z0-9]{26}$" - name: id - in: path - required: true - responses: - '200': - content: - application/json: - examples: - example1: - value: - - {key1: 'latestRequestDateTime', key2: 'date-value'} - - {key1: 'releaseVersion', key2: '1.0.0'} - - {key1: 'releaseTimestamp', key2: '1234567890'} - headers: {} - # Our DTO must be a resource. App\Dto\Screen: provider: App\State\ScreenProvider diff --git a/public/api-spec-v2.json b/public/api-spec-v2.json index 6b186542..94528502 100644 --- a/public/api-spec-v2.json +++ b/public/api-spec-v2.json @@ -10733,6 +10733,15 @@ "null" ] }, + "status": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, "modifiedBy": { "type": "string" }, @@ -10808,6 +10817,15 @@ "null" ] }, + "status": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, "relationsChecksum": { "type": "object" } @@ -10875,6 +10893,15 @@ "null" ] }, + "status": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, "modifiedBy": { "type": "string" }, @@ -10985,6 +11012,15 @@ "null" ] }, + "status": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, "modifiedBy": { "type": "string" }, @@ -11163,6 +11199,15 @@ "null" ] }, + "status": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, "modifiedBy": { "type": "string" }, @@ -11273,6 +11318,15 @@ "null" ] }, + "status": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, "relationsChecksum": { "type": "object" } diff --git a/public/api-spec-v2.yaml b/public/api-spec-v2.yaml index 53c73381..8af9a1ff 100644 --- a/public/api-spec-v2.yaml +++ b/public/api-spec-v2.yaml @@ -7469,6 +7469,12 @@ components: type: - boolean - 'null' + status: + type: + - array + - 'null' + items: + type: string modifiedBy: type: string createdBy: @@ -7521,6 +7527,12 @@ components: type: - boolean - 'null' + status: + type: + - array + - 'null' + items: + type: string relationsChecksum: type: object Screen-screen-campaigns.read: @@ -7567,6 +7579,12 @@ components: type: - boolean - 'null' + status: + type: + - array + - 'null' + items: + type: string modifiedBy: type: string createdBy: @@ -7642,6 +7660,12 @@ components: type: - boolean - 'null' + status: + type: + - array + - 'null' + items: + type: string modifiedBy: type: string createdBy: @@ -7763,6 +7787,12 @@ components: type: - boolean - 'null' + status: + type: + - array + - 'null' + items: + type: string modifiedBy: type: string createdBy: @@ -7838,6 +7868,12 @@ components: type: - boolean - 'null' + status: + type: + - array + - 'null' + items: + type: string relationsChecksum: type: object Screen.jsonld-screen-campaigns.read: diff --git a/src/Controller/ScreenStatusController.php b/src/Controller/ScreenStatusController.php deleted file mode 100644 index c5f5b348..00000000 --- a/src/Controller/ScreenStatusController.php +++ /dev/null @@ -1,40 +0,0 @@ -getId()?->jsonSerialize() ?? null; - - if ($key === null) { - return new JsonResponse([]); - } - - return new JsonResponse($this->screenStatusCache->get($key, function (CacheItemInterface $cacheItem) { - $cacheItem->expiresAfter(1); - return null; - })); - } -} diff --git a/src/Dto/Screen.php b/src/Dto/Screen.php index 6ae28510..825a013a 100644 --- a/src/Dto/Screen.php +++ b/src/Dto/Screen.php @@ -52,4 +52,7 @@ class Screen #[Groups(['campaigns/screens:read', 'screen-groups/screens:read'])] public ?bool $enableColorSchemeChange = null; + + #[Groups(['campaigns/screens:read', 'screen-groups/screens:read'])] + public ?array $status = null; } diff --git a/src/EventSubscriber/ScreenUserRequestSubscriber.php b/src/EventSubscriber/ScreenUserRequestSubscriber.php index e9a5be73..2f468fff 100644 --- a/src/EventSubscriber/ScreenUserRequestSubscriber.php +++ b/src/EventSubscriber/ScreenUserRequestSubscriber.php @@ -4,6 +4,7 @@ use App\Entity\ScreenUser; use Doctrine\ORM\EntityManagerInterface; +use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; use Psr\Cache\CacheItemInterface; use Psr\Cache\InvalidArgumentException; use Symfony\Bundle\SecurityBundle\Security; @@ -16,6 +17,7 @@ class ScreenUserRequestSubscriber implements EventSubscriberInterface { public function __construct( private readonly Security $security, + private readonly JWTTokenManagerInterface $tokenManager, private readonly CacheInterface $screenStatusCache, private readonly EntityManagerInterface $entityManager, private readonly bool $trackScreenInfo = false, @@ -35,7 +37,7 @@ public function onKernelRequest(RequestEvent $event): void $user = $this->security->getUser(); if ($user instanceof ScreenUser) { - $key = $user->getScreen()?->getId()->jsonSerialize() ?? null; + $key = $user->getId()?->jsonSerialize() ?? null; if ($key === null) { return; @@ -66,26 +68,40 @@ private function createCacheEntry(CacheItemInterface $item, RequestEvent $event, $releaseTimestamp = $queryArray['releaseTimestamp'] ?? null; // Update screen user fields. - $screenUser->setReleaseTimestamp($releaseTimestamp); + $screenUser->setReleaseTimestamp((int) $releaseTimestamp); $screenUser->setReleaseVersion($releaseVersion); $screenUser->setLatestRequest($requestDateTime); $userAgent = $request->headers->get('user-agent') ?? ''; $ip = $request->getClientIp(); + $host = preg_replace("/\/\?.*$/i", "", $referer); $clientMeta = [ + 'host' => $host, 'userAgent' => $userAgent, 'ip' => $ip, ]; + $token = $this->security->getToken(); + $decodedToken = $this->tokenManager->decode($token); + $expire = $decodedToken['exp'] ?? 0; + $expireDateTime = (new \DateTime())->setTimestamp($expire); + $now = new \DateTime(); + + $tokenExpired = $expireDateTime < $now; + + $clientMeta['tokenExpired'] = $tokenExpired; + $screenUser->setClientMeta($clientMeta); $this->entityManager->flush(); + $this->entityManager->clear(); return [ 'latestRequestDateTime' => $requestDateTime->format('c'), 'releaseVersion' => $releaseVersion, 'releaseTimestamp' => $releaseTimestamp, + 'clientMeta' => $clientMeta, ]; } diff --git a/src/State/ScreenProvider.php b/src/State/ScreenProvider.php index 3974577e..f4015d9c 100644 --- a/src/State/ScreenProvider.php +++ b/src/State/ScreenProvider.php @@ -7,6 +7,7 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\State\ProviderInterface; use App\Dto\Screen as ScreenDTO; +use App\Entity\ScreenUser; use App\Entity\Tenant\Screen; use App\Repository\ScreenRepository; @@ -16,6 +17,7 @@ public function __construct( private readonly IriConverterInterface $iriConverter, ProviderInterface $collectionProvider, ScreenRepository $entityRepository, + private readonly bool $trackScreenInfo = false, ) { parent::__construct($collectionProvider, $entityRepository); } @@ -62,6 +64,28 @@ public function toOutput(object $object): ScreenDTO } } + if ($this->trackScreenInfo) { + $screenUser = $object->getScreenUser(); + + $status = null; + + if (null != $screenUser) { + $status = $this->getStatus($screenUser); + } + + $output->status = $status; + } + return $output; } + + private function getStatus(ScreenUser $screenUser): array + { + return [ + 'latestRequestDateTime' => $screenUser->getLatestRequest()?->format('c'), + 'releaseVersion' => $screenUser->getReleaseVersion(), + 'releaseTimestamp' => $screenUser->getReleaseTimestamp(), + 'clientMeta' => $screenUser->getClientMeta(), + ]; + } } From 88523b0b4b4edee8a444603abfa54df17ec0a227 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Thu, 9 May 2024 08:03:13 +0200 Subject: [PATCH 4/7] 1241: Added filters for screenUser --- config/api_platform/screen.yaml | 3 +- config/services.yaml | 10 +++++ public/api-spec-v2.json | 70 +++++++++++++++++++++++++++++++++ public/api-spec-v2.yaml | 60 ++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 1 deletion(-) diff --git a/config/api_platform/screen.yaml b/config/api_platform/screen.yaml index 38521e43..f6388964 100644 --- a/config/api_platform/screen.yaml +++ b/config/api_platform/screen.yaml @@ -70,6 +70,8 @@ resources: ApiPlatform\Metadata\GetCollection: filters: - 'App\Filter\MultipleSearchFilter' + - 'screen.screen_user_exists_filter' + - 'screen.screen_user_latest_request_filter' - 'entity.blameable_filter' - 'entity.order_filter' - 'created.at.order_filter' @@ -100,7 +102,6 @@ resources: content: application/ld+json: examples: - headers: {} ApiPlatform\Metadata\Post: diff --git a/config/services.yaml b/config/services.yaml index e1573347..8391692b 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -269,6 +269,16 @@ services: tags: ['api_platform.filter'] arguments: [ { fullName: 'partial', email: 'partial' } ] + screen.screen_user_exists_filter: + parent: 'api_platform.doctrine.orm.exists_filter' + tags: ['api_platform.filter'] + arguments: [ { screenUser: ~ } ] + + screen.screen_user_latest_request_filter: + parent: 'api_platform.doctrine.orm.date_filter' + tags: ['api_platform.filter'] + arguments: [ { screenUser.latestRequest: ~ } ] + # App filters for Api Platform App\Filter\PublishedFilter: tags: ['api_platform.filter'] diff --git a/public/api-spec-v2.json b/public/api-spec-v2.json index 94528502..eb4c89fe 100644 --- a/public/api-spec-v2.json +++ b/public/api-spec-v2.json @@ -3270,6 +3270,76 @@ "explode": false, "allowReserved": false }, + { + "name": "exists[screenUser]", + "in": "query", + "description": "", + "required": false, + "deprecated": false, + "allowEmptyValue": true, + "schema": { + "type": "boolean" + }, + "style": "form", + "explode": false, + "allowReserved": false + }, + { + "name": "screenUser.latestRequest[before]", + "in": "query", + "description": "", + "required": false, + "deprecated": false, + "allowEmptyValue": true, + "schema": { + "type": "string" + }, + "style": "form", + "explode": false, + "allowReserved": false + }, + { + "name": "screenUser.latestRequest[strictly_before]", + "in": "query", + "description": "", + "required": false, + "deprecated": false, + "allowEmptyValue": true, + "schema": { + "type": "string" + }, + "style": "form", + "explode": false, + "allowReserved": false + }, + { + "name": "screenUser.latestRequest[after]", + "in": "query", + "description": "", + "required": false, + "deprecated": false, + "allowEmptyValue": true, + "schema": { + "type": "string" + }, + "style": "form", + "explode": false, + "allowReserved": false + }, + { + "name": "screenUser.latestRequest[strictly_after]", + "in": "query", + "description": "", + "required": false, + "deprecated": false, + "allowEmptyValue": true, + "schema": { + "type": "string" + }, + "style": "form", + "explode": false, + "allowReserved": false + }, { "name": "createdBy", "in": "query", diff --git a/public/api-spec-v2.yaml b/public/api-spec-v2.yaml index 8af9a1ff..4ef1fdaa 100644 --- a/public/api-spec-v2.yaml +++ b/public/api-spec-v2.yaml @@ -2302,6 +2302,66 @@ paths: style: form explode: false allowReserved: false + - + name: 'exists[screenUser]' + in: query + description: '' + required: false + deprecated: false + allowEmptyValue: true + schema: + type: boolean + style: form + explode: false + allowReserved: false + - + name: 'screenUser.latestRequest[before]' + in: query + description: '' + required: false + deprecated: false + allowEmptyValue: true + schema: + type: string + style: form + explode: false + allowReserved: false + - + name: 'screenUser.latestRequest[strictly_before]' + in: query + description: '' + required: false + deprecated: false + allowEmptyValue: true + schema: + type: string + style: form + explode: false + allowReserved: false + - + name: 'screenUser.latestRequest[after]' + in: query + description: '' + required: false + deprecated: false + allowEmptyValue: true + schema: + type: string + style: form + explode: false + allowReserved: false + - + name: 'screenUser.latestRequest[strictly_after]' + in: query + description: '' + required: false + deprecated: false + allowEmptyValue: true + schema: + type: string + style: form + explode: false + allowReserved: false - name: createdBy in: query From 0eaaccf606640f6777d5d42df0b0af6fceb735ef Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:32:59 +0100 Subject: [PATCH 5/7] 3104: Updated api specification --- public/api-spec-v2.json | 10 +++++----- public/api-spec-v2.yaml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/public/api-spec-v2.json b/public/api-spec-v2.json index b60df6c9..ce90fb5a 100644 --- a/public/api-spec-v2.json +++ b/public/api-spec-v2.json @@ -3860,7 +3860,7 @@ "description": "", "required": false, "deprecated": false, - "allowEmptyValue": true, + "allowEmptyValue": false, "schema": { "type": "boolean" }, @@ -3874,7 +3874,7 @@ "description": "", "required": false, "deprecated": false, - "allowEmptyValue": true, + "allowEmptyValue": false, "schema": { "type": "string" }, @@ -3888,7 +3888,7 @@ "description": "", "required": false, "deprecated": false, - "allowEmptyValue": true, + "allowEmptyValue": false, "schema": { "type": "string" }, @@ -3902,7 +3902,7 @@ "description": "", "required": false, "deprecated": false, - "allowEmptyValue": true, + "allowEmptyValue": false, "schema": { "type": "string" }, @@ -3916,7 +3916,7 @@ "description": "", "required": false, "deprecated": false, - "allowEmptyValue": true, + "allowEmptyValue": false, "schema": { "type": "string" }, diff --git a/public/api-spec-v2.yaml b/public/api-spec-v2.yaml index b78ede1f..4f35e1a6 100644 --- a/public/api-spec-v2.yaml +++ b/public/api-spec-v2.yaml @@ -2752,7 +2752,7 @@ paths: description: '' required: false deprecated: false - allowEmptyValue: true + allowEmptyValue: false schema: type: boolean style: form @@ -2764,7 +2764,7 @@ paths: description: '' required: false deprecated: false - allowEmptyValue: true + allowEmptyValue: false schema: type: string style: form @@ -2776,7 +2776,7 @@ paths: description: '' required: false deprecated: false - allowEmptyValue: true + allowEmptyValue: false schema: type: string style: form @@ -2788,7 +2788,7 @@ paths: description: '' required: false deprecated: false - allowEmptyValue: true + allowEmptyValue: false schema: type: string style: form @@ -2800,7 +2800,7 @@ paths: description: '' required: false deprecated: false - allowEmptyValue: true + allowEmptyValue: false schema: type: string style: form From 96a04537456ab6960cc395d67b549c68d0f85555 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 27 Nov 2024 12:54:45 +0100 Subject: [PATCH 6/7] 3104: Fixed replace --- src/EventSubscriber/ScreenUserRequestSubscriber.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EventSubscriber/ScreenUserRequestSubscriber.php b/src/EventSubscriber/ScreenUserRequestSubscriber.php index 2f468fff..9d65c62d 100644 --- a/src/EventSubscriber/ScreenUserRequestSubscriber.php +++ b/src/EventSubscriber/ScreenUserRequestSubscriber.php @@ -74,7 +74,7 @@ private function createCacheEntry(CacheItemInterface $item, RequestEvent $event, $userAgent = $request->headers->get('user-agent') ?? ''; $ip = $request->getClientIp(); - $host = preg_replace("/\/\?.*$/i", "", $referer); + $host = preg_replace("/\?.*$/i", "", $referer); $clientMeta = [ 'host' => $host, From 90273a12acd2f7bb9726f340150840b209083687 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Tue, 10 Dec 2024 06:58:26 +0100 Subject: [PATCH 7/7] 1241: Applied coding standards --- src/Entity/ScreenUser.php | 4 +-- .../ScreenUserRequestSubscriber.php | 29 ++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/Entity/ScreenUser.php b/src/Entity/ScreenUser.php index 1f8f9506..719e140c 100644 --- a/src/Entity/ScreenUser.php +++ b/src/Entity/ScreenUser.php @@ -21,10 +21,10 @@ class ScreenUser extends AbstractTenantScopedEntity implements UserInterface, Te { final public const string ROLE_SCREEN = Roles::ROLE_SCREEN; - #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 180, unique: true)] + #[ORM\Column(type: Types::STRING, length: 180, unique: true)] private string $username; - #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[ORM\Column(type: Types::JSON)] private array $roles = []; #[ORM\OneToOne(inversedBy: 'screenUser', targetEntity: Screen::class)] diff --git a/src/EventSubscriber/ScreenUserRequestSubscriber.php b/src/EventSubscriber/ScreenUserRequestSubscriber.php index 9d65c62d..335bcc58 100644 --- a/src/EventSubscriber/ScreenUserRequestSubscriber.php +++ b/src/EventSubscriber/ScreenUserRequestSubscriber.php @@ -1,5 +1,7 @@ getId()?->jsonSerialize() ?? null; - if ($key === null) { + if (null === $key) { return; } - $this->screenStatusCache->get($key, fn(CacheItemInterface $item) => $this->createCacheEntry($item, $event, $user)); + $this->screenStatusCache->get($key, fn (CacheItemInterface $item) => $this->createCacheEntry($item, $event, $user)); } } } @@ -57,7 +57,7 @@ private function createCacheEntry(CacheItemInterface $item, RequestEvent $event, $request = $event->getRequest(); $referer = $request->headers->get('referer') ?? ''; $url = parse_url($referer); - $queryString = $url['query'] ?? ""; + $queryString = $url['query'] ?? ''; $queryArray = []; if (!empty($queryString)) { @@ -74,7 +74,7 @@ private function createCacheEntry(CacheItemInterface $item, RequestEvent $event, $userAgent = $request->headers->get('user-agent') ?? ''; $ip = $request->getClientIp(); - $host = preg_replace("/\?.*$/i", "", $referer); + $host = preg_replace("/\?.*$/i", '', $referer); $clientMeta = [ 'host' => $host, @@ -83,14 +83,17 @@ private function createCacheEntry(CacheItemInterface $item, RequestEvent $event, ]; $token = $this->security->getToken(); - $decodedToken = $this->tokenManager->decode($token); - $expire = $decodedToken['exp'] ?? 0; - $expireDateTime = (new \DateTime())->setTimestamp($expire); - $now = new \DateTime(); - $tokenExpired = $expireDateTime < $now; + if (null !== $token) { + $decodedToken = $this->tokenManager->decode($token); + $expire = $decodedToken['exp'] ?? 0; + $expireDateTime = (new \DateTime())->setTimestamp($expire); + $now = new \DateTime(); - $clientMeta['tokenExpired'] = $tokenExpired; + $tokenExpired = $expireDateTime < $now; + + $clientMeta['tokenExpired'] = $tokenExpired; + } $screenUser->setClientMeta($clientMeta);