class RedisToken
Constants
- DEFAULT_PREFIX
- DEFAULT_TTL
Token lives 14 days by default
- VERSION
Attributes
Public Class Methods
Create RedisToken
instance
Implicit redis instance creation (redis parameters can be passed in args):
RedisToken.new(ttl: 5.days, prefix: 'project.tokens.', host: '127.0.0.1')
Explicit redis instance injection:
redis = Redis.new(host: '192.168.0.1', port: 33221) RedisToken.new(redis, ttl: 5.days, prefix: 'project.tokens.')
@param [Hash] args @option args [String] :prefix (DEFAULT_PREFIX
) redis keys prefix (e.g. 'myproject.tokens.') @option args [Integer] :ttl token time to live value (14 days by default) @option args [Class] :serializer_class serialization class, see RedisToken::Serializers::Native
, or use
method
@return [RedisToken] a new RedisToken
instance
# File lib/redis_token.rb, line 34 def initialize(args = {}, opts = {}) @redis = if args.nil? || args.is_a?(Hash) init_params(args) Redis.new(args) else init_params(opts) args end end
Public Instance Methods
All tokens
@return [Enumerator]
# File lib/redis_token.rb, line 142 def all all_tokens end
Create a new token
@param [Hash] args @option args [String] :owner owner of a token, e.g. 'client.1' or 'user-123' @option args [String] :token (SecureRandom.hex(16)) user defined token @option args :payload @option args [Integer] :ttl redefines the default ttl
@return [String] a new token
# File lib/redis_token.rb, line 53 def create(args = {}) token = args[:token] || generate_token value = { at: Time.now.to_i } owner = args[:owner] value[:owner] = owner if owner payload = args[:payload] value[:payload] = payload if payload @created_value = value key_ttl = args[:ttl] || @default_ttl @redis.multi do |multi| multi.set(token_to_key(token), @serializer.pack(value), ex: key_ttl) multi.set(token_to_owner(owner, token), nil, ex: key_ttl) end token end
Delete a token
@param [String] token
@return [Boolean]
# File lib/redis_token.rb, line 151 def delete(token) key = token_to_key(token) value = redis_get(key) return false unless value @redis.multi do |multi| multi.del(key) multi.del(token_to_owner(hash_get(value, :owner), token)) end true end
Delete all tokens
@return [Integer] number of deleted tokens
# File lib/redis_token.rb, line 185 def delete_all delete_tokens(all_tokens) end
Delete all tokens of an owner
@params [String] owner
@return [Integer] number of deleted tokens
# File lib/redis_token.rb, line 171 def delete_owned_by(owner) delete_tokens(owned_tokens(owner)) end
Delete tokens without an owner
@return [Integer] number of deleted tokens
# File lib/redis_token.rb, line 178 def delete_without_owner delete_tokens(owned_tokens) end
Get value of a token and slide ttl
@param [String] token @param [Hash] args @option args [Integer] :ttl @option args [Boolean] :slide_expire (true) slide ttl of a token
@return [Hash] value of a token
# File lib/redis_token.rb, line 82 def get(token, args = {}) key = token_to_key(token) value = redis_get(key) return unless value return value if args[:slide_expire] === false key_ttl = args[:ttl] || @default_ttl @redis.multi do |multi| multi.expire(key, key_ttl) multi.expire(token_to_owner(hash_get(value, :owner), token), key_ttl) end value end
Iterate all exist tokens of an owner
@param [String] owner
@return [Enumerator]
# File lib/redis_token.rb, line 128 def owned_by(owner) owned_tokens(owner) end
Set new payload of a token
@param [String] token @param [Hash] args @option args [Integer] :ttl set new time to live value @option args :payload new payload value
@return [Boolean]
# File lib/redis_token.rb, line 106 def set(token, args = {}) key = token_to_key(token) value = redis_get(key) return false unless value value[:payload] = args[:payload] key_ttl = args[:ttl] || @redis.ttl(key) @redis.multi do |multi| multi.set(key, @serializer.pack(value), ex: key_ttl) multi.expire(token_to_owner(hash_get(value, :owner), token), key_ttl) end true end
Retrieve the remaining ttl of a token
@return [Integer] ttl
# File lib/redis_token.rb, line 192 def ttl(token) @redis.ttl(token_to_key(token)) end
Use custom serialization class
Base serializer example:
class RedisToken class Serializers class Native def pack(value) Marshal.dump(value) end def unpack(value) Marshal.load(value) end end end end
MessagePack example:
require 'msgpack' class MsgPackSerializer def pack(value) MessagePack.pack(value) end def unpack(value) MessagePack.unpack(value) end end r = RedisToken.new.use(MsgPackSerializer)
@param [Object] serializer_class
@return [RedisToken]
# File lib/redis_token.rb, line 231 def use(serializer_class) @serializer = serializer_class.new self end
Tokens without an owner
@return [Enumerator]
# File lib/redis_token.rb, line 135 def without_owner owned_tokens end
Private Instance Methods
# File lib/redis_token.rb, line 274 def all_tokens iterator(nil, true) end
# File lib/redis_token.rb, line 295 def delete_tokens(enum) enum.reduce(0) do |deleted, token| del(token) deleted += 1 end end
# File lib/redis_token.rb, line 238 def generate_token SecureRandom.hex(16) end
Some serializers can't store symbols out of the box
# File lib/redis_token.rb, line 303 def hash_get(hash, sym) hash.fetch(sym, hash[sym.to_s]) end
# File lib/redis_token.rb, line 242 def init_params(args) @default_ttl = args[:ttl] || DEFAULT_TTL @prefix = args[:prefix] || DEFAULT_PREFIX @serializer = (args[:serializer_class] || Serializers::Native).new end
# File lib/redis_token.rb, line 278 def iterator(owner = nil, all = false) mask = all ? "#{@prefix}.t.*" : "#{@prefix}.o.#{owner}.*" Enumerator.new do |y| cursor = '0' loop do cursor, r = @redis.scan(cursor, match: mask) r.each do |key| y << (all ? key_to_token(key) : owner_key_to_token(owner, key)) end break if cursor == '0' end end end
# File lib/redis_token.rb, line 260 def key_to_token(key) key.sub("#{@prefix}.t.", '') end
# File lib/redis_token.rb, line 270 def owned_tokens(owner = nil) iterator(owner) end
# File lib/redis_token.rb, line 256 def owner_key_to_token(owner, key) key.sub("#{@prefix}.o.#{owner}.", '') end
# File lib/redis_token.rb, line 264 def redis_get(key) value = @redis.get(key) return unless value @serializer.unpack(value) end
# File lib/redis_token.rb, line 248 def token_to_key(token) "#{@prefix}.t.#{token}" end
# File lib/redis_token.rb, line 252 def token_to_owner(owner, token) "#{@prefix}.o.#{owner}.#{token}" end