Class: RubyCms::PasskeyWiring

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_cms/passkey_wiring.rb

Overview

Patches the host app's User model for passkey support:

* `has_many :passkey_credentials, dependent: :destroy`
* `before_create :assign_webauthn_id`
* private `assign_webauthn_id` method

Runs only when the passkeys module is installed. Idempotent.

Constant Summary collapse

ASSOCIATION =
"  has_many :passkey_credentials, dependent: :destroy"
CALLBACK =
"  before_create :assign_webauthn_id"
PRIVATE_METHOD =
<<~RUBY
  \n  private\n
    def assign_webauthn_id
      self.webauthn_id ||= SecureRandom.base64(32)
    end
RUBY

Instance Method Summary collapse

Constructor Details

#initialize(app_root:) ⇒ PasskeyWiring

Returns a new instance of PasskeyWiring.



21
22
23
# File 'lib/ruby_cms/passkey_wiring.rb', line 21

def initialize(app_root:)
  @path = Pathname.new(app_root).join("app/models/user.rb")
end

Instance Method Details

#apply!Object

rubocop:disable Naming/PredicateMethod



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/ruby_cms/passkey_wiring.rb', line 25

def apply! # rubocop:disable Naming/PredicateMethod
  return false unless @path.exist?

  content = @path.read
  return false if content.include?("passkey_credentials")
  return false unless content =~ /class User .*\n/

  patched = content.sub(/(class User .*\n)/) do
    "#{::Regexp.last_match(1)}#{ASSOCIATION}\n#{CALLBACK}\n"
  end
  patched = patched.sub(/(\nend\z|\nend\n\z)/) do
    "#{PRIVATE_METHOD}#{::Regexp.last_match(1)}"
  end
  @path.write(patched)
  true
end