Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebPush Delivery Method #112

Closed
excid3 opened this issue Apr 23, 2021 · 8 comments
Closed

WebPush Delivery Method #112

excid3 opened this issue Apr 23, 2021 · 8 comments
Labels
enhancement New feature or request

Comments

@excid3
Copy link
Owner

excid3 commented Apr 23, 2021

Web Push requires a service worker and a model to work.

https://blog.mozilla.org/services/2016/08/23/sending-vapid-identified-webpush-notifications-via-mozillas-push-service/

The Webpush gem provides some helpful features for generating VAPID keys, etc.

Some sample code:

class DeliveryMethods::Webpush < Noticed::DeliveryMethods::Base
  def deliver
    recipient.webpush_subscriptions.each do |sub|
      sub.publish(params[:message])
    end
  end
end
# == Schema Information
#
# Table name: webpush_subscriptions
#
#  id         :bigint           not null, primary key
#  endpoint   :string
#  auth_key   :string
#  p256dh_key :string
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  user_id    :bigint           not null
#
class WebpushSubscription < ApplicationRecord
  belongs_to :user

  def publish(message)
    Webpush.payload_send(
      message: message,
      endpoint: endpoint,
      p256dh: p256dh_key,
      auth: auth_key,
      vapid: {
        private_key: Rails.application.credentials.dig(:webpush, :private_key),
        public_key: Rails.application.credentials.dig(:webpush, :public_key)
      }
    )
  end
end
class WebpushSubscriptionsController < ApplicationController
  skip_before_action :verify_authenticity_token

  def index
  end

  def create
    notification = WebpushNotification.find_by(auth_key: params[:keys][:auth])
    if !notification
      notification = WebpushNotification.new(
        user: current_user,
        endpoint: params[:endpoint],
        auth_key: params[:keys][:auth],
        p256dh_key: params[:keys][:p256dh],
      )
    end

    if notification.save
      render json: notification
    else
      render json: notification.errors.full_messages
    end
  end
end
   const vapidPublicKey = new Uint8Array(<%= Base64.urlsafe_decode64(Rails.application.credentials.dig(:webpush, :public_key)).bytes %>);

  // application.js
  // Register the serviceWorker script at /serviceworker.js from your server if supported
  if (navigator.serviceWorker) {
    navigator.serviceWorker.register('/service_worker.js')
      .then(function(reg) {
        navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
          serviceWorkerRegistration.pushManager
          .subscribe({
            userVisibleOnly: true,
            applicationServerKey: vapidPublicKey
          }).then(async function(sub) {
            const data = await fetch('/webpush_subscriptions', {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json',
              },
              body: JSON.stringify(sub),
            }).then(r => r.json());
            console.log(data);
          });
        });
      });
  } else {
    console.error('Service worker is not supported in this browser');
  }
@excid3 excid3 added the enhancement New feature or request label Apr 23, 2021
@uurcank
Copy link

uurcank commented Apr 23, 2021

@excid3 push endpoints expire after a while.

Webpush gem method has a method to check for expired endpoints. I use that to clean up the database

Not sure if it can be part of this gem but might be worth considering

@uurcank
Copy link

uurcank commented Apr 23, 2021

something like this

rescue Webpush::Unauthorized
# skip for now
rescue Webpush::ExpiredSubscription
sub.destroy
end

which can rescue publish method

@excid3
Copy link
Owner Author

excid3 commented Apr 23, 2021

Good to know about the expirations. 👍 I haven't tried this out before, so lots to learn.

@uurcank
Copy link

uurcank commented Apr 27, 2021

@excid3 service worker has an event called 'pushsubscriptionchange' when the push endpoint expires, the event gets triggered which can be used to create another push endpoint in the background.

something like this

// Update push subscription if any change is detected
function onPushSubcriptionChange(event) {
  event.waitUntil(swRegistration.pushManager.subscribe(event.oldSubscription.options)
    .then(subscription => {

      const data = {
        subscription: subscription,
       };

      return fetch("/notifications/create", {
        method: "post",
        headers: {
          "Content-type": "application/json"
        },
            body: JSON.stringify(data),
      });
    })
  );

}

self.addEventListener('pushsubscriptionchange', onPushSubcriptionChange);

I am curious how you will choose to handle that. I could not see a way to update an existing subscription record so using those rescue methods to clean up the database and create a new subscription. There is not an identifier to use I think

there is also this idea to include service worker as part of asset pipeline or webpacker

@Tonksthebear
Copy link

Not sure if this is still being considered for Noticed but big news today for WebPush. I've never bothered looking into WebPush until iOS/iPadOS devices supported it but it seems like WebPush will be becoming much more popular now

@jbennett
Copy link

jbennett commented Jul 5, 2023

I created a video walking through setting this up with full support for iOS clients even. Was wondering if there would be interest in getting this pulled in as a PR. My big question would be around what the javascript resources would look like since so much of that is going to be custom.

Video Link: https://youtu.be/WHZ4strj6_U
Backing repo: https://github.com/jbennett/web_push_notifications

@jbennett
Copy link

jbennett commented Jul 6, 2023

I added a PR to automated most of the WebPush setup: #297

@excid3
Copy link
Owner Author

excid3 commented Jul 8, 2023

Thanks @jbennett can't wait to check this out!

Repository owner locked and limited conversation to collaborators Oct 31, 2023
@Kentasmic Kentasmic converted this issue into discussion #338 Oct 31, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants