devise_token_auth_multi_email 0.9.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 (183) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +13 -0
  3. data/README.md +97 -0
  4. data/Rakefile +42 -0
  5. data/app/controllers/devise_token_auth/application_controller.rb +100 -0
  6. data/app/controllers/devise_token_auth/concerns/resource_finder.rb +68 -0
  7. data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +199 -0
  8. data/app/controllers/devise_token_auth/confirmations_controller.rb +89 -0
  9. data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +284 -0
  10. data/app/controllers/devise_token_auth/passwords_controller.rb +216 -0
  11. data/app/controllers/devise_token_auth/registrations_controller.rb +205 -0
  12. data/app/controllers/devise_token_auth/sessions_controller.rb +153 -0
  13. data/app/controllers/devise_token_auth/token_validations_controller.rb +31 -0
  14. data/app/controllers/devise_token_auth/unlocks_controller.rb +94 -0
  15. data/app/models/devise_token_auth/concerns/active_record_support.rb +18 -0
  16. data/app/models/devise_token_auth/concerns/confirmable_support.rb +28 -0
  17. data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
  18. data/app/models/devise_token_auth/concerns/tokens_serialization.rb +31 -0
  19. data/app/models/devise_token_auth/concerns/user.rb +282 -0
  20. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +39 -0
  21. data/app/validators/devise_token_auth_email_validator.rb +31 -0
  22. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  23. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  24. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  25. data/app/views/devise_token_auth/omniauth_external_window.html.erb +38 -0
  26. data/config/locales/da-DK.yml +52 -0
  27. data/config/locales/de.yml +51 -0
  28. data/config/locales/en.yml +60 -0
  29. data/config/locales/es.yml +51 -0
  30. data/config/locales/fa.yml +60 -0
  31. data/config/locales/fr.yml +51 -0
  32. data/config/locales/he.yml +52 -0
  33. data/config/locales/it.yml +48 -0
  34. data/config/locales/ja.yml +60 -0
  35. data/config/locales/ko.yml +51 -0
  36. data/config/locales/nl.yml +32 -0
  37. data/config/locales/pl.yml +51 -0
  38. data/config/locales/pt-BR.yml +48 -0
  39. data/config/locales/pt.yml +51 -0
  40. data/config/locales/ro.yml +48 -0
  41. data/config/locales/ru.yml +52 -0
  42. data/config/locales/sq.yml +48 -0
  43. data/config/locales/sv.yml +52 -0
  44. data/config/locales/uk.yml +61 -0
  45. data/config/locales/vi.yml +52 -0
  46. data/config/locales/zh-CN.yml +48 -0
  47. data/config/locales/zh-HK.yml +50 -0
  48. data/config/locales/zh-TW.yml +50 -0
  49. data/lib/devise_token_auth/blacklist.rb +6 -0
  50. data/lib/devise_token_auth/controllers/helpers.rb +157 -0
  51. data/lib/devise_token_auth/controllers/url_helpers.rb +10 -0
  52. data/lib/devise_token_auth/engine.rb +105 -0
  53. data/lib/devise_token_auth/errors.rb +8 -0
  54. data/lib/devise_token_auth/rails/routes.rb +122 -0
  55. data/lib/devise_token_auth/token_factory.rb +126 -0
  56. data/lib/devise_token_auth/url.rb +44 -0
  57. data/lib/devise_token_auth/version.rb +5 -0
  58. data/lib/devise_token_auth.rb +14 -0
  59. data/lib/generators/devise_token_auth/USAGE +31 -0
  60. data/lib/generators/devise_token_auth/install_generator.rb +91 -0
  61. data/lib/generators/devise_token_auth/install_generator_helpers.rb +98 -0
  62. data/lib/generators/devise_token_auth/install_mongoid_generator.rb +46 -0
  63. data/lib/generators/devise_token_auth/install_views_generator.rb +18 -0
  64. data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +66 -0
  65. data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +49 -0
  66. data/lib/generators/devise_token_auth/templates/user.rb.erb +9 -0
  67. data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +56 -0
  68. data/lib/tasks/devise_token_auth_tasks.rake +6 -0
  69. data/test/controllers/custom/custom_confirmations_controller_test.rb +25 -0
  70. data/test/controllers/custom/custom_omniauth_callbacks_controller_test.rb +33 -0
  71. data/test/controllers/custom/custom_passwords_controller_test.rb +79 -0
  72. data/test/controllers/custom/custom_registrations_controller_test.rb +63 -0
  73. data/test/controllers/custom/custom_sessions_controller_test.rb +39 -0
  74. data/test/controllers/custom/custom_token_validations_controller_test.rb +42 -0
  75. data/test/controllers/demo_group_controller_test.rb +151 -0
  76. data/test/controllers/demo_mang_controller_test.rb +313 -0
  77. data/test/controllers/demo_user_controller_test.rb +658 -0
  78. data/test/controllers/devise_token_auth/confirmations_controller_test.rb +275 -0
  79. data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +438 -0
  80. data/test/controllers/devise_token_auth/passwords_controller_test.rb +893 -0
  81. data/test/controllers/devise_token_auth/registrations_controller_test.rb +920 -0
  82. data/test/controllers/devise_token_auth/sessions_controller_test.rb +605 -0
  83. data/test/controllers/devise_token_auth/token_validations_controller_test.rb +142 -0
  84. data/test/controllers/devise_token_auth/unlocks_controller_test.rb +235 -0
  85. data/test/controllers/overrides/confirmations_controller_test.rb +47 -0
  86. data/test/controllers/overrides/omniauth_callbacks_controller_test.rb +53 -0
  87. data/test/controllers/overrides/passwords_controller_test.rb +64 -0
  88. data/test/controllers/overrides/registrations_controller_test.rb +46 -0
  89. data/test/controllers/overrides/sessions_controller_test.rb +35 -0
  90. data/test/controllers/overrides/token_validations_controller_test.rb +43 -0
  91. data/test/dummy/README.rdoc +28 -0
  92. data/test/dummy/app/active_record/confirmable_user.rb +11 -0
  93. data/test/dummy/app/active_record/lockable_user.rb +7 -0
  94. data/test/dummy/app/active_record/mang.rb +5 -0
  95. data/test/dummy/app/active_record/only_email_user.rb +7 -0
  96. data/test/dummy/app/active_record/scoped_user.rb +9 -0
  97. data/test/dummy/app/active_record/unconfirmable_user.rb +9 -0
  98. data/test/dummy/app/active_record/unregisterable_user.rb +9 -0
  99. data/test/dummy/app/active_record/user.rb +6 -0
  100. data/test/dummy/app/controllers/application_controller.rb +14 -0
  101. data/test/dummy/app/controllers/auth_origin_controller.rb +7 -0
  102. data/test/dummy/app/controllers/custom/confirmations_controller.rb +13 -0
  103. data/test/dummy/app/controllers/custom/omniauth_callbacks_controller.rb +13 -0
  104. data/test/dummy/app/controllers/custom/passwords_controller.rb +39 -0
  105. data/test/dummy/app/controllers/custom/registrations_controller.rb +39 -0
  106. data/test/dummy/app/controllers/custom/sessions_controller.rb +29 -0
  107. data/test/dummy/app/controllers/custom/token_validations_controller.rb +19 -0
  108. data/test/dummy/app/controllers/demo_group_controller.rb +15 -0
  109. data/test/dummy/app/controllers/demo_mang_controller.rb +14 -0
  110. data/test/dummy/app/controllers/demo_user_controller.rb +27 -0
  111. data/test/dummy/app/controllers/overrides/confirmations_controller.rb +29 -0
  112. data/test/dummy/app/controllers/overrides/omniauth_callbacks_controller.rb +16 -0
  113. data/test/dummy/app/controllers/overrides/passwords_controller.rb +36 -0
  114. data/test/dummy/app/controllers/overrides/registrations_controller.rb +29 -0
  115. data/test/dummy/app/controllers/overrides/sessions_controller.rb +36 -0
  116. data/test/dummy/app/controllers/overrides/token_validations_controller.rb +23 -0
  117. data/test/dummy/app/helpers/application_helper.rb +1058 -0
  118. data/test/dummy/app/models/concerns/favorite_color.rb +19 -0
  119. data/test/dummy/app/mongoid/confirmable_user.rb +52 -0
  120. data/test/dummy/app/mongoid/lockable_user.rb +38 -0
  121. data/test/dummy/app/mongoid/mang.rb +46 -0
  122. data/test/dummy/app/mongoid/only_email_user.rb +33 -0
  123. data/test/dummy/app/mongoid/scoped_user.rb +50 -0
  124. data/test/dummy/app/mongoid/unconfirmable_user.rb +44 -0
  125. data/test/dummy/app/mongoid/unregisterable_user.rb +47 -0
  126. data/test/dummy/app/mongoid/user.rb +49 -0
  127. data/test/dummy/app/views/layouts/application.html.erb +12 -0
  128. data/test/dummy/config/application.rb +50 -0
  129. data/test/dummy/config/application.yml.bk +0 -0
  130. data/test/dummy/config/boot.rb +11 -0
  131. data/test/dummy/config/environment.rb +7 -0
  132. data/test/dummy/config/environments/development.rb +36 -0
  133. data/test/dummy/config/environments/production.rb +68 -0
  134. data/test/dummy/config/environments/test.rb +58 -0
  135. data/test/dummy/config/initializers/backtrace_silencers.rb +9 -0
  136. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  137. data/test/dummy/config/initializers/devise.rb +290 -0
  138. data/test/dummy/config/initializers/devise_token_auth.rb +55 -0
  139. data/test/dummy/config/initializers/figaro.rb +3 -0
  140. data/test/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  141. data/test/dummy/config/initializers/inflections.rb +18 -0
  142. data/test/dummy/config/initializers/mime_types.rb +6 -0
  143. data/test/dummy/config/initializers/omniauth.rb +11 -0
  144. data/test/dummy/config/initializers/session_store.rb +5 -0
  145. data/test/dummy/config/initializers/wrap_parameters.rb +16 -0
  146. data/test/dummy/config/routes.rb +57 -0
  147. data/test/dummy/config/spring.rb +3 -0
  148. data/test/dummy/config.ru +18 -0
  149. data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +58 -0
  150. data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +57 -0
  151. data/test/dummy/db/migrate/20140829044006_add_operating_thetan_to_user.rb +8 -0
  152. data/test/dummy/db/migrate/20140916224624_add_favorite_color_to_mangs.rb +7 -0
  153. data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +55 -0
  154. data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +56 -0
  155. data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +56 -0
  156. data/test/dummy/db/migrate/20160103235141_devise_token_auth_create_scoped_users.rb +56 -0
  157. data/test/dummy/db/migrate/20160629184441_devise_token_auth_create_lockable_users.rb +56 -0
  158. data/test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb +49 -0
  159. data/test/dummy/db/schema.rb +198 -0
  160. data/test/dummy/lib/migration_database_helper.rb +43 -0
  161. data/test/dummy/tmp/generators/app/models/mang.rb +9 -0
  162. data/test/dummy/tmp/generators/app/models/user.rb +9 -0
  163. data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +60 -0
  164. data/test/dummy/tmp/generators/config/routes.rb +9 -0
  165. data/test/dummy/tmp/generators/db/migrate/20210305040222_devise_token_auth_create_mangs.rb +49 -0
  166. data/test/dummy/tmp/generators/db/migrate/20210305040222_devise_token_auth_create_users.rb +49 -0
  167. data/test/factories/users.rb +41 -0
  168. data/test/lib/devise_token_auth/blacklist_test.rb +19 -0
  169. data/test/lib/devise_token_auth/rails/custom_routes_test.rb +29 -0
  170. data/test/lib/devise_token_auth/rails/routes_test.rb +87 -0
  171. data/test/lib/devise_token_auth/token_factory_test.rb +191 -0
  172. data/test/lib/devise_token_auth/url_test.rb +26 -0
  173. data/test/lib/generators/devise_token_auth/install_generator_test.rb +217 -0
  174. data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +222 -0
  175. data/test/lib/generators/devise_token_auth/install_views_generator_test.rb +25 -0
  176. data/test/models/concerns/mongoid_support_test.rb +31 -0
  177. data/test/models/concerns/tokens_serialization_test.rb +104 -0
  178. data/test/models/confirmable_user_test.rb +35 -0
  179. data/test/models/only_email_user_test.rb +29 -0
  180. data/test/models/user_test.rb +224 -0
  181. data/test/support/controllers/routes.rb +43 -0
  182. data/test/test_helper.rb +134 -0
  183. metadata +502 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f38c0b3641519bd0810319419aaf08804b532fd43cb0096bb72cd8b88d889bb1
