Skip to content

hopsoft/perm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

About

Simple authorization/permission management in Ruby

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages