Merge pull request #253 from differentreality/final_openid

Authenticate via openid
This commit is contained in:
Stella Rouzi 2014-06-19 15:53:56 +03:00
commit 0c698bac10
24 changed files with 412 additions and 15 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

View file

@ -1,6 +1,10 @@
class RegistrationsController < Devise::RegistrationsController
before_action :configure_permitted_parameters, if: :devise_controller?
def edit
@openids = Openid.where(user_id: current_user.id).order(:provider)
end
def update
@user = User.find(current_user.id)
email_changed = false

View file

@ -0,0 +1,34 @@
module Users
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
skip_before_filter :verify_authenticity_token
[:novell, :google, :facebook, :twitter].each do |provider|
define_method(provider) { handle(provider) }
end
private
def handle(provider)
auth_hash = request.env['omniauth.auth']
openid = Openid.find_for_oauth(auth_hash) # Get or create openid
# If openid exists and is associated with a user, sign in with associated user,
# even if the email of the associated user and the email of the provided openid are different
unless user = openid.user
user = User.find_for_auth(auth_hash, current_user) # Get or create users
end
begin
user.save!
if openid.user != user
openid.user = user
end
openid.save!
sign_in user
redirect_to root_path, notice: user.email + " signed in successfully with #{provider}"
rescue Exception => e
redirect_back_or_to new_user_registration_path, alert: 'Failed' + e.message
end
end
end
end

View file

@ -37,4 +37,4 @@ class DatatableSupporters < Datatable
def columns
["name", "email", "name", "name", "name"]
end
end
end

20
app/models/openid.rb Normal file
View file

@ -0,0 +1,20 @@
class Openid < ActiveRecord::Base
belongs_to :user
validates :provider, :uid, presence: true
# Searches for openid based on provider and uid.
# Returns found openid or a new openid.
# ====Returns
# * Openid::ActiveRecord_Relation -> openid
def self.find_for_oauth(auth)
openid = Openid.where(provider: auth.provider, uid: auth.uid).first_or_initialize
if openid.new_record?
openid.email = auth.info.email
if existing_openid = Openid.where(email: openid.email).first
openid.user_id = existing_openid.user_id
end
end
openid
end
end

View file

@ -4,13 +4,15 @@ class User < ActiveRecord::Base
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable
:recoverable, :rememberable, :trackable, :validatable, :confirmable,
:omniauthable, omniauth_providers: [:novell, :google, :facebook]
has_and_belongs_to_many :roles
has_one :person, :inverse_of => :user
has_many :openids
attr_accessible :email, :password, :password_confirmation, :remember_me, :role_id, :role_ids, :person_attributes
attr_accessible :email, :password, :password_confirmation, :remember_me, :role_id, :role_ids,
:person_attributes
accepts_nested_attributes_for :person
accepts_nested_attributes_for :roles
@ -19,6 +21,25 @@ class User < ActiveRecord::Base
delegate :last_name, :first_name, :public_name, to: :person
# Searches for user based on email. Returns found user or new user.
# ====Returns
# * +User::ActiveRecord_Relation+ -> user
def self.find_for_auth(auth, current_user = nil)
user = current_user
if user.nil? # No current user available, user is not already logged in
user = User.where(email: auth.info.email).first_or_initialize
end
if user.new_record?
user.email = auth.info.email
user.password = Devise.friendly_token[0, 20]
user.skip_confirmation!
end
user
end
def role?(role)
Rails.logger.debug("Checking role in user")
!!roles.find_by_name(role.to_s.downcase.camelize)

View file

@ -15,6 +15,18 @@
%br
%br
= render :partial => 'devise/registrations/volunteerperson', :locals => {:p => p}
= f.inputs :name => 'OpenID' do
%h4
Currently using the following openIDs:
- @openids.each do |openid|
= openid.provider
= openid.email
%br
%h4
To add an openID to your account using a different email address, sign in with your
openID while logged in to OSEM
= render 'devise/shared/openid'
= f.inputs :name => "Account" do
= f.input :email, :required => false
= f.input :password, :hint => "(Leave blank if you don't want to change it)", :input_html => {:autocomplete => "off"}

View file

@ -3,13 +3,17 @@
%h1.text-center Sign Up
.col-md-5.col-md-offset-1
.well
= semantic_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f|
= semantic_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
= f.input :email
= f.input :password
= f.input :password_confirmation
= f.action :submit, :as => :button, :label => "Sign Up", :button_html => {:class => "btn btn-primary"}
.col-md-3.col-md-offset-2
= f.action :submit, as: :button, label: 'Sign Up', button_html: {class: 'btn btn-primary'}
%br
%br
%h4 Already have an account?
= render 'devise/shared/links'
.col-md-4
.well
%h4
Already have an account?
= render "devise/shared/links"
%h4 Or use your openID
= render 'devise/shared/openid'

View file

@ -0,0 +1,21 @@
.row
.page-header
%h2.text-center Sign In
.col-md-5.col-md-offset-1
.well
= semantic_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
= f.input :email
= f.input :password
- if devise_mapping.rememberable?
= f.check_box :remember_me
= f.label 'Remember me'
%br
= f.action :submit, as: :button, label: 'Sign In', button_html: {class: 'btn btn-primary'}
%br
%br
= render "devise/shared/links"
.col-md-4
.well
%h4 Or use your openID
= render 'devise/shared/openid'

View file

@ -0,0 +1,19 @@
- if controller_name != 'sessions'
= link_to "Sign in", new_user_session_path
%br
- if devise_mapping.registerable? && controller_name != 'registrations'
= link_to "Sign up", new_registration_path(resource_name)
%br
- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
= link_to "Forgot your password?", new_password_path(resource_name)
%br
- if devise_mapping.confirmable? && controller_name != 'confirmations'
= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name)
%br
- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name)
%br

View file

@ -0,0 +1,4 @@
- if devise_mapping.omniauthable?
- resource_class.omniauth_providers.each do |provider|
= link_to image_tag("#{provider}.png", size: '32x32') + provider , omniauth_authorize_path(resource_name, provider)
%br

View file

@ -51,5 +51,6 @@
%button.btn.btn-block Sign in
%br
= link_to "Forgot your password?", new_password_path('user')
= link_to 'Sign in with openID', new_user_session_path
%li.hidden-lg
= link_to('Sign In', new_user_session_path)