store vapid key, initialise web-push in serviceWorker

This commit is contained in:
Mike Macgirvin 2023-11-11 09:53:33 +11:00
parent c257c31b7f
commit f9e3470e20
5 changed files with 73 additions and 40 deletions

View file

@ -73,46 +73,6 @@ class Channel
}
}
public static function getVapidKey()
{
$private_key = openssl_pkey_new([
'private_key_type' => OPENSSL_KEYTYPE_EC,
'curve_name' => 'prime256v1',
]);
$details = openssl_pkey_get_details($private_key);
$private_key_raw = $details['ec']['d'];
$public_key_raw = $details['ec']['x'] . $details['ec']['y'];
$auth_token = base64_encode(openssl_random_pseudo_bytes(16));
$vapid = [
'private_key' => rtrim(strtr(base64_encode($private_key_raw), '+/', '-_'), '='),
'public_key' => rtrim(strtr(base64_encode($public_key_raw), '+/', '-_'), '='),
'auth_token' => $auth_token,
];
return json_encode($vapid);
}
public static function getApplicationServerKey($vapid)
{
$publicKey = $vapid['public_key'];
$public_key_bytes = base64_decode($publicKey);
// Check that the public key has the correct format
if (strlen($public_key_bytes) != 65 || ord($public_key_bytes[0]) != 4) {
// The public key has an incorrect format
// Handle the error here
}
// Extract the x and y coordinates of the point
$x = substr($public_key_bytes, 1, 32);
$y = substr($public_key_bytes, 33, 32);
// Pack the bytes of the public key in the correct order
$application_server_key = "\x04" . $x . $y;
return base64_encode($application_server_key);
}
/**
* @brief Create a system channel - which has no account attached.

View file

@ -136,4 +136,46 @@ class System
return '0.0.0';
}
public static function getVapidKey()
{
$private_key = openssl_pkey_new([
'private_key_type' => OPENSSL_KEYTYPE_EC,
'curve_name' => 'prime256v1',
]);
$details = openssl_pkey_get_details($private_key);
$private_key_raw = $details['ec']['d'];
$public_key_raw = $details['ec']['x'] . $details['ec']['y'];
$auth_token = base64_encode(openssl_random_pseudo_bytes(16));
$vapid = [
'private_key' => rtrim(strtr(base64_encode($private_key_raw), '+/', '-_'), '='),
'public_key' => rtrim(strtr(base64_encode($public_key_raw), '+/', '-_'), '='),
'auth_token' => $auth_token,
];
return json_encode($vapid);
}
public static function getApplicationServerKey($vapid)
{
$publicKey = $vapid['public_key'];
$public_key_bytes = base64_decode($publicKey);
// Check that the public key has the correct format
if (strlen($public_key_bytes) != 65 || ord($public_key_bytes[0]) != 4) {
// The public key has an incorrect format
// Handle the error here
}
// Extract the x and y coordinates of the point
$x = substr($public_key_bytes, 1, 32);
$y = substr($public_key_bytes, 33, 32);
// Pack the bytes of the public key in the correct order
$application_server_key = "\x04" . $x . $y;
return base64_encode($application_server_key);
}
}

View file

@ -7,3 +7,23 @@ self.addEventListener('fetch', function(e) {
// nothing here yet
});
self.addEventListener('push', function (event) {
if (!(self.Notification && self.Notification.permission === 'granted')) {
return;
}
const sendNotification = body => {
// you could refresh a notification badge here with postMessage API
const title = "";
return self.registration.showNotification(title, {
body,
});
};
if (event.data) {
const payload = event.data.json();
event.waitUntil(sendNotification(payload.message));
}
});

View file

@ -909,6 +909,15 @@ function check_config() {
check_cron_broken();
// Ensure the site has a vapid (push-notification) keypair
$vapid = Config::Get('system','vapid');
if (!$vapid) {
$vapid = System::getVapidKey();
if ($vapid) {
Config::Set('system', 'vapid', $vapid);
}
}
}

View file

@ -32,6 +32,7 @@ let mode = '';
let update_url = '';
let update_mode = '';
let orgHeight = 0;
let serviceWorkerRegistration = false;
$.ajaxPrefilter(function( options, original_Options, jqXHR ) {
options.async = true;
@ -41,6 +42,7 @@ $.ajaxSetup({cache: false});
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/ServiceWorker.js', { scope: '/' }).then(function(registration) {
console.log('Service worker registered. scope is', registration.scope);
serviceWorkerRegistration = registration;
}).catch(function(error) {
console.log('Service worker registration failed because ' + error);
});