class Cloak::Redis

don't extend Redis so we can confirm operations are safe before adding

Public Class Methods

new(key: nil, **options) click to toggle source
# File lib/cloak/redis.rb, line 15
def initialize(key: nil, **options)
  @redis = ::Redis.new(**options)
  create_encryptor(key)
end

Public Instance Methods

bitcount(key, start = 0, stop = -1) click to toggle source

append not supported

# File lib/cloak/redis.rb, line 222
def bitcount(key, start = 0, stop = -1)
  on_result(@redis.get(encrypt_key(key))) do |res|
    decrypt_value(res)[start..stop].unpack1("B*").count("1")
  end
end
bitpos(key, bit, start = nil, stop = nil) click to toggle source

bitop not supported

# File lib/cloak/redis.rb, line 230
def bitpos(key, bit, start = nil, stop = nil)
  on_result(@redis.get(encrypt_key(key))) do |res|
    pos = decrypt_value(res)[(start || 0)..(stop || -1)].unpack1("B*").index(bit.to_s)
    pos ? pos + (start.to_i * 8) : -1
  end
end
blpop(*args) click to toggle source
# File lib/cloak/redis.rb, line 282
def blpop(*args)
  _bpop(:blpop, args)
end
brpop(*args) click to toggle source
# File lib/cloak/redis.rb, line 286
def brpop(*args)
  _bpop(:brpop, args)
end
brpoplpush(source, destination, deprecated_timeout = 0, timeout: deprecated_timeout) click to toggle source
# File lib/cloak/redis.rb, line 290
def brpoplpush(source, destination, deprecated_timeout = 0, timeout: deprecated_timeout)
  @redis.brpoplpush(encrypt_key(source), encrypt_key(destination), timeout: timeout)
end
bzpopmax(*args) click to toggle source
# File lib/cloak/redis.rb, line 440
def bzpopmax(*args)
  _bpop(:bzpopmax, args, zset: true)
end
bzpopmin(*args) click to toggle source
# File lib/cloak/redis.rb, line 444
def bzpopmin(*args)
  _bpop(:bzpopmin, args, zset: true)
end
debug(*args) click to toggle source
# File lib/cloak/redis.rb, line 20
def debug(*args)
  args[1] = encrypt_key(args[1]) if args[0] == "object"
  @redis.debug(*args)
end
decr(key) click to toggle source
# File lib/cloak/redis.rb, line 130
def decr(key)
  @redis.decr(encrypt_key(key))
end
decrby(key, decrement) click to toggle source
# File lib/cloak/redis.rb, line 134
def decrby(key, decrement)
  @redis.decrby(encrypt_key(key), decrement)
end
del(*keys) click to toggle source
# File lib/cloak/redis.rb, line 77
def del(*keys)
  @redis.del(*keys.map { |k| encrypt_key(k) })
end
dump(key) click to toggle source
# File lib/cloak/redis.rb, line 69
def dump(key)
  @redis.dump(encrypt_key(key))
end
echo(value) click to toggle source
# File lib/cloak/redis.rb, line 35
def echo(value)
  on_result(@redis.echo(encrypt_value(value))) do |res|
    decrypt_value(res)
  end
end
exists(*keys) click to toggle source
# File lib/cloak/redis.rb, line 85
def exists(*keys)
  @redis.exists(*keys.map { |k| encrypt_key(k) })
end
exists?(*keys) click to toggle source
# File lib/cloak/redis.rb, line 89
def exists?(*keys)
  @redis.exists?(*keys.map { |k| encrypt_key(k) })
end
expire(key, seconds) click to toggle source
# File lib/cloak/redis.rb, line 45
def expire(key, seconds)
  @redis.expire(encrypt_key(key), seconds)
end
expireat(key, unix_time) click to toggle source
# File lib/cloak/redis.rb, line 49
def expireat(key, unix_time)
  @redis.expireat(encrypt_key(key), unix_time)
end
get(key) click to toggle source
# File lib/cloak/redis.rb, line 184
def get(key)
  on_result(@redis.get(encrypt_key(key))) do |res|
    decrypt_value(res)
  end
