OO

Simple Activity Based Authorization provider for Rails projects using mongoid.

Installation

  1. Add to your Gemfile

    gem 'oo'
    
  2. Execute

    $ bundle
    
  3. Run

    $ rails g oo:install
    

Concept

The gem is based on following concept:

  • licenses are permissions for activities,
  • license key is n-deep, separated with dot, e.g. admins.edit.iban,
  • license key allows using * for "all permissions in this scope", e.g:
    • admins.* means that user can perform every activity that needs permission admins.[something], so having such a permission user can perform admins.edit, can perform admins.delete but cannot admins.edit.iban,
    • admins.*.* means that user can perform every activity that needs permission admins.[something].[something_else], so having such a permission user can admins.edit, can admins.delete, can admins.edit.iban but cannot e.g. admins.edit.iban.set_nil
    • etc.
  • license keys without * shall be understood literally: admins does not give access to admins.edit even though it's parent

Configuration and Usage

LicenseUser Module

Add OO::LicenseUser to your user model.

class User
  include OO::LicenseUser

  # ...
end

Ready?

If so, user class has been just extended with:

  • field license_keys (of type array),
  • method licensed?.

You can now assign permissions for user and use licensed? method to check them, like in the example below.

user = User.first
user.licensed?(to: 'admins_users.edit')

# true if user has permission 'admins_users.edit'
# or any wider permission:
# - `admins_users.*.*.*`, `admins_users.*.*`, `admins_users.*`
# - `*.*.*.*`, `*.*.*`, `*.*`
# otherwise: false

LicenseCheckers Module

Add OO::LicenseCheckers to your controller.

class ApplicationController < ActionController::Base
  include OO::LicenseCheckers

  # ...
end

Done?

Therefore, your controller can be sent:

  • method licensed?,
  • method check_license!.

Please find attached examples.

module Admins
  class UsersController < ApplicationController
    include OO::LicenseCheckers


    def edit
      check_license!(user: current_user, to: 'admins_users.edit')
      # this will check whether user can perform 'admins_users.edit' or not
      # if he can't then license_missing_reaction will be raised
      # license_missing_reaction can be customized in initializer

      # ...
    end

    # ...
  end
end

Too verbose?

module Admins
  class UsersController < ApplicationController
    include OO::LicenseCheckers

    def edit
      check_license!
      # this is equal to previous for by default:
      # - current_user method is used to inject user
      # - '[parameterized controller path].[action name]' is used to inject key
      # this call requires your controller to respond to #current_user
      # both defaults :user and :to can be customized in initializer

      # ...
    end

    # ...
  end
end

Configuration

Default configuration was set up in initializer. Please find its description.

OO.configure do |c|
  # this is about how many nodes (dot-splitted) can have a license key
  c.license_max_depth = 4

  # here you can change method for default user injected to license checkers
  c.license_checkers_default_user = ->(base) { base.current_user }

  # here you can change default permission (:to) injected to license checkers
  c.license_checkers_default_key = lambda do |base|
    base.controller_path.gsub('/', '_') +
      OO::License.separator +
      base.action_name
  end

  # here you can change default error raised when #check_license! fails
  c.license_missing_reaction = lambda do |license_key, user|
    raise OO::Errors::LicenseMissing, license_key: license_key,
                                      user_data: user.id
  end

  # here you can set default license keys that user will be initialized with
  c.default_license_keys = []
end

Contributing

Bug reports and pull requests are welcome.

License

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