webhook.rb 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. # frozen_string_literal: true
  2. # == Schema Information
  3. #
  4. # Table name: webhooks
  5. #
  6. # id :bigint(8) not null, primary key
  7. # url :string not null
  8. # events :string default([]), not null, is an Array
  9. # secret :string default(""), not null
  10. # enabled :boolean default(TRUE), not null
  11. # created_at :datetime not null
  12. # updated_at :datetime not null
  13. # template :text
  14. #
  15. class Webhook < ApplicationRecord
  16. EVENTS = %w(
  17. account.approved
  18. account.created
  19. account.updated
  20. report.created
  21. report.updated
  22. status.created
  23. status.updated
  24. ).freeze
  25. attr_writer :current_account
  26. scope :enabled, -> { where(enabled: true) }
  27. validates :url, presence: true, url: true
  28. validates :secret, presence: true, length: { minimum: 12 }
  29. validates :events, presence: true
  30. validate :events_validation_error, if: :invalid_events?
  31. validate :validate_permissions
  32. validate :validate_template
  33. normalizes :events, with: ->(events) { events.filter_map { |event| event.strip.presence } }
  34. before_validation :generate_secret
  35. def rotate_secret!
  36. update!(secret: SecureRandom.hex(20))
  37. end
  38. def enable!
  39. update!(enabled: true)
  40. end
  41. def disable!
  42. update!(enabled: false)
  43. end
  44. def required_permissions
  45. events.map { |event| Webhook.permission_for_event(event) }
  46. end
  47. def self.permission_for_event(event)
  48. case event
  49. when 'account.approved', 'account.created', 'account.updated'
  50. :manage_users
  51. when 'report.created', 'report.updated'
  52. :manage_reports
  53. when 'status.created', 'status.updated'
  54. :view_devops
  55. end
  56. end
  57. private
  58. def events_validation_error
  59. errors.add(:events, :invalid)
  60. end
  61. def invalid_events?
  62. events.blank? || events.difference(EVENTS).any?
  63. end
  64. def validate_permissions
  65. errors.add(:events, :invalid_permissions) if defined?(@current_account) && required_permissions.any? { |permission| !@current_account.user_role.can?(permission) }
  66. end
  67. def validate_template
  68. return if template.blank?
  69. begin
  70. parser = Webhooks::PayloadRenderer::TemplateParser.new
  71. parser.parse(template)
  72. rescue Parslet::ParseFailed
  73. errors.add(:template, :invalid)
  74. end
  75. end
  76. def generate_secret
  77. self.secret = SecureRandom.hex(20) if secret.blank?
  78. end
  79. end