end
getbit(key, offset) click to toggle source

TODO raise “ERR bit offset is not an integer or out of range” when needed

# File lib/cloak/redis.rb, line 213
def getbit(key, offset)
  on_result(@redis.get(encrypt_key(key))) do |res|
    v = decrypt_value(res)
    v.nil? ? 0 : v.unpack1("B*")[offset].to_i
  end
end
getrange(key, start, stop) click to toggle source

setrange not supported

# File lib/cloak/redis.rb, line 204
def getrange(key, start, stop)
  on_result(@redis.get(encrypt_key(key))) do |res|
    decrypt_value(res)[start..stop]
  end
end
getset(key, value) click to toggle source
# File lib/cloak/redis.rb, line 237
def getset(key, value)
  on_result(@redis.getset(encrypt_key(key), encrypt_value(value))) do |res|
    decrypt_value(res)
  end
end
hdel(key, *fields) click to toggle source
# File lib/cloak/redis.rb, line 575
def hdel(key, *fields)
  ek = encrypt_key(key)
  @redis.hdel(ek, *fields.map { |v| encrypt_field(ek, v) })
end
hexists(key, field) click to toggle source
# File lib/cloak/redis.rb, line 580
def hexists(key, field)
  ek = encrypt_key(key)
  @redis.hexists(ek, encrypt_field(ek, field))
end
hget(key, field) click to toggle source
# File lib/cloak/redis.rb, line 554
def hget(key, field)
  ek = encrypt_key(key)
  on_result(@redis.hget(ek, encrypt_field(ek, field))) do |res|
    decrypt_value(res)
  end
end
hgetall(key) click to toggle source
# File lib/cloak/redis.rb, line 609
def hgetall(key)
  ek = encrypt_key(key)
  on_result(@redis.hgetall(ek)) do |res|
    res.map { |f, v| [decrypt_field(ek, f), decrypt_value(v)] }.to_h
  end
end
hincrby(key, field, increment) click to toggle source
# File lib/cloak/redis.rb, line 585
def hincrby(key, field, increment)
  ek = encrypt_key(key)
  @redis.hincrby(ek, encrypt_field(ek, field), increment)
end
hincrbyfloat(key, field, increment) click to toggle source
# File lib/cloak/redis.rb, line 590
def hincrbyfloat(key, field, increment)
  ek = encrypt_key(key)
  @redis.hincrbyfloat(ek, encrypt_field(ek, field), increment)
end
hkeys(key) click to toggle source
# File lib/cloak/redis.rb, line 595
def hkeys(key)
  ek = encrypt_key(key)
  on_result(@redis.hkeys(ek)) do |res|
    res.map { |v| decrypt_field(ek, v) }
  end
end
hlen(key) click to toggle source
# File lib/cloak/redis.rb, line 528
def hlen(key)
  @redis.hlen(encrypt_key(key))
end
hmget(key, *fields, &blk) click to toggle source
# File lib/cloak/redis.rb, line 561
def hmget(key, *fields, &blk)
  ek = encrypt_key(key)
  on_result(@redis.hmget(ek, *fields.map { |f| encrypt_field(ek, f) }, &blk)) do |res|
    res.map { |v| decrypt_value(v) }
  end
end
hmset(key, *attrs) click to toggle source
# File lib/cloak/redis.rb, line 544
def hmset(key, *attrs)
  ek = encrypt_key(key)
  @redis.hset(ek, attrs.map.with_index { |v, i| i % 2 == 0 ? encrypt_field(ek, v) : encrypt_value(v) })
end
hscan(key, cursor, count: nil) click to toggle source

match option not supported

# File lib/cloak/redis.rb, line 639
def hscan(key, cursor, count: nil)
  ek = encrypt_key(key)
  on_result(@redis.hscan(ek, cursor, count: count)) do |res|
    [res[0], res[1].map { |v| [decrypt_field(ek, v[0]), decrypt_value(v[1])] }]
  end
