authentication-logic 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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/bin/console +11 -0
  3. data/bin/setup +8 -0
  4. data/lib/auth/logic/acts_as_authentic/base.rb +118 -0
  5. data/lib/auth/logic/acts_as_authentic/email.rb +32 -0
  6. data/lib/auth/logic/acts_as_authentic/logged_in_status.rb +87 -0
  7. data/lib/auth/logic/acts_as_authentic/login.rb +65 -0
  8. data/lib/auth/logic/acts_as_authentic/magic_columns.rb +40 -0
  9. data/lib/auth/logic/acts_as_authentic/password.rb +362 -0
  10. data/lib/auth/logic/acts_as_authentic/perishable_token.rb +125 -0
  11. data/lib/auth/logic/acts_as_authentic/persistence_token.rb +72 -0
  12. data/lib/auth/logic/acts_as_authentic/queries/case_sensitivity.rb +55 -0
  13. data/lib/auth/logic/acts_as_authentic/queries/find_with_case.rb +85 -0
  14. data/lib/auth/logic/acts_as_authentic/session_maintenance.rb +189 -0
  15. data/lib/auth/logic/acts_as_authentic/single_access_token.rb +85 -0
  16. data/lib/auth/logic/config.rb +41 -0
  17. data/lib/auth/logic/controller_adapters/abstract_adapter.rb +121 -0
  18. data/lib/auth/logic/controller_adapters/rack_adapter.rb +74 -0
  19. data/lib/auth/logic/controller_adapters/rails_adapter.rb +49 -0
  20. data/lib/auth/logic/controller_adapters/sinatra_adapter.rb +69 -0
  21. data/lib/auth/logic/cookie_credentials.rb +65 -0
  22. data/lib/auth/logic/crypto_providers/bcrypt.rb +116 -0
  23. data/lib/auth/logic/crypto_providers/md5/v2.rb +37 -0
  24. data/lib/auth/logic/crypto_providers/md5.rb +38 -0
  25. data/lib/auth/logic/crypto_providers/scrypt.rb +96 -0
  26. data/lib/auth/logic/crypto_providers/sha1/v2.rb +42 -0
  27. data/lib/auth/logic/crypto_providers/sha1.rb +43 -0
  28. data/lib/auth/logic/crypto_providers/sha256/v2.rb +60 -0
  29. data/lib/auth/logic/crypto_providers/sha256.rb +61 -0
  30. data/lib/auth/logic/crypto_providers/sha512/v2.rb +41 -0
  31. data/lib/auth/logic/crypto_providers/sha512.rb +40 -0
  32. data/lib/auth/logic/crypto_providers.rb +89 -0
  33. data/lib/auth/logic/errors.rb +52 -0
  34. data/lib/auth/logic/i18n/translator.rb +20 -0
  35. data/lib/auth/logic/i18n.rb +100 -0
  36. data/lib/auth/logic/random.rb +18 -0
  37. data/lib/auth/logic/session/base.rb +2205 -0
  38. data/lib/auth/logic/session/magic_column/assigns_last_request_at.rb +49 -0
  39. data/lib/auth/logic/test_case/mock_api_controller.rb +53 -0
  40. data/lib/auth/logic/test_case/mock_controller.rb +59 -0
  41. data/lib/auth/logic/test_case/mock_cookie_jar.rb +112 -0
  42. data/lib/auth/logic/test_case/mock_logger.rb +14 -0
  43. data/lib/auth/logic/test_case/mock_request.rb +36 -0
  44. data/lib/auth/logic/test_case/rails_request_adapter.rb +40 -0
  45. data/lib/auth/logic/test_case.rb +216 -0
  46. data/lib/auth/logic/version.rb +7 -0
  47. data/lib/auth/logic.rb +46 -0
  48. metadata +426 -0
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authentication
4
+ module Logic
5
+ module Session
6
+ module MagicColumn
7
+ # Assigns the current time to the `last_request_at` attribute.
8
+ #
9
+ # 1. The `last_request_at` column must exist
10
+ # 2. Assignment can be disabled on a per-controller basis
11
+ # 3. Assignment will not happen more often than `last_request_at_threshold`
12
+ # seconds.
13
+ #
14
+ # - current_time - a `Time`
15
+ # - record - eg. a `User`
16
+ # - controller - an `Authentication::Logic::ControllerAdapters::AbstractAdapter`
17
+ # - last_request_at_threshold - integer - seconds
18
+ #
19
+ # @api private
20
+ class AssignsLastRequestAt
21
+ def initialize(current_time, record, controller, last_request_at_threshold)
22
+ @current_time = current_time
23
+ @record = record
24
+ @controller = controller
25
+ @last_request_at_threshold = last_request_at_threshold
26
+ end
27
+
28
+ def assign
29
+ return unless assign?
30
+
31
+ @record.last_request_at = @current_time
32
+ end
33
+
34
+ private
35
+
36
+ # @api private
37
+ def assign?
38
+ @record &&
39
+ @record.class.column_names.include?("last_request_at") &&
40
+ @controller.last_request_update_allowed? && (
41
+ @record.last_request_at.blank? ||
42
+ @last_request_at_threshold.to_i.seconds.ago >= @record.last_request_at
43
+ )
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authentication
4
+ module Logic
5
+ module TestCase
6
+ # Basically acts like an API controller but doesn't do anything.
7
+ # Authentication::Logic can interact with this, do it's thing and then you can look at
8
+ # the controller object to see if anything changed.
9
+ class MockAPIController < ControllerAdapters::AbstractAdapter
10
+ attr_writer :request_content_type
11
+
12
+ def initialize; end
13
+
14
+ # Expected API controller has no cookies method.
15
+ undef :cookies
16
+
17
+ def cookie_domain
18
+ nil
19
+ end
20
+
21
+ def logger
22
+ @logger ||= MockLogger.new
23
+ end
24
+
25
+ def params
26
+ @params ||= {}
27
+ end
28
+
29
+ def request
30
+ @request ||= MockRequest.new(self)
31
+ end
32
+
33
+ def request_content_type
34
+ @request_content_type ||= "text/html"
35
+ end
36
+
37
+ def session
38
+ @session ||= {}
39
+ end
40
+
41
+ # If method is defined, it causes below behavior...
42
+ # controller = Authentication::Logic::ControllerAdapters::RailsAdapter.new(
43
+ # Authentication::Logic::TestCase::MockAPIController.new
44
+ # )
45
+ # controller.responds_to_single_access_allowed? #=> true
46
+ # controller.single_access_allowed?
47
+ # #=> NoMethodError: undefined method `single_access_allowed?' for nil:NilClass
48
+ #
49
+ undef :single_access_allowed?
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authentication
4
+ module Logic
5
+ module TestCase
6
+ # Basically acts like a controller but doesn't do anything. Authentication::Logic can interact
7
+ # with this, do it's thing and then you can look at the controller object to see if
8
+ # anything changed.
9
+ class MockController < ControllerAdapters::AbstractAdapter
10
+ attr_accessor :http_user, :http_password, :realm
11
+ attr_writer :request_content_type
12
+
13
+ def initialize; end
14
+
15
+ def authenticate_with_http_basic
16
+ yield http_user, http_password
17
+ end
18
+
19
+ def authenticate_or_request_with_http_basic(realm = "DefaultRealm")
20
+ self.realm = realm
21
+ @http_auth_requested = true
22
+ yield http_user, http_password
23
+ end
24
+
25
+ def cookies
26
+ @cookies ||= MockCookieJar.new
27
+ end
28
+
29
+ def cookie_domain
30
+ nil
31
+ end
32
+
33
+ def logger
34
+ @logger ||= MockLogger.new
35
+ end
36
+
37
+ def params
38
+ @params ||= {}
39
+ end
40
+
41
+ def request
42
+ @request ||= MockRequest.new(self)
43
+ end
44
+
45
+ def request_content_type
46
+ @request_content_type ||= "text/html"
47
+ end
48
+
49
+ def session
50
+ @session ||= {}
51
+ end
52
+
53
+ def http_auth_requested?
54
+ @http_auth_requested ||= false
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authentication
4
+ module Logic
5
+ module TestCase
6
+ # A mock of `ActionDispatch::Cookies::CookieJar`.
7
+ # See action_dispatch/middleware/cookies.rb
8
+ class MockCookieJar < Hash # :nodoc:
9
+ attr_accessor :set_cookies
10
+
11
+ def [](key)
12
+ hash = super
13
+ hash && hash[:value]
14
+ end
15
+
16
+ # @param options - "the cookie's value [usually a string] or a hash of
17
+ # options as documented above [in action_dispatch/middleware/cookies.rb]"
18
+ def []=(key, options)
19
+ opt = cookie_options_to_hash(options)
20
+ (@set_cookies ||= {})[key.to_s] = opt
21
+ super(key, opt)
22
+ end
23
+
24
+ def delete(key, _options = {})
25
+ super(key)
26
+ end
27
+
28
+ def signed
29
+ @signed ||= MockSignedCookieJar.new(self)
30
+ end
31
+
32
+ def encrypted
33
+ @encrypted ||= MockEncryptedCookieJar.new(self)
34
+ end
35
+
36
+ private
37
+
38
+ # @api private
39
+ def cookie_options_to_hash(options)
40
+ if options.is_a?(Hash)
41
+ options
42
+ else
43
+ { value: options }
44
+ end
45
+ end
46
+ end
47
+
48
+ # A mock of `ActionDispatch::Cookies::SignedKeyRotatingCookieJar`
49
+ #
50
+ # > .. a jar that'll automatically generate a signed representation of
51
+ # > cookie value and verify it when reading from the cookie again.
52
+ # > actionpack/lib/action_dispatch/middleware/cookies.rb
53
+ class MockSignedCookieJar < MockCookieJar
54
+ attr_reader :parent_jar # helper for testing
55
+
56
+ def initialize(parent_jar)
57
+ @parent_jar = parent_jar
58
+ parent_jar.each { |k, v| self[k] = v }
59
+ end
60
+
61
+ def [](val)
62
+ signed_message = @parent_jar[val]
63
+ return unless signed_message
64
+
65
+ payload, signature = signed_message.split("--")
66
+ raise "Invalid signature" unless Digest::SHA1.hexdigest(payload) == signature
67
+
68
+ payload
69
+ end
70
+
71
+ def []=(key, options)
72
+ opt = cookie_options_to_hash(options)
73
+ opt[:value] = "#{opt[:value]}--#{Digest::SHA1.hexdigest opt[:value]}"
74
+ @parent_jar[key] = opt
75
+ end
76
+ end
77
+
78
+ # Which ActionDispatch class is this a mock of?
79
+ # TODO: Document as with other mocks above.
80
+ class MockEncryptedCookieJar < MockCookieJar
81
+ attr_reader :parent_jar # helper for testing
82
+
83
+ def initialize(parent_jar)
84
+ @parent_jar = parent_jar
85
+ parent_jar.each { |k, v| self[k] = v }
86
+ end
87
+
88
+ def [](val)
89
+ encrypted_message = @parent_jar[val]
90
+ return unless encrypted_message
91
+
92
+ self.class.decrypt(encrypted_message)
93
+ end
94
+
95
+ def []=(key, options)
96
+ opt = cookie_options_to_hash(options)
97
+ opt[:value] = self.class.encrypt(opt[:value])
98
+ @parent_jar[key] = opt
99
+ end
100
+
101
+ # simple caesar cipher for testing
102
+ def self.encrypt(str)
103
+ str.unpack("U*").map(&:succ).pack("U*")
104
+ end
105
+
106
+ def self.decrypt(str)
107
+ str.unpack("U*").map(&:pred).pack("U*")
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authentication
4
+ module Logic
5
+ module TestCase
6
+ # Simple class to replace real loggers, so that we can raise any errors being logged.
7
+ class MockLogger
8
+ def error(message)
9
+ raise message
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authentication
4
+ module Logic
5
+ module TestCase
6
+ class MockRequest # :nodoc:
7
+ attr_accessor :controller
8
+
9
+ def initialize(controller)
10
+ self.controller = controller
11
+ end
12
+
13
+ def env
14
+ @env ||= {
15
+ ControllerAdapters::AbstractAdapter::ENV_SESSION_OPTIONS => {}
16
+ }
17
+ end
18
+
19
+ def format
20
+ controller.request_content_type if controller.respond_to? :request_content_type
21
+ end
22
+
23
+ def ip
24
+ controller.respond_to?(:env) &&
25
+ controller.env.is_a?(Hash) &&
26
+ controller.env["REMOTE_ADDR"] ||
27
+ "1.1.1.1"
28
+ end
29
+
30
+ private
31
+
32
+ def method_missing(*args, &block); end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authentication
4
+ module Logic
5
+ module TestCase
6
+ # Adapts authlogic to work with the @request object when testing. This way Authentication::Logic
7
+ # can set cookies and what not before a request is made, ultimately letting you log in
8
+ # users in functional tests.
9
+ class RailsRequestAdapter < ControllerAdapters::AbstractAdapter
10
+ def authenticate_with_http_basic(&block); end
11
+
12
+ def cookies
13
+ new_cookies = MockCookieJar.new
14
+ super.each do |key, value|
15
+ new_cookies[key] = cookie_value(value)
16
+ end
17
+ new_cookies
18
+ end
19
+
20
+ def cookie_domain
21
+ nil
22
+ end
23
+
24
+ def request
25
+ @request ||= MockRequest.new(controller)
26
+ end
27
+
28
+ def request_content_type
29
+ request.format.to_s
30
+ end
31
+
32
+ private
33
+
34
+ def cookie_value(value)
35
+ value.is_a?(Hash) ? value[:value] : value
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,216 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "#{File.dirname(__FILE__)}/test_case/rails_request_adapter"
4
+ require "#{File.dirname(__FILE__)}/test_case/mock_api_controller"
5
+ require "#{File.dirname(__FILE__)}/test_case/mock_cookie_jar"
6
+ require "#{File.dirname(__FILE__)}/test_case/mock_controller"
7
+ require "#{File.dirname(__FILE__)}/test_case/mock_logger"
8
+ require "#{File.dirname(__FILE__)}/test_case/mock_request"
9
+
10
+ module Authentication
11
+ module Logic
12
+ # This module is a collection of methods and classes that help you easily test
13
+ # Authlogic. In fact, I use these same tools to test the internals of
14
+ # Authlogic.
15
+ #
16
+ # === The quick and dirty
17
+ #
18
+ # require "authlogic/test_case" # include at the top of test_helper.rb
19
+ # setup :activate_authlogic # run before tests are executed
20
+ # UserSession.create(users(:whomever)) # logs a user in
21
+ #
22
+ # For a more detailed explanation, see below.
23
+ #
24
+ # === Setting up
25
+ #
26
+ # Authlogic comes with some simple testing tools. To get these, you need to
27
+ # first require Authlogic's TestCase. If you are doing this in a rails app,
28
+ # you would require this file at the top of your test_helper.rb file:
29
+ #
30
+ # require "authlogic/test_case"
31
+ #
32
+ # If you are using Test::Unit::TestCase, the standard testing library that
33
+ # comes with ruby, then you can skip this next part. If you are not, you need
34
+ # to include the Authlogic::TestCase into your testing suite as follows:
35
+ #
36
+ # include Authlogic::TestCase
37
+ #
38
+ # Now that everything is ready to go, let's move onto actually testing. Here
39
+ # is the basic idea behind testing:
40
+ #
41
+ # Authlogic requires a "connection" to your controller to activate it. In the
42
+ # same manner that ActiveRecord requires a connection to your database. It
43
+ # can't do anything until it gets connected. That being said, Authlogic will
44
+ # raise an Authlogic::Session::Activation::NotActivatedError any time you try
45
+ # to instantiate an object without a "connection". So before you do anything
46
+ # with Authlogic, you need to activate / connect Authlogic. Let's walk through
47
+ # how to do this in tests:
48
+ #
49
+ # === Fixtures / Factories
50
+ #
51
+ # Creating users via fixtures / factories is easy. Here's an example of a
52
+ # fixture:
53
+ #
54
+ # ben:
55
+ # email: whatever@whatever.com
56
+ # password_salt: <%= salt = Authlogic::Random.hex_token %>
57
+ # crypted_password: <%= Authlogic::CryptoProviders::SCrypt.encrypt("benrocks" + salt) %>
58
+ # persistence_token: <%= Authlogic::Random.hex_token %>
59
+ # single_access_token: <%= Authlogic::Random.friendly_token %>
60
+ # perishable_token: <%= Authlogic::Random.friendly_token %>
61
+ #
62
+ # Notice the crypted_password value. Just supplement that with whatever crypto
63
+ # provider you are using, if you are not using the default.
64
+ #
65
+ # === Functional tests
66
+ #
67
+ # Activating Authlogic isn't a problem here, because making a request will
68
+ # activate Authlogic for you. The problem is logging users in so they can
69
+ # access restricted areas. Solving this is simple, just do this:
70
+ #
71
+ # setup :activate_authlogic
72
+ #
73
+ # For those of you unfamiliar with TestUnit, the setup method basically just
74
+ # executes a method before any test is ran. It is essentially "setting up"
75
+ # your tests.
76
+ #
77
+ # Once you have done this, just log users in like usual:
78
+ #
79
+ # UserSession.create(users(:whomever))
80
+ # # access my restricted area here
81
+ #
82
+ # Do this before you make your request and it will act as if that user is
83
+ # logged in.
84
+ #
85
+ # === Integration tests
86
+ #
87
+ # Again, just like functional tests, you don't have to do anything. As soon as
88
+ # you make a request, Authlogic will be connected. If you want to activate
89
+ # Authlogic before making a request follow the same steps described in the
90
+ # "functional tests" section above. It works in the same manner.
91
+ #
92
+ # === Unit tests
93
+ #
94
+ # The only time you need to do any trickiness here is if you want to test
95
+ # Authlogic models. Maybe you added some custom code or methods in your
96
+ # Authlogic models. Maybe you are writing a plugin or a library that extends
97
+ # Authlogic.
98
+ #
99
+ # That being said, in this environment there is no controller. So you need to
100
+ # use a "mock" controller. Something that looks like a controller, acts like a
101
+ # controller, but isn't a "real" controller. You are essentially connecting
102
+ # Authlogic to your "mock" controller, then you can test off of the mock
103
+ # controller to make sure everything is functioning properly.
104
+ #
105
+ # I use a mock controller to test Authlogic myself. It's part of the Authlogic
106
+ # library that you can easily use. It's as simple as functional and
107
+ # integration tests. Just do the following:
108
+ #
109
+ # setup :activate_authlogic
110
+ #
111
+ # You also get a controller method that you can test off of. For example:
112
+ #
113
+ # ben = users(:ben)
114
+ # assert_nil controller.session["user_credentials"]
115
+ # assert UserSession.create(ben)
116
+ # assert_equal controller.session["user_credentials"], ben.persistence_token
117
+ #
118
+ # See how I am checking that Authlogic is interacting with the controller
119
+ # properly? That's the idea here.
120
+ #
121
+ # === Testing with Rails 5
122
+ #
123
+ # Rails 5 has [deprecated classic controller tests](https://goo.gl/4zmt6y).
124
+ # Controller tests now inherit from `ActionDispatch::IntegrationTest` making
125
+ # them plain old integration tests now. You have two options for testing
126
+ # AuthLogic in Rails 5:
127
+ #
128
+ # * Add the `rails-controller-testing` gem to bring back the original
129
+ # controller testing usage
130
+ # * Go full steam ahead with integration testing and actually log a user in
131
+ # by submitting a form in the integration test.
132
+ #
133
+ # Naturally DHH recommends the second method and this is
134
+ # [what he does in his own tests](https://goo.gl/Ar6p0u). This is useful
135
+ # for testing not only AuthLogic itself (submitting login credentials to a
136
+ # UserSessionsController, for example) but any controller action that is
137
+ # behind a login wall. Add a helper method and use that before testing your
138
+ # actual controller action:
139
+ #
140
+ # # test/test_helper.rb
141
+ # def login(user)
142
+ # post user_sessions_url, :params => { :email => user.email, :password => 'password' }
143
+ # end
144
+ #
145
+ # # test/controllers/posts_controller_test.rb
146
+ # test "#create requires a user to be logged in
147
+ # post posts_url, :params => { :body => 'Lorem ipsum' }
148
+ #
149
+ # assert_redirected_to new_user_session_url
150
+ # end
151
+ #
152
+ # test "#create lets a logged in user create a new post" do
153
+ # login(users(:admin))
154
+ #
155
+ # assert_difference 'Posts.count' do
156
+ # post posts_url, :params => { :body => 'Lorem ipsum' }
157
+ # end
158
+ #
159
+ # assert_redirected_to posts_url
160
+ # end
161
+ #
162
+ # You still have access to the `session` helper in an integration test and so
163
+ # you can still test to see if a user is logged in. A couple of helper methods
164
+ # might look like:
165
+ #
166
+ # # test/test_helper.rb
167
+ # def assert_logged_in
168
+ # assert session[:user_credentials].present?
169
+ # end
170
+ #
171
+ # def assert_not_logged_in
172
+ # assert session[:user_credentials].blank?
173
+ # end
174
+ #
175
+ # # test/user_sessions_controller_test.rb
176
+ # test "#create logs in a user" do
177
+ # login(users(:admin))
178
+ #
179
+ # assert_logged_in
180
+ # end
181
+ module TestCase
182
+ def initialize(*args)
183
+ @request = nil
184
+ super
185
+ end
186
+
187
+ # Activates authlogic so that you can use it in your tests. You should call
188
+ # this method in your test's setup. Ex:
189
+ #
190
+ # setup :activate_authlogic
191
+ def activate_authlogic
192
+ if @request && !@request.respond_to?(:params)
193
+ class << @request
194
+ alias_method :params, :parameters
195
+ end
196
+ end
197
+
198
+ Authlogic::Session::Base.controller = @request &&
199
+ Authlogic::TestCase::RailsRequestAdapter.new(@request) ||
200
+ controller
201
+ end
202
+
203
+ # The Authlogic::TestCase::MockController object passed to Authlogic to
204
+ # activate it. You can access this in your test. See the module description
205
+ # for an example.
206
+ def controller
207
+ @controller ||= Authlogic::TestCase::MockController.new
208
+ end
209
+ end
210
+
211
+ # TODO: Why are these lines inside the `Authlogic` module? Should be outside?
212
+ ::Test::Unit::TestCase.include TestCase if defined?(::Test::Unit::TestCase)
213
+ ::MiniTest::Unit::TestCase.include TestCase if defined?(::MiniTest::Unit::TestCase)
214
+ ::MiniTest::Test.include TestCase if defined?(::MiniTest::Test)
215
+ end
216
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authentication
4
+ module Logic
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
data/lib/auth/logic.rb ADDED
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "logic/version"
4
+ require "active_support/all"
5
+
6
+ require "active_record"
7
+
8
+ path = "#{File.dirname(__FILE__)}/auth/logic/"
9
+
10
+ [
11
+ "errors",
12
+ "i18n",
13
+ "random",
14
+ "config",
15
+
16
+ "controller_adapters/abstract_adapter",
17
+ "cookie_credentials",
18
+
19
+ "crypto_providers",
20
+
21
+ "acts_as_authentic/email",
22
+ "acts_as_authentic/logged_in_status",
23
+ "acts_as_authentic/login",
24
+ "acts_as_authentic/magic_columns",
25
+ "acts_as_authentic/password",
26
+ "acts_as_authentic/perishable_token",
27
+ "acts_as_authentic/persistence_token",
28
+ "acts_as_authentic/session_maintenance",
29
+ "acts_as_authentic/single_access_token",
30
+ "acts_as_authentic/base",
31
+
32
+ "session/magic_column/assigns_last_request_at",
33
+ "session/base"
34
+ ].each do |library|
35
+ require path + library
36
+ end
37
+
38
+ require "#{path}controller_adapters/rails_adapter" if defined?(Rails)
39
+ require "#{path}controller_adapters/sinatra_adapter" if defined?(Sinatra)
40
+
41
+ module Authentication
42
+ module Logic
43
+ class Error < StandardError; end
44
+ # Your code goes here...
45
+ end
46
+ end