-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce ability to add roles to groups. Group members inherit the permissions attached to the group's roles. Notable changes: - Several new Roles for Work, Collection, and User management - Role permission integration with Hyrax permission logic (Sipity, access controls, CanCan, etc.) - Hyku::Group replaced with already existing Hyrax::Group - Easily assign roles to individual users - Extended UI - Both pre-configured and customizable groups - Scripts to migrate existing Hyku applications - More This work is a joint contribution of PALNI and PALCI's Hyku for Consortia project.
- Loading branch information
1 parent
e2f508f
commit 1ba52f5
Showing
185 changed files
with
12,211 additions
and
218 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Groups with Roles | ||
|
||
## Table of Contents | ||
* [Creating Default Roles and Groups](#creating-default-roles-and-groups) | ||
* [Setup an Existing Application to use Groups with Roles](#setup-an-existing-application-to-use-groups-with-roles) | ||
* [Role Set Creation Guidelines](#role-set-creation-guidelines) | ||
* [Other Information](#other-information) | ||
* [Search Permissions Notes](#search-permissions-notes) | ||
|
||
--- | ||
|
||
## Creating Default Roles and Groups | ||
|
||
Default `Roles` and `Hyrax::Groups` are seeded into an account (tenant) at creation time (see [CreateAccount#create_defaults](app/services/create_account.rb)). | ||
|
||
To manually seed default `Roles` and `Hyrax::Groups` _across all tenants_, run this rake task: | ||
|
||
```bash | ||
rake hyku:roles:create_default_roles_and_groups | ||
``` | ||
|
||
## Setup an Existing Application to use Groups with Roles | ||
|
||
These rake tasks will create data across all tenants necessary to setup Groups with Roles. **Run them in the order listed below.** | ||
|
||
Prerequisites: | ||
- All Collections must have CollectionTypes _and_ PermissionTemplates (see the **Collection Migration** section in the [Hyrax 2.1 Release Notes](https://github.com/samvera/hyrax/releases?after=v2.2.0)) | ||
|
||
```bash | ||
rake hyku:roles:create_default_roles_and_groups | ||
rake hyku:roles:create_collection_accesses | ||
rake hyku:roles:create_admin_set_accesses | ||
rake hyku:roles:create_collection_type_participants | ||
rake hyku:roles:grant_workflow_roles | ||
rake hyku:roles:destroy_registered_group_collection_type_participants # optional | ||
``` | ||
|
||
<sup>\*</sup> The `hyku:roles:destroy_registered_group_collection_type_participants` task is technically optional. However, without it, collection readers will be allowed to create Collections. | ||
|
||
## Role Set Creation Guidelines | ||
1. Add role names to the [RolesService::DEFAULT_ROLES](app/services/roles_service.rb) constant | ||
2. Find related ability concern in Hyrax (if applicable) | ||
- Look in `app/models/concerns/hyrax/ability/` (local repo first, then Hyrax's repo) | ||
- E.g. ability concern for Collections is `app/models/concerns/hyrax/ability/collection_ability.rb` | ||
- If a concern matching the record type exists in Hyrax, but no the local repo, copy the file into the local repo | ||
- Be sure to add override comments (use the `OVERRIDE:` prefix) | ||
- If no concern matching the record type exists, create one. | ||
- E.g. if creating an ablility concern for the `User` model, create `app/models/concerns/hyrax/ability/user_ability.rb` | ||
3. Create a method in the concern called `<record_type>_roles` (e.g. `collection_roles`) | ||
4. Add the method to the array of method names in [Ability#ability_logic](app/models/ability.rb`) | ||
5. Within the `<record_type>_roles` method in the ability concern, add [CanCanCan](https://github.com/CanCanCommunity/cancancan) rules for each role, following that role's specific criteria. | ||
- When adding/removing permissions, get as granular as possible. | ||
- Beware using `can :manage` -- in CanCanCan, `:manage` [refers to **any** permission](https://github.com/CanCanCommunity/cancancan/blob/develop/docs/Defining-Abilities.md#the-can-method), not just CRUD actions. | ||
- E.g. If you want a role to be able to _create_, _read_, _edit_, _update_, but not _destroy_ Users | ||
```ruby | ||
# Bad - could grant unwanted permissions | ||
can :manage, User | ||
cannot :destroy, User | ||
|
||
# Good | ||
can :create, User | ||
can :read, User | ||
can :edit, User | ||
can :update, User | ||
``` | ||
- CanCanCan rules are [hierarchical](https://github.com/CanCanCommunity/cancancan/blob/develop/docs/Ability-Precedence.md): | ||
```ruby | ||
# Will still grant read permission | ||
cannot :manage, User # remove all permissions related to users | ||
can :read, User | ||
``` | ||
6. Add new / change existing `#can?` ability checks in views and controllers where applicable | ||
|
||
### Other Information | ||
- For guidelines on overriding dependencies, see the [Overrides to Dependencies](README#overrides-to-dependencies) section of the README | ||
- Add [ability specs](spec/abilities) and [feature specs](spec/features) | ||
|
||
## Search Permissions Notes | ||
- Permissions are injected in the solr query's `fq` ("filter query") param ([link to code](https://github.com/projectblacklight/blacklight-access_controls/blob/master/lib/blacklight/access_controls/enforcement.rb#L56)) | ||
- Enforced (injected into solr query) in [Blacklight::AccessControls::Enforcement](https://github.com/projectblacklight/blacklight-access_controls/blob/master/lib/blacklight/access_controls/enforcement.rb) | ||
- Represented by an instance of `Blacklight::AccessControls::PermissionsQuery` (see [#permissions_doc](https://github.com/projectblacklight/blacklight-access_controls/blob/master/lib/blacklight/access_controls/permissions_query.rb#L7-L14)) | ||
- Admin users don't have permission filters injected when searching ([link to code](https://github.com/samvera/hyrax/blob/v2.9.0/app/search_builders/hyrax/search_filters.rb#L15-L20)) | ||
- `SearchBuilder` may be related to when permissions are and aren't enforced | ||
- Related discussions in Slack: | ||
- [first inheritance question](https://samvera.slack.com/archives/C0F9JQJDQ/p1614103477032200) | ||
- [second inheritance question](https://notch8.slack.com/archives/CD47U8QCQ/p1615935043012800) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# frozen_string_literal: true | ||
|
||
module Admin | ||
# OVERRIDE from AdminController inheretence for user roles authorization | ||
class GroupRolesController < ApplicationController | ||
before_action :load_group | ||
before_action :cannot_remove_admin_role_from_admin_group, only: [:remove] | ||
layout 'hyrax/dashboard' | ||
|
||
rescue_from ActiveRecord::RecordNotFound, with: :redirect_not_found | ||
|
||
def index | ||
# OVERRIDE: AUTHORIZE AN EDIT ROLE TO ACCESS THE ROLES INDEX | ||
authorize! :edit, Hyrax::Group | ||
add_breadcrumb t(:'hyrax.controls.home'), root_path | ||
add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path | ||
add_breadcrumb t(:'hyku.admin.groups.title.edit'), edit_admin_group_path(@group) | ||
add_breadcrumb t(:'hyku.admin.groups.title.roles'), request.path | ||
|
||
@roles = ::Role.site - @group.roles | ||
render template: 'admin/groups/roles' | ||
end | ||
|
||
def add | ||
role = ::Role.find(params[:role_id]) | ||
@group.roles << role unless @group.roles.include?(role) | ||
|
||
respond_to do |format| | ||
format.html do | ||
flash[:notice] = 'Role has successfully been added to Group' | ||
redirect_to admin_group_roles_path(@group) | ||
end | ||
end | ||
end | ||
|
||
def remove | ||
@group.group_roles.find_by!(role_id: params[:role_id]).destroy | ||
|
||
respond_to do |format| | ||
format.html do | ||
flash[:notice] = 'Role has successfully been removed from Group' | ||
redirect_to admin_group_roles_path(@group) | ||
end | ||
end | ||
end | ||
|
||
private | ||
|
||
def load_group | ||
@group = Hyrax::Group.find_by(id: params[:group_id]) | ||
end | ||
|
||
def redirect_not_found | ||
flash[:error] = 'Unable to find Group Role with that ID' | ||
redirect_to admin_group_roles_path(@group) | ||
end | ||
|
||
def cannot_remove_admin_role_from_admin_group | ||
role = Role.find_by(id: params[:role_id]) | ||
return unless @group.name == ::Ability.admin_group_name && role.name == 'admin' | ||
|
||
redirect_back(fallback_location: edit_admin_group_path(@group), flash: { error: "Admin role cannot be removed from this group" }) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
app/controllers/concerns/hyrax/admin/users_controller_behavior.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# OVERRIDE FILE from Hyrax v2.9.0 | ||
module Hyrax | ||
module Admin | ||
module UsersControllerBehavior | ||
extend ActiveSupport::Concern | ||
include Blacklight::SearchContext | ||
included do | ||
with_themed_layout 'dashboard' | ||
end | ||
|
||
# Display admin menu list of users | ||
def index | ||
# OVERRIDE: AUTHORIZE A READER ROLE TO ACCESS THE USERS INDEX | ||
authorize! :read, ::User | ||
add_breadcrumb t(:'hyrax.controls.home'), root_path | ||
add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path | ||
add_breadcrumb t(:'hyrax.admin.users.index.title'), hyrax.admin_users_path | ||
@presenter = Hyrax::Admin::UsersPresenter.new | ||
@invite_roles_options = if current_ability.admin? | ||
::RolesService::DEFAULT_ROLES | ||
else | ||
::RolesService::DEFAULT_ROLES - [::RolesService::ADMIN_ROLE] | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
app/controllers/hyrax/admin/collection_type_participants_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# OVERRIDE FILE from Hryax v2.9.0 | ||
require_dependency Hyrax::Engine.root.join('app', 'controllers', 'hyrax', 'admin', 'collection_type_participants_controller').to_s | ||
|
||
Hyrax::Admin::CollectionTypeParticipantsController.class_eval do | ||
before_action :admin_group_participant_cannot_be_destroyed, only: :destroy | ||
|
||
# OVERRIDE: add backend validation to stop admin group access from being destroyed | ||
def admin_group_participant_cannot_be_destroyed | ||
@collection_type_participant = Hyrax::CollectionTypeParticipant.find(params[:id]) | ||
if @collection_type_participant.admin_group? && @collection_type_participant.access == Hyrax::CollectionTypeParticipant::MANAGE_ACCESS | ||
redirect_to( | ||
edit_admin_collection_type_path(@collection_type_participant.hyrax_collection_type_id, anchor: 'participants'), | ||
alert: 'Admin group access cannot be removed' | ||
) | ||
end | ||
end | ||
private :admin_group_participant_cannot_be_destroyed | ||
end |
18 changes: 18 additions & 0 deletions
18
app/controllers/hyrax/admin/permission_template_accesses_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# OVERRIDE FILE from Hryax v2.9.0 | ||
require_dependency Hyrax::Engine.root.join('app', 'controllers', 'hyrax', 'admin', 'permission_template_accesses_controller').to_s | ||
|
||
Hyrax::Admin::PermissionTemplateAccessesController.class_eval do | ||
# OVERRIDE: Only prevent delete if it is for the admin group's MANAGE access | ||
# | ||
# This is a controller validation rather than a model validation | ||
# because we don't want to prevent the ability to remove the whole | ||
# PermissionTemplate and all of its associated PermissionTemplateAccesses | ||
# @return [Boolean] true if it's valid | ||
def valid_delete? | ||
# OVERRIDE: add MANAGE access condition | ||
return true unless @permission_template_access.admin_group? && @permission_template_access.access == Hyrax::PermissionTemplateAccess::MANAGE | ||
|
||
@permission_template_access.errors[:base] << t('hyrax.admin.admin_sets.form.permission_destroy_errors.admin_group') | ||
false | ||
end | ||
end |
Oops, something went wrong.