permissions_update.rb 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. # Copyright (C) 2012-2023 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. update_object(roles_to_permissions)
  11. next if !@object.changed_for_autosave?
  12. @object.save!
  13. update_all_children
  14. ensure_editable!
  15. end
  16. end
  17. def update_using_params!(params)
  18. roles_to_permissions = params[:permissions].transform_keys { |key| Role.find key }
  19. update!(**roles_to_permissions)
  20. end
  21. private
  22. def update_object(roles_to_permissions)
  23. @object.permissions.reject { |elem| roles_to_permissions.key? elem.role }.each(&:mark_for_destruction)
  24. roles_to_permissions.each do |role, access|
  25. update_object_permission(role, access)
  26. end
  27. end
  28. def update_object_permission(role, access)
  29. permission = @object.permissions.detect { |elem| elem.role == role } || @object.permissions.build(role: role)
  30. permission.access = access
  31. mark_permission_for_cleanup_if_needed(permission, parent_object_permissions)
  32. end
  33. def parent_object_permissions
  34. @parent_object_permissions ||= begin
  35. if @object.is_a? KnowledgeBase::Category
  36. (@object.parent || @object.knowledge_base).permissions_effective || []
  37. else
  38. []
  39. end
  40. end
  41. end
  42. def all_children
  43. case @object
  44. when KnowledgeBase::Category
  45. @object.self_with_children - [@object]
  46. when KnowledgeBase
  47. @object.categories.root.map(&:self_with_children).flatten
  48. end
  49. end
  50. def update_single_child(child)
  51. inherited_permissions = (child.parent || child.knowledge_base).permissions_effective
  52. child.permissions.each do |child_permission|
  53. mark_permission_for_cleanup_if_needed(child_permission, inherited_permissions)
  54. end
  55. child.changed_for_autosave? ? child.save! : child.touch # rubocop:disable Rails/SkipsModelValidations
  56. end
  57. def update_all_children
  58. all_children.each do |child|
  59. update_single_child(child)
  60. end
  61. end
  62. def ensure_editable!
  63. return if !@user
  64. return if KnowledgeBase::EffectivePermission.new(@user, @object).access_effective == 'editor'
  65. raise Exceptions::UnprocessableEntity, __('Invalid permissions, do not lock yourself out.')
  66. end
  67. def mark_permission_for_cleanup_if_needed(permission, parents)
  68. matching = parents.find { |elem| elem.role == permission.role }
  69. return if !matching
  70. return if matching.access != permission.access && matching.access != 'none'
  71. permission.mark_for_destruction
  72. end
  73. end
  74. end