From 7cc27f4e134c93f3172d53f68f1980e0e40de510 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Mon, 26 Sep 2016 01:40:53 +0300 Subject: [PATCH] [#9] Added login via GitHub --- Gemfile | 1 + Gemfile.lock | 21 +++++++- .../users/omniauth_callbacks_controller.rb | 53 +++++++++++++++++++ app/models/user.rb | 3 +- app/views/devise/sessions/new.html.slim | 2 + app/views/devise/shared/_providers.slim | 9 ++++ config/initializers/devise.rb | 1 + config/locales/devise.en.yml | 3 ++ config/locales/devise.ru.yml | 3 ++ config/routes.rb | 10 ++-- 10 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 app/controllers/users/omniauth_callbacks_controller.rb create mode 100644 app/views/devise/shared/_providers.slim diff --git a/Gemfile b/Gemfile index acc698b4c..312551d6c 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,7 @@ gem 'pg' gem 'schema_plus' ######## gem 'devise' +gem 'omniauth-github' gem 'pundit' gem 'rbtrace' diff --git a/Gemfile.lock b/Gemfile.lock index e3ba5cac0..9e1c9d730 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -169,6 +169,7 @@ GEM actionpack (>= 3.2, < 5) activesupport (>= 3.2, < 5) hashdiff (0.3.0) + hashie (3.4.2) hirb (0.7.3) html2haml (2.0.0) erubis (~> 2.7.0) @@ -197,6 +198,7 @@ GEM railties (>= 3.2) sprockets-rails json (1.8.3) + jwt (1.5.0) kaminari (0.17.0) actionpack (>= 3.0.0) activesupport (>= 3.0.0) @@ -238,6 +240,7 @@ GEM key_struct (~> 0.4) msgpack (0.7.6) multi_json (1.12.1) + multi_xml (0.5.5) multipart-post (2.0.0) nest (1.1.2) redis @@ -248,6 +251,12 @@ GEM rails (>= 3.1) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) + oauth2 (1.0.0) + faraday (>= 0.8, < 0.10) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (~> 1.2) octokit (4.3.0) sawyer (~> 0.7.0, >= 0.5.3) ohm (1.3.2) @@ -256,6 +265,15 @@ GEM scrivener (~> 0.0.3) ohm-expire (0.1.3.2) ohm (>= 0.1.5) + omniauth (1.2.2) + hashie (>= 1.2, < 4) + rack (~> 1.0) + omniauth-github (1.1.2) + omniauth (~> 1.0) + omniauth-oauth2 (~> 1.1) + omniauth-oauth2 (1.3.0) + oauth2 (~> 1.0) + omniauth (~> 1.2) orm_adapter (0.5.0) paperclip (4.3.6) activemodel (>= 3.2.0) @@ -567,6 +585,7 @@ DEPENDENCIES octokit (~> 4.0) ohm (~> 1.3.2) ohm-expire (~> 0.1.3) + omniauth-github paperclip pg puma @@ -612,4 +631,4 @@ DEPENDENCIES will_paginate BUNDLED WITH - 1.11.2 + 1.13.1 diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb new file mode 100644 index 000000000..bdd55a71a --- /dev/null +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -0,0 +1,53 @@ +class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController + + def github + oauthorize 'GitHub' + end + + def passthru + render file: "#{Rails.root}/public/404.html", status: 404, layout: false + end + + private + + def oauthorize(kind) + provider = kind.downcase + @user = find_for_ouath(env["omniauth.auth"], current_user) + if @user && @user.persisted? + flash[:notice] = I18n.t "devise.omniauth_callbacks.success", kind: action_name.classify + sign_in_and_redirect @user, event: :authentication + else + session["devise.#{provider}_data"] = env["omniauth.auth"] + redirect_to new_user_registration_url + end + end + + def find_for_ouath(auth, resource=nil) + provider, uid = auth['provider'], auth['uid'] + authentication = Authentication.find_or_initialize_by(provider: provider, uid: uid) + if authentication.new_record? + if user_signed_in? # New authentication method for current_user + authentication.user = current_user + else # Register new user from session + case provider + when 'github' + name = auth['info']['nickname'] || auth['info']['name'] + else + raise ActiveRecord::RecordNotFound + end + user = User.find_or_initialize_by email: auth['info']['email'] + if user.new_record? + user.name = name + user.uname = name.gsub(/\s/, '').underscore + user.password = Devise.friendly_token[0,20] + user.confirmed_at = Time.zone.now + user.save + end + authentication.user = user + end + authentication.save + end + return authentication.user + end + +end diff --git a/app/models/user.rb b/app/models/user.rb index 9994e3e52..4dbc62d32 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -13,8 +13,9 @@ class User < Avatar LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last) NAME_REGEXP = /[a-z0-9_]+/ - devise :database_authenticatable, :registerable, :recoverable, + devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :lockable, :confirmable + devise :omniauthable, omniauth_providers: %i(github) has_one :notifier, class_name: 'SettingsNotifier', dependent: :destroy #:notifier has_one :builds_setting, class_name: 'UserBuildsSetting', dependent: :destroy diff --git a/app/views/devise/sessions/new.html.slim b/app/views/devise/sessions/new.html.slim index 41d884cda..818df312c 100644 --- a/app/views/devise/sessions/new.html.slim +++ b/app/views/devise/sessions/new.html.slim @@ -17,3 +17,5 @@ = f.button :submit, t('layout.devise.shared_links.sign_in') .row = link_to t('layout.devise.shared_links.forgot_password'), new_password_path(resource_name) + rd-widget-footer + == render 'devise/shared/providers' diff --git a/app/views/devise/shared/_providers.slim b/app/views/devise/shared/_providers.slim new file mode 100644 index 000000000..4126a9c32 --- /dev/null +++ b/app/views/devise/shared/_providers.slim @@ -0,0 +1,9 @@ +- if devise_mapping.omniauthable? + .row + .col-md-12 + .pull-left + = t('.sign_up_with') + .pull-right + - resource_class.omniauth_providers.each do |provider| + a.text-muted> href=omniauth_authorize_path(resource_name, provider) + i.fa.fa-2x class="fa-#{provider}-square" diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 1e40a8e09..484a78f75 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -184,6 +184,7 @@ Devise.setup do |config| # 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' + config.omniauth :github, APP_CONFIG['keys']['github']['id'], APP_CONFIG['keys']['github']['secret'], scope: 'user:email' # require 'openid/store/filesystem' # config.omniauth :openid, :name => 'open_id' #, :store => OpenID::Store::Filesystem.new('./tmp') diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index 8632ac80b..b9bf13689 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -10,6 +10,9 @@ en: other: "%{count} errors prevented %{resource} from being saved:" devise: + shared: + providers: + sign_up_with: 'or sign in with' failure: already_authenticated: 'You are already signed in.' unauthenticated: 'You need to sign in or sign up before continuing.' diff --git a/config/locales/devise.ru.yml b/config/locales/devise.ru.yml index bee394cfe..072cbf156 100644 --- a/config/locales/devise.ru.yml +++ b/config/locales/devise.ru.yml @@ -12,6 +12,9 @@ ru: other: "%{resource}: сохранение не удалось из-за %{count} ошибки" devise: + shared: + providers: + sign_up_with: 'или войти с помощью' failure: already_authenticated: 'Вы уже вошли в систему.' unauthenticated: "Вам необходимо войти в систему или зарегистрироваться." diff --git a/config/routes.rb b/config/routes.rb index ffc6160e1..523d48137 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -21,11 +21,13 @@ Rails.application.routes.draw do end devise_scope :user do - get 'users/sign_up' => 'users/registrations#new', as: :new_user_registration - post 'users' => 'users/registrations#create', as: :user_registration + get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru' + get 'users/sign_up' => 'users/registrations#new', as: :new_user_registration + post 'users' => 'users/registrations#create', as: :user_registration end devise_for :users, controllers: { + omniauth_callbacks: 'users/omniauth_callbacks', confirmations: 'users/confirmations' }, skip: [:registrations] @@ -193,8 +195,8 @@ Rails.application.routes.draw do put :cancel } end - collection { - get :autocomplete_project + collection { + get :autocomplete_project get :project_versions } end