fix(webpush): improve iOS push subscription endpoint cleanup

Signed-off-by: 0xsysr3ll <0xsysr3ll@pm.me>
This commit is contained in:
0xsysr3ll
2025-11-11 15:14:58 +01:00
parent 3ee69663dc
commit 3f899f5e76
2 changed files with 29 additions and 9 deletions

View File

@@ -109,11 +109,16 @@ const UserWebPushSettings = () => {
// Deletes/disables corresponding push subscription from database
const disablePushNotifications = async (endpoint?: string) => {
try {
await unsubscribeToPushNotifications(user?.id, endpoint);
const unsubscribedEndpoint = await unsubscribeToPushNotifications(
user?.id,
endpoint
);
// Delete from backend if endpoint is available
if (subEndpoint) {
await deletePushSubscriptionFromBackend(subEndpoint);
const endpointToDelete = unsubscribedEndpoint || subEndpoint || endpoint;
if (endpointToDelete) {
await deletePushSubscriptionFromBackend(endpointToDelete);
}
localStorage.setItem('pushNotificationsEnabled', 'false');

View File

@@ -56,7 +56,7 @@ export const verifyPushSubscription = async (
);
return expectedServerKey === currentServerKey && data.endpoint === endpoint;
} catch {
} catch (error) {
return false;
}
};
@@ -74,11 +74,24 @@ export const verifyAndResubscribePushSubscription = async (
if (currentSettings.enablePushRegistration) {
try {
// Unsubscribe from the backend to clear the existing push subscription (keys and endpoint)
await unsubscribeToPushNotifications(userId);
const oldEndpoint = await unsubscribeToPushNotifications(userId);
// Subscribe again to generate a fresh push subscription with updated keys and endpoint
await subscribeToPushNotifications(userId, currentSettings);
if (oldEndpoint && userId) {
try {
await axios.delete(
`/api/v1/user/${userId}/pushSubscription/${encodeURIComponent(
oldEndpoint
)}`
);
} catch (error) {
// Ignore errors when deleting old endpoint (it might not exist)
// This is expected when the endpoint was already cleaned up
}
}
return true;
} catch (error) {
throw new Error(`[SW] Resubscribe failed: ${error.message}`);
@@ -136,24 +149,26 @@ export const subscribeToPushNotifications = async (
export const unsubscribeToPushNotifications = async (
userId: number | undefined,
endpoint?: string
) => {
): Promise<string | null> => {
if (!('serviceWorker' in navigator) || !userId) {
return;
return null;
}
try {
const { subscription } = await getPushSubscription();
if (!subscription) {
return false;
return null;
}
const { endpoint: currentEndpoint } = subscription.toJSON();
if (!endpoint || endpoint === currentEndpoint) {
await subscription.unsubscribe();
return true;
return currentEndpoint ?? null;
}
return null;
} catch (error) {
throw new Error(
`Issue unsubscribing to push notifications: ${error.message}`