2019-05-03 06:17:27 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
class Admin::UsersController < Admin::AdminController
|
|
|
|
|
2017-08-31 12:06:56 +08:00
|
|
|
before_action :fetch_user, only: [:suspend,
|
2013-11-08 02:53:32 +08:00
|
|
|
:unsuspend,
|
2014-06-06 11:02:52 +08:00
|
|
|
:log_out,
|
2013-10-23 03:53:08 +08:00
|
|
|
:revoke_admin,
|
|
|
|
:grant_admin,
|
|
|
|
:revoke_moderation,
|
|
|
|
:grant_moderation,
|
|
|
|
:approve,
|
|
|
|
:activate,
|
|
|
|
:deactivate,
|
2017-11-11 01:18:08 +08:00
|
|
|
:silence,
|
|
|
|
:unsilence,
|
2013-10-23 03:53:08 +08:00
|
|
|
:trust_level,
|
2014-09-14 04:55:26 +08:00
|
|
|
:trust_level_lock,
|
2014-07-14 02:11:38 +08:00
|
|
|
:add_group,
|
|
|
|
:remove_group,
|
2014-02-11 05:59:36 +08:00
|
|
|
:primary_group,
|
2016-05-07 01:34:33 +08:00
|
|
|
:anonymize,
|
2020-04-22 16:37:51 +08:00
|
|
|
:merge,
|
2017-12-22 09:18:12 +08:00
|
|
|
:reset_bounce_score,
|
2018-12-15 08:01:35 +08:00
|
|
|
:disable_second_factor,
|
2020-09-15 22:00:10 +08:00
|
|
|
:delete_posts_batch,
|
|
|
|
:sso_record]
|
2013-05-31 23:41:40 +08:00
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
def index
|
2014-11-03 19:46:08 +08:00
|
|
|
users = ::AdminUserIndexQuery.new(params).find_users
|
|
|
|
|
2019-01-12 00:10:02 +08:00
|
|
|
opts = {}
|
2014-11-03 19:46:08 +08:00
|
|
|
if params[:show_emails] == "true"
|
2019-01-18 22:26:44 +08:00
|
|
|
StaffActionLogger.new(current_user).log_show_emails(users, context: request.path)
|
2019-01-12 00:10:02 +08:00
|
|
|
opts[:emails_desired] = true
|
2014-11-03 19:46:08 +08:00
|
|
|
end
|
|
|
|
|
2019-01-12 00:10:02 +08:00
|
|
|
render_serialized(users, AdminUserListSerializer, opts)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def show
|
2015-09-26 21:56:36 +08:00
|
|
|
@user = User.find_by(id: params[:id])
|
2015-05-07 09:00:51 +08:00
|
|
|
raise Discourse::NotFound unless @user
|
2013-02-06 03:16:51 +08:00
|
|
|
render_serialized(@user, AdminDetailedUserSerializer, root: false)
|
|
|
|
end
|
|
|
|
|
2018-12-14 18:04:18 +08:00
|
|
|
def delete_posts_batch
|
2018-12-15 08:01:35 +08:00
|
|
|
deleted_posts = @user.delete_posts_in_batches(guardian)
|
2018-12-14 18:04:18 +08:00
|
|
|
# staff action logs will have an entry for each post
|
|
|
|
|
|
|
|
render json: { posts_deleted: deleted_posts.length }
|
2013-02-07 15:11:56 +08:00
|
|
|
end
|
2013-04-05 00:59:44 +08:00
|
|
|
|
2018-05-25 23:45:42 +08:00
|
|
|
# DELETE action to delete penalty history for a user
|
|
|
|
def penalty_history
|
|
|
|
|
|
|
|
# We don't delete any history, we merely remove the action type
|
|
|
|
# with a removed type. It can still be viewed in the logs but
|
|
|
|
# will not affect TL3 promotions.
|
|
|
|
sql = <<~SQL
|
|
|
|
UPDATE user_histories
|
|
|
|
SET action = CASE
|
|
|
|
WHEN action = :silence_user THEN :removed_silence_user
|
|
|
|
WHEN action = :unsilence_user THEN :removed_unsilence_user
|
|
|
|
WHEN action = :suspend_user THEN :removed_suspend_user
|
|
|
|
WHEN action = :unsuspend_user THEN :removed_unsuspend_user
|
|
|
|
END
|
|
|
|
WHERE target_user_id = :user_id
|
|
|
|
AND action IN (
|
|
|
|
:silence_user,
|
|
|
|
:suspend_user,
|
|
|
|
:unsilence_user,
|
|
|
|
:unsuspend_user
|
|
|
|
)
|
|
|
|
SQL
|
|
|
|
|
2018-06-19 14:13:14 +08:00
|
|
|
DB.exec(
|
2018-05-25 23:45:42 +08:00
|
|
|
sql,
|
|
|
|
UserHistory.actions.slice(
|
|
|
|
:silence_user,
|
|
|
|
:suspend_user,
|
|
|
|
:unsilence_user,
|
|
|
|
:unsuspend_user,
|
|
|
|
:removed_silence_user,
|
|
|
|
:removed_unsilence_user,
|
|
|
|
:removed_suspend_user,
|
|
|
|
:removed_unsuspend_user
|
|
|
|
).merge(user_id: params[:user_id].to_i)
|
|
|
|
)
|
|
|
|
|
|
|
|
render json: success_json
|
|
|
|
end
|
|
|
|
|
2013-11-08 02:53:32 +08:00
|
|
|
def suspend
|
|
|
|
guardian.ensure_can_suspend!(@user)
|
2020-11-03 23:38:56 +08:00
|
|
|
|
|
|
|
if @user.suspended?
|
|
|
|
suspend_record = @user.suspend_record
|
|
|
|
message = I18n.t("user.already_suspended",
|
|
|
|
staff: suspend_record.acting_user.username,
|
|
|
|
time_ago: FreedomPatches::Rails4.time_ago_in_words(suspend_record.created_at, true, scope: :'datetime.distance_in_words_verbose')
|
|
|
|
)
|
|
|
|
return render json: failed_json.merge(message: message), status: 409
|
|
|
|
end
|
|
|
|
|
2020-08-27 09:05:33 +08:00
|
|
|
params.require([:suspend_until, :reason])
|
|
|
|
|
2017-09-14 04:44:47 +08:00
|
|
|
@user.suspended_till = params[:suspend_until]
|
2013-11-08 02:53:32 +08:00
|
|
|
@user.suspended_at = DateTime.now
|
2017-09-14 02:11:33 +08:00
|
|
|
|
2017-09-14 02:43:36 +08:00
|
|
|
message = params[:message]
|
|
|
|
|
|
|
|
user_history = nil
|
|
|
|
|
|
|
|
User.transaction do
|
|
|
|
@user.save!
|
|
|
|
|
|
|
|
user_history = StaffActionLogger.new(current_user).log_user_suspend(
|
|
|
|
@user,
|
|
|
|
params[:reason],
|
2017-11-21 01:33:02 +08:00
|
|
|
message: message,
|
2017-09-15 02:10:39 +08:00
|
|
|
post_id: params[:post_id]
|
2017-09-14 02:43:36 +08:00
|
|
|
)
|
|
|
|
end
|
2016-07-04 17:20:30 +08:00
|
|
|
@user.logged_out
|
2017-09-14 02:11:33 +08:00
|
|
|
|
2021-04-13 00:53:40 +08:00
|
|
|
if message.present?
|
2021-04-12 23:03:10 +08:00
|
|
|
Jobs.enqueue(
|
|
|
|
:critical_user_email,
|
|
|
|
type: :account_suspended,
|
|
|
|
user_id: @user.id,
|
|
|
|
user_history_id: user_history.id
|
|
|
|
)
|
|
|
|
end
|
2017-09-14 02:43:36 +08:00
|
|
|
|
2018-01-12 01:56:28 +08:00
|
|
|
DiscourseEvent.trigger(
|
|
|
|
:user_suspended,
|
|
|
|
user: @user,
|
|
|
|
reason: params[:reason],
|
|
|
|
message: message,
|
|
|
|
user_history: user_history,
|
|
|
|
post_id: params[:post_id],
|
|
|
|
suspended_till: params[:suspend_until],
|
|
|
|
suspended_at: DateTime.now
|
|
|
|
)
|
|
|
|
|
2018-01-31 05:31:29 +08:00
|
|
|
perform_post_action
|
|
|
|
|
2017-09-14 02:11:33 +08:00
|
|
|
render_json_dump(
|
|
|
|
suspension: {
|
|
|
|
suspend_reason: params[:reason],
|
2018-01-11 23:54:27 +08:00
|
|
|
full_suspend_reason: user_history.try(:details),
|
2017-09-14 02:11:33 +08:00
|
|
|
suspended_till: @user.suspended_till,
|
|
|
|
suspended_at: @user.suspended_at
|
|
|
|
}
|
|
|
|
)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2013-11-08 02:53:32 +08:00
|
|
|
def unsuspend
|
|
|
|
guardian.ensure_can_suspend!(@user)
|
|
|
|
@user.suspended_till = nil
|
|
|
|
@user.suspended_at = nil
|
2013-02-06 03:16:51 +08:00
|
|
|
@user.save!
|
2013-11-08 02:53:32 +08:00
|
|
|
StaffActionLogger.new(current_user).log_user_unsuspend(@user)
|
2017-09-14 02:11:33 +08:00
|
|
|
|
2018-11-09 05:32:59 +08:00
|
|
|
DiscourseEvent.trigger(:user_unsuspended, user: @user)
|
|
|
|
|
2017-09-14 02:11:33 +08:00
|
|
|
render_json_dump(
|
|
|
|
suspension: {
|
2019-10-18 07:49:26 +08:00
|
|
|
suspended_till: nil,
|
|
|
|
suspended_at: nil
|
2017-09-14 02:11:33 +08:00
|
|
|
}
|
|
|
|
)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2014-06-06 11:02:52 +08:00
|
|
|
def log_out
|
2014-12-01 21:03:25 +08:00
|
|
|
if @user
|
2017-02-01 06:21:37 +08:00
|
|
|
@user.user_auth_tokens.destroy_all
|
2016-07-04 17:20:30 +08:00
|
|
|
@user.logged_out
|
2014-12-01 21:03:25 +08:00
|
|
|
render json: success_json
|
|
|
|
else
|
|
|
|
render json: { error: I18n.t('admin_js.admin.users.id_not_found') }, status: 404
|
|
|
|
end
|
2014-06-06 11:02:52 +08:00
|
|
|
end
|
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
def revoke_admin
|
2013-05-31 23:41:40 +08:00
|
|
|
guardian.ensure_can_revoke_admin!(@user)
|
|
|
|
@user.revoke_admin!
|
2016-01-27 17:38:16 +08:00
|
|
|
StaffActionLogger.new(current_user).log_revoke_admin(@user)
|
2017-08-31 12:06:56 +08:00
|
|
|
render body: nil
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def grant_admin
|
2017-04-05 01:59:22 +08:00
|
|
|
AdminConfirmation.new(@user, current_user).create_confirmation
|
|
|
|
render json: success_json
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2013-02-13 06:58:08 +08:00
|
|
|
def revoke_moderation
|
2013-05-31 23:41:40 +08:00
|
|
|
guardian.ensure_can_revoke_moderation!(@user)
|
|
|
|
@user.revoke_moderation!
|
2016-01-27 17:38:16 +08:00
|
|
|
StaffActionLogger.new(current_user).log_revoke_moderation(@user)
|
2017-08-31 12:06:56 +08:00
|
|
|
render body: nil
|
2013-02-13 06:58:08 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def grant_moderation
|
|
|
|
guardian.ensure_can_grant_moderation!(@user)
|
2013-05-06 12:49:56 +08:00
|
|
|
@user.grant_moderation!
|
2016-01-27 17:38:16 +08:00
|
|
|
StaffActionLogger.new(current_user).log_grant_moderation(@user)
|
2013-02-13 06:58:08 +08:00
|
|
|
render_serialized(@user, AdminUserSerializer)
|
|
|
|
end
|
|
|
|
|
2014-07-14 02:11:38 +08:00
|
|
|
def add_group
|
|
|
|
group = Group.find(params[:group_id].to_i)
|
2020-04-21 09:50:20 +08:00
|
|
|
raise Discourse::NotFound unless group
|
2021-07-28 19:04:04 +08:00
|
|
|
|
2020-04-21 09:50:20 +08:00
|
|
|
return render_json_error(I18n.t('groups.errors.can_not_modify_automatic')) if group.automatic
|
2021-07-28 19:04:04 +08:00
|
|
|
guardian.ensure_can_edit!(group)
|
2015-10-29 00:21:54 +08:00
|
|
|
|
2016-12-11 23:36:15 +08:00
|
|
|
group.add(@user)
|
|
|
|
GroupActionLogger.new(current_user, group).log_add_user_to_group(@user)
|
2015-10-29 00:21:54 +08:00
|
|
|
|
2017-08-31 12:06:56 +08:00
|
|
|
render body: nil
|
2014-07-14 02:11:38 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def remove_group
|
|
|
|
group = Group.find(params[:group_id].to_i)
|
2020-04-21 09:50:20 +08:00
|
|
|
raise Discourse::NotFound unless group
|
2021-07-28 19:04:04 +08:00
|
|
|
|
2020-04-21 09:50:20 +08:00
|
|
|
return render_json_error(I18n.t('groups.errors.can_not_modify_automatic')) if group.automatic
|
2021-07-28 19:04:04 +08:00
|
|
|
guardian.ensure_can_edit!(group)
|
2017-08-05 00:13:20 +08:00
|
|
|
|
2021-07-28 19:04:04 +08:00
|
|
|
if group.remove(@user)
|
|
|
|
GroupActionLogger.new(current_user, group).log_remove_user_from_group(@user)
|
|
|
|
end
|
2017-08-05 00:13:20 +08:00
|
|
|
|
2017-08-31 12:06:56 +08:00
|
|
|
render body: nil
|
2014-07-14 02:11:38 +08:00
|
|
|
end
|
|
|
|
|
2014-02-11 05:59:36 +08:00
|
|
|
def primary_group
|
|
|
|
guardian.ensure_can_change_primary_group!(@user)
|
2017-08-05 00:13:20 +08:00
|
|
|
|
|
|
|
if params[:primary_group_id].present?
|
|
|
|
primary_group_id = params[:primary_group_id].to_i
|
|
|
|
if group = Group.find(primary_group_id)
|
|
|
|
if group.user_ids.include?(@user.id)
|
|
|
|
@user.primary_group_id = primary_group_id
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
@user.primary_group_id = nil
|
2017-05-18 00:42:04 +08:00
|
|
|
end
|
2017-08-05 00:13:20 +08:00
|
|
|
|
|
|
|
@user.save!
|
|
|
|
|
2017-08-31 12:06:56 +08:00
|
|
|
render body: nil
|
2014-02-11 05:59:36 +08:00
|
|
|
end
|
|
|
|
|
2013-07-03 16:27:40 +08:00
|
|
|
def trust_level
|
|
|
|
guardian.ensure_can_change_trust_level!(@user)
|
2014-09-30 11:12:33 +08:00
|
|
|
level = params[:level].to_i
|
|
|
|
|
2017-11-24 04:55:44 +08:00
|
|
|
if @user.manual_locked_trust_level.nil?
|
2019-05-07 09:27:05 +08:00
|
|
|
if [0, 1, 2].include?(level) && Promotion.public_send("tl#{level + 1}_met?", @user)
|
2017-11-24 04:55:44 +08:00
|
|
|
@user.manual_locked_trust_level = level
|
|
|
|
@user.save
|
|
|
|
elsif level == 3 && Promotion.tl3_lost?(@user)
|
|
|
|
@user.manual_locked_trust_level = level
|
|
|
|
@user.save
|
|
|
|
end
|
2014-09-30 11:12:33 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
@user.change_trust_level!(level, log_action_for: current_user)
|
2014-06-17 08:46:30 +08:00
|
|
|
|
2013-07-03 16:27:40 +08:00
|
|
|
render_serialized(@user, AdminUserSerializer)
|
2014-07-30 03:54:20 +08:00
|
|
|
rescue Discourse::InvalidAccess => e
|
|
|
|
render_json_error(e.message)
|
2013-07-03 16:27:40 +08:00
|
|
|
end
|
|
|
|
|
2014-09-14 04:55:26 +08:00
|
|
|
def trust_level_lock
|
|
|
|
guardian.ensure_can_change_trust_level!(@user)
|
|
|
|
|
2014-09-30 11:12:33 +08:00
|
|
|
new_lock = params[:locked].to_s
|
|
|
|
unless new_lock =~ /true|false/
|
2015-05-26 21:16:55 +08:00
|
|
|
return render_json_error I18n.t('errors.invalid_boolean')
|
2014-09-14 04:55:26 +08:00
|
|
|
end
|
|
|
|
|
2017-11-24 04:55:44 +08:00
|
|
|
@user.manual_locked_trust_level = (new_lock == "true") ? @user.trust_level : nil
|
2014-09-14 04:55:26 +08:00
|
|
|
@user.save
|
2014-09-30 11:12:33 +08:00
|
|
|
|
2017-01-11 05:45:36 +08:00
|
|
|
StaffActionLogger.new(current_user).log_lock_trust_level(@user)
|
2017-11-24 04:55:44 +08:00
|
|
|
Promotion.recalculate(@user, current_user)
|
2014-09-30 11:12:33 +08:00
|
|
|
|
2017-08-31 12:06:56 +08:00
|
|
|
render body: nil
|
2014-09-14 04:55:26 +08:00
|
|
|
end
|
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
def approve
|
2019-04-17 02:42:47 +08:00
|
|
|
guardian.ensure_can_approve!(@user)
|
|
|
|
|
|
|
|
reviewable = ReviewableUser.find_by(target: @user) ||
|
|
|
|
Jobs::CreateUserReviewable.new.execute(user_id: @user.id).reviewable
|
|
|
|
|
2019-04-17 23:26:43 +08:00
|
|
|
reviewable.perform(current_user, :approve_user)
|
2017-08-31 12:06:56 +08:00
|
|
|
render body: nil
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def approve_bulk
|
2019-04-17 23:26:43 +08:00
|
|
|
Reviewable.bulk_perform_targets(current_user, :approve_user, 'ReviewableUser', params[:users])
|
2017-08-31 12:06:56 +08:00
|
|
|
render body: nil
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2013-05-08 09:58:34 +08:00
|
|
|
def activate
|
|
|
|
guardian.ensure_can_activate!(@user)
|
2017-08-01 00:54:09 +08:00
|
|
|
# ensure there is an active email token
|
|
|
|
@user.email_tokens.create(email: @user.email) unless @user.email_tokens.active.exists?
|
2013-05-08 09:58:34 +08:00
|
|
|
@user.activate
|
2017-01-11 05:45:36 +08:00
|
|
|
StaffActionLogger.new(current_user).log_user_activate(@user, I18n.t('user.activated_by_staff'))
|
2014-12-09 02:16:57 +08:00
|
|
|
render json: success_json
|
2013-05-08 09:58:34 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def deactivate
|
|
|
|
guardian.ensure_can_deactivate!(@user)
|
2019-04-04 00:04:05 +08:00
|
|
|
@user.deactivate(current_user)
|
2018-05-08 10:44:49 +08:00
|
|
|
StaffActionLogger.new(current_user).log_user_deactivate(@user, I18n.t('user.deactivated_by_staff'), params.slice(:context))
|
2014-04-29 01:46:28 +08:00
|
|
|
refresh_browser @user
|
2019-12-30 23:14:29 +08:00
|
|
|
render json: success_json
|
2013-05-08 09:58:34 +08:00
|
|
|
end
|
|
|
|
|
2017-11-11 01:18:08 +08:00
|
|
|
def silence
|
|
|
|
guardian.ensure_can_silence_user! @user
|
2017-11-14 02:41:36 +08:00
|
|
|
|
2020-11-03 23:38:56 +08:00
|
|
|
if @user.silenced?
|
|
|
|
silenced_record = @user.silenced_record
|
|
|
|
message = I18n.t("user.already_silenced",
|
|
|
|
staff: silenced_record.acting_user.username,
|
|
|
|
time_ago: FreedomPatches::Rails4.time_ago_in_words(silenced_record.created_at, true, scope: :'datetime.distance_in_words_verbose')
|
|
|
|
)
|
|
|
|
return render json: failed_json.merge(message: message), status: 409
|
|
|
|
end
|
|
|
|
|
2017-11-14 02:41:36 +08:00
|
|
|
message = params[:message]
|
|
|
|
|
|
|
|
silencer = UserSilencer.new(
|
|
|
|
@user,
|
|
|
|
current_user,
|
|
|
|
silenced_till: params[:silenced_till],
|
|
|
|
reason: params[:reason],
|
2017-11-21 01:33:02 +08:00
|
|
|
message_body: message,
|
2018-02-14 04:33:15 +08:00
|
|
|
keep_posts: true,
|
|
|
|
post_id: params[:post_id]
|
2017-11-14 02:41:36 +08:00
|
|
|
)
|
2021-03-02 07:18:09 +08:00
|
|
|
if silencer.silence
|
2017-11-14 02:41:36 +08:00
|
|
|
Jobs.enqueue(
|
|
|
|
:critical_user_email,
|
|
|
|
type: :account_silenced,
|
|
|
|
user_id: @user.id,
|
|
|
|
user_history_id: silencer.user_history.id
|
|
|
|
)
|
|
|
|
end
|
2018-01-31 05:31:29 +08:00
|
|
|
perform_post_action
|
2017-11-14 02:41:36 +08:00
|
|
|
|
|
|
|
render_json_dump(
|
|
|
|
silence: {
|
|
|
|
silenced: true,
|
2018-01-11 23:54:27 +08:00
|
|
|
silence_reason: silencer.user_history.try(:details),
|
2017-11-14 02:41:36 +08:00
|
|
|
silenced_till: @user.silenced_till,
|
2018-07-23 06:08:36 +08:00
|
|
|
silenced_at: @user.silenced_at,
|
2018-03-30 05:07:09 +08:00
|
|
|
silenced_by: BasicUserSerializer.new(current_user, root: false).as_json
|
2017-11-14 02:41:36 +08:00
|
|
|
}
|
|
|
|
)
|
2013-05-31 23:41:40 +08:00
|
|
|
end
|
|
|
|
|
2017-11-11 01:18:08 +08:00
|
|
|
def unsilence
|
|
|
|
guardian.ensure_can_unsilence_user! @user
|
|
|
|
UserSilencer.unsilence(@user, current_user)
|
2017-11-14 02:41:36 +08:00
|
|
|
|
|
|
|
render_json_dump(
|
|
|
|
unsilence: {
|
|
|
|
silenced: false,
|
|
|
|
silence_reason: nil,
|
|
|
|
silenced_till: nil,
|
2018-07-23 06:08:36 +08:00
|
|
|
silenced_at: nil
|
2017-11-14 02:41:36 +08:00
|
|
|
}
|
|
|
|
)
|
2013-05-31 23:41:40 +08:00
|
|
|
end
|
|
|
|
|
2017-12-22 09:18:12 +08:00
|
|
|
def disable_second_factor
|
2018-02-20 14:44:51 +08:00
|
|
|
guardian.ensure_can_disable_second_factor!(@user)
|
2018-06-28 16:12:32 +08:00
|
|
|
user_second_factor = @user.user_second_factors
|
2020-07-08 03:19:30 +08:00
|
|
|
user_security_key = @user.security_keys
|
|
|
|
raise Discourse::InvalidParameters if user_second_factor.empty? && user_security_key.empty?
|
2018-02-20 14:44:51 +08:00
|
|
|
|
2018-06-28 16:12:32 +08:00
|
|
|
user_second_factor.destroy_all
|
2020-07-08 03:19:30 +08:00
|
|
|
user_security_key.destroy_all
|
2018-02-20 14:44:51 +08:00
|
|
|
StaffActionLogger.new(current_user).log_disable_second_factor_auth(@user)
|
|
|
|
|
2017-12-22 09:18:12 +08:00
|
|
|
Jobs.enqueue(
|
|
|
|
:critical_user_email,
|
|
|
|
type: :account_second_factor_disabled,
|
|
|
|
user_id: @user.id
|
|
|
|
)
|
2018-02-20 14:44:51 +08:00
|
|
|
|
|
|
|
render json: success_json
|
2017-12-22 09:18:12 +08:00
|
|
|
end
|
|
|
|
|
2013-04-12 04:04:20 +08:00
|
|
|
def destroy
|
2014-07-29 01:17:37 +08:00
|
|
|
user = User.find_by(id: params[:id].to_i)
|
2013-04-12 04:04:20 +08:00
|
|
|
guardian.ensure_can_delete_user!(user)
|
2018-05-04 04:18:19 +08:00
|
|
|
|
|
|
|
options = params.slice(:block_email, :block_urls, :block_ip, :context, :delete_as_spammer)
|
|
|
|
options[:delete_posts] = ActiveModel::Type::Boolean.new.cast(params[:delete_posts])
|
2019-01-18 23:04:29 +08:00
|
|
|
options[:prepare_for_destroy] = true
|
2018-05-04 04:18:19 +08:00
|
|
|
|
|
|
|
hijack do
|
|
|
|
begin
|
|
|
|
if UserDestroyer.new(current_user).destroy(user, options)
|
|
|
|
render json: { deleted: true }
|
|
|
|
else
|
|
|
|
render json: {
|
|
|
|
deleted: false,
|
|
|
|
user: AdminDetailedUserSerializer.new(user, root: false).as_json
|
|
|
|
}
|
|
|
|
end
|
|
|
|
rescue UserDestroyer::PostsExistError
|
2018-05-11 03:04:36 +08:00
|
|
|
render json: {
|
|
|
|
deleted: false,
|
2021-06-22 17:29:35 +08:00
|
|
|
message: I18n.t("user.cannot_delete_has_posts", username: user.username, count: user.posts.joins(:topic).count),
|
2018-05-23 06:17:44 +08:00
|
|
|
}, status: 403
|
2013-07-25 01:48:55 +08:00
|
|
|
end
|
2013-04-12 04:04:20 +08:00
|
|
|
end
|
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-03-19 22:27:21 +08:00
|
|
|
def badges
|
|
|
|
end
|
|
|
|
|
2014-09-25 08:19:26 +08:00
|
|
|
def tl3_requirements
|
2014-01-24 05:40:10 +08:00
|
|
|
end
|
|
|
|
|
2014-07-08 04:18:18 +08:00
|
|
|
def ip_info
|
|
|
|
params.require(:ip)
|
|
|
|
|
2018-10-31 09:38:57 +08:00
|
|
|
render json: DiscourseIpInfo.get(params[:ip], resolve_hostname: true)
|
2014-07-08 04:18:18 +08:00
|
|
|
end
|
2013-05-31 23:41:40 +08:00
|
|
|
|
2014-10-28 08:25:02 +08:00
|
|
|
def sync_sso
|
2021-02-08 18:04:33 +08:00
|
|
|
return render body: nil, status: 404 unless SiteSetting.enable_discourse_connect
|
2014-10-28 08:25:02 +08:00
|
|
|
|
2018-12-07 23:01:44 +08:00
|
|
|
begin
|
2021-02-18 18:35:10 +08:00
|
|
|
sso = DiscourseSingleSignOn.parse("sso=#{params[:sso]}&sig=#{params[:sig]}", secure_session: secure_session)
|
2021-04-21 08:42:07 +08:00
|
|
|
rescue DiscourseSingleSignOn::ParseError
|
2021-02-08 18:04:33 +08:00
|
|
|
return render json: failed_json.merge(message: I18n.t("discourse_connect.login_error")), status: 422
|
2018-12-07 23:01:44 +08:00
|
|
|
end
|
2014-10-28 08:25:02 +08:00
|
|
|
|
2016-03-26 13:28:49 +08:00
|
|
|
begin
|
|
|
|
user = sso.lookup_or_create_user
|
|
|
|
render_serialized(user, AdminDetailedUserSerializer, root: false)
|
|
|
|
rescue ActiveRecord::RecordInvalid => ex
|
|
|
|
render json: failed_json.merge(message: ex.message), status: 403
|
2020-01-09 00:47:01 +08:00
|
|
|
rescue DiscourseSingleSignOn::BlankExternalId => ex
|
2021-02-08 18:04:33 +08:00
|
|
|
render json: failed_json.merge(message: I18n.t('discourse_connect.blank_id_error')), status: 422
|
2016-03-26 13:28:49 +08:00
|
|
|
end
|
2014-10-28 08:25:02 +08:00
|
|
|
end
|
|
|
|
|
2014-11-21 02:59:20 +08:00
|
|
|
def delete_other_accounts_with_same_ip
|
|
|
|
params.require(:ip)
|
|
|
|
params.require(:exclude)
|
|
|
|
params.require(:order)
|
|
|
|
|
|
|
|
user_destroyer = UserDestroyer.new(current_user)
|
2017-11-22 22:43:54 +08:00
|
|
|
options = {
|
|
|
|
delete_posts: true,
|
|
|
|
block_email: true,
|
|
|
|
block_urls: true,
|
|
|
|
block_ip: true,
|
|
|
|
delete_as_spammer: true,
|
|
|
|
context: I18n.t("user.destroy_reasons.same_ip_address", ip_address: params[:ip])
|
|
|
|
}
|
2014-11-21 02:59:20 +08:00
|
|
|
|
2014-11-25 02:34:04 +08:00
|
|
|
AdminUserIndexQuery.new(params).find_users(50).each do |user|
|
2018-03-28 16:20:08 +08:00
|
|
|
user_destroyer.destroy(user, options)
|
2014-11-21 02:59:20 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
render json: success_json
|
|
|
|
end
|
|
|
|
|
2014-11-25 02:34:04 +08:00
|
|
|
def total_other_accounts_with_same_ip
|
|
|
|
params.require(:ip)
|
|
|
|
params.require(:exclude)
|
|
|
|
params.require(:order)
|
|
|
|
|
|
|
|
render json: { total: AdminUserIndexQuery.new(params).count_users }
|
|
|
|
end
|
|
|
|
|
2015-03-07 05:44:54 +08:00
|
|
|
def anonymize
|
|
|
|
guardian.ensure_can_anonymize_user!(@user)
|
2020-12-16 04:48:16 +08:00
|
|
|
opts = {}
|
|
|
|
opts[:anonymize_ip] = params[:anonymize_ip] if params[:anonymize_ip].present?
|
|
|
|
|
|
|
|
if user = UserAnonymizer.new(@user, current_user, opts).make_anonymous
|
2015-03-07 05:44:54 +08:00
|
|
|
render json: success_json.merge(username: user.username)
|
|
|
|
else
|
|
|
|
render json: failed_json.merge(user: AdminDetailedUserSerializer.new(user, root: false).as_json)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-04-22 16:37:51 +08:00
|
|
|
def merge
|
|
|
|
target_username = params.require(:target_username)
|
|
|
|
target_user = User.find_by_username(target_username)
|
2020-04-30 23:29:33 +08:00
|
|
|
raise Discourse::NotFound if target_user.blank?
|
2020-04-22 16:37:51 +08:00
|
|
|
|
2020-04-22 20:12:09 +08:00
|
|
|
guardian.ensure_can_merge_users!(@user, target_user)
|
2020-04-22 16:37:51 +08:00
|
|
|
|
2020-12-10 12:52:08 +08:00
|
|
|
Jobs.enqueue(:merge_user, user_id: @user.id, target_user_id: target_user.id, current_user_id: current_user.id)
|
|
|
|
render json: success_json
|
2020-04-22 16:37:51 +08:00
|
|
|
end
|
|
|
|
|
2016-05-07 01:34:33 +08:00
|
|
|
def reset_bounce_score
|
|
|
|
guardian.ensure_can_reset_bounce_score!(@user)
|
2017-02-20 17:37:01 +08:00
|
|
|
@user.user_stat&.reset_bounce_score!
|
2016-05-07 01:34:33 +08:00
|
|
|
render json: success_json
|
|
|
|
end
|
|
|
|
|
2020-09-15 22:00:10 +08:00
|
|
|
def sso_record
|
|
|
|
guardian.ensure_can_delete_sso_record!(@user)
|
|
|
|
@user.single_sign_on_record.destroy!
|
|
|
|
render json: success_json
|
|
|
|
end
|
|
|
|
|
2013-05-31 23:41:40 +08:00
|
|
|
private
|
|
|
|
|
2018-01-31 05:31:29 +08:00
|
|
|
def perform_post_action
|
|
|
|
return unless params[:post_id].present? &&
|
|
|
|
params[:post_action].present?
|
2018-06-07 13:28:18 +08:00
|
|
|
|
2018-01-31 05:31:29 +08:00
|
|
|
if post = Post.where(id: params[:post_id]).first
|
|
|
|
case params[:post_action]
|
|
|
|
when 'delete'
|
2019-05-31 04:42:59 +08:00
|
|
|
PostDestroyer.new(current_user, post).destroy if guardian.can_delete_post_or_topic?(post)
|
2019-05-28 00:27:16 +08:00
|
|
|
when "delete_replies"
|
2019-05-31 04:42:59 +08:00
|
|
|
PostDestroyer.delete_with_replies(current_user, post) if guardian.can_delete_post_or_topic?(post)
|
2018-01-31 05:31:29 +08:00
|
|
|
when 'edit'
|
|
|
|
revisor = PostRevisor.new(post)
|
2018-06-07 13:28:18 +08:00
|
|
|
|
2018-01-31 05:31:29 +08:00
|
|
|
# Take what the moderator edited in as gospel
|
|
|
|
revisor.revise!(
|
|
|
|
current_user,
|
|
|
|
{ raw: params[:post_edit] },
|
2018-03-13 01:49:52 +08:00
|
|
|
skip_validations: true,
|
|
|
|
skip_revision: true
|
2018-01-31 05:31:29 +08:00
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
2018-06-07 13:28:18 +08:00
|
|
|
end
|
2018-01-31 05:31:29 +08:00
|
|
|
|
2013-05-31 23:41:40 +08:00
|
|
|
def fetch_user
|
2014-05-06 21:41:59 +08:00
|
|
|
@user = User.find_by(id: params[:user_id])
|
2018-12-15 08:01:35 +08:00
|
|
|
raise Discourse::NotFound unless @user
|
2013-05-31 23:41:40 +08:00
|
|
|
end
|
|
|
|
|
2014-04-29 01:46:28 +08:00
|
|
|
def refresh_browser(user)
|
2015-05-04 10:21:00 +08:00
|
|
|
MessageBus.publish "/file-change", ["refresh"], user_ids: [user.id]
|
2014-04-29 01:46:28 +08:00
|
|
|
end
|
|
|
|
|
2013-04-12 04:04:20 +08:00
|
|
|
end
|