From 9765e2826a36c5668e6995545ebfbae327eb411a Mon Sep 17 00:00:00 2001 From: Sebastian Plattner Date: Mon, 20 Aug 2018 11:57:09 +0200 Subject: [PATCH 01/19] Initial try with webhook --- app/models/issue.rb | 1 + lib/staytus/webhook.rb | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 lib/staytus/webhook.rb diff --git a/app/models/issue.rb b/app/models/issue.rb index 4d50d3ac..57955f1c 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -81,6 +81,7 @@ def update_service_statuses end def send_notifications + Staytus::Webhook.call(:issue => self) for subscriber in Subscriber.verified Staytus::Email.deliver(subscriber, :new_issue, :issue => self, :update => self.updates.order(:id).first) end diff --git a/lib/staytus/webhook.rb b/lib/staytus/webhook.rb new file mode 100644 index 00000000..e8094dcf --- /dev/null +++ b/lib/staytus/webhook.rb @@ -0,0 +1,17 @@ +module Staytus + class Webhook + + class << self + + # + # Send an email to the given recipient + # + def call(attributes = {}) + logger.info "Webhook" + logger.info attributes.issue.to_json + + end + + end + end +end From 082224d22a231ae7c03e403ba689e70b6bccb309 Mon Sep 17 00:00:00 2001 From: Sebastian Plattner Date: Mon, 20 Aug 2018 13:04:33 +0200 Subject: [PATCH 02/19] Fix output --- lib/staytus/webhook.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/staytus/webhook.rb b/lib/staytus/webhook.rb index e8094dcf..d7b63f3e 100644 --- a/lib/staytus/webhook.rb +++ b/lib/staytus/webhook.rb @@ -7,8 +7,8 @@ class << self # Send an email to the given recipient # def call(attributes = {}) - logger.info "Webhook" - logger.info attributes.issue.to_json + puts "Webhook" + puts attributes.issue.to_json end From 5faf510fca9f40cb5c5b9b040b8fc1c135f59fea Mon Sep 17 00:00:00 2001 From: Sebastian Plattner Date: Wed, 22 Aug 2018 11:06:27 +0200 Subject: [PATCH 03/19] First Version for Webhooks --- app/controllers/admin/webhooks_controller.rb | 44 ++++++++ app/models/issue.rb | 2 +- app/models/issue_update.rb | 1 + app/models/webhook.rb | 18 ++++ app/views/admin/settings/index.html.haml | 9 +- app/views/admin/webhooks/_form.html.haml | 19 ++++ app/views/admin/webhooks/edit.html.haml | 4 + app/views/admin/webhooks/index.html.haml | 19 ++++ app/views/admin/webhooks/new.html.haml | 4 + config/routes.rb | 1 + db/migrate/20180821114121_create_webhooks.rb | 12 +++ lib/staytus/webhook.rb | 17 --- lib/staytus/webhookcaller.rb | 108 +++++++++++++++++++ 13 files changed, 238 insertions(+), 20 deletions(-) create mode 100644 app/controllers/admin/webhooks_controller.rb create mode 100644 app/models/webhook.rb create mode 100644 app/views/admin/webhooks/_form.html.haml create mode 100644 app/views/admin/webhooks/edit.html.haml create mode 100644 app/views/admin/webhooks/index.html.haml create mode 100644 app/views/admin/webhooks/new.html.haml create mode 100644 db/migrate/20180821114121_create_webhooks.rb delete mode 100644 lib/staytus/webhook.rb create mode 100644 lib/staytus/webhookcaller.rb diff --git a/app/controllers/admin/webhooks_controller.rb b/app/controllers/admin/webhooks_controller.rb new file mode 100644 index 00000000..157ec5a5 --- /dev/null +++ b/app/controllers/admin/webhooks_controller.rb @@ -0,0 +1,44 @@ +class Admin::WebhooksController < Admin::BaseController + + before_action { params[:id] && @webhook = Webhook.find(params[:id]) } + + def index + @webhooks = Webhook.ordered + end + + def new + @webhook = Webhook.new + end + + def create + @webhook = Webhook.new(safe_params) + if @webhook.save + redirect_to admin_webhooks_path, :notice => "#{@webhook.name} has been added successfully." + else + render 'new' + end + end + + def edit + end + + def update + if @webhook.update_attributes(safe_params) + redirect_to admin_webhooks_path, :notice => "#{@webhook.name} has been updated successfully." + else + render 'edit' + end + end + + def destroy + @webhook.destroy + redirect_to admin_webhooks_path, :notice => "#{@webhook.name} has been removed successfully." + end + + private + + def safe_params + params.require(:webhook).permit(:name, :url) + end + +end diff --git a/app/models/issue.rb b/app/models/issue.rb index 57955f1c..d8761e5e 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -81,7 +81,7 @@ def update_service_statuses end def send_notifications - Staytus::Webhook.call(:issue => self) + Staytus::Webhookcaller.call('issue_new', :detail => self) for subscriber in Subscriber.verified Staytus::Email.deliver(subscriber, :new_issue, :issue => self, :update => self.updates.order(:id).first) end diff --git a/app/models/issue_update.rb b/app/models/issue_update.rb index 492e33c8..4530434a 100644 --- a/app/models/issue_update.rb +++ b/app/models/issue_update.rb @@ -52,6 +52,7 @@ def update_base_issue end def send_notifications + Staytus::Webhookcaller.call('issue_update', :detail => self) for subscriber in Subscriber.verified Staytus::Email.deliver(subscriber, :new_issue_update, :issue => self.issue, :update => self) end diff --git a/app/models/webhook.rb b/app/models/webhook.rb new file mode 100644 index 00000000..106a033f --- /dev/null +++ b/app/models/webhook.rb @@ -0,0 +1,18 @@ +# == Schema Information +# +# Table name: webhooks +# +# id :integer not null, primary key +# name :string(255) +# url :string(255) + + +class Webhook < ActiveRecord::Base + + validates :name, :presence => true + validates :url, :presence => true + + + scope :ordered, -> { order(:name => :asc) } + +end diff --git a/app/views/admin/settings/index.html.haml b/app/views/admin/settings/index.html.haml index 50cd023e..629fc874 100644 --- a/app/views/admin/settings/index.html.haml +++ b/app/views/admin/settings/index.html.haml @@ -40,5 +40,10 @@ .navGrid__item = image_tag 'icons/email_templates.svg' %p= link_to "E-Mail Templates", admin_email_templates_path - %p.navGrid__text Customize the content of the emails which are sent to people who subscribe to your site by e-mail. - + %p.navGrid__text Customize the content of the emails which are sent to people who subscribe to your site by e-mail +.navGrid + .navGrid__item + = image_tag 'icons/api_tokens.svg' + %p= link_to "Webhooks", admin_webhooks_path + %p.navGrid__text Manage Webhooks + .navGrid__item diff --git a/app/views/admin/webhooks/_form.html.haml b/app/views/admin/webhooks/_form.html.haml new file mode 100644 index 00000000..3f3e874d --- /dev/null +++ b/app/views/admin/webhooks/_form.html.haml @@ -0,0 +1,19 @@ += form_for [:admin, @webhook] do |f| + = f.error_messages + .fieldSet.u-margin-2x + .row + .col.col--10 + %dl.fieldSet__field.u-margin + %dt.fieldSet__label= f.label :name + %dd.fieldSet__input= f.text_field :name, :class => 'textInput', :autofocus => true, :required => true + .col.col--10 + %dl.fieldSet__field.u-margin + %dt.fieldSet__label= f.label :url, "Webhook URL" + %dd.fieldSet__input= f.text_field :url, :class => 'textInput', :required => true + + + .formButtons + - unless @webhook.new_record? + .formButtons__secondary= link_to "Delete Webhook", [:admin, @webhook], :class => 'button button--grey button--solid', :method => :delete, :data => {:confirm => "Are you sure you wish to delete #{@webhook.name}?"}, :tabindex => -1 + = f.submit "Save Webhook", :class => 'button button--solid' + = link_to "Cancel", admin_webhooks_path, :class => 'button button--lightGrey' diff --git a/app/views/admin/webhooks/edit.html.haml b/app/views/admin/webhooks/edit.html.haml new file mode 100644 index 00000000..ef1afc0c --- /dev/null +++ b/app/views/admin/webhooks/edit.html.haml @@ -0,0 +1,4 @@ +- @active_nav_item = :settings += content_for :page_header do + .pageHeader__heading= @page_title = 'Edit Webhook' += render 'form' diff --git a/app/views/admin/webhooks/index.html.haml b/app/views/admin/webhooks/index.html.haml new file mode 100644 index 00000000..b2e8a8cf --- /dev/null +++ b/app/views/admin/webhooks/index.html.haml @@ -0,0 +1,19 @@ +- @active_nav_item = :settings += content_for :page_header do + .pageHeader__button= link_to "Add New Webhook", new_admin_webhook_path, :class => 'button button--green button--small button--solid' + .pageHeader__heading.u-margin= @page_title = 'Webhooks' + %p.u-intro + Send Data to Webhook + +%table.dataTable.u-margin + %thead + %tr + %td{:width => '35%'} Name + %td{:width => '45%'} URL + %td{:width => '20%'} + %tbody + - for webhook in @webhooks + %tr + %td= link_to webhook.name, [:edit, :admin, webhook], :class => 'u-underline ' + %td= webhook.url + %td.u-align-right= link_to "Edit", [:edit, :admin, webhook], :class => 'button button--small' diff --git a/app/views/admin/webhooks/new.html.haml b/app/views/admin/webhooks/new.html.haml new file mode 100644 index 00000000..908ed50f --- /dev/null +++ b/app/views/admin/webhooks/new.html.haml @@ -0,0 +1,4 @@ +- @active_nav_item = :settings += content_for :page_header do + .pageHeader__heading= @page_title = 'Add new Webhook' += render 'form' diff --git a/config/routes.rb b/config/routes.rb index 857a1d94..7902b7d5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -20,6 +20,7 @@ resources :service_groups resources :email_templates, :only => [:index, :edit, :update, :destroy] resources :api_tokens + resources :webhooks # # Issues diff --git a/db/migrate/20180821114121_create_webhooks.rb b/db/migrate/20180821114121_create_webhooks.rb new file mode 100644 index 00000000..6d0d32b3 --- /dev/null +++ b/db/migrate/20180821114121_create_webhooks.rb @@ -0,0 +1,12 @@ +class CreateWebhooks < ActiveRecord::Migration[5.1] + def self.up + create_table :webhooks do |table| + table.string :name, null: false # Name of the Webhook + table.string :url, null: false # URL of the Webhook + end + end + + def self.down + drop_table :webhooks + end +end diff --git a/lib/staytus/webhook.rb b/lib/staytus/webhook.rb deleted file mode 100644 index d7b63f3e..00000000 --- a/lib/staytus/webhook.rb +++ /dev/null @@ -1,17 +0,0 @@ -module Staytus - class Webhook - - class << self - - # - # Send an email to the given recipient - # - def call(attributes = {}) - puts "Webhook" - puts attributes.issue.to_json - - end - - end - end -end diff --git a/lib/staytus/webhookcaller.rb b/lib/staytus/webhookcaller.rb new file mode 100644 index 00000000..f087141a --- /dev/null +++ b/lib/staytus/webhookcaller.rb @@ -0,0 +1,108 @@ +module Staytus + class Webhookcaller + + class << self + + # + # Send an Data to a webhook + # + def call(type, attributes = {}) + + + # Get Detail data and add staytus_type to identify the Event + data = attributes[:detail].as_json + + message = {} + message["type"] = type + + # Empty if type is not available + message_data = {} + + if ['issue_new'].include? type + # Get Issue which was updated + issue = attributes[:detail].as_json + issue["services"] = [] + + # Add all affected services and the Service Status + issueJoins = IssueServiceJoin.where(issue_id: issue["id"]) + issueJoins.all.each do |issueJoin| + service = Service.find(issueJoin[:service_id]).as_json + + # Join Service Status for human readable text + service_status = ServiceStatus.find(service["status_id"]).as_json + service["status"] = service_status + + issue["services"].push(service) + + + + end + + # Add last Update + issueupdate = IssueUpdate.where(id: data["id"]).last.as_json + issue["updates"] = issueupdate + + message_data = issue + end + + if ['issue_update'].include? type + + # Get Issue which was updated + issue = Issue.find(data["issue_id"]).as_json + issue["services"] = [] + + # Add all affected services and the Service Status + issueJoins = IssueServiceJoin.where(issue_id: data["issue_id"]) + issueJoins.all.each do |issueJoin| + service = Service.find(issueJoin[:service_id]).as_json + + # Join Service Status for human readable text + service_status = ServiceStatus.find(service["status_id"]).as_json + service["status"] = service_status + + issue["services"].push(service) + + end + + # Add last Update + issueupdate = IssueUpdate.where(id: data["id"]).last.as_json + issue["updates"] = issueupdate + + message_data = issue + + end + + message["data"] = message_data + + Webhook.all.each do |webhook| + + puts "Call Webhook " + webhook.name + " with URL: " + webhook.url + + header = {'Content-Type': 'application/json'} + + uri = URI(webhook.url) + + # Create the HTTP objects + http = Net::HTTP.new(uri.host, uri.port) + if uri.scheme == "https" + http.use_ssl = true + end + request = Net::HTTP::Post.new(uri.request_uri, header) + + request.body = message.to_json + puts message.to_json + + response = http.request(request) + # Send the request + #begin + + #rescue StandardError + # Ignore if failed! + #end + + end + end # call + + end + end +end From 44a157c33ad31401ff6183ea76afe407cfa34fb8 Mon Sep 17 00:00:00 2001 From: Sebastian Plattner Date: Wed, 22 Aug 2018 11:18:40 +0200 Subject: [PATCH 04/19] Some cleanup and RocketChat JS Code --- app/views/admin/settings/index.html.haml | 6 +-- app/views/admin/webhooks/index.html.haml | 2 +- doc/webhooks/rocketchat_integration.js | 57 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 doc/webhooks/rocketchat_integration.js diff --git a/app/views/admin/settings/index.html.haml b/app/views/admin/settings/index.html.haml index 629fc874..58ded1ab 100644 --- a/app/views/admin/settings/index.html.haml +++ b/app/views/admin/settings/index.html.haml @@ -32,7 +32,7 @@ = image_tag 'icons/services.svg' %p= link_to "Service Groups", admin_service_groups_path %p.navGrid__text Configure the different groups which can be assigned to the services you're reporting on. -.navGrid +.navGrid.u-margin-2x .navGrid__item = image_tag 'icons/api_tokens.svg' %p= link_to "API Tokens", admin_api_tokens_path @@ -41,9 +41,9 @@ = image_tag 'icons/email_templates.svg' %p= link_to "E-Mail Templates", admin_email_templates_path %p.navGrid__text Customize the content of the emails which are sent to people who subscribe to your site by e-mail -.navGrid +.navGrid.u-margin-2x .navGrid__item = image_tag 'icons/api_tokens.svg' %p= link_to "Webhooks", admin_webhooks_path - %p.navGrid__text Manage Webhooks + %p.navGrid__text Manage Webhooks which are triggered on new or update Issue .navGrid__item diff --git a/app/views/admin/webhooks/index.html.haml b/app/views/admin/webhooks/index.html.haml index b2e8a8cf..a3a7f591 100644 --- a/app/views/admin/webhooks/index.html.haml +++ b/app/views/admin/webhooks/index.html.haml @@ -3,7 +3,7 @@ .pageHeader__button= link_to "Add New Webhook", new_admin_webhook_path, :class => 'button button--green button--small button--solid' .pageHeader__heading.u-margin= @page_title = 'Webhooks' %p.u-intro - Send Data to Webhook + Call Webhooks when a new Issue is created or an existing Issue is updated %table.dataTable.u-margin %thead diff --git a/doc/webhooks/rocketchat_integration.js b/doc/webhooks/rocketchat_integration.js new file mode 100644 index 00000000..19161f1d --- /dev/null +++ b/doc/webhooks/rocketchat_integration.js @@ -0,0 +1,57 @@ +class Script { + /** + * @params {object} request + */ + process_incoming_request({ request }) { + // request.url.hash + // request.url.search + // request.url.query + // request.url.pathname + // request.url.path + // request.url_raw + // request.url_params + // request.headers + // request.user._id + // request.user.name + // request.user.username + // request.content_raw + // request.content + + var staytus_url = "http://localhost:3000" + + + var staytus = request.content; + var message = {}; + message.attachement = []; + + var attachement = {} + attachement.title = staytus.data.title + " (" + staytus.data.updates.state + ")"; + attachement.title_link = staytus_url + "/issue/" + staytus.data.identifier; + attachement.text = staytus.data.updates.text; + attachement.text += "\n\nAffected Services:"; + message.attachement.push(attachement); + + + // Add more attachements for each affected Service + if (staytus.data.services.length > 0) { + for (i = 0; i < staytus.data.services.length; i++) { + var status_attachement = {} + status_attachement.text = " - " + staytus.data.services[i].name + " : " + staytus.data.services[i].status.name + status_attachement.color = "#" + staytus.data.services[i].status.color + message.attachement.push(status_attachement); + } + } else { + var status_attachement = {} + status_attachement.text = " - none"; + message.attachement.push(status_attachement); + } + + return { + content:{ + text: "", + "attachments": message.attachement + } + }; + + } +} From e064f33cd74610f1b45e8ddaaa781edbde6e43ff Mon Sep 17 00:00:00 2001 From: Sebastian Plattner Date: Wed, 22 Aug 2018 11:35:26 +0200 Subject: [PATCH 05/19] Catch Errors with http request to not block --- lib/staytus/webhookcaller.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/staytus/webhookcaller.rb b/lib/staytus/webhookcaller.rb index f087141a..e70b5f7c 100644 --- a/lib/staytus/webhookcaller.rb +++ b/lib/staytus/webhookcaller.rb @@ -90,15 +90,13 @@ def call(type, attributes = {}) request = Net::HTTP::Post.new(uri.request_uri, header) request.body = message.to_json - puts message.to_json - response = http.request(request) # Send the request - #begin - - #rescue StandardError + begin + response = http.request(request) + rescue StandardError # Ignore if failed! - #end + end end end # call From 46948e518aba246990ac488ce59ecff6cf05fb06 Mon Sep 17 00:00:00 2001 From: Sebastian Plattner Date: Mon, 27 Aug 2018 12:00:50 +0200 Subject: [PATCH 06/19] Call webhook even without Notification set --- app/models/issue.rb | 1 - app/models/issue_update.rb | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/models/issue.rb b/app/models/issue.rb index d8761e5e..4d50d3ac 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -81,7 +81,6 @@ def update_service_statuses end def send_notifications - Staytus::Webhookcaller.call('issue_new', :detail => self) for subscriber in Subscriber.verified Staytus::Email.deliver(subscriber, :new_issue, :issue => self, :update => self.updates.order(:id).first) end diff --git a/app/models/issue_update.rb b/app/models/issue_update.rb index 4530434a..b8091fda 100644 --- a/app/models/issue_update.rb +++ b/app/models/issue_update.rb @@ -52,16 +52,23 @@ def update_base_issue end def send_notifications - Staytus::Webhookcaller.call('issue_update', :detail => self) for subscriber in Subscriber.verified Staytus::Email.deliver(subscriber, :new_issue_update, :issue => self.issue, :update => self) end end + def call_webhook + Staytus::Webhookcaller.call('issue_update', :detail => self) + end + def send_notifications_on_create + if self.notify? delay.send_notifications end + + self.delay.call_webhook + end end From 02c0bdbd6f3d63e55aadb5ad0ba398bd0c9c324d Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Tue, 26 Feb 2019 17:48:14 +0100 Subject: [PATCH 07/19] Updated schema which includes the webhook table --- db/schema.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index bd1ae1a5..16f314f4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180425131827) do +ActiveRecord::Schema.define(version: 20180821114121) do create_table "api_tokens", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci" do |t| t.string "name" @@ -228,4 +228,9 @@ t.datetime "updated_at", null: false end + create_table "webhooks", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| + t.string "name", null: false + t.string "url", null: false + end + end From e7226c8c27523ddaaad2c1cccfb0e2cd2ead9fc2 Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Tue, 26 Feb 2019 17:52:30 +0100 Subject: [PATCH 08/19] adding new icon for webhook --- app/assets/images/icons/webhooks.svg | 3 +++ app/views/admin/settings/index.html.haml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 app/assets/images/icons/webhooks.svg diff --git a/app/assets/images/icons/webhooks.svg b/app/assets/images/icons/webhooks.svg new file mode 100644 index 00000000..1356bdb5 --- /dev/null +++ b/app/assets/images/icons/webhooks.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/views/admin/settings/index.html.haml b/app/views/admin/settings/index.html.haml index 58ded1ab..3e638194 100644 --- a/app/views/admin/settings/index.html.haml +++ b/app/views/admin/settings/index.html.haml @@ -43,7 +43,7 @@ %p.navGrid__text Customize the content of the emails which are sent to people who subscribe to your site by e-mail .navGrid.u-margin-2x .navGrid__item - = image_tag 'icons/api_tokens.svg' + = image_tag 'icons/webhooks.svg' %p= link_to "Webhooks", admin_webhooks_path %p.navGrid__text Manage Webhooks which are triggered on new or update Issue .navGrid__item From aedb2c7f0ae748720f3b425625c5d9db4e0b430b Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Tue, 26 Feb 2019 17:53:59 +0100 Subject: [PATCH 09/19] Enhanced webhooks view: Pagination and empty table message --- app/controllers/admin/webhooks_controller.rb | 2 +- app/views/admin/webhooks/index.html.haml | 32 ++++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/app/controllers/admin/webhooks_controller.rb b/app/controllers/admin/webhooks_controller.rb index 157ec5a5..cb3a8db7 100644 --- a/app/controllers/admin/webhooks_controller.rb +++ b/app/controllers/admin/webhooks_controller.rb @@ -3,7 +3,7 @@ class Admin::WebhooksController < Admin::BaseController before_action { params[:id] && @webhook = Webhook.find(params[:id]) } def index - @webhooks = Webhook.ordered + @webhooks = Webhook.ordered.page(params[:page]) end def new diff --git a/app/views/admin/webhooks/index.html.haml b/app/views/admin/webhooks/index.html.haml index a3a7f591..dfb73af9 100644 --- a/app/views/admin/webhooks/index.html.haml +++ b/app/views/admin/webhooks/index.html.haml @@ -1,19 +1,25 @@ - @active_nav_item = :settings -= content_for :page_header do +- content_for :page_header do .pageHeader__button= link_to "Add New Webhook", new_admin_webhook_path, :class => 'button button--green button--small button--solid' - .pageHeader__heading.u-margin= @page_title = 'Webhooks' + %h1.pageHeader__heading.u-margin= @page_title = 'Webhooks' %p.u-intro Call Webhooks when a new Issue is created or an existing Issue is updated -%table.dataTable.u-margin - %thead - %tr - %td{:width => '35%'} Name - %td{:width => '45%'} URL - %td{:width => '20%'} - %tbody - - for webhook in @webhooks +- if @webhooks.empty? + .noDataArea.noDataArea--large + %p.u-margin No webhooks have been configured yet. +- else + %table.dataTable.u-margin + %thead %tr - %td= link_to webhook.name, [:edit, :admin, webhook], :class => 'u-underline ' - %td= webhook.url - %td.u-align-right= link_to "Edit", [:edit, :admin, webhook], :class => 'button button--small' + %td{:width => '35%'} Name + %td{:width => '45%'} URL + %td{:width => '20%'} + %tbody + - for webhook in @webhooks + %tr + %td= link_to webhook.name, [:edit, :admin, webhook], :class => 'u-underline ' + %td= webhook.url + %td.u-align-right= link_to "Edit", [:edit, :admin, webhook], :class => 'button button--small' + + = paginate @webhooks From 916759ae405abe938c0bf6491e61c16cca318cdf Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Tue, 26 Feb 2019 17:55:59 +0100 Subject: [PATCH 10/19] Rewrite of webhookcaller and integration of webhook notifications for maintenances --- app/models/issue.rb | 5 ++ app/models/issue_update.rb | 7 +-- app/models/maintenance.rb | 5 ++ app/models/maintenance_update.rb | 5 ++ lib/staytus/webhookcaller.rb | 102 ++++++++----------------------- 5 files changed, 42 insertions(+), 82 deletions(-) diff --git a/app/models/issue.rb b/app/models/issue.rb index 4d50d3ac..d03c8f65 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -86,10 +86,15 @@ def send_notifications end end + def call_webhook + Staytus::Webhookcaller.call(:new_issue, :object => self, :update => self.updates.last) + end + def send_notifications_on_create if self.notify? self.delay.send_notifications end + delay.call_webhook end private diff --git a/app/models/issue_update.rb b/app/models/issue_update.rb index b8091fda..ab74e62c 100644 --- a/app/models/issue_update.rb +++ b/app/models/issue_update.rb @@ -58,17 +58,14 @@ def send_notifications end def call_webhook - Staytus::Webhookcaller.call('issue_update', :detail => self) + Staytus::Webhookcaller.call(:issue_update, :object => self.issue, :update => self) end def send_notifications_on_create - if self.notify? delay.send_notifications end - - self.delay.call_webhook - + delay.call_webhook end end diff --git a/app/models/maintenance.rb b/app/models/maintenance.rb index fb579005..fde923ea 100644 --- a/app/models/maintenance.rb +++ b/app/models/maintenance.rb @@ -117,10 +117,15 @@ def send_notifications end end + def call_webhook + Staytus::Webhookcaller.call(:new_maintenance, :object => self, :update => self.updates.last) + end + def send_notifications_on_create if self.notify? self.delay.send_notifications end + delay.call_webhook end private diff --git a/app/models/maintenance_update.rb b/app/models/maintenance_update.rb index cc7730be..203e9432 100644 --- a/app/models/maintenance_update.rb +++ b/app/models/maintenance_update.rb @@ -38,10 +38,15 @@ def send_notifications end end + def call_webhook + Staytus::Webhookcaller.call(:maintenance_update, :object => self.maintenance, :update => self) + end + def send_notifications_on_create if self.notify? self.delay.send_notifications end + delay.call_webhook end end diff --git a/lib/staytus/webhookcaller.rb b/lib/staytus/webhookcaller.rb index e70b5f7c..89c26d0f 100644 --- a/lib/staytus/webhookcaller.rb +++ b/lib/staytus/webhookcaller.rb @@ -2,102 +2,50 @@ module Staytus class Webhookcaller class << self - # - # Send an Data to a webhook + # Send a message to a webhook # def call(type, attributes = {}) - - - # Get Detail data and add staytus_type to identify the Event - data = attributes[:detail].as_json - - message = {} - message["type"] = type - - # Empty if type is not available - message_data = {} - - if ['issue_new'].include? type - # Get Issue which was updated - issue = attributes[:detail].as_json - issue["services"] = [] - - # Add all affected services and the Service Status - issueJoins = IssueServiceJoin.where(issue_id: issue["id"]) - issueJoins.all.each do |issueJoin| - service = Service.find(issueJoin[:service_id]).as_json - - # Join Service Status for human readable text - service_status = ServiceStatus.find(service["status_id"]).as_json - service["status"] = service_status - - issue["services"].push(service) - - - + # Get details about caller and update object + object = attributes[:object] + update = attributes[:update] + message = { "type" => type, "data" => {} } + + # Add Maintenance/Issue related data to the message + if object.is_a? Issue or object.is_a? Maintenance + data = object.as_json + data["class"] = object.class.to_s + data["services"] = object.services.map do |service| + service.as_json.merge( "status" => service.status.as_json ) end - - # Add last Update - issueupdate = IssueUpdate.where(id: data["id"]).last.as_json - issue["updates"] = issueupdate - - message_data = issue + data["updates"] = update.as_json + # Add a URL reference + data["url"] = "#{Site.first.domain_with_protocol}/#{object.class.to_s.downcase}/#{object.identifier}" + message["data"] = data end - if ['issue_update'].include? type - - # Get Issue which was updated - issue = Issue.find(data["issue_id"]).as_json - issue["services"] = [] - - # Add all affected services and the Service Status - issueJoins = IssueServiceJoin.where(issue_id: data["issue_id"]) - issueJoins.all.each do |issueJoin| - service = Service.find(issueJoin[:service_id]).as_json - - # Join Service Status for human readable text - service_status = ServiceStatus.find(service["status_id"]).as_json - service["status"] = service_status - - issue["services"].push(service) - - end - - # Add last Update - issueupdate = IssueUpdate.where(id: data["id"]).last.as_json - issue["updates"] = issueupdate - - message_data = issue - + if object.is_a? Maintenance + message["data"]["state"] = object.status.to_s end - message["data"] = message_data - Webhook.all.each do |webhook| - - puts "Call Webhook " + webhook.name + " with URL: " + webhook.url - - header = {'Content-Type': 'application/json'} - + puts "Call Webhook #{webhook.name} with URL: #{webhook.url}" + header = {"Content-Type" => "application/json"} uri = URI(webhook.url) # Create the HTTP objects http = Net::HTTP.new(uri.host, uri.port) - if uri.scheme == "https" - http.use_ssl = true - end - request = Net::HTTP::Post.new(uri.request_uri, header) + http.use_ssl = true if uri.scheme == "https" + request = Net::HTTP::Post.new(uri.request_uri, header) request.body = message.to_json # Send the request begin - response = http.request(request) - rescue StandardError - # Ignore if failed! + http.request(request) + rescue => e + puts "Error calling webhook: #{e.message}" end - end end # call From 96552fc6b60da2b624136d541fe4430fc8a48a07 Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Tue, 26 Feb 2019 17:58:05 +0100 Subject: [PATCH 11/19] Updated Rocket.Chat integration docs (and converted to markdown) --- ...tegration.js => rocketchat_integration.md} | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) rename doc/webhooks/{rocketchat_integration.js => rocketchat_integration.md} (57%) diff --git a/doc/webhooks/rocketchat_integration.js b/doc/webhooks/rocketchat_integration.md similarity index 57% rename from doc/webhooks/rocketchat_integration.js rename to doc/webhooks/rocketchat_integration.md index 19161f1d..cca9f1cb 100644 --- a/doc/webhooks/rocketchat_integration.js +++ b/doc/webhooks/rocketchat_integration.md @@ -1,38 +1,24 @@ -class Script { - /** - * @params {object} request - */ - process_incoming_request({ request }) { - // request.url.hash - // request.url.search - // request.url.query - // request.url.pathname - // request.url.path - // request.url_raw - // request.url_params - // request.headers - // request.user._id - // request.user.name - // request.user.username - // request.content_raw - // request.content - - var staytus_url = "http://localhost:3000" +# Rocket.Chat WebHook integration +Add the following script for formatting messages for Rocket.Chat +```javascript +class Script { + process_incoming_request({ request }) { var staytus = request.content; var message = {}; message.attachement = []; var attachement = {} - attachement.title = staytus.data.title + " (" + staytus.data.updates.state + ")"; - attachement.title_link = staytus_url + "/issue/" + staytus.data.identifier; + attachement.title = staytus.data.title + + " (" + staytus.data.class + ": " + staytus.data.state + ")"; + attachement.title_link = staytus.data.url; attachement.text = staytus.data.updates.text; attachement.text += "\n\nAffected Services:"; message.attachement.push(attachement); - // Add more attachements for each affected Service + // add attachements for each affected service if (staytus.data.services.length > 0) { for (i = 0; i < staytus.data.services.length; i++) { var status_attachement = {} @@ -49,9 +35,10 @@ class Script { return { content:{ text: "", - "attachments": message.attachement + "attachments": message.attachement } }; } } +``` From 6fe9edab6f19af3bed3586100cff140049fcab0d Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Tue, 26 Feb 2019 18:18:55 +0100 Subject: [PATCH 12/19] Updated WebHooks description on settings page --- app/views/admin/settings/index.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/settings/index.html.haml b/app/views/admin/settings/index.html.haml index 3e638194..7742be4f 100644 --- a/app/views/admin/settings/index.html.haml +++ b/app/views/admin/settings/index.html.haml @@ -44,6 +44,6 @@ .navGrid.u-margin-2x .navGrid__item = image_tag 'icons/webhooks.svg' - %p= link_to "Webhooks", admin_webhooks_path - %p.navGrid__text Manage Webhooks which are triggered on new or update Issue + %p= link_to "WebHooks", admin_webhooks_path + %p.navGrid__text Manage WebHooks which are triggered on maintenance and issue updates .navGrid__item From dbe80714b31cc58c0f8ed8a718d86910c7c7b5ad Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Fri, 1 Mar 2019 16:13:42 +0100 Subject: [PATCH 13/19] fix charset for webhooks --- db/schema.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index 16f314f4..0c464c4c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -228,7 +228,7 @@ t.datetime "updated_at", null: false end - create_table "webhooks", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| + create_table "webhooks", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci" do |t| t.string "name", null: false t.string "url", null: false end From 661d01007dde266947b778b47cf15bd1700e2755 Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Fri, 8 Mar 2019 15:07:25 +0100 Subject: [PATCH 14/19] Add webhook call under notify? block to prevent double updates --- app/models/issue.rb | 4 ++-- app/models/issue_update.rb | 2 +- app/models/maintenance.rb | 2 +- app/models/maintenance_update.rb | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/models/issue.rb b/app/models/issue.rb index d03c8f65..f30cddce 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -39,7 +39,7 @@ class Issue < ActiveRecord::Base has_one :latest_update, -> { order(:id => :desc) }, :class_name => 'IssueUpdate' after_create :add_initial_update - after_save :update_service_statuses + before_save :update_service_statuses after_create :create_history_item after_destroy :destroy_history_item after_commit :send_notifications_on_create, :on => :create @@ -93,8 +93,8 @@ def call_webhook def send_notifications_on_create if self.notify? self.delay.send_notifications + self.delay.call_webhook end - delay.call_webhook end private diff --git a/app/models/issue_update.rb b/app/models/issue_update.rb index ab74e62c..8ad56d7a 100644 --- a/app/models/issue_update.rb +++ b/app/models/issue_update.rb @@ -64,8 +64,8 @@ def call_webhook def send_notifications_on_create if self.notify? delay.send_notifications + delay.call_webhook end - delay.call_webhook end end diff --git a/app/models/maintenance.rb b/app/models/maintenance.rb index fde923ea..a1e6e9ac 100644 --- a/app/models/maintenance.rb +++ b/app/models/maintenance.rb @@ -124,8 +124,8 @@ def call_webhook def send_notifications_on_create if self.notify? self.delay.send_notifications + self.delay.call_webhook end - delay.call_webhook end private diff --git a/app/models/maintenance_update.rb b/app/models/maintenance_update.rb index 203e9432..db55028a 100644 --- a/app/models/maintenance_update.rb +++ b/app/models/maintenance_update.rb @@ -45,8 +45,8 @@ def call_webhook def send_notifications_on_create if self.notify? self.delay.send_notifications + self.delay.call_webhook end - delay.call_webhook end end From cf15716b3a1ca3fc0a9e1b0fd484cd896ca5f691 Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Fri, 8 Mar 2019 16:54:04 +0100 Subject: [PATCH 15/19] set data.text according to availability of update object --- lib/staytus/webhookcaller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/staytus/webhookcaller.rb b/lib/staytus/webhookcaller.rb index 89c26d0f..2638017f 100644 --- a/lib/staytus/webhookcaller.rb +++ b/lib/staytus/webhookcaller.rb @@ -18,7 +18,7 @@ def call(type, attributes = {}) data["services"] = object.services.map do |service| service.as_json.merge( "status" => service.status.as_json ) end - data["updates"] = update.as_json + data["text"] = update ? update.text : object.description # Add a URL reference data["url"] = "#{Site.first.domain_with_protocol}/#{object.class.to_s.downcase}/#{object.identifier}" message["data"] = data From 04dde2ba96b846299fa5b716d9fa2557b2cfaf25 Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Fri, 8 Mar 2019 17:33:46 +0100 Subject: [PATCH 16/19] Update webhhook doc --- doc/webhooks/rocketchat_integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/webhooks/rocketchat_integration.md b/doc/webhooks/rocketchat_integration.md index cca9f1cb..3869f087 100644 --- a/doc/webhooks/rocketchat_integration.md +++ b/doc/webhooks/rocketchat_integration.md @@ -13,7 +13,7 @@ class Script { attachement.title = staytus.data.title + " (" + staytus.data.class + ": " + staytus.data.state + ")"; attachement.title_link = staytus.data.url; - attachement.text = staytus.data.updates.text; + attachement.text = staytus.data.text; attachement.text += "\n\nAffected Services:"; message.attachement.push(attachement); From af1cfc2eb9b1057f61fb969ef5fd08a9ed1ad971 Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Tue, 26 Mar 2019 09:23:03 +0100 Subject: [PATCH 17/19] Use the standard rails logger for messages --- lib/staytus/webhookcaller.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/staytus/webhookcaller.rb b/lib/staytus/webhookcaller.rb index 2638017f..a9b00c8b 100644 --- a/lib/staytus/webhookcaller.rb +++ b/lib/staytus/webhookcaller.rb @@ -13,7 +13,7 @@ def call(type, attributes = {}) # Add Maintenance/Issue related data to the message if object.is_a? Issue or object.is_a? Maintenance - data = object.as_json + data = object.as_json data["class"] = object.class.to_s data["services"] = object.services.map do |service| service.as_json.merge( "status" => service.status.as_json ) @@ -29,7 +29,7 @@ def call(type, attributes = {}) end Webhook.all.each do |webhook| - puts "Call Webhook #{webhook.name} with URL: #{webhook.url}" + logger.info "Call Webhook #{webhook.name} with URL: #{webhook.url}" header = {"Content-Type" => "application/json"} uri = URI(webhook.url) @@ -39,12 +39,14 @@ def call(type, attributes = {}) request = Net::HTTP::Post.new(uri.request_uri, header) request.body = message.to_json + + logger.debug message.to_json # Send the request begin http.request(request) rescue => e - puts "Error calling webhook: #{e.message}" + logger.error "Error calling webhook: #{e.message}" end end end # call From cc389bce5656f7a4fabbfd0ff9e5f450617931c7 Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Tue, 26 Mar 2019 09:36:28 +0100 Subject: [PATCH 18/19] fixing direct reference to Rails.logger --- lib/staytus/webhookcaller.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/staytus/webhookcaller.rb b/lib/staytus/webhookcaller.rb index a9b00c8b..b6b325ab 100644 --- a/lib/staytus/webhookcaller.rb +++ b/lib/staytus/webhookcaller.rb @@ -29,7 +29,7 @@ def call(type, attributes = {}) end Webhook.all.each do |webhook| - logger.info "Call Webhook #{webhook.name} with URL: #{webhook.url}" + Rails.logger.info "Call Webhook #{webhook.name} with URL: #{webhook.url}" header = {"Content-Type" => "application/json"} uri = URI(webhook.url) @@ -39,14 +39,14 @@ def call(type, attributes = {}) request = Net::HTTP::Post.new(uri.request_uri, header) request.body = message.to_json - - logger.debug message.to_json + + Rails.logger.debug message.to_json # Send the request begin http.request(request) rescue => e - logger.error "Error calling webhook: #{e.message}" + Rails.logger.error "Error calling webhook: #{e.message}" end end end # call From 1bc7bbf8996b5d466b6cb911453fedfc0a345109 Mon Sep 17 00:00:00 2001 From: Nik Wolfgramm Date: Mon, 1 Apr 2019 15:34:24 +0200 Subject: [PATCH 19/19] improved debug log output --- lib/staytus/webhookcaller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/staytus/webhookcaller.rb b/lib/staytus/webhookcaller.rb index b6b325ab..5dfd2d3b 100644 --- a/lib/staytus/webhookcaller.rb +++ b/lib/staytus/webhookcaller.rb @@ -30,6 +30,7 @@ def call(type, attributes = {}) Webhook.all.each do |webhook| Rails.logger.info "Call Webhook #{webhook.name} with URL: #{webhook.url}" + header = {"Content-Type" => "application/json"} uri = URI(webhook.url) @@ -40,7 +41,7 @@ def call(type, attributes = {}) request = Net::HTTP::Post.new(uri.request_uri, header) request.body = message.to_json - Rails.logger.debug message.to_json + Rails.logger.debug "WebHook message: #{message.to_json}" # Send the request begin