diff --git a/Gemfile b/Gemfile index 2bc294480..e4bc8f8e8 100644 --- a/Gemfile +++ b/Gemfile @@ -21,6 +21,7 @@ gem "algorithmia", "~> 1.1" # Ruby Client for Algorithmia Algorithms and Data AP gem "ancestry", "~> 3.0" # Ancestry allows the records of a ActiveRecord model to be organized in a tree structure gem "autoprefixer-rails", "~> 9.7" # Parse CSS and add vendor prefixes to CSS rules using values from the Can I Use website gem "aws-sdk-lambda", "~> 1.36" # Official AWS Ruby gem for AWS Lambda +gem "blazer", "~> 2.2.1" # Allows admins to query data gem "bootsnap", ">= 1.1.0", require: false # Boot large ruby/rails apps faster gem "buffer", "~> 0.1" # Buffer is a Ruby Wrapper for the Buffer API gem "carrierwave", "~> 2.0" # Upload files in your Ruby applications, map them to a range of ORMs, store them on different backends diff --git a/Gemfile.lock b/Gemfile.lock index 55d5e1213..3d27ad336 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -130,6 +130,11 @@ GEM bindex (0.5.0) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) + blazer (2.2.1) + activerecord (>= 5) + chartkick (>= 3.2) + railties (>= 5) + safely_block (>= 0.1.1) bootsnap (1.4.6) msgpack (~> 1.0) brakeman (4.8.0) @@ -173,6 +178,7 @@ GEM fastimage caze (0.2.2) activesupport (>= 3) + chartkick (3.3.1) childprocess (3.0.0) cld (0.8.0) ffi @@ -869,6 +875,7 @@ DEPENDENCIES aws-sdk-lambda (~> 1.36) better_errors (~> 2.6) binding_of_caller (~> 0.8) + blazer (~> 2.2.1) bootsnap (>= 1.1.0) brakeman (~> 4.7) buffer (~> 0.1) diff --git a/config/blazer.yml b/config/blazer.yml new file mode 100644 index 000000000..1c770c34a --- /dev/null +++ b/config/blazer.yml @@ -0,0 +1,73 @@ +# see https://github.com/ankane/blazer for more info + +data_sources: + main: + url: <%= ENV["BLAZER_DATABASE_URL"] %> + + # statement timeout, in seconds + # none by default + timeout: 60 + + # caching settings + # can greatly improve speed + # off by default + cache: + mode: slow # or all + expires_in: 60 # min + slow_threshold: 15 # sec, only used in slow mode + + # wrap queries in a transaction for safety + # not necessary if you use a read-only user + # true by default + # use_transaction: false + + smart_variables: + # zone_id: "SELECT id, name FROM zones ORDER BY name ASC" + # period: ["day", "week", "month"] + # status: {0: "Active", 1: "Archived"} + + linked_columns: + # user_id: "/admin/users/{value}" + + smart_columns: + # user_id: "SELECT id, name FROM users WHERE id IN {value}" + +# create audits +audit: true + +# change the time zone +# time_zone: "Pacific Time (US & Canada)" + +# class name of the user model +# user_class: User + +# method name for the current user +# user_method: current_user + +# method name for the display name +# user_name: name + +# custom before_action to use for auth +# before_action_method: require_admin + +# email to send checks from +# from_email: blazer@example.org + +# webhook for Slack +# slack_webhook_url: <%= ENV["BLAZER_SLACK_WEBHOOK_URL"] %> + +check_schedules: + - "1 day" + - "1 hour" + - "5 minutes" + +# enable anomaly detection +# note: with trend, time series are sent to https://trendapi.org +# anomaly_checks: trend / r + +# enable forecasting +# note: with trend, time series are sent to https://trendapi.org +# forecasting: trend + +# enable map +# mapbox_access_token: <%= ENV["MAPBOX_ACCESS_TOKEN"] %> diff --git a/config/routes.rb b/config/routes.rb index b2dc1e81a..fa51af04f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -38,6 +38,10 @@ Rails.application.routes.draw do namespace :internal do get "/", to: redirect("/internal/articles") + authenticate :user, ->(user) { user.has_role?(:super_admin) } do + mount Blazer::Engine, at: "blazer" + end + resources :articles, only: %i[index show update] resources :broadcasts, only: %i[index new create edit update] resources :buffer_updates, only: %i[create update] diff --git a/db/migrate/20200304164719_install_blazer.rb b/db/migrate/20200304164719_install_blazer.rb new file mode 100644 index 000000000..dfa6ac472 --- /dev/null +++ b/db/migrate/20200304164719_install_blazer.rb @@ -0,0 +1,46 @@ +class InstallBlazer < ActiveRecord::Migration[5.2] + def change + create_table :blazer_queries do |t| + t.references :creator + t.string :name + t.text :description + t.text :statement + t.string :data_source + t.timestamps null: false + end + + create_table :blazer_audits do |t| + t.references :user + t.references :query + t.text :statement + t.string :data_source + t.timestamp :created_at + end + + create_table :blazer_dashboards do |t| + t.references :creator + t.text :name + t.timestamps null: false + end + + create_table :blazer_dashboard_queries do |t| + t.references :dashboard + t.references :query + t.integer :position + t.timestamps null: false + end + + create_table :blazer_checks do |t| + t.references :creator + t.references :query + t.string :state + t.string :schedule + t.text :emails + t.text :slack_channels + t.string :check_type + t.text :message + t.timestamp :last_run_at + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index cdfe4408d..c910bb949 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_02_27_214321) do +ActiveRecord::Schema.define(version: 2020_03_04_164719) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -202,6 +202,61 @@ ActiveRecord::Schema.define(version: 2020_02_27_214321) do t.index ["username"], name: "index_banished_users_on_username", unique: true end + create_table "blazer_audits", force: :cascade do |t| + t.datetime "created_at" + t.string "data_source" + t.bigint "query_id" + t.text "statement" + t.bigint "user_id" + t.index ["query_id"], name: "index_blazer_audits_on_query_id" + t.index ["user_id"], name: "index_blazer_audits_on_user_id" + end + + create_table "blazer_checks", force: :cascade do |t| + t.string "check_type" + t.datetime "created_at", null: false + t.bigint "creator_id" + t.text "emails" + t.datetime "last_run_at" + t.text "message" + t.bigint "query_id" + t.string "schedule" + t.text "slack_channels" + t.string "state" + t.datetime "updated_at", null: false + t.index ["creator_id"], name: "index_blazer_checks_on_creator_id" + t.index ["query_id"], name: "index_blazer_checks_on_query_id" + end + + create_table "blazer_dashboard_queries", force: :cascade do |t| + t.datetime "created_at", null: false + t.bigint "dashboard_id" + t.integer "position" + t.bigint "query_id" + t.datetime "updated_at", null: false + t.index ["dashboard_id"], name: "index_blazer_dashboard_queries_on_dashboard_id" + t.index ["query_id"], name: "index_blazer_dashboard_queries_on_query_id" + end + + create_table "blazer_dashboards", force: :cascade do |t| + t.datetime "created_at", null: false + t.bigint "creator_id" + t.text "name" + t.datetime "updated_at", null: false + t.index ["creator_id"], name: "index_blazer_dashboards_on_creator_id" + end + + create_table "blazer_queries", force: :cascade do |t| + t.datetime "created_at", null: false + t.bigint "creator_id" + t.string "data_source" + t.text "description" + t.string "name" + t.text "statement" + t.datetime "updated_at", null: false + t.index ["creator_id"], name: "index_blazer_queries_on_creator_id" + end + create_table "blocks", id: :serial, force: :cascade do |t| t.text "body_html" t.text "body_markdown"