Lamassu

Gem Version Build Status Coverage Join the chat at https://gitter.im/lamassu-rb/Lobby

Lamassu is an functional authorization framework for Ruby, based on callable policy objects and policy containers

Installation

Add this line to your application's Gemfile:

gem 'lamassu'

And then execute:

$ bundle

Or install it yourself as:

$ gem install lamassu

Usage

To use Lamassu, you need an Guardian for your project:

MyGuardian = Lamassu::Guardian.new

You can then register policies for various Modules with the guardian, and if authorized:

include Dry::Monads::Result::Mixin

Article = Struct.new(:title, :owner, :published)

MyGuardian.policies.for Article do
  policy :read, proc do |user, article|
    if article.published || user == article.owner
      Success(:allowed)
    else
      Failure(:no_access)
    end
  end
end

article = Article.new('My Article', :bob, true)
MyGuardian.authorize(:bob, article, :read)
# => Success(:allowed)

A policy can be any callable object returning a dry-monads Result object, or an object responding to to_result.

When building an application with many policies, it's recommended to create proper policy objects by including Lamassu::Policy:

# app/policies/article/read_policy.rb

class ReadPolicy
  include Lamassu::Policy

  def call(user, article)
    if article.published || user == article.owner
      Success(:allowed)
    else
      Failure(:disallowed)
    end
  end
end

MyGuardian.policies.for Article do
  policy :read, ReadPolicy.new
end

Subsets

Since the result is wrapped in a Result, the policy object can also be used to return a subset or selection of data:

class ReadPolicy
  include Lamassu::Policy

  def call(user, _)
    articles = ArticleRepository.select do |article|
      article.owner == user || article.published
    end

    if articles.empty?
      Failure(nil)
    else
      Success(articles)
    end
  end
end

result = guardian.authorize(:bob, article, :read)
# => Success([#<Article>, ...])

result.value! if result.success?
# => [#<Article>, ...]

Example usages for this include to return only the articles a user have authorization to view, or transform an object to remove any fields the user is authorized to read.

Policy adapters

Lamassu comes with several "policy adapters" for convenience when creating policies:

MyGuardian.policies.for Article do
  check :write, (proc { true })
  map :published, (proc { ArticleRepository.select(&:published) })
end

Both adapters wraps a callable object, and returns a valid policy object. The check adapter is used with an callable object that returns a truish or falsish value, and wraps the result in Success or Failure respectively. The map adapter wraps a callable object, and wraps any output in a Success.

These adapters are meant for simple applications or to ease porting existing ones. It's recommended to create proper policy objects when possible, as you have better control over the return value.

Web frameworks

Lamassu don't currently include any integrations with any web frameworks. It's meant to be flexible and usable with any framework, but the details will depend on the chosen framework.

To simplify calling lamassu, it could be useful to create a helper to include in your controllers:

module AuthorizationHelper
  # Convenience method for checking authorization where the user object is
  # available through `current_user`, and the scope is the current controller.
  def authorize(policy)
    MyGuardian.authorize(current_user, self, policy)
  end
end

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install.

Contributing

Bug reports and pull requests are welcome on GitHub at https://gitlab.com/huyderman/lamassu/issues. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Lamassu project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

Acknowledgments

  • dry-rb collection of gems which have both a great inspiration, and without this library would not be possible
  • Pundit which is an great authorization library and have been an influence of some of the design of Lamassu
  • Alex Daily (@[email protected] or @[email protected]) who created the awesome logo for Lamassu.