stn-simple_token_authentication 1.7.1

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.
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