docbrown/app/services/audit/notification.rb
Jeremy Friesen e2940e75ca
Adding :internal auditing for admin/spaces#update (#17010)
There are two existing listeners for the `Audit::Logger`: `:moderator`
and `:internal`.  (Note: during tests we ignore the :moderator and
:internal logs as defined in [config/initializers/audit_events.rb][1].)

Using `rg "Audit::Logger\.log\(:internal," --files-with-matches`, the
`:internal` listener is found in:

- app/controllers/admin/secrets_controller.rb
- app/controllers/admin/settings/base_controller.rb
- app/controllers/admin/settings/general_settings_controller.rb

Using `rg "Audit::Logger\.log\(:moderator," --files-with-matches`, the
`:moderator` listener is used in:

- app/controllers/rating_votes_controller.rb
- app/controllers/comments_controller.rb
- app/controllers/stories/pinned_articles_controller.rb
- app/controllers/admin/response_templates_controller.rb
- app/controllers/admin/tags_controller.rb
- app/controllers/admin/articles_controller.rb
- app/controllers/admin/users_controller.rb
- app/controllers/admin/reactions_controller.rb
- app/controllers/admin/tags/moderators_controller.rb
- app/controllers/tag_adjustments_controller.rb
- app/controllers/reactions_controller.rb

The `admin/spaces#update` action is most similar to the `admin#settings`
actions, which is why I chose `:internal`.  I am looking for further
guidance on documenting this little area of the application (in
particular providing a data dictionary of :internal and :moderator).

Closes forem/forem#16957

[1]:https://github.com/forem/forem/blob/main/config/initializers/audit_events.rb#L9-L11
2022-03-25 14:25:13 -04:00

49 lines
1.6 KiB
Ruby

module Audit
##
# Main class for wrapping ActiveSupport Instrumentation API.
#
# This class represent main entry point for receiving and notifying custom
# events, implemented according to
# https://guides.rubyonrails.org/active_support_instrumentation.html#creating-custom-events
class Notification
class << self
include Audit::Helper
##
# Audit::Notification.notify method, receives listener name, which is registered through
# Audit::Notification.listen and the event payload, passed as a block.
#
# Object of Audit::Event::Payload is send to the block as argument. This way,
# the payload object follows the rules defined in Audit::Event::Payload
#
# Example:
# Audit::Notification.notify('listener_name') do |payload|
# payload.user_id = current_user.id
# payload.roles = current_user.roles.pluck(:name)
# end
def notify(listener, &block)
return unless block
ActiveSupport::Notifications.instrument(instrument_name(listener), Audit::Event::Payload.new(&block))
end
##
# Audit::Notification.listen receives Events sent from ActiveSupport Instrumentation API.
# Then, this event is serialized and send to background job.
def listen(*args)
event = ActiveSupport::Notifications::Event.new(*args)
AuditLog.create!(params_hash(event))
end
def params_hash(event)
{
user_id: event.payload.user_id,
roles: event.payload.roles,
slug: event.payload.slug,
category: event.name,
data: event.payload.data
}
end
end
end
end