Skip to content

Commit

Permalink
Extract callbacks. Add setting for exctracted callbacks. Load it by d…
Browse files Browse the repository at this point in the history
…efault. Fix generator template. Add line to readme.
  • Loading branch information
merqlove committed Feb 5, 2016
1 parent 4ba29bd commit 9760a8b
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 22 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ test/dummy/.sass-cache
test/dummy/config/application.yml
coverage
.idea
.irb_history
.ruby-version
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ The following settings are available for configuration in `config/initializers/d
| **`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 exact matches to the client URLs to be visited after validation. |
| **`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. |


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:
Expand Down Expand Up @@ -356,7 +357,7 @@ The authentication routes must be mounted to your project. This gem includes a r
mount_devise_token_auth_for 'User', at: 'auth'
~~~

Any model class can be used, but the class will need to include [`DeviseTokenAuth::Concerns::User`](#model-concerns) for authentication to work properly.
Any model class can be used, but the class will need to include [`DeviseTokenAuth::Concerns::User`](#model-concerns) for authentication to work properly and [`DeviseTokenAuth::Concerns::UserOmniauthCallbacks`](#model-concerns) to use default omniauth callbacks & validations.

You can mount this engine to any route that you like. `/auth` is used by default to conform with the defaults of the [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) module and the [jToker](https://github.com/lynndylanhurley/j-toker) plugin.

Expand Down
23 changes: 3 additions & 20 deletions app/models/devise_token_auth/concerns/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,14 @@ def self.tokens_match?(token_hash, token)
serialize :tokens, JSON
end

validates :email, presence: true, email: true, if: Proc.new { |u| u.provider == 'email' }
validates_presence_of :uid, if: Proc.new { |u| u.provider != 'email' }

# only validate unique emails among email registration users
validate :unique_email_user, on: :create
if DeviseTokenAuth.default_callbacks
include DeviseTokenAuth::Concerns::UserOmniauthCallbacks
end

# can't set default on text fields in mysql, simulate here instead.
after_save :set_empty_token_hash
after_initialize :set_empty_token_hash

# keep uid in sync with email
before_save :sync_uid
before_create :sync_uid

# get rid of dead tokens
before_save :destroy_expired_tokens

Expand Down Expand Up @@ -239,21 +233,10 @@ def token_validation_response

protected

# only validate unique email among users that registered by email
def unique_email_user
if provider == 'email' and self.class.where(provider: 'email', email: email).count > 0
errors.add(:email, I18n.t("errors.messages.already_in_use"))
end
end

def set_empty_token_hash
self.tokens ||= {} if has_attribute?(:tokens)
end

def sync_uid
self.uid = email if provider == 'email'
end

def destroy_expired_tokens
if self.tokens
self.tokens.delete_if do |cid, v|
Expand Down
28 changes: 28 additions & 0 deletions app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module DeviseTokenAuth::Concerns::UserOmniauthCallbacks
extend ActiveSupport::Concern

included do
validates :email, presence: true, email: true, if: Proc.new { |u| u.provider == 'email' }
validates_presence_of :uid, if: Proc.new { |u| u.provider != 'email' }

# only validate unique emails among email registration users
validate :unique_email_user, on: :create

# keep uid in sync with email
before_save :sync_uid
before_create :sync_uid
end

protected

# only validate unique email among users that registered by email
def unique_email_user
if provider == 'email' and self.class.where(provider: 'email', email: email).count > 0
errors.add(:email, I18n.t("errors.messages.already_in_use"))
end
end

def sync_uid
self.uid = email if provider == 'email'
end
end
4 changes: 3 additions & 1 deletion lib/devise_token_auth/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class Engine < ::Rails::Engine
:redirect_whitelist,
:check_current_password_before_update,
:enable_standard_devise_support,
:remove_tokens_after_password_reset
:remove_tokens_after_password_reset,
:default_callbacks

self.change_headers_on_each_request = true
self.max_number_of_devices = 10
Expand All @@ -32,6 +33,7 @@ class Engine < ::Rails::Engine
self.check_current_password_before_update = false
self.enable_standard_devise_support = false
self.remove_tokens_after_password_reset = false
self.default_callbacks = true

def self.setup(&block)
yield self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
# password is updated.
# config.check_current_password_before_update = :attributes

# By default we will use callbacks for single omniauth.
# It depends on fields like email, provider and uid.
# config.default_callbacks = true

# 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!
Expand Down

0 comments on commit 9760a8b

Please sign in to comment.