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.