Sha256: ffabec1a4e8dfcd9c373499ee678a0715f9677519fe5ceb25cba2fcea385b992

Contents?: true

Size: 1.86 KB

Versions: 1

Compression:

Stored size: 1.86 KB

Contents

require 'authoraise/version'
require 'set'

module Authoraise
  Error = Class.new(RuntimeError)

  class << self; attr_accessor :strict_mode end

  def authorize(options = {}, &block)
    Policy.new(&block).authorize(options)
  end

  class Check
    attr_reader :required_keys

    def initialize(required_keys, procedure)
      @required_keys = required_keys.to_set
      @procedure = procedure
    end

    def call(options)
      given_keys = options.keys.to_set

      if required_keys.subset?(given_keys)
        @procedure.call(*required_keys.map{|k| options[k]})
      else
        raise Error, "Check failed, missing keys: #{missing_keys(given_keys)}"
      end
    end

    def missing_keys(given_keys)
      (required_keys - given_keys.to_set).to_a
    end
  end

  class Policy
    def initialize
      @checks = []
      yield(self) if block_given?
    end

    def allow(&procedure)
      @checks <<
        Check.new(procedure.parameters.map(&:last), procedure)
    end

    def authorize(options = {})
      raise Error, 'Policy is empty' if @checks.empty?
      given_keys = options.keys.to_set
      assert_all_keys_match(given_keys) if Authoraise.strict_mode
      missing_keys = Set.new

      @checks.each do |check|
        if check.required_keys.subset?(given_keys)
          return true if check.(options)
        else
          missing_keys += check.missing_keys(given_keys)
        end
      end

      if missing_keys.empty?
        return false
      else
        raise Error,
          "Inconclusive authorization, missing keys: #{missing_keys.to_a}"
      end
    end

    private

    def assert_all_keys_match(given_keys)
      missing_keys = @checks.inject(Set.new) do |set, check|
        set + check.missing_keys(given_keys)
      end.to_a

      if !missing_keys.empty?
        raise Error, "Strict mode found missing keys: #{missing_keys}"
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
authoraise-0.1.2 lib/authoraise.rb