-
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
1,179 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
module BoringGenerators | ||
module GeneratorHelper | ||
include Rails::Generators::Actions | ||
|
||
def app_ruby_version | ||
with_ruby_string = `grep "^ruby.*$" Gemfile` || `cat .ruby-version` | ||
|
||
# only keep 3.3.0 | ||
with_ruby_string.gsub(/[^\d\.]/, '').squish | ||
end | ||
|
||
def gem_installed?(gem_name) | ||
gem_regex = /gem.*\b#{gem_name}\b.*/ | ||
File.read("Gemfile").match?(gem_regex) | ||
end | ||
|
||
def bundle_install | ||
Bundler.with_unbundled_env do | ||
run "bundle install" | ||
end | ||
end | ||
|
||
def check_and_install_gem(*args) | ||
gem_name, = args | ||
|
||
gem_file_content_array = File.readlines("Gemfile") | ||
|
||
|
||
gem_exists = gem_file_content_array.any? { |line| line.include?(gem_name) } | ||
|
||
if gem_exists | ||
say "#{gem_name} is already in the Gemfile, skipping it ...", :yellow | ||
else | ||
gem *args | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
190 changes: 190 additions & 0 deletions
190
lib/generators/boring/devise/doorkeeper/install/install_generator.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'boring_generators/generator_helper' | ||
|
||
module Boring | ||
module Devise | ||
module Doorkeeper | ||
class InstallGenerator < Rails::Generators::Base | ||
include BoringGenerators::GeneratorHelper | ||
|
||
desc "Adds doorkeeper with devise to the application" | ||
|
||
class_option :model_name, type: :string, aliases: "-m", default: "User", | ||
desc: "Tell us the user model name which will be used for authentication. Defaults to User" | ||
class_option :grant_flows, type: :array, aliases: "-gf", default: %w[authorization_code client_credentials], | ||
enum: %w[authorization_code client_credentials password], | ||
desc: "Tell us the grant flows you want to use separated by space. Defaults to authorization_code and client_credentials" | ||
class_option :api_only, type: :boolean, aliases: "-a", default: false, | ||
desc: "Tell us if you want to setup doorkeeper for API only application. Defaults to false" | ||
class_option :skip_applications_routes, type: :boolean, aliases: "-sr", default: false, | ||
desc: "Tell us if you want to skip adding doorkeeper routes to manage applications. Defaults to false" | ||
class_option :use_refresh_token, type: :boolean, aliases: "-rt", default: false, | ||
desc: "Keep user logged in with refresh tokens. Defaults to false" | ||
|
||
def verify_presence_of_devise_gem | ||
return if gem_installed?("devise") | ||
|
||
say "We couldn't find devise gem. Please configure devise gem and rerun the generator. Consider running `rails generate boring:devise:install` to set up Devise.", | ||
:red | ||
|
||
abort | ||
end | ||
|
||
def verify_presence_of_devise_model | ||
return if File.exist?("app/models/#{options[:model_name].underscore}.rb") | ||
|
||
say "We couldn't find the #{options[:model_name]} model. Maybe there is a typo? Please provide the correct model name and run the generator again.", | ||
:red | ||
|
||
abort | ||
end | ||
|
||
def add_doorkeeper_gem | ||
say "Adding doorkeeper gem", :green | ||
check_and_install_gem("doorkeeper") | ||
bundle_install | ||
end | ||
|
||
def run_doorkeeper_generators | ||
say "Running doorkeeper generators", :green | ||
|
||
Bundler.with_unbundled_env do | ||
run "bundle exec rails generate doorkeeper:install" | ||
run "bundle exec rails generate doorkeeper:migration" | ||
end | ||
end | ||
|
||
def add_doorkeeper_related_association_to_model | ||
model_name = options[:model_name].underscore | ||
say "Adding doorkeeper related associations to the model file app/models/#{model_name}.rb", | ||
:green | ||
model_content = <<~RUBY | ||
has_many :access_grants, | ||
class_name: 'Doorkeeper::AccessGrant', | ||
foreign_key: :resource_owner_id, | ||
dependent: :delete_all # or :destroy if you need callbacks | ||
has_many :access_tokens, | ||
class_name: 'Doorkeeper::AccessToken', | ||
foreign_key: :resource_owner_id, | ||
dependent: :delete_all # or :destroy if you need callbacks | ||
RUBY | ||
|
||
inject_into_file "app/models/#{model_name}.rb", | ||
optimize_indentation(model_content, 2), | ||
after: "ApplicationRecord\n" | ||
end | ||
|
||
def update_doorkeeper_initializer | ||
say "Updating doorkeeper initializer", :green | ||
|
||
configure_resource_owner_authenticator if options[:grant_flows].include?("authorization_code") | ||
configure_admin_authenticator unless options[:api_only] || options[:skip_applications_routes] | ||
configure_resource_owner_from_credentials if options[:grant_flows].include?("password") | ||
|
||
gsub_file "config/initializers/doorkeeper.rb", | ||
/# grant_flows %w\[authorization_code client_credentials\]/, | ||
"grant_flows %w[#{options[:grant_flows].uniq.join(' ')}]" | ||
|
||
if options[:api_only] | ||
gsub_file "config/initializers/doorkeeper.rb", | ||
/# api_only/, | ||
"api_only" | ||
end | ||
|
||
if options[:skip_applications_routes] | ||
doorkeeper_routes_content = <<~RUBY | ||
use_doorkeeper do | ||
skip_controllers :applications, :authorized_applications | ||
end | ||
RUBY | ||
|
||
gsub_file "config/routes.rb", | ||
/.*use_doorkeeper/, | ||
optimize_indentation(doorkeeper_routes_content, 2) | ||
end | ||
|
||
if options[:use_refresh_token] | ||
uncomment_lines "config/initializers/doorkeeper.rb", | ||
/use_refresh_token/ | ||
end | ||
end | ||
|
||
def update_doorkeeper_migration | ||
say "Updating doorkeeper migration", :green | ||
model_name = options[:model_name].underscore | ||
|
||
uncomment_lines Dir["db/migrate/*_create_doorkeeper_tables.rb"].first, | ||
/add_foreign_key :oauth/ | ||
|
||
gsub_file Dir["db/migrate/*_create_doorkeeper_tables.rb"].first, | ||
/<model>/, | ||
":#{model_name.pluralize}" | ||
|
||
return unless (%w[password client_credentials] & options[:grant_flows]).any? | ||
|
||
gsub_file Dir["db/migrate/*_create_doorkeeper_tables.rb"].first, | ||
/t.text :redirect_uri, null: false/, | ||
"t.text :redirect_uri" | ||
end | ||
|
||
def show_message | ||
return if options[:api_only] || options[:skip_applications_routes] | ||
|
||
model_name = options[:model_name].underscore | ||
admin_authenticator_content = "current_#{model_name} || warden.authenticate!(scope: :#{model_name})" | ||
|
||
say "\nWe've implemented `#{admin_authenticator_content}` in the admin_authenticator block of config/initializers/doorkeeper.rb to manage access to application routes. Please adjust it as necessary to suit your requirements.", | ||
:yellow | ||
end | ||
|
||
private | ||
|
||
def configure_resource_owner_authenticator | ||
model_name = options[:model_name].underscore | ||
resource_owner_authenticator_content = <<~RUBY | ||
resource_owner_authenticator do | ||
current_#{model_name} || warden.authenticate!(scope: :#{model_name}) | ||
end | ||
RUBY | ||
|
||
gsub_file "config/initializers/doorkeeper.rb", | ||
/.*resource_owner_authenticator do\n(?:\s|.)*?end/, | ||
optimize_indentation(resource_owner_authenticator_content, 2) | ||
end | ||
|
||
def configure_admin_authenticator | ||
model_name = options[:model_name].underscore | ||
gsub_file "config/initializers/doorkeeper.rb", | ||
/(?:# admin_authenticator do\n*)((?:\s|.)*?)(?:# end)/, | ||
"admin_authenticator do\n" + "\\1" + "end" | ||
|
||
admin_authenticator_content = "current_#{model_name} || warden.authenticate!(scope: :#{model_name})" | ||
inject_into_file "config/initializers/doorkeeper.rb", | ||
optimize_indentation(admin_authenticator_content, 4), | ||
after: /admin_authenticator do\n/, | ||
force: true | ||
|
||
end | ||
|
||
def configure_resource_owner_from_credentials | ||
model_name = options[:model_name].underscore | ||
resource_owner_for_credentials_content = <<~RUBY | ||
resource_owner_from_credentials do |routes| | ||
#{model_name} = #{options[:model_name]}.find_for_database_authentication(email: params[:email]) | ||
if #{model_name}&.valid_for_authentication? { #{model_name}.valid_password?(params[:password]) } && #{model_name}&.active_for_authentication? | ||
request.env['warden'].set_user(#{model_name}, scope: :#{model_name}, store: false) | ||
#{model_name} | ||
end | ||
end | ||
RUBY | ||
|
||
inject_into_file "config/initializers/doorkeeper.rb", | ||
optimize_indentation(resource_owner_for_credentials_content, 2), | ||
after: /resource_owner_authenticator do\n(?:\s|.)*?end\n/ | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'boring_generators/generator_helper' | ||
|
||
module Boring | ||
module Pronto | ||
class BaseGenerator < Rails::Generators::Base | ||
desc "Adds Pronto gem with various extensions" | ||
|
||
class_option :skip_extensions, type: :array, aliases: "-se", | ||
desc: "List of extensions to skip. Available options: brakeman, flay, reek, rubocop", | ||
enum: %w[brakeman flay reek rubocop], | ||
default: [] | ||
|
||
include BoringGenerators::GeneratorHelper | ||
|
||
def add_pronto_gems | ||
say "Adding pronto gems", :green | ||
pronto_gem_content = <<~RUBY | ||
\n | ||
\t# Pronto is a code linter runner that can be used with git and GitHub pull requests | ||
\tgem "pronto" | ||
#{pronto_brakemen_gem_content} | ||
#{pronto_flay_gem_content} | ||
RUBY | ||
insert_into_file "Gemfile", pronto_gem_content | ||
Bundler.with_unbundled_env do | ||
run "bundle install" | ||
end | ||
end | ||
|
||
def pronto_brakemen_gem_content | ||
return unless options[:skip_extensions].exclude?('brakeman') | ||
return if gem_installed?('pronto-brakeman') | ||
|
||
"\tgem \"pronto-brakeman\", require: false" | ||
end | ||
|
||
def pronto_flay_gem_content | ||
return unless options[:skip_extensions].exclude?('flay') | ||
return if gem_installed?('pronto-flay') | ||
|
||
"\tgem \"pronto-flay\", require: false" | ||
end | ||
end | ||
end | ||
end |
27 changes: 27 additions & 0 deletions
27
lib/generators/boring/pronto/github_action/install/install_generator.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# frozen_string_literal: true | ||
|
||
require "generators/boring/pronto/base_generator" | ||
require "boring_generators/generator_helper" | ||
|
||
module Boring | ||
module Pronto | ||
module GithubAction | ||
class InstallGenerator < Boring::Pronto::BaseGenerator | ||
desc "Adds Pronto configurations to Github Action" | ||
source_root File.expand_path("templates", __dir__) | ||
|
||
class_option :ruby_version, type: :string, aliases: "-rv" | ||
|
||
include BoringGenerators::GeneratorHelper | ||
|
||
def add_pronto_configuration_for_github_action | ||
say "Adding Pronto configurations to .github/workflows/pronto.yml", :green | ||
|
||
@ruby_version = options.ruby_version || app_ruby_version | ||
|
||
template("pronto.yml", ".github/workflows/pronto.yml") | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.