-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathassign_controller.rb
186 lines (153 loc) · 7.15 KB
/
assign_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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# frozen_string_literal: true
module DiscourseAssign
class AssignController < ApplicationController
requires_login
before_action :ensure_logged_in, :ensure_assign_allowed
def suggestions
users = [current_user]
users += User
.where('users.id <> ?', current_user.id)
.joins(<<~SQL
JOIN(
SELECT assigned_to_id user_id, MAX(created_at) last_assigned
FROM assignments
WHERE assignments.assigned_to_type = 'User'
GROUP BY assigned_to_id
HAVING COUNT(*) < #{SiteSetting.max_assigned_topics}
) as X ON X.user_id = users.id
SQL
)
.assign_allowed
.order('X.last_assigned DESC')
.limit(6)
render json: {
assign_allowed_on_groups: Group.visible_groups(current_user).assign_allowed_groups.pluck(:name),
assign_allowed_for_groups: Group.visible_groups(current_user).assignable(current_user).pluck(:name),
suggestions: ActiveModel::ArraySerializer.new(users, scope: guardian, each_serializer: BasicUserSerializer),
}
end
def unassign
target_id = params.require(:target_id)
target_type = params.require(:target_type)
raise Discourse::NotFound if !Assignment.valid_type?(target_type)
target = target_type.constantize.where(id: target_id).first
raise Discourse::NotFound unless target
assigner = Assigner.new(target, current_user)
assigner.unassign
render json: success_json
end
def assign
target_id = params.require(:target_id)
target_type = params.require(:target_type)
username = params.permit(:username)['username']
group_name = params.permit(:group_name)['group_name']
priority = (params.permit(:priority)['priority'])&.to_i
assign_to = username.present? ? User.find_by(username_lower: username.downcase) : Group.where("LOWER(name) = ?", group_name.downcase).first
raise Discourse::NotFound unless assign_to
raise Discourse::NotFound if !Assignment.valid_type?(target_type)
target = target_type.constantize.where(id: target_id).first
raise Discourse::NotFound unless target
assign = Assigner.new(target, current_user).assign(assign_to, priority: priority)
if assign[:success]
render json: success_json
else
render json: translate_failure(assign[:reason], assign_to), status: 400
end
end
def assigned
raise Discourse::InvalidAccess unless current_user&.admin?
offset = (params[:offset] || 0).to_i
limit = (params[:limit] || 100).to_i
topics = Topic
.includes(:tags)
.includes(:user)
.joins("JOIN assignments a ON a.target_id = topics.id AND a.target_type = 'Topic' AND a.assigned_to_id IS NOT NULL")
.order("a.assigned_to_id, topics.bumped_at desc")
.offset(offset)
.limit(limit)
Topic.preload_custom_fields(topics, TopicList.preloaded_custom_fields)
topic_assignments = Assignment.where(target_id: topics.map(&:id), target_type: 'Topic', active: true).pluck(:target_id, :assigned_to_id).to_h
users = User
.where("users.id IN (?)", topic_assignments.values.uniq)
.joins("join user_emails on user_emails.user_id = users.id AND user_emails.primary")
.select(UserLookup.lookup_columns)
.to_a
User.preload_custom_fields(users, User.allowed_user_custom_fields(guardian))
users_map = users.index_by(&:id)
topics.each do |topic|
user_id = topic_assignments[topic.id]
topic.preload_assigned_to(users_map[user_id]) if user_id
end
render json: { topics: serialize_data(topics, AssignedTopicSerializer) }
end
def group_members
limit = (params[:limit] || 50).to_i
offset = params[:offset].to_i
raise Discourse::InvalidParameters.new(:limit) if limit < 0 || limit > 1000
raise Discourse::InvalidParameters.new(:offset) if offset < 0
raise Discourse::NotFound.new if !params[:group_name].present?
group = Group.find_by(name: params[:group_name])
guardian.ensure_can_see_group_members!(group)
members = User
.joins("LEFT OUTER JOIN group_users g ON g.user_id = users.id")
.joins("LEFT OUTER JOIN assignments a ON a.assigned_to_id = users.id AND a.assigned_to_type = 'User'")
.joins("LEFT OUTER JOIN topics t ON t.id = a.target_id AND a.target_type = 'Topic'")
.where("g.group_id = ? AND users.id > 0 AND t.deleted_at IS NULL", group.id)
.where("a.assigned_to_id IS NOT NULL AND a.active")
.order('COUNT(users.id) DESC')
.group('users.id')
.select('users.*, COUNT(users.id) as "assignments_count"')
.limit(limit)
.offset(offset)
if params[:filter]
members = members.where(<<~SQL, pattern: "%#{params[:filter]}%")
users.name ILIKE :pattern OR users.username_lower ILIKE :pattern
SQL
end
group_assignments = Topic
.joins("JOIN assignments a ON a.topic_id = topics.id")
.where(<<~SQL, group_id: group.id)
a.assigned_to_id = :group_id AND a.assigned_to_type = 'Group' AND a.active
SQL
.pluck(:topic_id)
assignments = TopicQuery
.new(current_user)
.group_topics_assigned_results(group)
.pluck('topics.id')
render json: {
members: serialize_data(members, GroupUserAssignedSerializer),
assignment_count: (assignments | group_assignments).count,
group_assignment_count: group_assignments.count
}
end
private
def translate_failure(reason, assign_to)
case reason
when :already_assigned
{ error: I18n.t('discourse_assign.already_assigned', username: assign_to.username) }
when :forbidden_assign_to
{ error: I18n.t('discourse_assign.forbidden_assign_to', username: assign_to.username) }
when :forbidden_assignee_not_pm_participant
{ error: I18n.t('discourse_assign.forbidden_assignee_not_pm_participant', username: assign_to.username) }
when :forbidden_assignee_cant_see_topic
{ error: I18n.t('discourse_assign.forbidden_assignee_cant_see_topic', username: assign_to.username) }
when :group_already_assigned
{ error: I18n.t('discourse_assign.group_already_assigned', group: assign_to.name) }
when :forbidden_group_assign_to
{ error: I18n.t('discourse_assign.forbidden_group_assign_to', group: assign_to.name) }
when :forbidden_group_assignee_not_pm_participant
{ error: I18n.t('discourse_assign.forbidden_group_assignee_not_pm_participant', group: assign_to.name) }
when :forbidden_group_assignee_cant_see_topic
{ error: I18n.t('discourse_assign.forbidden_group_assignee_cant_see_topic', group: assign_to.name) }
when :too_many_assigns_for_topic
{ error: I18n.t('discourse_assign.too_many_assigns_for_topic', limit: Assigner::ASSIGNMENTS_PER_TOPIC_LIMIT) }
else
max = SiteSetting.max_assigned_topics
{ error: I18n.t('discourse_assign.too_many_assigns', username: assign_to.username, max: max) }
end
end
def ensure_assign_allowed
raise Discourse::InvalidAccess.new unless current_user.can_assign?
end
end
end