producthunt/kitty-policy

View on GitHub
lib/kitty_policy/dsl.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

module KittyPolicy
  module DSL
    def self.extended(base)
      base.extend(base)
    end

    def can?(user, action, subject = :empty)
      if subject == :empty
        public_send Helper.method_name(action), user
      else
        public_send Helper.method_name(action, subject), user, subject
      end
    end

    def authorize!(*args)
      raise AccessDenied.new(*args) unless can?(*args)
    end

    private

    DEFAULT_BLOCK = ->(user, *_rest) { !!user }

    def can(abilities, subject = nil, allow_guest: false, &block)
      block ||= DEFAULT_BLOCK

      Array(abilities).each do |action|
        method_name = Helper.method_name(action, subject)

        raise %(Method "#{method_name}" already exists) if method_defined?(method_name)

        define_method method_name do |*args|
          (args[0] || allow_guest) && !!block.call(*args)
        end
      end
    end

    def delegate_ability(ability, subject, to:, to_ability: ability)
      can(ability, subject) do |user, record|
        can?(user, to_ability, record.public_send(to))
      end
    end
  end
end