drogus-authlogic 2.1.3
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.
- data/.gitignore +9 -0
- data/CHANGELOG.rdoc +345 -0
- data/LICENSE +20 -0
- data/README.rdoc +246 -0
- data/Rakefile +42 -0
- data/VERSION.yml +5 -0
- data/authlogic.gemspec +217 -0
- data/generators/session/session_generator.rb +9 -0
- data/generators/session/templates/session.rb +2 -0
- data/init.rb +1 -0
- data/lib/authlogic.rb +64 -0
- data/lib/authlogic/acts_as_authentic/base.rb +107 -0
- data/lib/authlogic/acts_as_authentic/email.rb +110 -0
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +60 -0
- data/lib/authlogic/acts_as_authentic/login.rb +137 -0
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +24 -0
- data/lib/authlogic/acts_as_authentic/password.rb +355 -0
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +105 -0
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +68 -0
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +61 -0
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +139 -0
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +65 -0
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +32 -0
- data/lib/authlogic/authenticates_many/association.rb +42 -0
- data/lib/authlogic/authenticates_many/base.rb +55 -0
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +67 -0
- data/lib/authlogic/controller_adapters/merb_adapter.rb +30 -0
- data/lib/authlogic/controller_adapters/rails_adapter.rb +48 -0
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +61 -0
- data/lib/authlogic/crypto_providers/aes256.rb +43 -0
- data/lib/authlogic/crypto_providers/bcrypt.rb +90 -0
- data/lib/authlogic/crypto_providers/md5.rb +34 -0
- data/lib/authlogic/crypto_providers/sha1.rb +35 -0
- data/lib/authlogic/crypto_providers/sha256.rb +50 -0
- data/lib/authlogic/crypto_providers/sha512.rb +50 -0
- data/lib/authlogic/crypto_providers/wordpress.rb +43 -0
- data/lib/authlogic/i18n.rb +83 -0
- data/lib/authlogic/i18n/translator.rb +15 -0
- data/lib/authlogic/random.rb +33 -0
- data/lib/authlogic/regex.rb +25 -0
- data/lib/authlogic/session/activation.rb +58 -0
- data/lib/authlogic/session/active_record_trickery.rb +64 -0
- data/lib/authlogic/session/base.rb +37 -0
- data/lib/authlogic/session/brute_force_protection.rb +96 -0
- data/lib/authlogic/session/callbacks.rb +99 -0
- data/lib/authlogic/session/cookies.rb +130 -0
- data/lib/authlogic/session/existence.rb +93 -0
- data/lib/authlogic/session/foundation.rb +63 -0
- data/lib/authlogic/session/http_auth.rb +58 -0
- data/lib/authlogic/session/id.rb +41 -0
- data/lib/authlogic/session/klass.rb +78 -0
- data/lib/authlogic/session/magic_columns.rb +95 -0
- data/lib/authlogic/session/magic_states.rb +59 -0
- data/lib/authlogic/session/params.rb +101 -0
- data/lib/authlogic/session/password.rb +240 -0
- data/lib/authlogic/session/perishable_token.rb +18 -0
- data/lib/authlogic/session/persistence.rb +70 -0
- data/lib/authlogic/session/priority_record.rb +34 -0
- data/lib/authlogic/session/scopes.rb +101 -0
- data/lib/authlogic/session/session.rb +62 -0
- data/lib/authlogic/session/timeout.rb +82 -0
- data/lib/authlogic/session/unauthorized_record.rb +50 -0
- data/lib/authlogic/session/validation.rb +82 -0
- data/lib/authlogic/test_case.rb +120 -0
- data/lib/authlogic/test_case/mock_controller.rb +45 -0
- data/lib/authlogic/test_case/mock_cookie_jar.rb +14 -0
- data/lib/authlogic/test_case/mock_logger.rb +10 -0
- data/lib/authlogic/test_case/mock_request.rb +19 -0
- data/lib/authlogic/test_case/rails_request_adapter.rb +30 -0
- data/rails/init.rb +1 -0
- data/shoulda_macros/authlogic.rb +69 -0
- data/test/acts_as_authentic_test/base_test.rb +18 -0
- data/test/acts_as_authentic_test/email_test.rb +97 -0
- data/test/acts_as_authentic_test/logged_in_status_test.rb +36 -0
- data/test/acts_as_authentic_test/login_test.rb +109 -0
- data/test/acts_as_authentic_test/magic_columns_test.rb +27 -0
- data/test/acts_as_authentic_test/password_test.rb +236 -0
- data/test/acts_as_authentic_test/perishable_token_test.rb +90 -0
- data/test/acts_as_authentic_test/persistence_token_test.rb +55 -0
- data/test/acts_as_authentic_test/restful_authentication_test.rb +40 -0
- data/test/acts_as_authentic_test/session_maintenance_test.rb +84 -0
- data/test/acts_as_authentic_test/single_access_test.rb +44 -0
- data/test/authenticates_many_test.rb +16 -0
- data/test/crypto_provider_test/aes256_test.rb +14 -0
- data/test/crypto_provider_test/bcrypt_test.rb +14 -0
- data/test/crypto_provider_test/sha1_test.rb +23 -0
- data/test/crypto_provider_test/sha256_test.rb +14 -0
- data/test/crypto_provider_test/sha512_test.rb +14 -0
- data/test/fixtures/companies.yml +5 -0
- data/test/fixtures/employees.yml +17 -0
- data/test/fixtures/projects.yml +3 -0
- data/test/fixtures/users.yml +24 -0
- data/test/i18n_test.rb +33 -0
- data/test/libs/affiliate.rb +7 -0
- data/test/libs/company.rb +6 -0
- data/test/libs/employee.rb +7 -0
- data/test/libs/employee_session.rb +2 -0
- data/test/libs/ldaper.rb +3 -0
- data/test/libs/ordered_hash.rb +9 -0
- data/test/libs/project.rb +3 -0
- data/test/libs/user.rb +5 -0
- data/test/libs/user_session.rb +6 -0
- data/test/random_test.rb +49 -0
- data/test/session_test/activation_test.rb +43 -0
- data/test/session_test/active_record_trickery_test.rb +36 -0
- data/test/session_test/brute_force_protection_test.rb +101 -0
- data/test/session_test/callbacks_test.rb +6 -0
- data/test/session_test/cookies_test.rb +112 -0
- data/test/session_test/credentials_test.rb +0 -0
- data/test/session_test/existence_test.rb +64 -0
- data/test/session_test/http_auth_test.rb +28 -0
- data/test/session_test/id_test.rb +17 -0
- data/test/session_test/klass_test.rb +40 -0
- data/test/session_test/magic_columns_test.rb +62 -0
- data/test/session_test/magic_states_test.rb +60 -0
- data/test/session_test/params_test.rb +53 -0
- data/test/session_test/password_test.rb +106 -0
- data/test/session_test/perishability_test.rb +15 -0
- data/test/session_test/persistence_test.rb +21 -0
- data/test/session_test/scopes_test.rb +60 -0
- data/test/session_test/session_test.rb +59 -0
- data/test/session_test/timeout_test.rb +52 -0
- data/test/session_test/unauthorized_record_test.rb +13 -0
- data/test/session_test/validation_test.rb +23 -0
- data/test/test_helper.rb +182 -0
- metadata +238 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
module Authlogic
|
2
|
+
module Session
|
3
|
+
# Handles all parts of authentication that deal with sessions. Such as persisting a session and saving / destroy a session.
|
4
|
+
module Session
|
5
|
+
def self.included(klass)
|
6
|
+
klass.class_eval do
|
7
|
+
extend Config
|
8
|
+
include InstanceMethods
|
9
|
+
persist :persist_by_session
|
10
|
+
after_save :update_session
|
11
|
+
after_destroy :update_session
|
12
|
+
after_persisting :update_session, :unless => :single_access?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Configuration for the session feature.
|
17
|
+
module Config
|
18
|
+
# Works exactly like cookie_key, but for sessions. See cookie_key for more info.
|
19
|
+
#
|
20
|
+
# * <tt>Default:</tt> cookie_key
|
21
|
+
# * <tt>Accepts:</tt> Symbol or String
|
22
|
+
def session_key(value = nil)
|
23
|
+
rw_config(:session_key, value, cookie_key)
|
24
|
+
end
|
25
|
+
alias_method :session_key=, :session_key
|
26
|
+
end
|
27
|
+
|
28
|
+
# Instance methods for the session feature.
|
29
|
+
module InstanceMethods
|
30
|
+
private
|
31
|
+
# Tries to validate the session from information in the session
|
32
|
+
def persist_by_session
|
33
|
+
persistence_token, record_id = session_credentials
|
34
|
+
if !persistence_token.nil?
|
35
|
+
# Allow finding by persistence token, because when records are created the session is maintained in a before_save, when there is no id.
|
36
|
+
# This is done for performance reasons and to save on queries.
|
37
|
+
record = record_id.nil? ?
|
38
|
+
search_for_record("find_by_persistence_token", persistence_token) :
|
39
|
+
search_for_record("find_by_#{klass.primary_key}", record_id)
|
40
|
+
self.unauthorized_record = record if record && record.persistence_token == persistence_token
|
41
|
+
valid?
|
42
|
+
else
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def session_credentials
|
48
|
+
[controller.session[session_key], controller.session["#{session_key}_#{klass.primary_key}"]].compact
|
49
|
+
end
|
50
|
+
|
51
|
+
def session_key
|
52
|
+
build_key(self.class.session_key)
|
53
|
+
end
|
54
|
+
|
55
|
+
def update_session
|
56
|
+
controller.session[session_key] = record && record.persistence_token
|
57
|
+
controller.session["#{session_key}_#{klass.primary_key}"] = record && record.send(record.class.primary_key)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Authlogic
|
2
|
+
module Session
|
3
|
+
# Think about financial websites, if you are inactive for a certain period of time you will be asked to
|
4
|
+
# log back in on your next request. You can do this with Authlogic easily, there are 2 parts to this:
|
5
|
+
#
|
6
|
+
# 1. Define the timeout threshold:
|
7
|
+
#
|
8
|
+
# acts_as_authentic do |c|
|
9
|
+
# c.logged_in_timeout = 10.minutes # default is 10.minutes
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# 2. Enable logging out on timeouts
|
13
|
+
#
|
14
|
+
# class UserSession < Authlogic::Session::Base
|
15
|
+
# logout_on_timeout true # default if false
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# This will require a user to log back in if they are inactive for more than 10 minutes. In order for
|
19
|
+
# this feature to be used you must have a last_request_at datetime column in your table for whatever model
|
20
|
+
# you are authenticating with.
|
21
|
+
module Timeout
|
22
|
+
def self.included(klass)
|
23
|
+
klass.class_eval do
|
24
|
+
extend Config
|
25
|
+
include InstanceMethods
|
26
|
+
before_persisting :reset_stale_state
|
27
|
+
after_persisting :enforce_timeout
|
28
|
+
attr_accessor :stale_record
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Configuration for the timeout feature.
|
33
|
+
module Config
|
34
|
+
# With acts_as_authentic you get a :logged_in_timeout configuration option. If this is set, after this amount of time has passed the user
|
35
|
+
# will be marked as logged out. Obviously, since web based apps are on a per request basis, we have to define a time limit threshold that
|
36
|
+
# determines when we consider a user to be "logged out". Meaning, if they login and then leave the website, when do mark them as logged out?
|
37
|
+
# I recommend just using this as a fun feature on your website or reports, giving you a ballpark number of users logged in and active. This is
|
38
|
+
# not meant to be a dead accurate representation of a users logged in state, since there is really no real way to do this with web based apps.
|
39
|
+
# Think about a user that logs in and doesn't log out. There is no action that tells you that the user isn't technically still logged in and
|
40
|
+
# active.
|
41
|
+
#
|
42
|
+
# That being said, you can use that feature to require a new login if their session timesout. Similar to how financial sites work. Just set this option to
|
43
|
+
# true and if your record returns true for stale? then they will be required to log back in.
|
44
|
+
#
|
45
|
+
# Lastly, UserSession.find will still return a object is the session is stale, but you will not get a record. This allows you to determine if the
|
46
|
+
# user needs to log back in because their session went stale, or because they just aren't logged in. Just call current_user_session.stale? as your flag.
|
47
|
+
#
|
48
|
+
# * <tt>Default:</tt> false
|
49
|
+
# * <tt>Accepts:</tt> Boolean
|
50
|
+
def logout_on_timeout(value = nil)
|
51
|
+
rw_config(:logout_on_timeout, value, false)
|
52
|
+
end
|
53
|
+
alias_method :logout_on_timeout=, :logout_on_timeout
|
54
|
+
end
|
55
|
+
|
56
|
+
# Instance methods for the timeout feature.
|
57
|
+
module InstanceMethods
|
58
|
+
# Tells you if the record is stale or not. Meaning the record has timed out. This will only return true if you set logout_on_timeout to true in your configuration.
|
59
|
+
# Basically how a bank website works. If you aren't active over a certain period of time your session becomes stale and requires you to log back in.
|
60
|
+
def stale?
|
61
|
+
!stale_record.nil? || (logout_on_timeout? && record && record.logged_out?)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def reset_stale_state
|
66
|
+
self.stale_record = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def enforce_timeout
|
70
|
+
if stale?
|
71
|
+
self.stale_record = record
|
72
|
+
self.record = nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def logout_on_timeout?
|
77
|
+
self.class.logout_on_timeout == true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Authlogic
|
2
|
+
module Session
|
3
|
+
# Allows you to create session with an object. Ex:
|
4
|
+
#
|
5
|
+
# UserSession.create(my_user_object)
|
6
|
+
#
|
7
|
+
# Be careful with this, because Authlogic is assuming that you have already confirmed that the
|
8
|
+
# user is who he says he is.
|
9
|
+
#
|
10
|
+
# For example, this is the method used to persist the session internally. Authlogic finds the user with
|
11
|
+
# the persistence token. At this point we know the user is who he says he is, so Authlogic just creates a
|
12
|
+
# session with the record. This is particularly useful for 3rd party authentication methods, such as
|
13
|
+
# OpenID. Let that method verify the identity, once it's verified, pass the object and create a session.
|
14
|
+
module UnauthorizedRecord
|
15
|
+
def self.included(klass)
|
16
|
+
klass.class_eval do
|
17
|
+
attr_accessor :unauthorized_record
|
18
|
+
validate :validate_by_unauthorized_record, :if => :authenticating_with_unauthorized_record?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returning meaningful credentials
|
23
|
+
def credentials
|
24
|
+
if authenticating_with_unauthorized_record?
|
25
|
+
details = {}
|
26
|
+
details[:unauthorized_record] = "<protected>"
|
27
|
+
details
|
28
|
+
else
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Setting the unauthorized record if it exists in the credentials passed.
|
34
|
+
def credentials=(value)
|
35
|
+
super
|
36
|
+
values = value.is_a?(Array) ? value : [value]
|
37
|
+
self.unauthorized_record = values.first if values.first.class < ::ActiveRecord::Base
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def authenticating_with_unauthorized_record?
|
42
|
+
!unauthorized_record.nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_by_unauthorized_record
|
46
|
+
self.attempted_record = unauthorized_record
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Authlogic
|
2
|
+
module Session
|
3
|
+
# Responsible for session validation
|
4
|
+
module Validation
|
5
|
+
# The errors in Authlogic work JUST LIKE ActiveRecord. In fact, it uses the exact same ActiveRecord errors class. Use it the same way:
|
6
|
+
#
|
7
|
+
# class UserSession
|
8
|
+
# validate :check_if_awesome
|
9
|
+
#
|
10
|
+
# private
|
11
|
+
# def check_if_awesome
|
12
|
+
# errors.add(:login, "must contain awesome") if login && !login.include?("awesome")
|
13
|
+
# errors.add(:base, "You must be awesome to log in") unless attempted_record.awesome?
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
class Errors < (defined?(::ActiveModel) ? ::ActiveModel::Errors : ::ActiveRecord::Errors)
|
17
|
+
unless defined?(::ActiveModel)
|
18
|
+
def [](key)
|
19
|
+
value = super
|
20
|
+
value.is_a?(Array) ? value : [value].compact
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# You should use this as a place holder for any records that you find during validation. The main reason for this is to
|
26
|
+
# allow other modules to use it if needed. Take the failed_login_count feature, it needs this in order to increase
|
27
|
+
# the failed login count.
|
28
|
+
def attempted_record
|
29
|
+
@attempted_record
|
30
|
+
end
|
31
|
+
|
32
|
+
# See attempted_record
|
33
|
+
def attempted_record=(value)
|
34
|
+
@attempted_record = value
|
35
|
+
end
|
36
|
+
|
37
|
+
# The errors in Authlogic work JUST LIKE ActiveRecord. In fact, it uses the exact same ActiveRecord errors class.
|
38
|
+
# Use it the same way:
|
39
|
+
#
|
40
|
+
# === Example
|
41
|
+
#
|
42
|
+
# class UserSession
|
43
|
+
# before_validation :check_if_awesome
|
44
|
+
#
|
45
|
+
# private
|
46
|
+
# def check_if_awesome
|
47
|
+
# errors.add(:login, "must contain awesome") if login && !login.include?("awesome")
|
48
|
+
# errors.add(:base, "You must be awesome to log in") unless attempted_record.awesome?
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
def errors
|
52
|
+
@errors ||= Errors.new(self)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Determines if the information you provided for authentication is valid or not. If there is
|
56
|
+
# a problem with the information provided errors will be added to the errors object and this
|
57
|
+
# method will return false.
|
58
|
+
def valid?
|
59
|
+
errors.clear
|
60
|
+
self.attempted_record = nil
|
61
|
+
|
62
|
+
before_validation
|
63
|
+
new_session? ? before_validation_on_create : before_validation_on_update
|
64
|
+
validate
|
65
|
+
ensure_authentication_attempted
|
66
|
+
|
67
|
+
if errors.size == 0
|
68
|
+
new_session? ? after_validation_on_create : after_validation_on_update
|
69
|
+
after_validation
|
70
|
+
end
|
71
|
+
|
72
|
+
save_record(attempted_record)
|
73
|
+
errors.size == 0
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
def ensure_authentication_attempted
|
78
|
+
errors.add(:base, I18n.t('error_messages.no_authentication_details', :default => "You did not provide any details for authentication.")) if errors.empty? && attempted_record.nil?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/test_case/rails_request_adapter"
|
2
|
+
require File.dirname(__FILE__) + "/test_case/mock_cookie_jar"
|
3
|
+
require File.dirname(__FILE__) + "/test_case/mock_controller"
|
4
|
+
require File.dirname(__FILE__) + "/test_case/mock_logger"
|
5
|
+
require File.dirname(__FILE__) + "/test_case/mock_request"
|
6
|
+
|
7
|
+
module Authlogic
|
8
|
+
# This module is a collection of methods and classes that help you easily test Authlogic. In fact,
|
9
|
+
# I use these same tools to test the internals of Authlogic.
|
10
|
+
#
|
11
|
+
# === The quick and dirty
|
12
|
+
#
|
13
|
+
# require "authlogic/test_case" # include at the top of test_helper.rb
|
14
|
+
# setup :activate_authlogic # run before tests are executed
|
15
|
+
# UserSession.create(users(:whomever)) # logs a user in
|
16
|
+
#
|
17
|
+
# For a more detailed explanation, see below.
|
18
|
+
#
|
19
|
+
# === Setting up
|
20
|
+
#
|
21
|
+
# Authlogic comes with some simple testing tools. To get these, you need to first require Authlogic's TestCase. If
|
22
|
+
# you are doing this in a rails app, you would require this file at the top of your test_helper.rb file:
|
23
|
+
#
|
24
|
+
# require "authlogic/test_case"
|
25
|
+
#
|
26
|
+
# If you are using Test::Unit::TestCase, the standard testing library that comes with ruby, then you can skip this next part.
|
27
|
+
# If you are not, you need to include the Authlogic::TestCase into your testing suite as follows:
|
28
|
+
#
|
29
|
+
# include Authlogic::TestCase
|
30
|
+
#
|
31
|
+
# Now that everything is ready to go, let's move onto actually testing. Here is the basic idea behind testing:
|
32
|
+
#
|
33
|
+
# Authlogic requires a "connection" to your controller to activate it. In the same manner that ActiveRecord requires a connection to
|
34
|
+
# your database. It can't do anything until it gets connnected. That being said, Authlogic will raise an
|
35
|
+
# Authlogic::Session::Activation::NotActivatedError any time you try to instantiate an object without a "connection".
|
36
|
+
# So before you do anything with Authlogic, you need to activate / connect Authlogic. Let's walk through how to do this in tests:
|
37
|
+
#
|
38
|
+
# === Fixtures / Factories
|
39
|
+
#
|
40
|
+
# Creating users via fixtures / factories is easy. Here's an example of a fixture:
|
41
|
+
#
|
42
|
+
# ben:
|
43
|
+
# email: whatever@whatever.com
|
44
|
+
# password_salt: <%= salt = Authlogic::Random.hex_token %>
|
45
|
+
# crypted_password: <%= Authlogic::CryptoProviders::Sha512.encrypt("benrocks" + salt) %>
|
46
|
+
# persistence_token: <%= Authlogic::Random.hex_token %>
|
47
|
+
# single_access_token: <%= Authlogic::Random.friendly_token %>
|
48
|
+
# perishable_token: <%= Authlogic::Random.friendly_token %>
|
49
|
+
#
|
50
|
+
# Notice the crypted_password value. Just supplement that with whatever crypto provider you are using, if you are not using the default.
|
51
|
+
#
|
52
|
+
# === Functional tests
|
53
|
+
#
|
54
|
+
# Activating Authlogic isn't a problem here, because making a request will activate Authlogic for you. The problem is
|
55
|
+
# logging users in so they can access restricted areas. Solving this is simple, just do this:
|
56
|
+
#
|
57
|
+
# setup :activate_authlogic
|
58
|
+
#
|
59
|
+
# For those of you unfamiliar with TestUnit, the setup method bascially just executes a method before any test is ran.
|
60
|
+
# It is essentially "setting up" your tests.
|
61
|
+
#
|
62
|
+
# Once you have done this, just log users in like usual:
|
63
|
+
#
|
64
|
+
# UserSession.create(users(:whomever))
|
65
|
+
# # access my restricted area here
|
66
|
+
#
|
67
|
+
# Do this before you make your request and it will act as if that user is logged in.
|
68
|
+
#
|
69
|
+
# === Integration tests
|
70
|
+
#
|
71
|
+
# Again, just like functional tests, you don't have to do anything. As soon as you make a request, Authlogic will be
|
72
|
+
# conntected. If you want to activate Authlogic before making a request follow the same steps described in the
|
73
|
+
# "functional tests" section above. It works in the same manner.
|
74
|
+
#
|
75
|
+
# === Unit tests
|
76
|
+
#
|
77
|
+
# The only time you need to do any trickiness here is if you want to test Authlogic models. Maybe you added some custom
|
78
|
+
# code or methods in your Authlogic models. Maybe you are writing a plugin or a library that extends Authlogic.
|
79
|
+
#
|
80
|
+
# That being said, in this environment there is no controller. So you need to use a "mock" controller. Something
|
81
|
+
# that looks like a controller, acts like a controller, but isn't a "real" controller. You are essentially connecting
|
82
|
+
# Authlogic to your "mock" controller, then you can test off of the mock controller to make sure everything is functioning
|
83
|
+
# properly.
|
84
|
+
#
|
85
|
+
# I use a mock controller to test Authlogic myself. It's part of the Authlogic library that you can easily use. It's as simple
|
86
|
+
# as functional and integration tests. Just do the following:
|
87
|
+
#
|
88
|
+
# setup :activate_authlogic
|
89
|
+
#
|
90
|
+
# You also get a controller method that you can test off of. For example:
|
91
|
+
#
|
92
|
+
# ben = users(:ben)
|
93
|
+
# assert_nil controller.session["user_credentials"]
|
94
|
+
# assert UserSession.create(ben)
|
95
|
+
# assert_equal controller.session["user_credentials"], ben.persistence_token
|
96
|
+
#
|
97
|
+
# See how I am checking that Authlogic is interacting with the controller properly? That's the idea here.
|
98
|
+
module TestCase
|
99
|
+
# Activates authlogic so that you can use it in your tests. You should call this method in your test's setup. Ex:
|
100
|
+
#
|
101
|
+
# setup :activate_authlogic
|
102
|
+
def activate_authlogic
|
103
|
+
if @request && ! @request.respond_to?(:params)
|
104
|
+
class <<@request
|
105
|
+
alias_method :params, :parameters
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
Authlogic::Session::Base.controller = (@request && Authlogic::TestCase::RailsRequestAdapter.new(@request)) || controller
|
110
|
+
end
|
111
|
+
|
112
|
+
# The Authlogic::TestCase::MockController object passed to Authlogic to activate it. You can access this in your test.
|
113
|
+
# See the module description for an example.
|
114
|
+
def controller
|
115
|
+
@controller ||= Authlogic::TestCase::MockController.new
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
::Test::Unit::TestCase.send(:include, TestCase) if defined?(::Test::Unit::TestCase)
|
120
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Authlogic
|
2
|
+
module TestCase
|
3
|
+
# Basically acts like a controller but doesn't do anything. Authlogic can interact with this, do it's thing and then you
|
4
|
+
# can look at the controller object to see if anything changed.
|
5
|
+
class MockController < ControllerAdapters::AbstractAdapter
|
6
|
+
attr_accessor :http_user, :http_password
|
7
|
+
attr_writer :request_content_type
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
end
|
11
|
+
|
12
|
+
def authenticate_with_http_basic(&block)
|
13
|
+
yield http_user, http_password
|
14
|
+
end
|
15
|
+
|
16
|
+
def cookies
|
17
|
+
@cookies ||= MockCookieJar.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def cookie_domain
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def logger
|
25
|
+
@logger ||= MockLogger.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def params
|
29
|
+
@params ||= {}
|
30
|
+
end
|
31
|
+
|
32
|
+
def request
|
33
|
+
@request ||= MockRequest.new(controller)
|
34
|
+
end
|
35
|
+
|
36
|
+
def request_content_type
|
37
|
+
@request_content_type ||= "text/html"
|
38
|
+
end
|
39
|
+
|
40
|
+
def session
|
41
|
+
@session ||= {}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|