oath 1.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 (94) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +165 -0
  7. data/LICENSE.txt +22 -0
  8. data/NEWS.rdoc +118 -0
  9. data/README.md +384 -0
  10. data/Rakefile +6 -0
  11. data/lib/oath.rb +132 -0
  12. data/lib/oath/back_door.rb +53 -0
  13. data/lib/oath/configuration.rb +149 -0
  14. data/lib/oath/constraints/signed_in.rb +14 -0
  15. data/lib/oath/constraints/signed_out.rb +14 -0
  16. data/lib/oath/controller_helpers.rb +161 -0
  17. data/lib/oath/failure_app.rb +48 -0
  18. data/lib/oath/field_map.rb +56 -0
  19. data/lib/oath/param_transformer.rb +38 -0
  20. data/lib/oath/railtie.rb +11 -0
  21. data/lib/oath/services.rb +5 -0
  22. data/lib/oath/services/authentication.rb +40 -0
  23. data/lib/oath/services/password_reset.rb +27 -0
  24. data/lib/oath/services/sign_in.rb +25 -0
  25. data/lib/oath/services/sign_out.rb +24 -0
  26. data/lib/oath/services/sign_up.rb +42 -0
  27. data/lib/oath/strategies/password_strategy.rb +42 -0
  28. data/lib/oath/test/controller_helpers.rb +43 -0
  29. data/lib/oath/test/helpers.rb +24 -0
  30. data/lib/oath/version.rb +4 -0
  31. data/lib/oath/warden_setup.rb +47 -0
  32. data/oath.gemspec +30 -0
  33. data/spec/features/user/user_signs_in_spec.rb +14 -0
  34. data/spec/features/user/user_signs_in_through_back_door_spec.rb +11 -0
  35. data/spec/features/user/user_tries_to_access_constrained_routes_spec.rb +18 -0
  36. data/spec/features/user/user_tries_to_access_http_auth_page_spec.rb +9 -0
  37. data/spec/features/visitor/visitor_fails_to_sign_up_spec.rb +10 -0
  38. data/spec/features/visitor/visitor_is_unauthorized_spec.rb +8 -0
  39. data/spec/features/visitor/visitor_signs_in_via_invalid_form_spec.rb +11 -0
  40. data/spec/features/visitor/visitor_signs_up_spec.rb +40 -0
  41. data/spec/features/visitor/visitor_tries_to_access_constrained_routes_spec.rb +14 -0
  42. data/spec/features/visitor/visitor_uses_remember_token_spec.rb +13 -0
  43. data/spec/oath/configuration_spec.rb +11 -0
  44. data/spec/oath/controller_helpers_spec.rb +180 -0
  45. data/spec/oath/field_map_spec.rb +19 -0
  46. data/spec/oath/services/authentication_spec.rb +25 -0
  47. data/spec/oath/services/password_reset_spec.rb +24 -0
  48. data/spec/oath/services/sign_in_spec.rb +13 -0
  49. data/spec/oath/services/sign_out_spec.rb +13 -0
  50. data/spec/oath/services/sign_up_spec.rb +49 -0
  51. data/spec/oath/strategies/password_strategy_spec.rb +23 -0
  52. data/spec/oath/test_controller_helpers_spec.rb +63 -0
  53. data/spec/oath/test_helpers_spec.rb +97 -0
  54. data/spec/oath_spec.rb +27 -0
  55. data/spec/rails_app/Rakefile +7 -0
  56. data/spec/rails_app/app/assets/images/rails.png +0 -0
  57. data/spec/rails_app/app/assets/javascripts/application.js +13 -0
  58. data/spec/rails_app/app/assets/stylesheets/application.css +13 -0
  59. data/spec/rails_app/app/controllers/application_controller.rb +4 -0
  60. data/spec/rails_app/app/controllers/basic_auth_controller.rb +7 -0
  61. data/spec/rails_app/app/controllers/constrained_to_users_controller.rb +5 -0
  62. data/spec/rails_app/app/controllers/constrained_to_visitors_controller.rb +5 -0
  63. data/spec/rails_app/app/controllers/failures_controller.rb +5 -0
  64. data/spec/rails_app/app/controllers/invalid_sessions_controller.rb +2 -0
  65. data/spec/rails_app/app/controllers/posts_controller.rb +6 -0
  66. data/spec/rails_app/app/controllers/sessions_controller.rb +26 -0
  67. data/spec/rails_app/app/controllers/users_controller.rb +23 -0
  68. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  69. data/spec/rails_app/app/models/user.rb +10 -0
  70. data/spec/rails_app/app/views/invalid_sessions/new.html.erb +4 -0
  71. data/spec/rails_app/app/views/layouts/application.html.erb +18 -0
  72. data/spec/rails_app/app/views/posts/index.html.erb +1 -0
  73. data/spec/rails_app/app/views/sessions/new.html.erb +5 -0
  74. data/spec/rails_app/app/views/users/new.html.erb +5 -0
  75. data/spec/rails_app/config.ru +4 -0
  76. data/spec/rails_app/config/application.rb +58 -0
  77. data/spec/rails_app/config/boot.rb +6 -0
  78. data/spec/rails_app/config/database.yml +25 -0
  79. data/spec/rails_app/config/environment.rb +5 -0
  80. data/spec/rails_app/config/environments/development.rb +29 -0
  81. data/spec/rails_app/config/environments/production.rb +54 -0
  82. data/spec/rails_app/config/environments/test.rb +29 -0
  83. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  84. data/spec/rails_app/config/initializers/inflections.rb +15 -0
  85. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  86. data/spec/rails_app/config/routes.rb +24 -0
  87. data/spec/rails_app/db/seeds.rb +7 -0
  88. data/spec/rails_app/public/404.html +26 -0
  89. data/spec/rails_app/public/422.html +26 -0
  90. data/spec/rails_app/public/500.html +25 -0
  91. data/spec/rails_app/public/favicon.ico +0 -0
  92. data/spec/rails_app/script/rails +6 -0
  93. data/spec/spec_helper.rb +37 -0
  94. metadata +325 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 68aae5082f1c535f427988290c1424f11b415313
