Skip to content

Integration with rolify

Recipe contributed by Paul after discussing it here.

It is possible to implement the rolify gem in conjunction with pundit in an Avo using basic functionality. Following the next steps allows for easy management of roles within the admin panel, which can be used to control access to different parts of the application based on user roles. By assigning specific permissions to each user role, Avo users can ensure that their admin panels remain secure and accessible only to authorised users.

WARNING

You must manually require rolify in your Gemfile.

ruby
gem "rolify"

If this is a new app you need to do some initial steps, create the role model and specify which models should be handled by rolify

INFO

Check out the rolify documentation for reference.

We assume that your model for managing users is called Account (default when using rodauth) and your role model is called Role (default when using rolify).

ruby
class Account < ApplicationRecord
  rolify

  # ...
end

A Role connects to an Account through has_and_belongs_to_many while an Account connects to Role through has_many (not directly used in the model because the rolify statement manage this). Although rolify has its own functions for adding and deleting roles, normal rails operations can also be used to manage the roles. To implement this in avo, the appropriate resources need to be created.

Perhaps the creation of the account resource is not necessary, as it has already been done in previous steps or has been created automatically by the avo generator through a scaffold/model. So we assume this step is already done.

zsh
bin/rails generate avo:resource role

After this step the roles should now accessible via the avo interface. The final modification should be done in the corresponding Account resource file.

ruby
class AccountResource < Avo::BaseResource
  # ...

  field :assigned_roles, as: :tags, hide_on: :forms do |model, resource, view|
    model.roles.map {|role|role.name}
  end
   
  # Only show roles that have not already been assigned to the object, because Avo does not use the add_role method, so it is possible to assign a role twice
  field :roles, as: :has_many, attach_scope: -> { query.where.not(id: parent.roles.pluck(:id)) }

  # ...
end

Example of RoleResource file:

ruby
class RoleResource < Avo::BaseResource
  self.title = :name
  self.includes = []

  field :name, as: :text
  field :accounts, as: :has_and_belongs_to_many
end

The roles of an account can now be easily assigned and removed using avo. The currently assigned roles are displayed in the index and show view using the virtual `assigned_roles' field.