4
+ data.tar.gz: 81d521ee99a8ae5ccf45ae72be78d355d39350dd6344933703cac1b880f9d3a2
5
+ SHA512:
6
+ metadata.gz: 5f4ad633633d142a5f3d5dc4f33c1351d9040ceffd4e683b16fc3275f12444545ab3e576aec9b0fa42089dffde199bc3c9759aca480a3a1fc92d786c74d776c5
7
+ data.tar.gz: 8626946a5de31ccfc622e0a9b29a51640a414d478f70a2d77e931fc8854ae5dc9900218263327dd35d115dcb6c8c3c6360487425c76468d92b09d43a30a5b438
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2
+ Version 2, December 2004
3
+
4
+ Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
5
+
6
+ Everyone is permitted to copy and distribute verbatim or modified
7
+ copies of this license document, and changing it is allowed as long
8
+ as the name is changed.
9
+
10
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12
+
13
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
data/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # Devise Token Auth
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/devise_token_auth.svg)](http://badge.fury.io/rb/devise_token_auth)
4
+ [![Build Status](https://github.com/lynndylanhurley/devise_token_auth/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/lynndylanhurley/devise_token_auth/actions/workflows/test.yml)
5
+ [![Code Climate](https://codeclimate.com/github/lynndylanhurley/devise_token_auth/badges/gpa.svg)](https://codeclimate.com/github/lynndylanhurley/devise_token_auth)
6
+ [![Test Coverage](https://codeclimate.com/github/lynndylanhurley/devise_token_auth/badges/coverage.svg)](https://codeclimate.com/github/lynndylanhurley/devise_token_auth/coverage)
7
+ [![Downloads](https://img.shields.io/gem/dt/devise_token_auth.svg)](https://rubygems.org/gems/devise_token_auth)
8
+ [![Backers on Open Collective](https://opencollective.com/devise_token_auth/backers/badge.svg)](#backers)
9
+ [![Sponsors on Open Collective](https://opencollective.com/devise_token_auth/sponsors/badge.svg)](#sponsors)
10
+ [![Join the chat at https://gitter.im/lynndylanhurley/devise_token_auth](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lynndylanhurley/devise_token_auth?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
11
+
12
+ Simple, multi-client and secure token-based authentication for Rails.
13
+
14
+ If you're building SPA or a mobile app, and you want authentication, you need tokens, not cookies.
15
+ This gem refreshes the tokens on each request, and expires them in a short time, so the app is secure.
16
+ Also, it maintains a session for each client/device, so you can have as many sessions as you want.
17
+
18
+ ## Main features
19
+
20
+ * Seamless integration with:
21
+ * [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) for [AngularJS](https://github.com/angular/angular.js)
22
+ * [Angular-Token](https://github.com/neroniaky/angular-token) for [Angular](https://github.com/angular/angular)
23
+ * [redux-token-auth](https://github.com/kylecorbelli/redux-token-auth) for [React with Redux](https://github.com/reactjs/react-redux)
24
+ * [jToker](https://github.com/lynndylanhurley/j-toker) for [jQuery](https://jquery.com/)
25
+ * [vanilla-token-auth](https://github.com/theblang/vanilla-token-auth) for an unopinionated client
26
+ * [flutter_token_auth](https://github.com/diarmuidr3d/flutter_token_auth) for Flutter
27
+ * Oauth2 authentication using [OmniAuth](https://github.com/intridea/omniauth).
28
+ * Email authentication using [Devise](https://github.com/plataformatec/devise), including:
29
+ * User registration, update and deletion
30
+ * Login and logout
31
+ * Password reset, account confirmation
32
+ * Support for [multiple user models](./docs/usage/multiple_models.md).
33
+ * It is [secure](docs/security.md).
34
+
35
+ This project leverages the following gems:
36
+
37
+ * [Devise](https://github.com/plataformatec/devise)
38
+ * [OmniAuth](https://github.com/intridea/omniauth)
39
+
40
+ ## Installation
41
+
42
+ Add the following to your `Gemfile`:
43
+
44
+ ~~~ruby
45
+ gem 'devise_token_auth'
46
+ ~~~
47
+
48
+ Then install the gem using bundle:
49
+
50
+ ~~~bash
51
+ bundle install
52
+ ~~~
53
+
54
+ ## [Docs](https://devise-token-auth.gitbook.io/devise-token-auth)
55
+
56
+ ## Need help?
57
+
58
+ Please use [StackOverflow](https://stackoverflow.com/questions/tagged/devise-token-auth) for help requests and how-to questions.
59
+
60
+ Please open GitHub issues for bugs and enhancements only, not general help requests. Please search previous issues (and Google and StackOverflow) before creating a new issue.
61
+
62
+ Please read the [issue template](https://github.com/lynndylanhurley/devise_token_auth/blob/master/.github/ISSUE_TEMPLATE.md) before posting issues.
63
+
64
+ ## [FAQ](docs/faq.md)
65
+
66
+ ## Contributors wanted!
67
+
68
+ See our [Contribution Guidelines](https://github.com/lynndylanhurley/devise_token_auth/blob/master/.github/CONTRIBUTING.md). Feel free to submit pull requests, review pull requests, or review open issues. If you'd like to get in contact, [Zach Feldman](https://github.com/zachfeldman) has been wrangling this effort, you can reach him with his name @gmail. Further discussion of this in [this issue](https://github.com/lynndylanhurley/devise_token_auth/issues/969).
69
+
70
+ We have some bounties for some issues, [check them out](https://github.com/lynndylanhurley/devise_token_auth/issues?q=is%3Aopen+is%3Aissue+label%3Abounty)!
71
+
72
+ ## Live Demos
73
+
74
+ [Here is a demo](https://stackblitz.com/github/neroniaky/angular-token) of this app running with the [Angular-Token](https://github.com/neroniaky/angular-token) service and [Angular](https://github.com/angular/angular).
75
+
76
+ The fully configured api used in these demos can be found [here](https://github.com/lynndylanhurley/devise_token_auth_demo).
77
+
78
+
79
+ ## Contributors
80
+
81
+ <a href="graphs/contributors"><img src="https://opencollective.com/devise_token_auth/contributors.svg?width=890&button=false" /></a>
82
+
83
+ ## Backers
84
+
85
+ Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/devise_token_auth#backer)]
86
+
87
+ [![](https://opencollective.com/devise_token_auth/backers.svg?width=890)](https://opencollective.com/devise_token_auth#backers)
88
+
89
+
90
+ ## Sponsors
91
+
92
+ Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/devise_token_auth#sponsor)]
93
+
94
+ [![](https://opencollective.com/devise_token_auth/sponsor/0/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/0/website) [![](https://opencollective.com/devise_token_auth/sponsor/1/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/1/website) [![](https://opencollective.com/devise_token_auth/sponsor/2/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/2/website) [![](https://opencollective.com/devise_token_auth/sponsor/3/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/3/website) [![](https://opencollective.com/devise_token_auth/sponsor/4/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/4/website) [![](https://opencollective.com/devise_token_auth/sponsor/5/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/5/website) [![](https://opencollective.com/devise_token_auth/sponsor/6/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/6/website) [![](https://opencollective.com/devise_token_auth/sponsor/7/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/7/website) [![](https://opencollective.com/devise_token_auth/sponsor/8/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/8/website) [![](https://opencollective.com/devise_token_auth/sponsor/9/avatar.svg)](https://opencollective.com/devise_token_auth/sponsor/9/website)
95
+
96
+ ## License
97
+ This project uses the WTFPL
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rdoc/task'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'DeviseTokenAuth'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.rdoc')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
20
+ load 'rails/tasks/engine.rake'
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ t.warning = false
32
+ end
33
+
34
+ task default: :test
35
+
36
+ require 'rubocop/rake_task'
37
+
38
+ desc 'Run RuboCop'
39
+ RuboCop::RakeTask.new(:rubocop) do |task|
40
+ task.formatters = %w[fuubar offenses worst]
41
+ task.fail_on_error = false # don't abort rake on failure
42
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeviseTokenAuth
4
+ class ApplicationController < DeviseController
5
+ include DeviseTokenAuth::Concerns::SetUserByToken
6
+
7
+ def resource_data(opts = {})
8
+ response_data = opts[:resource_json] || @resource.as_json
9
+ response_data['type'] = @resource.class.name.parameterize if json_api?
10
+ response_data
11
+ end
12
+
13
+ def resource_errors
14
+ @resource.errors.to_hash.merge(full_messages: @resource.errors.full_messages)
15
+ end
16
+
17
+ protected
18
+
19
+ def blacklisted_redirect_url?(redirect_url)
20
+ DeviseTokenAuth.redirect_whitelist && !DeviseTokenAuth::Url.whitelisted?(redirect_url)
21
+ end
22
+
23
+ def build_redirect_headers(access_token, client, redirect_header_options = {})
24
+ {
25
+ DeviseTokenAuth.headers_names[:"access-token"] => access_token,
26
+ DeviseTokenAuth.headers_names[:"client"] => client,
27
+ :config => params[:config],
28
+
29
+ # Legacy parameters which may be removed in a future release.
30
+ # Consider using "client" and "access-token" in client code.
31
+ # See: github.com/lynndylanhurley/devise_token_auth/issues/993
32
+ :client_id => client,
33
+ :token => access_token
34
+ }.merge(redirect_header_options)
35
+ end
36
+
37
+ def params_for_resource(resource)
38
+ devise_parameter_sanitizer.instance_values['permitted'][resource].each do |type|
39
+ params[type.to_s] ||= request.headers[type.to_s] unless request.headers[type.to_s].nil?
40
+ end
41
+ devise_parameter_sanitizer.instance_values['permitted'][resource]
42
+ end
43
+
44
+ def resource_class(m = nil)
45
+ if m
46
+ mapping = Devise.mappings[m]
47
+ else
48
+ mapping = Devise.mappings[resource_name] || Devise.mappings.values.first
49
+ end
50
+
51
+ mapping.to
52
+ end
53
+
54
+ def json_api?
55
+ return false unless defined?(ActiveModel::Serializer)
56
+ return ActiveModel::Serializer.setup do |config|
57
+ config.adapter == :json_api
58
+ end if ActiveModel::Serializer.respond_to?(:setup)
59
+ ActiveModelSerializers.config.adapter == :json_api
60
+ end
61
+
62
+ def recoverable_enabled?
63
+ resource_class.devise_modules.include?(:recoverable)
64
+ end
65
+
66
+ def confirmable_enabled?
67
+ resource_class.devise_modules.include?(:confirmable)
68
+ end
69
+
70
+ def render_error(status, message, data = nil)
71
+ response = {
72
+ success: false,
73
+ errors: [message]
74
+ }
75
+ response = response.merge(data) if data
76
+ render json: response, status: status
77
+ end
78
+
79
+ def success_message(name, email)
80
+ if Devise.paranoid
81
+ I18n.t("devise_token_auth.#{name}.sended_paranoid")
82
+ else
83
+ I18n.t("devise_token_auth.#{name}.sended", email: email)
84
+ end
85
+ end
86
+
87
+ def redirect_options
88
+ {}
89
+ end
90
+
91
+ # When using a cookie to transport the auth token we can set it immediately in flows such as
92
+ # reset password and OmniAuth success, rather than making the client scrape the token from
93
+ # query params (to then send in the initial validate_token request).
94
+ # TODO: We should be able to stop exposing the token in query params when this method is used
95
+ def set_token_in_cookie(resource, token)
96
+ auth_header = resource.build_auth_headers(token.token, token.client)
97
+ cookies[DeviseTokenAuth.cookie_name] = DeviseTokenAuth.cookie_attributes.merge(value: auth_header.to_json)
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeviseTokenAuth::Concerns::ResourceFinder
4
+ extend ActiveSupport::Concern
5
+ include DeviseTokenAuth::Controllers::Helpers
6
+
7
+ def get_case_insensitive_field_from_resource_params(field)
8
+ # honor Devise configuration for case_insensitive keys
9
+ q_value = resource_params[field.to_sym]
10
+
11
+ if resource_class.case_insensitive_keys.include?(field.to_sym)
12
+ q_value.downcase!
13
+ end
14
+
15
+ if resource_class.strip_whitespace_keys.include?(field.to_sym)
16
+ q_value.strip!
17
+ end
18
+
19
+ q_value
20
+ end
21
+
22
+ def find_resource(field, value)
23
+ @@multi_email_field = if( defined? @@multi_email_field )
24
+ @@multi_email_field = if( defined?( Devise::MultiEmail.emails_association_name ).nil? )
25
+ Devise::MultiEmail.emails_association_name.to_s.singularize.to_sym
26
+ else
27
+ false
28
+ end
29
+ end
30
+
31
+ @resource = if :email == field && !@@multi_email_field
32
+ resource_class.find_by_email value
33
+ elsif database_adapter&.include?('mysql')
34
+ # fix for mysql default case insensitivity
35
+ field_sanitized = resource_class.connection.quote_column_name(field)
36
+ resource_class.where("BINARY #{field_sanitized} = ? AND provider= ?", value, provider).first
37
+ else
38
+ resource_class.dta_find_by(field => value, 'provider' => provider)
39
+ end
40
+ end
41
+
42
+ def database_adapter
43
+ @database_adapter ||= begin
44
+ rails_version = [Rails::VERSION::MAJOR, Rails::VERSION::MINOR].join(".")
45
+
46
+ adapter =
47
+ if rails_version >= "6.1"
48
+ resource_class.try(:connection_db_config)&.try(:adapter)
49
+ else
50
+ resource_class.try(:connection_config)&.try(:[], :adapter)
51
+ end
52
+ end
53
+ end
54
+
55
+ def resource_class(m = nil)
56
+ mapping = if m
57
+ Devise.mappings[m]
58
+ else
59
+ Devise.mappings[resource_name] || Devise.mappings.values.first
60
+ end
61
+
62
+ mapping.to
63
+ end
64
+
65
+ def provider
66
+ 'email'
67
+ end
68
+ end
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeviseTokenAuth::Concerns::SetUserByToken
4
+ extend ActiveSupport::Concern
5
+ include DeviseTokenAuth::Concerns::ResourceFinder
6
+
7
+ included do
8
+ before_action :set_request_start
9
+ after_action :update_auth_header
10
+ end
11
+
12
+ protected
13
+
14
+ # keep track of request duration
15
+ def set_request_start
16
+ @request_started_at = Time.zone.now
17
+ @used_auth_by_token = true
18
+
19
+ # initialize instance variables
20
+ @token ||= DeviseTokenAuth::TokenFactory.new
21
+ @resource ||= nil
22
+ @is_batch_request ||= nil
23
+ end
24
+
25
+ # user auth
26
+ def set_user_by_token(mapping = nil)
27
+ # determine target authentication class
28
+ rc = resource_class(mapping)
29
+
30
+ # no default user defined
31
+ return unless rc
32
+
33
+ # gets the headers names, which was set in the initialize file
34
+ uid_name = DeviseTokenAuth.headers_names[:'uid']
35
+ other_uid_name = DeviseTokenAuth.other_uid && DeviseTokenAuth.headers_names[DeviseTokenAuth.other_uid.to_sym]
36
+ access_token_name = DeviseTokenAuth.headers_names[:'access-token']
37
+ client_name = DeviseTokenAuth.headers_names[:'client']
38
+ authorization_name = DeviseTokenAuth.headers_names[:"authorization"]
39
+
40
+ # Read Authorization token and decode it if present
41
+ decoded_authorization_token = decode_bearer_token(request.headers[authorization_name])
42
+
43
+ # gets values from cookie if configured and present
44
+ parsed_auth_cookie = {}
45
+ if DeviseTokenAuth.cookie_enabled
46
+ auth_cookie = request.cookies[DeviseTokenAuth.cookie_name]
47
+ if auth_cookie.present?
48
+ parsed_auth_cookie = JSON.parse(auth_cookie)
49
+ end
50
+ end
51
+
52
+ # parse header for values necessary for authentication
53
+ uid = request.headers[uid_name] || params[uid_name] || parsed_auth_cookie[uid_name] || decoded_authorization_token[uid_name]
54
+ other_uid = other_uid_name && request.headers[other_uid_name] || params[other_uid_name] || parsed_auth_cookie[other_uid_name]
55
+ @token = DeviseTokenAuth::TokenFactory.new unless @token
56
+ @token.token ||= request.headers[access_token_name] || params[access_token_name] || parsed_auth_cookie[access_token_name] || decoded_authorization_token[access_token_name]
57
+ @token.client ||= request.headers[client_name] || params[client_name] || parsed_auth_cookie[client_name] || decoded_authorization_token[client_name]
58
+
59
+ # client isn't required, set to 'default' if absent
60
+ @token.client ||= 'default'
61
+
62
+ # check for an existing user, authenticated via warden/devise, if enabled
63
+ if DeviseTokenAuth.enable_standard_devise_support
64
+ devise_warden_user = warden.user(mapping)
65
+ if devise_warden_user && devise_warden_user.tokens[@token.client].nil?
66
+ @used_auth_by_token = false
67
+ @resource = devise_warden_user
68
+ # REVIEW: The following line _should_ be safe to remove;
69
+ # the generated token does not get used anywhere.
70
+ # @resource.create_new_auth_token
71
+ end
72
+ end
73
+
74
+ # user has already been found and authenticated
75
+ return @resource if @resource && @resource.is_a?(rc)
76
+
77
+ # ensure we clear the client
78
+ unless @token.present?
79
+ @token.client = nil
80
+ return
81
+ end
82
+
83
+ # mitigate timing attacks by finding by uid instead of auth token
84
+ user = (uid && rc.dta_find_by(uid: uid)) || (other_uid && rc.dta_find_by("#{DeviseTokenAuth.other_uid}": other_uid))
85
+ scope = rc.to_s.underscore.to_sym
86
+
87
+ if user && user.valid_token?(@token.token, @token.client)
88
+ # sign_in with bypass: true will be deprecated in the next version of Devise
89
+ if respond_to?(:bypass_sign_in) && DeviseTokenAuth.bypass_sign_in
90
+ bypass_sign_in(user, scope: scope)
91
+ else
92
+ sign_in(scope, user, store: false, event: :fetch, bypass: DeviseTokenAuth.bypass_sign_in)
93
+ end
94
+ return @resource = user
95
+ else
96
+ # zero all values previously set values
97
+ @token.client = nil
98
+ return @resource = nil
99
+ end
100
+ end
101
+
102
+ def update_auth_header
103
+ # cannot save object if model has invalid params
104
+ return unless @resource && @token.client
105
+
106
+ # Generate new client with existing authentication
107
+ @token.client = nil unless @used_auth_by_token
108
+
109
+ if @used_auth_by_token && !DeviseTokenAuth.change_headers_on_each_request
110
+ # should not append auth header if @resource related token was
111
+ # cleared by sign out in the meantime
112
+ return if @resource.reload.tokens[@token.client].nil?
113
+
114
+ auth_header = @resource.build_auth_headers(@token.token, @token.client)
115
+
116
+ # update the response header
117
+ response.headers.merge!(auth_header)
118
+
119
+ # set a server cookie if configured
120
+ if DeviseTokenAuth.cookie_enabled
121
+ set_cookie(auth_header)
122
+ end
123
+ else
124
+ unless @resource.reload.valid?
125
+ @resource = @resource.class.find(@resource.to_param) # errors remain after reload
126
+ # if we left the model in a bad state, something is wrong in our app
127
+ unless @resource.valid?
128
+ raise DeviseTokenAuth::Errors::InvalidModel, "Cannot set auth token in invalid model. Errors: #{@resource.errors.full_messages}"
129
+ end
130
+ end
131
+ refresh_headers
132
+ end
133
+ end
134
+
135
+ private
136
+
137
+ def decode_bearer_token(bearer_token)
138
+ return {} if bearer_token.blank?
139
+
140
+ encoded_token = bearer_token.split.last # Removes the 'Bearer' from the string
141
+ JSON.parse(Base64.strict_decode64(encoded_token)) rescue {}
142
+ end
143
+
144
+ def refresh_headers
145
+ # Lock the user record during any auth_header updates to ensure
146
+ # we don't have write contention from multiple threads
147
+ @resource.with_lock do
148
+ # should not append auth header if @resource related token was
149
+ # cleared by sign out in the meantime
150
+ return if @used_auth_by_token && @resource.tokens[@token.client].nil?
151
+
152
+ _auth_header_from_batch_request = auth_header_from_batch_request
153
+
154
+ # update the response header
155
+ response.headers.merge!(_auth_header_from_batch_request)
156
+
157
+ # set a server cookie if configured and is not a batch request
158
+ if DeviseTokenAuth.cookie_enabled && !@is_batch_request
159
+ set_cookie(_auth_header_from_batch_request)
160
+ end
161
+ end # end lock
162
+ end
163
+
164
+ def set_cookie(auth_header)
165
+ cookies[DeviseTokenAuth.cookie_name] = DeviseTokenAuth.cookie_attributes.merge(value: auth_header.to_json)
166
+ end
167
+
168
+ def is_batch_request?(user, client)
169
+ !params[:unbatch] &&
170
+ user.tokens[client] &&
171
+ user.tokens[client]['updated_at'] &&
172
+ user.tokens[client]['updated_at'].to_time > @request_started_at - DeviseTokenAuth.batch_request_buffer_throttle
173
+ end
174
+
175
+ def auth_header_from_batch_request
176
+ # determine batch request status after request processing, in case
177
+ # another processes has updated it during that processing
178
+ @is_batch_request = is_batch_request?(@resource, @token.client)
179
+
180
+ auth_header = {}
181
+ # extend expiration of batch buffer to account for the duration of
182
+ # this request
183
+ if @is_batch_request
184
+ auth_header = @resource.extend_batch_buffer(@token.token, @token.client)
185
+
186
+ # Do not return token for batch requests to avoid invalidated
187
+ # tokens returned to the client in case of race conditions.
188
+ # Use a blank string for the header to still be present and
189
+ # being passed in a XHR response in case of
190
+ # 304 Not Modified responses.
191
+ auth_header[DeviseTokenAuth.headers_names[:"access-token"]] = ' '
192
+ auth_header[DeviseTokenAuth.headers_names[:"expiry"]] = ' '
193
+ else
194
+ # update Authorization response header with new token
195
+ auth_header = @resource.create_new_auth_token(@token.client)
196
+ end
197
+ auth_header
198
+ end
199
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeviseTokenAuth
4
+ class ConfirmationsController < DeviseTokenAuth::ApplicationController
5
+
6
+ def show
7
+ @resource = resource_class.confirm_by_token(resource_params[:confirmation_token])
8
+
9
+ if @resource.errors.empty?
10
+ yield @resource if block_given?
11
+
12
+ redirect_header_options = { account_confirmation_success: true }
13
+
14
+ if signed_in?(resource_name)
15
+ token = signed_in_resource.create_token
16
+ signed_in_resource.save!
17
+
18
+ redirect_headers = build_redirect_headers(token.token,
19
+ token.client,
20
+ redirect_header_options)
21
+
22
+ redirect_to_link = signed_in_resource.build_auth_url(redirect_url, redirect_headers)
23
+ else
24
+ redirect_to_link = DeviseTokenAuth::Url.generate(redirect_url, redirect_header_options)
25
+ end
26
+
27
+ redirect_to(redirect_to_link, redirect_options)
28
+ else
29
+ if redirect_url
30
+ redirect_to DeviseTokenAuth::Url.generate(redirect_url, account_confirmation_success: false), redirect_options
31
+ else
32
+ raise ActionController::RoutingError, 'Not Found'
33
+ end
34
+ end
35
+ end
36
+
37
+ def create
38
+ return render_create_error_missing_email if resource_params[:email].blank?
39
+
40
+ @email = get_case_insensitive_field_from_resource_params(:email)
41
+
42
+ @resource = resource_class.dta_find_by(uid: @email, provider: provider)
43
+
44
+ return render_not_found_error unless @resource
45
+
46
+ @resource.send_confirmation_instructions({
47
+ redirect_url: redirect_url,
48
+ client_config: resource_params[:config_name]
49
+ })
50
+
51
+ return render_create_success
52
+ end
53
+
54
+ protected
55
+
56
+ def render_create_error_missing_email
57
+ render_error(401, I18n.t('devise_token_auth.confirmations.missing_email'))
58
+ end
59
+
60
+ def render_create_success
61
+ render json: {
62
+ success: true,
63
+ message: success_message('confirmations', @email)
64
+ }
65
+ end
66
+
67
+ def render_not_found_error
68
+ if Devise.paranoid
69
+ render_create_success
70
+ else
71
+ render_error(404, I18n.t('devise_token_auth.confirmations.user_not_found', email: @email))
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def resource_params
78
+ params.permit(:email, :confirmation_token, :config_name)
79
+ end
80
+
81
+ # give redirect value from params priority or fall back to default value if provided
82
+ def redirect_url
83
+ params.fetch(
84
+ :redirect_url,
85
+ DeviseTokenAuth.default_confirm_success_url
86
+ )
87
+ end
88
+ end
89
+ end