end
hscan_each(key, **options, &block) click to toggle source

match redis

# File lib/cloak/redis.rb, line 647
def hscan_each(key, **options, &block)
  return to_enum(:hscan_each, key, **options) unless block_given?

  cursor = 0
  loop do
    # hscan encrypts key
    cursor, values = hscan(key, cursor, **options)
    values.each(&block)
    break if cursor == "0"
  end
end
hset(key, *attrs) click to toggle source
# File lib/cloak/redis.rb, line 532
def hset(key, *attrs)
  attrs = attrs.first.flatten if attrs.size == 1 && attrs.first.is_a?(Hash)

  ek = encrypt_key(key)
  @redis.hset(ek, attrs.map.with_index { |v, i| i % 2 == 0 ? encrypt_field(ek, v) : encrypt_value(v) })
end
hsetnx(key, field, value) click to toggle source
# File lib/cloak/redis.rb, line 539
def hsetnx(key, field, value)
  ek = encrypt_key(key)
  @redis.hsetnx(ek, encrypt_field(ek, field), encrypt_value(value))
end
hvals(key) click to toggle source
# File lib/cloak/redis.rb, line 602
def hvals(key)
  ek = encrypt_key(key)
  on_result(@redis.hvals(ek)) do |res|
    res.map { |v| decrypt_value(v) }
  end
end
incr(key) click to toggle source
# File lib/cloak/redis.rb, line 138
def incr(key)
  @redis.incr(encrypt_key(key))
end
incrby(key, increment) click to toggle source
# File lib/cloak/redis.rb, line 142
def incrby(key, increment)
  @redis.incrby(encrypt_key(key), increment)
end
incrbyfloat(key, increment) click to toggle source
# File lib/cloak/redis.rb, line 146
def incrbyfloat(key, increment)
  @redis.incrbyfloat(encrypt_key(key), increment)
end
keys(pattern = "*") click to toggle source

could match in-memory

# File lib/cloak/redis.rb, line 94
def keys(pattern = "*")
  raise "Only * pattern supported" if pattern != "*"
  on_result(@redis.keys(pattern)) do |res|
    res.map { |k| decrypt_key(k) }
  end
end
lindex(key, index) click to toggle source
# File lib/cloak/redis.rb, line 294
def lindex(key, index)
  on_result(@redis.lindex(encrypt_key(key), index)) do |res|
    decrypt_element(res)
  end
end
linsert(key, where, pivot, value) click to toggle source
# File lib/cloak/redis.rb, line 300
def linsert(key, where, pivot, value)
  @redis.linsert(encrypt_key(key), where, pivot, encrypt_element(value))
end
llen(key) click to toggle source
# File lib/cloak/redis.rb, line 250
def llen(key)
  @redis.llen(encrypt_key(key))
end
lpop(key) click to toggle source
# File lib/cloak/redis.rb, line 270
def lpop(key)
  @redis.lpop(encrypt_key(key))
end
lpush(key, value) click to toggle source
# File lib/cloak/redis.rb, line 254
def lpush(key, value)
  @redis.lpush(encrypt_key(key), value.is_a?(Array) ? value.map { |v| encrypt_element(v) } : encrypt_element(value))
end
lpushx(key, value) click to toggle source
# File lib/cloak/redis.rb, line 258
def lpushx(key, value)
  @redis.lpushx(encrypt_key(key), encrypt_element(value))
end
lrange(key, start, stop) click to toggle source
# File lib/cloak/redis.rb, line 304
def lrange(key, start, stop)
  @redis.lrange(encrypt_key(key), start, stop)
end
lset(key, index, value) click to toggle source

lrem not possible with random nonce

# File lib/cloak/redis.rb, line 310
def lset(key, index, value)
  @redis.lset(encrypt_key(key), index, encrypt_element(value))
end
ltrim(key, start, stop) click to toggle source
# File lib/cloak/redis.rb, line 314
def ltrim(key, start, stop)
  @redis.ltrim(encrypt_key(key), start, stop)
