Last active
April 13, 2020 14:35
-
-
Save songjiz/811d62e01f3958f509e83006295c1a1e to your computer and use it in GitHub Desktop.
stateless token base on ActiveSupport::MessageEncryptor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ResetPasswordSupport | |
extend ActiveSupport::Concern | |
class ResetPasswordToken | |
include StatelessToken | |
def self.purpose | |
:reset_password | |
end | |
end | |
module ClassMethods | |
def find_by_reset_password_token(token) | |
class_name, id = ResetPasswordToken.decrypt(token) | |
return unless class_name == name | |
find(id).tap do |record| | |
record.reset_password_token = token | |
end | |
end | |
end | |
attr_accessor :reset_password_token | |
def generate_reset_password_token(options = {}) | |
self.reset_password_token = ResetPasswordToken.new(self, options).value | |
end | |
def reset_password(password, password_confirmation = nil) | |
self.password = password.presence | |
self.password_confirmation = password_confirmation.presence | |
save | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module StatelessToken | |
extend ActiveSupport::Concern | |
module ClassMethods | |
def decrypt(token) | |
encryptor.decrypt_and_verify(token, purpose: purpose) | |
rescue ActiveSupport::MessageEncryptor::InvalidMessage | |
nil | |
end | |
def encrypt(data, expires_in: nil, expires_at: nil, **options) | |
options.merge!( | |
purpose: purpose, | |
expires_in: expires_in, | |
expires_at: expires_at | |
) | |
encryptor.encrypt_and_sign data, **options | |
end | |
def purpose; end | |
private | |
def encryptor | |
@encryptor ||= ActiveSupport::MessageEncryptor.new(secret) | |
end | |
def secret | |
@secret ||= key_generator.generate_key(salt, key_len) | |
end | |
def key_generator | |
Rails.application.key_generator | |
end | |
def salt | |
to_s | |
end | |
def key_len | |
ActiveSupport::MessageEncryptor.key_len | |
end | |
end | |
def initialize(record, expires_in: nil, expires_at: nil) | |
@record = record | |
@expires_in = expires_in | |
@expires_at = expires_at | |
end | |
def payload | |
[@record.class.name, @record.id] | |
end | |
def value | |
@value ||= self.class.encrypt(payload, expires_in: @expires_in, expires_at: @expires_at) | |
end | |
def to_s | |
value | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ApplicationRecord | |
include ResetPasswordSupport | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment