Rokku
Rokku (ロック - lock) offers authorization for Hanami web applications.
Authorization was setup as inspired by this blog post. It supports the generation of policy files for each controller where authorized roles are specified for each action.
Note: For Hanami 1.3 support, see the 0.7.0 branch or install Rokku 0.7.0.
1. Installation
Add this line to your application's Gemfile:
gem 'rokku'And then execute:
$ bundle
Or install it yourself as:
$ gem install rokku
Rokku 2.0 needs to be included in the action:
# auto_register: false
# frozen_string_literal: true
require "hanami/action"
require "dry/monads"
require "rokku"
module MyApplication
class Action < Hanami::Action
# Provide `Success` and `Failure` for pattern matching on operation results
include Dry::Monads[:result]
include Hanami::Rokku
handle_exception "ROM::TupleCountMismatchError" => :handle_not_found
private
def handle_not_found(request, response, exception)
response.status = 404
response.format = :html
response.body = "Not found"
end
end
end2. Usage
2.1 Role based authorization
2.1.1 Prerequisites
Prior to authorizing the user, retrieve the entity from the database and assign it to a variable user so it can be passed to the authorized? method. Rokku supports roles both as a type of Array and String.
For example, the user.roles could either be a simple string like 'admin' or an array of roles like ['level_1', 'level_2', 'level_3'].
2.2 Policy creation
Rokku supports policy creation for either the main application or for a specific slice. Application policies are created in the app/policies folder, while the slice policies are created in the slices/'slice name'/policies. See the two command examples below.
rokku -p tasks -a myapp #=> app/policies/tasks_policy.rbrokku -p tasks -s admin #=> app/slices/admin/policies/tasks_policy.rbThe command must be run in the project root folder.
Flags:
- -p, --policy => policy
- -s, --slice => slice
- -a, --app => application
2.2.1 Naming requirements
For multi part names snake case must be used.
rokku -p admin_tasks -s admin_tickets #=> app/slices/admin_tickets/policies/admin_tasks_policy.rb2.3 Verifying authorization
Once the file is generated, the authorized roles variables in the initialize block for required actions need to be uncommented and supplied with specific roles.
For example:
# @authorized_roles_for_show = []
# @authorized_roles_for_index = []
# @authorized_roles_for_edit = []
@authorized_roles_for_update = ['admin']Then we can check if a user is authorized for the AdminTickets slice, AdminTasks resources and the Updateaction.
authorized?(user)The authorized? method checks if the specified user has the required role and permission to access the action. It returns true or false and provides the basis for further actions in either case.
Rokku supports 2 modes of arguments specification: automatic and manual. Automatic fits most cases, since the app or slice name, resource name and action are automatically extracted.
With manual it's possible to do cross-namespace authorization checks and multiple permission checks. For example it's possible to check for authorization for EndGames in
an action for ChessOpenings.
-
Automatic
authorized?(current_user) -
Manual
authorized?(current_user, namespace: "ChessBase", resource: "ChessOpenings", action: "destroy")
The namespace argument can either be the main application name or s slice name.
2.2.1 Naming requirements
For multi part names PascalCase must be used as shown in the above example for Manual.
2.4 Authorization verification in a share code module
It is possible to enable session handling in a share code module as provided by Hanami. To do this, create an authentication module in app/actions/authentication.rb. The example below shows also how to custom values to replace default values in actions.
module ChessBase
module Actions
module Authorization
def self.included(action_class)
action_class.class_eval do
include Deps["repos.user_repo"]
before :check_authorization
end
end
private
def check_authorization(request, response)
user_id = request.session[:current_user]
user = user_repo.find_by_id(user_id) if user_id
if authorized?(user) == false
response.flash[:failed_notice] = "You tried to visit an URL you are not authorized for."
response.redirect_to '/'
end
end
end
end
endWe can then simply include the Authorization module in actions, where required.
However, if we include this in the base action class, it will be available in all actions and there is no need for separate includes in actions:
#
#
module MyApplication
class Action < Hanami::Action
# Provide `Success` and `Failure` for pattern matching on operation results
include Dry::Monads[:result]
include Hanami::Rokku
include Xpresstube::Actions::Authorization
handle_exception "ROM::TupleCountMismatchError" => :handle_not_found
private
#
#Disabling the authorization shared module in specific actions
Sometimes we might not want to check for authorized user. For example,
doing so in the login action will cause an infinite loop. There we can
disable the module by overwriting the desired methods in the action:
private
def check_authorization; endChangelog
2.0.0
Breaking Changes:
- Supports Hanami ~> 2.0 applications only.
- Application policies are now created in
app/policies. - Slice policies are now created in
slices/my_slice/policies. - Rokku must be explicitly included in the base action:
include Hanami::Rokku. - Rokku 2.0.0 doesn't rely on instance variable like
@useranymore. Instead, auservariable must be passed as an argument to a method.
For Hanami 1.3 support, use Rokku 0.7.0.
0.7.0
- Policies are now scoped under application module so it is possible to have two
Dashboardpolicies for two different applications. - Readme update.
0.6.0
- Change to accept a string or an array as roles.
- Refactored tests.
- Added
commands.rbtobin/rokku. - Small style changes.
0.5.1
- Readme update
- Refactored tests
0.5.0
- Move from Tachiban
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake test 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. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/sebastjan-hribar/rokku. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant 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 Rokku project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.