end
mapped_hmget(key, *fields) click to toggle source
# File lib/cloak/redis.rb, line 568
def mapped_hmget(key, *fields)
  ek = encrypt_key(key)
  on_result(@redis.mapped_hmget(ek, *fields.map { |f| encrypt_field(ek, f) })) do |res|
    res.map { |f, v| [decrypt_field(ek, f), decrypt_value(v)] }.to_h
  end
end
mapped_hmset(key, hash) click to toggle source

match redis

# File lib/cloak/redis.rb, line 550
def mapped_hmset(key, hash)
  hmset(key, hash.to_a.flatten)
end
mapped_mget(*keys) click to toggle source
# File lib/cloak/redis.rb, line 196
def mapped_mget(*keys)
  on_result(@redis.mapped_mget(*keys.map { |k| encrypt_key(k) })) do |res|
    res.map { |k, v| [decrypt_key(k), decrypt_value(v)] }.to_h
  end
end
mapped_mset(hash) click to toggle source

match redis

# File lib/cloak/redis.rb, line 171
def mapped_mset(hash)
  mset(hash.to_a.flatten)
end
mapped_msetnx(hash) click to toggle source

match redis

# File lib/cloak/redis.rb, line 180
def mapped_msetnx(hash)
  msetnx(hash.to_a.flatten)
end
mget(*keys, &blk) click to toggle source
# File lib/cloak/redis.rb, line 190
def mget(*keys, &blk)
  on_result(@redis.mget(*keys.map { |k| encrypt_key(k) }, &blk)) do |res|
    res.map { |v| decrypt_value(v) }
  end
end
move(key, db) click to toggle source
# File lib/cloak/redis.rb, line 101
def move(key, db)
  @redis.move(encrypt_key(key), db)
end
mset(*args) click to toggle source
# File lib/cloak/redis.rb, line 166
def mset(*args)
  @redis.mset(args.map.with_index { |v, i| i % 2 == 0 ? encrypt_key(v) : encrypt_value(v) })
end
msetnx(*args) click to toggle source
# File lib/cloak/redis.rb, line 175
def msetnx(*args)
  @redis.msetnx(args.map.with_index { |v, i| i % 2 == 0 ? encrypt_key(v) : encrypt_value(v) })
end
object(*args) click to toggle source
# File lib/cloak/redis.rb, line 105
def object(*args)
  args[1] = encrypt_key(args[1]) if args.size > 1
  @redis.object(*args)
end
persist(key) click to toggle source
# File lib/cloak/redis.rb, line 41
def persist(key)
  @redis.persist(encrypt_key(key))
end
pexpire(key, milliseconds) click to toggle source
# File lib/cloak/redis.rb, line 57
def pexpire(key, milliseconds)
  @redis.pexpire(encrypt_key(key), milliseconds)
end
pexpireat(key, ms_unix_time) click to toggle source
# File lib/cloak/redis.rb, line 61
def pexpireat(key, ms_unix_time)
  @redis.pexpireat(encrypt_key(key), ms_unix_time)
end
pfadd(key, member) click to toggle source
# File lib/cloak/redis.rb, line 699
def pfadd(key, member)
  @redis.pfadd(encrypt_key(key), member.is_a?(Array) ? member.map { |v| encrypt_hll_element(v) } : encrypt_hll_element(member))
end
pfcount(*keys) click to toggle source
# File lib/cloak/redis.rb, line 703
def pfcount(*keys)
  @redis.pfcount(*keys.map { |k| encrypt_key(k) })
end
pfmerge(dest_key, *source_key) click to toggle source
# File lib/cloak/redis.rb, line 707
def pfmerge(dest_key, *source_key)
  @redis.pfmerge(encrypt_key(dest_key), *source_key.map { |k| encrypt_key(k) })
end
ping(message = nil) click to toggle source
# File lib/cloak/redis.rb, line 25
def ping(message = nil)
  if message.nil?
    @redis.ping
  else
    on_result(@redis.ping(encrypt_value(message))) do |res|
      decrypt_value(res)
    end
  end
