From c2e89f8781d1b1bd8fa1556078d0d98758756be4 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Tue, 26 Mar 2013 03:13:15 +0400 Subject: [PATCH] #30: use omniauth for registration through Facebook, GitHub, Google --- Gemfile | 11 ++- Gemfile.lock | 64 +++++++++------ .../users/omniauth_callbacks_controller.rb | 79 ++++++++++++++----- .../users/register_requests_controller.rb | 6 +- app/models/user.rb | 1 + app/views/devise/registrations/new.html.haml | 10 ++- config/application.yml.sample | 10 +++ config/initializers/devise.rb | 11 ++- config/initializers/omniauth.rb | 9 +++ lib/ext/preregistration.rb | 8 +- 10 files changed, 154 insertions(+), 55 deletions(-) create mode 100644 config/initializers/omniauth.rb diff --git a/Gemfile b/Gemfile index fb9224fac..4b7317e2b 100644 --- a/Gemfile +++ b/Gemfile @@ -5,10 +5,15 @@ gem 'redhillonrails_core', :git => 'git://github.com/warpc/redhillonrails_core.g gem 'pg', '~> 0.14.0' -gem 'devise', '~> 2.1.2' -gem 'omniauth', '~> 1.1.0' -gem 'omniauth-openid', '~> 1.0.1' +gem 'devise', '~> 2.2.3' +gem 'omniauth' +# gem 'oa-oauth', :require => 'omniauth/oauth' +gem 'omniauth-facebook' +gem 'omniauth-google-oauth2' +gem 'omniauth-github' +# gem 'omniauth-openid', '~> 1.0.1' gem 'cancan', '1.6.7' # 1.6.8 fail specs with strange error +# gem 'uuidtools' gem 'ancestry', '~> 1.3.0' gem 'paperclip', '~> 3.3.1' diff --git a/Gemfile.lock b/Gemfile.lock index c73f08a63..422b28923 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -52,7 +52,7 @@ GEM activesupport (3.2.13) i18n (= 0.6.1) multi_json (~> 1.0) - airbrake (3.1.8) + airbrake (3.1.9) activesupport builder json @@ -68,8 +68,8 @@ GEM daemons (~> 1.1.4) i18n (>= 0.5.0) state_machine (~> 1.1.0) - bourne (1.2.1) - mocha (= 0.12.7) + bourne (1.4.0) + mocha (~> 0.13.2) builder (3.0.4) cancan (1.6.7) cape (1.7.0) @@ -80,7 +80,7 @@ GEM net-ssh (>= 2.0.14) net-ssh-gateway (>= 1.1.0) capistrano_colors (0.5.5) - charlock_holmes (0.6.9.1) + charlock_holmes (0.6.9.2) chronic (0.6.7) chunky_png (1.2.7) cocaine (0.4.2) @@ -90,7 +90,7 @@ GEM coffee-script (2.2.0) coffee-script-source execjs - coffee-script-source (1.6.1) + coffee-script-source (1.6.2) compass (0.12.2) chunky_png (~> 1.2) fssm (>= 0.2.7) @@ -99,7 +99,7 @@ GEM compass (>= 0.12.2, < 0.14) creole (0.5.0) daemons (1.1.9) - devise (2.1.3) + devise (2.2.3) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.1) railties (~> 3.1) @@ -119,6 +119,8 @@ GEM factory_girl_rails (4.0.0) factory_girl (~> 4.0.0) railties (>= 3.0.0) + faraday (0.8.7) + multipart-post (~> 1.1) ffi (1.0.11) fssm (0.2.10) github-linguist (2.2.1) @@ -147,9 +149,10 @@ GEM haml (~> 3.1) railties (>= 3.1, < 4.1) hashie (1.2.0) - highline (1.6.16) + highline (1.6.15) hike (1.2.1) hirb (0.7.1) + httpauth (0.2.0) i18n (0.6.1) jbuilder (0.8.3) activesupport (>= 3.0.0) @@ -158,6 +161,8 @@ GEM railties (>= 3.1.0, < 5.0) thor (~> 0.14) json (1.7.7) + jwt (0.1.8) + multi_json (>= 1.5) kgio (2.8.0) libv8 (3.3.10.4) macaddr (1.6.1) @@ -179,10 +184,11 @@ GEM actionpack metaclass (0.0.1) mime-types (1.21) - mocha (0.12.7) + mocha (0.13.3) metaclass (~> 0.0.1) mock_redis (0.6.2) - multi_json (1.7.1) + multi_json (1.7.2) + multipart-post (1.2.0) mustache (0.99.4) net-scp (1.1.0) net-ssh (>= 2.6.5) @@ -192,13 +198,27 @@ GEM net-ssh-gateway (1.2.0) net-ssh (>= 2.6.5) newrelic_rpm (3.5.5.38) - nokogiri (1.5.7) + nokogiri (1.5.9) + oauth2 (0.8.1) + faraday (~> 0.8) + httpauth (~> 0.1) + jwt (~> 0.1.4) + multi_json (~> 1.0) + rack (~> 1.2) omniauth (1.1.3) hashie (~> 1.2) rack - omniauth-openid (1.0.1) + omniauth-facebook (1.4.1) + omniauth-oauth2 (~> 1.1.0) + omniauth-github (1.1.0) + omniauth (~> 1.0) + omniauth-oauth2 (~> 1.1) + omniauth-google-oauth2 (0.1.13) + omniauth (~> 1.0) + omniauth-oauth2 + omniauth-oauth2 (1.1.1) + oauth2 (~> 0.8.0) omniauth (~> 1.0) - rack-openid (~> 1.3.1) orm_adapter (0.4.0) paperclip (3.3.1) activemodel (>= 3.0.0) @@ -218,9 +238,6 @@ GEM rack (1.4.5) rack-cache (1.2) rack (>= 0.4) - rack-openid (1.3.1) - rack (>= 1.1.0) - ruby-openid (>= 2.1.8) rack-protection (1.5.0) rack rack-ssl (1.3.3) @@ -253,7 +270,7 @@ GEM rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) raindrops (0.10.0) - rake (10.0.3) + rake (10.0.4) rdiscount (2.0.7.1) rdoc (3.12.2) json (~> 1.4) @@ -294,7 +311,6 @@ GEM ruby-haml-js (0.0.3) execjs sprockets (>= 2.0.0) - ruby-openid (2.2.3) rubypython (0.5.3) blankslate (>= 2.1.2.3) ffi (~> 1.0.7) @@ -315,9 +331,9 @@ GEM shoulda-context (~> 1.0, >= 1.0.1) shoulda-matchers (~> 1.0, >= 1.4.1) shoulda-context (1.0.2) - shoulda-matchers (1.5.0) + shoulda-matchers (1.5.4) activesupport (>= 3.0.0) - bourne (~> 1.2.0) + bourne (~> 1.3) sinatra (1.3.6) rack (~> 1.4) rack-protection (~> 1.3) @@ -341,7 +357,7 @@ GEM eventmachine (>= 0.12.6) rack (>= 1.0.0) thor (0.17.0) - tilt (1.3.5) + tilt (1.3.6) treetop (1.4.12) polyglot polyglot (>= 0.3.1) @@ -388,7 +404,7 @@ DEPENDENCIES coffee-rails (~> 3.2.2) compass-rails (~> 1.0.3) creole - devise (~> 2.1.2) + devise (~> 2.2.3) diff-display (~> 0.0.1) factory_girl_rails (~> 4.0.0) github-linguist (~> 2.2.1) @@ -404,8 +420,10 @@ DEPENDENCIES meta-tags (~> 1.2.5) mock_redis (= 0.6.2) newrelic_rpm (~> 3.5.5.38) - omniauth (~> 1.1.0) - omniauth-openid (~> 1.0.1) + omniauth + omniauth-facebook + omniauth-github + omniauth-google-oauth2 paperclip (~> 3.3.1) perform_later (~> 1.3.0) pg (~> 0.14.0) diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index a23a8c7e1..35277c82d 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -1,30 +1,69 @@ # -*- encoding : utf-8 -*- class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController - def open_id - # raise env['omniauth.auth'].inspect - generic + require 'uuidtools' + + # def facebook + # generic + # end + + def facebook + oauthorize 'Facebook' + end + + def google_oauth2 + oauthorize 'google_oauth2' + end + + def github + oauthorize 'GitHub' end def passthru render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false end + + private - protected - - def generic - authentication = Authentication.find_or_initialize_by_provider_and_uid(env['omniauth.auth']['provider'], env['omniauth.auth']['uid']) - if authentication.new_record? - if user_signed_in? # New authentication method for current_user - authentication.user = current_user - authentication.save - else # Register new user from session - session["devise.omniauth_data"] = env["omniauth.auth"].except('extra') - flash[:notice] = I18n.t "devise.omniauth_callbacks.register" - redirect_to new_user_registration_url - end - else + def oauthorize(kind) + provider = kind.downcase + @user = find_for_ouath(env["omniauth.auth"], current_user) + if @user.persisted? flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => action_name.classify - sign_in_and_redirect authentication.user, :event => :authentication - end + sign_in_and_redirect @user, :event => :authentication + else + session["devise.#{provider}_data"] = env["omniauth.auth"] + redirect_to new_user_registration_url + end end -end + + def find_for_ouath(auth, resource=nil) + provider, uid = auth['provider'], auth['uid'] + authentication = Authentication.find_or_initialize_by_provider_and_uid(provider, uid) + if authentication.new_record? + unless user_signed_in? # Register new user from session + case provider + when 'facebook' + name = auth['extra']['raw_info']['name'] + email = auth['info']['email'] + when 'google_oauth2' + name = auth['info']['nickname'] + email = auth['info']['email'] + when 'github' + + else + raise 'Provider #{provider} not handled' + end + user = User.create( + :uname => "#{provider}-#{uid}", + :name => name, + :email => email, + :password => Devise.friendly_token[0,20] + ) + end + authentication.user = current_user + authentication.save + end + return user + end + +end \ No newline at end of file diff --git a/app/controllers/users/register_requests_controller.rb b/app/controllers/users/register_requests_controller.rb index a21249cdb..e541f7476 100644 --- a/app/controllers/users/register_requests_controller.rb +++ b/app/controllers/users/register_requests_controller.rb @@ -4,7 +4,11 @@ class Users::RegisterRequestsController < ApplicationController layout 'invite' def new - render :invite + if APP_CONFIG['preregistration'] + render :invite + else + redirect_to new_user_registration_path + end end def create diff --git a/app/models/user.rb b/app/models/user.rb index 953665770..fce41e6b6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -7,6 +7,7 @@ class User < Avatar devise :database_authenticatable, :registerable, :omniauthable, :token_authenticatable,# :encryptable, :timeoutable :recoverable, :rememberable, :validatable, :lockable, :confirmable#, :reconfirmable, :trackable + devise :omniauthable, :omniauth_providers => [:facebook, :google_oauth2, :github] has_one :notifier, :class_name => 'SettingsNotifier', :dependent => :destroy #:notifier diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index 5fb9371d6..4d1c06b22 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -17,7 +17,10 @@ .both .left=t('activerecord.attributes.user.email') .right - = f.text_field :email, :id => 'email', :readonly => 'readonly', :class => "registartion-input #{email_error ? 'registartion-input-error' : ''}" + - if APP_CONFIG['preregistration'] + = f.text_field :email, :id => 'email', :readonly => 'readonly', :class => "registartion-input #{email_error ? 'registartion-input-error' : ''}" + - else + = f.text_field :email, :id => 'email', :class => 'registartion-input' .both .left=t('activerecord.attributes.user.password') .right @@ -31,6 +34,11 @@ =f.submit t("layout.devise.shared_links.sign_up"), :class => 'button', :id => 'btnLogin' .both + - if devise_mapping.omniauthable? + - resource_class.omniauth_providers.each do |provider| + = link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) + %br + =showDeviseHintError(:login, uname_error) =showDeviseHintError(:name, name_error) =showDeviseHintError(:email, email_error) diff --git a/config/application.yml.sample b/config/application.yml.sample index 07a3e369a..abf353069 100644 --- a/config/application.yml.sample +++ b/config/application.yml.sample @@ -2,6 +2,7 @@ common: &common project_name: ABF repo_project_name: ABF anonymous_access: true + preregistration: false file_store_url: 'http://file-store.rosalinux.ru' distr_types: ['mdv', 'rhel', 'nau5'] abf_worker: @@ -11,6 +12,15 @@ common: &common airbrake_api_key: 'airbrake_api_key' devise_pepper: 'devise_pepper' secret_token: 'secret_token' + github: + id: 'APP_ID' + secret: 'APP_SECRET' + google: + id: 'APP_ID' + secret: 'APP_SECRET' + facebook: + id: 'APP_ID' + secret: 'APP_SECRET' wiki_formats: markdown: "Markdown" diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 6f9f45858..be74b0c29 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -182,14 +182,19 @@ Devise.setup do |config| # config.navigational_formats = [:"*/*", "*/*", :html] # The default HTTP method used to sign out a resource. Default is :delete. - config.sign_out_via = :delete + config.sign_out_via = :get # ==> OmniAuth # Add a new OmniAuth provider. Check the wiki for more information on setting # up on your models and hooks. # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo' - require 'openid/store/filesystem' - config.omniauth :openid, :name => 'open_id' #, :store => OpenID::Store::Filesystem.new('./tmp') + + # require 'openid/store/filesystem' + # config.omniauth :openid, :name => 'open_id' #, :store => OpenID::Store::Filesystem.new('./tmp') + + config.omniauth :facebook, APP_CONFIG['keys']['facebook']['id'], APP_CONFIG['keys']['facebook']['secret'] + config.omniauth :google_oauth2, APP_CONFIG['keys']['google']['id'], APP_CONFIG['keys']['google']['secret'], {:access_type => 'offline', :approval_prompt => ''} + config.omniauth :github, APP_CONFIG['keys']['github']['id'], APP_CONFIG['keys']['github']['secret'] # ==> Warden configuration # If you want to use other strategies, that are not supported by Devise, or diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 000000000..ac5e72a76 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,9 @@ +# require "omniauth-facebook" + +# Rails.application.config.middleware.use OmniAuth::Builder do +# [:facebook, :github, :google_oauth2].each do |kind| +# provider kind, APP_CONFIG['keys']["#{kind}"]['id'], APP_CONFIG['keys']["#{kind}"]['secret'] +# end +# end + +OmniAuth.config.logger = Rails.logger \ No newline at end of file diff --git a/lib/ext/preregistration.rb b/lib/ext/preregistration.rb index 5b07c5d88..77b5ee919 100644 --- a/lib/ext/preregistration.rb +++ b/lib/ext/preregistration.rb @@ -51,10 +51,10 @@ module Preregistration end end - end #RegistrationsController - end #Devise -end #Preregistration + end # RegistrationsController + end # Devise +end # Preregistration Rails.application.config.to_prepare do - ::Devise::RegistrationsController.send :include, Preregistration::Devise::RegistrationsController + ::Devise::RegistrationsController.send :include, Preregistration::Devise::RegistrationsController if APP_CONFIG['preregistration'] end