janus 0.5.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 (79) hide show
  1. data/README.rdoc +144 -0
  2. data/lib/janus/config.rb +26 -0
  3. data/lib/janus/controllers/confirmations_controller.rb +56 -0
  4. data/lib/janus/controllers/helpers.rb +54 -0
  5. data/lib/janus/controllers/internal_helpers.rb +33 -0
  6. data/lib/janus/controllers/passwords_controller.rb +60 -0
  7. data/lib/janus/controllers/registrations_controller.rb +55 -0
  8. data/lib/janus/controllers/sessions_controller.rb +94 -0
  9. data/lib/janus/controllers/url_helpers.rb +61 -0
  10. data/lib/janus/helper.rb +11 -0
  11. data/lib/janus/hooks/rememberable.rb +20 -0
  12. data/lib/janus/hooks/remote_authenticatable.rb +27 -0
  13. data/lib/janus/hooks/trackable.rb +3 -0
  14. data/lib/janus/hooks.rb +58 -0
  15. data/lib/janus/mailer.rb +13 -0
  16. data/lib/janus/manager.rb +97 -0
  17. data/lib/janus/models/base.rb +31 -0
  18. data/lib/janus/models/confirmable.rb +45 -0
  19. data/lib/janus/models/database_authenticatable.rb +98 -0
  20. data/lib/janus/models/rememberable.rb +54 -0
  21. data/lib/janus/models/remote_authenticatable.rb +99 -0
  22. data/lib/janus/models/remote_token.rb +17 -0
  23. data/lib/janus/models/trackable.rb +37 -0
  24. data/lib/janus/routes.rb +78 -0
  25. data/lib/janus/strategies/base.rb +40 -0
  26. data/lib/janus/strategies/database_authenticatable.rb +20 -0
  27. data/lib/janus/strategies/rememberable.rb +52 -0
  28. data/lib/janus/strategies/remote_authenticatable.rb +28 -0
  29. data/lib/janus/strategies.rb +33 -0
  30. data/lib/janus/test_helper.rb +25 -0
  31. data/lib/janus.rb +60 -0
  32. data/test/functional/home_controller_test.rb +8 -0
  33. data/test/functional/janus/mailer_test.rb +14 -0
  34. data/test/functional/janus/manager_test.rb +94 -0
  35. data/test/functional/users/confirmations_controller_test.rb +59 -0
  36. data/test/functional/users/passwords_controller_test.rb +101 -0
  37. data/test/functional/users/registrations_controller_test.rb +112 -0
  38. data/test/functional/users/sessions_controller_test.rb +100 -0
  39. data/test/functional/users_controller_test.rb +22 -0
  40. data/test/integration/users/rememberable_test.rb +32 -0
  41. data/test/integration/users/remote_test.rb +72 -0
  42. data/test/integration/users/sessions_test.rb +18 -0
  43. data/test/integration/users/trackable_test.rb +22 -0
  44. data/test/rails_app/app/controllers/application_controller.rb +9 -0
  45. data/test/rails_app/app/controllers/blogs_controller.rb +6 -0
  46. data/test/rails_app/app/controllers/home_controller.rb +4 -0
  47. data/test/rails_app/app/controllers/users/confirmations_controller.rb +3 -0
  48. data/test/rails_app/app/controllers/users/passwords_controller.rb +3 -0
  49. data/test/rails_app/app/controllers/users/registrations_controller.rb +7 -0
  50. data/test/rails_app/app/controllers/users/sessions_controller.rb +11 -0
  51. data/test/rails_app/app/controllers/users_controller.rb +9 -0
  52. data/test/rails_app/app/helpers/application_helper.rb +2 -0
  53. data/test/rails_app/app/mailers/janus_mailer.rb +2 -0
  54. data/test/rails_app/app/models/remote_token.rb +6 -0
  55. data/test/rails_app/app/models/user.rb +8 -0
  56. data/test/rails_app/config/application.rb +42 -0
  57. data/test/rails_app/config/boot.rb +6 -0
  58. data/test/rails_app/config/environment.rb +5 -0
  59. data/test/rails_app/config/environments/development.rb +26 -0
  60. data/test/rails_app/config/environments/production.rb +49 -0
  61. data/test/rails_app/config/environments/test.rb +36 -0
  62. data/test/rails_app/config/initializers/janus.rb +11 -0
  63. data/test/rails_app/config/initializers/secret_token.rb +7 -0
  64. data/test/rails_app/config/initializers/session_store.rb +8 -0
  65. data/test/rails_app/config/routes.rb +12 -0
  66. data/test/rails_app/db/migrate/20110323153820_create_users.rb +34 -0
  67. data/test/rails_app/db/migrate/20110331153546_create_remote_tokens.rb +15 -0
  68. data/test/rails_app/db/schema.rb +45 -0
  69. data/test/rails_app/db/seeds.rb +7 -0
  70. data/test/test_helper.rb +103 -0
  71. data/test/unit/confirmable_test.rb +36 -0
  72. data/test/unit/janus_test.rb +27 -0
  73. data/test/unit/rememberable_test.rb +50 -0
  74. data/test/unit/remote_authenticatable_test.rb +37 -0
  75. data/test/unit/remote_token_test.rb +9 -0
  76. data/test/unit/reset_password_test.rb +45 -0
  77. data/test/unit/trackable_test.rb +21 -0
  78. data/test/unit/user_test.rb +60 -0
  79. metadata +232 -0
