class ICFS::UsersRedis

Implement Users with a Redis cache

Public Class Methods

new(redis, base, opts={}) click to toggle source

New instance

@param redis [Redis] The redis client @param base [Users] The base Users store @param opts [Hash] Options @option opts [String] :prefix Prefix for Redis key @option opts [Integer] :expires Expiration time in seconds @option opts [Logger] :log Logger which records info about user

# File lib/icfs/users_redis.rb, line 33
def initialize(redis, base, opts={})
  @redis = redis
  @base = base
  @pre = opts[:prefix] || ''
  @exp = opts[:expires] || 1*60*60 # 1 hour default
  @log = opts[:log]
end

Public Instance Methods

flush(urg) click to toggle source

(see Users#flush)

# File lib/icfs/users_redis.rb, line 54
def flush(urg)
  Items.validate(urg, 'User/role/group name', Items::FieldUsergrp)
  @log.info('User/role/group cache flush: %s' % urg) if @log
  @redis.del(_key(urg))
  return true
end
read(urg) click to toggle source

(see Users#read)

# File lib/icfs/users_redis.rb, line 65
def read(urg)
  Items.validate(urg, 'User/role/group name', Items::FieldUsergrp)
  key = _key(urg)
  @log.debug('User/role/group read: %s' % urg) if @log

  # try cache
  json = @redis.get(key)
  if json
    @log.debug('User/role/group cache hit: %s' % urg) if @log
    return JSON.parse(json)
  end

  # get base object from base store
  bse = @base.read(urg)
  if !bse
    @log.warn('User/role/group not found: %s' % urg) if @log
    return nil
  end

  # assemble
  seen = Set.new.add(urg)
  ary = []
  roles = Set.new
  grps = Set.new
  perms = Set.new
  if bse['roles']
    ary.concat bse['roles']
    roles.merge bse['roles']
  end
  if bse['groups']
    ary.concat bse['groups']
    grps.merge bse['groups']
  end
  if bse['perms']
    perms.merge bse['perms']
  end

  # call ourself recursively for any un-expanded memberships
  while itm = ary.shift
    next if seen.include?(itm)
    seen.add(itm)
    ikey = _key(itm)

    # all included u/r/g have been seen & expanded
    mem = self.read(itm)
    next if !mem
    if mem['roles']
      roles.merge mem['roles']
      seen.merge mem['roles']
    end
    if mem['groups']
      grps.merge mem['groups']
      seen.merge mem['groups']
    end
    if mem['perms']
      perms.merge mem['perms']
    end
  end

  # final result
  bse['roles'] = roles.to_a unless roles.empty?
  bse['groups'] = grps.to_a unless grps.empty?
  bse['perms'] = perms.to_a unless perms.empty?
  json = JSON.generate(bse)

  # save to cache
  @redis.set(key, json)
  @redis.expire(key, @exp)
  @log.info('User/role/group cached: %s %s' % [urg, json]) if @log
  return bse
end
write(obj) click to toggle source

(see Users#write)

# File lib/icfs/users_redis.rb, line 141
def write(obj)
  json = Items.generate(obj, 'User/Role/Group', Users::ValUser)
  key = _key(obj['name'])
  @log.info('User/role/group write: %s' % urg) if @log
  @redis.del(key)
  @base.write(obj)
end

Private Instance Methods

_key(urg) click to toggle source

Where to store in Redis

# File lib/icfs/users_redis.rb, line 45
def _key(urg)
  @pre + urg
end