Skip to content
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

WebHook Feature #281

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/assets/images/icons/webhooks.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions app/controllers/admin/webhooks_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
class Admin::WebhooksController < Admin::BaseController

before_action { params[:id] && @webhook = Webhook.find(params[:id]) }

def index
@webhooks = Webhook.ordered.page(params[:page])
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
7 changes: 6 additions & 1 deletion app/models/issue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -86,9 +86,14 @@ 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
self.delay.call_webhook
end
end

Expand Down
5 changes: 5 additions & 0 deletions app/models/issue_update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,14 @@ def send_notifications
end
end

def call_webhook
Staytus::Webhookcaller.call(:issue_update, :object => self.issue, :update => self)
end

def send_notifications_on_create
if self.notify?
delay.send_notifications
delay.call_webhook
end
end

Expand Down
5 changes: 5 additions & 0 deletions app/models/maintenance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,14 @@ 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
self.delay.call_webhook
end
end

Expand Down
5 changes: 5 additions & 0 deletions app/models/maintenance_update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,14 @@ 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
self.delay.call_webhook
end
end

Expand Down
18 changes: 18 additions & 0 deletions app/models/webhook.rb
Original file line number Diff line number Diff line change
@@ -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
11 changes: 8 additions & 3 deletions app/views/admin/settings/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@
= 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
%p.navGrid__text Manage which external applications are permitted to access your status site using the API.
.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.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 maintenance and issue updates
.navGrid__item
19 changes: 19 additions & 0 deletions app/views/admin/webhooks/_form.html.haml
Original file line number Diff line number Diff line change
@@ -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'
4 changes: 4 additions & 0 deletions app/views/admin/webhooks/edit.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- @active_nav_item = :settings
= content_for :page_header do
.pageHeader__heading= @page_title = 'Edit Webhook'
= render 'form'
25 changes: 25 additions & 0 deletions app/views/admin/webhooks/index.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
- @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'
%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

- if @webhooks.empty?
.noDataArea.noDataArea--large
%p.u-margin No webhooks have been configured yet.
- else
%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'

= paginate @webhooks
4 changes: 4 additions & 0 deletions app/views/admin/webhooks/new.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- @active_nav_item = :settings
= content_for :page_header do
.pageHeader__heading= @page_title = 'Add new Webhook'
= render 'form'
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
resources :service_groups
resources :email_templates, :only => [:index, :edit, :update, :destroy]
resources :api_tokens
resources :webhooks

#
# Issues
Expand Down
12 changes: 12 additions & 0 deletions db/migrate/20180821114121_create_webhooks.rb
Original file line number Diff line number Diff line change
@@ -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
7 changes: 6 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -228,4 +228,9 @@
t.datetime "updated_at", null: false
end

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

end
44 changes: 44 additions & 0 deletions doc/webhooks/rocketchat_integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# 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.class + ": " + staytus.data.state + ")";
attachement.title_link = staytus.data.url;
attachement.text = staytus.data.text;
attachement.text += "\n\nAffected Services:";
message.attachement.push(attachement);


// add 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
}
};

}
}
```
57 changes: 57 additions & 0 deletions lib/staytus/webhookcaller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module Staytus
class Webhookcaller

class << self
#
# Send a message to a webhook
#
def call(type, attributes = {})
# 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
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
end

if object.is_a? Maintenance
message["data"]["state"] = object.status.to_s
end

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)

# Create the HTTP objects
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == "https"

request = Net::HTTP::Post.new(uri.request_uri, header)
request.body = message.to_json

Rails.logger.debug "WebHook message: #{message.to_json}"

# Send the request
begin
http.request(request)
rescue => e
Rails.logger.error "Error calling webhook: #{e.message}"
end
end
end # call

end
end
end