Skip to content

Commit 89bd01c

Browse files
committed
Add some basic validation for gcm payloads
1 parent 5a13c4c commit 89bd01c

File tree

1 file changed

+59
-5
lines changed

1 file changed

+59
-5
lines changed

lib/pusher/native_notification/client.rb

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ class Client
55

66
API_PREFIX = "customer_api"
77
API_VERSION = "v1"
8+
GCM_TTL = 241920
9+
RESTRICTED_GCM_PAYLOAD_KEYS = [:to, :registration_ids]
810

911
def initialize(app_id, host, pusher_client)
1012
@app_id = app_id
@@ -42,21 +44,73 @@ def notify(interests, data = {})
4244
def payload(interests, data)
4345
interests = Array(interests).map(&:to_s)
4446

47+
raise Pusher::Error, "Too many interests provided" if interests.length > 1
48+
4549
payload = { interests: interests }
4650

47-
unless (data.has_key?(:apns) || data.has_key?(:gcm))
48-
raise Pusher::Error, "GCM or APNS data must be provided"
49-
end
51+
data = deep_symbolize_keys!(data)
52+
validate_payload(data)
5053

51-
payload.merge({ gcm: data[:gcm] }) if data.has_key?(:gcm)
52-
payload.merge({ apns: data[:apns] }) if data.has_key?(:apns)
54+
payload.merge!({ gcm: data[:gcm] }) if data.has_key?(:gcm)
55+
payload.merge!({ apns: data[:apns] }) if data.has_key?(:apns)
5356

5457
MultiJson.encode(payload)
5558
end
5659

5760
def url(path = nil)
5861
URI.parse("https://#{@host}/#{API_PREFIX}/#{API_VERSION}/apps/#{@app_id}#{path}")
5962
end
63+
64+
# Validate payload
65+
# `time_to_live` -> value b/w 0 and 241920
66+
# If the `notification` key is provided, ensure
67+
# that there is an accompanying `title` and `icon`
68+
# field
69+
def validate_payload(payload)
70+
# Restricted keys
71+
RESTRICTED_GCM_PAYLOAD_KEYS.each { |k| payload.delete(k) }
72+
73+
unless (payload.has_key?(:apns) || payload.has_key?(:gcm))
74+
raise Pusher::Error, "GCM or APNS data must be provided"
75+
end
76+
77+
if payload.has_key?(:gcm)
78+
gcm_payload = payload[:gcm]
79+
80+
if gcm_payload.has_key?(:time_to_live)
81+
ttl = gcm_payload[:time_to_live].to_i
82+
83+
if ttl < 0 || ttl > GCM_TTL
84+
raise Pusher::Error, "time_to_live key must have a value between 0 and 241920 (4 weeks)"
85+
end
86+
end
87+
88+
# If the notification key is provided
89+
# validate the `icon` and `title`keys
90+
if gcm_payload.has_key?(:notification)
91+
notification_title, notification_icon = gcm_payload[:notification].values_at(:title, :icon)
92+
93+
if (!notification_title || notification_title.empty?)
94+
raise Pusher::Error, "Notification title is a required field"
95+
end
96+
97+
if (!notification_icon || notification_icon.empty?)
98+
raise Pusher::Error, "Notification icon is a required field"
99+
end
100+
end
101+
end
102+
end
103+
104+
# Symbolize all keys in the hash recursively
105+
def deep_symbolize_keys!(hash)
106+
hash.keys.each do |k|
107+
ks = k.respond_to?(:to_sym) ? k.to_sym : k
108+
hash[ks] = hash.delete(k)
109+
deep_symbolize_keys!(hash[ks]) if hash[ks].kind_of?(Hash)
110+
end
111+
112+
hash
113+
end
60114
end
61115
end
62116
end

0 commit comments

Comments
 (0)