diff --git a/.travis.yml b/.travis.yml index a583f5574..30db4c1e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,12 +11,14 @@ rvm: - 2.4.7 - 2.5.6 - 2.6.4 + - 2.7.0 gemfile: - gemfiles/rails_4_2.gemfile - gemfiles/rails_5_0.gemfile - gemfiles/rails_5_1.gemfile - gemfiles/rails_5_2.gemfile + - gemfiles/rails_6_0.gemfile env: global: @@ -28,51 +30,60 @@ env: matrix: include: - - rvm: 2.3.8 - gemfile: gemfiles/rails_4_2_mongoid_5.gemfile - env: DEVISE_TOKEN_AUTH_ORM=mongoid - - rvm: 2.3.8 - gemfile: gemfiles/rails_5_1_mongoid_6.gemfile - env: DEVISE_TOKEN_AUTH_ORM=mongoid - - rvm: 2.4.7 - gemfile: gemfiles/rails_5_1_mongoid_7.gemfile - env: DEVISE_TOKEN_AUTH_ORM=mongoid - - rvm: 2.5.6 - gemfile: gemfiles/rails_5_2_mongoid_6.gemfile - env: DEVISE_TOKEN_AUTH_ORM=mongoid - - rvm: 2.5.6 - gemfile: gemfiles/rails_5_2_mongoid_7.gemfile - env: DEVISE_TOKEN_AUTH_ORM=mongoid - - rvm: 2.6.4 - gemfile: gemfiles/rails_5_2_mongoid_7.gemfile - env: DEVISE_TOKEN_AUTH_ORM=mongoid - - name: Code Climate Test Coverage - rmv: 2.5.6 - env: - - CC_TEST_REPORTER_ID=44d7688de8e1b567b4af25ec5083c2cc0a355ab911192a7cbefd1ea25b2ffd3d - - GEMFILE_AR=gemfiles/rails_5_1.gemfile - - GEMFILE_MONGOID=gemfiles/rails_5_1_mongoid_7.gemfile - script: - - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - - chmod +x ./cc-test-reporter - - ./cc-test-reporter before-build - # with ActiveRecord - - bundle install --jobs=3 --retry=3 --gemfile $GEMFILE_AR - - BUNDLE_GEMFILE=$GEMFILE_AR bundle exec rake --trace db:migrate - - BUNDLE_GEMFILE=$GEMFILE_AR bundle exec rake - - ./cc-test-reporter format-coverage -t simplecov -o coverage/codeclimate.active_record.json coverage/.resultset.json - # with Mongoid - - bundle install --jobs=3 --retry=3 --gemfile $GEMFILE_MONGOID - - BUNDLE_GEMFILE=$GEMFILE_MONGOID DEVISE_TOKEN_AUTH_ORM=mongoid bundle exec rake - - ./cc-test-reporter format-coverage -t simplecov -o coverage/codeclimate.mongoid.json coverage/.resultset.json - # merge test results - - if [[ "$TRAVIS_TEST_RESULT" == 0 ]]; then + - rvm: 2.3.8 + gemfile: gemfiles/rails_4_2_mongoid_5.gemfile + env: DEVISE_TOKEN_AUTH_ORM=mongoid + - rvm: 2.3.8 + gemfile: gemfiles/rails_5_1_mongoid_6.gemfile + env: DEVISE_TOKEN_AUTH_ORM=mongoid + - rvm: 2.4.7 + gemfile: gemfiles/rails_5_1_mongoid_7.gemfile + env: DEVISE_TOKEN_AUTH_ORM=mongoid + - rvm: 2.5.6 + gemfile: gemfiles/rails_5_2_mongoid_6.gemfile + env: DEVISE_TOKEN_AUTH_ORM=mongoid + - rvm: 2.5.6 + gemfile: gemfiles/rails_5_2_mongoid_7.gemfile + env: DEVISE_TOKEN_AUTH_ORM=mongoid + - rvm: 2.6.4 + gemfile: gemfiles/rails_5_2_mongoid_7.gemfile + env: DEVISE_TOKEN_AUTH_ORM=mongoid + - rvm: 2.7.0 + gemfile: gemfiles/rails_6_0_mongoid_7.gemfile + env: DEVISE_TOKEN_AUTH_ORM=mongoid + - name: Code Climate Test Coverage + rvm: 2.5.6 + env: + - CC_TEST_REPORTER_ID=44d7688de8e1b567b4af25ec5083c2cc0a355ab911192a7cbefd1ea25b2ffd3d + - GEMFILE_AR=gemfiles/rails_5_1.gemfile + - GEMFILE_MONGOID=gemfiles/rails_5_1_mongoid_7.gemfile + script: + - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter + - chmod +x ./cc-test-reporter + - ./cc-test-reporter before-build + # with ActiveRecord + - bundle install --jobs=3 --retry=3 --gemfile $GEMFILE_AR + - BUNDLE_GEMFILE=$GEMFILE_AR bundle exec rake --trace db:migrate + - BUNDLE_GEMFILE=$GEMFILE_AR bundle exec rake + - ./cc-test-reporter format-coverage coverage/.resultset.json -t simplecov -o coverage/codeclimate.active_record.json + # with Mongoid + - bundle install --jobs=3 --retry=3 --gemfile $GEMFILE_MONGOID + - BUNDLE_GEMFILE=$GEMFILE_MONGOID DEVISE_TOKEN_AUTH_ORM=mongoid bundle exec rake + - ./cc-test-reporter format-coverage coverage/.resultset.json -t simplecov -o coverage/codeclimate.mongoid.json + # merge test results + - if [[ "$TRAVIS_TEST_RESULT" == 0 ]]; then ./cc-test-reporter sum-coverage coverage/codeclimate.active_record.json coverage/codeclimate.mongoid.json; ./cc-test-reporter upload-coverage; - fi + fi exclude: - rvm: 2.6.4 gemfile: gemfiles/rails_4_2.gemfile + - rvm: 2.7.0 + gemfile: gemfiles/rails_4_2.gemfile + - rvm: 2.3.8 + gemfile: gemfiles/rails_6_0.gemfile + - rvm: 2.4.7 + gemfile: gemfiles/rails_6_0.gemfile fast_finish: true before_install: diff --git a/Appraisals b/Appraisals index 0a5fd61b8..dfb2bb1e1 100644 --- a/Appraisals +++ b/Appraisals @@ -32,7 +32,8 @@ end { name: '5-1', ruby: '2.4.5', rails: '5.1', mongoid: '7.0' }, { name: '5-2', ruby: '2.5.5', rails: '5.2', mongoid: '6.4' }, { name: '5-2', ruby: '2.5.5', rails: '5.2', mongoid: '7.0' }, - { name: '5-2', ruby: '2.6.2', rails: '5.2', mongoid: '7.0' } + { name: '5-2', ruby: '2.6.2', rails: '5.2', mongoid: '7.0' }, + { name: '6-0', ruby: '2.7.0', rails: '6.0', mongoid: '7.0' } ].each do |set| appraise "rails-#{set[:name]}-mongoid-#{set[:mongoid][0]}" do gem 'rails', "~> #{set[:rails]}" diff --git a/CHANGELOG.md b/CHANGELOG.md index e7c273a2d..9a074e690 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,47 @@ +# Changelog + +## [v1.1.4](https://github.com/lynndylanhurley/devise_token_auth/tree/v1.1.4) (2020-06-02) + +[Full Changelog](https://github.com/lynndylanhurley/devise_token_auth/compare/v1.1.3...v1.1.4) + +**Closed issues:** + +- possible to disable the self-registration endpoint? [\#1402](https://github.com/lynndylanhurley/devise_token_auth/issues/1402) +- Axios formatting and Rails controller validation? [\#1380](https://github.com/lynndylanhurley/devise_token_auth/issues/1380) +- NoMethodError \(undefined method `client' for "\":String\) [\#1375](https://github.com/lynndylanhurley/devise_token_auth/issues/1375) +- mation\_instruction [\#1373](https://github.com/lynndylanhurley/devise_token_auth/issues/1373) +- Unpermitted parameter :session when signing in using javascript fetch [\#1361](https://github.com/lynndylanhurley/devise_token_auth/issues/1361) +- How do i authenticate with graphql-ruby? [\#1360](https://github.com/lynndylanhurley/devise_token_auth/issues/1360) +- Using DeviseTokenAuth::Concerns::User breaks Devise::confirmable and Devise::reconfirmable [\#1013](https://github.com/lynndylanhurley/devise_token_auth/issues/1013) + +**Merged pull requests:** + +- Update faq.md [\#1401](https://github.com/lynndylanhurley/devise_token_auth/pull/1401) ([mdjamal](https://github.com/mdjamal)) +- Update assign\_provider\_attrs to strip 'name' field [\#1398](https://github.com/lynndylanhurley/devise_token_auth/pull/1398) ([SpLouk](https://github.com/SpLouk)) +- Fix grammar [\#1396](https://github.com/lynndylanhurley/devise_token_auth/pull/1396) ([arku](https://github.com/arku)) +- \[Refactor\] fixed "not\_email" setting in ja.yml [\#1395](https://github.com/lynndylanhurley/devise_token_auth/pull/1395) ([h-sada](https://github.com/h-sada)) +- CI build fix: Pin to pry \< 0.13 for 2.3 support, workaround CodeClimate reporter issue [\#1393](https://github.com/lynndylanhurley/devise_token_auth/pull/1393) ([olleolleolle](https://github.com/olleolleolle)) +- Fix broken link [\#1392](https://github.com/lynndylanhurley/devise_token_auth/pull/1392) ([dlederle](https://github.com/dlederle)) +- Fix: Save user authentication token after email confirmation [\#1391](https://github.com/lynndylanhurley/devise_token_auth/pull/1391) ([gabrielbursztein2](https://github.com/gabrielbursztein2)) +- Fix token-type header key in testing example docs [\#1390](https://github.com/lynndylanhurley/devise_token_auth/pull/1390) ([goalaleo](https://github.com/goalaleo)) +- Issue - 1358 Argument error when converting token updated\_at using to… [\#1388](https://github.com/lynndylanhurley/devise_token_auth/pull/1388) ([saichander17](https://github.com/saichander17)) +- Validate that token is valid for patch request last token [\#1386](https://github.com/lynndylanhurley/devise_token_auth/pull/1386) ([ahmedmagdy711](https://github.com/ahmedmagdy711)) +- Fix docs/usage/reset\_password.md [\#1382](https://github.com/lynndylanhurley/devise_token_auth/pull/1382) ([K-Sato1995](https://github.com/K-Sato1995)) +- Fix missing polish and portugese missing translation errors [\#1377](https://github.com/lynndylanhurley/devise_token_auth/pull/1377) ([woochaq](https://github.com/woochaq)) +- \[Documentation\] write complete path for authentication\_test\_spec.rb [\#1376](https://github.com/lynndylanhurley/devise_token_auth/pull/1376) ([cprodhomme](https://github.com/cprodhomme)) +- Add case sensitive option required to prevent deprecation warning in … [\#1368](https://github.com/lynndylanhurley/devise_token_auth/pull/1368) ([niciliketo](https://github.com/niciliketo)) +- Add rails 6.0 config to travis [\#1366](https://github.com/lynndylanhurley/devise_token_auth/pull/1366) ([brateq](https://github.com/brateq)) +- Add docs for confirmation endpoint [\#1365](https://github.com/lynndylanhurley/devise_token_auth/pull/1365) ([brateq](https://github.com/brateq)) +- Remove Trackable option from generator [\#1362](https://github.com/lynndylanhurley/devise_token_auth/pull/1362) ([SugiKent](https://github.com/SugiKent)) +- Please merge again [\#1350](https://github.com/lynndylanhurley/devise_token_auth/pull/1350) ([exocode](https://github.com/exocode)) +- Fix dead link [\#1349](https://github.com/lynndylanhurley/devise_token_auth/pull/1349) ([tegandbiscuits](https://github.com/tegandbiscuits)) +- detect Mongoid \(till Mongoid will implement it\) [\#1348](https://github.com/lynndylanhurley/devise_token_auth/pull/1348) ([exocode](https://github.com/exocode)) +- feat\(oauth-apple\): support Sign in with Apple as a documented OmniAuth provider [\#1347](https://github.com/lynndylanhurley/devise_token_auth/pull/1347) ([booleanbetrayal](https://github.com/booleanbetrayal)) +- Add Korean locale [\#1346](https://github.com/lynndylanhurley/devise_token_auth/pull/1346) ([sdu6342](https://github.com/sdu6342)) +- doc: remove duplicated test case on ./docs/usage/testing.md [\#1344](https://github.com/lynndylanhurley/devise_token_auth/pull/1344) ([miyataka](https://github.com/miyataka)) +- Fix to be able to use Devise::confirmable module [\#1343](https://github.com/lynndylanhurley/devise_token_auth/pull/1343) ([makicamel](https://github.com/makicamel)) +- repeat any query params after a fragment [\#1341](https://github.com/lynndylanhurley/devise_token_auth/pull/1341) ([colmben](https://github.com/colmben)) + # Change Log ## [v1.1.3](https://github.com/lynndylanhurley/devise_token_auth/tree/v1.1.3) (2019-09-26) @@ -2923,4 +2967,6 @@ \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* -\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* + +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/app/controllers/devise_token_auth/concerns/set_user_by_token.rb b/app/controllers/devise_token_auth/concerns/set_user_by_token.rb index 0d03a47bc..40800d056 100644 --- a/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +++ b/app/controllers/devise_token_auth/concerns/set_user_by_token.rb @@ -17,7 +17,7 @@ def set_request_start @used_auth_by_token = true # initialize instance variables - @token = DeviseTokenAuth::TokenFactory.new + @token ||= DeviseTokenAuth::TokenFactory.new @resource ||= nil @is_batch_request ||= nil end @@ -46,7 +46,7 @@ def set_user_by_token(mapping = nil) # check for an existing user, authenticated via warden/devise, if enabled if DeviseTokenAuth.enable_standard_devise_support - devise_warden_user = warden.user(rc.to_s.underscore.to_sym) + devise_warden_user = warden.user(mapping) if devise_warden_user && devise_warden_user.tokens[@token.client].nil? @used_auth_by_token = false @resource = devise_warden_user @@ -140,7 +140,7 @@ def update_auth_header else unless @resource.reload.valid? - @resource = resource_class.find(@resource.to_param) # errors remain after reload + @resource = @resource.class.find(@resource.to_param) # errors remain after reload # if we left the model in a bad state, something is wrong in our app unless @resource.valid? raise DeviseTokenAuth::Errors::InvalidModel, "Cannot set auth token in invalid model. Errors: #{@resource.errors.full_messages}" diff --git a/app/controllers/devise_token_auth/confirmations_controller.rb b/app/controllers/devise_token_auth/confirmations_controller.rb index 7bc05a2ad..d06bd9ca2 100644 --- a/app/controllers/devise_token_auth/confirmations_controller.rb +++ b/app/controllers/devise_token_auth/confirmations_controller.rb @@ -13,6 +13,7 @@ def show if signed_in?(resource_name) token = signed_in_resource.create_token + signed_in_resource.save! redirect_headers = build_redirect_headers(token.token, token.client, diff --git a/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb b/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb index 37bea0921..85add605e 100644 --- a/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +++ b/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb @@ -112,7 +112,8 @@ def omniauth_params # break out provider attribute assignment for easy method extension def assign_provider_attrs(user, auth_hash) - attrs = auth_hash['info'].slice(*user.attribute_names) + attrs = auth_hash['info'].to_hash + attrs = attrs.slice(*user.attribute_names) user.assign_attributes(attrs) end diff --git a/app/controllers/devise_token_auth/sessions_controller.rb b/app/controllers/devise_token_auth/sessions_controller.rb index fadcb31db..5d34eaf69 100644 --- a/app/controllers/devise_token_auth/sessions_controller.rb +++ b/app/controllers/devise_token_auth/sessions_controller.rb @@ -48,7 +48,7 @@ def create def destroy # remove auth instance variables so that after_action does not run user = remove_instance_variable(:@resource) if @resource - client = @token.client if @token.client + client = @token.client @token.clear! if user && client && user.tokens[client] diff --git a/app/models/devise_token_auth/concerns/active_record_support.rb b/app/models/devise_token_auth/concerns/active_record_support.rb index d086b8bdc..e86d2c17f 100644 --- a/app/models/devise_token_auth/concerns/active_record_support.rb +++ b/app/models/devise_token_auth/concerns/active_record_support.rb @@ -1,5 +1,3 @@ -require_relative 'tokens_serialization' - module DeviseTokenAuth::Concerns::ActiveRecordSupport extend ActiveSupport::Concern diff --git a/app/models/devise_token_auth/concerns/confirmable_support.rb b/app/models/devise_token_auth/concerns/confirmable_support.rb index 11df762a5..86b07a59b 100644 --- a/app/models/devise_token_auth/concerns/confirmable_support.rb +++ b/app/models/devise_token_auth/concerns/confirmable_support.rb @@ -18,7 +18,8 @@ def postpone_email_change? protected def email_value_in_database - if Devise.rails51? && respond_to?(:email_in_database) + rails51 = Rails.gem_version >= Gem::Version.new("5.1.x") + if rails51 && respond_to?(:email_in_database) email_in_database else email_was diff --git a/app/models/devise_token_auth/concerns/tokens_serialization.rb b/app/models/devise_token_auth/concerns/tokens_serialization.rb index 5e6cc1c6d..d5e376c74 100644 --- a/app/models/devise_token_auth/concerns/tokens_serialization.rb +++ b/app/models/devise_token_auth/concerns/tokens_serialization.rb @@ -1,12 +1,14 @@ module DeviseTokenAuth::Concerns::TokensSerialization + extend self # Serialization hash to json - def self.dump(object) - object.each_value(&:compact!) unless object.nil? - JSON.generate(object) + def dump(object) + JSON.generate(object && object.transform_values do |token| + serialize_updated_at(token).compact + end.compact) end # Deserialization json to hash - def self.load(json) + def load(json) case json when String JSON.parse(json) @@ -16,4 +18,14 @@ def self.load(json) json end end + + private + + def serialize_updated_at(token) + updated_at_key = ['updated_at', :updated_at].find(&token.method(:[])) + + return token unless token[updated_at_key].respond_to?(:iso8601) + + token.merge updated_at_key => token[updated_at_key].iso8601 + end end diff --git a/app/models/devise_token_auth/concerns/user.rb b/app/models/devise_token_auth/concerns/user.rb index 7e0df07b5..1b0e0f7cc 100644 --- a/app/models/devise_token_auth/concerns/user.rb +++ b/app/models/devise_token_auth/concerns/user.rb @@ -163,17 +163,17 @@ def refresh_token_is_current?(refresh_token, client) def token_can_be_reused?(token, client) # ghetto HashWithIndifferentAccess updated_at = tokens[client]['updated_at'] || tokens[client][:updated_at] - last_token = tokens[client]['last_token'] || tokens[client][:last_token] + last_token_hash = tokens[client]['last_token'] || tokens[client][:last_token] return true if ( # ensure that the last token and its creation time exist - updated_at && last_token && + updated_at && last_token_hash && # ensure that previous token falls within the batch buffer throttle time of the last request updated_at.to_time > Time.zone.now - DeviseTokenAuth.batch_request_buffer_throttle && # ensure that the token is valid - DeviseTokenAuth::TokenFactory.valid_token_hash?(last_token) + DeviseTokenAuth::TokenFactory.token_hash_is_token?(last_token_hash, token) ) end diff --git a/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb b/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb index 04ede1d29..50f77c698 100644 --- a/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +++ b/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb @@ -9,7 +9,7 @@ module DeviseTokenAuth::Concerns::UserOmniauthCallbacks validates_presence_of :uid, unless: :email_provider? # only validate unique emails among email registration users - validates :email, uniqueness: { scope: :provider }, on: :create, if: :email_provider? + validates :email, uniqueness: { case_sensitive: false, scope: :provider }, on: :create, if: :email_provider? # keep uid in sync with email before_save :sync_uid @@ -23,6 +23,9 @@ def email_provider? end def sync_uid + if devise_modules.include?(:confirmable) && !@bypass_confirmation_postpone + return if postpone_email_change? + end self.uid = email if email_provider? end end diff --git a/app/validators/devise_token_auth_email_validator.rb b/app/validators/devise_token_auth_email_validator.rb index 3637cf688..c5e1db846 100644 --- a/app/validators/devise_token_auth_email_validator.rb +++ b/app/validators/devise_token_auth_email_validator.rb @@ -3,7 +3,7 @@ class DeviseTokenAuthEmailValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i - record.errors[attribute] << email_invalid_message + record.errors.add(attribute, email_invalid_message) end end diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 4bde7ed04..04447a156 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -29,7 +29,7 @@ ja: messages: validate_sign_up_params: "リクエストボディに適切なアカウント新規登録データを送信してください。" validate_account_update_params: "リクエストボディに適切なアカウント更新のデータを送信してください。" - not_email: "はメールアドレスではありません" + not_email: "は有効ではありません" devise: mailer: confirmation_instructions: diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 418fd7af1..dadae4e88 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -26,9 +26,10 @@ pl: missing_passwords: "Musisz wypełnić wszystkie pola z etykietą 'Hasło' oraz 'Potwierdzenie hasła'." successfully_updated: "Twoje hasło zostało zaktualizowane." errors: - validate_sign_up_params: "Proszę dostarczyć odpowiednie dane logowania w ciele zapytania." - validate_account_update_params: "Proszę dostarczyć odpowiednie dane aktualizacji konta w ciele zapytania." - not_email: "nie jest prawidłowym adresem e-mail" + messages: + validate_sign_up_params: "Proszę dostarczyć odpowiednie dane logowania w ciele zapytania." + validate_account_update_params: "Proszę dostarczyć odpowiednie dane aktualizacji konta w ciele zapytania." + not_email: "nie jest prawidłowym adresem e-mail" devise: mailer: confirmation_instructions: diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 9abf58afa..6232821ef 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -26,9 +26,10 @@ pt: missing_passwords: "Preencha a senha e a confirmação de senha." successfully_updated: "Senha atualizada com sucesso." errors: - validate_sign_up_params: "Os dados submetidos na requisição de registo são inválidos." - validate_account_update_params: "Os dados submetidos para atualização de conta são inválidos." - not_email: "não é um e-mail" + messages: + validate_sign_up_params: "Os dados submetidos na requisição de registo são inválidos." + validate_account_update_params: "Os dados submetidos para atualização de conta são inválidos." + not_email: "não é um e-mail" devise: mailer: confirmation_instructions: diff --git a/devise_token_auth.gemspec b/devise_token_auth.gemspec index 0f8c0818f..f61264f92 100644 --- a/devise_token_auth.gemspec +++ b/devise_token_auth.gemspec @@ -22,8 +22,7 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 2.2.0" - s.add_dependency 'rails', '>= 4.2.0', '< 6.1' - s.add_dependency 'sprockets', '3.7.2' # FIXME: breaking changes in 4.0.0 + s.add_dependency 'rails', '>= 4.2.0', '< 6.2' s.add_dependency 'devise', '> 3.5.2', '< 5' s.add_dependency 'bcrypt', '~> 3.0' diff --git a/docs/conceptual.md b/docs/conceptual.md index 9ebf5fbf5..50def4eed 100644 --- a/docs/conceptual.md +++ b/docs/conceptual.md @@ -39,7 +39,7 @@ In this case, it's impossible to update the `access-token` header for the second ![batch request overview](https://github.com/lynndylanhurley/ng-token-auth/raw/master/test/app/images/flow/batch-request-overview.jpg) -The "5 second" buffer in the diagram is the default used this gem. +The "5 second" buffer in the diagram is the default used by this gem. The following diagram details the relationship between the client, server, and access tokens used over time when dealing with batch requests: diff --git a/docs/config/initialization.md b/docs/config/initialization.md index 485aa4b83..aa6b35866 100644 --- a/docs/config/initialization.md +++ b/docs/config/initialization.md @@ -2,22 +2,22 @@ The following settings are available for configuration in `config/initializers/devise_token_auth.rb`: -| Name | Default | Description| +| Name (default) | Description| |---|---|---| -| **`change_headers_on_each_request`** | `true` | By default the access-token header will change after each request. The client is responsible for keeping track of the changing tokens. Both [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) and [jToker](https://github.com/lynndylanhurley/j-toker) do this out of the box. While this implementation is more secure, it can be difficult to manage. Set this to false to prevent the `access-token` header from changing after each request. [Read more](#about-token-management). | -| **`token_lifespan`** | `2.weeks` | Set the length of your tokens' lifespans. Users will need to re-authenticate after this duration of time has passed since their last login. | -| **`token_cost`** | `10` | Set the cost of your tokens' cost. The possible cost value is within range from 4 to 31. It is recommended to not use a value more than 10. For details see [BCrypt Cost Factors](https://github.com/codahale/bcrypt-ruby#cost-factors). | -| **`batch_request_buffer_throttle`** | `5.seconds` | Sometimes it's necessary to make several requests to the API at the same time. In this case, each request in the batch will need to share the same auth token. This setting determines how far apart the requests can be while still using the same auth token. [Read more](conceptual#about-batch-requests). | -| **`omniauth_prefix`** | `"/omniauth"` | This route will be the prefix for all oauth2 redirect callbacks. For example, using the default '/omniauth' setting, the github oauth2 provider will redirect successful authentications to '/omniauth/github/callback'. [Read more](#omniauth-provider-settings). | -| **`default_confirm_success_url`** | `nil` | By default this value is expected to be sent by the client so that the API knows where to redirect users after successful email confirmation. If this param is set, the API will redirect to this value when no value is provided by the client. | -| **`default_password_reset_url`** | `nil` | By default this value is expected to be sent by the client so that the API knows where to redirect users after successful password resets. If this param is set, the API will redirect to this value when no value is provided by the client. | -| **`redirect_whitelist`** | `nil` | As an added security measure, you can limit the URLs to which the API will redirect after email token validation (password reset, email confirmation, etc.). This value should be an array containing matches to the client URLs to be visited after validation. Wildcards are supported. | -| **`enable_standard_devise_support`** | `false` | By default, only Bearer Token authentication is implemented out of the box. If, however, you wish to integrate with legacy Devise authentication, you can do so by enabling this flag. NOTE: This feature is highly experimental! | -| **`remove_tokens_after_password_reset`** | `false` | By default, old tokens are not invalidated when password is changed. Enable this option if you want to make passwords updates to logout other devices. | -| **`default_callbacks`** | `true` | By default User model will include the `DeviseTokenAuth::Concerns::UserOmniauthCallbacks` concern, which has `email`, `uid` validations & `uid` synchronization callbacks. | -| **`bypass_sign_in`** | `true` | By default DeviseTokenAuth will not check user's `#active_for_authentication?` which includes confirmation check on each call (it will do it only on sign in). If you want it to be validated on each request (for example, to be able to deactivate logged in users on the fly), set it to false. | -| **`send_confirmation_email`** | `false` | By default DeviseTokenAuth will not send confirmation email, even when including devise confirmable module. If you want to use devise confirmable module and send email, set it to true. (This is a setting for compatibility) | -| **`require_client_password_reset_token`** | `false` | By default, the password-reset confirmation link redirects to the client with valid session credentials as querystring params. With this option enabled, the redirect will NOT include the valid session credentials. Instead the redirect will include a password_reset_token querystring param that can be used to reset the users password. Once the user has reset their password, the password-reset success response headers will contain valid session credentials. | +| **`change_headers_on_each_request`** (`true`) | By default the access-token header will change after each request. The client is responsible for keeping track of the changing tokens. Both [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) and [jToker](https://github.com/lynndylanhurley/j-toker) do this out of the box. While this implementation is more secure, it can be difficult to manage. Set this to false to prevent the `access-token` header from changing after each request. [Read more](/conceptual#about-token-management). | +| **`token_lifespan`** (`2.weeks`) | Set the length of your tokens' lifespans. Users will need to re-authenticate after this duration of time has passed since their last login. | +| **`token_cost`** (`10`) | Set the cost of your tokens' cost. The possible cost value is within range from 4 to 31. It is recommended to not use a value more than 10. For details see [BCrypt Cost Factors](https://github.com/codahale/bcrypt-ruby#cost-factors). | +| **`batch_request_buffer_throttle`** (`5.seconds`) | Sometimes it's necessary to make several requests to the API at the same time. In this case, each request in the batch will need to share the same auth token. This setting determines how far apart the requests can be while still using the same auth token. [Read more](conceptual#about-batch-requests). | +| **`omniauth_prefix`** (`"/omniauth"`) | This route will be the prefix for all oauth2 redirect callbacks. For example, using the default '/omniauth' setting, the github oauth2 provider will redirect successful authentications to '/omniauth/github/callback'. [Read more](#omniauth-provider-settings). | +| **`default_confirm_success_url`** (`nil`) | By default this value is expected to be sent by the client so that the API knows where to redirect users after successful email confirmation. If this param is set, the API will redirect to this value when no value is provided by the client. | +| **`default_password_reset_url`** (`nil`) | By default this value is expected to be sent by the client so that the API knows where to redirect users after successful password resets. If this param is set, the API will redirect to this value when no value is provided by the client. | +| **`redirect_whitelist`** (`nil`) | As an added security measure, you can limit the URLs to which the API will redirect after email token validation (password reset, email confirmation, etc.). This value should be an array containing matches to the client URLs to be visited after validation. Wildcards are supported. | +| **`enable_standard_devise_support`** (`false`) | By default, only Bearer Token authentication is implemented out of the box. If, however, you wish to integrate with legacy Devise authentication, you can do so by enabling this flag. NOTE: This feature is highly experimental! | +| **`remove_tokens_after_password_reset`** (`false`) | By default, old tokens are not invalidated when password is changed. Enable this option if you want to make passwords updates to logout other devices. | +| **`default_callbacks`** (`true`) | By default User model will include the `DeviseTokenAuth::Concerns::UserOmniauthCallbacks` concern, which has `email`, `uid` validations & `uid` synchronization callbacks. | +| **`bypass_sign_in`** (`true`) | By default DeviseTokenAuth will not check user's `#active_for_authentication?` which includes confirmation check on each call (it will do it only on sign in). If you want it to be validated on each request (for example, to be able to deactivate logged in users on the fly), set it to false. | +| **`send_confirmation_email`** (`false`) | By default DeviseTokenAuth will not send confirmation email, even when including devise confirmable module. If you want to use devise confirmable module and send email, set it to true. (This is a setting for compatibility) | +| **`require_client_password_reset_token`** (`false`) | By default, the password-reset confirmation link redirects to the client with valid session credentials as querystring params. With this option enabled, the redirect will NOT include the valid session credentials. Instead the redirect will include a password_reset_token querystring param that can be used to reset the users password. Once the user has reset their password, the password-reset success response headers will contain valid session credentials. | Additionally, you can configure other aspects of devise by manually creating the traditional devise.rb file at `config/initializers/devise.rb`. Here are some examples of what you can do in this file: diff --git a/docs/faq.md b/docs/faq.md index 633975223..a197ece31 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -124,7 +124,10 @@ You may be interested in [solidus_devise_token_auth](https://github.com/skycocke add_column :users, :tokens, :text # if your existing User model does not have an existing **encrypted_password** column uncomment below line. - # add_column :users, :encrypted_password, :null => false, :default => "" + # add_column :users, :encrypted_password, :string, null: false, default: '' + + # if your existing User model does not have an existing **allow_password_change** column uncomment below line. + # add_column :users, :allow_password_change, :boolean, default: false # the following will update your models so that when you run your migration @@ -145,6 +148,7 @@ You may be interested in [solidus_devise_token_auth](https://github.com/skycocke def down # if you added **encrypted_password** above, add here to successfully rollback + # if you added **allow_password_change** above, add here to successfully rollback remove_columns :users, :provider, :uid, :tokens end diff --git a/docs/usage/README.md b/docs/usage/README.md index 1363ca772..d309b3ef3 100644 --- a/docs/usage/README.md +++ b/docs/usage/README.md @@ -15,3 +15,4 @@ The following routes are available for use by your client. These routes live rel | /password | POST | Use this route to send a password reset confirmation email to users that registered by email. Accepts **`email`** and **`redirect_url`** as params. The user matching the `email` param will be sent instructions on how to reset their password. `redirect_url` is the url to which the user will be redirected after visiting the link contained in the email. | | /password | PUT | Use this route to change users' passwords. Requires **`password`** and **`password_confirmation`** as params. This route is only valid for users that registered by email (OAuth2 users will receive an error). It also checks **`current_password`** if **`config.check_current_password_before_update`** is not set `false` (disabled by default). | | /password/edit | GET | Verify user by password reset token. This route is the destination URL for password reset confirmation. This route must contain **`reset_password_token`** and **`redirect_url`** params. These values will be set automatically by the confirmation email that is generated by the password reset request. | +| /confirmation | POST | Re-sends confirmation email. Requires **`email`** and accepts **`redirect_url`** params (this last one can be omitted if you have set `config.default_confirm_success_url` in `config/initializers/devise_token_auth.rb`). | \ No newline at end of file diff --git a/docs/usage/overrides.md b/docs/usage/overrides.md index bf8d134d6..26f43a1d4 100644 --- a/docs/usage/overrides.md +++ b/docs/usage/overrides.md @@ -47,6 +47,8 @@ To customize json rendering, implement the following protected controller method * render_update_success * render_update_error * render_update_error_user_not_found +* render_destroy_success +* render_destroy_error ### Sessions Controller diff --git a/docs/usage/reset_password.md b/docs/usage/reset_password.md index f296b0850..7b8bcc6fa 100644 --- a/docs/usage/reset_password.md +++ b/docs/usage/reset_password.md @@ -11,6 +11,7 @@ This is the overall workflow for a User to reset their password: - that form submission sends a request to the API: `POST /auth/password` with some parameters: `email` (the email supplied in the field) & `redirect_url` (a page in the front end site that will contain a form with `password` and `password_confirmation` fields) - the API responds to this request by generating a `reset_password_token` and sending an email (the `reset_password_instructions.html.erb` file from devise) to the email address provided within the `email` parameter + - we need to modify the `reset_password_instructions.html.erb` file to point to the API: `GET /auth/password/edit` - for example, if you have your API under the `api/v1` namespaces: `<%= link_to 'Change my password', edit_api_v1_user_password_url(reset_password_token: @token, config: message['client-config'].to_s, redirect_url: message['redirect-url'].to_s) %>` (I came up with this `link_to` by referring to [this line](https://github.com/lynndylanhurley/devise_token_auth/blob/15bf7857eca2d33602c7a9cb9d08db8a160f8ab8/app/views/devise/mailer/reset_password_instructions.html.erb#L5)) @@ -21,6 +22,7 @@ This is the overall workflow for a User to reset their password: - this `redirect_url` is a page on the frontend which contains a `password` and `password_confirmation` field - the user submits the form on this frontend page, which sends a request to API: `PUT /auth/password` with the `password` and `password_confirmation` parameters. In addition headers need to be included from the url params (you get these from the url as query params). A side note, ensure that the header names follow the convention outlined in `config/initializers/devise_token_auth.rb`; at this time of writing it is: `uid`, `client` and `access-token`. + - _Ensure that the `uid` sent in the headers is not URL-escaped. e.g. it should be bob@example.com, not bob%40example.com_ - the API changes the user's password and responds back with a success message @@ -31,7 +33,7 @@ This is the overall workflow for a User to reset their password: The next diagram shows how it works: -![password reset flow](password_diagram_reset.jpg) +![password reset flow](../password_diagram_reset.jpg) If you get in any trouble configuring or overriding the behavior, you can check the [issue #604](https://github.com/lynndylanhurley/devise_token_auth/issues/604). diff --git a/docs/usage/testing.md b/docs/usage/testing.md index a6f45dca0..78bbfd85a 100644 --- a/docs/usage/testing.md +++ b/docs/usage/testing.md @@ -17,7 +17,8 @@ Check #75 if you have any problem or doubt. Below are some generic examples which may assist in helping you devise (pun intended) your own tests: ```ruby -# I've called it authentication_test_spec.rb and placed it in the spec/requests folder +# spec/requests/authentication_test_spec.rb + require 'rails_helper' include ActionController::RespondWith @@ -112,7 +113,7 @@ describe 'Whether access is ocurring properly', type: :request do 'client' => client, 'uid' => uid, 'expiry' => expiry, - 'token_type' => token_type + 'token-type' => token_type } auth_params end diff --git a/gemfiles/rails_4_2.gemfile b/gemfiles/rails_4_2.gemfile index 192ba55d0..df4846b8c 100644 --- a/gemfiles/rails_4_2.gemfile +++ b/gemfiles/rails_4_2.gemfile @@ -27,7 +27,7 @@ group :development, :test do gem "minitest-rails" gem "minitest-reporters" gem "mocha", ">= 1.5" - gem "pry" + gem "pry", "< 0.13" gem "pry-byebug" gem "pry-remote" gem "rubocop", require: false @@ -35,7 +35,7 @@ end group :test do gem "rails-controller-testing" - gem "simplecov", require: false + gem "simplecov", "< 0.18", require: false end group :development do diff --git a/gemfiles/rails_4_2_mongoid_5.gemfile b/gemfiles/rails_4_2_mongoid_5.gemfile index 80a6d10a9..083bba80b 100644 --- a/gemfiles/rails_4_2_mongoid_5.gemfile +++ b/gemfiles/rails_4_2_mongoid_5.gemfile @@ -8,6 +8,7 @@ gem "mongoid-locker", "~> 1.0" group :development, :test do gem "attr_encrypted" + gem "byebug", "< 11.1" gem "figaro", git: "https://github.com/laserlemon/figaro" gem "omniauth-facebook", git: "https://github.com/mkdynamic/omniauth-facebook" gem "omniauth-github", git: "https://github.com/intridea/omniauth-github" @@ -26,7 +27,7 @@ group :development, :test do gem "minitest-rails" gem "minitest-reporters" gem "mocha", ">= 1.5" - gem "pry" + gem "pry", "< 0.13" gem "pry-byebug" gem "pry-remote" gem "rubocop", require: false @@ -34,7 +35,7 @@ end group :test do gem "rails-controller-testing" - gem "simplecov", require: false + gem "simplecov", "< 0.18", require: false end group :development do diff --git a/gemfiles/rails_5_0.gemfile b/gemfiles/rails_5_0.gemfile index e19e94884..4f009a808 100644 --- a/gemfiles/rails_5_0.gemfile +++ b/gemfiles/rails_5_0.gemfile @@ -27,7 +27,7 @@ group :development, :test do gem "minitest-rails" gem "minitest-reporters" gem "mocha", ">= 1.5" - gem "pry" + gem "pry", "< 0.13" gem "pry-byebug" gem "pry-remote" gem "rubocop", require: false @@ -35,7 +35,7 @@ end group :test do gem "rails-controller-testing" - gem "simplecov", require: false + gem "simplecov", "< 0.18", require: false end group :development do diff --git a/gemfiles/rails_5_1.gemfile b/gemfiles/rails_5_1.gemfile index 2606dcd56..c8fb85550 100644 --- a/gemfiles/rails_5_1.gemfile +++ b/gemfiles/rails_5_1.gemfile @@ -27,7 +27,7 @@ group :development, :test do gem "minitest-rails" gem "minitest-reporters" gem "mocha", ">= 1.5" - gem "pry" + gem "pry", "< 0.13" gem "pry-byebug" gem "pry-remote" gem "rubocop", require: false @@ -35,7 +35,11 @@ end group :test do gem "rails-controller-testing" - gem "simplecov", require: false + + # Workaround for cc-test-reporter with SimpleCov 0.18. + # Stop upgrading SimpleCov until the following issue will be resolved. + # https://github.com/codeclimate/test-reporter/issues/418 + gem 'simplecov', '~> 0.10', '< 0.18', require: false end group :development do diff --git a/gemfiles/rails_5_1_mongoid_6.gemfile b/gemfiles/rails_5_1_mongoid_6.gemfile index 5367006df..b875adf55 100644 --- a/gemfiles/rails_5_1_mongoid_6.gemfile +++ b/gemfiles/rails_5_1_mongoid_6.gemfile @@ -8,6 +8,7 @@ gem "mongoid-locker", "~> 1.0" group :development, :test do gem "attr_encrypted" + gem "byebug", "< 11.1" gem "figaro", git: "https://github.com/laserlemon/figaro" gem "omniauth-facebook", git: "https://github.com/mkdynamic/omniauth-facebook" gem "omniauth-github", git: "https://github.com/intridea/omniauth-github" @@ -26,7 +27,7 @@ group :development, :test do gem "minitest-rails" gem "minitest-reporters" gem "mocha", ">= 1.5" - gem "pry" + gem "pry", "< 0.13" gem "pry-byebug" gem "pry-remote" gem "rubocop", require: false @@ -34,7 +35,7 @@ end group :test do gem "rails-controller-testing" - gem "simplecov", require: false + gem "simplecov", "< 0.18", require: false end group :development do diff --git a/gemfiles/rails_5_1_mongoid_7.gemfile b/gemfiles/rails_5_1_mongoid_7.gemfile index d3e0d6aef..193f9649a 100644 --- a/gemfiles/rails_5_1_mongoid_7.gemfile +++ b/gemfiles/rails_5_1_mongoid_7.gemfile @@ -34,7 +34,11 @@ end group :test do gem "rails-controller-testing" - gem "simplecov", require: false + + # Workaround for cc-test-reporter with SimpleCov 0.18. + # Stop upgrading SimpleCov until the following issue will be resolved. + # https://github.com/codeclimate/test-reporter/issues/418 + gem 'simplecov', '~> 0.10', '< 0.18', require: false end group :development do diff --git a/gemfiles/rails_5_2.gemfile b/gemfiles/rails_5_2.gemfile index c40d78a36..791f8825b 100644 --- a/gemfiles/rails_5_2.gemfile +++ b/gemfiles/rails_5_2.gemfile @@ -27,7 +27,7 @@ group :development, :test do gem "minitest-rails" gem "minitest-reporters" gem "mocha", ">= 1.5" - gem "pry" + gem "pry", "< 0.13" gem "pry-byebug" gem "pry-remote" gem "rubocop", require: false @@ -35,7 +35,7 @@ end group :test do gem "rails-controller-testing" - gem "simplecov", require: false + gem "simplecov", "< 0.18", require: false end group :development do diff --git a/gemfiles/rails_5_2_mongoid_6.gemfile b/gemfiles/rails_5_2_mongoid_6.gemfile index 14bad1c02..13cc0599c 100644 --- a/gemfiles/rails_5_2_mongoid_6.gemfile +++ b/gemfiles/rails_5_2_mongoid_6.gemfile @@ -34,7 +34,7 @@ end group :test do gem "rails-controller-testing" - gem "simplecov", require: false + gem "simplecov", "< 0.18", require: false end group :development do diff --git a/gemfiles/rails_5_2_mongoid_7.gemfile b/gemfiles/rails_5_2_mongoid_7.gemfile index 4bf9cb494..261ace014 100644 --- a/gemfiles/rails_5_2_mongoid_7.gemfile +++ b/gemfiles/rails_5_2_mongoid_7.gemfile @@ -34,7 +34,7 @@ end group :test do gem "rails-controller-testing" - gem "simplecov", require: false + gem "simplecov", "< 0.18", require: false end group :development do diff --git a/gemfiles/rails_6_0.gemfile b/gemfiles/rails_6_0.gemfile new file mode 100644 index 000000000..2a3ec791c --- /dev/null +++ b/gemfiles/rails_6_0.gemfile @@ -0,0 +1,45 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "rails", "~> 6.0" +gem "sqlite3", "~> 1.4.1" +gem "mysql2" +gem "pg" + +group :development, :test do + gem "attr_encrypted" + gem "figaro", git: "https://github.com/laserlemon/figaro" + gem "omniauth-facebook", git: "https://github.com/mkdynamic/omniauth-facebook" + gem "omniauth-github", git: "https://github.com/intridea/omniauth-github" + gem "omniauth-google-oauth2", git: "https://github.com/zquestz/omniauth-google-oauth2" + gem 'omniauth-apple' + gem "rack-cors", require: "rack/cors" + gem "thor" + gem "database_cleaner" + gem "factory_bot_rails" + gem "faker" + gem "fuzz_ball" + gem "guard" + gem "guard-minitest" + gem "minitest" + gem "minitest-focus" + gem "minitest-rails" + gem "minitest-reporters" + gem "mocha", ">= 1.5" + gem "pry", "< 0.13" + gem "pry-byebug" + gem "pry-remote" + gem "rubocop", require: false +end + +group :test do + gem "rails-controller-testing" + gem "simplecov", "< 0.18", require: false +end + +group :development do + gem "github_changelog_generator" +end + +gemspec path: "../" diff --git a/gemfiles/rails_6_0_mongoid_7.gemfile b/gemfiles/rails_6_0_mongoid_7.gemfile new file mode 100644 index 000000000..8b6bbca87 --- /dev/null +++ b/gemfiles/rails_6_0_mongoid_7.gemfile @@ -0,0 +1,44 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "rails", "~> 6.0" +gem "mongoid", "~> 7.0" +gem "mongoid-locker", "~> 1.0" + +group :development, :test do + gem "attr_encrypted" + gem "figaro", git: "https://github.com/laserlemon/figaro" + gem "omniauth-facebook", git: "https://github.com/mkdynamic/omniauth-facebook" + gem "omniauth-github", git: "https://github.com/intridea/omniauth-github" + gem "omniauth-google-oauth2", git: "https://github.com/zquestz/omniauth-google-oauth2" + gem "omniauth-apple" + gem "rack-cors", require: "rack/cors" + gem "thor" + gem "database_cleaner" + gem "factory_bot_rails" + gem "faker" + gem "fuzz_ball" + gem "guard" + gem "guard-minitest" + gem "minitest" + gem "minitest-focus" + gem "minitest-rails" + gem "minitest-reporters" + gem "mocha", ">= 1.5" + gem "pry" + gem "pry-byebug" + gem "pry-remote" + gem "rubocop", require: false +end + +group :test do + gem "rails-controller-testing" + gem "simplecov", "< 0.18", require: false +end + +group :development do + gem "github_changelog_generator" +end + +gemspec path: "../" diff --git a/lib/devise_token_auth/controllers/helpers.rb b/lib/devise_token_auth/controllers/helpers.rb index 2f2352a92..4239495d7 100644 --- a/lib/devise_token_auth/controllers/helpers.rb +++ b/lib/devise_token_auth/controllers/helpers.rb @@ -34,12 +34,6 @@ def devise_token_auth_group(group_name, opts = {}) class_eval <<-METHODS, __FILE__, __LINE__ + 1 def authenticate_#{group_name}!(favourite=nil, opts={}) unless #{group_name}_signed_in? - mappings = #{mappings} - mappings.unshift mappings.delete(favourite.to_sym) if favourite - mappings.each do |mapping| - set_user_by_token(mapping) - end - unless current_#{group_name} render_authenticate_error end @@ -47,12 +41,14 @@ def authenticate_#{group_name}!(favourite=nil, opts={}) end def #{group_name}_signed_in? - #{mappings}.any? do |mapping| - set_user_by_token(mapping) - end + !!current_#{group_name} end def current_#{group_name}(favourite=nil) + @current_#{group_name} ||= set_group_user_by_token(favourite) + end + + def set_group_user_by_token(favourite) mappings = #{mappings} mappings.unshift mappings.delete(favourite.to_sym) if favourite mappings.each do |mapping| diff --git a/lib/devise_token_auth/rails/routes.rb b/lib/devise_token_auth/rails/routes.rb index 3112df576..585835fe9 100644 --- a/lib/devise_token_auth/rails/routes.rb +++ b/lib/devise_token_auth/rails/routes.rb @@ -8,26 +8,31 @@ def mount_devise_token_auth_for(resource, opts) opts[:skip] ||= [] # check for ctrl overrides, fall back to defaults - sessions_ctrl = opts[:controllers][:sessions] || 'devise_token_auth/sessions' - registrations_ctrl = opts[:controllers][:registrations] || 'devise_token_auth/registrations' - passwords_ctrl = opts[:controllers][:passwords] || 'devise_token_auth/passwords' - confirmations_ctrl = opts[:controllers][:confirmations] || 'devise_token_auth/confirmations' - token_validations_ctrl = opts[:controllers][:token_validations] || 'devise_token_auth/token_validations' - omniauth_ctrl = opts[:controllers][:omniauth_callbacks] || 'devise_token_auth/omniauth_callbacks' - unlocks_ctrl = opts[:controllers][:unlocks] || 'devise_token_auth/unlocks' + sessions_ctrl = opts[:controllers].delete(:sessions) || 'devise_token_auth/sessions' + registrations_ctrl = opts[:controllers].delete(:registrations) || 'devise_token_auth/registrations' + passwords_ctrl = opts[:controllers].delete(:passwords) || 'devise_token_auth/passwords' + confirmations_ctrl = opts[:controllers].delete(:confirmations) || 'devise_token_auth/confirmations' + token_validations_ctrl = opts[:controllers].delete(:token_validations) || 'devise_token_auth/token_validations' + omniauth_ctrl = opts[:controllers].delete(:omniauth_callbacks) || 'devise_token_auth/omniauth_callbacks' + unlocks_ctrl = opts[:controllers].delete(:unlocks) || 'devise_token_auth/unlocks' + + # check for resource override + route = opts[:as] || resource.pluralize.underscore.gsub('/', '_') # define devise controller mappings - controllers = { sessions: sessions_ctrl, + controllers = opts[:controllers].merge( + sessions: sessions_ctrl, registrations: registrations_ctrl, passwords: passwords_ctrl, - confirmations: confirmations_ctrl } + confirmations: confirmations_ctrl + ) controllers[:unlocks] = unlocks_ctrl if unlocks_ctrl # remove any unwanted devise modules opts[:skip].each{ |item| controllers.delete(item) } - devise_for resource.pluralize.underscore.gsub('/', '_').to_sym, + devise_for route.to_sym, class_name: resource, module: :devise, path: opts[:at].to_s, diff --git a/lib/devise_token_auth/version.rb b/lib/devise_token_auth/version.rb index a423e8258..cfe7158d8 100644 --- a/lib/devise_token_auth/version.rb +++ b/lib/devise_token_auth/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module DeviseTokenAuth - VERSION = '1.1.3'.freeze + VERSION = '1.1.4'.freeze end diff --git a/lib/generators/devise_token_auth/install_generator.rb b/lib/generators/devise_token_auth/install_generator.rb index 14e7d0ba9..fb39afdc3 100644 --- a/lib/generators/devise_token_auth/install_generator.rb +++ b/lib/generators/devise_token_auth/install_generator.rb @@ -26,7 +26,7 @@ def create_user_model inclusion = 'include DeviseTokenAuth::Concerns::User' unless parse_file_for_line(fname, inclusion) - active_record_needle = (Rails::VERSION::MAJOR == 5) ? 'ApplicationRecord' : 'ActiveRecord::Base' + active_record_needle = (Rails::VERSION::MAJOR >= 5) ? 'ApplicationRecord' : 'ActiveRecord::Base' inject_into_file fname, after: "class #{user_class} < #{active_record_needle}\n" do <<-'RUBY' # Include default devise modules. devise :database_authenticatable, :registerable, @@ -75,12 +75,12 @@ def database_version ActiveRecord::Base.connection.select_value('SELECT VERSION()') end - def rails5? - Rails.version.start_with? '5' + def rails_5_or_newer? + Rails::VERSION::MAJOR >= 5 end def primary_key_type - primary_key_string if rails5? + primary_key_string if rails_5_or_newer? end def primary_key_string diff --git a/lib/generators/devise_token_auth/install_mongoid_generator.rb b/lib/generators/devise_token_auth/install_mongoid_generator.rb index 9f45db3e5..dba05e900 100644 --- a/lib/generators/devise_token_auth/install_mongoid_generator.rb +++ b/lib/generators/devise_token_auth/install_mongoid_generator.rb @@ -29,9 +29,9 @@ def create_user_model field :tokens, type: Hash, default: {} # Include default devise modules. Others available are: - # :confirmable, :lockable, :timeoutable and :omniauthable + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, - :recoverable, :rememberable, :trackable, :validatable + :recoverable, :rememberable, :validatable include DeviseTokenAuth::Concerns::User index({ uid: 1, provider: 1}, { name: 'uid_provider_index', unique: true, background: true }) diff --git a/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb b/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb index 0c63f681c..d56a6d0d0 100644 --- a/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +++ b/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb @@ -44,6 +44,6 @@ class DeviseTokenAuthCreate<%= user_class.pluralize.gsub("::","") %> < ActiveRec add_index :<%= table_name %>, [:uid, :provider], unique: true add_index :<%= table_name %>, :reset_password_token, unique: true add_index :<%= table_name %>, :confirmation_token, unique: true - # add_index :<%= table_name %>, :unlock_token, unique: true + # add_index :<%= table_name %>, :unlock_token, unique: true end end diff --git a/lib/generators/devise_token_auth/templates/user.rb.erb b/lib/generators/devise_token_auth/templates/user.rb.erb index a6cb47a23..f5ba25e34 100644 --- a/lib/generators/devise_token_auth/templates/user.rb.erb +++ b/lib/generators/devise_token_auth/templates/user.rb.erb @@ -2,8 +2,8 @@ class <%= user_class %> < ActiveRecord::Base # Include default devise modules. Others available are: - # :confirmable, :lockable, :timeoutable and :omniauthable + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, - :recoverable, :rememberable, :trackable, :validatable + :recoverable, :rememberable, :validatable include DeviseTokenAuth::Concerns::User end diff --git a/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb b/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb index 761ca527f..08c463762 100644 --- a/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +++ b/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb @@ -43,9 +43,9 @@ class <%= user_class %> field :tokens, type: Hash, default: {} # Include default devise modules. Others available are: - # :confirmable, :lockable, :timeoutable and :omniauthable + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, - :recoverable, :rememberable, :trackable, :validatable + :recoverable, :rememberable, :validatable include DeviseTokenAuth::Concerns::User index({ email: 1 }, { name: 'email_index', unique: true, background: true }) diff --git a/test/controllers/devise_token_auth/confirmations_controller_test.rb b/test/controllers/devise_token_auth/confirmations_controller_test.rb index 29ef2b8aa..7da4341e5 100644 --- a/test/controllers/devise_token_auth/confirmations_controller_test.rb +++ b/test/controllers/devise_token_auth/confirmations_controller_test.rb @@ -53,6 +53,10 @@ def token_and_client_config_from(body) assert @resource.confirmed? end + test 'should save the authentication token' do + assert @resource.reload.tokens.present? + end + test 'should redirect to success url' do assert_redirected_to(/^#{@redirect_url}/) end diff --git a/test/dummy/app/assets/javascripts/application.js b/test/dummy/app/assets/javascripts/application.js deleted file mode 100644 index 5bc2e1c8b..000000000 --- a/test/dummy/app/assets/javascripts/application.js +++ /dev/null @@ -1,13 +0,0 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, -// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. -// -// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details -// about supported directives. -// -//= require_tree . diff --git a/test/dummy/app/assets/stylesheets/application.css b/test/dummy/app/assets/stylesheets/application.css deleted file mode 100644 index a443db340..000000000 --- a/test/dummy/app/assets/stylesheets/application.css +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, - * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any styles - * defined in the other CSS/SCSS files in this directory. It is generally better to create a new - * file per style scope. - * - *= require_tree . - *= require_self - */ diff --git a/test/dummy/app/views/layouts/application.html.erb b/test/dummy/app/views/layouts/application.html.erb index 593a778ba..bdb7dd946 100644 --- a/test/dummy/app/views/layouts/application.html.erb +++ b/test/dummy/app/views/layouts/application.html.erb @@ -2,8 +2,6 @@ Dummy - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> - <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb index 76d5ede8e..3f8ab788e 100644 --- a/test/dummy/config/application.rb +++ b/test/dummy/config/application.rb @@ -4,7 +4,6 @@ require 'action_controller/railtie' require 'action_mailer/railtie' -require 'sprockets/railtie' require 'rails/generators' require 'rack/cors' diff --git a/test/dummy/config/environments/development.rb b/test/dummy/config/environments/development.rb index 04184e7fb..0e0af3d7d 100644 --- a/test/dummy/config/environments/development.rb +++ b/test/dummy/config/environments/development.rb @@ -29,16 +29,6 @@ # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load - # Debug mode disables concatenation and preprocessing of assets. - # This option may cause significant delays in view rendering with a large - # number of complex assets. - config.assets.debug = true - - # Adds additional error checking when serving assets at runtime. - # Checks for improperly declared sprockets dependencies. - # Raises helpful error messages. - config.assets.raise_runtime_errors = true - # Raises error for missing translations # config.action_view.raise_on_missing_translations = true diff --git a/test/dummy/config/environments/production.rb b/test/dummy/config/environments/production.rb index fe23e903f..962135566 100644 --- a/test/dummy/config/environments/production.rb +++ b/test/dummy/config/environments/production.rb @@ -24,18 +24,6 @@ # Disable Rails's static asset server (Apache or nginx will already do this). config.serve_static_files = false - # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier - # config.assets.css_compressor = :sass - - # Do not fallback to assets pipeline if a precompiled asset is missed. - config.assets.compile = false - - # Generate digests for assets URLs. - config.assets.digest = true - - # `config.assets.precompile` has moved to config/initializers/assets.rb - # Specifies the header that your server uses for sending files. # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx @@ -58,10 +46,6 @@ # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.action_controller.asset_host = "http://assets.example.com" - # Precompile additional assets. - # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. - # config.assets.precompile += %w( search.js ) - # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false diff --git a/test/dummy/config/initializers/assets.rb b/test/dummy/config/initializers/assets.rb deleted file mode 100644 index 761905a73..000000000 --- a/test/dummy/config/initializers/assets.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. - -# Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -# Rails.application.config.assets.precompile += %w( search.js ) diff --git a/test/lib/devise_token_auth/rails/custom_routes_test.rb b/test/lib/devise_token_auth/rails/custom_routes_test.rb new file mode 100644 index 000000000..57ef71685 --- /dev/null +++ b/test/lib/devise_token_auth/rails/custom_routes_test.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'test_helper' + +class DeviseTokenAuth::CustomRoutesTest < ActiveSupport::TestCase + after do + Rails.application.reload_routes! + end + test 'custom controllers' do + class ActionDispatch::Routing::Mapper + include Mocha::ParameterMatchers + end + Rails.application.routes.draw do + self.expects(:devise_for).with( + :users, + has_entries( + controllers: has_entries( + invitations: "custom/invitations", foo: "custom/foo" + ) + ) + ) + + mount_devise_token_auth_for 'User', at: 'my_custom_users', controllers: { + invitations: 'custom/invitations', + foo: 'custom/foo' + } + end + end +end diff --git a/test/lib/devise_token_auth/rails/routes_test.rb b/test/lib/devise_token_auth/rails/routes_test.rb new file mode 100644 index 000000000..c01f8b132 --- /dev/null +++ b/test/lib/devise_token_auth/rails/routes_test.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +require 'test_helper' + +# Needed for MiniTest to start a controller test so we can use assert_recognizes +class DeviseTokenAuth::RoutesTestController < DeviseTokenAuth::ApplicationController +end + +class DeviseTokenAuth::RoutesTest < ActionController::TestCase + self.controller_class = DeviseTokenAuth::RoutesTestController + before do + Rails.application.routes.draw do + mount_devise_token_auth_for 'User', at: 'my_custom_users', controllers: { + invitations: 'custom/invitations', + foo: 'custom/foo' + } + end + end + + after do + Rails.application.reload_routes! + end + + test 'map new user session' do + assert_recognizes({controller: 'devise_token_auth/sessions', action: 'new'}, {path: 'my_custom_users/sign_in', method: :get}) + end + + test 'map create user session' do + assert_recognizes({controller: 'devise_token_auth/sessions', action: 'create'}, {path: 'my_custom_users/sign_in', method: :post}) + end + + test 'map destroy user session' do + assert_recognizes({controller: 'devise_token_auth/sessions', action: 'destroy'}, {path: 'my_custom_users/sign_out', method: :delete}) + end + + test 'map new user confirmation' do + assert_recognizes({controller: 'devise_token_auth/confirmations', action: 'new'}, 'my_custom_users/confirmation/new') + end + + test 'map create user confirmation' do + assert_recognizes({controller: 'devise_token_auth/confirmations', action: 'create'}, {path: 'my_custom_users/confirmation', method: :post}) + end + + test 'map show user confirmation' do + assert_recognizes({controller: 'devise_token_auth/confirmations', action: 'show'}, {path: 'my_custom_users/confirmation', method: :get}) + end + + test 'map new user password' do + assert_recognizes({controller: 'devise_token_auth/passwords', action: 'new'}, 'my_custom_users/password/new') + end + + test 'map create user password' do + assert_recognizes({controller: 'devise_token_auth/passwords', action: 'create'}, {path: 'my_custom_users/password', method: :post}) + end + + test 'map edit user password' do + assert_recognizes({controller: 'devise_token_auth/passwords', action: 'edit'}, 'my_custom_users/password/edit') + end + + test 'map update user password' do + assert_recognizes({controller: 'devise_token_auth/passwords', action: 'update'}, {path: 'my_custom_users/password', method: :put}) + end + + test 'map new user registration' do + assert_recognizes({controller: 'devise_token_auth/registrations', action: 'new'}, 'my_custom_users/sign_up') + end + + test 'map create user registration' do + assert_recognizes({controller: 'devise_token_auth/registrations', action: 'create'}, {path: 'my_custom_users', method: :post}) + end + + test 'map edit user registration' do + assert_recognizes({controller: 'devise_token_auth/registrations', action: 'edit'}, {path: 'my_custom_users/edit', method: :get}) + end + + test 'map update user registration' do + assert_recognizes({controller: 'devise_token_auth/registrations', action: 'update'}, {path: 'my_custom_users', method: :put}) + end + + test 'map destroy user registration' do + assert_recognizes({controller: 'devise_token_auth/registrations', action: 'destroy'}, {path: 'my_custom_users', method: :delete}) + end + + test 'map cancel user registration' do + assert_recognizes({controller: 'devise_token_auth/registrations', action: 'cancel'}, {path: 'my_custom_users/cancel', method: :get}) + end +end \ No newline at end of file diff --git a/test/lib/generators/devise_token_auth/install_generator_test.rb b/test/lib/generators/devise_token_auth/install_generator_test.rb index c58c92faf..99fb60196 100644 --- a/test/lib/generators/devise_token_auth/install_generator_test.rb +++ b/test/lib/generators/devise_token_auth/install_generator_test.rb @@ -70,7 +70,7 @@ class InstallGeneratorTest < Rails::Generators::TestCase case DEVISE_TOKEN_AUTH_ORM when :active_record # account for rails version 5 - active_record_needle = (Rails::VERSION::MAJOR == 5) ? 'ApplicationRecord' : 'ActiveRecord::Base' + active_record_needle = (Rails::VERSION::MAJOR >= 5) ? 'ApplicationRecord' : 'ActiveRecord::Base' @f = File.open(@fname, 'w') do |f| f.write <<-RUBY diff --git a/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb b/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb index f407fb052..6cfd443fd 100644 --- a/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +++ b/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb @@ -75,7 +75,7 @@ class InstallGeneratorTest < Rails::Generators::TestCase case DEVISE_TOKEN_AUTH_ORM when :active_record # account for rails version 5 - active_record_needle = (Rails::VERSION::MAJOR == 5) ? 'ApplicationRecord' : 'ActiveRecord::Base' + active_record_needle = (Rails::VERSION::MAJOR >= 5) ? 'ApplicationRecord' : 'ActiveRecord::Base' @f = File.open(@fname, 'w') do |f| f.write <<-RUBY diff --git a/test/models/concerns/tokens_serialization_test.rb b/test/models/concerns/tokens_serialization_test.rb index 388ec4c86..901e056c3 100644 --- a/test/models/concerns/tokens_serialization_test.rb +++ b/test/models/concerns/tokens_serialization_test.rb @@ -13,7 +13,6 @@ user.tokens end - let(:json) { JSON.generate(tokens) } it 'is defined' do assert_equal(ts.present?, true) @@ -21,6 +20,9 @@ end describe '.load(json)' do + + let(:json) { JSON.generate(tokens) } + let(:default) { {} } it 'is defined' do @@ -55,16 +57,48 @@ assert_equal(ts.dump({}), '{}') end - it 'deserialize tokens' do - assert_equal(ts.dump(tokens), json) - end - it 'removes nil values' do new_tokens = tokens.dup new_tokens[new_tokens.first[0]][:kos] = nil assert_equal(ts.dump(tokens), ts.dump(new_tokens)) end + + describe 'updated_at' do + before do + @default_format = ::Time::DATE_FORMATS[:default] + ::Time::DATE_FORMATS[:default] = 'imprecise format' + end + + after do + ::Time::DATE_FORMATS[:default] = @default_format + end + + def updated_ats(tokens) + tokens. + values. + flat_map do |token| + [:updated_at, 'updated_at'].map do |key| + token[key] + end + end. + compact + end + + it 'is defined' do + refute_empty updated_ats(tokens) + end + + it 'uses iso8601' do + updated_ats(JSON.parse(ts.dump(tokens))).each do |updated_at| + Time.strptime(updated_at, '%Y-%m-%dT%H:%M:%SZ') + end + end + + it 'does not rely on Time#to_s' do + refute_includes(updated_ats(tokens), 'imprecise format') + end + end end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index d7f43477b..a5bd24834 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -46,7 +46,7 @@ class ActiveSupport::TestCase def age_token(user, client_id) if user.tokens[client_id] - user.tokens[client_id]['updated_at'] = Time.zone.now - (DeviseTokenAuth.batch_request_buffer_throttle + 10.seconds) + user.tokens[client_id]['updated_at'] = (Time.zone.now - (DeviseTokenAuth.batch_request_buffer_throttle + 10.seconds)) user.save! end end