fix permission inheritance
fixes CNVS-14451 test plan: * create a role in a root account * grant a permission to that role, and add an admin to that role * in a sub-account, revoke that permission from that role * ensure that the admin still has the permission in both the root account and a sub account (the sub account can't revoke permissions that admins got from further up the chain) * add an admin in that role to the sub account * ensure this new admin does not have the permission * and, sadly, permissions regression, cause we're messing with low level permissions stuff again Change-Id: I7ccc32f36e4476d5df77eaec765abcb1c7b89b3e Reviewed-on: https://gerrit.instructure.com/38604 Reviewed-by: Nick Cloward <ncloward@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com>
This commit is contained in:
parent
abea42ae86
commit
948a57a183
|
@ -866,32 +866,44 @@ class RoleOverride < ActiveRecord::Base
|
|||
@@role_override_chain ||= {}
|
||||
overrides = @@role_override_chain[permissionless_key] ||= begin
|
||||
role_context.shard.activate do
|
||||
account_ids = context.account_chain_ids(include_site_admin: true)
|
||||
case_string = ""
|
||||
account_ids.each_with_index{|account_id, idx| case_string += " WHEN context_id='#{account_id}' THEN #{idx} " }
|
||||
overrides = RoleOverride.where(:context_id => account_ids, :enrollment_type => generated_permission[:enrollment_type].to_s).order("CASE #{case_string} ELSE 9999 END DESC")
|
||||
overrides.group_by(&:permission).freeze
|
||||
account_ids = context.account_chain_ids(include_site_admin: true).reverse
|
||||
overrides = RoleOverride.where(:context_id => account_ids, :enrollment_type => generated_permission[:enrollment_type].to_s).group_by(&:permission)
|
||||
# every context has to be represented so that we can't miss role_context below
|
||||
overrides.each_key do |permission|
|
||||
overrides_by_account = overrides[permission].index_by { |override| [override.context_id, override.context.class.base_class.name] }
|
||||
overrides[permission] = account_ids.map do |account_id|
|
||||
overrides_by_account[[account_id, 'Account']] || RoleOverride.new { |ro| ro.context_id = account_id; ro.context_type = 'Account' }
|
||||
end
|
||||
end
|
||||
overrides
|
||||
end
|
||||
end
|
||||
|
||||
# walk the overrides from most general (root account) to most specific (the role's account)
|
||||
# walk the overrides from most general (site admin, root account) to most specific (the role's account)
|
||||
# and apply them; short-circuit once someone has locked it
|
||||
last_override = false
|
||||
hit_role_context = false
|
||||
(overrides[permission.to_s] || []).each do |override|
|
||||
# set the flag that we have an override for the context we're on
|
||||
last_override = override.context_id == context.id && override.context_type == context.class.base_class.name
|
||||
|
||||
generated_permission[:context_id] = override.context_id
|
||||
generated_permission[:context_id] = override.context_id unless override.new_record?
|
||||
generated_permission[:locked] = override.locked?
|
||||
# keep track of the value for the parent
|
||||
generated_permission[:prior_default] = generated_permission[:enabled]
|
||||
|
||||
unless override.enabled.nil?
|
||||
generated_permission[:explicit] = true if last_override
|
||||
generated_permission[:enabled] = override.enabled? ? override.applies_to : nil
|
||||
if hit_role_context
|
||||
generated_permission[:enabled] ||= override.enabled? ? override.applies_to : nil
|
||||
else
|
||||
generated_permission[:enabled] = override.enabled? ? override.applies_to : nil
|
||||
end
|
||||
end
|
||||
hit_role_context ||= override.context_id == role_context.id && override.context_type == role_context.class.base_class.name
|
||||
|
||||
break if override.locked?
|
||||
break if generated_permission[:enabled] && hit_role_context
|
||||
end
|
||||
|
||||
# there was not an override matching this context, so do a half loop
|
||||
|
|
|
@ -349,6 +349,7 @@ describe RoleOverride do
|
|||
it "should use permission for role in parent account" do
|
||||
@parent_account = @account
|
||||
@sub = account_model(:parent_account => @account)
|
||||
@course = @sub.courses.create!
|
||||
@account = @parent_account
|
||||
|
||||
# create in parent
|
||||
|
@ -363,13 +364,14 @@ describe RoleOverride do
|
|||
create_override(@role_name, !@default_perm)
|
||||
|
||||
# check based on sub account
|
||||
hash = RoleOverride.permission_for(@parent_account, @sub, @permission, @base_role.to_s, @role_name.to_s)
|
||||
hash = RoleOverride.permission_for(@course, @sub, @permission, @base_role.to_s, @role_name.to_s)
|
||||
(!!hash[:enabled]).should == !@default_perm
|
||||
end
|
||||
|
||||
it "should use permission for role in parent account even if sub account doesn't have role" do
|
||||
@parent_account = @account
|
||||
@sub = account_model(:parent_account => @account)
|
||||
@course = @sub.courses.create!
|
||||
@account = @parent_account
|
||||
|
||||
create_role(@base_role, @role_name)
|
||||
|
@ -378,13 +380,14 @@ describe RoleOverride do
|
|||
create_override(@role_name, !@default_perm)
|
||||
|
||||
# check based on sub account
|
||||
hash = RoleOverride.permission_for(@parent_account, @sub, @permission, @base_role.to_s, @role_name.to_s)
|
||||
hash = RoleOverride.permission_for(@course, @sub, @permission, @base_role.to_s, @role_name.to_s)
|
||||
(!!hash[:enabled]).should == !@default_perm
|
||||
end
|
||||
|
||||
it "should use permission for role in sub account" do
|
||||
@parent_account = @account
|
||||
@sub = account_model(:parent_account => @account)
|
||||
@course = @sub.courses.create!
|
||||
|
||||
create_role(@base_role, @role_name)
|
||||
|
||||
|
@ -392,7 +395,7 @@ describe RoleOverride do
|
|||
create_override(@role_name, !@default_perm)
|
||||
|
||||
# check based on sub account
|
||||
hash = RoleOverride.permission_for(@parent_account, @sub, @permission, @base_role.to_s, @role_name.to_s)
|
||||
hash = RoleOverride.permission_for(@course, @sub, @permission, @base_role.to_s, @role_name.to_s)
|
||||
(!!hash[:enabled]).should == !@default_perm
|
||||
end
|
||||
end
|
||||
|
@ -435,6 +438,13 @@ describe RoleOverride do
|
|||
@permission = :become_user
|
||||
check_permission(AccountUser::BASE_ROLE_NAME, 'AccountAdmin', false)
|
||||
end
|
||||
|
||||
it "should not allow a sub-account to revoke a permission granted to a parent account" do
|
||||
@sub_account.role_overrides.create!(enrollment_type: 'AccountAdmin', enabled: false, permission: :manage_admin_users)
|
||||
@sub_account.grants_right?(@site_admin, :manage_admin_users).should be_true
|
||||
@sub_account.grants_right?(@root_admin, :manage_admin_users).should be_true
|
||||
@sub_account.grants_right?(@sub_admin, :manage_admin_users).should be_false
|
||||
end
|
||||
end
|
||||
|
||||
context "sharding" do
|
||||
|
|
Loading…
Reference in New Issue