end
psetex(key, ttl, value) click to toggle source
# File lib/cloak/redis.rb, line 158
def psetex(key, ttl, value)
  @redis.psetex(encrypt_key(key), ttl, encrypt_value(value))
end
pttl(key) click to toggle source
# File lib/cloak/redis.rb, line 65
def pttl(key)
  @redis.pttl(encrypt_key(key))
end
randomkey() click to toggle source
# File lib/cloak/redis.rb, line 110
def randomkey
  on_result(@redis.randomkey) do |res|
    res.nil? ? res : decrypt_key(res)
  end
end
rename(old_name, new_name) click to toggle source
# File lib/cloak/redis.rb, line 116
def rename(old_name, new_name)
  @redis.rename(encrypt_key(old_name), encrypt_key(new_name))
end
renamenx(old_name, new_name) click to toggle source
# File lib/cloak/redis.rb, line 120
def renamenx(old_name, new_name)
  @redis.renamenx(encrypt_key(old_name), encrypt_key(new_name))
end
restore(key, ttl, serialized_value, replace: nil) click to toggle source
# File lib/cloak/redis.rb, line 73
def restore(key, ttl, serialized_value, replace: nil)
  @redis.restore(encrypt_key(key), ttl, serialized_value, replace: replace)
end
rpop(key) click to toggle source
# File lib/cloak/redis.rb, line 274
def rpop(key)
  @redis.rpop(encrypt_key(key))
end
rpoplpush(source, destination) click to toggle source
# File lib/cloak/redis.rb, line 278
def rpoplpush(source, destination)
  @redis.rpoplpush(encrypt_key(source), encrypt_key(destination))
end
rpush(key, value) click to toggle source
# File lib/cloak/redis.rb, line 262
def rpush(key, value)
  @redis.rpush(encrypt_key(key), value.is_a?(Array) ? value.map { |v| encrypt_element(v) } : encrypt_element(value))
end
rpushx(key, value) click to toggle source
# File lib/cloak/redis.rb, line 266
def rpushx(key, value)
  @redis.rpushx(encrypt_key(key), encrypt_element(value))
end
sadd(key, member) click to toggle source
# File lib/cloak/redis.rb, line 322
def sadd(key, member)
  @redis.sadd(encrypt_key(key), encrypt_member(member))
end
scan(cursor, count: nil) click to toggle source

match option not supported

# File lib/cloak/redis.rb, line 620
def scan(cursor, count: nil)
  on_result(@redis.scan(cursor, count: count)) do |res|
    [res[0], res[1].map { |v| decrypt_key(v) }]
  end
end
scan_each(**options, &block) click to toggle source

match redis

# File lib/cloak/redis.rb, line 627
def scan_each(**options, &block)
  return to_enum(:scan_each, **options) unless block_given?

  cursor = 0
  loop do
    cursor, keys = scan(cursor, **options)
    keys.each(&block)
    break if cursor == "0"
  end
end
scard(key) click to toggle source
# File lib/cloak/redis.rb, line 318
def scard(key)
  @redis.scard(encrypt_key(key))
end
sdiff(*keys) click to toggle source
# File lib/cloak/redis.rb, line 364
def sdiff(*keys)
  on_result(@redis.sdiff(*keys.map { |k| encrypt_key(k) })) do |res|
    res.map { |v| decrypt_member(v) }
  end
end
sdiffstore(destination, *keys) click to toggle source
# File lib/cloak/redis.rb, line 370
def sdiffstore(destination, *keys)
  @redis.sdiffstore(encrypt_key(destination), *keys.map { |k| encrypt_key(k) })
end
set(key, value, **options) click to toggle source
# File lib/cloak/redis.rb, line 150
def set(key, value, **options)
  @redis.set(encrypt_key(key), encrypt_value(value), **options)
end
setex(key, ttl, value) click to toggle source
# File lib/cloak/redis.rb, line 154
def setex(key, ttl, value)
  @redis.setex(encrypt_key(key), ttl, encrypt_value(value))
