socialite 0.1.0.pre → 0.1.0.pre.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/app/assets/images/socialite/facebook_64.png +0 -0
  2. data/app/assets/images/socialite/twitter_64.png +0 -0
  3. data/app/controllers/socialite/sessions_controller.rb +69 -0
  4. data/app/controllers/socialite/users_controller.rb +2 -31
  5. data/app/views/layouts/socialite/application.html.haml +1 -1
  6. data/app/views/socialite/identities/new.html.haml +6 -19
  7. data/app/views/socialite/sessions/new.html.haml +30 -0
  8. data/app/views/socialite/users/new.html.haml +10 -0
  9. data/config/routes.rb +6 -7
  10. data/lib/generators/socialite/install_generator.rb +24 -5
  11. data/lib/generators/socialite/migrations_generator.rb +1 -1
  12. data/lib/generators/socialite/templates/socialite.rb +9 -0
  13. data/lib/generators/socialite/templates/users.rb.erb +5 -1
  14. data/lib/generators/socialite/views_generator.rb +22 -0
  15. data/lib/socialite.rb +4 -8
  16. data/lib/socialite/controllers/helpers.rb +5 -115
  17. data/lib/socialite/engine.rb +8 -11
  18. data/lib/socialite/ext/omniauth/identity/model.rb +29 -0
  19. data/lib/socialite/models/identity_concern.rb +24 -5
  20. data/lib/socialite/models/user_concern.rb +39 -0
  21. data/lib/socialite/version.rb +1 -1
  22. data/spec/dummy/app/controllers/pages_controller.rb +7 -0
  23. data/spec/dummy/app/models/user.rb +2 -0
  24. data/spec/dummy/app/views/pages/index.html.haml +5 -0
  25. data/spec/dummy/config/initializers/omniauth-identity.rb +11 -0
  26. data/spec/dummy/config/initializers/socialite.rb +9 -0
  27. data/spec/dummy/config/routes.rb +17 -1
  28. data/spec/dummy/db/migrate/20130207223009_create_socialite_users.rb +16 -0
  29. data/spec/dummy/db/migrate/{20130206224517_create_socialite_identities.rb → 20130207223010_create_socialite_identities.rb} +0 -0
  30. data/spec/dummy/db/schema.rb +7 -3
  31. data/spec/factories/user.rb +11 -1
  32. data/{features/registration/twitter_signup.feature → spec/features/.gitkeep} +0 -0
  33. data/spec/features/facebook_registration_spec.rb +16 -0
  34. data/spec/features/identity_login_spec.rb +26 -0
  35. data/spec/features/identity_registration_spec.rb +31 -0
  36. data/spec/generators/socialite/install_generator_spec.rb +8 -1
  37. data/spec/generators/socialite/views_generator_spec.rb +27 -0
  38. data/spec/models/identity_spec.rb +4 -6
  39. data/spec/models/user_spec.rb +18 -18
  40. data/spec/socialite_spec.rb +31 -7
  41. data/spec/spec_helper.rb +4 -1
  42. data/spec/support/capybara.rb +3 -0
  43. data/spec/support/database_cleaner.rb +18 -0
  44. data/spec/support/identity_shared_example.rb +4 -23
  45. data/spec/support/omniauth.rb +35 -0
  46. metadata +95 -78
  47. data/app/controllers/socialite/identities_controller.rb +0 -41
  48. data/app/controllers/socialite/session_controller.rb +0 -32
  49. data/app/views/socialite/session/new.html.haml +0 -31
  50. data/app/views/socialite/user/_form.html.haml +0 -13
  51. data/app/views/socialite/user/edit.html.haml +0 -1
  52. data/app/views/socialite/user/show.html.haml +0 -16
  53. data/features/authentication/facebook_signin.feature +0 -5
  54. data/features/authentication/twitter_signin.feature +0 -5
  55. data/features/identities/facebook_management.feature +0 -14
  56. data/features/identities/twitter_management.feature +0 -7
  57. data/features/registration/facebook_signup.feature +0 -10
  58. data/features/step_definitions/authentication_steps.rb +0 -31
  59. data/features/step_definitions/common_steps.rb +0 -13
  60. data/features/step_definitions/identity_steps.rb +0 -5
  61. data/features/step_definitions/web_steps.rb +0 -254
  62. data/features/support/env.rb +0 -58
  63. data/features/support/hooks.rb +0 -3
  64. data/features/support/omniauth.rb +0 -31
  65. data/features/support/paths.rb +0 -34
  66. data/features/support/selectors.rb +0 -39
  67. data/lib/socialite/helpers/authentication.rb +0 -17
  68. data/lib/socialite/models/facebook_identity.rb +0 -14
  69. data/spec/dummy/db/migrate/20130206224516_create_socialite_users.rb +0 -12
  70. data/spec/factories/facebook.rb +0 -5
  71. data/spec/factories/twitter.rb +0 -6
  72. data/spec/models/facebook_spec.rb +0 -31
