Class: Passkeyed::Generators::InstallGenerator
- Inherits:
-
Rails::Generators::Base
- Object
- Rails::Generators::Base
- Passkeyed::Generators::InstallGenerator
- Includes:
- ActiveRecord::Generators::Migration
- Defined in:
- lib/generators/passkeyed/install/install_generator.rb
Overview
Wires passkeyed into a host Rails app:
bin/rails generate passkeyed:install
Adds the credentials table (and a webauthn_id column on the owner), an initializer, the Stimulus controller, and the model concern.
Instance Method Summary collapse
- #copy_stimulus_controller ⇒ Object
- #create_initializer ⇒ Object
- #create_migration_file ⇒ Object
- #inject_model_concern ⇒ Object
- #print_next_steps ⇒ Object
Instance Method Details
#copy_stimulus_controller ⇒ Object
35 36 37 38 39 40 |
# File 'lib/generators/passkeyed/install/install_generator.rb', line 35 def copy_stimulus_controller copy_file( "passkey_controller.js", "app/javascript/controllers/passkey_controller.js" ) end |
#create_initializer ⇒ Object
31 32 33 |
# File 'lib/generators/passkeyed/install/install_generator.rb', line 31 def create_initializer template "initializer.rb", "config/initializers/passkeyed.rb" end |
#create_migration_file ⇒ Object
24 25 26 27 28 29 |
# File 'lib/generators/passkeyed/install/install_generator.rb', line 24 def create_migration_file migration_template( "create_passkeyed_credentials.rb.erb", "db/migrate/create_passkeyed_credentials.rb" ) end |
#inject_model_concern ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/generators/passkeyed/install/install_generator.rb', line 42 def inject_model_concern model_path = "app/models/#{owner_model.underscore}.rb" full_path = File.join(destination_root, model_path) unless File.exist?(full_path) say_status :skip, "#{model_path} not found; add `include Passkeyed::Model` to your owner model", :yellow return end source = File.read(full_path) class_name = owner_model.demodulize # Idempotent: re-running the generator must not inject a second include. # Anchor on a real include line (not a bare substring, which a comment or # the just-injected snippet would satisfy). if source.match?(/^\s*include\s+Passkeyed::Model\b/) say_status :identical, "Passkeyed::Model already included in #{model_path}", :blue return end # A single-line body (`class User; end`) can't take an injected line # safely, so bail to a manual instruction rather than placing the include # outside the class. if source.match?(/^\s*class\s+#{Regexp.escape(class_name)}\b[^\n]*;\s*end/) say_status :skip, "#{model_path} defines #{class_name} on one line; add `include Passkeyed::Model` manually", :yellow return end # inject_into_class places the include after the class declaration with # correct indentation, and handles namespaced/indented definitions. inject_into_class model_path, class_name, " include Passkeyed::Model\n" # inject_into_class is a silent no-op when the class can't be matched, so # confirm the include actually landed rather than reporting false success. return if File.read(full_path).match?(/^\s*include\s+Passkeyed::Model\b/) say_status :skip, "could not edit #{model_path}; add `include Passkeyed::Model` manually", :yellow end |
#print_next_steps ⇒ Object
82 83 84 85 86 |
# File 'lib/generators/passkeyed/install/install_generator.rb', line 82 def print_next_steps say "\npasskeyed installed. Next:", :green say " 1. bin/rails db:migrate" say " 2. add routes + a controller using Passkeyed::Ceremonies (see the README)" end |