-
Notifications
You must be signed in to change notification settings - Fork 755
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] GitHub Authentication #1595
Changes from all commits
557bce5
4d66809
d1771fb
06f2740
6b1698a
6e6a3ac
67c8e5e
bc9eb4c
e94f239
69c7cf4
e4d6359
55fbb03
25f05a5
333028a
dd6b7bb
06b4482
97641a7
c82023f
b585f49
c517f55
a1e85f3
411ac59
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,20 @@ def google_oauth2 | |
kind: t('omniauth.google')) | ||
sign_in_and_redirect @user, event: :authentication | ||
else | ||
redirect_to new_user_session_path, notice: t('omniauth.access_denied') | ||
redirect_to new_user_session_path, alert: t('omniauth.access_denied') | ||
end | ||
end | ||
|
||
def github | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am just curious why we have github auth, are our users mostly from github? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is something that @julianguyen can answer, but if I may try. since this is a platform that encourages collaboration, maybe a target audience of tech people are in mind? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah GitHub authentication isn't a priority like Facebook would be for instance. This was requested by a contributor 🙃 But we could use this functionality to show links for filing GitHub issues just for folks signed in it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also test this new method! |
||
@user = User.from_omniauth request.env['omniauth.auth'] | ||
|
||
if @user.valid? | ||
flash[:notice] = I18n.t('devise.omniauth_callbacks.success', | ||
kind: t('omniauth.github')) | ||
|
||
sign_in_and_redirect @user, event: :authentication | ||
else | ||
redirect_to new_user_session_path, alert: t('omniauth.access_denied') | ||
end | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,7 +55,7 @@ class User < ApplicationRecord | |
# :confirmable, :lockable, :timeoutable and :omniauthable | ||
devise :invitable, :database_authenticatable, :registerable, :uid, | ||
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, | ||
omniauth_providers: [:google_oauth2] | ||
omniauth_providers: %i[google_oauth2 github] | ||
|
||
mount_uploader :avatar, AvatarUploader | ||
|
||
|
@@ -81,24 +81,38 @@ class User < ApplicationRecord | |
validates :locale, inclusion: { | ||
in: Rails.application.config.i18n.available_locales.map(&:to_s).push(nil) | ||
} | ||
validate :password_complexity | ||
|
||
# add unless statement here instead of the concern for readability | ||
# TODO: refactor the Password validator concern | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this be done in another PR? :) Feel free to create an issue for this as well just to document. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is one of the setbacks on making this PR short. I agree on having this as another ticket. |
||
validate :password_complexity, unless: :oauth_provided? | ||
|
||
def active_for_authentication? | ||
super && !banned | ||
end | ||
|
||
def self.find_for_google_oauth2(access_token) | ||
user = find_or_initialize_by(email: access_token.info.email) | ||
user.name ||= access_token.info.name | ||
# TODO: to refactor and to move to builder pattern | ||
# UserBuilder::GoogleOauth2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar comment as above. |
||
def self.find_for_google_oauth2(auth) | ||
user = find_or_initialize_by(email: auth.info.email) | ||
user.name ||= auth.info.name | ||
user.password ||= Devise.friendly_token[0, 20] | ||
update_access_token_fields(user: user, access_token: access_token) | ||
update_access_token_fields(user: user, access_token: auth) | ||
user | ||
end | ||
|
||
# to refactor, could be single oauth method to begin with | ||
def self.from_omniauth(auth) | ||
where(provider: auth.provider, | ||
uid: auth.provider + auth.uid).first_or_create do |user| | ||
UserBuilder::Builder.build(user: user, auth: auth) | ||
end | ||
end | ||
|
||
def google_access_token | ||
google_access_token_expired? ? update_access_token : token | ||
end | ||
|
||
# TODO: refactor this and use one checker | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call! |
||
def google_oauth2_enabled? | ||
token.present? | ||
end | ||
|
@@ -140,6 +154,11 @@ def update_access_token | |
|
||
private | ||
|
||
# checks if user is created from oauth | ||
def oauth_provided? | ||
provider.present? || token.present? | ||
end | ||
|
||
def google_access_token_expired? | ||
!access_expires_at || Time.zone.now > access_expires_at | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# frozen_string_literal: true | ||
module UserBuilder | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
class Base | ||
attr_reader :user | ||
|
||
def self.call(user:, auth:) | ||
new(user: user, auth: auth) | ||
end | ||
|
||
def initialize(user:, auth:) | ||
@user = user | ||
@user.tap do | ||
user.provider = auth.provider | ||
user.name = auth.info.name | ||
user.uid = provider_uid(auth) | ||
user.email = auth.info.email | ||
user.password = default_password | ||
end | ||
end | ||
|
||
private | ||
|
||
def default_password | ||
Devise.friendly_token[0, 20] | ||
end | ||
|
||
def provider_uid(auth) | ||
auth.provider + auth.uid | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# frozen_string_literal: true | ||
module UserBuilder | ||
class Builder | ||
# Adds new omni auth providers here | ||
SERVICE = { | ||
# 'google_oauth' => GoogleOauth2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be uncommented? |
||
}.freeze | ||
|
||
# UserBuilder::Builder.build(user: user, provider: provider, auth: auth) | ||
def self.build(user:, auth:) | ||
service = SERVICE.fetch(auth.provider, UserBuilder::Base) | ||
service.call(user: user, auth: auth) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,16 @@ | ||
<div class="smallMarginTop"> | ||
<%- if devise_mapping.omniauthable? and request.base_url != 'http://0.0.0.0:3000' %> | ||
<%- resource_class.omniauth_providers.each do |provider| %> | ||
<% if provider.to_s == "google_oauth2" && (current_page?(new_user_session_path) || current_page?(new_user_password_path)) %> | ||
<%= button_to t('devise.shared.sign_in_google'), omniauth_authorize_path(resource_name, provider), method: :post, class: 'buttonGhostM' %> | ||
<% elsif provider.to_s == "google_oauth2" %> | ||
<%= button_to t('devise.shared.sign_up_google'), omniauth_authorize_path(resource_name, provider), method: :post, class: 'buttonGhostM' %> | ||
<% end -%> | ||
<%- resource_class.omniauth_providers.each do |provider| %> | ||
|
||
<% if provider.to_s == "google_oauth2" && (current_page?(new_user_session_path) || current_page?(new_user_password_path)) %> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: show_signup_page? provider show_register_page? provider |
||
<%= button_to t('devise.shared.sign_in_google'), omniauth_authorize_path(resource_name, provider), method: :post, class: 'buttonGhostM smallMarginBottom' %> | ||
<% elsif provider.to_s == "github" && (current_page?(new_user_session_path) || current_page?(new_user_password_path)) %> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this part is a bit dirty, needs some refactoring There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be great! |
||
<%= button_to t('devise.shared.sign_in_github'), omniauth_authorize_path(resource_name, provider), method: :post, class: 'buttonGhostM smallMarginBottom' %> | ||
<% elsif provider.to_s == "google_oauth2" %> | ||
<%= button_to t('devise.shared.sign_up_google'), omniauth_authorize_path(resource_name, provider), method: :post, class: 'buttonGhostM smallMarginBottom' %> | ||
<% elsif provider.to_s == 'github' %> | ||
<%= button_to t('devise.shared.sign_up_github'), omniauth_authorize_path(resource_name, provider), method: :post, class: 'buttonGhostM smallMarginBottom' %> | ||
<% end -%> | ||
<% end -%> | ||
<% end -%> | ||
</div> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -440,6 +440,7 @@ it: | |
nostra %{code_of_conduct_link}. Non sei più bannato.' | ||
omniauth: | ||
google: Google | ||
github: Github | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I don't think we need to add another GitHub translation since we already have one at |
||
access_denied: 'Accesso Negato' | ||
pages: | ||
about: | ||
|
@@ -965,6 +966,8 @@ it: | |
shared: | ||
sign_in_google: 'Effettua il login con Google' | ||
sign_up_google: 'Registrati con Google' | ||
sign_in_github: 'Sign in with Github' | ||
sign_up_github: 'Sign up with Github' | ||
confirmation: 'Non hai ricevuto le istruzioni per confermare la tua EMail?' | ||
unlock: 'Non hai ricevuto le istruzioni per sbloccare il tuo account?' | ||
unlock: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this gem necessary? What's it being used for?