From eef2cc054faaa808cb014d644317fbc398f6c75f Mon Sep 17 00:00:00 2001
From: Emelia Smith <ThisIsMissEm@users.noreply.github.com>
Date: Wed, 5 Jun 2024 10:06:06 +0200
Subject: [PATCH] Add url validation to Web::PushSubscription endpoints
 (#30540)

---
 app/models/web/push_subscription.rb             |  2 +-
 spec/requests/api/v1/push/subscriptions_spec.rb | 15 ++++++++++++++-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/app/models/web/push_subscription.rb b/app/models/web/push_subscription.rb
index a3a2ec3f0..1860f0aa3 100644
--- a/app/models/web/push_subscription.rb
+++ b/app/models/web/push_subscription.rb
@@ -21,7 +21,7 @@ class Web::PushSubscription < ApplicationRecord
 
   has_one :session_activation, foreign_key: 'web_push_subscription_id', inverse_of: :web_push_subscription, dependent: nil
 
-  validates :endpoint, presence: true
+  validates :endpoint, presence: true, url: true
   validates :key_p256dh, presence: true
   validates :key_auth, presence: true
 
diff --git a/spec/requests/api/v1/push/subscriptions_spec.rb b/spec/requests/api/v1/push/subscriptions_spec.rb
index 700250ee2..82ea308cd 100644
--- a/spec/requests/api/v1/push/subscriptions_spec.rb
+++ b/spec/requests/api/v1/push/subscriptions_spec.rb
@@ -4,10 +4,11 @@ require 'rails_helper'
 
 describe 'API V1 Push Subscriptions' do
   let(:user) { Fabricate(:user) }
+  let(:endpoint) { 'https://fcm.googleapis.com/fcm/send/fiuH06a27qE:APA91bHnSiGcLwdaxdyqVXNDR9w1NlztsHb6lyt5WDKOC_Z_Q8BlFxQoR8tWFSXUIDdkyw0EdvxTu63iqamSaqVSevW5LfoFwojws8XYDXv_NRRLH6vo2CdgiN4jgHv5VLt2A8ah6lUX' }
   let(:create_payload) do
     {
       subscription: {
-        endpoint: 'https://fcm.googleapis.com/fcm/send/fiuH06a27qE:APA91bHnSiGcLwdaxdyqVXNDR9w1NlztsHb6lyt5WDKOC_Z_Q8BlFxQoR8tWFSXUIDdkyw0EdvxTu63iqamSaqVSevW5LfoFwojws8XYDXv_NRRLH6vo2CdgiN4jgHv5VLt2A8ah6lUX',
+        endpoint: endpoint,
         keys: {
           p256dh: 'BEm_a0bdPDhf0SOsrnB2-ategf1hHoCnpXgQsFj5JCkcoMrMt2WHoPfEYOYPzOIs9mZE8ZUaD7VA5vouy0kEkr8=',
           auth: 'eH_C8rq2raXqlcBVDa1gLg==',
@@ -63,6 +64,18 @@ describe 'API V1 Push Subscriptions' do
       expect(endpoint_push_subscriptions.count)
         .to eq(1)
     end
+
+    context 'with invalid endpoint URL' do
+      let(:endpoint) { 'app://example.foo' }
+
+      it 'returns a validation error' do
+        subject
+
+        expect(response).to have_http_status(422)
+        expect(endpoint_push_subscriptions.count).to eq(0)
+        expect(endpoint_push_subscription).to be_nil
+      end
+    end
   end
 
   describe 'PUT /api/v1/push/subscription' do