end
setnx(key, value) click to toggle source
# File lib/cloak/redis.rb, line 162
def setnx(key, value)
  @redis.setnx(encrypt_key(key), ttl, encrypt_value(value))
end
sinter(*keys) click to toggle source
# File lib/cloak/redis.rb, line 374
def sinter(*keys)
  on_result(@redis.sinter(*keys.map { |k| encrypt_key(k) })) do |res|
    res.map { |v| decrypt_member(v) }
  end
end
sinterstore(destination, *keys) click to toggle source
# File lib/cloak/redis.rb, line 380
def sinterstore(destination, *keys)
  @redis.sinterstore(encrypt_key(destination), *keys.map { |k| encrypt_key(k) })
end
sismember(key, member) click to toggle source
# File lib/cloak/redis.rb, line 354
def sismember(key, member)
  @redis.sismember(encrypt_key(key), encrypt_member(member))
end
smembers(key) click to toggle source
# File lib/cloak/redis.rb, line 358
def smembers(key)
  on_result(@redis.smembers(encrypt_key(key))) do |res|
    res.map { |v| decrypt_member(v) }
  end
end
smove(source, destination, member) click to toggle source
# File lib/cloak/redis.rb, line 350
def smove(source, destination, member)
  @redis.smove(encrypt_key(source), encrypt_key(destination), encrypt_member(member))
end
spop(key, count = nil) click to toggle source
# File lib/cloak/redis.rb, line 330
def spop(key, count = nil)
  on_result(@redis.spop(encrypt_key(key))) do |res|
    if count.nil?
      decrypt_member(res)
    else
      res.map { |v| decrypt_member(v) }
    end
  end
end
srandmember(key, count = nil) click to toggle source
# File lib/cloak/redis.rb, line 340
def srandmember(key, count = nil)
  on_result(@redis.srandmember(encrypt_key(key))) do |res|
    if count.nil?
      decrypt_member(res)
    else
      res.map { |v| decrypt_member(v) }
    end
  end
end
srem(key, member) click to toggle source
# File lib/cloak/redis.rb, line 326
def srem(key, member)
  @redis.srem(encrypt_key(key), encrypt_member(member))
end
sscan(key, cursor, count: nil) click to toggle source

match option not supported

# File lib/cloak/redis.rb, line 680
def sscan(key, cursor, count: nil)
  on_result(@redis.sscan(encrypt_key(key), cursor, count: count)) do |res|
    [res[0], res[1].map { |v| decrypt_member(v) }]
  end
end
sscan_each(key, **options, &block) click to toggle source

match redis

# File lib/cloak/redis.rb, line 687
def sscan_each(key, **options, &block)
  return to_enum(:sscan_each, key, **options) unless block_given?

  cursor = 0
  loop do
    # sscan encrypts key
    cursor, keys = sscan(key, cursor, **options)
    keys.each(&block)
    break if cursor == "0"
  end
end
strlen(key) click to toggle source

subtract nonce size (16) and auth tag (16)

# File lib/cloak/redis.rb, line 244
def strlen(key)
  on_result(@redis.strlen(encrypt_key(key))) do |res|
    res == 0 ? 0 : res - 32
  end
end
sunion(*keys) click to toggle source
# File lib/cloak/redis.rb, line 384
def sunion(*keys)
  on_result(@redis.sunion(*keys.map { |k| encrypt_key(k) })) do |res|
    res.map { |v| decrypt_member(v) }
  end
end
sunionstore(destination, *keys) click to toggle source
# File lib/cloak/redis.rb, line 390
def sunionstore(destination, *keys)
  @redis.sunionstore(encrypt_key(destination), *keys.map { |k| encrypt_key(k) })
end
ttl(key) click to toggle source
# File lib/cloak/redis.rb, line 53
def ttl(key)
  @redis.ttl(encrypt_key(key))
end
type(key) click to toggle source

sort not supported

# File lib/cloak/redis.rb, line 126
def type(key)
  @redis.type(encrypt_key(key))
