diff --git a/phpBB/adm/style/ajax.js b/phpBB/adm/style/ajax.js
index 5949c73920..25a6527481 100644
--- a/phpBB/adm/style/ajax.js
+++ b/phpBB/adm/style/ajax.js
@@ -157,6 +157,68 @@ phpbb.addAjaxCallback('row_delete', function(res) {
}
});
+/**
+ * This callback generates the VAPID keys for the web push notification service.
+ */
+phpbb.addAjaxCallback('generate_vapid_keys', (res) => {
+ function rawKeyToBase64(rawKey) {
+ const keyBuffer = new Uint8Array(rawKey);
+ let keyText = '';
+ const keyLength = keyBuffer.byteLength;
+ for (let i = 0; i < keyLength; i++) {
+ keyText += String.fromCharCode(keyBuffer[i]);
+ }
+
+ keyText = window.btoa(keyText);
+ return keyText;
+ }
+
+ function base64SafeEncode(base64String) {
+ const base64URL = base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
+ return base64URL;
+ }
+
+ async function generateVAPIDKeys() {
+ try {
+ // Generate a new key pair using the Subtle Crypto API
+ const keyPair = await crypto.subtle.generateKey(
+ {
+ name: 'ECDH',
+ namedCurve: 'P-256',
+ },
+ true,
+ ['deriveKey', 'deriveBits']
+ );
+
+ // Export the private key as a JWK (JSON Web Key) object
+ const privateKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey);
+ console.log(privateKeyJwk.d);
+
+ const privateKeyString = privateKeyJwk.d;
+
+ // Export the public key as a JWK object
+ const publicKeyBuffer = await crypto.subtle.exportKey('raw', keyPair.publicKey);
+ const publicKeyString = base64SafeEncode(rawKeyToBase64(publicKeyBuffer));
+ console.log(publicKeyString);
+
+ return {
+ privateKey: privateKeyString,
+ publicKey: publicKeyString
+ };
+ } catch (error) {
+ console.error('Error generating private key:', error);
+ return null;
+ }
+ }
+
+ generateVAPIDKeys().then(keyPair => {
+ const publicKeyInput = document.querySelector('#webpush_vapid_public');
+ const privateKeyInput = document.querySelector('#webpush_vapid_private');
+ publicKeyInput.value = keyPair.publicKey;
+ privateKeyInput.value = keyPair.privateKey;
+ })
+})
+
/**
* Handler for submitting permissions form in chunks
* This call will submit permissions forms in chunks of 5 fieldsets.
diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php
index ceb7f47d58..d0ced6788f 100644
--- a/phpBB/includes/acp/acp_board.php
+++ b/phpBB/includes/acp/acp_board.php
@@ -491,7 +491,7 @@ class acp_board
'title' => 'ACP_WEBPUSH_SETTINGS',
'vars' => [
'legend1' => 'GENERAL_SETTINGS',
- 'webpush_enable' => ['lang' => 'WEBPUSH_ENABLE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true],
+ 'webpush_enable' => ['lang' => 'WEBPUSH_ENABLE', 'validate' => 'bool', 'type' => 'custom', 'method' => 'webpush_enable', 'explain' => true],
'webpush_vapid_public' => ['lang' => 'WEBPUSH_VAPID_PUBLIC', 'validate' => 'string', 'type' => 'text:25:255', 'explain' => true],
'webpush_vapid_private' => ['lang' => 'WEBPUSH_VAPID_PRIVATE', 'validate' => 'string', 'type' => 'password:25:255', 'explain' => true],
@@ -539,27 +539,6 @@ class acp_board
}
}
- if ($mode == 'webpush')
- {
- // Create VAPID keys if keys are empty and web push is enabled
- if ($submit && $cfg_array['webpush_enable'] && $cfg_array['webpush_enable'] != $config['webpush_enable']
- && empty($cfg_array['webpush_vapid_public']) && empty($cfg_array['webpush_vapid_private'])
- && empty($config['webpush_vapid_public']) && empty($config['webpush_vapid_private']))
- {
- try
- {
- $vapid_keys = VAPID::createVapidKeys();
- $cfg_array['webpush_vapid_public'] = $vapid_keys['publicKey'];
- $cfg_array['webpush_vapid_private'] = $vapid_keys['privateKey'];
- }
- catch (\ErrorException $exception)
- {
- // Nothing we can do about this, user will have to follow the
- // documentation and manually create these.
- }
- }
- }
-
// We validate the complete config if wished
validate_config_vars($display_vars['vars'], $cfg_array, $error);
@@ -1383,4 +1362,49 @@ class acp_board
return '
';
}
+
+ /**
+ * Generate form data for web push enable
+ *
+ * @param string $value Webpush enable value
+ * @param string $key Webpush enable config key
+ *
+ * @return array[] Form data
+ */
+ public function webpush_enable($value, $key): array
+ {
+ return [
+ [
+ 'tag' => 'radio',
+ 'buttons' => [
+ [
+ 'name' => "config[$key]",
+ 'label' => $this->language->lang('YES'),
+ 'type' => 'radio',
+ 'class' => 'radio',
+ 'value' => 1,
+ 'checked' => $value,
+ ],
+ [
+ 'name' => "config[$key]",
+ 'label' => $this->language->lang('NO'),
+ 'type' => 'radio',
+ 'class' => 'radio',
+ 'value' => 0,
+ 'checked' => !$value,
+ ],
+ ],
+ ],
+ [
+ 'tag' => 'input',
+ 'class' => 'button2',
+ 'name' => "config[$key]",
+ 'type' => 'button',
+ 'value' => $this->language->lang('WEBPUSH_GENERATE_VAPID_KEYS'),
+ 'data' => [
+ 'ajax' => 'generate_vapid_keys',
+ ]
+ ],
+ ];
+ }
}
diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php
index 8fe9f832f2..d2905d94e8 100644
--- a/phpBB/language/en/acp/board.php
+++ b/phpBB/language/en/acp/board.php
@@ -603,6 +603,7 @@ $lang = array_merge($lang, [
'ACP_WEBPUSH_SETTINGS_EXPLAIN' => 'Here you can enable and control the use of Webpush for board notifications. Webpush is a simple protocol for the delivery of real-time events to user agents, more commonly known as push messages. It is supported by most modern browsers on desktop and mobile devices.',
'WEBPUSH_ENABLE' => 'Enable Webpush',
'WEBPUSH_ENABLE_EXPLAIN' => 'Allow receiving notifications via Webpush.
Note: If VAPID keys have not been set, phpBB will try to automatically create them when enabling Webpush.',
+ 'WEBPUSH_GENERATE_VAPID_KEYS' => 'Generate VAPID keys',
'WEBPUSH_VAPID_PUBLIC' => 'VAPID public key',
'WEBPUSH_VAPID_PUBLIC_EXPLAIN' => 'The VAPID public key will be shared to authenticate push messages sent by your site.
Warning: Changing the VAPID public key will automatically invalidate all webpush subscriptions.',
'WEBPUSH_VAPID_PRIVATE' => 'VAPID private key',