0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 05:42:36 +08:00
discourse/lib/acl/user.rb
Martin Brennan 7ff30d81a3
FEATURE: Support users in DAccessControl and backend (#41358)
Followup 5823e4e3b2,
this commit allows the addition of users along with
groups to access control lists, modifying DAccessControl
to support selecting a user or group from the same
search input.

Shown here is a mix of user & group permissions in the
`DAccessControl` component:

<img width="611" height="664" alt="image"
src="https://github.com/user-attachments/assets/c25e13b0-8885-4ce7-972c-5116f3acb094"
/>

When the search opens, we show the site's groups that
the user can see as preloaded values, showing only the
group name for clarity:

<img width="612" height="389" alt="image"
src="https://github.com/user-attachments/assets/df93a94b-918e-4fed-b045-ac72f02aca41"
/>

When searching a GET request is sent and users are included
in search results.

<img width="608" height="404" alt="image"
src="https://github.com/user-attachments/assets/ff17e6c0-2505-480e-ae25-e6f8309555bc"
/>

---------

Co-authored-by: Jordan Vidrine <jordan@jordanvidrine.com>
2026-07-15 09:18:06 +10:00

54 lines
1.7 KiB
Ruby
Vendored

# frozen_string_literal: true
module Acl
# This class is used to provide easy lookup methods for a single user's
# flattened ACL list, which can consist of multiple different targets, as an
# alternative to iterating through the flattened array.
class User
attr_reader :target_lookup, :permission_lookup
def initialize(flattened_acl_list)
@target_lookup = {}
@permission_lookup = {}
flattened_acl_list.each do |acl|
@target_lookup[target_key(acl)] ||= []
@target_lookup[target_key(acl)] << acl[:permission]
@permission_lookup[acl[:permission]] ||= {}
@permission_lookup[acl[:permission]][acl[:target_type]] ||= []
@permission_lookup[acl[:permission]][acl[:target_type]] << acl[:target_id]
end
end
def has_target_permission?(target, permission)
@target_lookup[target_key(target)]&.include?(permission)
end
def has_any_target_permission?(target, permissions)
target_permissions = @target_lookup[target_key(target)]
(target_permissions || []).any? { |permission| permissions.include?(permission) }
end
def target_ids_with_permission(target_class, permission)
((@permission_lookup[permission] || {}).dig(target_class.polymorphic_name) || []).dup
end
def target_ids_with_any_permissions(target_class, permissions)
permissions
.flat_map { |permission| target_ids_with_permission(target_class, permission) }
.uniq
.dup
end
private
def target_key(target)
if target.is_a?(Hash)
"#{target[:target_type]}_#{target[:target_id]}"
else
"#{target.class.polymorphic_name}_#{target.id}"
end
end
end
end