app/models/user.rb in devise_token_auth-0.1.16 vs app/models/user.rb in devise_token_auth-0.1.17

- old
+ new

@@ -5,38 +5,112 @@ :recoverable, :rememberable, :trackable, :validatable, :confirmable serialize :tokens, JSON - # only validate unique emails among email registration users validates_presence_of :email, if: Proc.new { |u| u.provider == 'email' } validates_presence_of :confirm_success_url, if: Proc.new {|u| u.provider == 'email'} + # only validate unique emails among email registration users validate :unique_email_user, on: :create - def valid_token?(client_id, token) - return false unless self.tokens[client_id]['expiry'] > 2.weeks.ago - return false unless BCrypt::Password.new(self.tokens[client_id]['token']) == token + def valid_token?(token, client_id='default') + client_id ||= 'default' - return true + return true if ( + # ensure that expiry and token are set + self.tokens[client_id]['expiry'] and + self.tokens[client_id]['token'] and + + # ensure that the token was created within the last two weeks + self.tokens[client_id]['expiry'] > DeviseTokenAuth.token_lifespan.ago.to_f * 1000 and + + # ensure that the token is valid + BCrypt::Password.new(self.tokens[client_id]['token']) == token + ) + + return true if ( + # ensure that the last token and its creation time exist + self.tokens[client_id]['updated_at'] and + self.tokens[client_id]['last_token'] and + + # ensure that previous token falls within the batch buffer throttle time of the last request + Time.parse(self.tokens[client_id]['updated_at']) > Time.now - DeviseTokenAuth.batch_request_buffer_throttle and + + # ensure that the token is valid + BCrypt::Password.new(self.tokens[client_id]['last_token']) == token + ) + + # return false if none of the above conditions are met + return false end + + # update user's auth token (should happen on each request) + def create_new_auth_token(client_id=nil) + client_id ||= SecureRandom.urlsafe_base64(nil, false) + last_token ||= nil + token = SecureRandom.urlsafe_base64(nil, false) + token_hash = BCrypt::Password.create(token) + expiry = (Time.now.to_f + DeviseTokenAuth.token_lifespan).to_i * 1000 + + if self.tokens[client_id] and self.tokens[client_id]['token'] + last_token = self.tokens[client_id]['token'] + end + + self.tokens[client_id] = { + token: token_hash, + expiry: expiry, + last_token: last_token, + updated_at: Time.now + } + + self.save! + + return build_auth_header(token, client_id) + end + + + def build_auth_header(token, client_id='default') + client_id ||= 'default' + + # client may use expiry to prevent validation request if expired + expiry = self.tokens[client_id]['expiry'] + + return "token=#{token} client=#{client_id} expiry=#{expiry} uid=#{self.uid}" + end + + + def extend_batch_buffer(token, client_id) + self.tokens[client_id]['updated_at'] = Time.now + self.save! + + return build_auth_header(token, client_id) + end + + + private + + def serializable_hash(options={}) options ||= {} options[:except] ||= [:tokens] super(options) end + # don't use default devise email validation def email_changed? false end + def unique_email_user if provider == 'email' and User.where(provider: 'email', email: email).count > 0 - errors.add(:email, "Your email address is already in use") + errors.add(:email, "This email address is already in use") end end + def email_required? provider == 'email' end end