@@ -1,5 +1,6 @@
1
1
  require 'haml'
2
2
  require 'omniauth'
3
+ require 'simple_form'
3
4
 
4
5
  module Socialite
5
6
  class Engine < ::Rails::Engine
@@ -13,20 +14,16 @@ module Socialite
13
14
  g.helper false
14
15
  end
15
16
 
16
- initializer 'socialite.load_middleware', :after => :load_config_initializers do
17
- Socialite.providers.each do |provider_info|
18
- OmniAuth.configure do |config|
19
- config.provider(*provider_info)
17
+ initializer 'socialite.load_middleware' do |app|
18
+ app.middleware.use OmniAuth::Builder do
19
+ Socialite.providers.each do |provider_info|
20
+ provider(provider_info.first, *provider_info.last)
20
21
  end
21
22
  end
22
23
  end
23
24
 
24
- # ActiveSupport.on_load(:action_controller) do
25
- # include Socialite::Controllers::Helpers
26
- # end
27
-
28
- # ActiveSupport.on_load(:action_view) do
29
- # include Socialite::Helpers::Authentication
30
- # end
25
+ ActiveSupport.on_load(:action_controller) do
26
+ include Socialite::Controllers::Helpers
27
+ end
31
28
  end
32
29
  end
@@ -0,0 +1,29 @@
1
+ if defined?(OmniAuth::Identity)
2
+ require 'omniauth/identity/model'
3
+ require 'omniauth/identity/secure_password'
4
+
5
+ module OmniAuth
6
+ module Identity
7
+ module Model
8
+ extend ActiveSupport::Concern
9
+ # class << self
10
+ # # alias_method :old_included, :included
11
+ # extend ActiveSupport::Concern
12
+ # end
13
+ end
14
+ end
15
+ end
16
+
17
+ module OmniAuth
18
+ module Identity
19
+ module SecurePassword
20
+ extend ActiveSupport::Concern
21
+ # class << self
22
+ # # alias_method :old_included, :included
23
+ # extend ActiveSupport::Concern
24
+ # end
25
+ end
26
+ end
27
+ end
28
+
29
+ end
@@ -4,6 +4,8 @@ module Socialite
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
+ attr_accessible :provider, :uid, :user_id, :auth_hash
8
+
7
9
  belongs_to :user,
8
10
  :class_name => Socialite.user_class_name,
9
11
  :foreign_key => "#{Socialite.user_class.table_name.singularize}_id"
@@ -21,7 +23,10 @@ module Socialite
21
23
 
22
24
  # Ensure each user has only a single identity per provider type
23
25
  validates :provider,
24
- :uniqueness => {:scope => "#{Socialite.user_class.table_name.singularize}_id", :case_sensitive => false},
26
+ :uniqueness => {
27
+ :scope => "#{Socialite.user_class.table_name.singularize}_id",
28
+ :case_sensitive => false
29
+ },
25
30
  :presence => true
26
31
 
27
32
  # Ensure an identity is never reused by another account
@@ -39,10 +44,24 @@ module Socialite
39
44
  #
40
45
  # @params [Hash] the OAuth authentication hash
41
46
  # @returns [Identity]
