authentication-logic 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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