@@ -0,0 +1,58 @@
1
+ module Janus
2
+ module Hooks # :nodoc:
3
+ extend ActiveSupport::Concern
4
+
5
+ # Hooks allow you the react at the different steps of a user session.
6
+ # All callbacks will receive the same arguments: +user+, +manager+ and
7
+ # +options+.
8
+ #
9
+ # Example:
10
+ #
11
+ # Janus::Manager.after_login do |user, manager, options|
12
+ # session = manager.session(options[:scope])
13
+ #
14
+ # # write some great code here
15
+ # end
16
+ #
17
+ # Options:
18
+ #
19
+ # - +:scope+
20
+ #
21
+ module ClassMethods
22
+ # Executed after a strategy succeeds to authenticate a user.
23
+ def after_authenticate(&block)
24
+ add_callback(:authenticate, block)
25
+ end
26
+
27
+ # Executed the first time an authenticated user is fetched from session.
28
+ def after_fetch(&block)
29
+ add_callback(:fetch, block)
30
+ end
31
+
32
+ # Executed after a user is logged in.
33
+ def after_login(&block)
34
+ add_callback(:login, block)
35
+ end
36
+
37
+ # Executed after a user is logged out. after_logout will be executed for
38
+ # each scope when logging out from multiple scopes at once.
39
+ def after_logout(&block)
40
+ add_callback(:logout, block)
41
+ end
42
+
43
+ def run_callbacks(kind, *args) # :nodoc:
44
+ callbacks(kind).each { |block| block.call(*args) }
45
+ end
46
+
47
+ private
48
+ def add_callback(kind, block)
49
+ callbacks(kind) << block
50
+ end
51
+
52
+ def callbacks(kind)
53
+ @callbacks ||= {}
54
+ @callbacks[kind] ||= []
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,13 @@
1
+ class Janus::Mailer < ActionMailer::Base
2
+ default_from = Janus::Config.contact_email
3
+
4
+ def reset_password_instructions(user)
5
+ @user = user
6
+ mail :to => @user.email, :subject => I18n.t('janus.mailer.reset_password_instructions.subject')
7
+ end
8
+
9
+ def confirmation_instructions(user)
10
+ @user = user
11
+ mail :to => @user.email, :subject => I18n.t('janus.mailer.confirmation_instructions.subject')
12
+ end
13
+ end
@@ -0,0 +1,97 @@
1
+ module Janus
2
+ class Manager
3
+ include Janus::Hooks
4
+ include Janus::Strategies
5
+
6
+ attr_reader :request, :cookies
7
+
8
+ def initialize(request, cookies)
9
+ @request, @cookies = request, cookies
10
+ end
11
+
12
+ # Tries to authenticate the user using strategies, before returning
13
+ # the current user or nil.
14
+ def authenticate(scope)
15
+ run_strategies(scope) unless authenticated?(scope)
16
+ user(scope)
17
+ end
18
+
19
+ # Raises a Janus::NotAuthenticated exception unless a user is authenticated.
20
+ def authenticate!(scope)
21
+ raise Janus::NotAuthenticated.new(scope) unless authenticate?(scope)
22
+ end
23
+
24
+ # Tries to authenticate the user before checking if it's authenticated.
25
+ def authenticate?(scope)
26
+ authenticate(scope)
27
+ authenticated?(scope)
28
+ end
29
+
30
+ # Returns true if a user is authenticated.
31
+ def authenticated?(scope) # :nodoc:
32
+ !!session(scope)
33
+ end
34
+
35
+ # Logs a user in.
36
+ #
37
+ # FIXME: what should happen when a user signs in but a user is already signed in?!
38
+ def login(user, options = {})
39
+ options[:scope] ||= Janus.scope_for(user)
40
+ set_user(user, options)
41
+ Janus::Manager.run_callbacks(:login, user, self, options)
42
+ end
43
+
44
+ # Logs a user out from the given scopes or from all scopes at once
45
+ # if no scope is defined. If no scope is left after logout, then the
46
+ # whole session will be resetted.
47
+ def logout(*scopes)
48
+ scopes = janus_sessions.keys if scopes.empty?
49
+
50
+ scopes.each do |scope|
51
+ _user = user(scope)
52
+ unset_user(scope)
53
+ Janus::Manager.run_callbacks(:logout, _user, self, :scope => scope)
54
+ end
55
+
56
+ request.reset_session if janus_sessions.empty?
57
+ end
58
+
59
+ # Manually sets a user without going throught the whole login or
60
+ # authenticate process.
61
+ def set_user(user, options = {})
62
+ scope = options[:scope] || Janus.scope_for(user)
63
+ janus_sessions[scope.to_sym] = { :user_class => user.class, :user_id => user.id }
64
+ end
65
+
66
+ # Manually removes the user without going throught the whole logout process.
67
+ def unset_user(scope)
68
+ janus_sessions.delete(scope.to_sym)
69
+ @users.delete(scope.to_sym) unless @users.nil?
70
+ end
71
+
72
+ # Returns the currently connected user.
73
+ def user(scope)
74
+ scope = scope.to_sym
75
+ @users ||= {}
76
+
77
+ if authenticated?(scope)
78
+ if @users[scope].nil?
79
+ @users[scope] = session(scope)[:user_class].find(session(scope)[:user_id])
80
+ Janus::Manager.run_callbacks(:fetch, @users[scope], self, :scope => scope)
81
+ end
82
+
83
+ @users[scope]
84
+ end
85
+ end
86
+
87
+ # Returns the current session for user.
88
+ def session(scope)
89
+ janus_sessions[scope.to_sym]
90
+ end
91
+
92
+ private
93
+ def janus_sessions
94
+ request.session['janus'] ||= {}
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,31 @@
1
+ module Janus
2
+ module Models
3
+ module Base
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def generate_token(column_name, size = 32)
8
+ loop do
9
+ token = SecureRandom.hex(size)
10
+ return token unless where(column_name => token).any?
11
+ end
12
+ end
13
+
14
+ def janus_config(*keys)
15
+ keys.each do |key|
16
+ class_eval <<-EOV
17
+ def self.#{key}
18
+ @#{key} || Janus::Config.#{key}
19
+ end
20
+
21
+ def self.#{key}=(value)
22
+ @#{key} = value
23
+ end
24
+ EOV
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ module Janus
2
+ module Models
3
+ # = Confirmable
4
+ #
5
+ # Confirms an account's email by sending an email with an unique token.
6
+ # This is necessary to be sure the user can be contacted on that email.
7
+ #
8
+ # IMPROVE: reconfirm whenever email changes.
9
+ module Confirmable
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ attr_protected :confirmation_token, :confirmation_sent_at, :confirmed_at
14
+ janus_config(:confirmation_key)
15
+
16
+ before_create :generate_confirmation_token
17
+ # before_update :generate_confirmation_token, :if => :email_changed?
18
+ end
19
+
20
+ # Generates the confirmation token, but won't save the record.
21
+ def generate_confirmation_token
22
+ self.confirmation_token = self.class.generate_token(:confirmation_token)
23
+ self.confirmation_sent_at = Time.now
24
+ end
25
+
26
+ # Confirms the record.
27
+ def confirm!
28
+ self.confirmation_token = self.confirmation_sent_at = nil
29
+ self.confirmed_at = Time.now
30
+ save
31
+ end
32
+
33
+ # Checks wether the email of this user if confirmed, or not.
34
+ def confirmed?
35
+ confirmed_at?
36
+ end
37
+
38
+ module ClassMethods
39
+ def find_for_confirmation(token)
40
+ where(:confirmation_token => token).first unless token.blank?
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,98 @@
1
+ require 'bcrypt'
2
+
3
+ module Janus
4
+ module Models
5
+ # = DatabaseAuthenticatable
6
+ #
7
+ # This is the initial part and is required for email + password registration
8
+ # and logins. Passwords are automatically encrypted following Devise's
9
+ # default encryption logic, which relies on bcrypt.
10
+ #
11
+ # == Required columns:
12
+ #
13
+ # - email
14
+ # - encrypted_password
15
+ #
16
+ # == Configuration
17
+ #
18
+ # - +stretches+
19
+ # - +pepper+
20
+ # - +authentication_keys+ - required keys for authenticating a user, defaults to <tt>[:email]</tt>
21
+ #
22
+ module DatabaseAuthenticatable
23
+ extend ActiveSupport::Concern
24
+
25
+ included do
26
+ attr_protected :encrypted_password, :reset_password_token, :reset_password_sent_at
27
+ attr_reader :password
28
+ attr_accessor :current_password
29
+
30
+ validates :password, :presence => true, :confirmation => true, :if => :password_required?
31
+ validate :validate_current_password, :on => :update, :if => :current_password
32
+
33
+ janus_config(:authentication_keys, :stretches, :pepper)
34
+ end
35
+
36
+ def password=(password)
37
+ @password = password
38
+ self.encrypted_password = digest_password(@password) unless @password.blank?
39
+ end
40
+
41
+ # Checks if a given password matches this user password.
42
+ def valid_password?(password)
43
+ ::BCrypt::Password.new(encrypted_password) == "#{password}#{self.class.pepper}"
44
+ end
45
+
46
+ def digest_password(password)
47
+ ::BCrypt::Password.create("#{password}#{self.class.pepper}", :cost => self.class.stretches).to_s
48
+ end
49
+
50
+ def clean_up_passwords
51
+ self.current_password = self.password = self.password_confirmation = nil
52
+ end
53
+
54
+ def generate_reset_password_token!
55
+ self.reset_password_token = self.class.generate_token(:reset_password_token)
56
+ self.reset_password_sent_at = Time.now
57
+ save
58
+ end
59
+
60
+ def reset_password!(params)
61
+ params.each do |key, value|
62
+ send("#{key}=", value) if [:password, :password_confirmation].include?(key.to_sym)
63
+ end
64
+
65
+ self.reset_password_sent_at = self.reset_password_token = nil
66
+ save
67
+ end
68
+
69
+ protected
70
+ def password_required?
71
+ !persisted? || !!password || !!password_confirmation
72
+ end
73
+
74
+ def validate_current_password
75
+ errors.add(:current_password, :invalid) unless valid_password?(current_password)
76
+ end
77
+
78
+ module ClassMethods
79
+ def find_for_database_authentication(params)
80
+ params = params.reject { |k,v| !authentication_keys.include?(k.to_sym) }
81
+ where(params).first
82
+ end
83
+
84
+ def find_for_password_reset(token)
85
+ user = find_by_reset_password_token(token) unless token.blank?
86
+
87
+ if user && user.reset_password_sent_at < 2.days.ago
88
+ user.reset_password_token = user.reset_password_sent_at = nil
89
+ user.save
90
+ user = nil
91
+ end
92
+
93
+ user
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,54 @@
1
+ module Janus
2
+ module Models
3
+ # = Rememberable
4
+ #
5
+ # Allows a user to check a remember me check box when she logs in through
6
+ # DatabaseAuthenticatable. It will set a cookie with a configurable
7
+ # expiration date.
8
+ #
9
+ # == Required columns
10
+ #
11
+ # - remember_token
12
+ # - remember_created_at
13
+ #
14
+ # == Configuration
15
+ #
16
+ # - remember_for - how long to remember the user, for instance <tt>1.week</tt>.
17
+ # - :extend_remember_period - set to true to extend the remember cookie every time the user logs in.
18
+ #
19
+ module Rememberable
20
+ extend ActiveSupport::Concern
21
+
22
+ included do
23
+ attr_protected :remember_token, :remember_created_at
24
+ janus_config :remember_for, :extend_remember_period
25
+ end
26
+
27
+ # Generates an unique remote_token.
28
+ def remember_me!
29
+ self.remember_token = self.class.generate_token(:remember_token)
30
+ self.remember_created_at = Time.now
31
+ save
32
+ end
33
+
34
+ # Nullifies remote_token.
35
+ def forget_me!
36
+ self.remember_token = self.remember_created_at = nil
37
+ save
38
+ end
39
+
40
+ module ClassMethods
41
+ def find_for_remember_authentication(token)
42
+ user = where(:remember_token => token).first unless token.blank?
43
+
44
+ if user && user.remember_created_at < remember_for.ago
45
+ user.forget_me!
46
+ user = nil
47
+ end
48
+
49
+ user
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,99 @@
1
+ require 'janus/hooks/remote_authenticatable'
2
+
3
+ module Janus
4
+ module Models
5
+ # = RemoteAuthenticatable
6
+ #
7
+ # Keeping a user connected on subdomains is an easy task, all you need to do
8
+ # is define the session cookie to <tt>.example.com</tt> for instance. But
9
+ # keeping a user connected on multiple top level domains is a harder task.
10
+ #
11
+ # Hopefully RemoteAuthenticatable takes care of all the hassle.
12
+ #
13
+ # == Single Sign In
14
+ #
15
+ # The authentication must happen on a single domain, for instance
16
+ # <tt>login.example.com</tt>, then other domains must redirect to that
17
+ # domain's new session url. For instance:
18
+ #
19
+ # redirect_to new_user_session_url(:host => "login.example.com") unless user_signed_in?
20
+ #
21
+ # And that's it! The user shall be redirected with an unique +remote_token+,
22
+ # which shall log her in. Actually the user won't be logged in through
23
+ # Janus::Manager#login but through Janus::Manager#set_user which won't
24
+ # run the login hooks. This is useful for not tracking the user everytime
25
+ # it gets authenticated on each remote site.
26
+ #
27
+ # == Single Sign Out
28
+ #
29
+ # Session state is maintained across domains through the session_token
30
+ # column of your User model. If a session token is invalid the session
31
+ # is simply resetted, thus logging out the user on remote domains. Actually
32
+ # the user is logged out using Janus::Manager#unset_user before
33
+ # resetting the session.
34
+ #
35
+ # == Required columns and models:
36
+ #
37
+ # A +session_token+ column (string) is required, as well as a RemoteToken
38
+ # model like so:
39
+ #
40
+ # class RemoteToken < ActiveRecord::Base
41
+ # include Janus::Models::RemoteToken
42
+ #
43
+ # belongs_to :user
44
+ # validates_presence_of :user
45
+ # end
46
+ #
47
+ # With the associated table:
48
+ #
49
+ # create_table :remote_tokens do |t|
50
+ # t.references :user
51
+ # t.string :token
52
+ # t.datetime :created_at
53
+ # end
54
+ #
55
+ # add_index :remote_tokens, :token, :unique => true
56
+ module RemoteAuthenticatable
57
+ extend ActiveSupport::Concern
58
+
59
+ included do |klass|
60
+ attr_protected :session_token
61
+ klass.class_eval { has_many :remote_tokens }
62
+ janus_config :remote_authentication_key
63
+ end
64
+
65
+ # Generates an unique session token. This token will be used to validate
66
+ # the current session, and must be generated whenever a user signs in on
67
+ # the main site.
68
+ #
69
+ # The token won't be regenerated if it already exists.
70
+ def generate_session_token!
71
+ update_attribute(:session_token, self.class.generate_token(:session_token)) unless session_token
72
+ session_token
73
+ end
74
+
75
+ # Destroys the session token. This must be called whenever the user signs
76
+ # out. Doing so will invalidate all sessions using this token at once
77
+ # --hence single sign out.
78
+ def destroy_session_token!
79
+ update_attribute(:session_token, nil)
80
+ end
81
+
82
+ # Returns a temporary token to be used with find_for_remote_authentication.
83
+ def generate_remote_token!
84
+ remote_tokens.create.token
85
+ end
86
+
87
+ module ClassMethods
88
+ def find_for_remote_authentication(token)
89
+ remote_token = ::RemoteToken.where(:token => token).first
90
+
91
+ if remote_token
92
+ remote_token.destroy
93
+ remote_token.user unless remote_token.created_at < 30.seconds.ago
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,17 @@
1
+ module Janus
2
+ module Models
3
+ module RemoteToken
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+ include Janus::Models::Base
7
+ before_save :reset_token
8
+ end
9
+ end
10
+
11
+ # Generates an unique token.
12
+ def reset_token
13
+ self.token = self.class.generate_token(:token)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ require 'janus/hooks/trackable'
2
+
3
+ module Janus
4
+ module Models
5
+ # = Trackable
6
+ #
7
+ # Simple hook to update some columns of your model whenever a user logs in.
8
+ #
9
+ # == Required columns
10
+ #
11
+ # - +sign_in_count+
12
+ # - +current_sign_in_ip+
13
+ # - +current_sign_in_at+
14
+ # - +last_sign_in_ip+
15
+ # - +last_sign_in_at+
16
+ #
17
+ module Trackable
18
+ extend ActiveSupport::Concern
19
+
20
+ included do
21
+ attr_protected :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip
22
+ end
23
+
24
+ def track!(ip)
25
+ self.sign_in_count += 1
26
+
27
+ self.last_sign_in_at = self.current_sign_in_at
28
+ self.last_sign_in_ip = self.current_sign_in_ip
29
+
30
+ self.current_sign_in_at = Time.now
31
+ self.current_sign_in_ip = ip
32
+
33
+ save(:validate => false)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,78 @@
1
+ module ActionDispatch # :nodoc:
2
+ module Routing # :nodoc:
3
+ class Mapper
4
+ # Creates the routes for a Janus capable resource.
5
+ #
6
+ # Example:
7
+ #
8
+ # MyApp::Application.routes.draw do
9
+ # janus :users, :session => true, :registration => false
10
+ # end
11
+ #
12
+ # Options:
13
+ #
14
+ # - +session+ - true to generate session routes
15
+ # - +registration+ - true to generate registration routes
16
+ # - +confirmation+ - true to generate confirmation routes
17
+ # - +password+ - true to generate password reset routes
18
+ #
19
+ # Generated session routes:
20
+ #
21
+ # new_user_session GET /users/sign_in(.:format) {:controller=>"users/sessions", :action=>"new"}
22
+ # user_session POST /users/sign_in(.:format) {:controller=>"users/sessions", :action=>"create"}
23
+ # destroy_user_session /users/sign_out(.:format) {:controller=>"users/sessions", :action=>"destroy"}
24
+ #
25
+ # Generated registration routes:
26
+ #
27
+ # new_user_registration GET /users/sign_up(.:format) {:controller=>"users/registrations", :action=>"new"}
28
+ # user_registration POST /users(.:format) {:controller=>"users/registrations", :action=>"create"}
29
+ # edit_user_registration GET /users/edit(.:format) {:controller=>"users/registrations", :action=>"edit"}
30
+ # PUT /users(.:format) {:controller=>"users/registrations", :action=>"update"}
31
+ # DELETE /users(.:format) {:controller=>"users/registrations", :action=>"destroy"}
32
+ #
33
+ # Generated confirmation routes:
34
+ #
35
+ # user_confirmation POST /users/confirmation(.:format) {:controller=>"users/confirmations", :action=>"create"}
36
+ # new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"users/confirmations", :action=>"new"}
37
+ # GET /users/confirmation(.:format) {:controller=>"users/confirmations", :action=>"show"}
38
+ #
39
+ # Generated password reset routes:
40
+ #
41
+ # user_password POST /users/password(.:format) {:controller=>"users/passwords", :action=>"create"}
42
+ # new_user_password GET /users/password/new(.:format) {:controller=>"users/passwords", :action=>"new"}
43
+ # edit_user_password GET /users/password/edit(.:format) {:controller=>"users/passwords", :action=>"edit"}
44
+ # PUT /users/password(.:format) {:controller=>"users/passwords", :action=>"update"}
45
+ # DELETE /users/password(.:format) {:controller=>"users/passwords", :action=>"destroy"}
46
+ #
47
+ def janus(*resources)
48
+ ActionController::Base.send(:include, Janus::Helpers) unless ActionController::Base.include?(Janus::Helpers)
49
+ ActionController::Base.send(:include, Janus::UrlHelpers) unless ActionController::Base.include?(Janus::UrlHelpers)
50
+ options = resources.extract_options!
51
+
52
+ resources.each do |plural|
53
+ singular = plural.to_s.singularize
54
+
55
+ if options[:session]
56
+ scope :path => plural, :controller => "#{plural}/sessions" do
57
+ match "/sign_in(.:format)", :action => "new", :via => :get, :as => "new_#{singular}_session"
58
+ match "/sign_in(.:format)", :action => "create", :via => :post, :as => "#{singular}_session"
59
+ match "/sign_out(.:format)", :action => "destroy", :as => "destroy_#{singular}_session"
60
+ end
61
+ end
62
+
63
+ namespace plural, :as => singular do
64
+ if options[:registration]
65
+ resource :registration, :except => [:index, :show], :path => "",
66
+ :path_names => { :new => 'sign_up' }
67
+ end
68
+
69
+ resource :confirmation, :only => [:show, :new, :create] if options[:confirmation]
70
+ resource :password, :except => [:index, :show] if options[:password]
71
+ end
72
+
73
+ ActionController::Base.janus(singular)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,40 @@
1
+ module Janus
2
+ module Strategies
3
+ # Base class for writing authentication strategies.
4
+ class Base
5
+ attr_reader :scope, :manager, :request, :cookies, :user
6
+
7
+ def initialize(scope, manager) # :nodoc:
8
+ @scope, @manager = scope, manager
9
+ @request, @cookies = manager.request, manager.cookies
10
+ end
11
+
12
+ def valid?
13
+ true
14
+ end
15
+
16
+ def pass
17
+ end
18
+
19
+ def success!(user)
20
+ @user = user
21
+ end
22
+
23
+ def success?
24
+ !@user.nil?
25
+ end
26
+
27
+ def resource
28
+ @resource ||= scope.to_s.camelize.constantize
29
+ end
30
+
31
+ def authenticate!
32
+ raise StandardError.new("You must define the #{self.class.name}#authenticate! method.")
33
+ end
34
+
35
+ def auth_method
36
+ :login
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ #module Janus
2
+ # module Strategies
3
+ # class DatabaseAuthenticatable < Base
4
+ # def valid?
5
+ # if params[scope].blank? ||
6
+ # false
7
+ # else
8
+ # keys = resource.authentication_keys
9
+ # keys << :password
10
+ # keys.each { |key| return false if request.params[scope][key].blank? }
11
+ # true
12
+ # end
13
+ # end
14
+
15
+ # def authenticate!
16
+ # if params[]
17
+ # end
18
+ # end
19
+ # end
20
+ #end