42
- def find_or_initialize_by_omniauth(auth)
43
- identity = where(:provider => auth['provider'], :uid => auth['uid']).first || new
44
- identity.auth_hash = auth
45
- identity
47
+ def create_from_omniauth(auth={})
48
+ create do |identity|
49
+ identity.provider = auth['provider']
50
+ identity.uid = auth['uid']
51
+ identity.auth_hash = auth
52
+ end
53
+ end
54
+
55
+ def find_or_create_from_omniauth(auth)
56
+ raise ArgumentError, 'auth parameter must be a hash' unless auth.is_a?(Hash)
57
+ find_from_omniauth(auth) || create_from_omniauth(auth)
58
+ end
59
+
60
+ # Finder method that finds the matching Provider and UID.
61
+ #
62
+ # @params [Hash] the OmniAuth authentication hash
63
+ def find_from_omniauth(auth={})
64
+ where(:provider => auth['provider'], :uid => auth['uid']).first
46
65
  end
47
66
  end
48
67
 
@@ -1,13 +1,52 @@
1
+ require 'omniauth-identity'
2
+ require 'socialite/ext/omniauth/identity/model'
3
+
1
4
  module Socialite
2
5
  module Models
3
6
  module UserConcern
4
7
  extend ActiveSupport::Concern
8
+ include OmniAuth::Identity::Model
9
+ include OmniAuth::Identity::SecurePassword
5
10
 
6
11
  included do
12
+
13
+ attr_accessible :email, :name, :password, :password_confirmation
14
+
15
+ has_secure_password if defined?(BCrypt)
16
+
7
17
  has_many :identities,
8
18
  :dependent => :destroy,
9
19
  :class_name => Socialite.identity_class_name,
10
20
  :foreign_key => "#{Socialite.user_class.table_name.singularize}_id"
21
+
22
+ validates :email,
23
+ :presence => true,
24
+ :format => { :with => /.+@.+\..+/i },
25
+ :uniqueness => { :case_sensitive => false }
26
+ end
27
+
28
+ module ClassMethods
29
+ # include OmniAuth::Identity::Model#::ClassMethods
30
+ # include OmniAuth::Identity::SecurePassword::ClassMethods
31
+
32
+ def create_from_omniauth(auth)
33
+ create do |user|
34
+ user.name = auth['info']['name']
35
+ user.name = auth['info']['email']
36
+ user.password ||= rand(36**10).to_s(36)
37
+ end
38
+ end
39
+
40
+ def auth_key; :email; end
41
+
42
+ # def auth_key=(key)
43
+ # super
44
+ # validates_uniqueness_of key, :case_sensitive => false
45
+ # end
46
+
47
+ def locate(search_hash)
48
+ where(search_hash).first
49
+ end
11
50
  end
12
51
 
13
52
  def method_missing(id, *args, &block)
@@ -1,3 +1,3 @@
1
1
  module Socialite
2
- VERSION = '0.1.0.pre'
2
+ VERSION = '0.1.0.pre.2'
3
3
  end
@@ -0,0 +1,7 @@
1
+ class PagesController < ApplicationController
2
+ protect_from_forgery
3
+
4
+ def index
5
+
6
+ end
7
+ end
@@ -1,3 +1,5 @@
1
+ require 'bcrypt'
2
+
1
3
  class User < ActiveRecord::Base
2
4
  self.table_name = 'socialite_users'
3
5
  include Socialite::Models::UserConcern
@@ -0,0 +1,5 @@
1
+ %h1 Home
2
+
3
+ - flash.each do |type, message|
4
+ .flash{class: "#{type}"}
5
+ = message
@@ -0,0 +1,11 @@
1
+ require 'omniauth-facebook'
2
+ require 'omniauth-identity'
3
+ require 'omniauth/identity'
4
+
5
+ Socialite.setup do |config|
6
+ config.provider :identity,
7
+ :model => User,
8
+ :fields => [:email],
9
+ :on_failed_registration => Socialite::UsersController.action(:new)
10
+ config.provider :facebook, 'xyz', '123'
11
+ end
@@ -20,6 +20,15 @@ Socialite.setup do |config|
20
20
  # }
21
21
  # config.provider :twitter, ENV['TWITTER_APP_KEY'], ENV['TWITTER_SECRET']
22
22
 
