Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extend ability DSL for parents inheriting children's permissions
This allows us to easily define abilities which parents can inherit from their children. I.e. if the child is allowed to do it, the parent is also allowed to do it. Refs hitobito/hitobito#1967
- Loading branch information
1 parent
bca91f8
commit a41015e
Showing
6 changed files
with
129 additions
and
12 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# frozen_string_literal: true | ||
|
||
# Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of | ||
# hitobito_youth and licensed under the Affero General Public License version 3 | ||
# or later. See the COPYING file at the top-level directory or at | ||
# https ://github.com/hitobito/hitobito_youth. | ||
|
||
# Adds to the core the option to specify ability conditions like this: | ||
# on(Event) do | ||
# for_self_or_manageds do | ||
# permission(:foo).may(:bar).some_condition | ||
# end | ||
# end | ||
# The condition will then grant permission when either the logged in user or one | ||
# of their manageds is granted permission. I.e. the logged in user inherits the | ||
# permissions of his manageds. | ||
# Technically, this is implemented by normally generating the "can :foo, :bar" | ||
# statements from the stored ability configs, and then for each of the manageds | ||
# generating additional "can :foo, :bar" statements (but only the ones which | ||
# originate inside a for_self_or_manageds block in the ability DSL). | ||
module Youth::Ability | ||
|
||
private | ||
|
||
def define_user_abilities(current_store, current_user_context) | ||
super | ||
|
||
user.manageds.each do |managed| | ||
managed_user_context = AbilityDsl::UserContext.new(managed) | ||
managed_store = current_store.only_manager_inheritable | ||
|
||
super(managed_store, managed_user_context) | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# frozen_string_literal: true | ||
|
||
# Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of | ||
# hitobito_youth and licensed under the Affero General Public License version 3 | ||
# or later. See the COPYING file at the top-level directory or at | ||
# https ://github.com/hitobito/hitobito_youth. | ||
|
||
# Extends the ability configs from core with the possibility | ||
# to add options. | ||
module Youth::AbilityDsl::Config | ||
|
||
attr_reader :options | ||
|
||
def initialize(permission, subject_class, action, ability_class, constraint, options = {}) | ||
super(permission, subject_class, action, ability_class, constraint) | ||
@options = options | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# frozen_string_literal: true | ||
|
||
# Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of | ||
# hitobito_youth and licensed under the Affero General Public License version 3 | ||
# or later. See the COPYING file at the top-level directory or at | ||
# https ://github.com/hitobito/hitobito_youth. | ||
|
||
# Extends the ability DSL with the for_self_or_manageds syntax. | ||
# All ability conditions in such a block are granted if either the current user | ||
# or one of their manageds (children) individually is granted the ability. | ||
# In other words, if the abilities defined in a for_self_or_manageds block are granted | ||
# to my child, I automatically get the same abilities. | ||
module Youth::AbilityDsl::Recorder | ||
|
||
def for_self_or_manageds | ||
return unless block_given? | ||
|
||
AbilityDsl::Recorder::Base.include_manageds = true | ||
yield | ||
AbilityDsl::Recorder::Base.include_manageds = false | ||
end | ||
|
||
# I found no way to add a class_attribute using the .prepend mechanism. | ||
# Therefore, this module is .include'd instead of .prepend'd into its core counterpart. | ||
module Base | ||
extend ActiveSupport::Concern | ||
|
||
included do | ||
class_attribute :include_manageds | ||
self.include_manageds = false | ||
|
||
def add_config(permission, action, constraint) | ||
@store.add(AbilityDsl::Config.new(permission, | ||
@subject_class, | ||
action, | ||
@ability_class, | ||
constraint, | ||
{ include_manageds: self.include_manageds })) | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
# Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of | ||
# hitobito_youth and licensed under the Affero General Public License version 3 | ||
# or later. See the COPYING file at the top-level directory or at | ||
# https ://github.com/hitobito/hitobito_youth. | ||
|
||
# Extends the ability store from the core with the possibility to filter the | ||
# stored ability configs and keep only the ones which a manager can inherit from their | ||
# manageds (children). | ||
module Youth::AbilityDsl::Store | ||
|
||
def only_manager_inheritable | ||
filtered_configs = configs.select { |_, config| config.options[:include_manageds] } | ||
AbilityDsl::Store.new.tap do |clone| | ||
clone.instance_variable_set(:@ability_classes, ability_classes) | ||
clone.instance_variable_set(:@configs, filtered_configs) | ||
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