Skip to content

Commit 7dd65e8

Browse files
authored
Add GitHub oauth install generator (#25)
* Adds the google oauth install generator * Refactored and extracted the common code for oauth generator + completed the github oauth generator
1 parent 0f046fa commit 7dd65e8

File tree

10 files changed

+205
-68
lines changed

10 files changed

+205
-68
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## master (unreleased)
44
* Upgrade the Tailwind CSS generator to support Tailwind V2.0. ([@abhaynikam][])
5+
* Adds Devise GitHub Omniauth generator. ([@abhaynikam][])
56

67
## 0.6.0 (January 10th, 2021)
78
* Updates default ruby version of GitHub Actions install generator. ([@jamesglover][])

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ The boring generator introduces following generators:
6161
- Install SimpleForm: `rails generate boring:simple_form:install --css_framework=<css_framework>`
6262
- Install Devise: `rails generate boring:devise:install`
6363
- Install Devise Facebook Omniauth: `rails generate boring:oauth:facebook:install`
64+
- Install Devise GitHub Omniauth: `rails generate boring:oauth:github:install`
6465

6566
## Development
6667

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# frozen_string_literal: true
2+
3+
require 'bundler'
4+
5+
module Boring
6+
module Oauth
7+
module BaseGenerator
8+
def add_provider_and_uuid_user_details
9+
say "Adding migration to add provider and uuid columns to users", :green
10+
Bundler.with_unbundled_env do
11+
run "DISABLE_SPRING=1 bundle exec rails generate migration AddOmniauthToUsers provider:string uid:string"
12+
end
13+
end
14+
15+
def configure_devise_omniauth
16+
say "Adding omniauth devise configuration", :green
17+
if File.exist?("config/initializers/devise.rb")
18+
insert_into_file "config/initializers/devise.rb", <<~RUBY, after: /Devise.setup do \|config\|/
19+
\n
20+
\tconfig.omniauth :#{@oauth_name}, "APP_ID", "APP_SECRET"
21+
RUBY
22+
else
23+
raise MissingDeviseConfigurationError, <<~ERROR
24+
Looks like the devise installation is incomplete. Could not find devise.rb in config/initializers.
25+
ERROR
26+
end
27+
end
28+
29+
def add_omniauth_callback_routes
30+
devise_route = '# devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }'.dup
31+
route devise_route
32+
end
33+
34+
def add_omniauth_callback_controller
35+
say "Copying omniauth_callbacks_controller.rb", :green
36+
template("omniauth_callbacks_controller.rb", "app/controllers/users/omniauth_callbacks_controller.rb")
37+
end
38+
39+
def configure_and_add_devise_setting_in_user_model
40+
say "Configuring #{@oauth_name.to_s} omniauth for user model", :green
41+
insert_into_file "app/models/user.rb", <<~RUBY, after: /class User < ApplicationRecord/
42+
\n\tdevise :omniauthable, omniauth_providers: %i[#{@oauth_name}]
43+
44+
\tdef self.from_omniauth(auth)
45+
\twhere(provider: auth.provider, uid: auth.uid).first_or_create do |user|
46+
\tuser.email = auth.info.email
47+
\tuser.password = Devise.friendly_token[0, 20]
48+
\tuser.name = auth.info.name # assuming the user model has a name
49+
\t# user.image = auth.info.image # assuming the user model has an image
50+
\t# If you are using confirmable and the provider(s) you use validate emails,
51+
\t# uncomment the line below to skip the confirmation emails.
52+
\t# user.skip_confirmation!
53+
\tend
54+
\tend
55+
RUBY
56+
end
57+
58+
def show_readme
59+
readme "README"
60+
end
61+
end
62+
end
63+
end

lib/generators/boring/oauth/facebook/install/install_generator.rb

Lines changed: 11 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
# frozen_string_literal: true
22

33
require 'bundler'
4+
require 'generators/boring/oauth/base_generator'
45

56
module Boring
67
module Oauth
78
module Facebook
89
class InstallGenerator < Rails::Generators::Base
10+
include Boring::Oauth::BaseGenerator
11+
912
class MissingDeviseConfigurationError < StandardError; end
1013

1114
desc "Adds facebook OmniAuth to the application"
@@ -24,66 +27,14 @@ def add_facebook_omniauth_gem
2427
end
2528
end
2629

27-
def add_provider_and_uuid_user_details
28-
say "Adding migration to add provider and uuid columns to users", :green
29-
Bundler.with_unbundled_env do
30-
run "DISABLE_SPRING=1 bundle exec rails generate migration AddOmniauthToUsers provider:string uid:string"
31-
end
32-
end
33-
34-
def configure_devise_omniauth_facebook
35-
say "Adding omniauth devise configuration", :green
36-
if File.exist?("config/initializers/devise.rb")
37-
insert_into_file "config/initializers/devise.rb", <<~RUBY, after: /Devise.setup do \|config\|/
38-
\n
39-
\tconfig.omniauth :facebook, "APP_ID", "APP_SECRET"
40-
RUBY
41-
else
42-
raise MissingDeviseConfigurationError, <<~ERROR
43-
Looks like the devise installation is incomplete. Could not find devise.rb in config/initializers.
44-
ERROR
45-
end
46-
end
47-
48-
def add_omniauth_callback_routes
49-
devise_route = '# devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }'.dup
50-
route devise_route
51-
end
52-
53-
def add_omniauth_callback_controller
54-
say "Copying omniauth_callbacks_controller.rb", :green
55-
template("omniauth_callbacks_controller.rb", "app/controllers/users/omniauth_callbacks_controller.rb")
56-
end
57-
58-
def configure_and_add_devise_setting_in_user_model
59-
say "Configuring facebook omniauth for user model", :green
60-
insert_into_file "app/models/user.rb", <<~RUBY, after: /class User < ApplicationRecord/
61-
62-
\tdevise :omniauthable, omniauth_providers: %i[facebook]
63-
64-
\tdef self.from_omniauth(auth)
65-
\twhere(provider: auth.provider, uid: auth.uid).first_or_create do |user|
66-
\tuser.email = auth.info.email
67-
\tuser.password = Devise.friendly_token[0, 20]
68-
\tuser.name = auth.info.name # assuming the user model has a name
69-
\t# user.image = auth.info.image # assuming the user model has an image
70-
\t# If you are using confirmable and the provider(s) you use validate emails,
71-
\t# uncomment the line below to skip the confirmation emails.
72-
\t# user.skip_confirmation!
73-
\tend
74-
\tend
75-
RUBY
76-
end
77-
78-
def add_the_facebook_devise_omniauth_view
79-
insert_into_file "app/views/users/sessions/new.html.erb", <<~RUBY, after: /<%= render "users\/shared\/links" %>/
80-
81-
<%= link_to "Sign in with Facebook", user_facebook_omniauth_authorize_path %>
82-
RUBY
83-
end
84-
85-
def show_readme
86-
readme "README"
30+
def invoke_common_generator_methods
31+
@oauth_name = :facebook
32+
add_provider_and_uuid_user_details
33+
configure_devise_omniauth
34+
add_omniauth_callback_routes
35+
add_omniauth_callback_controller
36+
configure_and_add_devise_setting_in_user_model
37+
show_readme
8738
end
8839
end
8940
end

lib/generators/boring/oauth/facebook/install/templates/README

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,5 @@ Some setup you must do manually if you haven't yet:
1616
For example:
1717

1818
config.omniauth :facebook, "APP_ID", "APP_SECRET"
19-
3. Ensure you have added the facebook omniauth route in the devise session view:
20-
For example:
21-
22-
<%= link_to "Sign in with Facebook", user_facebook_omniauth_authorize_path %>
2319

2420
===============================================================================
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# frozen_string_literal: true
2+
3+
require 'bundler'
4+
require 'generators/boring/oauth/base_generator'
5+
6+
module Boring
7+
module Oauth
8+
module Github
9+
class InstallGenerator < Rails::Generators::Base
10+
include Boring::Oauth::BaseGenerator
11+
12+
class MissingDeviseConfigurationError < StandardError; end
13+
14+
desc "Adds GitHub OmniAuth to the application"
15+
source_root File.expand_path("templates", __dir__)
16+
17+
def add_github_omniauth_gem
18+
say "Adding GitHub OmniAuth gem", :green
19+
github_omniauth_gem = <<~RUBY
20+
\n
21+
# for omniauth github
22+
gem 'omniauth-github', '~> 1.4.0'
23+
RUBY
24+
append_to_file "Gemfile", github_omniauth_gem
25+
Bundler.with_unbundled_env do
26+
run "bundle install"
27+
end
28+
end
29+
30+
def invoke_common_generator_methods
31+
@oauth_name = :github
32+
add_provider_and_uuid_user_details
33+
configure_devise_omniauth
34+
add_omniauth_callback_routes
35+
add_omniauth_callback_controller
36+
configure_and_add_devise_setting_in_user_model
37+
show_readme
38+
end
39+
end
40+
end
41+
end
42+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
===============================================================================
2+
3+
Some setup you must do manually if you haven't yet:
4+
5+
1. Ensure you have overridden or uncommented the routes for generated omniauth callback controllers in your routes.rb.
6+
For example:
7+
8+
Rails.application.routes.draw do
9+
devise_for :users, controllers: {
10+
omniauth_callbacks: "users/omniauth_callbacks"
11+
}
12+
end
13+
14+
2. Update the devise github omniauth APP_ID and APP_SECRET in "config/initializers/devise.rb"
15+
after registering the Rails application on: https://github.com/settings/applications/new
16+
For example:
17+
18+
config.omniauth :github, "APP_ID", "APP_SECRET"
19+
20+
===============================================================================
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
2+
# See https://github.com/omniauth/omniauth/wiki/FAQ#rails-session-is-clobbered-after-callback-on-developer-strategy
3+
skip_before_action :verify_authenticity_token, only: :github
4+
5+
def github
6+
# You need to implement the method below in your model (e.g. app/models/user.rb)
7+
@user = User.from_omniauth(request.env["omniauth.auth"])
8+
9+
if @user.persisted?
10+
sign_in_and_redirect @user, event: :authentication #this will throw if @user is not activated
11+
set_flash_message(:notice, :success, kind: "GitHub") if is_navigational_format?
12+
else
13+
session["devise.github_data"] = request.env["omniauth.auth"].except(:extra) # Removing extra as it can overflow some session stores
14+
redirect_to new_user_registration_url
15+
end
16+
end
17+
18+
def failure
19+
redirect_to root_path
20+
end
21+
end

test/generators/oauth/facebook_install_generator_test.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ def test_should_install_facebook_oauth
3333
assert_match('devise :omniauthable, omniauth_providers: %i[facebook]', content)
3434
assert_match('def self.from_omniauth(auth)', content)
3535
end
36-
37-
assert_file "app/views/users/sessions/new.html.erb" do |content|
38-
assert_match('Sign in with Facebook', content)
39-
end
4036
end
4137
end
4238

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
require "generators/boring/devise/install/install_generator"
5+
require "generators/boring/oauth/github/install/install_generator"
6+
7+
class OauthGithubInstallGeneratorTest < Rails::Generators::TestCase
8+
tests Boring::Oauth::Github::InstallGenerator
9+
setup :build_app
10+
teardown :teardown_app
11+
12+
include GeneratorHelper
13+
include ActiveSupport::Testing::Isolation
14+
15+
def destination_root
16+
app_path
17+
end
18+
19+
def test_should_install_github_oauth
20+
Dir.chdir(app_path) do
21+
quietly { Rails::Generators.invoke("boring:devise:install") }
22+
quietly { run_generator }
23+
24+
assert_gem "omniauth-github"
25+
assert_migration "db/migrate/add_omniauth_to_users.rb"
26+
assert_file "config/initializers/devise.rb" do |content|
27+
assert_match('config.omniauth :github', content)
28+
end
29+
30+
assert_file "app/controllers/users/omniauth_callbacks_controller.rb"
31+
32+
assert_file "app/models/user.rb" do |content|
33+
assert_match('devise :omniauthable, omniauth_providers: %i[github]', content)
34+
assert_match('def self.from_omniauth(auth)', content)
35+
end
36+
end
37+
end
38+
39+
def test_should_raise_devise_configuration_missing_error
40+
Dir.chdir(app_path) do
41+
assert_raises do
42+
run_generator
43+
end
44+
end
45+
end
46+
end

0 commit comments

Comments
 (0)