adds omniauth basic authentication process with Twitter, including an intermediate step to ask the user for her email if not provided by the OAuth provider - Twitter, for instance
This commit is contained in:
@@ -13,6 +13,8 @@ class ApplicationController < ActionController::Base
|
|||||||
# For APIs, you may want to use :null_session instead.
|
# For APIs, you may want to use :null_session instead.
|
||||||
protect_from_forgery with: :exception
|
protect_from_forgery with: :exception
|
||||||
|
|
||||||
|
before_action :ensure_signup_complete
|
||||||
|
|
||||||
rescue_from CanCan::AccessDenied do |exception|
|
rescue_from CanCan::AccessDenied do |exception|
|
||||||
redirect_to main_app.root_url, alert: exception.message
|
redirect_to main_app.root_url, alert: exception.message
|
||||||
end
|
end
|
||||||
@@ -40,4 +42,13 @@ class ApplicationController < ActionController::Base
|
|||||||
def set_debate_votes(debates)
|
def set_debate_votes(debates)
|
||||||
@voted_values = current_user ? current_user.debate_votes(debates) : {}
|
@voted_values = current_user ? current_user.debate_votes(debates) : {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def ensure_signup_complete
|
||||||
|
# Ensure we don't go into an infinite loop
|
||||||
|
return if action_name.in? %w(finish_signup do_finish_signup)
|
||||||
|
|
||||||
|
if user_signed_in? && !current_user.email_provided?
|
||||||
|
redirect_to finish_signup_path
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
30
app/controllers/users/omniauth_callbacks_controller.rb
Normal file
30
app/controllers/users/omniauth_callbacks_controller.rb
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
|
def self.provides_callback_for(provider)
|
||||||
|
class_eval %Q{
|
||||||
|
def #{provider}
|
||||||
|
@user = User.find_for_oauth(env["omniauth.auth"], current_user)
|
||||||
|
|
||||||
|
if @user.persisted?
|
||||||
|
sign_in_and_redirect @user, event: :authentication
|
||||||
|
set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
|
||||||
|
else
|
||||||
|
session["devise.#{provider}_data"] = env["omniauth.auth"]
|
||||||
|
redirect_to new_user_registration_url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# [:twitter, :facebook, :google_oauth2].each do |provider|
|
||||||
|
[:twitter].each do |provider|
|
||||||
|
provides_callback_for provider
|
||||||
|
end
|
||||||
|
|
||||||
|
def after_sign_in_path_for(resource)
|
||||||
|
if resource.email_provided?
|
||||||
|
super(resource)
|
||||||
|
else
|
||||||
|
finish_signup_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
class Users::RegistrationsController < Devise::RegistrationsController
|
class Users::RegistrationsController < Devise::RegistrationsController
|
||||||
|
prepend_before_filter :authenticate_scope!, only: [:edit, :update, :destroy, :finish_signup, :do_finish_signup]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
build_resource(sign_up_params)
|
build_resource(sign_up_params)
|
||||||
@@ -9,6 +10,20 @@ class Users::RegistrationsController < Devise::RegistrationsController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def finish_signup
|
||||||
|
end
|
||||||
|
|
||||||
|
def do_finish_signup
|
||||||
|
if current_user.update(sign_up_params)
|
||||||
|
current_user.skip_reconfirmation!
|
||||||
|
sign_in(current_user, bypass: true)
|
||||||
|
redirect_to root_url, notice: I18n.t('devise.registrations.updated')
|
||||||
|
else
|
||||||
|
@show_errors = true
|
||||||
|
render :finish_signup
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def sign_up_params
|
def sign_up_params
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
class User < ActiveRecord::Base
|
class User < ActiveRecord::Base
|
||||||
include ActsAsParanoidAliases
|
include ActsAsParanoidAliases
|
||||||
|
|
||||||
|
OMNIAUTH_EMAIL_PREFIX = 'omniauth@participacion'
|
||||||
|
OMNIAUTH_EMAIL_REGEX = /\A#{OMNIAUTH_EMAIL_PREFIX}/
|
||||||
|
|
||||||
apply_simple_captcha
|
apply_simple_captcha
|
||||||
devise :database_authenticatable, :registerable, :confirmable,
|
devise :database_authenticatable, :registerable, :confirmable,
|
||||||
:recoverable, :rememberable, :trackable, :validatable
|
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
|
||||||
|
|
||||||
acts_as_voter
|
acts_as_voter
|
||||||
acts_as_paranoid column: :hidden_at
|
acts_as_paranoid column: :hidden_at
|
||||||
@@ -11,9 +15,11 @@ class User < ActiveRecord::Base
|
|||||||
has_one :moderator
|
has_one :moderator
|
||||||
has_one :organization
|
has_one :organization
|
||||||
has_many :inappropiate_flags
|
has_many :inappropiate_flags
|
||||||
|
has_many :identities, dependent: :destroy
|
||||||
|
|
||||||
validates :username, presence: true, unless: :organization?
|
validates :username, presence: true, unless: :organization?
|
||||||
validates :official_level, inclusion: {in: 0..5}
|
validates :official_level, inclusion: {in: 0..5}
|
||||||
|
validates_format_of :email, without: OMNIAUTH_EMAIL_REGEX, on: :update
|
||||||
|
|
||||||
validates_associated :organization, message: false
|
validates_associated :organization, message: false
|
||||||
|
|
||||||
@@ -25,6 +31,47 @@ class User < ActiveRecord::Base
|
|||||||
scope :organizations, -> { joins(:organization) }
|
scope :organizations, -> { joins(:organization) }
|
||||||
scope :officials, -> { where("official_level > 0") }
|
scope :officials, -> { where("official_level > 0") }
|
||||||
|
|
||||||
|
def self.find_for_oauth(auth, signed_in_resource = nil)
|
||||||
|
# Get the identity and user if they exist
|
||||||
|
identity = Identity.find_for_oauth(auth)
|
||||||
|
|
||||||
|
# If a signed_in_resource is provided it always overrides the existing user
|
||||||
|
# to prevent the identity being locked with accidentally created accounts.
|
||||||
|
# Note that this may leave zombie accounts (with no associated identity) which
|
||||||
|
# can be cleaned up at a later date.
|
||||||
|
user = signed_in_resource ? signed_in_resource : identity.user
|
||||||
|
|
||||||
|
# Create the user if needed
|
||||||
|
if user.nil?
|
||||||
|
|
||||||
|
# Get the existing user by email if the provider gives us a verified email.
|
||||||
|
# If no verified email was provided we assign a temporary email and ask the
|
||||||
|
# user to verify it on the next step via RegistrationsController.finish_signup
|
||||||
|
email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
|
||||||
|
email = auth.info.email if email_is_verified
|
||||||
|
user = User.where(email: email).first if email
|
||||||
|
|
||||||
|
# Create the user if it's a new registration
|
||||||
|
if user.nil?
|
||||||
|
user = User.new(
|
||||||
|
username: auth.info.nickname || auth.extra.raw_info.name.parameterize('-') || auth.uid,
|
||||||
|
email: email ? email : "#{OMNIAUTH_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
|
||||||
|
password: Devise.friendly_token[0,20]
|
||||||
|
)
|
||||||
|
user.skip_confirmation!
|
||||||
|
user.save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Associate the identity with the user if needed
|
||||||
|
if identity.user != user
|
||||||
|
identity.user = user
|
||||||
|
identity.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
user
|
||||||
|
end
|
||||||
|
|
||||||
def name
|
def name
|
||||||
organization? ? organization.name : username
|
organization? ? organization.name : username
|
||||||
end
|
end
|
||||||
@@ -67,4 +114,8 @@ class User < ActiveRecord::Base
|
|||||||
e.present? ? where(email: e) : none
|
e.present? ? where(email: e) : none
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def email_provided?
|
||||||
|
!!(email && email !~ OMNIAUTH_EMAIL_REGEX) ||
|
||||||
|
!!(unconfirmed_email && unconfirmed_email !~ OMNIAUTH_EMAIL_REGEX)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
5
app/views/devise/_omniauth_form.html.erb
Normal file
5
app/views/devise/_omniauth_form.html.erb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<br/>
|
||||||
|
|
||||||
|
<%= link_to t("omniauth.twitter.sign_in"), user_omniauth_authorize_path(:twitter), class: 'button radius expand' %>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
@@ -7,11 +7,11 @@
|
|||||||
<%= link_to(t("devise_views.menu.login_items.logout"), destroy_user_session_path, method: :delete) %>
|
<%= link_to(t("devise_views.menu.login_items.logout"), destroy_user_session_path, method: :delete) %>
|
||||||
</li>
|
</li>
|
||||||
<% else %>
|
<% else %>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to(t("devise_views.menu.login_items.login"), new_user_session_path) %>
|
<%= link_to(t("devise_views.menu.login_items.login"), new_user_session_path) %>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to(t("devise_views.menu.login_items.signup"), new_user_registration_path, class: "button radius small") %>
|
<%= link_to(t("devise_views.menu.login_items.signup"), new_user_registration_path, class: "button radius small") %>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -19,4 +19,4 @@
|
|||||||
<%= render "devise/shared/links" %>
|
<%= render "devise/shared/links" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<div class="panel">
|
<div class="panel">
|
||||||
<h2><%= t("devise_views.sessions.new.title") %></h2>
|
<h2><%= t("devise_views.sessions.new.title") %></h2>
|
||||||
|
|
||||||
|
<%= render 'devise/omniauth_form' %>
|
||||||
|
|
||||||
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
|
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="small-12 columns">
|
<div class="small-12 columns">
|
||||||
@@ -28,4 +30,4 @@
|
|||||||
<%= render "devise/shared/links" %>
|
<%= render "devise/shared/links" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
13
app/views/users/registrations/finish_signup.html.erb
Normal file
13
app/views/users/registrations/finish_signup.html.erb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<div class="auth row">
|
||||||
|
<div class="small-12 medium-8 large-5 column small-centered">
|
||||||
|
<div class="panel">
|
||||||
|
<h1><%= t('omniauth.finish_signup.title') %></h1>
|
||||||
|
|
||||||
|
<%= form_for current_user, as: :user, url: do_finish_signup_path, html: { role: 'form'} do |f| %>
|
||||||
|
<%= render 'shared/errors', resource: current_user %>
|
||||||
|
<%= f.email_field :email, placeholder: t("devise_views.users.registrations.new.email_label"), value: nil %>
|
||||||
|
<%= f.submit t("devise_views.users.registrations.new.submit"), class: 'button radius' %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -2,6 +2,9 @@
|
|||||||
<div class="small-12 medium-8 large-5 column small-centered">
|
<div class="small-12 medium-8 large-5 column small-centered">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<h2><%= t("devise_views.users.registrations.new.title") %></h2>
|
<h2><%= t("devise_views.users.registrations.new.title") %></h2>
|
||||||
|
|
||||||
|
<%= render 'devise/omniauth_form' %>
|
||||||
|
|
||||||
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
|
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
|
||||||
<%= render 'shared/errors', resource: resource %>
|
<%= render 'shared/errors', resource: resource %>
|
||||||
|
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ Devise.setup do |config|
|
|||||||
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
||||||
# up on your models and hooks.
|
# up on your models and hooks.
|
||||||
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
|
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
|
||||||
|
config.omniauth :twitter, Rails.application.secrets.twitter_key, Rails.application.secrets.twitter_secret
|
||||||
|
|
||||||
# ==> Warden configuration
|
# ==> Warden configuration
|
||||||
# If you want to use other strategies, that are not supported by Devise, or
|
# If you want to use other strategies, that are not supported by Devise, or
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
Rails.application.config.middleware.use OmniAuth::Builder do
|
|
||||||
provider :developer unless Rails.env.production?
|
|
||||||
provider :twitter, Rails.application.secrets.twitter_key, Rails.application.secrets.twitter_secret
|
|
||||||
end
|
|
||||||
@@ -55,4 +55,4 @@ es:
|
|||||||
not_locked: "no estaba bloqueado."
|
not_locked: "no estaba bloqueado."
|
||||||
not_saved:
|
not_saved:
|
||||||
one: "1 error impidió que este %{resource} fuera guardado:"
|
one: "1 error impidió que este %{resource} fuera guardado:"
|
||||||
other: "%{count} errores impidieron que este %{resource} fuera guardado:"
|
other: "%{count} errores impidieron que este %{resource} fuera guardado:"
|
||||||
|
|||||||
@@ -148,3 +148,9 @@ en:
|
|||||||
all: "You are not authorized to %{action} %{subject}."
|
all: "You are not authorized to %{action} %{subject}."
|
||||||
welcome:
|
welcome:
|
||||||
last_debates: Last debates
|
last_debates: Last debates
|
||||||
|
omniauth:
|
||||||
|
finish_signup:
|
||||||
|
title: Add Email
|
||||||
|
twitter:
|
||||||
|
sign_in: Sign in with Twitter
|
||||||
|
or: or
|
||||||
|
|||||||
@@ -148,3 +148,9 @@ es:
|
|||||||
all: "No tienes permiso para realizar la acción '%{action}' sobre %{subject}."
|
all: "No tienes permiso para realizar la acción '%{action}' sobre %{subject}."
|
||||||
welcome:
|
welcome:
|
||||||
last_debates: Últimos debates
|
last_debates: Últimos debates
|
||||||
|
omniauth:
|
||||||
|
finish_signup:
|
||||||
|
title: Añade tu email
|
||||||
|
twitter:
|
||||||
|
sign_in: Inicia sessión con Twitter
|
||||||
|
or: o
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
devise_for :users, controllers: { registrations: 'users/registrations' }
|
devise_for :users, controllers: {
|
||||||
|
registrations: 'users/registrations',
|
||||||
|
omniauth_callbacks: 'users/omniauth_callbacks'
|
||||||
|
}
|
||||||
devise_for :organizations, class_name: 'User',
|
devise_for :organizations, class_name: 'User',
|
||||||
controllers: {
|
controllers: {
|
||||||
registrations: 'organizations/registrations',
|
registrations: 'organizations/registrations',
|
||||||
sessions: 'devise/sessions'
|
sessions: 'devise/sessions',
|
||||||
}
|
},
|
||||||
|
skip: [:omniauth_callbacks]
|
||||||
|
|
||||||
|
devise_scope :user do
|
||||||
|
get :finish_signup, to: 'users/registrations#finish_signup'
|
||||||
|
patch :do_finish_signup, to: 'users/registrations#do_finish_signup'
|
||||||
|
end
|
||||||
|
|
||||||
# The priority is based upon order of creation: first created -> highest priority.
|
# The priority is based upon order of creation: first created -> highest priority.
|
||||||
# See how all your routes lay out with "rake routes".
|
# See how all your routes lay out with "rake routes".
|
||||||
|
|||||||
Reference in New Issue
Block a user