socialite 0.1.0.pre → 0.1.0.pre.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|