110 lines
3.4 KiB
Ruby
110 lines
3.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
#
|
|
# Copyright (C) 2021 - present Instructure, Inc.
|
|
#
|
|
# This file is part of Canvas.
|
|
#
|
|
# Canvas is free software: you can redistribute it and/or modify it under
|
|
# the terms of the GNU Affero General Public License as published by the Free
|
|
# Software Foundation, version 3 of the License.
|
|
#
|
|
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License along
|
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
require "audits/engine"
|
|
require "canvas_cassandra"
|
|
require "switchman"
|
|
|
|
module Audits
|
|
class << self
|
|
def stream(&block)
|
|
::EventStream::Stream.new(&block).tap do |stream|
|
|
stream.raise_on_error ||= Rails.env.test?
|
|
|
|
stream.on_insert do |record|
|
|
EventStream::Logger.info('AUDITOR', identifier, 'insert', record.to_json)
|
|
end
|
|
|
|
stream.on_error do |operation, record, exception|
|
|
next unless Audits.configured?
|
|
|
|
EventStream::Logger.error('AUDITOR', identifier, operation, record.to_json, exception.message.to_s)
|
|
end
|
|
end
|
|
end
|
|
|
|
def logger
|
|
Rails.logger
|
|
end
|
|
|
|
def read_stream_options(options)
|
|
return { backend_strategy: :cassandra }.merge(options) if Audits.read_from_cassandra?
|
|
return { backend_strategy: :active_record }.merge(options) if Audits.read_from_postgres?
|
|
|
|
# Assume cassandra by default until transition complete
|
|
{ backend_strategy: :cassandra }.merge(options)
|
|
end
|
|
|
|
def backend_strategy
|
|
strategy_value = :cassandra
|
|
strategy_value = :active_record if read_from_postgres?
|
|
strategy_value
|
|
end
|
|
|
|
def configured?
|
|
strategy = backend_strategy
|
|
if strategy == :cassandra
|
|
return CanvasCassandra::DatabaseBuilder.configured?('auditors')
|
|
elsif strategy == :active_record
|
|
return Rails.configuration.database_configuration[Rails.env].present?
|
|
end
|
|
|
|
raise ArgumentError, "Unknown Audits Backend Strategy: #{strategy}"
|
|
end
|
|
|
|
def write_to_cassandra?
|
|
write_paths.include?('cassandra')
|
|
end
|
|
|
|
def write_to_postgres?
|
|
write_paths.include?('active_record')
|
|
end
|
|
|
|
def read_from_cassandra?
|
|
read_path == 'cassandra'
|
|
end
|
|
|
|
def read_from_postgres?
|
|
read_path == 'active_record'
|
|
end
|
|
|
|
def read_path
|
|
config&.[]('read_path') || 'cassandra'
|
|
end
|
|
|
|
def write_paths
|
|
paths = [config&.[]('write_paths')].flatten.compact
|
|
# default to both for now.
|
|
# after a year we will have hit our retention period
|
|
# and can safely de-comission all auditors cassandra code.
|
|
return_paths = paths.empty? ? ['cassandra', 'active_record'] : paths
|
|
unless return_paths.include?('active_record')
|
|
logger.warn("[Auditors | DEPRECATION] Your auditors config attempts to not write to the relational db: #{paths}. This is deprecated, the intended future target for these audit records is postgres. Configuring to write to the db anyway.")
|
|
return_paths.unshift('active_record')
|
|
end
|
|
return_paths
|
|
end
|
|
|
|
def config(shard = ::Switchman::Shard.current)
|
|
settings = DynamicSettings.find(tree: :private, cluster: shard.database_server.id)
|
|
YAML.safe_load(settings['auditors.yml'] || '{}')
|
|
end
|
|
end
|
|
end
|