23
+ # We highly recommended adding the omniauth-identity gem to your Gemfile.
24
+ # This does not enforce a password on signup, but establishes a common
25
+ # 'password recovery' entry point for all users.
26
+ #
27
+ # config.provider :identity,
28
+ # :model => Socialite.user_class,
29
+ # :fields => [:email],
30
+ # :on_failed_registration => Socialite::UsersController.action(:new)
31
+
23
32
  if Rails.env.production?
24
33
  # Any production specific information
25
34
  elsif Rails.env.development?
@@ -1,3 +1,19 @@
1
1
  Rails.application.routes.draw do
2
- mount Socialite::Engine => "/socialite"
2
+
3
+ # This line mounts Socialite's routes at /socialite by default.
4
+ # This means, any requests to the /socialite URL of your application will go
5
+ # to Socialite::SessionsController#new. If you would like to change where
6
+ # this extension is mounted, simply change the :at option to something
7
+ # different.
8
+ #
9
+ # We ask that you don't use the :as option here, as Socialite relies on it
10
+ # being the default of "socialite"
11
+ mount Socialite::Engine, :at => '/socialite'
12
+ match '/login' => 'socialite::sessions#new'
13
+ match '/logout', :to => 'socialite::sessions#destroy'
14
+ match '/signup', :to => 'socialite::users#new'
15
+ match '/auth/:provider/callback', :to => 'socialite::sessions#create'
16
+ match '/auth/failure', :to => 'socialite::sessions#failure'
17
+
18
+ root :to => "pages#index"
3
19
  end
@@ -0,0 +1,16 @@
1
+ class CreateSocialiteUsers < ActiveRecord::Migration
2
+ def up
3
+ create_table :socialite_users do |t|
4
+ t.string :name, :email
5
+ t.string :password_digest # set :null => false to enforce identity, requires 'bcrypt-ruby' in your Gemfile.
6
+ t.timestamps
7
+ end
8
+
9
+ # Enforce only every email must be unique
10
+ add_index :socialite_users, :email, :unique => true
11
+ end
12
+
13
+ def down
14
+ drop_table :socialite_users
15
+ end
16
+ end
@@ -11,7 +11,7 @@
11
11
  #
12
12
  # It's strongly recommended to check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20130206224517) do
14
+ ActiveRecord::Schema.define(:version => 20130207223010) do
15
15
 
16
16
  create_table "socialite_identities", :force => true do |t|
17
17
  t.string "uid"
@@ -28,8 +28,12 @@ ActiveRecord::Schema.define(:version => 20130206224517) do
28
28
 
29
29
  create_table "socialite_users", :force => true do |t|
30
30
  t.string "name"
31
- t.datetime "created_at", :null => false
32
- t.datetime "updated_at", :null => false
31
+ t.string "email"
32
+ t.string "password_digest"
33
+ t.datetime "created_at", :null => false
34
+ t.datetime "updated_at", :null => false
33
35
  end
34
36
 
37
+ add_index "socialite_users", ["email"], :name => "index_socialite_users_on_email", :unique => true
38
+
35
39
  end
@@ -1,6 +1,8 @@
1
1
  FactoryGirl.define do
2
2
  factory :user do
3
- # Something here
3
+ name { Faker::Name.name }
4
+ email { Faker::Internet.email }
5
+ password 'secret'
4
6
  end
5
7
 
6
8
  factory :linked_user, :parent => :user do
@@ -11,4 +13,12 @@ FactoryGirl.define do
11
13
  ]
12
14
  end
13
15
  end
16
+
17
+ factory :identity_user, :parent => :user do
18
+ after(:create) do |user|
19
+ user.identities = [
20
+ FactoryGirl.build(:identity, :provider => 'identity', :uid => user.uid)
21
+ ]
22
+ end
23
+ end
14
24
  end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ # FIXME Relies on spec/dummy/config/initializers/omniauth-facebook.rb or you get
