diff --git a/app/assets/javascripts/oauths.js.coffee b/app/assets/javascripts/oauths.js.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/oauths.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/oauths.css.scss b/app/assets/stylesheets/oauths.css.scss new file mode 100644 index 0000000..c879339 --- /dev/null +++ b/app/assets/stylesheets/oauths.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Oauths controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/oauths_controller.rb b/app/controllers/oauths_controller.rb new file mode 100644 index 0000000..bde25df --- /dev/null +++ b/app/controllers/oauths_controller.rb @@ -0,0 +1,32 @@ +class OauthsController < ApplicationController + skip_before_filter :require_login + + # sends the user on a trip to the provider, + # and after authorizing there back to the callback url. + def oauth + login_at(auth_params[:provider]) + end + + def callback + provider = auth_params[:provider] + if @user = login_from(provider) + redirect_to root_path, :notice => "Logged in with #{provider.titleize}!" + else + begin + @user = create_from(auth_params[:provider]) + + reset_session + auto_login(@user) + redirect_to root_path, :notice => "Signed up with #{provider.titleize}!" + rescue + redirect_to root_path, :alert => "Failed to login with #{provider.titleize}!" + end + end + end + + private + def auth_params + params.permit(:code, :provider) + end + +end \ No newline at end of file diff --git a/app/helpers/oauths_helper.rb b/app/helpers/oauths_helper.rb new file mode 100644 index 0000000..d6a2251 --- /dev/null +++ b/app/helpers/oauths_helper.rb @@ -0,0 +1,2 @@ +module OauthsHelper +end diff --git a/app/models/authentication.rb b/app/models/authentication.rb new file mode 100644 index 0000000..69a2df1 --- /dev/null +++ b/app/models/authentication.rb @@ -0,0 +1,3 @@ +class Authentication < ActiveRecord::Base + belongs_to :user +end diff --git a/app/models/user.rb b/app/models/user.rb index 9d312f0..ed8ff62 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,7 @@ class User < ActiveRecord::Base - authenticates_with_sorcery! + authenticates_with_sorcery! do |config| + config.authentications_class = Authentication + end validates :password, presence: true, confirmation: true, length: { minimum: 3 }, unless: ("id?" || "password_confirmation?") validates :password_confirmation, presence: true, unless: ("id?" || "password?") @@ -16,5 +18,7 @@ class User < ActiveRecord::Base has_many :user_organization_relationships has_many :organizations, through: :user_organization_relationships + has_many :authentications, :dependent => :destroy + accepts_nested_attributes_for :authentications end diff --git a/app/views/oauths/callback.html.haml b/app/views/oauths/callback.html.haml new file mode 100644 index 0000000..425fb4c --- /dev/null +++ b/app/views/oauths/callback.html.haml @@ -0,0 +1,2 @@ +%h1 Oauths#callback +%p Find me in app/views/oauths/callback.html.haml diff --git a/app/views/oauths/oauth.html.haml b/app/views/oauths/oauth.html.haml new file mode 100644 index 0000000..a694b6c --- /dev/null +++ b/app/views/oauths/oauth.html.haml @@ -0,0 +1,2 @@ +%h1 Oauths#oauth +%p Find me in app/views/oauths/oauth.html.haml diff --git a/app/views/user_sessions/new.html.haml b/app/views/user_sessions/new.html.haml index 820fd0a..35cd257 100644 --- a/app/views/user_sessions/new.html.haml +++ b/app/views/user_sessions/new.html.haml @@ -8,4 +8,6 @@ Create an Account %p #{_ 'user.why_register', 'paragraph'} + = link_to 'Login with Facebook', auth_at_provider_path(:provider => :facebook) = render '/users/form' + diff --git a/config/initializers/sorcery.rb b/config/initializers/sorcery.rb index d32bd20..750459f 100644 --- a/config/initializers/sorcery.rb +++ b/config/initializers/sorcery.rb @@ -71,7 +71,7 @@ Rails.application.config.sorcery.configure do |config| # What providers are supported by this app, i.e. [:twitter, :facebook, :github, :linkedin, :xing, :google, :liveid] . # Default: `[]` # - # config.external_providers = + config.external_providers = [:facebook] # You can change it by your local ca_file. i.e. '/etc/pki/tls/certs/ca-bundle.crt' @@ -109,13 +109,14 @@ Rails.application.config.sorcery.configure do |config| # config.twitter.secret = "" # config.twitter.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=twitter" # config.twitter.user_info_mapping = {:email => "screen_name"} - # - # config.facebook.key = "" - # config.facebook.secret = "" - # config.facebook.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=facebook" - # config.facebook.user_info_mapping = {:email => "name"} - # config.facebook.access_permissions = ["email", "publish_stream"] - # + + config.facebook.key = "726202304080642" + config.facebook.secret = "386a7b717d348af4120aeb1bb0ca3516" + config.facebook.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=facebook" + config.facebook.user_info_mapping = {:email => "email", :username => "username", :avatar => "picture/data/url"} + config.facebook.scope = "email" + config.facebook.display = "popup" + # config.github.key = "" # config.github.secret = "" # config.github.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=github" @@ -147,7 +148,7 @@ Rails.application.config.sorcery.configure do |config| # specify username attributes, for example: [:username, :email]. # Default: `[:username]` # - # user.username_attribute_names = + user.username_attribute_names = [:username, :email] # change *virtual* password attribute, the one which is used until an encrypted one is generated. @@ -214,7 +215,7 @@ Rails.application.config.sorcery.configure do |config| # make this configuration inheritable for subclasses. Useful for ActiveRecord's STI. # Default: `false` # - # user.subclasses_inherit_config = + user.subclasses_inherit_config = true # -- remember_me -- @@ -411,7 +412,7 @@ Rails.application.config.sorcery.configure do |config| # Class which holds the various external provider data for this user. # Default: `nil` # - # user.authentications_class = + user.authentications_class = Authentication # User's identifier in authentications class. diff --git a/config/routes.rb b/config/routes.rb index 2e373e4..5b9d4ea 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -56,6 +56,10 @@ BikeBike::Application.routes.draw do get 'login' => 'user_sessions#new', :as => :login post 'logout' => 'user_sessions#destroy', :as => :logout get 'register' => 'users#new', :as => 'register' + + post "oauth/callback" => "oauths#callback" + get "oauth/callback" => "oauths#callback" + get "oauth/:provider" => "oauths#oauth", :as => :auth_at_provider root 'pages#home' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9e2f87e..3c4e392 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -23,6 +23,8 @@ require 'capybara/rspec' #Capybara.ignore_hidden_elements = false # testing hidden fields +include Sorcery::TestHelpers::Rails + RSpec.configure do |config| # == Mock Framework # @@ -33,6 +35,7 @@ RSpec.configure do |config| # config.mock_with :rr # config.mock_with :rspec + config.include AuthenticationForFeatureRequest, type: :feature # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing diff --git a/spec/support/authentication.rb b/spec/support/authentication.rb new file mode 100644 index 0000000..deb7d9d --- /dev/null +++ b/spec/support/authentication.rb @@ -0,0 +1,8 @@ +module AuthenticationForFeatureRequest + def login user, password = 'login' + user.update_attribute :password, password + + page.driver.post sessions_url, {email: user.email, password: password} + visit root_url + end +end \ No newline at end of file diff --git a/test/controllers/oauths_controller_test.rb b/test/controllers/oauths_controller_test.rb new file mode 100644 index 0000000..884a527 --- /dev/null +++ b/test/controllers/oauths_controller_test.rb @@ -0,0 +1,14 @@ +require 'test_helper' + +class OauthsControllerTest < ActionController::TestCase + test "should get oauth" do + get :oauth + assert_response :success + end + + test "should get callback" do + get :callback + assert_response :success + end + +end diff --git a/test/factories/authentications.rb b/test/factories/authentications.rb new file mode 100644 index 0000000..38adeeb --- /dev/null +++ b/test/factories/authentications.rb @@ -0,0 +1,6 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :authentication do + end +end diff --git a/test/helpers/oauths_helper_test.rb b/test/helpers/oauths_helper_test.rb new file mode 100644 index 0000000..8783ff3 --- /dev/null +++ b/test/helpers/oauths_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class OauthsHelperTest < ActionView::TestCase +end diff --git a/test/models/authentication_test.rb b/test/models/authentication_test.rb new file mode 100644 index 0000000..f01e61d --- /dev/null +++ b/test/models/authentication_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class AuthenticationTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end