end
zadd(key, *args, **options) click to toggle source
# File lib/cloak/redis.rb, line 398
def zadd(key, *args, **options)
  if args.size == 1 && args[0].is_a?(Array)
    args = args[0]
  elsif args.size == 2
    args = [args]
  else
    raise ArgumentError, "wrong number of arguments"
  end

  # convert score to numeric to avoid data leakage
  # if there's an issue with arguments
  @redis.zadd(encrypt_key(key), args.map { |v| [to_score(v[0]), encrypt_member(v[1])] }, **options)
end
zcard(key) click to toggle source
# File lib/cloak/redis.rb, line 394
def zcard(key)
  @redis.zcard(encrypt_key(key))
end
zcount(key, min, max) click to toggle source
# File lib/cloak/redis.rb, line 516
def zcount(key, min, max)
  @redis.zcount(encrypt_key(key), min, max)
end
zincrby(key, increment, member) click to toggle source
# File lib/cloak/redis.rb, line 412
def zincrby(key, increment, member)
  @redis.zincrby(encrypt_key(key), increment, encrypt_member(member))
end
zinterstore(destination, keys, weights: nil, aggregate: nil) click to toggle source
# File lib/cloak/redis.rb, line 520
def zinterstore(destination, keys, weights: nil, aggregate: nil)
  @redis.zinterstore(encrypt_key(destination), keys.map { |k| encrypt_key(k) }, weights: weights, aggregate: aggregate)
end
zpopmax(key, count = nil) click to toggle source
# File lib/cloak/redis.rb, line 420
def zpopmax(key, count = nil)
  on_result(@redis.zpopmax(encrypt_key(key), count)) do |res|
    if count.to_i > 1
      res.map { |v, s| [decrypt_member(v), s] }
    else
      [decrypt_member(res[0]), res[1]]
    end
  end
end
zpopmin(key, count = nil) click to toggle source
# File lib/cloak/redis.rb, line 430
def zpopmin(key, count = nil)
  on_result(@redis.zpopmin(encrypt_key(key), count)) do |res|
    if count.to_i > 1
      res.map { |v, s| [decrypt_member(v), s] }
    else
      [decrypt_member(res[0]), res[1]]
    end
  end
end
zrange(key, start, stop, withscores: false, with_scores: withscores) click to toggle source

can't guarantee lexographical order without potentially fetching all elements

# File lib/cloak/redis.rb, line 453
def zrange(key, start, stop, withscores: false, with_scores: withscores)
  on_result(@redis.zrange(encrypt_key(key), start, stop, with_scores: with_scores)) do |res|
    if with_scores
      res.map { |v, s| [decrypt_member(v), s] }
    else
      res.map { |v| decrypt_member(v) }
    end
  end
end
zrangebyscore(key, min, max, withscores: false, with_scores: withscores, limit: nil) click to toggle source

could guarantee lexographical order when limit not used

# File lib/cloak/redis.rb, line 491
def zrangebyscore(key, min, max, withscores: false, with_scores: withscores, limit: nil)
  on_result(@redis.zrangebyscore(encrypt_key(key), min, max, with_scores: with_scores, limit: limit)) do |res|
    if with_scores
      res.map { |v, s| [decrypt_member(v), s] }
    else
      res.map { |v| decrypt_member(v) }
    end
  end
end
zrank(key, member) click to toggle source
# File lib/cloak/redis.rb, line 474
def zrank(key, member)
  @redis.zrank(encrypt_key(key), encrypt_member(member))
end
zrem(key, member) click to toggle source
# File lib/cloak/redis.rb, line 416
def zrem(key, member)
  @redis.zrem(encrypt_key(key), member.is_a?(Array) ? member.map { |v| encrypt_member(v) } : encrypt_member(member))
end
zremrangebyrank(key, start, stop) click to toggle source
# File lib/cloak/redis.rb, line 482
def zremrangebyrank(key, start, stop)
  @redis.zremrangebyrank(encrypt_key(key), start, stop)
end
zremrangebyscore(key, min, max) click to toggle source
# File lib/cloak/redis.rb, line 512
def zremrangebyscore(key, min, max)
  @redis.zremrangebyscore(encrypt_key(key), min, max)
