Implemented issue#453 - Possibility to monitor Zammad via URL from external, like gitlab is offering it.
This commit is contained in:
parent
0766ffc0f5
commit
44a5b9861f
10 changed files with 788 additions and 3 deletions
47
app/assets/javascripts/app/controllers/monitoring.coffee
Normal file
47
app/assets/javascripts/app/controllers/monitoring.coffee
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
class Index extends App.ControllerSubContent
|
||||||
|
requiredPermission: 'admin.monitoring'
|
||||||
|
header: 'Monitoring'
|
||||||
|
events:
|
||||||
|
'click .js-resetToken': 'resetToken'
|
||||||
|
'click .js-select': 'selectAll'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@load()
|
||||||
|
@interval(
|
||||||
|
=>
|
||||||
|
@load()
|
||||||
|
35000
|
||||||
|
)
|
||||||
|
|
||||||
|
# fetch data, render view
|
||||||
|
load: ->
|
||||||
|
@startLoading()
|
||||||
|
@ajax(
|
||||||
|
id: 'health_check'
|
||||||
|
type: 'GET'
|
||||||
|
url: "#{@apiPath}/monitoring/health_check"
|
||||||
|
success: (data) =>
|
||||||
|
@stopLoading()
|
||||||
|
console.log('111', data, @data)
|
||||||
|
return if @data && data.token is @data.token && data.healthy is @data.healthy && data.message is @data.message
|
||||||
|
console.log('222')
|
||||||
|
@data = data
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
@html App.view('monitoring')(data: @data)
|
||||||
|
|
||||||
|
resetToken: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@formDisable(e)
|
||||||
|
@ajax(
|
||||||
|
id: 'health_check_token'
|
||||||
|
type: 'POST'
|
||||||
|
url: "#{@apiPath}/monitoring/token"
|
||||||
|
success: (data) =>
|
||||||
|
@load()
|
||||||
|
)
|
||||||
|
|
||||||
|
App.Config.set('Monitoring', { prio: 3600, name: 'Monitoring', parent: '#system', target: '#system/monitoring', controller: Index, permission: ['admin.monitoring'] }, 'NavBarAdmin')
|
|
@ -54,4 +54,4 @@ class Index extends App.ControllerSubContent
|
||||||
@load()
|
@load()
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('Packages', { prio: 3600, name: 'Packages', parent: '#system', target: '#system/package', controller: Index, permission: ['admin.package'] }, 'NavBarAdmin')
|
App.Config.set('Packages', { prio: 3700, name: 'Packages', parent: '#system', target: '#system/package', controller: Index, permission: ['admin.package'] }, 'NavBarAdmin')
|
||||||
|
|
39
app/assets/javascripts/app/views/monitoring.jst.eco
Normal file
39
app/assets/javascripts/app/views/monitoring.jst.eco
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<div class="page-header">
|
||||||
|
<div class="page-header-title">
|
||||||
|
<h1><%- @T('Monitoring') %><small></small></h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="page-content">
|
||||||
|
|
||||||
|
<div class="settings-entry">
|
||||||
|
<div class="page-header-title">
|
||||||
|
<h2><%- @T('Current Token') %></h2>
|
||||||
|
</div>
|
||||||
|
<p><input class="js-select js-token" type="text" value="<%= @data.token %>" readonly></p>
|
||||||
|
<button class="btn btn--primary js-resetToken"><%- @T('Reset') %></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-entry">
|
||||||
|
<div class="page-header-title">
|
||||||
|
<h2><%- @T('Health Check') %></h2>
|
||||||
|
</div>
|
||||||
|
<p><%- @T('Health information can be retrieved as JSON using') %>:</p>
|
||||||
|
<input class="js-select js-url" type="text" value="<%- @C('http_type') %>://<%- @C('fqdn') %>/<%- @C('api_path') %>/monitoring/health_check?token=<%= @data.token %>" readonly></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-entry">
|
||||||
|
<div class="page-header-title">
|
||||||
|
<h2><% if _.isEmpty(@data.issues): %><%- @Icon('status', 'ok inline') %><% else: %><%- @Icon('status', 'error inline') %><% end %> <%- @T('Current Status') %></h2>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
<% if _.isEmpty(@data.issues): %>
|
||||||
|
<li><%- @T('no issues') %>
|
||||||
|
<% else: %>
|
||||||
|
<% for issue in @data.issues: %>
|
||||||
|
<li><%= issue %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
182
app/controllers/monitoring_controller.rb
Normal file
182
app/controllers/monitoring_controller.rb
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class MonitoringController < ApplicationController
|
||||||
|
before_action -> { authentication_check(permission: 'admin.monitoring') }, except: [:health_check, :status]
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
GET /api/v1/monitoring/health_check?token=XXX
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"healthy": true,
|
||||||
|
"message": "success",
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"healthy": false,
|
||||||
|
"message": "authentication of XXX failed; issue #2",
|
||||||
|
"issues": ["authentication of XXX failed", "issue #2"],
|
||||||
|
}
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/v1/monitoring/health_check?token=XXX
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def health_check
|
||||||
|
token_or_permission_check
|
||||||
|
|
||||||
|
issues = []
|
||||||
|
|
||||||
|
# channel check
|
||||||
|
Channel.where(active: true).each { |channel|
|
||||||
|
next if (channel.status_in.empty? || channel.status_in == 'ok') && (channel.status_out.empty? || channel.status_out == 'ok')
|
||||||
|
if channel.status_in == 'error'
|
||||||
|
message = "Channel: #{channel.area} in "
|
||||||
|
%w(host user uid).each { |key|
|
||||||
|
next if !channel.options[key] || channel.options[key].empty?
|
||||||
|
message += "key:#{channel.options[key]};"
|
||||||
|
}
|
||||||
|
issues.push "#{message} #{channel.last_log_in}"
|
||||||
|
end
|
||||||
|
next if channel.status_out != 'error'
|
||||||
|
message = "Channel: #{channel.area} out "
|
||||||
|
%w(host user uid).each { |key|
|
||||||
|
next if !channel.options[key] || channel.options[key].empty?
|
||||||
|
message += "key:#{channel.options[key]};"
|
||||||
|
}
|
||||||
|
issues.push "#{message} #{channel.last_log_out}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# unprocessable mail check
|
||||||
|
directory = "#{Rails.root}/tmp/unprocessable_mail"
|
||||||
|
if File.exist?(directory)
|
||||||
|
count = 0
|
||||||
|
Dir.glob("#{directory}/*.eml") { |_entry|
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
if count.nonzero?
|
||||||
|
issues.push "unprocessable mails: #{count}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# scheduler check
|
||||||
|
Scheduler.where(active: true).where.not(last_run: nil).each { |scheduler|
|
||||||
|
next if scheduler.period <= 300
|
||||||
|
next if scheduler.last_run + scheduler.period.seconds > Time.zone.now - 5.minutes
|
||||||
|
issues.push 'scheduler not running'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if Scheduler.where(active: true, last_run: nil).count == Scheduler.where(active: true).count
|
||||||
|
issues.push 'scheduler not running'
|
||||||
|
end
|
||||||
|
|
||||||
|
token = Setting.get('monitoring_token')
|
||||||
|
|
||||||
|
if issues.empty?
|
||||||
|
result = {
|
||||||
|
healthy: true,
|
||||||
|
message: 'success',
|
||||||
|
token: token,
|
||||||
|
}
|
||||||
|
render json: result
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
result = {
|
||||||
|
healthy: false,
|
||||||
|
message: issues.join(';'),
|
||||||
|
issues: issues,
|
||||||
|
token: token,
|
||||||
|
}
|
||||||
|
render json: result
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
GET /api/v1/monitoring/status?token=XXX
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"agents": 8123,
|
||||||
|
"last_login": "2016-11-21T14:14:14Z",
|
||||||
|
"counts": {
|
||||||
|
"users": 12313,
|
||||||
|
"tickets": 23123,
|
||||||
|
"ticket_articles": 131451,
|
||||||
|
},
|
||||||
|
"last_created_at": {
|
||||||
|
"users": "2016-11-21T14:14:14Z",
|
||||||
|
"tickets": "2016-11-21T14:14:14Z",
|
||||||
|
"ticket_articles": "2016-11-21T14:14:14Z",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Test:
|
||||||
|
curl http://localhost/api/v1/monitoring/status?token=XXX
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def status
|
||||||
|
token_or_permission_check
|
||||||
|
|
||||||
|
last_login = nil
|
||||||
|
last_login_user = User.where('last_login IS NOT NULL').order(last_login: :desc).limit(1).first
|
||||||
|
if last_login_user
|
||||||
|
last_login = last_login_user.last_login
|
||||||
|
end
|
||||||
|
|
||||||
|
status = {
|
||||||
|
counts: {},
|
||||||
|
last_created_at: {},
|
||||||
|
last_login: last_login,
|
||||||
|
agents: User.with_permissions('ticket.agent').count,
|
||||||
|
}
|
||||||
|
|
||||||
|
map = {
|
||||||
|
users: User,
|
||||||
|
groups: Group,
|
||||||
|
overviews: Overview,
|
||||||
|
tickets: Ticket,
|
||||||
|
ticket_articles: Ticket::Article,
|
||||||
|
}
|
||||||
|
map.each { |key, class_name|
|
||||||
|
status[:counts][key] = class_name.count
|
||||||
|
last = class_name.last
|
||||||
|
status[:last_created_at][key] = if last
|
||||||
|
last.created_at
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
render json: status
|
||||||
|
end
|
||||||
|
|
||||||
|
def token
|
||||||
|
access_check
|
||||||
|
token = SecureRandom.urlsafe_base64(40)
|
||||||
|
Setting.set('monitoring_token', token)
|
||||||
|
|
||||||
|
result = {
|
||||||
|
token: token,
|
||||||
|
}
|
||||||
|
render json: result, status: :created
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def token_or_permission_check
|
||||||
|
user = authentication_check_only(permission: 'admin.monitoring')
|
||||||
|
return if user
|
||||||
|
return if Setting.get('monitoring_token') == params[:token]
|
||||||
|
raise Exceptions::NotAuthorized
|
||||||
|
end
|
||||||
|
|
||||||
|
def access_check
|
||||||
|
return if Permission.find_by(name: 'admin.monitoring', active: true)
|
||||||
|
raise Exceptions::NotAuthorized
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
8
config/routes/monitoring.rb
Normal file
8
config/routes/monitoring.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Zammad::Application.routes.draw do
|
||||||
|
api_path = Rails.configuration.api_path
|
||||||
|
|
||||||
|
match api_path + '/monitoring/health_check', to: 'monitoring#health_check', via: :get
|
||||||
|
match api_path + '/monitoring/status', to: 'monitoring#status', via: :get
|
||||||
|
match api_path + '/monitoring/token', to: 'monitoring#token', via: :post
|
||||||
|
|
||||||
|
end
|
37
db/migrate/20161122000001_monitoring_issue_453.rb
Normal file
37
db/migrate/20161122000001_monitoring_issue_453.rb
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
class MonitoringIssue453 < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
# return if it's a new setup
|
||||||
|
return if !Setting.find_by(name: 'system_init_done')
|
||||||
|
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Monitoring Token',
|
||||||
|
name: 'monitoring_token',
|
||||||
|
area: 'HealthCheck::Base',
|
||||||
|
description: 'Token for Monitoring.',
|
||||||
|
options: {
|
||||||
|
form: [
|
||||||
|
{
|
||||||
|
display: '',
|
||||||
|
null: false,
|
||||||
|
name: 'monitoring_token',
|
||||||
|
tag: 'input',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
state: SecureRandom.urlsafe_base64(40),
|
||||||
|
preferences: {
|
||||||
|
permission: ['admin.monitoring'],
|
||||||
|
},
|
||||||
|
frontend: false,
|
||||||
|
)
|
||||||
|
|
||||||
|
Permission.create_if_not_exists(
|
||||||
|
name: 'admin.monitoring',
|
||||||
|
note: 'Manage %s',
|
||||||
|
preferences: {
|
||||||
|
translations: ['Monitoring']
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
33
db/seeds.rb
33
db/seeds.rb
|
@ -1575,7 +1575,7 @@ Setting.create_if_not_exists(
|
||||||
frontend: false
|
frontend: false
|
||||||
)
|
)
|
||||||
|
|
||||||
Setting.create_or_update(
|
Setting.create_if_not_exists(
|
||||||
title: 'API Token Access',
|
title: 'API Token Access',
|
||||||
name: 'api_token_access',
|
name: 'api_token_access',
|
||||||
area: 'API::Base',
|
area: 'API::Base',
|
||||||
|
@ -1600,7 +1600,7 @@ Setting.create_or_update(
|
||||||
},
|
},
|
||||||
frontend: false
|
frontend: false
|
||||||
)
|
)
|
||||||
Setting.create_or_update(
|
Setting.create_if_not_exists(
|
||||||
title: 'API Password Access',
|
title: 'API Password Access',
|
||||||
name: 'api_password_access',
|
name: 'api_password_access',
|
||||||
area: 'API::Base',
|
area: 'API::Base',
|
||||||
|
@ -1626,6 +1626,28 @@ Setting.create_or_update(
|
||||||
frontend: false
|
frontend: false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Monitoring Token',
|
||||||
|
name: 'monitoring_token',
|
||||||
|
area: 'HealthCheck::Base',
|
||||||
|
description: 'Token for Monitoring.',
|
||||||
|
options: {
|
||||||
|
form: [
|
||||||
|
{
|
||||||
|
display: '',
|
||||||
|
null: false,
|
||||||
|
name: 'monitoring_token',
|
||||||
|
tag: 'input',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
state: SecureRandom.urlsafe_base64(40),
|
||||||
|
preferences: {
|
||||||
|
permission: ['admin.monitoring'],
|
||||||
|
},
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
|
||||||
Setting.create_if_not_exists(
|
Setting.create_if_not_exists(
|
||||||
title: 'Enable Chat',
|
title: 'Enable Chat',
|
||||||
name: 'chat',
|
name: 'chat',
|
||||||
|
@ -2765,6 +2787,13 @@ Permission.create_if_not_exists(
|
||||||
translations: ['Translations']
|
translations: ['Translations']
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
Permission.create_if_not_exists(
|
||||||
|
name: 'admin.monitoring',
|
||||||
|
note: 'Manage %s',
|
||||||
|
preferences: {
|
||||||
|
translations: ['Monitoring']
|
||||||
|
},
|
||||||
|
)
|
||||||
Permission.create_if_not_exists(
|
Permission.create_if_not_exists(
|
||||||
name: 'admin.maintenance',
|
name: 'admin.maintenance',
|
||||||
note: 'Manage %s',
|
note: 'Manage %s',
|
||||||
|
|
|
@ -47,6 +47,8 @@ if [ "$LEVEL" == '1' ]; then
|
||||||
# test/browser/maintenance_login_message_test.rb
|
# test/browser/maintenance_login_message_test.rb
|
||||||
# test/browser/maintenance_mode_test.rb
|
# test/browser/maintenance_mode_test.rb
|
||||||
# test/browser/maintenance_session_message_test.rb
|
# test/browser/maintenance_session_message_test.rb
|
||||||
|
# test/browser/manage_test.rb
|
||||||
|
# test/browser/monitoring_test.rb
|
||||||
rm test/browser/preferences_language_test.rb
|
rm test/browser/preferences_language_test.rb
|
||||||
rm test/browser/preferences_permission_check_test.rb
|
rm test/browser/preferences_permission_check_test.rb
|
||||||
rm test/browser/preferences_token_access_test.rb
|
rm test/browser/preferences_token_access_test.rb
|
||||||
|
@ -101,6 +103,7 @@ elif [ "$LEVEL" == '2' ]; then
|
||||||
rm test/browser/maintenance_mode_test.rb
|
rm test/browser/maintenance_mode_test.rb
|
||||||
rm test/browser/maintenance_session_message_test.rb
|
rm test/browser/maintenance_session_message_test.rb
|
||||||
rm test/browser/manage_test.rb
|
rm test/browser/manage_test.rb
|
||||||
|
rm test/browser/monitoring_test.rb
|
||||||
rm test/browser/preferences_language_test.rb
|
rm test/browser/preferences_language_test.rb
|
||||||
rm test/browser/preferences_permission_check_test.rb
|
rm test/browser/preferences_permission_check_test.rb
|
||||||
rm test/browser/preferences_token_access_test.rb
|
rm test/browser/preferences_token_access_test.rb
|
||||||
|
@ -155,6 +158,7 @@ elif [ "$LEVEL" == '3' ]; then
|
||||||
rm test/browser/maintenance_mode_test.rb
|
rm test/browser/maintenance_mode_test.rb
|
||||||
rm test/browser/maintenance_session_message_test.rb
|
rm test/browser/maintenance_session_message_test.rb
|
||||||
rm test/browser/manage_test.rb
|
rm test/browser/manage_test.rb
|
||||||
|
rm test/browser/monitoring_test.rb
|
||||||
rm test/browser/preferences_language_test.rb
|
rm test/browser/preferences_language_test.rb
|
||||||
rm test/browser/preferences_permission_check_test.rb
|
rm test/browser/preferences_permission_check_test.rb
|
||||||
rm test/browser/preferences_token_access_test.rb
|
rm test/browser/preferences_token_access_test.rb
|
||||||
|
@ -209,6 +213,7 @@ elif [ "$LEVEL" == '4' ]; then
|
||||||
rm test/browser/maintenance_mode_test.rb
|
rm test/browser/maintenance_mode_test.rb
|
||||||
rm test/browser/maintenance_session_message_test.rb
|
rm test/browser/maintenance_session_message_test.rb
|
||||||
rm test/browser/manage_test.rb
|
rm test/browser/manage_test.rb
|
||||||
|
rm test/browser/monitoring_test.rb
|
||||||
rm test/browser/preferences_language_test.rb
|
rm test/browser/preferences_language_test.rb
|
||||||
rm test/browser/preferences_permission_check_test.rb
|
rm test/browser/preferences_permission_check_test.rb
|
||||||
rm test/browser/preferences_token_access_test.rb
|
rm test/browser/preferences_token_access_test.rb
|
||||||
|
@ -262,6 +267,7 @@ elif [ "$LEVEL" == '5' ]; then
|
||||||
rm test/browser/maintenance_mode_test.rb
|
rm test/browser/maintenance_mode_test.rb
|
||||||
rm test/browser/maintenance_session_message_test.rb
|
rm test/browser/maintenance_session_message_test.rb
|
||||||
rm test/browser/manage_test.rb
|
rm test/browser/manage_test.rb
|
||||||
|
rm test/browser/monitoring_test.rb
|
||||||
rm test/browser/preferences_language_test.rb
|
rm test/browser/preferences_language_test.rb
|
||||||
rm test/browser/preferences_permission_check_test.rb
|
rm test/browser/preferences_permission_check_test.rb
|
||||||
rm test/browser/preferences_token_access_test.rb
|
rm test/browser/preferences_token_access_test.rb
|
||||||
|
@ -318,6 +324,7 @@ elif [ "$LEVEL" == '6' ]; then
|
||||||
rm test/browser/maintenance_mode_test.rb
|
rm test/browser/maintenance_mode_test.rb
|
||||||
rm test/browser/maintenance_session_message_test.rb
|
rm test/browser/maintenance_session_message_test.rb
|
||||||
rm test/browser/manage_test.rb
|
rm test/browser/manage_test.rb
|
||||||
|
rm test/browser/monitoring_test.rb
|
||||||
# test/browser/preferences_language_test.rb
|
# test/browser/preferences_language_test.rb
|
||||||
# test/browser/preferences_permission_check_test.rb
|
# test/browser/preferences_permission_check_test.rb
|
||||||
# test/browser/preferences_token_access_test.rb
|
# test/browser/preferences_token_access_test.rb
|
||||||
|
|
43
test/browser/monitoring_test.rb
Normal file
43
test/browser/monitoring_test.rb
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'browser_test_helper'
|
||||||
|
|
||||||
|
class MonitoringTest < TestCase
|
||||||
|
|
||||||
|
def test_mode
|
||||||
|
browser1 = browser_instance
|
||||||
|
login(
|
||||||
|
browser: browser1,
|
||||||
|
username: 'master@example.com',
|
||||||
|
password: 'test',
|
||||||
|
url: browser_url,
|
||||||
|
)
|
||||||
|
click(
|
||||||
|
browser: browser1,
|
||||||
|
css: 'a[href="#manage"]',
|
||||||
|
)
|
||||||
|
click(
|
||||||
|
browser: browser1,
|
||||||
|
css: 'a[href="#system/monitoring"]',
|
||||||
|
)
|
||||||
|
|
||||||
|
token = browser1.find_elements(css: '.active.content .js-token')[0].attribute('value')
|
||||||
|
url = browser1.find_elements(css: '.active.content .js-url')[0].attribute('value')
|
||||||
|
|
||||||
|
assert_match(token.to_s, url)
|
||||||
|
|
||||||
|
click(
|
||||||
|
browser: browser1,
|
||||||
|
css: '.active.content .js-resetToken',
|
||||||
|
)
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
token_new = browser1.find_elements(css: '.active.content .js-token')[0].attribute('value')
|
||||||
|
url_new = browser1.find_elements(css: '.active.content .js-url')[0].attribute('value')
|
||||||
|
|
||||||
|
assert_not_equal(token, token_new)
|
||||||
|
assert_not_equal(url, url_new)
|
||||||
|
assert_match(token_new.to_s, url_new)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
393
test/controllers/monitoring_controller_test.rb
Normal file
393
test/controllers/monitoring_controller_test.rb
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class MonitoringControllerTest < ActionDispatch::IntegrationTest
|
||||||
|
setup do
|
||||||
|
|
||||||
|
# set accept header
|
||||||
|
@headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
|
||||||
|
|
||||||
|
# set token
|
||||||
|
@token = SecureRandom.urlsafe_base64(64)
|
||||||
|
Setting.set('monitoring_token', @token)
|
||||||
|
|
||||||
|
# create agent
|
||||||
|
roles = Role.where(name: %w(Admin Agent))
|
||||||
|
groups = Group.all
|
||||||
|
|
||||||
|
# channel cleanup
|
||||||
|
Channel.where.not(area: 'Email::Notification').destroy_all
|
||||||
|
Channel.all.each { |channel|
|
||||||
|
channel.status_in = 'ok'
|
||||||
|
channel.status_out = 'ok'
|
||||||
|
channel.last_log_in = nil
|
||||||
|
channel.last_log_out = nil
|
||||||
|
channel.save!
|
||||||
|
}
|
||||||
|
dir = "#{Rails.root}/tmp/unprocessable_mail"
|
||||||
|
Dir.glob("#{dir}/*.eml") do |entry|
|
||||||
|
File.delete(entry)
|
||||||
|
end
|
||||||
|
|
||||||
|
Scheduler.where(active: true).each { |scheduler|
|
||||||
|
scheduler.last_run = Time.zone.now
|
||||||
|
scheduler.save!
|
||||||
|
}
|
||||||
|
|
||||||
|
permission = Permission.find_by(name: 'admin.monitoring')
|
||||||
|
permission.active = true
|
||||||
|
permission.save!
|
||||||
|
|
||||||
|
UserInfo.current_user_id = 1
|
||||||
|
@admin = User.create_or_update(
|
||||||
|
login: 'monitoring-admin',
|
||||||
|
firstname: 'Monitoring',
|
||||||
|
lastname: 'Admin',
|
||||||
|
email: 'monitoring-admin@example.com',
|
||||||
|
password: 'adminpw',
|
||||||
|
active: true,
|
||||||
|
roles: roles,
|
||||||
|
groups: groups,
|
||||||
|
)
|
||||||
|
|
||||||
|
# create agent
|
||||||
|
roles = Role.where(name: 'Agent')
|
||||||
|
@agent = User.create_or_update(
|
||||||
|
login: 'monitoring-agent@example.com',
|
||||||
|
firstname: 'Monitoring',
|
||||||
|
lastname: 'Agent',
|
||||||
|
email: 'monitoring-agent@example.com',
|
||||||
|
password: 'agentpw',
|
||||||
|
active: true,
|
||||||
|
roles: roles,
|
||||||
|
groups: groups,
|
||||||
|
)
|
||||||
|
|
||||||
|
# create customer without org
|
||||||
|
roles = Role.where(name: 'Customer')
|
||||||
|
@customer_without_org = User.create_or_update(
|
||||||
|
login: 'monitoring-customer1@example.com',
|
||||||
|
firstname: 'Monitoring',
|
||||||
|
lastname: 'Customer1',
|
||||||
|
email: 'monitoring-customer1@example.com',
|
||||||
|
password: 'customer1pw',
|
||||||
|
active: true,
|
||||||
|
roles: roles,
|
||||||
|
)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test '01 monitoring without token' do
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get '/api/v1/monitoring/health_check', {}, @headers
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['healthy'])
|
||||||
|
assert_equal('Not authorized', result['error'])
|
||||||
|
|
||||||
|
# status
|
||||||
|
get '/api/v1/monitoring/status', {}, @headers
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['agents'])
|
||||||
|
assert_not(result['last_login'])
|
||||||
|
assert_not(result['counts'])
|
||||||
|
assert_not(result['last_created_at'])
|
||||||
|
assert_equal('Not authorized', result['error'])
|
||||||
|
|
||||||
|
# token
|
||||||
|
post '/api/v1/monitoring/token', {}, @headers
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['token'])
|
||||||
|
assert_equal('authentication failed', result['error'])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test '02 monitoring with wrong token' do
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get '/api/v1/monitoring/health_check?token=abc', {}, @headers
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['healthy'])
|
||||||
|
assert_equal('Not authorized', result['error'])
|
||||||
|
|
||||||
|
# status
|
||||||
|
get '/api/v1/monitoring/status?token=abc', {}, @headers
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['agents'])
|
||||||
|
assert_not(result['last_login'])
|
||||||
|
assert_not(result['counts'])
|
||||||
|
assert_not(result['last_created_at'])
|
||||||
|
assert_equal('Not authorized', result['error'])
|
||||||
|
|
||||||
|
# token
|
||||||
|
post '/api/v1/monitoring/token', { token: 'abc' }.to_json, @headers
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['token'])
|
||||||
|
assert_equal('authentication failed', result['error'])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test '03 monitoring with correct token' do
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get "/api/v1/monitoring/health_check?token=#{@token}", {}, @headers
|
||||||
|
assert_response(200)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['error'])
|
||||||
|
assert_equal(true, result['healthy'])
|
||||||
|
assert_equal('success', result['message'])
|
||||||
|
|
||||||
|
# status
|
||||||
|
get "/api/v1/monitoring/status?token=#{@token}", {}, @headers
|
||||||
|
assert_response(200)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['error'])
|
||||||
|
assert(result.key?('agents'))
|
||||||
|
assert(result.key?('last_login'))
|
||||||
|
assert(result.key?('counts'))
|
||||||
|
assert(result.key?('last_created_at'))
|
||||||
|
|
||||||
|
# token
|
||||||
|
post '/api/v1/monitoring/token', { token: @token }.to_json, @headers
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['token'])
|
||||||
|
assert_equal('authentication failed', result['error'])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test '04 monitoring with admin user' do
|
||||||
|
|
||||||
|
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('monitoring-admin@example.com', 'adminpw')
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get '/api/v1/monitoring/health_check', {}, @headers.merge('Authorization' => credentials)
|
||||||
|
assert_response(200)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['error'])
|
||||||
|
assert_equal(true, result['healthy'])
|
||||||
|
assert_equal('success', result['message'])
|
||||||
|
|
||||||
|
# status
|
||||||
|
get '/api/v1/monitoring/status', {}, @headers.merge('Authorization' => credentials)
|
||||||
|
assert_response(200)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['error'])
|
||||||
|
assert(result.key?('agents'))
|
||||||
|
assert(result.key?('last_login'))
|
||||||
|
assert(result.key?('counts'))
|
||||||
|
assert(result.key?('last_created_at'))
|
||||||
|
|
||||||
|
# token
|
||||||
|
post '/api/v1/monitoring/token', { token: @token }.to_json, @headers.merge('Authorization' => credentials)
|
||||||
|
assert_response(201)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert(result['token'])
|
||||||
|
@token = result['token']
|
||||||
|
assert_not(result['error'])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test '05 monitoring with agent user' do
|
||||||
|
|
||||||
|
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('monitoring-agent@example.com', 'agentpw')
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get '/api/v1/monitoring/health_check', {}, @headers.merge('Authorization' => credentials)
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['healthy'])
|
||||||
|
assert_equal('Not authorized (user)!', result['error'])
|
||||||
|
|
||||||
|
# status
|
||||||
|
get '/api/v1/monitoring/status', {}, @headers.merge('Authorization' => credentials)
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['agents'])
|
||||||
|
assert_not(result['last_login'])
|
||||||
|
assert_not(result['counts'])
|
||||||
|
assert_not(result['last_created_at'])
|
||||||
|
assert_equal('Not authorized (user)!', result['error'])
|
||||||
|
|
||||||
|
# token
|
||||||
|
post '/api/v1/monitoring/token', { token: @token }.to_json, @headers.merge('Authorization' => credentials)
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['token'])
|
||||||
|
assert_equal('Not authorized (user)!', result['error'])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test '06 monitoring with admin user and invalid permission' do
|
||||||
|
|
||||||
|
permission = Permission.find_by(name: 'admin.monitoring')
|
||||||
|
permission.active = false
|
||||||
|
permission.save!
|
||||||
|
|
||||||
|
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('monitoring-admin@example.com', 'adminpw')
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get '/api/v1/monitoring/health_check', {}, @headers.merge('Authorization' => credentials)
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['healthy'])
|
||||||
|
assert_equal('Not authorized (user)!', result['error'])
|
||||||
|
|
||||||
|
# status
|
||||||
|
get '/api/v1/monitoring/status', {}, @headers.merge('Authorization' => credentials)
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['agents'])
|
||||||
|
assert_not(result['last_login'])
|
||||||
|
assert_not(result['counts'])
|
||||||
|
assert_not(result['last_created_at'])
|
||||||
|
assert_equal('Not authorized (user)!', result['error'])
|
||||||
|
|
||||||
|
# token
|
||||||
|
post '/api/v1/monitoring/token', { token: @token }.to_json, @headers.merge('Authorization' => credentials)
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['token'])
|
||||||
|
assert_equal('Not authorized (user)!', result['error'])
|
||||||
|
|
||||||
|
permission.active = true
|
||||||
|
permission.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
test '07 monitoring with correct token and invalid permission' do
|
||||||
|
|
||||||
|
permission = Permission.find_by(name: 'admin.monitoring')
|
||||||
|
permission.active = false
|
||||||
|
permission.save!
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get "/api/v1/monitoring/health_check?token=#{@token}", {}, @headers
|
||||||
|
assert_response(200)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['error'])
|
||||||
|
assert_equal(true, result['healthy'])
|
||||||
|
assert_equal('success', result['message'])
|
||||||
|
|
||||||
|
# status
|
||||||
|
get "/api/v1/monitoring/status?token=#{@token}", {}, @headers
|
||||||
|
assert_response(200)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['error'])
|
||||||
|
assert(result.key?('agents'))
|
||||||
|
assert(result.key?('last_login'))
|
||||||
|
assert(result.key?('counts'))
|
||||||
|
assert(result.key?('last_created_at'))
|
||||||
|
|
||||||
|
# token
|
||||||
|
post '/api/v1/monitoring/token', { token: @token }.to_json, @headers
|
||||||
|
assert_response(401)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert_not(result['token'])
|
||||||
|
assert_equal('authentication failed', result['error'])
|
||||||
|
|
||||||
|
permission.active = true
|
||||||
|
permission.save!
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test '08 check health false' do
|
||||||
|
|
||||||
|
channel = Channel.find_by(active: true)
|
||||||
|
channel.status_in = 'ok'
|
||||||
|
channel.status_out = 'error'
|
||||||
|
channel.last_log_in = nil
|
||||||
|
channel.last_log_out = nil
|
||||||
|
channel.save!
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get "/api/v1/monitoring/health_check?token=#{@token}", {}, @headers
|
||||||
|
assert_response(200)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert(result['message'])
|
||||||
|
assert(result['issues'])
|
||||||
|
assert_equal(false, result['healthy'])
|
||||||
|
assert_equal('Channel: Email::Notification out ', result['message'])
|
||||||
|
|
||||||
|
scheduler = Scheduler.where(active: true).last
|
||||||
|
scheduler.last_run = Time.zone.now - 1.day
|
||||||
|
scheduler.period = 600
|
||||||
|
scheduler.save!
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get "/api/v1/monitoring/health_check?token=#{@token}", {}, @headers
|
||||||
|
assert_response(200)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert(result['message'])
|
||||||
|
assert(result['issues'])
|
||||||
|
assert_equal(false, result['healthy'])
|
||||||
|
assert_equal('Channel: Email::Notification out ;scheduler not running', result['message'])
|
||||||
|
|
||||||
|
dir = "#{Rails.root}/tmp/unprocessable_mail"
|
||||||
|
FileUtils.touch("#{dir}/test.eml")
|
||||||
|
|
||||||
|
# health_check
|
||||||
|
get "/api/v1/monitoring/health_check?token=#{@token}", {}, @headers
|
||||||
|
assert_response(200)
|
||||||
|
|
||||||
|
result = JSON.parse(@response.body)
|
||||||
|
assert_equal(Hash, result.class)
|
||||||
|
assert(result['message'])
|
||||||
|
assert(result['issues'])
|
||||||
|
assert_equal(false, result['healthy'])
|
||||||
|
assert_equal('Channel: Email::Notification out ;unprocessable mails: 1;scheduler not running', result['message'])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue