forked from discourse/discourse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdirectory_items_controller.rb
150 lines (125 loc) · 5.32 KB
/
directory_items_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# frozen_string_literal: true
class DirectoryItemsController < ApplicationController
PAGE_SIZE = 50
before_action :set_groups_exclusion, if: -> { params[:exclude_groups].present? }
def index
unless SiteSetting.enable_user_directory?
raise Discourse::InvalidAccess.new(:enable_user_directory)
end
period = params.require(:period)
period_type = DirectoryItem.period_types[period.to_sym]
raise Discourse::InvalidAccess.new(:period_type) unless period_type
result = DirectoryItem.where(period_type: period_type).includes(user: :user_custom_fields)
if params[:group]
group = Group.find_by(name: params[:group])
raise Discourse::InvalidParameters.new(:group) if group.blank?
guardian.ensure_can_see!(group)
guardian.ensure_can_see_group_members!(group)
result = result.includes(user: :groups).where(users: { groups: { id: group.id } })
else
result = result.includes(user: :primary_group)
end
result = apply_exclude_groups_filter(result)
if params[:exclude_usernames]
result =
result
.references(:user)
.where.not(users: { username: params[:exclude_usernames].split(",") })
end
order = params[:order] || DirectoryColumn.automatic_column_names.first
dir = params[:asc] ? "ASC" : "DESC"
active_directory_column_names = DirectoryColumn.active_column_names
if active_directory_column_names.include?(order.to_sym)
result = result.order("directory_items.#{order} #{dir}, directory_items.id")
elsif params[:order] === "username"
result = result.order("users.#{order} #{dir}, directory_items.id")
else
# Ordering by user field value
user_field = UserField.find_by(name: params[:order])
if user_field
result =
result
.references(:user)
.joins(
"LEFT OUTER JOIN user_custom_fields ON user_custom_fields.user_id = users.id AND user_custom_fields.name = 'user_field_#{user_field.id}'",
)
.order(
"user_custom_fields.name = 'user_field_#{user_field.id}' ASC, user_custom_fields.value #{dir}",
)
end
end
result = result.includes(:user_stat) if period_type == DirectoryItem.period_types[:all]
page = fetch_int_from_params(:page, default: 0)
user_ids = nil
if params[:name].present?
user_ids = UserSearch.new(params[:name], include_staged_users: true).search.pluck(:id)
if user_ids.present?
# Add the current user if we have at least one other match
user_ids << current_user.id if current_user && result.dup.where(user_id: user_ids).exists?
result = result.where(user_id: user_ids)
else
result = result.where("false")
end
end
if params[:username]
user_id = User.where(username_lower: params[:username].to_s.downcase).pick(:id)
if user_id
result = result.where(user_id: user_id)
else
result = result.where("false")
end
end
limit = fetch_limit_from_params(default: PAGE_SIZE, max: PAGE_SIZE)
result_count = result.count
result = result.limit(limit).offset(limit * page).to_a
more_params = params.slice(:period, :order, :asc, :group, :user_field_ids).permit!
more_params[:page] = page + 1
load_more_uri = URI.parse(directory_items_path(more_params))
load_more_directory_items_json = "#{load_more_uri.path}.json?#{load_more_uri.query}"
# Put yourself at the top of the first page
if result.present? && current_user.present? && page == 0 && !params[:group].present?
position = result.index { |r| r.user_id == current_user.id }
# Don't show the record unless you're not in the top positions already
if (position || 10) >= 10
unless @users_in_exclude_groups&.include?(current_user.id)
your_item = DirectoryItem.where(period_type: period_type, user_id: current_user.id).first
result.insert(0, your_item) if your_item
end
end
end
last_updated_at = DirectoryItem.last_updated_at(period_type)
serializer_opts = {}
if params[:user_field_ids]
serializer_opts[:user_custom_field_map] = {}
user_field_ids = params[:user_field_ids]&.split("|")&.map(&:to_i)
user_field_ids.each do |user_field_id|
serializer_opts[:user_custom_field_map][
"#{User::USER_FIELD_PREFIX}#{user_field_id}"
] = user_field_id
end
end
if params[:plugin_column_ids]
serializer_opts[:plugin_column_ids] = params[:plugin_column_ids]&.split("|")&.map(&:to_i)
end
serializer_opts[:attributes] = active_directory_column_names
serialized = serialize_data(result, DirectoryItemSerializer, serializer_opts)
render_json_dump(
directory_items: serialized,
meta: {
last_updated_at: last_updated_at,
total_rows_directory_items: result_count,
load_more_directory_items: load_more_directory_items_json,
},
)
end
private
def set_groups_exclusion
@exclude_group_names = params[:exclude_groups].split("|")
@exclude_group_ids = Group.where(name: @exclude_group_names).pluck(:id)
@users_in_exclude_groups = GroupUser.where(group_id: @exclude_group_ids).pluck(:user_id)
end
def apply_exclude_groups_filter(result)
result = result.where.not(user_id: @users_in_exclude_groups) if params[:exclude_groups]
result
end
end