mirror of
https://github.com/codeninjasllc/discourse.git
synced 2025-02-17 04:01:29 -05:00
FEATURE: backend support for pushing notifications to clients
This commit is contained in:
parent
2b15919aee
commit
4fe52c8cbe
5 changed files with 108 additions and 0 deletions
28
app/jobs/regular/push_notification.rb
Normal file
28
app/jobs/regular/push_notification.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
module Jobs
|
||||
class PushNotification < Jobs::Base
|
||||
def execute(args)
|
||||
notification = args["payload"]
|
||||
notification["url"] = UrlHelper.absolute(notification["post_url"])
|
||||
notification.delete("post_url")
|
||||
|
||||
payload = {
|
||||
secret_key: SiteSetting.push_api_secret_key,
|
||||
url: Discourse.base_url,
|
||||
title: SiteSetting.title,
|
||||
description: SiteSetting.site_description,
|
||||
}
|
||||
|
||||
clients = args["clients"]
|
||||
clients.group_by{|r| r[1]}.each do |push_url, group|
|
||||
notifications = group.map do |client_id, _|
|
||||
notification.merge({
|
||||
client_id: client_id
|
||||
})
|
||||
end
|
||||
|
||||
RestClient.send :post, push_url, payload.merge({notifications: notifications})
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -388,12 +388,26 @@ class PostAlerter
|
|||
}
|
||||
|
||||
MessageBus.publish("/notification-alert/#{user.id}", payload, user_ids: [user.id])
|
||||
push_notification(user, payload)
|
||||
DiscourseEvent.trigger(:post_notification_alert, user, payload)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def push_notification(user, payload)
|
||||
if SiteSetting.allow_push_user_api_keys && SiteSetting.allowed_user_api_push_urls.present?
|
||||
clients = user.user_api_keys
|
||||
.where('push AND push_url IS NOT NULL AND position(push_url in ?) > 0 AND revoked_at IS NULL',
|
||||
SiteSetting.allowed_user_api_push_urls)
|
||||
.pluck(:client_id, :push_url)
|
||||
|
||||
if clients.length > 0
|
||||
Jobs.enqueue(:push_notification, clients: clients, payload: payload, user_id: user.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def expand_group_mentions(groups, post)
|
||||
return unless post.user && groups
|
||||
|
||||
|
|
|
@ -7,6 +7,11 @@ reload_settings = lambda {
|
|||
RailsMultisite::ConnectionManagement.each_connection do
|
||||
begin
|
||||
SiteSetting.refresh!
|
||||
|
||||
unless String === SiteSetting.push_api_secret_key && SiteSetting.push_api_secret_key.length == 32
|
||||
SiteSetting.push_api_secret_key = SecureRandom.hex
|
||||
end
|
||||
|
||||
rescue ActiveRecord::StatementInvalid
|
||||
# This will happen when migrating a new database
|
||||
rescue => e
|
||||
|
|
|
@ -1270,11 +1270,14 @@ user_api:
|
|||
default: true
|
||||
max_api_keys_per_user:
|
||||
default: 10
|
||||
push_api_secret_key:
|
||||
hidden: true
|
||||
min_trust_level_for_user_api_key:
|
||||
default: 1
|
||||
allowed_user_api_push_urls:
|
||||
default: ''
|
||||
type: list
|
||||
shadowed_by_global: true
|
||||
allowed_user_api_auth_redirects:
|
||||
default: 'https://api.discourse.org/api/auth_redirect|discourse://auth_redirect'
|
||||
type: list
|
||||
|
|
|
@ -326,6 +326,64 @@ describe PostAlerter do
|
|||
end
|
||||
end
|
||||
|
||||
describe "push_notification" do
|
||||
let(:mention_post) { create_post_with_alerts(user: user, raw: 'Hello @eviltrout')}
|
||||
let(:topic) { mention_post.topic }
|
||||
|
||||
it "correctly pushes notifications if configured correctly" do
|
||||
SiteSetting.allowed_user_api_push_urls = "https://site.com/push|https://site2.com/push"
|
||||
|
||||
2.times do |i|
|
||||
UserApiKey.create!(user_id: evil_trout.id,
|
||||
client_id: "xxx#{i}",
|
||||
key: "yyy#{i}",
|
||||
application_name: "iPhone#{i}",
|
||||
read: true,
|
||||
write: true,
|
||||
push: true,
|
||||
push_url: "https://site2.com/push")
|
||||
end
|
||||
|
||||
# I want to test payload ... but we have chicked egg problem
|
||||
# if I test it then it makes the req and the the expects is not correct ...
|
||||
# need to track all reqs in rest client and check after the fact
|
||||
|
||||
# payload = {
|
||||
# secret_key: SiteSetting.push_api_secret_key,
|
||||
# url: Discourse.base_url,
|
||||
# title: SiteSetting.title,
|
||||
# description: SiteSetting.site_description,
|
||||
# notifications: [
|
||||
# {
|
||||
# 'notification_type' => 1,
|
||||
# 'post_number' => 1,
|
||||
# 'topic_title' => topic.title,
|
||||
# 'topic_id' => topic.id,
|
||||
# 'excerpt' => 'Hello @eviltrout',
|
||||
# 'username' => user.username,
|
||||
# 'url' => UrlHelper.absolute(mention_post.url),
|
||||
# 'client_id' => 'xxx0'
|
||||
# },
|
||||
# {
|
||||
# 'notification_type' => 1,
|
||||
# 'post_number' => 1,
|
||||
# 'topic_title' => topic.title,
|
||||
# 'topic_id' => topic.id,
|
||||
# 'excerpt' => 'Hello @eviltrout',
|
||||
# 'username' => user.username,
|
||||
# 'url' => UrlHelper.absolute(mention_post.url),
|
||||
# 'client_id' => 'xxx1'
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
|
||||
# should only happen once even though we are using 2 keys
|
||||
RestClient.expects(:post).returns("OK")
|
||||
|
||||
mention_post
|
||||
end
|
||||
end
|
||||
|
||||
describe "watching_first_post" do
|
||||
let(:group) { Fabricate(:group) }
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
|
Loading…
Reference in a new issue