From 6b00e9fe09c464b55a23076da684b744607dbd8a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 3 Jul 2023 14:38:01 +0200 Subject: [PATCH] [ticket/17010] Handle already existing subscriptions PHPBB3-17010 --- .../db/migration/data/v400/add_webpush.php | 1 - phpBB/phpbb/ucp/controller/webpush.php | 26 +++++++++-- phpBB/styles/all/js/webpush.js.twig | 45 ++++++++++++++++--- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/phpBB/phpbb/db/migration/data/v400/add_webpush.php b/phpBB/phpbb/db/migration/data/v400/add_webpush.php index 248be387bd..351e02a361 100644 --- a/phpBB/phpbb/db/migration/data/v400/add_webpush.php +++ b/phpBB/phpbb/db/migration/data/v400/add_webpush.php @@ -48,7 +48,6 @@ class add_webpush extends migration 'COLUMNS' => [ 'subscription_id' => ['ULINT', null, 'auto_increment'], 'user_id' => ['ULINT', 0], -// 'device_name' => ['VCHAR:64', ''], 'endpoint' => ['TEXT', ''], 'expiration_time' => ['TIMESTAMP', 0], 'p256dh' => ['VCHAR', ''], diff --git a/phpBB/phpbb/ucp/controller/webpush.php b/phpBB/phpbb/ucp/controller/webpush.php index f1f5c197be..e292f35fac 100644 --- a/phpBB/phpbb/ucp/controller/webpush.php +++ b/phpBB/phpbb/ucp/controller/webpush.php @@ -35,9 +35,6 @@ class webpush /** @var string UCP form token name */ private const FORM_TOKEN_UCP = 'ucp_webpush'; - /** @var string Push worker form token name */ - private const FORM_TOKEN_WORKER = 'webpush_worker'; - /** @var config */ protected $config; @@ -206,6 +203,7 @@ class webpush $template_data += [ 'VAPID_PUBLIC_KEY' => $this->config['webpush_vapid_public'], 'U_WEBPUSH_WORKER_URL' => $this->controller_helper->route('phpbb_ucp_push_worker_controller'), + 'SUBSCRIPTIONS' => $this->get_subscriptions(), ]; $content = $this->template->render('webpush.js.twig', $template_data); @@ -273,4 +271,26 @@ class webpush 'form_tokens' => $this->form_helper->get_form_tokens(self::FORM_TOKEN_UCP), ]); } + + /** + * Get subscriptions for current user + * + * @return array Subscriptions for user + */ + protected function get_subscriptions(): array + { + $subscriptions = []; + + $sql = 'SELECT endpoint, expiration_time + FROM ' . $this->push_subscriptions_table . ' + WHERE user_id = ' . $this->user->id(); + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $subscriptions[] = $row; + } + $this->db->sql_freeresult($result); + + return $subscriptions; + } } diff --git a/phpBB/styles/all/js/webpush.js.twig b/phpBB/styles/all/js/webpush.js.twig index e634f4539c..b9c776d549 100644 --- a/phpBB/styles/all/js/webpush.js.twig +++ b/phpBB/styles/all/js/webpush.js.twig @@ -18,6 +18,13 @@ function PhpbbWebpush() { formToken: '{{ FORM_TOKENS.form_token }}' }; + /** @type [{endpoint: string, expiration: string}[]] Subscriptions */ + let subscriptions = [ + {% for sub in SUBSCRIPTIONS %} + {endpoint: '{{ sub.endpoint }}', expiration: '{{ sub.expiration }}' }, + {% endfor %} + ]; + /** @type {string} VAPID public key */ const VAPID_PUBLIC_KEY = '{{ VAPID_PUBLIC_KEY }}'; @@ -70,7 +77,7 @@ function PhpbbWebpush() { registration.pushManager.getSubscription() .then((subscribed) => { - if (subscribed) { + if (isValidSubscription(subscribed)) { setSubscriptionState(true); } }) @@ -78,6 +85,31 @@ function PhpbbWebpush() { } } + /** + * Check whether subscription is valid + * + * @param {PushSubscription} subscription + * @returns {boolean} + */ + const isValidSubscription = (subscription) => { + if (!subscription) { + return false; + } + + if (subscription.expirationTime && subscription.expirationTime <= Date.now()) { + return false; + } + + for (const curSubscription of subscriptions) { + if (subscription.endpoint === curSubscription.endpoint) { + return true; + } + } + + // Subscription is not in valid subscription list for user + return false; + }; + /** * Set subscription state for buttons * @@ -111,16 +143,19 @@ function PhpbbWebpush() { } const registration = await navigator.serviceWorker.getRegistration(serviceWorkerUrl); + + // We might already have a subscription that is unknown to this instance of phpBB. + // Unsubscribe before trying to subscribe again. if (typeof registration !== 'undefined') { const subscribed = await registration.pushManager.getSubscription(); if (subscribed) { - setSubscriptionState(true); - return; + await subscribed.unsubscribe(); } } - const newSubscription = await registration.pushManager.subscribe({ + + let newSubscription = await registration.pushManager.subscribe({ userVisibleOnly: true, - applicationServerKey: urlB64ToUint8Array(VAPID_PUBLIC_KEY) + applicationServerKey: urlB64ToUint8Array(VAPID_PUBLIC_KEY), }); const loadingIndicator = phpbb.loadingIndicator();