Commit 5c510d69b4daa882c3a075c24a287573c93cd470
1 parent
6ef69937
Exists in
master
Add sign in with google omniauth
Showing
16 changed files
with
98 additions
and
0 deletions
Show diff stats
.env.default
... | ... | @@ -23,3 +23,5 @@ GITHUB_API_URL=https://api.github.com |
23 | 23 | GITHUB_ACCESS_SCOPE='[repo]' |
24 | 24 | GITHUB_SITE_TITLE=GitHub |
25 | 25 | DEVISE_MODULES='[database_authenticatable,recoverable,rememberable,trackable,validatable,omniauthable]' |
26 | +GOOGLE_AUTHENTICATION=true | |
27 | +GOOGLE_SITE_TITLE=Google | ... | ... |
Gemfile
Gemfile.lock
... | ... | @@ -228,6 +228,11 @@ GEM |
228 | 228 | omniauth-github (1.1.2) |
229 | 229 | omniauth (~> 1.0) |
230 | 230 | omniauth-oauth2 (~> 1.1) |
231 | + omniauth-google-oauth2 (0.4.0) | |
232 | + jwt (~> 1.5.0) | |
233 | + multi_json (~> 1.3) | |
234 | + omniauth (>= 1.1.1) | |
235 | + omniauth-oauth2 (>= 1.3.1) | |
231 | 236 | omniauth-oauth2 (1.3.1) |
232 | 237 | oauth2 (~> 1.0) |
233 | 238 | omniauth (~> 1.2) |
... | ... | @@ -460,6 +465,7 @@ DEPENDENCIES |
460 | 465 | mongoid-rspec (~> 3.0.0) |
461 | 466 | mongoid_rails_migrations |
462 | 467 | omniauth-github |
468 | + omniauth-google-oauth2 | |
463 | 469 | pjax_rails |
464 | 470 | poltergeist |
465 | 471 | pry-byebug | ... | ... |
app/assets/stylesheets/errbit.css.erb
... | ... | @@ -231,6 +231,7 @@ a.action { float: right; font-size: 0.9em;} |
231 | 231 | } |
232 | 232 | |
233 | 233 | #action-bar span.github a:before { font-family: FontAwesome; content: "\f09b"; margin-right: 8px; position: relative; top: 4px; font-size: 26px; } |
234 | +#action-bar span.google a:before { font-family: FontAwesome; content: "\f1a0"; margin-right: 8px; position: relative; top: 4px; font-size: 26px; } | |
234 | 235 | |
235 | 236 | #action-bar span a.issue-tracker-button { |
236 | 237 | padding-left: 5px; | ... | ... |
app/controllers/users/omniauth_callbacks_controller.rb
... | ... | @@ -39,6 +39,32 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController |
39 | 39 | end |
40 | 40 | end |
41 | 41 | |
42 | + def google_oauth2 | |
43 | + google_uid = env['omniauth.auth'].uid | |
44 | + google_email = env['omniauth.auth'].info.email | |
45 | + google_user = User.where(google_uid: google_uid).first | |
46 | + google_site_title = Errbit::Config.google_site_title | |
47 | + # If user is already signed in, link google details to their account | |
48 | + if current_user | |
49 | + # ... unless a user is already registered with same google login | |
50 | + if google_user && google_user != current_user | |
51 | + flash[:error] = "User already registered with #{google_site_title} login '#{google_email}'!" | |
52 | + else | |
53 | + # Add github details to current user | |
54 | + current_user.update(google_uid: google_uid) | |
55 | + flash[:success] = "Successfully linked #{google_email} account!" | |
56 | + end | |
57 | + # User must have clicked 'link account' from their user page, so redirect there. | |
58 | + redirect_to user_path(current_user) | |
59 | + elsif google_user | |
60 | + flash[:success] = I18n.t 'devise.omniauth_callbacks.success', kind: google_site_title | |
61 | + sign_in_and_redirect google_user, event: :authentication | |
62 | + else | |
63 | + flash[:error] = "There are no authorized users with #{google_site_title} login '#{google_email}'. Please ask an administrator to register your user account." | |
64 | + redirect_to new_user_session_path | |
65 | + end | |
66 | + end | |
67 | + | |
42 | 68 | private def update_user_with_github_attributes(user, login, token) |
43 | 69 | user.update_attributes( |
44 | 70 | github_login: login, | ... | ... |
app/controllers/users_controller.rb
app/models/user.rb
... | ... | @@ -8,6 +8,7 @@ class User |
8 | 8 | field :email |
9 | 9 | field :github_login |
10 | 10 | field :github_oauth_token |
11 | + field :google_uid | |
11 | 12 | field :name |
12 | 13 | field :admin, type: Boolean, default: false |
13 | 14 | field :per_page, type: Fixnum, default: PER_PAGE |
... | ... | @@ -71,6 +72,10 @@ class User |
71 | 72 | self[:github_login] = login |
72 | 73 | end |
73 | 74 | |
75 | + def google_account? | |
76 | + google_uid.present? | |
77 | + end | |
78 | + | |
74 | 79 | def ensure_authentication_token |
75 | 80 | if authentication_token.blank? |
76 | 81 | self.authentication_token = generate_authentication_token | ... | ... |
app/views/devise/sessions/new.html.haml
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 | - content_for :action_bar do |
6 | 6 | %div.action-bar |
7 | 7 | %span.github= link_to "Sign in with #{Errbit::Config.github_site_title}", user_omniauth_authorize_path(:github) |
8 | + %span.google= link_to "Sign in with #{Errbit::Config.google_site_title}", user_omniauth_authorize_path(:google_oauth2) | |
8 | 9 | |
9 | 10 | = form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| |
10 | 11 | .required | ... | ... |
... | ... | @@ -0,0 +1,5 @@ |
1 | +- if Errbit::Config.google_authentication && user == current_user | |
2 | + - if user.google_account? | |
3 | + %span.google= link_to "Unlink #{Errbit::Config.google_site_title} account", unlink_google_user_path, method: :delete, data: { confirm: 'Are you sure?' } | |
4 | + - else | |
5 | + %span.google= link_to "Link #{Errbit::Config.google_site_title} account", user_omniauth_authorize_path(:google_oauth2) | ... | ... |
app/views/users/edit.html.haml
1 | 1 | - content_for :title, "Edit #{user.name}" |
2 | 2 | - content_for :action_bar do |
3 | 3 | = render 'shared/link_github_account', :user => user |
4 | + = render 'shared/link_google_account' | |
4 | 5 | = link_to('cancel', user_path(user), :class => 'button') |
5 | 6 | |
6 | 7 | = form_for user, :html => {:autocomplete => "off"} do |f| | ... | ... |
app/views/users/show.html.haml
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | |
8 | 8 | - content_for :action_bar do |
9 | 9 | = render 'shared/link_github_account' |
10 | + = render 'shared/link_google_account' | |
10 | 11 | = link_to 'edit', edit_user_path(user), :class => 'button' |
11 | 12 | = link_to 'destroy', user_path(user), :method => :delete, |
12 | 13 | :data => { :confirm => t('users.confirm_delete') }, :class => 'delete button' | ... | ... |
config/initializers/devise.rb
... | ... | @@ -252,6 +252,12 @@ Devise.setup do |config| |
252 | 252 | github_options |
253 | 253 | end |
254 | 254 | |
255 | + if Errbit::Config.google_authentication || Rails.env.test? | |
256 | + config.omniauth :google_oauth2, | |
257 | + Errbit::Config.google_client_id, | |
258 | + Errbit::Config.google_secret | |
259 | + end | |
260 | + | |
255 | 261 | # ==> Warden configuration |
256 | 262 | # If you want to use other strategies, that are not supported by Devise, or |
257 | 263 | # change the failure app, you can configure them inside the config.warden block. | ... | ... |
config/load.rb
... | ... | @@ -39,6 +39,11 @@ Errbit::Config = Configurator.run( |
39 | 39 | github_access_scope: ['GITHUB_ACCESS_SCOPE'], |
40 | 40 | github_api_url: ['GITHUB_API_URL'], |
41 | 41 | github_site_title: ['GITHUB_SITE_TITLE'], |
42 | ||
43 | + google_authentication: ['GOOGLE_AUTHENTICATION'], | |
44 | + google_site_title: ['GOOGLE_SITE_TITLE'], | |
45 | + google_client_id: ['GOOGLE_CLIENT_ID'], | |
46 | + google_secret: ['GOOGLE_SECRET'], | |
42 | 47 | |
43 | 48 | email_delivery_method: ['EMAIL_DELIVERY_METHOD', lambda do |values| |
44 | 49 | values[:email_delivery_method] && values[:email_delivery_method].to_sym | ... | ... |
config/routes.rb
spec/acceptance/acceptance_helper.rb
... | ... | @@ -18,6 +18,14 @@ def mock_auth(user = "test_user", token = "abcdef") |
18 | 18 | 'token' => token |
19 | 19 | } |
20 | 20 | ) |
21 | + | |
22 | + OmniAuth.config.mock_auth[:google_oauth2] = Hashie::Mash.new( | |
23 | + provider: 'google', | |
24 | + uid: user, | |
25 | + info: { | |
26 | + email: 'errbit@errbit.example.com' | |
27 | + } | |
28 | + ) | |
21 | 29 | end |
22 | 30 | |
23 | 31 | def log_in(user) | ... | ... |
... | ... | @@ -0,0 +1,23 @@ |
1 | +require 'acceptance/acceptance_helper' | |
2 | + | |
3 | +feature 'Sign in with Google' do | |
4 | + background do | |
5 | + allow(Errbit::Config).to receive(:google_authentication).and_return(true) | |
6 | + Fabricate(:user, google_uid: 'nashby') | |
7 | + visit root_path | |
8 | + end | |
9 | + | |
10 | + scenario 'log in via Google with recognized user' do | |
11 | + mock_auth('nashby') | |
12 | + | |
13 | + click_link 'Sign in with Google' | |
14 | + expect(page).to have_content I18n.t('devise.omniauth_callbacks.success', kind: 'Google') | |
15 | + end | |
16 | + | |
17 | + scenario 'reject unrecognized user if authenticating via Google' do | |
18 | + mock_auth('unknown_user') | |
19 | + | |
20 | + click_link 'Sign in with Google' | |
21 | + expect(page).to have_content 'There are no authorized users with Google login' | |
22 | + end | |
23 | +end | ... | ... |