stn-simple_token_authentication 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +270 -0
  4. data/Rakefile +61 -0
  5. data/doc/README.md +18 -0
  6. data/lib/simple_token_authentication.rb +58 -0
  7. data/lib/simple_token_authentication/acts_as_token_authenticatable.rb +49 -0
  8. data/lib/simple_token_authentication/acts_as_token_authentication_handler.rb +22 -0
  9. data/lib/simple_token_authentication/adapter.rb +7 -0
  10. data/lib/simple_token_authentication/adapters/active_record_adapter.rb +14 -0
  11. data/lib/simple_token_authentication/adapters/mongoid_adapter.rb +14 -0
  12. data/lib/simple_token_authentication/adapters/rails_adapter.rb +14 -0
  13. data/lib/simple_token_authentication/adapters/rails_api_adapter.rb +18 -0
  14. data/lib/simple_token_authentication/configuration.rb +45 -0
  15. data/lib/simple_token_authentication/entities_manager.rb +10 -0
  16. data/lib/simple_token_authentication/entity.rb +64 -0
  17. data/lib/simple_token_authentication/fallback_authentication_handler.rb +11 -0
  18. data/lib/simple_token_authentication/sign_in_handler.rb +19 -0
  19. data/lib/simple_token_authentication/token_authentication_handler.rb +149 -0
  20. data/lib/simple_token_authentication/token_comparator.rb +20 -0
  21. data/lib/simple_token_authentication/token_generator.rb +9 -0
  22. data/lib/simple_token_authentication/version.rb +3 -0
  23. data/lib/tasks/simple_token_authentication_tasks.rake +4 -0
  24. data/spec/configuration/action_controller_callbacks_options_spec.rb +53 -0
  25. data/spec/configuration/fallback_to_devise_option_spec.rb +128 -0
  26. data/spec/configuration/header_names_option_spec.rb +463 -0
  27. data/spec/configuration/sign_in_token_option_spec.rb +92 -0
  28. data/spec/lib/simple_token_authentication/acts_as_token_authenticatable_spec.rb +108 -0
  29. data/spec/lib/simple_token_authentication/acts_as_token_authentication_handler_spec.rb +127 -0
  30. data/spec/lib/simple_token_authentication/adapter_spec.rb +19 -0
  31. data/spec/lib/simple_token_authentication/adapters/active_record_adapter_spec.rb +21 -0
  32. data/spec/lib/simple_token_authentication/adapters/mongoid_adapter_spec.rb +21 -0
  33. data/spec/lib/simple_token_authentication/adapters/rails_adapter_spec.rb +21 -0
  34. data/spec/lib/simple_token_authentication/adapters/rails_api_adapter_spec.rb +43 -0
  35. data/spec/lib/simple_token_authentication/configuration_spec.rb +133 -0
  36. data/spec/lib/simple_token_authentication/entities_manager_spec.rb +67 -0
  37. data/spec/lib/simple_token_authentication/entity_spec.rb +190 -0
  38. data/spec/lib/simple_token_authentication/errors_spec.rb +8 -0
  39. data/spec/lib/simple_token_authentication/fallback_authentication_handler_spec.rb +24 -0
  40. data/spec/lib/simple_token_authentication/sign_in_handler_spec.rb +43 -0
  41. data/spec/lib/simple_token_authentication/token_authentication_handler_spec.rb +351 -0
  42. data/spec/lib/simple_token_authentication/token_comparator_spec.rb +19 -0
  43. data/spec/lib/simple_token_authentication/token_generator_spec.rb +19 -0
  44. data/spec/lib/simple_token_authentication_spec.rb +181 -0
  45. data/spec/spec_helper.rb +15 -0
  46. data/spec/support/dummy_classes_helper.rb +80 -0
  47. data/spec/support/spec_for_adapter.rb +10 -0
  48. data/spec/support/spec_for_authentication_handler_interface.rb +8 -0
  49. data/spec/support/spec_for_configuration_option_interface.rb +28 -0
  50. data/spec/support/spec_for_entities_manager_interface.rb +8 -0
  51. data/spec/support/spec_for_sign_in_handler_interface.rb +8 -0
  52. data/spec/support/spec_for_token_comparator_interface.rb +8 -0
  53. data/spec/support/spec_for_token_generator_interface.rb +8 -0
  54. data/spec/support/specs_for_token_authentication_handler_interface.rb +8 -0
  55. metadata +250 -0
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleTokenAuthentication::Configuration do
4
+
5
+
6
+ context 'when included in any class' do
7
+
8
+ before(:each) do
9
+ SimpleTokenAuthentication.const_set(:ConfigurableClass, Class.new)
10
+ klass = SimpleTokenAuthentication::ConfigurableClass
11
+ klass.send :include, SimpleTokenAuthentication::Configuration
12
+ @subject = klass.new
13
+ end
14
+
15
+ after(:each) do
16
+ SimpleTokenAuthentication.send(:remove_const, :ConfigurableClass)
17
+ end
18
+
19
+ describe 'provides #controller_adapters which' do
20
+
21
+ it_behaves_like 'a configuration option', 'controller_adapters'
22
+
23
+ it "defauts to ['rails', 'rails_api']", private: true do
24
+ expect(@subject.controller_adapters).to eq ['rails', 'rails_api']
25
+ end
26
+ end
27
+
28
+ describe 'provides #model_adapters which' do
29
+
30
+ it_behaves_like 'a configuration option', 'model_adapters'
31
+
32
+ it "defauts to ['active_record', 'mongoid']", private: true do
33
+ expect(@subject.model_adapters).to eq ['active_record', 'mongoid']
34
+ end
35
+ end
36
+
37
+ describe 'provides #adapters_dependencies which' do
38
+
39
+ it_behaves_like 'a configuration option', 'adapters_dependencies'
40
+
41
+ it 'lists the supported adapters dependencies by default', private: true do
42
+ expect(@subject.adapters_dependencies['active_record']).to eq 'ActiveRecord::Base'
43
+ expect(@subject.adapters_dependencies['mongoid']).to eq 'Mongoid::Document'
44
+ expect(@subject.adapters_dependencies['rails']).to eq 'ActionController::Base'
45
+ expect(@subject.adapters_dependencies['rails_api']).to eq 'ActionController::API'
46
+ end
47
+ end
48
+
49
+ describe 'provides #header_names which', header_names_option: true do
50
+
51
+ it_behaves_like 'a configuration option', 'header_names'
52
+
53
+ it 'defauts to {}', public: true do
54
+ expect(@subject.header_names).to eq({})
55
+ end
56
+ end
57
+
58
+ describe 'provides #sign_in_token which', sign_in_token_option: true do
59
+
60
+ it_behaves_like 'a configuration option', 'sign_in_token'
61
+
62
+ it 'defauts to false', public: true do
63
+ expect(@subject.sign_in_token).to eq false
64
+ end
65
+ end
66
+
67
+ describe 'does provide #fallback which', fallback_option: true do
68
+
69
+ it 'is readable', private: true do
70
+ expect(@subject).to respond_to :fallback
71
+ end
72
+
73
+ it 'can\'t be written', private: true do
74
+ expect(@subject).not_to respond_to :fallback=
75
+ end
76
+
77
+ it 'defaults to :devise', private: true do
78
+ expect(@subject.fallback).to eq :devise
79
+ end
80
+ end
81
+
82
+ describe 'provides #parse_options which' do
83
+
84
+ describe 'replaces :fallback_to_devise by :fallback' do
85
+
86
+ context 'when :fallback option is set' do
87
+
88
+ it 'removes :fallback_to_devise', private: true do
89
+ options = { fallback: 'anything', fallback_to_devise: true }
90
+ expect(@subject.parse_options(options)).to eq({ fallback: 'anything' })
91
+ end
92
+ end
93
+
94
+ context 'when :fallback option is omitted' do
95
+ context 'and :fallback_to_devise is true' do
96
+
97
+ it 'replaces it by fallback: :devise', private: true do
98
+ options = { fallback_to_devise: true }
99
+ expect(@subject.parse_options(options)).to eq({ fallback: :devise })
100
+ end
101
+ end
102
+
103
+ context 'and :fallback_to_devise is false' do
104
+
105
+ context 'when :fallback default is :devise' do
106
+ it 'replaces :fallback_to_devise by fallback: :none', private: true do
107
+ allow(SimpleTokenAuthentication).to receive(:fallback).and_return(:devise)
108
+ options = { fallback_to_devise: false }
109
+ expect(@subject.parse_options(options)).to eq({ fallback: :none })
110
+ end
111
+ end
112
+
113
+ context 'when :fallback default is not :devise' do
114
+ it 'replaces :fallback_to_devise by :fallback default', private: true do
115
+ allow(SimpleTokenAuthentication).to receive(:fallback).and_return('anything_but_devise')
116
+ options = { fallback_to_devise: false }
117
+ expect(@subject.parse_options(options)).to eq({ fallback: 'anything_but_devise' })
118
+ end
119
+ end
120
+ end
121
+
122
+ context 'and :fallback_to_devise is omitted' do
123
+ it 'sets :fallback to its default value', private: true do
124
+ allow(SimpleTokenAuthentication).to receive(:fallback).and_return('any_value')
125
+ options = {}
126
+ expect(@subject.parse_options(options)).to eq({ fallback: 'any_value' })
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleTokenAuthentication::EntitiesManager do
4
+
5
+ # The 'model' argument is quite vague, as it is for Entity;
6
+ # let's do nothing to solve that undefinition for now.
7
+
8
+ it_behaves_like 'an entities manager'
9
+
10
+ describe '#find_or_create_entity' do
11
+
12
+ before(:each) do
13
+ entity = double()
14
+ allow(entity).to receive(:new).and_return('an Entity instance')
15
+ stub_const('SimpleTokenAuthentication::Entity', entity)
16
+
17
+ super_user = double()
18
+ allow(super_user).to receive(:name) # any Ruby class has a name
19
+ stub_const('SuperUser', super_user)
20
+ end
21
+
22
+ context 'when a model is provided for the first time' do
23
+
24
+ it 'creates an Entity instance for the model', private: true do
25
+ expect(SimpleTokenAuthentication::Entity).to receive(:new).with(SuperUser)
26
+ expect(subject.find_or_create_entity(SuperUser)).to eq 'an Entity instance'
27
+ end
28
+
29
+ context 'even if Entity instances for other models exist', private: true do
30
+
31
+ before(:each) do
32
+ # define another model
33
+ admin = double()
34
+ allow(admin).to receive(:name).and_return('Admin')
35
+ stub_const('Admin', admin)
36
+ # ensure its Entity instance exists
37
+ subject.find_or_create_entity(Admin)
38
+ allow(SimpleTokenAuthentication::Entity).to receive(:new).and_return('some new Entity instance')
39
+ end
40
+
41
+ it 'creates an Entity instance for the model', private: true do
42
+ expect(SimpleTokenAuthentication::Entity).to receive(:new).with(SuperUser)
43
+ expect(subject.find_or_create_entity(SuperUser)).to eq 'some new Entity instance'
44
+ end
45
+ end
46
+ end
47
+
48
+ context 'when an Entity instance for that model already exists' do
49
+
50
+ before(:each) do
51
+ allow(SuperUser).to receive(:name).and_return('SuperUser')
52
+ subject.find_or_create_entity(SuperUser)
53
+
54
+ allow(SimpleTokenAuthentication::Entity).to receive(:new).and_return('some new Entity instance')
55
+ end
56
+
57
+ it 'returns that Entity instance', private: true do
58
+ expect(subject.find_or_create_entity(SuperUser)).to eq 'an Entity instance'
59
+ end
60
+
61
+ it 'does not create a new Entity instance', private: true do
62
+ expect(SimpleTokenAuthentication::Entity).not_to receive(:new).with(SuperUser)
63
+ subject.find_or_create_entity(SuperUser)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,190 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleTokenAuthentication::Entity do
4
+
5
+ before(:each) do
6
+ user = double()
7
+ allow(user).to receive(:name).and_return('SuperUser')
8
+ stub_const('SuperUser', user)
9
+
10
+ @subject = SimpleTokenAuthentication::Entity.new(SuperUser)
11
+ end
12
+
13
+ it 'responds to :model', protected: true do
14
+ expect(@subject).to respond_to :model
15
+ end
16
+
17
+ it 'responds to :name', protected: true do
18
+ expect(@subject).to respond_to :name
19
+ end
20
+
21
+ it 'responds to :name_underscore', protected: true do
22
+ expect(@subject).to respond_to :name_underscore
23
+ end
24
+
25
+ it 'responds to :token_header_name', protected: true do
26
+ expect(@subject).to respond_to :token_header_name
27
+ end
28
+
29
+ it 'responds to :identifier_header_name', protected: true do
30
+ expect(@subject).to respond_to :identifier_header_name
31
+ end
32
+
33
+ it 'responds to :token_param_name', protected: true do
34
+ expect(@subject).to respond_to :token_param_name
35
+ end
36
+
37
+ it 'responds to :identifier_param_name', protected: true do
38
+ expect(@subject).to respond_to :identifier_param_name
39
+ end
40
+
41
+ it 'responds to :get_token_from_params_or_headers', protected: true do
42
+ expect(@subject).to respond_to :get_token_from_params_or_headers
43
+ end
44
+
45
+ it 'responds to :get_identifier_from_params_or_headers', protected: true do
46
+ expect(@subject).to respond_to :get_identifier_from_params_or_headers
47
+ end
48
+
49
+ describe '#model' do
50
+ it 'is a constant', protected: true do
51
+ expect(@subject.model).to eq SuperUser
52
+ end
53
+ end
54
+
55
+ describe '#name' do
56
+ it 'is a camelized String', protected: true do
57
+ expect(@subject.name).to be_instance_of String
58
+ expect(@subject.name).to eq @subject.name.camelize
59
+ end
60
+ end
61
+
62
+ describe '#name_underscore', protected: true do
63
+ it 'is an underscored String' do
64
+ expect(@subject.name_underscore).to be_instance_of String
65
+ expect(@subject.name_underscore).to eq @subject.name_underscore.underscore
66
+ end
67
+ end
68
+
69
+ describe '#token_header_name', protected: true do
70
+ it 'is a String' do
71
+ expect(@subject.token_header_name).to be_instance_of String
72
+ end
73
+
74
+ it 'defines a non-standard header field' do
75
+ expect(@subject.token_header_name[0..1]).to eq 'X-'
76
+ end
77
+ end
78
+
79
+ describe '#identifier_header_name', protected: true do
80
+ it 'is a String' do
81
+ expect(@subject.identifier_header_name).to be_instance_of String
82
+ end
83
+
84
+ it 'defines a non-standard header field' do
85
+ expect(@subject.identifier_header_name[0..1]).to eq 'X-'
86
+ end
87
+ end
88
+
89
+ describe '#token_param_name', protected: true do
90
+ it 'is a Symbol' do
91
+ expect(@subject.token_param_name).to be_instance_of Symbol
92
+ end
93
+ end
94
+
95
+ describe '#identifier_param_name', protected: true do
96
+ it 'is a Symbol' do
97
+ expect(@subject.identifier_param_name).to be_instance_of Symbol
98
+ end
99
+ end
100
+
101
+ describe '#get_token_from_params_or_headers', protected: true do
102
+
103
+ context 'when a token is present in params' do
104
+
105
+ before(:each) do
106
+ @controller = double()
107
+ allow(@controller).to receive(:params).and_return({ super_user_token: 'The_ToKeN' })
108
+ end
109
+
110
+ it 'returns that token (String)' do
111
+ expect(@subject.get_token_from_params_or_headers(@controller)).to be_instance_of String
112
+ expect(@subject.get_token_from_params_or_headers(@controller)).to eq 'The_ToKeN'
113
+ end
114
+
115
+ context 'and another token is present in the headers' do
116
+
117
+ before(:each) do
118
+ allow(@controller).to receive_message_chain(:request, :headers)
119
+ .and_return({ 'X-SuperUser-Token' => 'HeAd3rs_ToKeN' })
120
+ end
121
+
122
+ it 'returns the params token' do
123
+ expect(@subject.get_token_from_params_or_headers(@controller)).to eq 'The_ToKeN'
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'when no token is present in params' do
129
+
130
+ context 'and a token is present in the headers' do
131
+
132
+ before(:each) do
133
+ @controller = double()
134
+ allow(@controller).to receive(:params).and_return({ super_user_token: '' })
135
+ allow(@controller).to receive_message_chain(:request, :headers)
136
+ .and_return({ 'X-SuperUser-Token' => 'HeAd3rs_ToKeN' })
137
+ end
138
+
139
+ it 'returns the headers token' do
140
+ expect(@subject.get_token_from_params_or_headers(@controller)).to eq 'HeAd3rs_ToKeN'
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ describe '#get_identifier_from_params_or_headers', protected: true do
147
+
148
+ context 'when an identifier is present in params' do
149
+
150
+ before(:each) do
151
+ @controller = double()
152
+ allow(@controller).to receive(:params).and_return({ super_user_email: 'alice@example.com' })
153
+ end
154
+
155
+ it 'returns that identifier (String)' do
156
+ expect(@subject.get_identifier_from_params_or_headers(@controller)).to be_instance_of String
157
+ expect(@subject.get_identifier_from_params_or_headers(@controller)).to eq 'alice@example.com'
158
+ end
159
+
160
+ context 'and another identifier is present in the headers' do
161
+
162
+ before(:each) do
163
+ allow(@controller).to receive_message_chain(:request, :headers)
164
+ .and_return({ 'X-SuperUser-Email' => 'bob@example.com' })
165
+ end
166
+
167
+ it 'returns the params identifier' do
168
+ expect(@subject.get_identifier_from_params_or_headers(@controller)).to eq 'alice@example.com'
169
+ end
170
+ end
171
+ end
172
+
173
+ context 'when no identifier is present in params' do
174
+
175
+ context 'and an identifier is present in the headers' do
176
+
177
+ before(:each) do
178
+ @controller = double()
179
+ allow(@controller).to receive(:params).and_return({ super_user_email: '' })
180
+ allow(@controller).to receive_message_chain(:request, :headers)
181
+ .and_return({ 'X-SuperUser-Email' => 'bob@example.com' })
182
+ end
183
+
184
+ it 'returns the headers identifier' do
185
+ expect(@subject.get_identifier_from_params_or_headers(@controller)).to eq 'bob@example.com'
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleTokenAuthentication::NoAdapterAvailableError do
4
+
5
+ it 'is a kind of LoadError', public: true do
6
+ expect(subject).to be_kind_of LoadError
7
+ end
8
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleTokenAuthentication::FallbackAuthenticationHandler do
4
+
5
+ it_behaves_like 'an authentication handler'
6
+
7
+ describe '#authenticate_entity!' do
8
+
9
+ it 'delegates authentication to Devise::Controllers::Helpers through a controller', private: true do
10
+ controller = double()
11
+ allow(controller).to receive(:authenticate_user!).and_return('Devise response.')
12
+
13
+ entity = double()
14
+ allow(entity).to receive_message_chain(:name_underscore).and_return('user')
15
+
16
+ # delegating consists in sending the message
17
+ expect(controller).to receive(:authenticate_user!)
18
+ response = subject.authenticate_entity!(controller, entity)
19
+
20
+ # and returning the response
21
+ expect(response).to eq 'Devise response.'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleTokenAuthentication::SignInHandler do
4
+
5
+ it_behaves_like 'a sign in handler'
6
+
7
+ describe '#sign_in' do
8
+
9
+ it 'delegates sign in to Devise::Controllers::SignInOut#sign_in through a controller', private: true do
10
+ controller = double()
11
+ allow(controller).to receive(:sign_in).with(:record, option: 'some_value').and_return('Devise response.')
12
+ allow(controller).to receive(:env).and_return({})
13
+
14
+ # delegating consists in sending the message
15
+ expect(controller).to receive(:sign_in)
16
+ response = subject.sign_in(controller, :record, option: 'some_value')
17
+
18
+ # and returning the response
19
+ expect(response).to eq 'Devise response.'
20
+ end
21
+
22
+ it 'integrates with Devise trackable', protected: true do
23
+ controller = double()
24
+ allow(controller).to receive(:sign_in).with(:record)
25
+ allow(controller).to receive(:integrate_with_devise_trackable!)
26
+
27
+ expect(subject).to receive(:integrate_with_devise_trackable!).with(controller)
28
+ subject.sign_in(controller, :record)
29
+ end
30
+ end
31
+
32
+ describe '#integrate_with_devise_trackable!' do
33
+
34
+ it 'ensures Devise trackable statistics are kept clean', private: true do
35
+ controller = double()
36
+ env = double()
37
+ allow(controller).to receive(:env).and_return(env)
38
+ expect(env).to receive(:[]=).with('devise.skip_trackable', true)
39
+
40
+ subject.send :integrate_with_devise_trackable!, controller
41
+ end
42
+ end
43
+ end