scenario_import.rb 3.4KB

    # This is a helper class for managing Scenario imports. class ScenarioImport include ActiveModel::Model include ActiveModel::Callbacks include ActiveModel::Validations::Callbacks DANGEROUS_AGENT_TYPES = %w[Agents::ShellCommandAgent] URL_REGEX = /\Ahttps?:\/\//i attr_accessor :file, :url, :data, :do_import attr_reader :user before_validation :parse_file before_validation :fetch_url validate :validate_presence_of_file_url_or_data validates_format_of :url, :with => URL_REGEX, :allow_nil => true, :allow_blank => true, :message => "appears to be invalid" validate :validate_data def step_one? data.blank? end def step_two? valid? end def set_user(user) @user = user end def existing_scenario @existing_scenario ||= user.scenarios.find_by_guid(parsed_data["guid"]) end def dangerous? (parsed_data['agents'] || []).any? { |agent| DANGEROUS_AGENT_TYPES.include?(agent['type']) } end def parsed_data @parsed_data ||= data && JSON.parse(data) rescue {} end def do_import? do_import == "1" end def import!(options = {}) guid = parsed_data['guid'] description = parsed_data['description'] name = parsed_data['name'] agents = parsed_data['agents'] links = parsed_data['links'] source_url = parsed_data['source_url'].presence || nil @scenario = user.scenarios.where(:guid => guid).first_or_initialize @scenario.update_attributes!(:name => name, :description => description, :source_url => source_url, :public => false) unless options[:skip_agents] created_agents = agents.map do |agent_data| agent = @scenario.agents.find_by(:guid => agent_data['guid']) || Agent.build_for_type(agent_data['type'], user) agent.guid = agent_data['guid'] agent.attributes = { :name => agent_data['name'], :schedule => agent_data['schedule'], :keep_events_for => agent_data['keep_events_for'], :propagate_immediately => agent_data['propagate_immediately'], :disabled => agent_data['disabled'], :options => agent_data['options'], :scenario_ids => [@scenario.id] } agent.save! agent end links.each do |link| receiver = created_agents[link['receiver']] source = created_agents[link['source']] receiver.sources << source unless receiver.sources.include?(source) end end end def scenario @scenario || @existing_scenario end def will_request_local?(url_root) data.blank? && file.blank? && url.present? && url.starts_with?(url_root) end protected def parse_file if data.blank? && file.present? self.data = file.read end end def fetch_url if data.blank? && url.present? && url =~ URL_REGEX self.data = Faraday.get(url).body end end def validate_data if data.present? @parsed_data = JSON.parse(data) rescue {} if (%w[name guid agents] - @parsed_data.keys).length > 0 errors.add(:base, "The provided data does not appear to be a valid Scenario.") self.data = nil end else @parsed_data = nil end end def validate_presence_of_file_url_or_data unless file.present? || url.present? || data.present? errors.add(:base, "Please provide either a Scenario JSON File or a Public Scenario URL.") end end end