UnixLikePermissions
The UnixLikePermissions
gem provides a Ruby implementation for managing a Unix-like permissions system. It allows you to manipulate permission flags (such as read, create, update, destroy) using binary operations, offering an ActiveRecord type for easy integration with Rails applications.
Installation
Add this line to your application's Gemfile:
gem 'unix_like_permissions'
And then execute:
bundle install
Or install it yourself with:
gem install unix_like_permissions
The UnixLikePermissions
gem utilizes binary operations to manage permissions efficiently. Each permission is associated with a bit within an integer, and the permission set is represented as a binary number. Here's how it works:
- Each permission is assigned a binary value (
read
is1
,create
is10
,update
is100
,destroy
is1000
in binary). - Setting a permission turns the corresponding bit to
1
(true), while unsetting it turns the bit to0
(false). - Binary
OR
(|
) operations are used to enable permissions. - Binary
AND
(&
) operations combined withNOT
(~
) are used to disable permissions. - Binary
AND
(&
) operations are used to check if a permission is enabled.
These operations allow the gem to manage permissions in a performant and memory-efficient way, mirroring the time-tested Unix permission system.
- Efficiency: Managing permissions as bits within a single integer is computationally efficient and fast.
- Flexibility: Easily define your own set of permissions according to the needs of your application.
- Intuitiveness: The API is designed to be simple and easy to use, even for developers not familiar with bitwise operations.
- ActiveRecord Integration: Comes with built-in support for ActiveRecord, making it easy to store permissions in a database.
- Object-Oriented: Provides a clear object-oriented interface for permission operations.
Usage
After installing the gem, you can use it to define a set of permissions and interact with them in an object-oriented manner. Defining Permissions
Permissions are represented as a series of bits, with each bit corresponding to a particular permission. You can define and load a custom permissions map or use the default one. Using Default Permissions
UnixLikePermissions::PermissionSeries object consumes Integer value of a permission code. To create a new PermissionSeries object, you can pass an Integer value to the constructor:
permission_series = UnixLikePermissions::PermissionSeries.new(0)
0 stands for no permissions set. You can also pass a string to the constructor 0 and then set permissions using the set method:
permission_series = UnixLikePermissions::PermissionSeries.new('0')
permission_series.set(update: true)
permission_series.set(destroy: true)
permission_series.to_i # => 6
permission_series.to_h # => {:update=>true, :destroy=>true, :read=>false, :create=>false}
permission_series.update? # => true
permission_series.read # => false
The gem comes with a default set of permissions:
read
create
update
destroy
You can use these permissions as follows:
permission_series = UnixLikePermissions::PermissionSeries.new(0)
permission_series.set(update: true)
permission_series.set(destroy: true)
Loading a Custom Permissions Map
You can define your own permissions map and load it using the UnixLikePermissions.load_permissions_map! method:
custom_permissions = [
:show,
:impersonate,
:delete,
:report
]
UnixLikePermissions.load_permissions_map!(custom_permissions)
Checking Permissions
You can check if a particular permission is set by calling the query methods:
permission_series.delete? # => true or false
permission_series.impersonate? # => true or false
Serialization for ActiveRecord
The gem provides a custom type for ActiveRecord, so you can use it directly in your models:
# db/migrate/*
class AddPermissionsToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :permissions, :integer, default: 0
end
end
# app/models/user.rb
class User < ApplicationRecord
attribute :permissions, UnixLikePermissions::Types::PermissionSeries.new
end
# config/initializers/unix_like_permissions.rb
require 'unix_like_permissions'
require 'unix_like_permissions/types/permission_series'
ActiveRecord::Type.register(:permission_series_type, UnixLikePermissions::Types::PermissionSeries)
API
With default permissions map goes the following API:
Checking Permissions
read?: Returns true if the read permission is set.
create?: Returns true if the create permission is set.
update?: Returns true if the update permission is set.
destroy?: Returns true if the destroy permission is set.
permissions.update?
Permission Value
#to_i
: Returns the integer value of the permissions.
permissions.to_i # => 4
Serialization
#to_h(type = :bool)
: Returns a hash with permission names as keys and boolean values indicating whether each permission is set.
permissions.to_h # => { read: false, create: false, update: true, destroy: false }
permissions.to_h(:int) # => { read: 0, create: 0, update: 1, destroy: 0 }
permissions.to_h(:str) # => { read: '0', create: '0', update: '1', destroy: '0' }
#to_s
: Returns a string representation of the set permissions.
permissions.to_s # => "update"
#to_a(type = :str)
: Returns an array representation of the permissions. The type parameter can be :str, :int, or :bool.
permissions.to_a(:bool) # => [false, false, true, false]
permissions.to_a(:int) # => [0, 0, 1, 0]
permissions.to_a(:str) # => ['0', '0', '1', '0]
Miscellaneous
#set_all(value)
: Sets all permissions to the boolean value provided (true or false).
permissions.set_all(true)
permissions.to_s # => "read create update destroy"
set({ permission: value, ... })
: Sets the specified permission to the boolean value provided (true or false).
permissions.set(read: true, create: false)
permissions.to_s # => "read"
Contributing
Bug reports and pull requests are welcome on GitHub. 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.