solidus_social 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.hound.yml +26 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +8 -0
  6. data/.travis.yml +19 -0
  7. data/CHANGELOG.md +5 -0
  8. data/CONTRIBUTING.md +31 -0
  9. data/Gemfile +7 -0
  10. data/Guardfile +10 -0
  11. data/LICENSE.md +26 -0
  12. data/README.md +148 -0
  13. data/Rakefile +15 -0
  14. data/app/assets/javascripts/spree/backend/solidus_social.js +1 -0
  15. data/app/assets/javascripts/spree/frontend/solidus_social.js +1 -0
  16. data/app/assets/stylesheets/spree/backend/solidus_social.css +3 -0
  17. data/app/assets/stylesheets/spree/frontend/fontello.css +64 -0
  18. data/app/assets/stylesheets/spree/frontend/solidus_social.css +4 -0
  19. data/app/controllers/spree/admin/authentication_methods_controller.rb +18 -0
  20. data/app/controllers/spree/omniauth_callbacks_controller.rb +67 -0
  21. data/app/controllers/spree/user_authentications_controller.rb +12 -0
  22. data/app/controllers/spree/user_registrations_controller_decorator.rb +15 -0
  23. data/app/helpers/spree/omniauth_callbacks_helper.rb +5 -0
  24. data/app/models/spree/authentication_method.rb +13 -0
  25. data/app/models/spree/social_configuration.rb +5 -0
  26. data/app/models/spree/user_authentication.rb +3 -0
  27. data/app/models/spree/user_decorator.rb +16 -0
  28. data/app/overrides/add_authentications_to_account_summary.rb +5 -0
  29. data/app/overrides/admin_configuration_decorator.rb +5 -0
  30. data/app/overrides/user_registrations_decorator.rb +17 -0
  31. data/app/views/spree/admin/authentication_methods/_form.html.erb +45 -0
  32. data/app/views/spree/admin/authentication_methods/edit.html.erb +18 -0
  33. data/app/views/spree/admin/authentication_methods/index.html.erb +54 -0
  34. data/app/views/spree/admin/authentication_methods/new.html.erb +18 -0
  35. data/app/views/spree/admin/shared/_configurations_menu.html.erb +4 -0
  36. data/app/views/spree/shared/_social.html.erb +11 -0
  37. data/app/views/spree/shared/_user_form.html.erb +19 -0
  38. data/app/views/spree/users/_new-customer.html.erb +5 -0
  39. data/app/views/spree/users/_social.html.erb +28 -0
  40. data/bin/rails +7 -0
  41. data/config/initializers/devise.rb +13 -0
  42. data/config/locales/de.yml +26 -0
  43. data/config/locales/en.yml +26 -0
  44. data/config/locales/es-MX.yml +26 -0
  45. data/config/locales/fr.yml +26 -0
  46. data/config/locales/nl.yml +26 -0
  47. data/config/locales/pt-BR.yml +26 -0
  48. data/config/locales/sv.yml +26 -0
  49. data/config/routes.rb +14 -0
  50. data/db/migrate/20120120163432_create_user_authentications.rb +10 -0
  51. data/db/migrate/20120123163222_create_authentication_methods.rb +13 -0
  52. data/lib/generators/solidus_social/install/install_generator.rb +24 -0
  53. data/lib/solidus_social.rb +10 -0
  54. data/lib/solidus_social/engine.rb +70 -0
  55. data/lib/solidus_social/version.rb +18 -0
  56. data/solidus_social.gemspec +47 -0
  57. data/spec/controllers/spree/omniauth_callbacks_controller_spec.rb +160 -0
  58. data/spec/features/spree/admin/authentication_methods_configuration_spec.rb +79 -0
  59. data/spec/features/spree/sign_in_spec.rb +81 -0
  60. data/spec/lib/spree_social/engine_spec.rb +16 -0
  61. data/spec/models/spree/user_decorator_spec.rb +54 -0
  62. data/spec/spec_helper.rb +36 -0
  63. data/spec/support/capybara.rb +18 -0
  64. data/spec/support/database_cleaner.rb +24 -0
  65. data/spec/support/devise.rb +3 -0
  66. data/spec/support/factory_girl.rb +7 -0
  67. data/spec/support/spree.rb +8 -0
  68. metadata +429 -0
