oath 1.1.0

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