discourse-assign/app/controllers/discourse_assign/assign_controller.rb

170 lines
5.7 KiB
Ruby

# 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 value::integer user_id, MAX(created_at) last_assigned
FROM topic_custom_fields
WHERE name = 'assigned_to_id'
GROUP BY value::integer
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),
suggestions: ActiveModel::ArraySerializer.new(users, scope: guardian, each_serializer: BasicUserSerializer)
}
end
def claim
topic_id = params.require(:topic_id).to_i
topic = Topic.find(topic_id)
assigned = TopicCustomField.where(
"topic_id = :topic_id AND name = 'assigned_to_id' AND value IS NOT NULL",
topic_id: topic_id
).pluck(:value)
if assigned && user_id = assigned[0]
extras = nil
if user = User.where(id: user_id).first
extras = {
assigned_to: serialize_data(user, BasicUserSerializer, root: false)
}
end
return render_json_error(I18n.t('discourse_assign.already_claimed'), extras: extras)
end
assigner = TopicAssigner.new(topic, current_user)
assigner.assign(current_user)
render json: success_json
end
def unassign
topic_id = params.require(:topic_id)
topic = Topic.find(topic_id.to_i)
assigner = TopicAssigner.new(topic, current_user)
assigner.unassign
render json: success_json
end
def assign
topic_id = params.require(:topic_id)
username = params.require(:username)
topic = Topic.find(topic_id.to_i)
assign_to = User.find_by(username_lower: username.downcase)
raise Discourse::NotFound unless assign_to
# perhaps?
#Scheduler::Defer.later "assign topic" do
assign = TopicAssigner.new(topic, current_user).assign(assign_to)
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 topic_custom_fields tcf ON topics.id = tcf.topic_id AND tcf.name = 'assigned_to_id' AND tcf.value IS NOT NULL")
.order('tcf.value::integer, topics.bumped_at desc')
.offset(offset)
.limit(limit)
Topic.preload_custom_fields(topics, TopicList.preloaded_custom_fields)
# TODO Drop AvatarLookup after Discourse 2.6.0 release
lookup_columns = defined?(UserLookup) ? UserLookup.lookup_columns : AvatarLookup.lookup_columns
users = User
.where("users.id IN (SELECT value::int FROM topic_custom_fields WHERE name = 'assigned_to_id' AND topic_id IN (?))", topics.map(&:id))
.joins('join user_emails on user_emails.user_id = users.id AND user_emails.primary')
.select(lookup_columns)
.to_a
# TODO Drop after Discourse 2.6.0 release
if User.respond_to?(:whitelisted_user_custom_fields)
User.preload_custom_fields(users, User.whitelisted_user_custom_fields(guardian))
else
User.preload_custom_fields(users, User.allowed_user_custom_fields(guardian))
end
users = users.to_h { |u| [u.id, u] }
topics.each do |t|
if id = t.custom_fields[TopicAssigner::ASSIGNED_TO_ID]
t.preload_assigned_to_user(users[id.to_i])
end
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 users.id=g.user_id LEFT OUTER JOIN user_options uo on uo.user_id=users.id LEFT OUTER JOIN topic_custom_fields tcf ON tcf.value::int = users.id")
.where("tcf.name = 'assigned_to_id' AND g.group_id=? AND (users.id > 0)", group.id)
.order('COUNT(users.id) DESC')
.group('users.id')
.select('users.*, COUNT(users.id) as "assignments_count"')
.limit(limit)
.offset(offset)
render json: { members: serialize_data(members, GroupUserAssignedSerializer) }
end
private
def translate_failure(reason, user)
case reason
when :already_assigned
{ error: I18n.t('discourse_assign.already_assigned', username: user.username) }
when :forbidden_assign_to
{ error: I18n.t('discourse_assign.forbidden_assign_to', username: user.username) }
else
max = SiteSetting.max_assigned_topics
{ error: I18n.t('discourse_assign.too_many_assigns', username: user.username, max: max) }
end
end
def ensure_assign_allowed
raise Discourse::InvalidAccess.new unless current_user.can_assign?
end
end
end