zammad/zammad

View on GitHub
app/controllers/integration/check_mk_controller.rb

Summary

Maintainability
C
1 day
Test Coverage
# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/

class Integration::CheckMkController < ApplicationController
  skip_before_action :verify_csrf_token
  before_action :check_configured

  def update

    # check params
    raise Exceptions::UnprocessableEntity, 'event_id is missing!' if params[:event_id].blank?
    raise Exceptions::UnprocessableEntity, 'state is missing!' if params[:state].blank?
    raise Exceptions::UnprocessableEntity, 'host is missing!' if params[:host].blank?

    # search for open ticket
    auto_close = Setting.get('check_mk_auto_close')
    auto_close_state_id = Setting.get('check_mk_auto_close_state_id')
    group_id = Setting.get('check_mk_group_id')
    state_recovery_match = '(OK|UP)'

    # follow-up detection by meta data
    integration = 'check_mk'
    open_states = Ticket::State.by_category(:open)
    ticket_ids = Ticket.where(state: open_states).reorder(created_at: :desc).limit(5000).pluck(:id)
    ticket_ids_found = []
    ticket_ids.each do |ticket_id|
      ticket = Ticket.find_by(id: ticket_id)
      next if !ticket
      next if !ticket.preferences
      next if !ticket.preferences[integration]
      next if !ticket.preferences[integration]['host']
      next if ticket.preferences[integration]['host'] != params[:host]
      next if ticket.preferences[integration]['service'] != params[:service]

      # found open ticket for service+host
      ticket_ids_found.push ticket.id
    end

    # new ticket, set meta data
    title = "#{params[:host]} is #{params[:state]}"
    body = "EventID: #{params[:event_id]}
Host: #{params[:host]}
Service: #{params[:service] || '-'}
State: #{params[:state]}
Text: #{params[:text] || '-'}
RemoteIP: #{request.remote_ip}
UserAgent: #{request.env['HTTP_USER_AGENT'] || '-'}
"

    # add article
    if params[:state].present? && ticket_ids_found.present?
      ticket_ids_found.each do |ticket_id|
        ticket = Ticket.find_by(id: ticket_id)
        next if !ticket

        Ticket::Article.create!(
          ticket_id: ticket_id,
          type_id:   Ticket::Article::Type.find_by(name: 'web').id,
          sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
          body:      body,
          subject:   title,
          internal:  false,
        )
      end
      if (!auto_close && params[:state].match(%r{#{state_recovery_match}}i)) || !params[:state].match(%r{#{state_recovery_match}}i)
        render json: {
          result:     'ticket already open, added note',
          ticket_ids: ticket_ids_found,
        }
        return
      end
    end

    # check if service is recovered
    if auto_close && params[:state].present? && params[:state].match(%r{#{state_recovery_match}}i)
      if ticket_ids_found.blank?
        render json: {
          result: 'no open tickets found, ignore action',
        }
        return
      end
      ticket_ids_found.each do |ticket_id|
        ticket = Ticket.find_by(id: ticket_id)
        next if !ticket

        ticket.state_id = auto_close_state_id
        ticket.save!
      end
      render json: {
        result:     "closed tickets with ids #{ticket_ids_found.join(',')}",
        ticket_ids: ticket_ids_found,
      }
      return
    end

    # define customer of ticket
    customer = nil
    if params[:customer].present?
      customer = User.find_by(login: params[:customer].downcase)
      if !customer
        customer = User.find_by(email: params[:customer].downcase)
      end
    end
    if !customer
      customer = User.lookup(id: 1)
    end

    params[:state] = nil
    params[:customer] = nil
    ticket = Ticket.new(Ticket.param_cleanup(Ticket.association_name_to_id_convert(params)))
    ticket.group_id ||= group_id
    ticket.customer_id = customer.id
    ticket.title = title
    ticket.preferences = {
      check_mk: {
        host:    params[:host],
        service: params[:service],
      },
    }
    ticket.save!

    Ticket::Article.create!(
      ticket_id: ticket.id,
      type_id:   Ticket::Article::Type.find_by(name: 'web').id,
      sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
      body:      body,
      subject:   title,
      internal:  false,
    )

    render json: {
      result:        "new ticket created (ticket id: #{ticket.id})",
      ticket_id:     ticket.id,
      ticket_number: ticket.number,
    }
  end

  private

  def check_configured
    http_log_config facility: 'check_mk'

    if !Setting.get('check_mk_integration')
      raise Exceptions::UnprocessableEntity, __('Feature is disabled, please contact your administrator!')
    end

    if Setting.get('check_mk_token') != params[:token]
      raise Exceptions::UnprocessableEntity, __('The provided token is invalid.')
    end

    true
  end

end