4
+ # stack/routing/middleware issues.
5
+ #
6
+ feature "Facebook Registration", :omniauth => true do
7
+ background do
8
+ FactoryGirl.create(:linked_user)
9
+ end
10
+
11
+ scenario "Signing up with Facebook" do
12
+ visit '/auth/facebook'
13
+ page.should have_text 'Welcome to The app!'
14
+ end
15
+ end
16
+
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ # FIXME Relies on spec/dummy/config/initializers/omniauth-identity.rb or you get
4
+ # stack/routing/middleware issues.
5
+ #
6
+ feature "Identity Login" do
7
+ background do
8
+ FactoryGirl.create(:identity_user, :email => 'user@example.com', :password => 'caplin')
9
+ end
10
+
11
+ scenario "Signing in with correct credentials" do
12
+ visit '/login'
13
+ fill_in 'Email', :with => 'user@example.com'
14
+ fill_in 'Password', :with => 'caplin'
15
+ click_button 'Sign in'
16
+ page.should have_content 'Signed in!'
17
+ end
18
+
19
+ scenario "Signing in as invalid user" do
20
+ visit '/login'
21
+ fill_in 'Email', :with => 'user@example.com'
22
+ fill_in 'Password', :with => 'bogus'
23
+ click_button 'Sign in'
24
+ page.should have_content 'Authentication failed, please try again.'
25
+ end
26
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ # FIXME Relies on spec/dummy/config/initializers/omniauth-identity.rb or you get
4
+ # stack/routing/middleware issues.
5
+ #
6
+ feature "Identity Registration" do
7
+ background do
8
+ FactoryGirl.create(:identity_user, :email => 'user@example.com', :password => 'caplin')
9
+ end
10
+
11
+ scenario "Signing up with existing email" do
12
+ visit '/signup'
13
+ fill_in 'Email', :with => 'user@example.com'
14
+ fill_in 'password', :with => 'caplin'
15
+ fill_in 'password_confirmation', :with => 'caplin'
16
+ click_button 'Sign Up'
17
+ page.should have_css('.error')
18
+ page.should have_button('Sign Up')
19
+ end
20
+
21
+ scenario "Signing up with valid email" do
22
+ visit '/signup'
23
+ fill_in 'Email', :with => 'diffuser@example.com'
24
+ fill_in 'password', :with => 'secrets'
25
+ fill_in 'password_confirmation', :with => 'secrets'
26
+ click_button 'Sign Up'
27
+ page.should have_text 'Welcome to The app!'
28
+ page.should have_no_css('.error')
29
+ page.should have_no_button('Sign Up')
30
+ end
31
+ end
@@ -22,6 +22,7 @@ describe Socialite::Generators::InstallGenerator do
22
22
  it 'should run all tasks in the generator' do
23
23
  gen = generator %w(install)
24
24
  gen.should_receive :copy_initializer
25
+ gen.should_receive :mount_engine
25
26
  capture(:stdout) { gen.invoke_all }
26
27
  end
27
28
 
@@ -30,7 +31,8 @@ describe Socialite::Generators::InstallGenerator do
30
31
  before do
31
32
  run_generator %w(install)
32
33
  end
33
- describe 'the spec' do
34
+
35
+ describe 'the configuration file' do
34
36
  # file - gives you the absolute path where the generator will create the file
35
37
  subject { file('config/initializers/socialite.rb') }
36
38
  # should exist - verifies the file exists
@@ -39,5 +41,10 @@ describe Socialite::Generators::InstallGenerator do
39
41
  # should contain - verifies the file's contents
40
42
  it { should contain(/Socialite.setup do \|config\|/) }
41
43
  end
44
+
45
+ describe 'the routes file' do
46
+ subject { file('config/routes.rb') }
47
+ it { should contain(/mount Socialite::Engine, :at => '\/socialite'/) }
48
+ end
42
49
  end
43
50
  end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ require "generators/socialite/views_generator"
3
+
4
+ describe Socialite::Generators::ViewsGenerator do
5
+ destination File.expand_path("../../../../tmp", __FILE__)
6
+
7
+ before(:each) do
8
+ prepare_destination
9
+ %w(config script).each do |dir|
10
+ `ln -s #{Rails.root + dir} #{destination_root}`
11
+ end
12
+ end
13
+
14
+ after(:each) do
15
+ unless example.exception
16
+ prepare_destination
17
+ end
18
+ end
19
+
20
+ # using mocks to ensure proper methods are called
21
+ # invoke_all - will call all the tasks in the generator
22
+ it 'should run all tasks in the generator' do
23
+ gen = generator %w(views)
24
+ gen.should_receive :copy_views
25
+ capture(:stdout) { gen.invoke_all }
26
+ end
27
+ end