devise_meteor 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +21 -0
- data/README.md +78 -0
- data/Rakefile +7 -0
- data/app/models/devise_meteor/meteor_profile.rb +12 -0
- data/app/models/devise_meteor/meteor_service.rb +16 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/devise_meteor.gemspec +37 -0
- data/lib/devise/strategies/meteor.rb +92 -0
- data/lib/devise_meteor/concerns/meteor_user_model.rb +148 -0
- data/lib/devise_meteor/engine.rb +10 -0
- data/lib/devise_meteor/railtie.rb +7 -0
- data/lib/devise_meteor/strategies/encrypter.rb +15 -0
- data/lib/devise_meteor/strategies/hasher.rb +91 -0
- data/lib/devise_meteor/strategies/strategy.rb +92 -0
- data/lib/devise_meteor/version.rb +3 -0
- data/lib/devise_meteor.rb +37 -0
- data/lib/generators/devise_meteor/install_generator.rb +16 -0
- data/lib/generators/templates/meteor_initializer.rb +12 -0
- data/spec/factories/users.rb +19 -0
- data/spec/models/meteor_authentication_spec.rb +261 -0
- data/spec/rails_helper.rb +72 -0
- data/spec/spec_helper.rb +92 -0
- data/spec/support/api_macros.rb +30 -0
- data/spec/support/controller_macros.rb +18 -0
- data/spec/support/devise_macros.rb +58 -0
- data/spec/support/omniauth_macros.rb +44 -0
- data/spec/support/request_macros.rb +13 -0
- data/spec/test_app/README.rdoc +3 -0
- data/spec/test_app/Rakefile +6 -0
- data/spec/test_app/app/assets/javascripts/application.js +13 -0
- data/spec/test_app/app/assets/stylesheets/application.css +15 -0
- data/spec/test_app/app/controllers/application_controller.rb +5 -0
- data/spec/test_app/app/controllers/products_controller.rb +89 -0
- data/spec/test_app/app/helpers/application_helper.rb +2 -0
- data/spec/test_app/app/models/user.rb +43 -0
- data/spec/test_app/app/views/layouts/application.html.erb +14 -0
- data/spec/test_app/app/views/products/_form.html.erb +29 -0
- data/spec/test_app/app/views/products/edit.html.erb +6 -0
- data/spec/test_app/app/views/products/index.html.erb +33 -0
- data/spec/test_app/app/views/products/new.html.erb +5 -0
- data/spec/test_app/app/views/products/show.html.erb +25 -0
- data/spec/test_app/bin/bundle +3 -0
- data/spec/test_app/bin/rails +4 -0
- data/spec/test_app/bin/rake +4 -0
- data/spec/test_app/bin/setup +29 -0
- data/spec/test_app/config/application.rb +28 -0
- data/spec/test_app/config/boot.rb +5 -0
- data/spec/test_app/config/environment.rb +5 -0
- data/spec/test_app/config/environments/development.rb +38 -0
- data/spec/test_app/config/environments/production.rb +77 -0
- data/spec/test_app/config/environments/test.rb +45 -0
- data/spec/test_app/config/initializers/assets.rb +11 -0
- data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_app/config/initializers/cookies_serializer.rb +3 -0
- data/spec/test_app/config/initializers/devise.rb +268 -0
- data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/test_app/config/initializers/inflections.rb +16 -0
- data/spec/test_app/config/initializers/mime_types.rb +4 -0
- data/spec/test_app/config/initializers/secret_token.rb +3 -0
- data/spec/test_app/config/initializers/session_store.rb +3 -0
- data/spec/test_app/config/initializers/wrap_parameters.rb +9 -0
- data/spec/test_app/config/locales/en.yml +23 -0
- data/spec/test_app/config/mongoid.yml +80 -0
- data/spec/test_app/config/routes.rb +5 -0
- data/spec/test_app/config/secrets.yml +22 -0
- data/spec/test_app/config.ru +4 -0
- data/spec/test_app/lib/tasks/cucumber.rake +65 -0
- data/spec/test_app/log/test.log +23511 -0
- data/spec/test_app/public/404.html +67 -0
- data/spec/test_app/public/422.html +67 -0
- data/spec/test_app/public/500.html +66 -0
- data/spec/test_app/public/favicon.ico +0 -0
- metadata +350 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
module DeviseMeteor
|
2
|
+
module Encrypter
|
3
|
+
|
4
|
+
def self.digest(password)
|
5
|
+
sha256_hasher = DeviseMeteor::BCryptSHA256Hasher.new
|
6
|
+
sha256_hasher.encode(password, sha256_hasher.salt)
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
def self.compare(password, encrypted_password)
|
11
|
+
sha256_hasher = DeviseMeteor::BCryptSHA256Hasher.new
|
12
|
+
sha256_hasher.verify(password, encrypted_password)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "base64"
|
2
|
+
require "bcrypt"
|
3
|
+
require "openssl"
|
4
|
+
|
5
|
+
module DeviseMeteor
|
6
|
+
class Hasher
|
7
|
+
attr_reader :algorithm
|
8
|
+
|
9
|
+
# Returns salt value to be used for hashing.
|
10
|
+
#
|
11
|
+
# @return [String] random salt value.
|
12
|
+
def salt
|
13
|
+
SecureRandom.hex(9)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns if the given password match the encoded password.
|
17
|
+
#
|
18
|
+
# @param [String] password in plain text
|
19
|
+
# @param [String] encoded password to be matched
|
20
|
+
# @return [Boolean] if password match encoded password.
|
21
|
+
def verify(password, encoded)
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns given password encoded with the given salt.
|
26
|
+
#
|
27
|
+
# @param [String] password in plain text
|
28
|
+
# @param [String] salt to be used during hashing
|
29
|
+
# @return [String] given password hashed using the given salt
|
30
|
+
def encode(password, salt)
|
31
|
+
raise NotImplementedError
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns if given encoded password needs to be updated.
|
35
|
+
#
|
36
|
+
# @param [String] encoded password
|
37
|
+
# @return [Boolean] if encoded password needs to be updated
|
38
|
+
def must_update(encoded)
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def constant_time_compare(a, b)
|
45
|
+
check = a.bytesize ^ b.bytesize
|
46
|
+
a.bytes.zip(b.bytes) { |x, y| check |= x ^ y }
|
47
|
+
check == 0
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# BCryptSHA256Hasher implements a BCrypt password hasher using SHA256.
|
52
|
+
class BCryptSHA256Hasher < Hasher
|
53
|
+
def initialize
|
54
|
+
@algorithm = :bcrypt_sha256
|
55
|
+
@cost = 10
|
56
|
+
@digest = OpenSSL::Digest::SHA256.new
|
57
|
+
end
|
58
|
+
|
59
|
+
def salt
|
60
|
+
BCrypt::Engine.generate_salt(@cost)
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_password_string(password)
|
64
|
+
@digest.digest(password) unless @digest.nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
def encode(password, salt)
|
68
|
+
password = get_password_string(password)
|
69
|
+
hash = BCrypt::Engine.hash_secret(password, salt)
|
70
|
+
return hash
|
71
|
+
end
|
72
|
+
|
73
|
+
def verify(password, encoded)
|
74
|
+
password_digest = get_password_string(password)
|
75
|
+
hash = BCrypt::Engine.hash_secret(password_digest, encoded)
|
76
|
+
Devise.secure_compare(encoded, hash)
|
77
|
+
|
78
|
+
constant_time_compare(encoded, hash)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
# BCryptHasher implements a BCrypt password hasher.
|
84
|
+
class BCryptHasher < BCryptSHA256Hasher
|
85
|
+
def initialize
|
86
|
+
@algorithm = :bcrypt
|
87
|
+
@cost = 10
|
88
|
+
@digest = nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'devise/strategies/authenticatable'
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Strategies
|
5
|
+
class Meteor < Authenticatable
|
6
|
+
|
7
|
+
def valid?
|
8
|
+
valid_for_params_auth? || valid_for_http_auth?
|
9
|
+
end
|
10
|
+
|
11
|
+
def authenticate!
|
12
|
+
self.password = params_auth_hash[:password]
|
13
|
+
|
14
|
+
# search for user email
|
15
|
+
devise_resource = valid_for_params_auth? && mapping.to.find_for_database_authentication(authentication_hash)
|
16
|
+
meteor_resource = User.where(:emails.elem_match => {address: params_auth_hash[:email]}).first unless devise_resource
|
17
|
+
resource = devise_resource || meteor_resource
|
18
|
+
|
19
|
+
return fail!(:not_found_in_database) unless resource
|
20
|
+
|
21
|
+
# before continuing authentication process
|
22
|
+
# check existing passwords and synchronize them
|
23
|
+
if meteor_auth_missing?(resource)
|
24
|
+
# when already devise credentials stored
|
25
|
+
# assign them to devise_meteor fields
|
26
|
+
new_hashed_password = User.new(:password => password).encrypted_password
|
27
|
+
resource.services.set(password: {bcrypt: new_hashed_password})
|
28
|
+
|
29
|
+
elsif devise_auth_missing?(resource)
|
30
|
+
# when user registered through devise_meteor
|
31
|
+
# and credentials for devise not present
|
32
|
+
email = params_auth_hash[:email]
|
33
|
+
crypt = resource.services.password[:bcrypt]
|
34
|
+
|
35
|
+
unless resource.update_attributes(encrypted_password: crypt, email: email)
|
36
|
+
fail(resource.unauthenticated_message)
|
37
|
+
end
|
38
|
+
resource.reload
|
39
|
+
|
40
|
+
elsif both_auth_present?(resource)
|
41
|
+
#when both passwords already set
|
42
|
+
else
|
43
|
+
return pass
|
44
|
+
end
|
45
|
+
|
46
|
+
# now do validation
|
47
|
+
# this code is copied from Devise::Strategies::DatabaseAuthenticable
|
48
|
+
encrypted = false
|
49
|
+
if validate(resource) { encrypted = true; resource.valid_password?(password) }
|
50
|
+
remember_me(resource)
|
51
|
+
resource.after_database_authentication
|
52
|
+
success!(resource)
|
53
|
+
end
|
54
|
+
|
55
|
+
mapping.to.new.password = password if !encrypted && Devise.paranoid
|
56
|
+
fail(:not_found_in_database) unless resource
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def both_auth_present?(resource)
|
62
|
+
has_a_meteor_password?(resource) && has_a_devise_password?(resource)
|
63
|
+
end
|
64
|
+
|
65
|
+
def devise_auth_missing?(resource)
|
66
|
+
has_a_meteor_password?(resource) && !has_a_devise_password?(resource)
|
67
|
+
end
|
68
|
+
|
69
|
+
def meteor_auth_missing?(resource)
|
70
|
+
has_a_devise_password?(resource) && !has_a_meteor_password?(resource)
|
71
|
+
end
|
72
|
+
|
73
|
+
def has_a_devise_password?(resource)
|
74
|
+
resource.encrypted_password.present?
|
75
|
+
end
|
76
|
+
|
77
|
+
def has_a_meteor_password?(resource)
|
78
|
+
resource.services.password.present?
|
79
|
+
end
|
80
|
+
|
81
|
+
# if you migrate from some other strategies than bcrypt
|
82
|
+
def legacy_authenticates?(resource, password)
|
83
|
+
# resource.encrypted_password == encrypt(resource, password)
|
84
|
+
end
|
85
|
+
|
86
|
+
def encrypt(resource, password)
|
87
|
+
# some old strategies code
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'devise_meteor/engine'
|
2
|
+
|
3
|
+
|
4
|
+
require "devise_meteor/version"
|
5
|
+
|
6
|
+
require 'rails'
|
7
|
+
|
8
|
+
require 'devise_meteor/railtie' if defined?(Rails)
|
9
|
+
require 'devise_meteor/railtie'
|
10
|
+
|
11
|
+
require 'devise'
|
12
|
+
require 'devise_meteor/strategies/encrypter'
|
13
|
+
require 'devise_meteor/strategies/hasher'
|
14
|
+
require 'devise/strategies/meteor'
|
15
|
+
|
16
|
+
require 'devise_meteor/concerns/meteor_user_model'
|
17
|
+
|
18
|
+
module DeviseMeteor
|
19
|
+
|
20
|
+
# enable configuration
|
21
|
+
class << self
|
22
|
+
attr_accessor :configuration
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.configure
|
26
|
+
self.configuration ||= Configuration.new
|
27
|
+
yield(configuration)
|
28
|
+
end
|
29
|
+
|
30
|
+
class Configuration
|
31
|
+
attr_accessor :option
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@option = 'default_option'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module DeviseMeteor
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
|
5
|
+
source_root File.expand_path("../../templates", __FILE__)
|
6
|
+
|
7
|
+
desc "Creates initializer for devise_meteor specific config"
|
8
|
+
|
9
|
+
def copy_initializer
|
10
|
+
template "meteor_initializer.rb", "config/initializers/devise_meteor.rb"
|
11
|
+
|
12
|
+
puts "Added initializer to your app."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
|
3
|
+
factory :user do
|
4
|
+
#after(:build) { |u| u.password_confirmation = u.password = mypassword }
|
5
|
+
email { Faker::Internet.email }
|
6
|
+
password "password"
|
7
|
+
password_confirmation "password"
|
8
|
+
|
9
|
+
factory :confirmed_user do
|
10
|
+
confirmed_at Date.today
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
factory :invalid_user, parent: :user do
|
15
|
+
email { Faker::Internet.email }
|
16
|
+
password "short"
|
17
|
+
password_confirmation "short"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe DeviseMeteor::MeteorUserModel do
|
4
|
+
|
5
|
+
let(:meteor_user_attributes) {
|
6
|
+
|
7
|
+
{
|
8
|
+
'_id' => "633DYLkePqv2xMbDi",
|
9
|
+
"createdAt" => Time.now,
|
10
|
+
"emails" => [
|
11
|
+
{"address" => Faker::Internet.email,
|
12
|
+
"verified" => true}
|
13
|
+
],
|
14
|
+
"profile" => {"firstName" => "DemoFirstName",
|
15
|
+
"lastName" => "DemoLastName"
|
16
|
+
},
|
17
|
+
"services" => {
|
18
|
+
"password" => {
|
19
|
+
"bcrypt" => "$2a$10$4my6JyO3FxMDr4xm24k2Kev7Jqu0E.8KecXEv8fHhZQMSCHrQCUM."
|
20
|
+
},
|
21
|
+
"resume" => {
|
22
|
+
"loginTokens" => [
|
23
|
+
{
|
24
|
+
"when" => Time.now,
|
25
|
+
"hashedToken" => "fPtV4ud7WzT9nKwgfRb56MwI8GORe3kGc4cO6FfM8xY="
|
26
|
+
}
|
27
|
+
]
|
28
|
+
}
|
29
|
+
},
|
30
|
+
"username" => "demouser"
|
31
|
+
}
|
32
|
+
|
33
|
+
}
|
34
|
+
|
35
|
+
describe "Meteor User attribute mapping" do
|
36
|
+
|
37
|
+
it "calls meteor_map_attributes before saving" do
|
38
|
+
user = User.new
|
39
|
+
|
40
|
+
expect(user).to receive(:meteor_map_attributes)
|
41
|
+
user.save
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
before :each do
|
46
|
+
@user = create :user
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'emails' do
|
50
|
+
|
51
|
+
it 'should be an array' do
|
52
|
+
expect(@user.emails).to be_an Array
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'when changing the email' do
|
56
|
+
|
57
|
+
it 'does not verify on new unconfirmed' do
|
58
|
+
@user.confirm
|
59
|
+
@user.email = "test@test.com"
|
60
|
+
result2 = {address: @user.email, verified: false}
|
61
|
+
|
62
|
+
@user.save!
|
63
|
+
expect(@user.emails).to include result2
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'does verify on confirm' do
|
67
|
+
@user.confirm
|
68
|
+
@user.email = "test@test.com"
|
69
|
+
@user.save!
|
70
|
+
result2 = {address: @user.email, verified: true}
|
71
|
+
|
72
|
+
@user.confirm
|
73
|
+
|
74
|
+
expect(@user.emails).to include result2
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'does not overwrite old email' do
|
78
|
+
result1 = {address: @user.email, verified: true}
|
79
|
+
|
80
|
+
@user.confirm
|
81
|
+
@user.email = "test@test.com"
|
82
|
+
result2 = {address: @user.email, verified: false}
|
83
|
+
|
84
|
+
@user.save!
|
85
|
+
expect(@user.emails).to include result1
|
86
|
+
expect(@user.emails).to include result2
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'does not have duplicated emails with different verified status' do
|
90
|
+
confirmed = {address: @user.email, verified: true}
|
91
|
+
@user.confirm
|
92
|
+
|
93
|
+
@user.email = "another@email.com"
|
94
|
+
unconfirmed = {address: @user.email, verified: false}
|
95
|
+
@user.save!
|
96
|
+
expect(@user.emails).to include confirmed
|
97
|
+
expect(@user.emails).to include unconfirmed
|
98
|
+
expect(@user.emails.size).to eql 2
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'verified' do
|
104
|
+
|
105
|
+
specify 'on new email should be false' do
|
106
|
+
result = {address: @user.email, verified: false}
|
107
|
+
|
108
|
+
expect(@user.emails).to include(result)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'on confirmed email should be true' do
|
112
|
+
result = {address: @user.email, verified: true}
|
113
|
+
|
114
|
+
@user.confirm
|
115
|
+
|
116
|
+
expect(@user.emails).to include(result)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'createdAt' do
|
124
|
+
it 'should match created_at' do
|
125
|
+
expect(@user.created_at).to eql @user.createdAt
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'profile' do
|
130
|
+
|
131
|
+
it 'has a relation to Profile' do
|
132
|
+
expect(@user.profile).to be_a DeviseMeteor::MeteorProfile
|
133
|
+
end
|
134
|
+
|
135
|
+
describe 'name' do
|
136
|
+
|
137
|
+
it 'writes into name field' do
|
138
|
+
name = "John Doe"
|
139
|
+
@user.update_attribute(:name, name)
|
140
|
+
expect(User.last.profile.name).to eql name
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'reads from name field' do
|
144
|
+
name = "John Doe"
|
145
|
+
@user.update_attribute(:name, name)
|
146
|
+
expect(@user.name).to eql @user.profile.name
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe 'username' do
|
151
|
+
|
152
|
+
it 'writes into name field' do
|
153
|
+
username = "John Doe"
|
154
|
+
@user.update_attribute(:username, username)
|
155
|
+
expect(User.last.profile.username).to eql username
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'reads from name field' do
|
159
|
+
username = "John Doe"
|
160
|
+
@user.update_attribute(:username, username)
|
161
|
+
expect(@user.username).to eql @user.profile.username
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
describe 'services' do
|
168
|
+
|
169
|
+
# this example is copy pasted from the devise_meteor documentation
|
170
|
+
# http://docs.meteor.com/#/full/meteor_users
|
171
|
+
# bcrypt: password decrypted is "asdfasdf"
|
172
|
+
let(:valid_services_hash) {
|
173
|
+
{"password" => {
|
174
|
+
"bcrypt" => "$2a$10$4my6JyO3FxMDr4xm24k2Kev7Jqu0E.8KecXEv8fHhZQMSCHrQCUM."
|
175
|
+
},
|
176
|
+
"facebook" => {
|
177
|
+
"id" => "709050",
|
178
|
+
"accessToken" => "S0M3_R34LLY-CMPLX-T0K3N"
|
179
|
+
},
|
180
|
+
"resume" => {
|
181
|
+
"loginTokens" => [
|
182
|
+
{"token" => "4no7eR-c0mpl3x-c0d3-with-numb3r5",
|
183
|
+
"when" => 1234567890}
|
184
|
+
]
|
185
|
+
}}
|
186
|
+
}
|
187
|
+
|
188
|
+
let(:decrypted_password) {
|
189
|
+
'asdfasdf'
|
190
|
+
}
|
191
|
+
|
192
|
+
it 'must have a service relation' do
|
193
|
+
expect(@user.services).to be_a DeviseMeteor::MeteorService
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'password' do
|
197
|
+
before :each do
|
198
|
+
@user.confirm
|
199
|
+
end
|
200
|
+
|
201
|
+
let(:valid_password_hash) {
|
202
|
+
valid_services_hash[:password]
|
203
|
+
}
|
204
|
+
|
205
|
+
context 'changed by devise' do
|
206
|
+
it 'writes password on creation' do
|
207
|
+
expect(User.last.services.password[:bcrypt]).to eql @user.services.password[:bcrypt]
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'writes new password also to session.password' do
|
211
|
+
new_password = 'N3W_P455W0RD'
|
212
|
+
|
213
|
+
@user.password = new_password
|
214
|
+
@user.password_confirmation = new_password
|
215
|
+
@user.save
|
216
|
+
|
217
|
+
expect(User.last.services.password[:bcrypt]).to eql @user.services.password[:bcrypt]
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'tries to use the meteors password' do
|
221
|
+
password = @user.services.password[:bcrypt]
|
222
|
+
true
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
context 'facebook' do
|
230
|
+
|
231
|
+
it 'allows multiple provider assignment' do
|
232
|
+
@user.services.update_attributes(facebook: valid_services_hash['facebook'])
|
233
|
+
|
234
|
+
expect(User.last.services.facebook[:id]).to eq valid_services_hash['facebook']['id']
|
235
|
+
expect(User.last.services.facebook[:id]).to eq valid_services_hash['facebook']['id']
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'allows single provider assignment' do
|
239
|
+
@user.services.update_attribute(:facebook, valid_services_hash['facebook'])
|
240
|
+
|
241
|
+
expect(User.last.services.facebook[:id]).to eq valid_services_hash['facebook']['id']
|
242
|
+
expect(User.last.services.facebook[:accessToken]).to eq valid_services_hash['facebook']['accessToken']
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'allows to change provider data' do
|
246
|
+
new_facebook_hash = {id: '12345678', accessToken: 'New_Access_token'}
|
247
|
+
|
248
|
+
@user.services.update_attribute(:facebook, valid_services_hash['facebook'])
|
249
|
+
expect(User.last.services.facebook[:id]).to eq valid_services_hash['facebook']['id']
|
250
|
+
expect(User.last.services.facebook[:accessToken]).to eq valid_services_hash['facebook']['accessToken']
|
251
|
+
|
252
|
+
@user.services.update_attribute(:facebook, new_facebook_hash)
|
253
|
+
|
254
|
+
expect(User.last.services.facebook[:id]).to eq new_facebook_hash[:id]
|
255
|
+
expect(User.last.services.facebook[:accessToken]).to eq new_facebook_hash[:accessToken]
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|