@@ -0,0 +1,26 @@
1
+ ---
2
+ nl:
3
+ devise:
4
+ omniauth_callbacks:
5
+ success: "U bent nu aangemeld met uw %{kind}-account."
6
+ spree:
7
+ user_was_not_valid: Gebruiker was niet geldig.
8
+ add_another_service: 'Nog een log-in dienst toevoegen:'
9
+ authentications:
10
+ destroy: "Met succes vernietigd authenticatiemethode."
11
+ back_to_authentication_methods_list: "Terug naar de lijst verificatiemethoden"
12
+ edit_social_method: 'Bewerk Social Authenticatie Methodes'
13
+ new_social_method: 'Nieuwe Authenticatie Methode'
14
+ no_authentication_methods_found: "Geen verificatiemethoden gevonden"
15
+ one_more_step: 'Laatste stap om registratie met %{kind} te voltooien'
16
+ remove_authentication_option_confirmation: 'Weet je zeker dat je deze authenticatie methode wilt verwijderen?'
17
+ sign_into_account: 'Je kunt bij deze account inlogen met:'
18
+ sign_in_through_one_of_these_services: 'Log in met een van de volgende diensten:'
19
+ social_api_key: 'API Key'
20
+ social_api_secret: 'API Secret'
21
+ social_authentication_methods: 'Social Authenticatie Methodes'
22
+ social_authentication_methods_description: 'OAuth Authenticatie Methodes Instellen'
23
+ social_provider: 'Social Provider'
24
+ please_confirm_your_email: 'Bevestig je email adres om verder te gaan'
25
+ sign_in_with: 'Login met %{provider}'
26
+ you_have_signed_in_with_these_services: "Je hebt in deze diensten ondertekend"
@@ -0,0 +1,26 @@
1
+ ---
2
+ pt-BR:
3
+ devise:
4
+ omniauth_callbacks:
5
+ success: "Você está logado agora com a sua conta do %{kind}."
6
+ spree:
7
+ user_was_not_valid: "Usuário não era válido."
8
+ add_another_service: "Adicione outro serviço para se logar:"
9
+ authentications:
10
+ destroy: 'Método de autenticação destruído com sucesso.'
11
+ back_to_authentication_methods_list: "Voltar Para Lista de Métodos de Autenticação"
12
+ edit_social_method: "Editando Método de Autenticação Social"
13
+ new_social_method: "Novo Método de Autenticação"
14
+ no_authentication_methods_found: "Métodos de Autenticação Não Encontrados"
15
+ one_more_step: 'Um passo apenas para completar seu registro pelo %{kind}'
16
+ remove_authentication_option_confirmation: "Você tem certeza que deseja remover este método de autenticação ?"
17
+ sign_into_account: "Você pode acessar esta conta usando:"
18
+ sign_in_through_one_of_these_services: "Acesse através de um destes serviços:"
19
+ social_api_key: "Chave API"
20
+ social_api_secret: "Segredo API"
21
+ social_authentication_methods: "Métodos de Autenticação Social"
22
+ social_authentication_methods_description: "Configure Métodos de Autenticação OAuth"
23
+ social_provider: "Provedor Social"
24
+ please_confirm_your_email: "Por favor confirme seu endereço de e-mail para continuar"
25
+ sign_in_with: "Login com %{provider}"
26
+ you_have_signed_in_with_these_services: "Você se cadastrou com estes serviços"
@@ -0,0 +1,26 @@
1
+ ---
2
+ sv:
3
+ devise:
4
+ omniauth_callbacks:
5
+ success: "Du är nu inloggad med ditt %{kind} konto."
6
+ spree:
7
+ user_was_not_valid: "Användaren var inte giltigt."
8
+ add_another_service: "Lägg en annan tjänst för att logga in med:"
9
+ authentications:
10
+ destroy: "Autentiseringsmetoden har nu blivit borttagen."
11
+ back_to_authentication_methods_list: "Tillbaka till listan med autentiseringsmetoder"
12
+ edit_social_method: "Redigera social autentiseringsmetod"
13
+ new_social_method: "Ny autentiseringsmetod"
14
+ no_authentication_methods_found: "Inga autentiseringsmetoder funna"
15
+ one_more_step: "Ett steg från att slutföra din registrering från %{kind}"
16
+ remove_authentication_option_confirmation: "Är du säker på att du vill ta bort denna autentiseringsmetod?"
17
+ sign_into_account: "Du kan logga in på detta konto med hjälp av:"
18
+ sign_in_through_one_of_these_services: "Logga in genom en av dessa tjänster:"
19
+ social_api_key: "API-nyckel"
20
+ social_api_secret: "API lösenord"
21
+ social_authentication_methods: "Sociala autentiseringsmetoder"
22
+ social_authentication_methods_description: "Sätt upp OAuth autentiseringsmetoder"
23
+ social_provider: "Social tjänst"
24
+ please_confirm_your_email: "Bekräfta din e-postadress för att fortsätta"
25
+ sign_in_with: "Logga in med %{provider}"
26
+ you_have_signed_in_with_these_services: "Du har loggat in via dessa tjänster"
@@ -0,0 +1,14 @@
1
+ Spree::Core::Engine.add_routes do
2
+ devise_for :spree_user,
3
+ class_name: Spree::User,
4
+ only: [:omniauth_callbacks],
5
+ controllers: { omniauth_callbacks: 'spree/omniauth_callbacks' },
6
+ path: Spree::SocialConfig[:path_prefix]
7
+ resources :user_authentications
8
+
9
+ get 'account' => 'users#show', as: 'user_root'
10
+
11
+ namespace :admin do
12
+ resources :authentication_methods
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ class CreateUserAuthentications < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_user_authentications do |t|
4
+ t.integer :user_id
5
+ t.string :provider
6
+ t.string :uid
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ class CreateAuthenticationMethods < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_authentication_methods do |t|
4
+ t.string :environment
5
+ t.string :provider
6
+ t.string :api_key
7
+ t.string :api_secret
8
+ t.boolean :active
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ module SolidusSocial
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ class_option :auto_run_migrations, type: :boolean, default: false
5
+
6
+ def add_stylesheets
7
+ inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/solidus_social\n", before: /\*\//, verbose: true
8
+ end
9
+
10
+ def add_migrations
11
+ run 'bundle exec rake railties:install:migrations FROM=solidus_social'
12
+ end
13
+
14
+ def run_migrations
15
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
16
+ if run_migrations
17
+ run 'bundle exec rake db:migrate'
18
+ else
19
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ require 'spree_core'
2
+ require 'solidus_auth_devise'
3
+ require 'omniauth-twitter'
4
+ require 'omniauth-facebook'
5
+ require 'omniauth-github'
6
+ require 'omniauth-google-oauth2'
7
+ require 'omniauth-amazon'
8
+ require 'solidus_social/engine'
9
+ require 'solidus_social/version'
10
+ require 'coffee_script'
@@ -0,0 +1,70 @@
1
+ module SolidusSocial
2
+ OAUTH_PROVIDERS = [
3
+ %w(Facebook facebook),
4
+ %w(Twitter twitter),
5
+ %w(Github github),
6
+ %w(Google google_oauth2),
7
+ %w(Amazon amazon)
8
+ ]
9
+
10
+ class Engine < Rails::Engine
11
+ engine_name 'solidus_social'
12
+
13
+ config.autoload_paths += %W(#{config.root}/lib)
14
+
15
+ initializer 'solidus_social.environment', before: 'spree.environment' do
16
+ Spree::SocialConfig = Spree::SocialConfiguration.new
17
+ end
18
+
19
+ def self.activate
20
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
21
+ Rails.configuration.cache_classes ? require(c) : load(c)
22
+ end
23
+ end
24
+
25
+ config.to_prepare(&method(:activate).to_proc)
26
+ end
27
+
28
+ # Setup all OAuth providers
29
+ def self.init_provider(provider)
30
+ return unless ActiveRecord::Base.connection.table_exists?('spree_authentication_methods')
31
+ key, secret = nil
32
+ Spree::AuthenticationMethod.where(environment: ::Rails.env).each do |auth_method|
33
+ next unless auth_method.provider == provider
34
+ key = auth_method.api_key
35
+ secret = auth_method.api_secret
36
+ Rails.logger.info("[Spree Social] Loading #{auth_method.provider.capitalize} as authentication source")
37
+ end
38
+ setup_key_for(provider.to_sym, key, secret)
39
+ end
40
+
41
+ def self.setup_key_for(provider, key, secret)
42
+ Devise.setup do |config|
43
+ config.omniauth provider, key, secret, setup: true
44
+ end
45
+ end
46
+ end
47
+
48
+ module OmniAuth
49
+ module Strategies
50
+ class Facebook < OAuth2
51
+ MOBILE_USER_AGENTS = 'palm|blackberry|nokia|phone|midp|mobi|symbian|chtml|ericsson|minimo|' \
52
+ 'audiovox|motorola|samsung|telit|upg1|windows ce|ucweb|astel|plucker|' \
53
+ 'x320|x240|j2me|sgh|portable|sprint|docomo|kddi|softbank|android|mmp|' \
54
+ 'pdxgw|netfront|xiino|vodafone|portalmmm|sagem|mot-|sie-|ipod|up\\.b|' \
55
+ 'webos|amoi|novarra|cdm|alcatel|pocket|ipad|iphone|mobileexplorer|' \
56
+ 'mobile'
57
+ def request_phase
58
+ options[:scope] ||= 'email'
59
+ options[:info_fields] ||= 'email'
60
+ options[:display] = mobile_request? ? 'touch' : 'page'
61
+ super
62
+ end
63
+
64
+ def mobile_request?
65
+ ua = Rack::Request.new(@env).user_agent.to_s
66
+ ua.downcase =~ Regexp.new(MOBILE_USER_AGENTS)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,18 @@
1
+ module SolidusSocial
2
+ module_function
3
+
4
+ # Returns the version of the currently loaded SolidusSocial as a
5
+ # <tt>Gem::Version</tt>.
6
+ def version
7
+ Gem::Version.new VERSION::STRING
8
+ end
9
+
10
+ module VERSION
11
+ MAJOR = 1
12
+ MINOR = 0
13
+ TINY = 0
14
+ PRE = nil
15
+
16
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
17
+ end
18
+ end
@@ -0,0 +1,47 @@
1
+ lib = File.expand_path('../lib/', __FILE__)
2
+ $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'solidus_social/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.platform = Gem::Platform::RUBY
8
+ s.name = 'solidus_social'
9
+ s.version = SolidusSocial.version
10
+ s.summary = 'Adds social network login services (OAuth) to Spree'
11
+ s.description = s.summary
12
+ s.required_ruby_version = '>= 1.9.3'
13
+
14
+ s.author = 'John Dyer'
15
+ s.email = 'jdyer@spreecommerce.com'
16
+ s.homepage = 'http://www.spreecommerce.com'
17
+ s.license = 'BSD-3'
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- spec/*`.split("\n")
21
+ s.require_path = 'lib'
22
+ s.requirements << 'none'
23
+
24
+ s.add_runtime_dependency 'solidus_core', ["~> 1.0"]
25
+ s.add_runtime_dependency 'omniauth'
26
+ s.add_runtime_dependency 'oa-core'
27
+ s.add_runtime_dependency 'omniauth-twitter'
28
+ s.add_runtime_dependency 'omniauth-facebook'
29
+ s.add_runtime_dependency 'omniauth-github'
30
+ s.add_runtime_dependency 'omniauth-google-oauth2'
31
+ s.add_runtime_dependency 'omniauth-amazon'
32
+
33
+ s.add_development_dependency 'capybara', '~> 2.4.1'
34
+ s.add_development_dependency 'database_cleaner', '1.3.0'
35
+ s.add_development_dependency 'rspec-rails', '~> 3.1.0'
36
+ s.add_development_dependency 'factory_girl', '~> 4.4'
37
+ s.add_development_dependency 'pry-rails'
38
+ s.add_development_dependency 'selenium-webdriver', '>= 2.41.0'
39
+ s.add_development_dependency 'poltergeist', '~> 1.5.0'
40
+ s.add_development_dependency 'simplecov', '~> 0.9.0'
41
+ s.add_development_dependency 'sqlite3', '~> 1.3.10'
42
+ s.add_development_dependency 'coffee-rails'
43
+ s.add_development_dependency 'sass-rails'
44
+ s.add_development_dependency 'guard-rspec'
45
+ s.add_development_dependency 'rubocop', '>= 0.24.1'
46
+ s.add_development_dependency 'rake', '< 11'
47
+ end
@@ -0,0 +1,160 @@
1
+ RSpec.describe Spree::OmniauthCallbacksController, type: :controller do
2
+ let(:user) { create(:user) }
3
+ let(:omni_params) { double('omni', :[] => nil).as_null_object }
4
+ let(:order) { double('Spree::Order', associate_user: nil) }
5
+
6
+ before do
7
+ Rails.application.routes.default_url_options[:host] = 'test.host'
8
+ request.env['omniauth.auth'] = omni_params
9
+ allow(controller).to receive(:sign_in_and_redirect)
10
+ allow(controller).to receive(:redirect_back_or_default)
11
+ allow(Spree::User).to receive(:anonymous!).with(user)
12
+ end
13
+
14
+ shared_examples_for 'denied_permissions' do
15
+ before { request.env['omniauth.error'] = 'FAIL' }
16
+
17
+ it 'redirects properly' do
18
+ expect(controller).to receive(:redirect_back_or_default)
19
+ controller.twitter
20
+ end
21
+
22
+ it 'displays an error message' do
23
+ controller.twitter
24
+ expect(flash[:error]).not_to be_blank
25
+ end
26
+
27
+ it 'does not attempt authentication' do
28
+ expect(controller).not_to receive(:sign_in_and_redirect)
29
+ controller.twitter
30
+ end
31
+ end
32
+
33
+ shared_examples_for 'associate_order' do
34
+ before { allow(controller).to receive(:current_order).and_return(order) }
35
+
36
+ it 'associates the order with the user' do
37
+ expect(order).to receive(:associate_user!).with(user)
38
+ controller.twitter
39
+ end
40
+ end
41
+
42
+ shared_examples_for 'authenticate_as_user' do
43
+ it 'authenticates as that user' do
44
+ expect(controller).to receive(:sign_in_and_redirect).with(user, event: :authentication)
45
+ end
46
+ end
47
+
48
+ context '#callback' do
49
+ context 'when user is authenticated' do
50
+ before do
51
+ allow(controller).to receive(:spree_current_user).and_return(user)
52
+ end
53
+
54
+ it_should_behave_like 'denied_permissions'
55
+
56
+ context 'when existing user_authentication' do
57
+ let(:user_authentication) { double('user_authentication', user: user) }
58
+ before do
59
+ allow(Spree::UserAuthentication).to receive(:find_by_provider_and_uid).and_return(user_authentication)
60
+ end
61
+
62
+ it 'does not need to create the user_authentication' do
63
+ expect(user.user_authentications).not_to receive(:create!)
64
+ controller.twitter
65
+ end
66
+
67
+ it 'sets the flash notice' do
68
+ controller.twitter
69
+ expect(flash[:notice]).not_to be_blank
70
+ end
71
+
72
+ it 'authenticates as that user' do
73
+ expect(controller).to receive(:sign_in_and_redirect)
74
+ controller.twitter
75
+ end
76
+ end
77
+
78
+ context 'when no existing user_authentication' do
79
+ before do
80
+ allow(Spree::UserAuthentication).to receive(:find_by_provider_and_uid).and_return(nil)
81
+ end
82
+
83
+ it 'creates a new user_authentication' do
84
+ expect(user).to receive(:apply_omniauth)
85
+ expect(user).to receive(:save!)
86
+ controller.twitter
87
+ end
88
+
89
+ it 'sets the flash notice' do
90
+ controller.twitter
91
+ expect(flash[:notice]).not_to be_blank
92
+ end
93
+
94
+ it 'redirects properly' do
95
+ expect(controller).to receive(:redirect_back_or_default)
96
+ controller.twitter
97
+ end
98
+
99
+ it_should_behave_like 'associate_order'
100
+ end
101
+ end
102
+
103
+ context 'when user is not authenticated' do
104
+ before do
105
+ allow(controller).to receive(:spree_current_user).and_return(nil)
106
+ end
107
+
108
+ it_should_behave_like 'denied_permissions'
109
+
110
+ context 'when existing user_authentication' do
111
+ let(:user_authentication) { double('user_authentication', user: user) }
112
+ before do
113
+ allow(Spree::UserAuthentication).to receive(:find_by_provider_and_uid).and_return(user_authentication)
114
+ end
115
+
116
+ it 'does not need to create the user_authentication' do
117
+ expect(user.user_authentications).not_to receive(:create!)
118
+ controller.twitter
119
+ end
120
+
121
+ it 'does not create a new user account' do
122
+ expect(Spree::User).not_to receive :new
123
+ controller.twitter
124
+ end
125
+
126
+ it 'authenticates as that user' do
127
+ expect(controller).to receive(:sign_in_and_redirect).with(:spree_user, user)
128
+ controller.twitter
129
+ end
130
+ end
131
+
132
+ context 'when no existing user_authentication' do
133
+ let(:user) { Spree::User.new }
134
+ before do
135
+ allow(Spree::UserAuthentication).to receive(:find_by_provider_and_uid).and_return(nil)
136
+ allow(controller).to receive(:auth_hash).and_return('provider' => 'facebook', 'info' => { 'email' => 'spree@gmail.com' }, 'uid' => '123')
137
+ end
138
+
139
+ context "email doesn't belongs to anyone" do
140
+ it 'creates a new user' do
141
+ expect(controller).to receive(:sign_in_and_redirect)
142
+ expect { controller.twitter }.to change(Spree::User, :count).by(1)
143
+ end
144
+ end
145
+
146
+ context 'email belongs to existing user' do
147
+ before { @user = create(:user, email: 'spree@gmail.com') }
148
+
149
+ it 'does not create new user' do
150
+ expect { controller.twitter }.to_not change(Spree::User, :count)
151
+ end
152
+
153
+ it 'assigns authentication to existing user' do
154
+ expect { controller.twitter }.to change(@user.user_authentications, :count).by(1)
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end