Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ APP_HOST=localhost:3000
RAILS_SERVE_STATIC_FILES=true
ORGANIZATION_NAME=A Window Between Worlds
REPLY_TO_EMAIL=umberto.user@example.com
BLAZER_DATABASE_URL=db_url # Optional if you want to use a different db for Blazer
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ gem "groupdate"
# Charts and graphs
gem "chartkick"

# Business intelligence for database queries
gem "blazer"

# Geocoding for charts and other features
gem "geocoder"

Expand Down
8 changes: 8 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ GEM
rack (>= 0.9.0)
rouge (>= 1.0.0)
bigdecimal (4.0.1)
blazer (3.3.0)
activerecord (>= 7.1)
chartkick (>= 5)
csv
railties (>= 7.1)
safely_block (>= 0.4)
bootsnap (1.22.0)
msgpack (~> 1.2)
brakeman (8.0.2)
Expand Down Expand Up @@ -603,6 +609,7 @@ DEPENDENCIES
bcrypt (= 3.1.16)
better_errors
binding_of_caller!
blazer
bootsnap
brakeman (~> 8.0.1)
bullet
Expand Down Expand Up @@ -689,6 +696,7 @@ CHECKSUMS
better_errors (2.10.1) sha256=f798f1bac93f3e775925b7fcb24cffbcf0bb62ee2210f5350f161a6b75fc0a73
bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7
binding_of_caller (1.0.1)
blazer (3.3.0) sha256=01e151091ce1e7d27c156243916b2f13109ef2ef1a16cfa62bef67f4c5fd169f
bootsnap (1.22.0) sha256=5820c9d42c2efef095bee6565484bdc511f1223bf950140449c9385ae775793e
brakeman (8.0.2) sha256=7b02065ce8b1de93949cefd3f2ad78e8eb370e644b95c8556a32a912a782426a
builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
Expand Down
79 changes: 79 additions & 0 deletions config/blazer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# see https://github.com/ankane/blazer for more info

data_sources:
main:
url: <%= ENV["BLAZER_DATABASE_URL"].presence || ENV["DATABASE_URL"].presence || "trilogy://root@127.0.0.1/awbw_development" %>

# statement timeout, in seconds
# none by default
# timeout: 15

# 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: email

# custom before_action to use for auth
# auth handled via Devise route constraint in routes.rb

# 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: prophet / trend / anomaly_detection

# enable forecasting
# note: with trend, time series are sent to https://trendapi.org
# forecasting: prophet / trend

# enable map
# mapbox_access_token: <%= ENV["MAPBOX_ACCESS_TOKEN"] %>

# enable uploads
# uploads:
# url: <%= ENV["BLAZER_UPLOADS_URL"] %>
# schema: uploads
# data_source: main
14 changes: 14 additions & 0 deletions config/initializers/blazer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Blazer authentication configuration
# Only allow super_users to access Blazer
Rails.application.config.to_prepare do
Blazer::BaseController.class_eval do
before_action :authenticate_user!
before_action :require_blazer_access

private

def require_blazer_access
redirect_to root_path, alert: "You are not authorized to access this page." unless current_user&.super_user?
end
end
end
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

# mount Ckeditor::Engine, at: '/admin/ckeditor', as: 'ckeditor'
apipie
authenticate :user, ->(user) { user.super_user? } do
mount Blazer::Engine, at: "blazer"
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nest the blazer route under call to super_user

devise_for :users,
controllers: { registrations: "registrations",
confirmations: "confirmations",
Expand Down
47 changes: 47 additions & 0 deletions db/migrate/20260215064655_install_blazer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
class InstallBlazer < ActiveRecord::Migration[8.1]
def change
create_table :blazer_queries do |t|
t.references :creator, type: :integer, foreign_key: { to_table: :users }
t.string :name
t.text :description
t.text :statement
t.string :data_source
t.string :status
t.timestamps null: false
end

create_table :blazer_audits do |t|
t.references :user, type: :integer, foreign_key: { to_table: :users }
t.references :query, foreign_key: { to_table: :blazer_queries }
t.text :statement
t.string :data_source
t.timestamp :created_at, null: false
end

create_table :blazer_dashboards do |t|
t.references :creator, type: :integer, foreign_key: { to_table: :users }
t.string :name
t.timestamps null: false
end

create_table :blazer_dashboard_queries do |t|
t.references :dashboard, foreign_key: { to_table: :blazer_dashboards }
t.references :query, foreign_key: { to_table: :blazer_queries }
t.integer :position
t.timestamps null: false
end

create_table :blazer_checks do |t|
t.references :creator, type: :integer, foreign_key: { to_table: :users }
t.references :query, foreign_key: { to_table: :blazer_queries }
t.string :state
t.string :schedule
t.text :emails
t.text :slack_channels
t.string :check_type
t.text :message
t.datetime :last_run_at
t.timestamps null: false
end
end
end
66 changes: 65 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[8.1].define(version: 2026_02_14_230901) do
ActiveRecord::Schema[8.1].define(version: 2026_02_16_120927) do
create_table "action_text_mentions", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.bigint "action_text_rich_text_id", null: false
t.datetime "created_at", null: false
Expand Down Expand Up @@ -202,6 +202,62 @@
t.index ["updated_by_id"], name: "index_banners_on_updated_by_id"
end

create_table "blazer_audits", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.timestamp "created_at", null: false
t.string "data_source"
t.bigint "query_id"
t.text "statement"
t.integer "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", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.string "check_type"
t.datetime "created_at", null: false
t.integer "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", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", 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", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.datetime "created_at", null: false
t.integer "creator_id"
t.string "name"
t.datetime "updated_at", null: false
t.index ["creator_id"], name: "index_blazer_dashboards_on_creator_id"
end

create_table "blazer_queries", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.datetime "created_at", null: false
t.integer "creator_id"
t.string "data_source"
t.text "description"
t.string "name"
t.text "statement"
t.string "status"
t.datetime "updated_at", null: false
t.index ["creator_id"], name: "index_blazer_queries_on_creator_id"
end

create_table "bookmark_annotations", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.text "annotation", size: :long
t.integer "bookmark_id"
Expand Down Expand Up @@ -1164,6 +1220,14 @@
add_foreign_key "age_ranges", "windows_types"
add_foreign_key "banners", "users", column: "created_by_id"
add_foreign_key "banners", "users", column: "updated_by_id"
add_foreign_key "blazer_audits", "blazer_queries", column: "query_id"
add_foreign_key "blazer_audits", "users"
add_foreign_key "blazer_checks", "blazer_queries", column: "query_id"
add_foreign_key "blazer_checks", "users", column: "creator_id"
add_foreign_key "blazer_dashboard_queries", "blazer_dashboards", column: "dashboard_id"
add_foreign_key "blazer_dashboard_queries", "blazer_queries", column: "query_id"
add_foreign_key "blazer_dashboards", "users", column: "creator_id"
add_foreign_key "blazer_queries", "users", column: "creator_id"
add_foreign_key "bookmark_annotations", "bookmarks"
add_foreign_key "bookmarks", "users"
add_foreign_key "categories", "category_types"
Expand Down