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.
- data/app/assets/images/socialite/facebook_64.png +0 -0
- data/app/assets/images/socialite/twitter_64.png +0 -0
- data/app/controllers/socialite/sessions_controller.rb +69 -0
- data/app/controllers/socialite/users_controller.rb +2 -31
- data/app/views/layouts/socialite/application.html.haml +1 -1
- data/app/views/socialite/identities/new.html.haml +6 -19
- data/app/views/socialite/sessions/new.html.haml +30 -0
- data/app/views/socialite/users/new.html.haml +10 -0
- data/config/routes.rb +6 -7
- data/lib/generators/socialite/install_generator.rb +24 -5
- data/lib/generators/socialite/migrations_generator.rb +1 -1
- data/lib/generators/socialite/templates/socialite.rb +9 -0
- data/lib/generators/socialite/templates/users.rb.erb +5 -1
- data/lib/generators/socialite/views_generator.rb +22 -0
- data/lib/socialite.rb +4 -8
- data/lib/socialite/controllers/helpers.rb +5 -115
- data/lib/socialite/engine.rb +8 -11
- data/lib/socialite/ext/omniauth/identity/model.rb +29 -0
- data/lib/socialite/models/identity_concern.rb +24 -5
- data/lib/socialite/models/user_concern.rb +39 -0
- data/lib/socialite/version.rb +1 -1
- data/spec/dummy/app/controllers/pages_controller.rb +7 -0
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/app/views/pages/index.html.haml +5 -0
- data/spec/dummy/config/initializers/omniauth-identity.rb +11 -0
- data/spec/dummy/config/initializers/socialite.rb +9 -0
- data/spec/dummy/config/routes.rb +17 -1
- data/spec/dummy/db/migrate/20130207223009_create_socialite_users.rb +16 -0
- data/spec/dummy/db/migrate/{20130206224517_create_socialite_identities.rb → 20130207223010_create_socialite_identities.rb} +0 -0
- data/spec/dummy/db/schema.rb +7 -3
- data/spec/factories/user.rb +11 -1
- data/{features/registration/twitter_signup.feature → spec/features/.gitkeep} +0 -0
- data/spec/features/facebook_registration_spec.rb +16 -0
- data/spec/features/identity_login_spec.rb +26 -0
- data/spec/features/identity_registration_spec.rb +31 -0
- data/spec/generators/socialite/install_generator_spec.rb +8 -1
- data/spec/generators/socialite/views_generator_spec.rb +27 -0
- data/spec/models/identity_spec.rb +4 -6
- data/spec/models/user_spec.rb +18 -18
- data/spec/socialite_spec.rb +31 -7
- data/spec/spec_helper.rb +4 -1
- data/spec/support/capybara.rb +3 -0
- data/spec/support/database_cleaner.rb +18 -0
- data/spec/support/identity_shared_example.rb +4 -23
- data/spec/support/omniauth.rb +35 -0
- metadata +95 -78
- data/app/controllers/socialite/identities_controller.rb +0 -41
- data/app/controllers/socialite/session_controller.rb +0 -32
- data/app/views/socialite/session/new.html.haml +0 -31
- data/app/views/socialite/user/_form.html.haml +0 -13
- data/app/views/socialite/user/edit.html.haml +0 -1
- data/app/views/socialite/user/show.html.haml +0 -16
- data/features/authentication/facebook_signin.feature +0 -5
- data/features/authentication/twitter_signin.feature +0 -5
- data/features/identities/facebook_management.feature +0 -14
- data/features/identities/twitter_management.feature +0 -7
- data/features/registration/facebook_signup.feature +0 -10
- data/features/step_definitions/authentication_steps.rb +0 -31
- data/features/step_definitions/common_steps.rb +0 -13
- data/features/step_definitions/identity_steps.rb +0 -5
- data/features/step_definitions/web_steps.rb +0 -254
- data/features/support/env.rb +0 -58
- data/features/support/hooks.rb +0 -3
- data/features/support/omniauth.rb +0 -31
- data/features/support/paths.rb +0 -34
- data/features/support/selectors.rb +0 -39
- data/lib/socialite/helpers/authentication.rb +0 -17
- data/lib/socialite/models/facebook_identity.rb +0 -14
- data/spec/dummy/db/migrate/20130206224516_create_socialite_users.rb +0 -12
- data/spec/factories/facebook.rb +0 -5
- data/spec/factories/twitter.rb +0 -6
- data/spec/models/facebook_spec.rb +0 -31
data/lib/socialite/engine.rb
CHANGED
@@ -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'
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
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 => {
|
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
|
43
|
-
|
44
|
-
|
45
|
-
|
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)
|
data/lib/socialite/version.rb
CHANGED
@@ -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?
|
data/spec/dummy/config/routes.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
|
-
|
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
|
File without changes
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -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 =>
|
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.
|
32
|
-
t.
|
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
|
data/spec/factories/user.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
FactoryGirl.define do
|
2
2
|
factory :user do
|
3
|
-
|
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
|
File without changes
|
@@ -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
|
-
|
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
|