end
zrevrange(key, start, stop, withscores: false, with_scores: withscores) click to toggle source

can't guarantee lexographical order without potentially fetching all elements

# File lib/cloak/redis.rb, line 464
def zrevrange(key, start, stop, withscores: false, with_scores: withscores)
  on_result(@redis.zrevrange(encrypt_key(key), start, stop, with_scores: with_scores)) do |res|
    if with_scores
      res.map { |v, s| [decrypt_member(v), s] }
    else
      res.map { |v| decrypt_member(v) }
    end
  end
end
zrevrangebyscore(key, max, min, withscores: false, with_scores: withscores, limit: nil) click to toggle source

could guarantee lexographical order when limit not used

# File lib/cloak/redis.rb, line 502
def zrevrangebyscore(key, max, min, withscores: false, with_scores: withscores, limit: nil)
  on_result(@redis.zrevrangebyscore(encrypt_key(key), max, min, with_scores: with_scores, limit: limit)) do |res|
    if with_scores
      res.map { |v, s| [decrypt_member(v), s] }
    else
      res.map { |v| decrypt_member(v) }
    end
  end
end
zrevrank(key, member) click to toggle source
# File lib/cloak/redis.rb, line 478
def zrevrank(key, member)
  @redis.zrevrank(encrypt_key(key), encrypt_member(member))
end
zscan(key, cursor, count: nil) click to toggle source

match option not supported

# File lib/cloak/redis.rb, line 660
def zscan(key, cursor, count: nil)
  on_result(@redis.zscan(encrypt_key(key), cursor, count: count)) do |res|
    [res[0], res[1].map { |v| [decrypt_member(v[0]), v[1]] }]
  end
end
zscan_each(key, **options, &block) click to toggle source

match redis

# File lib/cloak/redis.rb, line 667
def zscan_each(key, **options, &block)
  return to_enum(:zscan_each, key, **options) unless block_given?

  cursor = 0
  loop do
    # zscan encrypts key
    cursor, values = zscan(key, cursor, **options)
    values.each(&block)
    break if cursor == "0"
  end
end
zscore(key, member) click to toggle source
# File lib/cloak/redis.rb, line 448
def zscore(key, member)
  @redis.zscore(encrypt_key(key), encrypt_member(member))
end
zunionstore(destination, keys, weights: nil, aggregate: nil) click to toggle source
# File lib/cloak/redis.rb, line 524
def zunionstore(destination, keys, weights: nil, aggregate: nil)
  @redis.zunionstore(encrypt_key(destination), keys.map { |k| encrypt_key(k) }, weights: weights, aggregate: aggregate)
end

Private Instance Methods

_bpop(cmd, args, zset: false, &blk) click to toggle source
# File lib/cloak/redis.rb, line 731
def _bpop(cmd, args, zset: false, &blk)
  # match redis
  timeout = if args.last.is_a?(Hash)
    options = args.pop
    options[:timeout]
  elsif args.last.respond_to?(:to_int)
    args.pop.to_int
  end

  keys = args.flatten.map { |k| encrypt_key(k) }

  on_result(@redis._bpop(cmd, [keys, {timeout: timeout}], &blk)) do |res|
    if res.nil?
      res
    elsif zset
      [decrypt_key(res[0]), decrypt_member(res[1]), res[2]]
    else
      [decrypt_key(res[0]), decrypt_element(res[1])]
    end
  end
end
on_result(res, &block) click to toggle source

geo not supported streams not supported

# File lib/cloak/redis.rb, line 716
def on_result(res, &block)
  if res.is_a?(::Redis::Future)
    res.instance_exec do
      if @transformation
        raise "Not implemented yet. Please create an issue."
      else
        @transformation = block
      end
    end
    res
  else
    block.call(res)
  end
end
to_score(v) click to toggle source
# File lib/cloak/redis.rb, line 753
def to_score(v)
  v.is_a?(Numeric) ? v : v.to_f
end