4
+ data.tar.gz: 680198b631bfc9e899c17ed0618cd62d0af0d4f4
5
+ SHA512:
6
+ metadata.gz: 953c7077d5abff66905acdd54eee2de098ade20a6d39edc7ca3f718d97ae26b6a52a9c3dbbc7c846f3c55ac0b79ab87cb53139e046a192b8e46ff05517180a63
7
+ data.tar.gz: b389a8c3bea393096bc1114f0de8aa5ece4332019ad7e4d8c7de36cff6e197e2269a3528ec6231d02cf5be3405fb21da9403e63fc59be0fc888856cfb4ba73db
@@ -0,0 +1,7 @@
1
+ spec/rails_app/log/*
2
+ spec/rails_app/tmp/*
3
+ *.sqlite3
4
+ pkg
5
+ /.yardoc/
6
+ /_yardoc/
7
+ /doc/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.1
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,165 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ oath (1.1.0)
5
+ bcrypt
6
+ rails
7
+ warden
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actioncable (5.1.4)
13
+ actionpack (= 5.1.4)
14
+ nio4r (~> 2.0)
15
+ websocket-driver (~> 0.6.1)
16
+ actionmailer (5.1.4)
17
+ actionpack (= 5.1.4)
18
+ actionview (= 5.1.4)
19
+ activejob (= 5.1.4)
20
+ mail (~> 2.5, >= 2.5.4)
21
+ rails-dom-testing (~> 2.0)
22
+ actionpack (5.1.4)
23
+ actionview (= 5.1.4)
24
+ activesupport (= 5.1.4)
25
+ rack (~> 2.0)
26
+ rack-test (>= 0.6.3)
27
+ rails-dom-testing (~> 2.0)
28
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
29
+ actionview (5.1.4)
30
+ activesupport (= 5.1.4)
31
+ builder (~> 3.1)
32
+ erubi (~> 1.4)
33
+ rails-dom-testing (~> 2.0)
34
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
35
+ active_hash (1.5.2)
36
+ activesupport (>= 2.2.2)
37
+ activejob (5.1.4)
38
+ activesupport (= 5.1.4)
39
+ globalid (>= 0.3.6)
40
+ activemodel (5.1.4)
41
+ activesupport (= 5.1.4)
42
+ activerecord (5.1.4)
43
+ activemodel (= 5.1.4)
44
+ activesupport (= 5.1.4)
45
+ arel (~> 8.0)
46
+ activesupport (5.1.4)
47
+ concurrent-ruby (~> 1.0, >= 1.0.2)
48
+ i18n (~> 0.7)
49
+ minitest (~> 5.1)
50
+ tzinfo (~> 1.1)
51
+ addressable (2.5.2)
52
+ public_suffix (>= 2.0.2, < 4.0)
53
+ arel (8.0.0)
54
+ bcrypt (3.1.11)
55
+ builder (3.2.3)
56
+ capybara (2.16.1)
57
+ addressable
58
+ mini_mime (>= 0.1.3)
59
+ nokogiri (>= 1.3.3)
60
+ rack (>= 1.0.0)
61
+ rack-test (>= 0.5.4)
62
+ xpath (~> 2.0)
63
+ concurrent-ruby (1.0.5)
64
+ crass (1.0.3)
65
+ diff-lcs (1.3)
66
+ erubi (1.7.0)
67
+ globalid (0.4.1)
68
+ activesupport (>= 4.2.0)
69
+ i18n (0.9.1)
70
+ concurrent-ruby (~> 1.0)
71
+ loofah (2.1.1)
72
+ crass (~> 1.0.2)
73
+ nokogiri (>= 1.5.9)
74
+ mail (2.7.0)
75
+ mini_mime (>= 0.1.1)
76
+ method_source (0.9.0)
77
+ mini_mime (1.0.0)
78
+ mini_portile2 (2.3.0)
79
+ minitest (5.10.3)
80
+ nio4r (2.1.0)
81
+ nokogiri (1.8.1)
82
+ mini_portile2 (~> 2.3.0)
83
+ public_suffix (3.0.1)
84
+ rack (2.0.3)
85
+ rack-test (0.8.2)
86
+ rack (>= 1.0, < 3)
87
+ rails (5.1.4)
88
+ actioncable (= 5.1.4)
89
+ actionmailer (= 5.1.4)
90
+ actionpack (= 5.1.4)
91
+ actionview (= 5.1.4)
92
+ activejob (= 5.1.4)
93
+ activemodel (= 5.1.4)
94
+ activerecord (= 5.1.4)
95
+ activesupport (= 5.1.4)
96
+ bundler (>= 1.3.0)
97
+ railties (= 5.1.4)
98
+ sprockets-rails (>= 2.0.0)
99
+ rails-dom-testing (2.0.3)
100
+ activesupport (>= 4.2.0)
101
+ nokogiri (>= 1.6)
102
+ rails-html-sanitizer (1.0.3)
103
+ loofah (~> 2.0)
104
+ railties (5.1.4)
105
+ actionpack (= 5.1.4)
106
+ activesupport (= 5.1.4)
107
+ method_source
108
+ rake (>= 0.8.7)
109
+ thor (>= 0.18.1, < 2.0)
110
+ rake (12.3.0)
111
+ rspec (3.7.0)
112
+ rspec-core (~> 3.7.0)
113
+ rspec-expectations (~> 3.7.0)
114
+ rspec-mocks (~> 3.7.0)
115
+ rspec-core (3.7.0)
116
+ rspec-support (~> 3.7.0)
117
+ rspec-expectations (3.7.0)
118
+ diff-lcs (>= 1.2.0, < 2.0)
119
+ rspec-support (~> 3.7.0)
120
+ rspec-mocks (3.7.0)
121
+ diff-lcs (>= 1.2.0, < 2.0)
122
+ rspec-support (~> 3.7.0)
123
+ rspec-rails (3.7.2)
124
+ actionpack (>= 3.0)
125
+ activesupport (>= 3.0)
126
+ railties (>= 3.0)
127
+ rspec-core (~> 3.7.0)
128
+ rspec-expectations (~> 3.7.0)
129
+ rspec-mocks (~> 3.7.0)
130
+ rspec-support (~> 3.7.0)
131
+ rspec-support (3.7.0)
132
+ sprockets (3.7.1)
133
+ concurrent-ruby (~> 1.0)
134
+ rack (> 1, < 3)
135
+ sprockets-rails (3.2.1)
136
+ actionpack (>= 4.0)
137
+ activesupport (>= 4.0)
138
+ sprockets (>= 3.0.0)
139
+ sqlite3 (1.3.13)
140
+ thor (0.20.0)
141
+ thread_safe (0.3.6)
142
+ tzinfo (1.2.4)
143
+ thread_safe (~> 0.1)
144
+ warden (1.2.7)
145
+ rack (>= 1.0)
146
+ websocket-driver (0.6.5)
147
+ websocket-extensions (>= 0.1.0)
148
+ websocket-extensions (0.1.3)
149
+ xpath (2.1.0)
150
+ nokogiri (~> 1.3)
151
+
152
+ PLATFORMS
153
+ ruby
154
+
155
+ DEPENDENCIES
156
+ active_hash
157
+ capybara
158
+ oath!
159
+ rake
160
+ rspec
161
+ rspec-rails
162
+ sqlite3
163
+
164
+ BUNDLED WITH
165
+ 1.16.0
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 halogenandtoast
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,118 @@
1
+ == 1.1.0
2
+ * `Oath.config.sign_in_notice` should now be a callable object in order for I18n to work correctly
3
+ * [DEPRECATED] you should no longer set `Oath.config.sign_in_notice` to a string value
4
+
5
+ == 1.0.1
6
+ * Wrap helper_method calls in respond_to?(:helper_method)
7
+ * param_transformations now correctly use string keys
8
+
9
+ == 1.0.0
10
+ * Do not perform lookup if no params are passed to lookup
11
+ * Add param transformer for sanitizing and normalizing
12
+
13
+ == 0.3.1
14
+ * Extend private interface for services
15
+
16
+ == 0.3.0
17
+ * Warden serialization is now configurable
18
+
19
+ == 0.2.1
20
+ * Updated documentation for test helpers
21
+ * Updated documentation for using oath in console
22
+ * Fixed bug with failure app now allowing actual http auth to occur
23
+
24
+ == 0.2.0
25
+ * `sign_in` test helper now returns the user
26
+ * `authenticate_session` arguments are coerced to Hash
27
+ * Oath::BackDoor can be configured with a block
28
+ * Document validation suggestions
29
+ * Document locale suggestions
30
+ * Deprecate usage of Oath.user_class in favor of Oath.config.user_class
31
+ * Make warden strategy configurable via Oath.config.authentication_strategy
32
+ * Extract warden setup into the WardenSetup class
33
+ * Document layout suggestions
34
+
35
+ == 0.1.1
36
+ * Link to Rubydoc in documentation
37
+ * Fix header in documentation
38
+ * Fix no_login_redirect to default to a properly named controller
39
+ * Fix documentation reference to sign_up to mention user_params instead of user
40
+
41
+ == 0.1.0
42
+ * Fix PasswordStrategy to use configuration options
43
+ * Documentation
44
+ * Renamed encryption to hashing
45
+ * Renamed encrypted to digested
46
+ * Renamed unencrypted to undigested
47
+ * A configuration for `no_login_redirect` was added. This accepts anything that
48
+ can be passed to `redirect_to` and is used when `require_login` is called with
49
+ no logged in user.
50
+ * A configuration for `no_login_handler` was added. This allows developers to
51
+ completely customize the response when `require_login` is called with no
52
+ logged in user.
53
+
54
+ == 0.0.15
55
+ * Delegate user_class correctly so that config returns class
56
+ * Fixed issue authenticate session not allowing for multiple fields
57
+ * Do not hardcode User class
58
+ * Add signed out routing constraint
59
+ * Backfill NEWS.md
60
+
61
+ == 0.0.14
62
+ * Encryption of empty string is empty string.
63
+ * Remove last trace of generators.
64
+
65
+ == 0.0.13
66
+ * Oath requires Rails 4+.
67
+ * Move generators to the oath-generators gem.
68
+
69
+ == 0.0.12
70
+ * Ensure forms can't be tampered with by providing no username.
71
+ * Prevent hashing of empty string passwords.
72
+ * Memoize the configuration.
73
+
74
+ == 0.0.11
75
+ * Add `Oath::Backdoor` for easier tests.
76
+
77
+ == 0.0.10
78
+ * Add Oath::Test::ControllerHelpers for controller specs.
79
+ * Depend on the bcrypt gem, not the bcrypt-ruby gem.
80
+
81
+ == 0.0.9
82
+ * Make user creation method configurable.
83
+ * Redirect to SessionsController#new, ignoring namespace.
84
+ * Add `Oath.config.creation_method`.
85
+
86
+ == 0.0.8
87
+ * Now configurable via `Oath.configure`:
88
+ * sign in service
89
+ * sign up service
90
+ * authentication service
91
+ * user_token_store_field
92
+ * user_token_field
93
+ * Add PasswordReset service.
94
+ * Rename controller_helpers to services.
95
+ * Allos blocks to be passed into sign_in and sign_up.
96
+ * Fix error on trying to respond with HTTP 401.
97
+ * Oath does not generate a User model for you.
98
+ * Add `Oath.test_mode!` and `Oath.test_reset!`.
99
+ * Add a lot of tests.
100
+
101
+ == 0.0.7
102
+ * Check for Rails 4 or the strong_parameters gem, not just the strong_parameters gem
103
+
104
+ == 0.0.6
105
+ * [FIX] require_login should use controller and action for routing.
106
+
107
+ == 0.0.5
108
+ * [FIX] Scaffolded SessionsController should have respond_to.
109
+ * [FIX] SignUp should get the value instead of slicing.
110
+
111
+ == 0.0.4
112
+ * Cleaned up generated controllers.
113
+ * Use find_by_id instead of find so invalid sessions don't cause apps to crash.
114
+ * Hashes passed in are no longer mutated via delete.
115
+
116
+ == 0.0.3
117
+
118
+ * Fixed bug where password wasn't deleted from session params which would cause lookup to fail.
@@ -0,0 +1,384 @@
1
+
2
+ # Oath
3
+
4
+ [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/halogenandtoast/oath?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5
+
6
+ [![Build Status](https://travis-ci.org/halogenandtoast/oath.png?branch=master)](https://travis-ci.org/halogenandtoast/oath)
7
+ [![Code Climate](https://codeclimate.com/github/halogenandtoast/oath.png)](https://codeclimate.com/github/halogenandtoast/oath)
8
+
9
+ Oath is designed to be a very simple and extensible user authentication
10
+ library for rails. Its goal is to give all the power to the developer instead
11
+ of forcing them to make Oath work with their system.
12
+
13
+ ## Why use Oath?
14
+
15
+ Oath makes authentication simple:
16
+
17
+ - Easy to use in tests with dependency injection
18
+ - Provides convenient controller helpers
19
+ - Very customizable
20
+
21
+ Oath doesn't do the following:
22
+
23
+ - Doesn't automatically add routes to your application
24
+ - Doesn't force you to use engine based controllers or views
25
+ - Doesn't require you to make changes to your user model
26
+
27
+ ## Documentation
28
+
29
+ You can read the full documentation at [rubydoc](http://rubydoc.info/github/halogenandtoast/oath)
30
+
31
+ ## Installation
32
+
33
+ Oath was designed to work with Rails > 4.0. Add this line to your Gemfile:
34
+
35
+ gem 'oath'
36
+
37
+ Then inside of your ApplicationController add the following:
38
+
39
+ include Oath::ControllerHelpers
40
+
41
+ And you're ready to start designing your authentication system.
42
+
43
+ ## Generators
44
+
45
+ If you'd like a good starting point for building an app using Oath, it is suggested to use the [oath generators]
46
+
47
+ ## Usage
48
+
49
+ Oath does currently have some out-of-the-box expectations, but you can
50
+ configure and change any of these:
51
+
52
+ - By default the model should be called `User`
53
+ - Oath expects your user model to respond to `create`, `id`, and `find_by`
54
+ - You should have an `email` and `password_digest` column on your `User`
55
+ - Passwords will be handled with BCrypt
56
+
57
+ ### Suggestions
58
+
59
+ #### Console Usage
60
+
61
+ If you're trying to sign up a User in a console you won't be able to call User#new or User#create because the User model does not know how to encrypt passwords.
62
+ You should instead use the sign up service in order to create the user:
63
+
64
+ ```ruby
65
+ Oath.config.sign_up_service.new(email: "foo@example.com", password: "password").perform
66
+ ```
67
+
68
+ #### Validations
69
+
70
+ Oath doesn't add validations to your user model unless you're using [oath generators] so it's suggested to add the following validations:
71
+
72
+ ```ruby
73
+ validates :email, presence: true, uniqueness: true
74
+ validates :password_digest, presence: true
75
+ ```
76
+
77
+ In addition to that you'll want to add the following to your `config/locale/en.yml`:
78
+
79
+ ```yaml
80
+ en:
81
+ activerecord:
82
+ attributes:
83
+ user:
84
+ password_digest: "Password"
85
+ ```
86
+
87
+ Which will generate the error message `Password can't be blank` instead of `Password digest can't be blank`.
88
+
89
+ #### Layout changes
90
+
91
+ It is suggested you add something like this to your application layout:
92
+
93
+ ```erb
94
+ <% if signed_in? %>
95
+ <%= link_to "Sign out", session_path, method: :delete %>
96
+ <% else %>
97
+ <%= link_to "Sign in", new_session_path %>
98
+ <%= link_to "Sign up", new_user_path %>
99
+ <% end %>
100
+ ```
101
+
102
+ #### Guest user
103
+
104
+ If you want to introduce a Guest object when a user is not signed in, you can override Oath's `current_user` method in your `ApplicationController`:
105
+
106
+ ```ruby
107
+ def current_user
108
+ super || Guest.new
109
+ end
110
+ ```
111
+
112
+ In `app/models/`, define a `Guest` class:
113
+
114
+ ```ruby
115
+ class Guest
116
+ def name
117
+ "Guest"
118
+ end
119
+ end
120
+ ```
121
+
122
+ This article on the [Null Object Pattern](http://robots.thoughtbot.com/handling-associations-on-null-objects) provides a good explanation of why you might want to do this.
123
+
124
+ #### Using I18n for sign in notice
125
+
126
+ If you want to use I18n for the notice instructing users to sign in when they try to access an unauthorized page you can do so with the following configuration:
127
+
128
+ ```ruby
129
+ Oath.configure do |config|
130
+ config.sign_in_notice = -> { I18n.t("sign_in_notice") }
131
+ end
132
+ ```
133
+
134
+ It is suggested to store this file at `config/initializers/oath.rb`
135
+
136
+ ### Controller Additions
137
+
138
+ Oath provides the following controller methods:
139
+
140
+ - `sign_in(user)`
141
+ - `sign_out`
142
+ - `sign_up(user_params)`
143
+ - `authenticate(user, password)`
144
+ - `authenticate_session(session_params)`
145
+ - `reset_password(user, password)`
146
+
147
+ These helpers:
148
+
149
+ - `current_user`
150
+ - `signed_in?`
151
+
152
+ And this filter:
153
+
154
+ - `require_login`
155
+
156
+ ### Routing Constraints
157
+
158
+ To authorize users in `config/routes.rb`:
159
+
160
+ ```ruby
161
+ require "oath/constraints/signed_in"
162
+ require "oath/constraints/signed_out"
163
+
164
+ Blog::Application.routes.draw do
165
+ constraints Oath::Constraints::SignedIn.new do
166
+ root "dashboards#show", as: :dashboard
167
+ end
168
+
169
+ constraints Oath::Constraints::SignedOut.new do
170
+ root "landings#show"
171
+ end
172
+ end
173
+ ```
174
+
175
+ ## Usage in Tests
176
+
177
+ ### Test mode
178
+
179
+ Oath provides the following:
180
+
181
+ ```ruby
182
+ Oath.test_mode!
183
+ ```
184
+
185
+ Which will change password hashing method to provide plaintext responses instead of using BCrypt. This will allow you to write factories using the password_digest field:
186
+
187
+ ```ruby
188
+ FactoryBot.define do
189
+ factory :user do
190
+ username 'wombat'
191
+ password_digest 'password'
192
+ end
193
+ end
194
+ ```
195
+
196
+ ### Spec helpers
197
+
198
+ A couple of convenience methods are available in your tests. In order to set this up you'll want to add the following to `rails_helper.rb` or if that doesn't exist `spec_helper.rb`
199
+
200
+ ```ruby
201
+ Oath.test_mode!
202
+
203
+ RSpec.configure do |config|
204
+ config.include Oath::Test::Helpers, type: :feature
205
+ config.after :each do
206
+ Oath.test_reset!
207
+ end
208
+ end
209
+ ```
210
+
211
+ Then you can use any of the [test helpers] in your scenarios
212
+
213
+ ```ruby
214
+ feature "A feature spec" do
215
+ scenario "that requires login" do
216
+ user = create(:user)
217
+ sign_in(user)
218
+ # do something
219
+ sign_out
220
+ # do something else
221
+ end
222
+ end
223
+ ```
224
+
225
+ ### Oath Backdoor
226
+
227
+ Similar to clearance's backdoor you can visit a path and sign in quickly via
228
+
229
+ ```ruby
230
+ user = create(:user)
231
+ visit dashboard_path(as: user)
232
+ ```
233
+
234
+ To enable this functionality you'll want to add the following to `config/environments/test.rb`:
235
+
236
+ ```ruby
237
+ config.middleware.insert_after Warden::Manager, Oath::BackDoor
238
+ ```
239
+
240
+ If you'd like to find your User model by a field other than `id`, insert the
241
+ middleware with a block that accepts the `as` query parameter and returns an
242
+ instance of your User model:
243
+
244
+ ```ruby
245
+ config.middleware.insert_after Warden::Manager, Oath::BackDoor do |user_param|
246
+ User.find_by(username: user_param)
247
+ end
248
+ ```
249
+
250
+ ### Controller Specs
251
+
252
+ If you are going to write controller tests, helpers are provided for those as well:
253
+
254
+ ```ruby
255
+ Oath.test_mode!
256
+
257
+ RSpec.configure do |config|
258
+ config.include Oath::Test::ControllerHelpers, type: :controller
259
+ config.after :each do
260
+ Oath.test_reset!
261
+ end
262
+ end
263
+ ```
264
+
265
+ ```ruby
266
+ require 'spec_helper'
267
+
268
+ describe ProtectedController do
269
+
270
+ describe "GET 'index'" do
271
+ it "returns http success when signed in" do
272
+ user = create(:user)
273
+ sign_in(user)
274
+ get 'index'
275
+ response.should be_success
276
+ end
277
+
278
+ it "redirects when not signed in" do
279
+ get 'index'
280
+ response.should be_redirect
281
+ end
282
+ end
283
+ end
284
+ ```
285
+
286
+ ## Advanced Functionality
287
+
288
+ ### Authentication with username instead of email
289
+
290
+ If you want to sign in with username instead of email just change the configuration option
291
+
292
+ ```ruby
293
+ # config/initializers/oath.rb
294
+ Oath.configure do |config|
295
+ config.user_lookup_field = :username
296
+ end
297
+ ```
298
+
299
+ If you used the oath:scaffold generator from [oath generators] you'll have to change the following four references to email.
300
+
301
+ * In SessionsController#session_params
302
+ * In UsersController#user_params
303
+ * The email form field on sessions#new
304
+ * The email form field on users#new
305
+
306
+ ### Using multiple lookup fields
307
+
308
+ You may perform a look up on a user using multiple fields by doing something like the following:
309
+
310
+ ```ruby
311
+ class SessionsController < ApplicationController
312
+ def create
313
+ user = authenticate_session(session_params, email_or_username: [:email, :username])
314
+
315
+ if sign_in(user)
316
+ redirect_to(root_path)
317
+ else
318
+ render :new
319
+ end
320
+ end
321
+
322
+ private
323
+
324
+ def session_params
325
+ params.require(:session).permit(:email_or_username, :password)
326
+ end
327
+
328
+ end
329
+ ```
330
+
331
+ This will allow the user to enter either their username or email to login
332
+
333
+ ## Configuration
334
+
335
+ Oath::Configuration has lots of options for changing how oath works. Currently the options you can change are as follows:
336
+
337
+ ### User values
338
+
339
+ * **user_lookup_field**: (default `:email`) Field in the database to lookup a user by.
340
+ * **user_token_field**: (default `:password`) Field the form submits containing the undigested password.
341
+ * **user_token_store_field**: (default: `:password_digest`) Field in the database that stores the user's digested password.
342
+ * **user_class**: (default: `'User'`) The user class.
343
+
344
+ ### Services
345
+
346
+ * **sign_in_notice**: (default: `You must be signed in`) Rails flash message to set when user signs in.
347
+ * **sign_in_service**: (default: `Oath::Services::SignIn`) Service for signing a user in.
348
+ * **sign_up_service**: (default: `Oath::Services::SignUp`) Service for signing a user up.
349
+ * **sign_out_service**: (default: `Oath::Services::SignOut`) Service for signing a user out.
350
+ * **authentication_service**: (default: `Oath::Services::Authentication`) Service for authenticated a user.
351
+ * **password_reset_service**: (default: `Oath::Services::PasswordReset`) Service for resetting a user's password.
352
+
353
+ ### Rails values
354
+
355
+ * **no_login_handler**: A before_action for rails that handles when a user is not signed in.
356
+ * **no_login_redirect**: Used by the no_login_handler to redirect the user
357
+
358
+ ### Methods
359
+
360
+ * **hashing_method**: Method to hash an undigested password.
361
+ * **token_comparison**: Method to compare a digested and undigested password.
362
+ * **creation_method**: Method for creating a user.
363
+ * **find_method**: Method for finding a user.
364
+
365
+ ### Warden Settings
366
+
367
+ * **failure_app**: Necessary for warden to work. A rack app that handles failures in authentication.
368
+
369
+ ## Limitations
370
+
371
+ Here are a few of the current limitations of oath:
372
+
373
+ - Oath assumes you only have one user model.
374
+
375
+ ## Contributing
376
+
377
+ 1. [Fork it](https://github.com/halogenandtoast/oath/fork)
378
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
379
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
380
+ 4. Push to the branch (`git push origin my-new-feature`)
381
+ 5. Create new Pull Request
382
+
383
+ [oath generators]: https://github.com/halogenandtoast/oath-generators
384
+ [test helpers]: https://github.com/halogenandtoast/oath/blob/master/lib/oath/test/helpers.rb