feat: migrate AuthUser to main database

This commit completes the migration to consolidate the openneo_id database
into the main openneo_impress database.

Changes:
- AuthUser: Changed from AuthRecord to ApplicationRecord
- AuthUser: Removed explicit table_name (Rails infers 'auth_users')
- AuthUser: Removed all temporary write lock code
- AuthUser: Added TODO comment about future table merge opportunity
- User: Added TODO comment about simplifying remote_id relationship
- AuthRecord: Deleted (no longer needed)
- ApplicationController: Removed temporary rescue_from handler
- database.yml: Removed openneo_id database configuration entirely
- database.yml: Simplified from multi-database (primary:) to single-database structure

The application now runs as a single-database Rails app. The auth_users table
lives in the main openneo_impress database alongside the users table, with
the remote_id relationship preserved.

Next steps for production:
1. Deploy Phase 1 (write lock)
2. Run the CopyAuthUsersTableToMainDatabase migration
3. Deploy this commit (Phase 2)
4. Verify everything works
5. Drop the openneo_id database

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Emi Matchu 2025-11-02 06:55:11 +00:00
parent 604a8667cf
commit 2c21269a16
5 changed files with 30 additions and 97 deletions

View file

@ -27,10 +27,6 @@ class ApplicationController < ActionController::Base
rescue_from ActiveRecord::ConnectionTimeoutError, with: :on_db_timeout
# TEMPORARY: Rescue handler for database migration write lock
# This catches attempts to modify AuthUser records during the migration.
rescue_from AuthUser::TemporarilyReadOnly, with: :on_auth_user_read_only
def authenticate_user!
redirect_to(new_auth_user_session_path) unless user_signed_in?
end
@ -77,11 +73,6 @@ class ApplicationController < ActionController::Base
status: :service_unavailable
end
def on_auth_user_read_only
flash[:alert] = "Account changes are temporarily unavailable during maintenance. Please try again shortly."
redirect_to root_path
end
def redirect_back!(default=:back)
redirect_to(params[:return_to] || default)
end

View file

@ -1,5 +0,0 @@
class AuthRecord < ApplicationRecord
self.abstract_class = true
connects_to database: {reading: :openneo_id, writing: :openneo_id}
end

View file

@ -1,39 +1,12 @@
class AuthUser < AuthRecord
self.table_name = 'users'
# TEMPORARY: Write lock for database migration
# During the migration to consolidate databases, we need to prevent writes to
# the AuthUser table while keeping reads (like login) working. This will be
# removed in the next phase of the migration.
class TemporarilyReadOnly < StandardError; end
# Block all save attempts via before_save callback (more reliable than overriding methods)
before_save :prevent_writes_during_migration
before_destroy :prevent_writes_during_migration
def prevent_writes_during_migration
raise TemporarilyReadOnly, "Account changes temporarily unavailable during maintenance"
end
class AuthUser < ApplicationRecord
# TODO: Consider merging with User model to eliminate the remote_id relationship
# and simplify the authentication architecture. This would involve combining the
# auth_users and users tables into a single table.
devise :database_authenticatable, :encryptable, :registerable, :validatable,
:rememberable, :trackable, :recoverable, :omniauthable,
omniauth_providers: [:neopass]
# Disable Devise's trackable feature during migration to prevent login tracking updates
# This means we'll lose some login tracking data during the migration window, but that's
# acceptable compared to breaking logins entirely.
def update_tracked_fields!(request)
# Normally this would update sign_in_count, current_sign_in_at, etc.
# During migration, we just skip it silently.
end
# Disable Devise's rememberable feature during migration to prevent logout from crashing
# This means remember_created_at won't be cleared on logout, but that's acceptable.
def forget_me!
# Normally this would update remember_created_at to nil.
# During migration, we just skip it silently.
end
validates :name, presence: true, uniqueness: {case_sensitive: false},
length: {maximum: 30}

View file

@ -3,6 +3,9 @@ class User < ApplicationRecord
PreviewTopContributorsCount = 3
# TODO: This relationship could be simplified by merging the auth_users and users
# tables. Currently User.remote_id points to AuthUser.id, but if the tables were
# merged, we could eliminate remote_id and auth_server_id entirely.
belongs_to :auth_user, foreign_key: :remote_id, inverse_of: :user
delegate :disconnect_neopass, :uses_neopass?, to: :auth_user

View file

@ -1,57 +1,28 @@
development:
primary:
adapter: mysql2
host: <%= ENV.fetch("DB_HOST", "localhost") %>
database: openneo_impress
username: root
pool: 5
encoding: utf8mb4
collation: utf8mb4_unicode_520_ci
variables:
sql_mode: TRADITIONAL
openneo_id:
adapter: mysql2
host: <%= ENV.fetch("DB_HOST", "localhost") %>
database: openneo_id
username: root
pool: 2
variables:
sql_mode: TRADITIONAL
migrations_paths: db/openneo_id_migrate
adapter: mysql2
host: <%= ENV.fetch("DB_HOST", "localhost") %>
database: openneo_impress
username: root
pool: 5
encoding: utf8mb4
collation: utf8mb4_unicode_520_ci
variables:
sql_mode: TRADITIONAL
test:
primary:
adapter: mysql2
host: <%= ENV.fetch("DB_HOST", "localhost") %>
database: openneo_impress_test
username: root
pool: 5
encoding: utf8mb4
collation: utf8mb4_unicode_520_ci
variables:
sql_mode: TRADITIONAL
openneo_id:
adapter: mysql2
host: <%= ENV.fetch("DB_HOST", "localhost") %>
database: openneo_id_test
username: root
pool: 2
variables:
sql_mode: TRADITIONAL
migrations_paths: db/openneo_id_migrate
adapter: mysql2
host: <%= ENV.fetch("DB_HOST", "localhost") %>
database: openneo_impress_test
username: root
pool: 5
encoding: utf8mb4
collation: utf8mb4_unicode_520_ci
variables:
sql_mode: TRADITIONAL
production:
primary:
url: <%= ENV['DATABASE_URL_PRIMARY'] %>
encoding: utf8mb4
collation: utf8mb4_unicode_520_ci
variables:
sql_mode: TRADITIONAL
openneo_id:
url: <%= ENV['DATABASE_URL_OPENNEO_ID'] %>
variables:
sql_mode: TRADITIONAL
migrations_paths: db/openneo_id_migrate
url: <%= ENV['DATABASE_URL_PRIMARY'] %>
encoding: utf8mb4
collation: utf8mb4_unicode_520_ci
variables:
sql_mode: TRADITIONAL