Project

perm

0.0
No commit activity in last 3 years
No release in over 3 years
Simple permission management
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

 Project Readme

Lines of Code Maintainability Build Status Coverage Status Downloads

Perm

Incredibly simple permission management i.e. authorization.

Quickstart

gem install perm

Setup

Let's create a simple example with users & posts.

class User
  attr_reader :roles, :posts

  def initialize(roles: [])
    @roles = roles
    @posts = []
  end
end
class Post
  attr_reader :user, :title
  attr_accessor :published

  def initialize(user:, title:)
    @user = user
    @title = title
    @user.posts << self
  end
end

Once our basic classes have be defined, we can create an authorized user to manage permissions.

class AuthorizedUser < Perm::Authorized
  def can_read?(post)
    return true if user.roles.include?(:admin)
    return true if user.roles.include?(:editor)
    return true if user == post.user
    post.published
  end

  def can_update?(post)
    return true if user.roles.include?(:admin)
    return true if user.roles.include?(:editor)
    user == post.user
  end

  def can_delete?(post)
    return true if user.roles.include?(:admin)
    user == post.user
  end
end

Authorized users do the following.

  • wrap user objects — somewhat like the presenter pattern
  • add behavior to wrapped users
  • respond to authorization methods defined as can_OPERATION?
  • secure by default i.e. authorization checks return false until implemented

Usage

Create some users

mary = User.new(roles: [:admin])
john = User.new(roles: [:editor, :writer])
beth = User.new(roles: [:writer])
drew = User.new

Create a post

post = Post.new(user: beth, title: "Authorization made easy")

Wrap each user with an authorizer

authorized_mary = AuthorizedUser.new(mary)
authorized_john = AuthorizedUser.new(john)
authorized_beth = AuthorizedUser.new(beth)
authorized_drew = AuthorizedUser.new(drew)

# wrapped users continue to act like users
authorized_beth.posts # => [#<Post:0x007fe35d081798 @title="Authorization made easy"...

# if conflicts arise, simply access the original
authorized_beth.user

Check permissions

authorized_mary.can_read?(post) # => true
authorized_mary.can_update?(post) # => true
authorized_mary.can_delete?(post) # => true

authorized_john.can_read?(post) # => true
authorized_john.can_update?(post) # => true
authorized_john.can_delete?(post) # => false

authorized_beth.can_read?(post) # => true
authorized_beth.can_update?(post) # => true
authorized_beth.can_delete?(post) # => true

authorized_drew.can_read?(post) # => false
authorized_drew.can_update?(post) # => false
authorized_drew.can_delete?(post) # => false

post.published = true
authorized_drew.can_read?(post) # => true

# we can also check unimplemented permissions
authorized_mary.can_create?(post) # => false
authorized_john.can_view?(post) # => false