permissions_update.rb 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class KnowledgeBase
  3. class PermissionsUpdate
  4. def initialize(object, user = nil)
  5. @object = object
  6. @user = user
  7. end
  8. def update!(**roles_to_permissions)
  9. ActiveRecord::Base.transaction do
  10. ensure_unoverrideable_permissions!(roles_to_permissions)
  11. update_object(roles_to_permissions)
  12. next if !@object.changed_for_autosave?
  13. @object.save!
  14. update_all_children
  15. ensure_editable!
  16. end
  17. end
  18. def update_using_params!(params)
  19. roles_to_permissions = params[:permissions].transform_keys { |key| Role.find key }
  20. update!(**roles_to_permissions)
  21. end
  22. private
  23. def update_object(roles_to_permissions)
  24. @object.permissions.reject { |elem| roles_to_permissions.key? elem.role }.each(&:mark_for_destruction)
  25. roles_to_permissions.each do |role, access|
  26. update_object_permission(role, access)
  27. end
  28. end
  29. def update_object_permission(role, access)
  30. permission = @object.permissions.detect { |elem| elem.role == role } || @object.permissions.build(role: role)
  31. permission.access = access
  32. mark_permission_for_cleanup_if_needed(permission, parent_object_permissions)
  33. end
  34. def parent_object_permissions
  35. @parent_object_permissions ||= begin
  36. if @object.is_a? KnowledgeBase::Category
  37. (@object.parent || @object.knowledge_base).permissions_effective || []
  38. else
  39. []
  40. end
  41. end
  42. end
  43. def all_children
  44. case @object
  45. when KnowledgeBase::Category
  46. @object.self_with_children - [@object]
  47. when KnowledgeBase
  48. @object.categories.root.map(&:self_with_children).flatten
  49. end
  50. end
  51. def update_single_child(child)
  52. inherited_permissions = (child.parent || child.knowledge_base).permissions_effective
  53. child.permissions.each do |child_permission|
  54. mark_permission_for_cleanup_if_needed(child_permission, inherited_permissions)
  55. end
  56. child.changed_for_autosave? ? child.save! : child.touch # rubocop:disable Rails/SkipsModelValidations
  57. end
  58. def update_all_children
  59. all_children.each do |child|
  60. update_single_child(child)
  61. end
  62. end
  63. def ensure_editable!
  64. return if !@user
  65. return if KnowledgeBase::EffectivePermission.new(@user, @object).access_effective == 'editor'
  66. raise Exceptions::UnprocessableEntity, __('Invalid permissions, do not lock yourself out.')
  67. end
  68. def mark_permission_for_cleanup_if_needed(permission, parents)
  69. matching = parents.find { |elem| elem.role == permission.role }
  70. return if !matching
  71. return if matching.access == 'reader' && permission.access != 'reader'
  72. permission.mark_for_destruction
  73. end
  74. def ensure_unoverrideable_permissions!(new_roles_permissions)
  75. new_roles_permissions.each do |role, new_permission|
  76. ensure_single_unoverrideable_permission!(role, new_permission)
  77. end
  78. end
  79. def ensure_single_unoverrideable_permission!(role, new_permission)
  80. parent_permission = parent_object_permissions.find { |elem| elem.role == role }
  81. return if parent_permission.nil?
  82. return if parent_permission.access == 'reader'
  83. return if parent_permission.access == new_permission
  84. message = case parent_permission.access
  85. when 'editor'
  86. __('Invalid permissions. This role has editor access to parent category. Limiting access is not effective.')
  87. when 'none'
  88. __('Invalid permissions. This role does not have access to this category because parent category is not visible for it.')
  89. else
  90. __('Invalid permissions.')
  91. end
  92. raise Exceptions::UnprocessableEntity, message
  93. end
  94. end
  95. end