Add console1984 and audits1984
To keep as much of this as we can in the `fizzy-saas` gem, this PR opts to store console/audits models in a separate database, and so: - the gem contains the migrations and the database config - the app contains a separate schema file distinctly for SaaS concerns - Rails' current behavior prevents us from easily keeping this file in the gem Also note that the stock `audits1984` schema is updated to reference the auditor via a UUID foreign key. Finally, in order for the database schema file to be located in the gem directory (and not the application directory), it's necessary to monkeypatch `AR::DatabaseTasks.schema_dump_path` to support absolute paths. This functionality has been proposed upstream in https://github.com/rails/rails/pull/56290 but is awaiting a decision from the core team. ref: https://app.fizzy.do/5986089/cards/2469 ref: #17
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
class SaasAdminController < ::AdminController
|
||||||
|
private
|
||||||
|
def find_current_auditor
|
||||||
|
Current.identity
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class SaasRecord < ActiveRecord::Base
|
||||||
|
self.abstract_class = true
|
||||||
|
|
||||||
|
connects_to database: { writing: :saas, reading: :saas }
|
||||||
|
end
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
mysql_app_user = ENV[mysql_app_user_key]
|
mysql_app_user = ENV[mysql_app_user_key]
|
||||||
mysql_app_password = ENV[mysql_app_password_key]
|
mysql_app_password = ENV[mysql_app_password_key]
|
||||||
|
|
||||||
|
gem_path = Gem::Specification.find_by_name("fizzy-saas").gem_dir
|
||||||
%>
|
%>
|
||||||
|
|
||||||
default: &default
|
default: &default
|
||||||
@@ -48,6 +50,12 @@ development:
|
|||||||
database: development_queue
|
database: development_queue
|
||||||
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
||||||
migrations_paths: db/queue_migrate
|
migrations_paths: db/queue_migrate
|
||||||
|
saas:
|
||||||
|
<<: *default
|
||||||
|
database: fizzy_saas_development
|
||||||
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
||||||
|
migrations_paths: <%= File.join(gem_path, "db", "migrate") %>
|
||||||
|
schema_dump: <%= File.join(gem_path, "db", "saas_schema.rb") %>
|
||||||
|
|
||||||
# Warning: The database defined as "test" will be erased and
|
# Warning: The database defined as "test" will be erased and
|
||||||
# re-generated from your development database when you run "rake".
|
# re-generated from your development database when you run "rake".
|
||||||
@@ -62,6 +70,12 @@ test:
|
|||||||
database: fizzy_test
|
database: fizzy_test
|
||||||
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
||||||
replica: true
|
replica: true
|
||||||
|
saas:
|
||||||
|
<<: *default
|
||||||
|
database: fizzy_saas_test
|
||||||
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
||||||
|
migrations_paths: <%= File.join(gem_path, "db", "migrate") %>
|
||||||
|
schema_dump: <%= File.join(gem_path, "db", "saas_schema.rb") %>
|
||||||
|
|
||||||
production: &production
|
production: &production
|
||||||
primary:
|
primary:
|
||||||
@@ -98,6 +112,14 @@ production: &production
|
|||||||
username: <%= mysql_app_user %>
|
username: <%= mysql_app_user %>
|
||||||
password: <%= mysql_app_password %>
|
password: <%= mysql_app_password %>
|
||||||
migrations_paths: db/cache_migrate
|
migrations_paths: db/cache_migrate
|
||||||
|
saas:
|
||||||
|
<<: *default
|
||||||
|
database: fizzy_saas_production
|
||||||
|
host: <%= ENV["MYSQL_DATABASE_HOST"] %>
|
||||||
|
username: <%= mysql_app_user %>
|
||||||
|
password: <%= mysql_app_password %>
|
||||||
|
migrations_paths: <%= File.join(gem_path, "db", "migrate") %>
|
||||||
|
schema_dump: <%= File.join(gem_path, "db", "saas_schema.rb") %>
|
||||||
|
|
||||||
beta: *production
|
beta: *production
|
||||||
staging: *production
|
staging: *production
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
Fizzy::Saas::Engine.routes.draw do
|
Fizzy::Saas::Engine.routes.draw do
|
||||||
Queenbee.routes(self)
|
Queenbee.routes(self)
|
||||||
|
|
||||||
|
namespace :admin do
|
||||||
|
mount Audits1984::Engine, at: "/console"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# This migration comes from console1984 (originally 20210517203931)
|
||||||
|
class CreateConsole1984Tables < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
create_table :console1984_sessions do |t|
|
||||||
|
t.text :reason
|
||||||
|
t.references :user, null: false, index: false
|
||||||
|
t.timestamps
|
||||||
|
|
||||||
|
t.index :created_at
|
||||||
|
t.index [ :user_id, :created_at ]
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table :console1984_users do |t|
|
||||||
|
t.string :username, null: false
|
||||||
|
t.timestamps
|
||||||
|
|
||||||
|
t.index [:username]
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table :console1984_commands do |t|
|
||||||
|
t.text :statements
|
||||||
|
t.references :sensitive_access
|
||||||
|
t.references :session, null: false, index: false
|
||||||
|
t.timestamps
|
||||||
|
|
||||||
|
t.index [ :session_id, :created_at, :sensitive_access_id ], name: "on_session_and_sensitive_chronologically"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table :console1984_sensitive_accesses do |t|
|
||||||
|
t.text :justification
|
||||||
|
t.references :session, null: false
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# This migration comes from audits1984 (originally 20210810092639)
|
||||||
|
class CreateAuditingTables < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
create_table :audits1984_audits do |t|
|
||||||
|
t.integer :status, default: 0, null: false
|
||||||
|
t.text :notes
|
||||||
|
t.references :session, null: false
|
||||||
|
t.uuid :auditor_id, null: false
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# This file is auto-generated from the current state of the database. Instead
|
||||||
|
# of editing this file, please use the migrations feature of Active Record to
|
||||||
|
# incrementally modify your database, and then regenerate this schema definition.
|
||||||
|
#
|
||||||
|
# This file is the source Rails uses to define your schema when running `bin/rails
|
||||||
|
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
||||||
|
# be faster and is potentially less error prone than running all of your
|
||||||
|
# migrations from scratch. Old migrations may fail to apply correctly if those
|
||||||
|
# migrations use external dependencies or application code.
|
||||||
|
#
|
||||||
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
|
ActiveRecord::Schema[8.2].define(version: 2025_12_02_205753) do
|
||||||
|
create_table "audits1984_audits", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
|
t.uuid "auditor_id", null: false
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.text "notes"
|
||||||
|
t.bigint "session_id", null: false
|
||||||
|
t.integer "status", default: 0, null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["session_id"], name: "index_audits1984_audits_on_session_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "console1984_commands", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.bigint "sensitive_access_id"
|
||||||
|
t.bigint "session_id", null: false
|
||||||
|
t.text "statements"
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["sensitive_access_id"], name: "index_console1984_commands_on_sensitive_access_id"
|
||||||
|
t.index ["session_id", "created_at", "sensitive_access_id"], name: "on_session_and_sensitive_chronologically"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "console1984_sensitive_accesses", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.text "justification"
|
||||||
|
t.bigint "session_id", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["session_id"], name: "index_console1984_sensitive_accesses_on_session_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "console1984_sessions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.text "reason"
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.bigint "user_id", null: false
|
||||||
|
t.index ["created_at"], name: "index_console1984_sessions_on_created_at"
|
||||||
|
t.index ["user_id", "created_at"], name: "index_console1984_sessions_on_user_id_and_created_at"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "console1984_users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.string "username", null: false
|
||||||
|
t.index ["username"], name: "index_console1984_users_on_username"
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -35,4 +35,6 @@ Gem::Specification.new do |spec|
|
|||||||
spec.add_dependency "yabeda-puma-plugin"
|
spec.add_dependency "yabeda-puma-plugin"
|
||||||
spec.add_dependency "yabeda-rails", ">= 0.10"
|
spec.add_dependency "yabeda-rails", ">= 0.10"
|
||||||
spec.add_dependency "prometheus-client-mmap", "~> 1.4.0"
|
spec.add_dependency "prometheus-client-mmap", "~> 1.4.0"
|
||||||
|
spec.add_dependency "console1984"
|
||||||
|
spec.add_dependency "audits1984"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
require_relative "transaction_pinning"
|
require_relative "transaction_pinning"
|
||||||
require_relative "signup"
|
require_relative "signup"
|
||||||
|
require_relative "../../rails_ext/active_record_tasks_database_tasks.rb"
|
||||||
|
|
||||||
module Fizzy
|
module Fizzy
|
||||||
module Saas
|
module Saas
|
||||||
@@ -41,7 +42,7 @@ module Fizzy
|
|||||||
# Load test mocks automatically in test environment
|
# Load test mocks automatically in test environment
|
||||||
initializer "fizzy_saas.test_mocks", after: :load_config_initializers do
|
initializer "fizzy_saas.test_mocks", after: :load_config_initializers do
|
||||||
if Rails.env.test?
|
if Rails.env.test?
|
||||||
require "fizzy/saas/testing"
|
require_relative "testing"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -79,6 +80,22 @@ module Fizzy
|
|||||||
require_relative "metrics"
|
require_relative "metrics"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config.before_initialize do
|
||||||
|
config.console1984.protected_environments = %i[ production beta staging ]
|
||||||
|
config.console1984.ask_for_username_if_empty = true
|
||||||
|
config.console1984.base_record_class = "::SaasRecord"
|
||||||
|
|
||||||
|
config.audits1984.base_controller_class = "::SaasAdminController"
|
||||||
|
config.audits1984.auditor_class = "::Identity"
|
||||||
|
config.audits1984.auditor_name_attribute = :email_address
|
||||||
|
|
||||||
|
if config.console1984.protected_environments.include?(Rails.env.to_sym)
|
||||||
|
config.active_record.encryption.primary_key = ENV.fetch("ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY")
|
||||||
|
config.active_record.encryption.deterministic_key = ENV.fetch("ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY")
|
||||||
|
config.active_record.encryption.key_derivation_salt = ENV.fetch("ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
config.to_prepare do
|
config.to_prepare do
|
||||||
::Signup.prepend(Fizzy::Saas::Signup)
|
::Signup.prepend(Fizzy::Saas::Signup)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
module ActiveRecordTasksDatabaseTasksExtension
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
class_methods do
|
||||||
|
# proposed upstream in https://github.com/rails/rails/pull/56290
|
||||||
|
def schema_dump_path(db_config, format = db_config.schema_format)
|
||||||
|
return ENV["SCHEMA"] if ENV["SCHEMA"]
|
||||||
|
|
||||||
|
filename = db_config.schema_dump(format)
|
||||||
|
return unless filename
|
||||||
|
|
||||||
|
if Pathname.new(filename).absolute?
|
||||||
|
filename
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ActiveSupport.on_load(:active_record) do
|
||||||
|
ActiveRecord::Tasks::DatabaseTasks.include(ActiveRecordTasksDatabaseTasksExtension)
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user