diff --git a/.streerc b/.streerc
index fd138211ec6..cc0be494538 100644
--- a/.streerc
+++ b/.streerc
@@ -1,3 +1,2 @@
--print-width=100
--plugins=plugin/trailing_comma,disable_ternary
---ignore-files=app/*
diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb
index 3f3f9e15a36..ba5d59879e1 100644
--- a/app/controllers/about_controller.rb
+++ b/app/controllers/about_controller.rb
@@ -1,30 +1,28 @@
# frozen_string_literal: true
class AboutController < ApplicationController
-
requires_login only: [:live_post_counts]
skip_before_action :check_xhr, only: [:index]
def index
- return redirect_to path('/login') if SiteSetting.login_required? && current_user.nil?
+ return redirect_to path("/login") if SiteSetting.login_required? && current_user.nil?
@about = About.new(current_user)
@title = "#{I18n.t("js.about.simple_title")} - #{SiteSetting.title}"
respond_to do |format|
- format.html do
- render :index
- end
- format.json do
- render_json_dump(AboutSerializer.new(@about, scope: guardian))
- end
+ format.html { render :index }
+ format.json { render_json_dump(AboutSerializer.new(@about, scope: guardian)) }
end
end
def live_post_counts
- RateLimiter.new(current_user, "live_post_counts", 1, 10.minutes).performed! unless current_user.staff?
+ unless current_user.staff?
+ RateLimiter.new(current_user, "live_post_counts", 1, 10.minutes).performed!
+ end
category_topic_ids = Category.pluck(:topic_id).compact!
- public_topics = Topic.listable_topics.visible.secured(Guardian.new(nil)).where.not(id: category_topic_ids)
+ public_topics =
+ Topic.listable_topics.visible.secured(Guardian.new(nil)).where.not(id: category_topic_ids)
stats = { public_topic_count: public_topics.count }
stats[:public_post_count] = public_topics.sum(:posts_count) - stats[:public_topic_count]
render json: stats
diff --git a/app/controllers/admin/admin_controller.rb b/app/controllers/admin/admin_controller.rb
index d9b1d705d97..2220a511e77 100644
--- a/app/controllers/admin/admin_controller.rb
+++ b/app/controllers/admin/admin_controller.rb
@@ -7,5 +7,4 @@ class Admin::AdminController < ApplicationController
def index
render body: nil
end
-
end
diff --git a/app/controllers/admin/api_controller.rb b/app/controllers/admin/api_controller.rb
index 627c4c40093..49b8a70414e 100644
--- a/app/controllers/admin/api_controller.rb
+++ b/app/controllers/admin/api_controller.rb
@@ -8,40 +8,40 @@ class Admin::ApiController < Admin::AdminController
offset = (params[:offset] || 0).to_i
limit = (params[:limit] || 50).to_i.clamp(1, 50)
- keys = ApiKey
- .where(hidden: false)
- .includes(:user, :api_key_scopes)
- # Sort revoked keys by revoked_at and active keys by created_at
- .order("revoked_at DESC NULLS FIRST, created_at DESC")
- .offset(offset)
- .limit(limit)
+ keys =
+ ApiKey
+ .where(hidden: false)
+ .includes(:user, :api_key_scopes)
+ # Sort revoked keys by revoked_at and active keys by created_at
+ .order("revoked_at DESC NULLS FIRST, created_at DESC")
+ .offset(offset)
+ .limit(limit)
- render_json_dump(
- keys: serialize_data(keys, ApiKeySerializer),
- offset: offset,
- limit: limit
- )
+ render_json_dump(keys: serialize_data(keys, ApiKeySerializer), offset: offset, limit: limit)
end
def show
api_key = ApiKey.includes(:api_key_scopes).find_by!(id: params[:id])
- render_serialized(api_key, ApiKeySerializer, root: 'key')
+ render_serialized(api_key, ApiKeySerializer, root: "key")
end
def scopes
- scopes = ApiKeyScope.scope_mappings.reduce({}) do |memo, (resource, actions)|
- memo.tap do |m|
- m[resource] = actions.map do |k, v|
- {
- scope_id: "#{resource}:#{k}",
- key: k,
- name: k.to_s.gsub('_', ' '),
- params: v[:params],
- urls: v[:urls]
- }
+ scopes =
+ ApiKeyScope
+ .scope_mappings
+ .reduce({}) do |memo, (resource, actions)|
+ memo.tap do |m|
+ m[resource] = actions.map do |k, v|
+ {
+ scope_id: "#{resource}:#{k}",
+ key: k,
+ name: k.to_s.gsub("_", " "),
+ params: v[:params],
+ urls: v[:urls],
+ }
+ end
+ end
end
- end
- end
render json: { scopes: scopes }
end
@@ -52,7 +52,7 @@ class Admin::ApiController < Admin::AdminController
api_key.update!(update_params)
log_api_key(api_key, UserHistory.actions[:api_key_update], changes: api_key.saved_changes)
end
- render_serialized(api_key, ApiKeySerializer, root: 'key')
+ render_serialized(api_key, ApiKeySerializer, root: "key")
end
def destroy
@@ -76,7 +76,7 @@ class Admin::ApiController < Admin::AdminController
api_key.save!
log_api_key(api_key, UserHistory.actions[:api_key_create], changes: api_key.saved_changes)
end
- render_serialized(api_key, ApiKeySerializer, root: 'key')
+ render_serialized(api_key, ApiKeySerializer, root: "key")
end
def undo_revoke_key
@@ -105,7 +105,7 @@ class Admin::ApiController < Admin::AdminController
def build_scopes
params.require(:key)[:scopes].to_a.map do |scope_params|
- resource, action = scope_params[:scope_id].split(':')
+ resource, action = scope_params[:scope_id].split(":")
mapping = ApiKeyScope.scope_mappings.dig(resource.to_sym, action.to_sym)
raise Discourse::InvalidParameters if mapping.nil? # invalid mapping
@@ -113,7 +113,7 @@ class Admin::ApiController < Admin::AdminController
ApiKeyScope.new(
resource: resource,
action: action,
- allowed_parameters: build_params(scope_params, mapping[:params])
+ allowed_parameters: build_params(scope_params, mapping[:params]),
)
end
end
@@ -121,11 +121,13 @@ class Admin::ApiController < Admin::AdminController
def build_params(scope_params, params)
return if params.nil?
- scope_params.slice(*params).tap do |allowed_params|
- allowed_params.each do |k, v|
- v.blank? ? allowed_params.delete(k) : allowed_params[k] = v.split(',')
+ scope_params
+ .slice(*params)
+ .tap do |allowed_params|
+ allowed_params.each do |k, v|
+ v.blank? ? allowed_params.delete(k) : allowed_params[k] = v.split(",")
+ end
end
- end
end
def update_params
@@ -146,5 +148,4 @@ class Admin::ApiController < Admin::AdminController
def log_api_key_restore(*args)
StaffActionLogger.new(current_user).log_api_key_restore(*args)
end
-
end
diff --git a/app/controllers/admin/backups_controller.rb b/app/controllers/admin/backups_controller.rb
index 64dfeb0ee48..2660c9895e8 100644
--- a/app/controllers/admin/backups_controller.rb
+++ b/app/controllers/admin/backups_controller.rb
@@ -7,7 +7,7 @@ class Admin::BackupsController < Admin::AdminController
include ExternalUploadHelpers
before_action :ensure_backups_enabled
- skip_before_action :check_xhr, only: [:index, :show, :logs, :check_backup_chunk, :upload_backup_chunk]
+ skip_before_action :check_xhr, only: %i[index show logs check_backup_chunk upload_backup_chunk]
def index
respond_to do |format|
@@ -62,7 +62,7 @@ class Admin::BackupsController < Admin::AdminController
Jobs.enqueue(
:download_backup_email,
user_id: current_user.id,
- backup_file_path: url_for(controller: 'backups', action: 'show')
+ backup_file_path: url_for(controller: "backups", action: "show"),
)
render body: nil
@@ -73,8 +73,8 @@ class Admin::BackupsController < Admin::AdminController
def show
if !EmailBackupToken.compare(current_user.id, params.fetch(:token))
- @error = I18n.t('download_backup_mailer.no_token')
- return render layout: 'no_ember', status: 422, formats: [:html]
+ @error = I18n.t("download_backup_mailer.no_token")
+ return render layout: "no_ember", status: 422, formats: [:html]
end
store = BackupRestore::BackupStore.create
@@ -86,7 +86,7 @@ class Admin::BackupsController < Admin::AdminController
if store.remote?
redirect_to backup.source
else
- headers['Content-Length'] = File.size(backup.source).to_s
+ headers["Content-Length"] = File.size(backup.source).to_s
send_file backup.source
end
else
@@ -170,9 +170,15 @@ class Admin::BackupsController < Admin::AdminController
identifier = params.fetch(:resumableIdentifier)
raise Discourse::InvalidParameters.new(:resumableIdentifier) unless valid_filename?(identifier)
- return render status: 415, plain: I18n.t("backup.backup_file_should_be_tar_gz") unless valid_extension?(filename)
- return render status: 415, plain: I18n.t("backup.not_enough_space_on_disk") unless has_enough_space_on_disk?(total_size)
- return render status: 415, plain: I18n.t("backup.invalid_filename") unless valid_filename?(filename)
+ unless valid_extension?(filename)
+ return render status: 415, plain: I18n.t("backup.backup_file_should_be_tar_gz")
+ end
+ unless has_enough_space_on_disk?(total_size)
+ return render status: 415, plain: I18n.t("backup.not_enough_space_on_disk")
+ end
+ unless valid_filename?(filename)
+ return render status: 415, plain: I18n.t("backup.invalid_filename")
+ end
file = params.fetch(:file)
chunk_number = params.fetch(:resumableChunkNumber).to_i
@@ -187,7 +193,13 @@ class Admin::BackupsController < Admin::AdminController
uploaded_file_size = previous_chunk_number * chunk_size
if uploaded_file_size + current_chunk_size >= total_size
# merge all the chunks in a background thread
- Jobs.enqueue_in(5.seconds, :backup_chunks_merger, filename: filename, identifier: identifier, chunks: chunk_number)
+ Jobs.enqueue_in(
+ 5.seconds,
+ :backup_chunks_merger,
+ filename: filename,
+ identifier: identifier,
+ chunks: chunk_number,
+ )
end
render body: nil
@@ -197,7 +209,9 @@ class Admin::BackupsController < Admin::AdminController
params.require(:filename)
filename = params.fetch(:filename)
- return render_json_error(I18n.t("backup.backup_file_should_be_tar_gz")) unless valid_extension?(filename)
+ unless valid_extension?(filename)
+ return render_json_error(I18n.t("backup.backup_file_should_be_tar_gz"))
+ end
return render_json_error(I18n.t("backup.invalid_filename")) unless valid_filename?(filename)
store = BackupRestore::BackupStore.create
@@ -236,8 +250,16 @@ class Admin::BackupsController < Admin::AdminController
end
def validate_before_create_multipart(file_name:, file_size:, upload_type:)
- raise ExternalUploadHelpers::ExternalUploadValidationError.new(I18n.t("backup.backup_file_should_be_tar_gz")) unless valid_extension?(file_name)
- raise ExternalUploadHelpers::ExternalUploadValidationError.new(I18n.t("backup.invalid_filename")) unless valid_filename?(file_name)
+ unless valid_extension?(file_name)
+ raise ExternalUploadHelpers::ExternalUploadValidationError.new(
+ I18n.t("backup.backup_file_should_be_tar_gz"),
+ )
+ end
+ unless valid_filename?(file_name)
+ raise ExternalUploadHelpers::ExternalUploadValidationError.new(
+ I18n.t("backup.invalid_filename"),
+ )
+ end
end
def self.serialize_upload(_upload)
@@ -248,7 +270,11 @@ class Admin::BackupsController < Admin::AdminController
begin
yield
rescue BackupRestore::BackupStore::StorageError => err
- message = debug_upload_error(err, I18n.t("upload.create_multipart_failure", additional_detail: err.message))
+ message =
+ debug_upload_error(
+ err,
+ I18n.t("upload.create_multipart_failure", additional_detail: err.message),
+ )
raise ExternalUploadHelpers::ExternalUploadValidationError.new(message)
rescue BackupRestore::BackupStore::BackupFileExists
raise ExternalUploadHelpers::ExternalUploadValidationError.new(I18n.t("backup.file_exists"))
diff --git a/app/controllers/admin/badges_controller.rb b/app/controllers/admin/badges_controller.rb
index 6d278679e5f..4efb86cff89 100644
--- a/app/controllers/admin/badges_controller.rb
+++ b/app/controllers/admin/badges_controller.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'csv'
+require "csv"
class Admin::BadgesController < Admin::AdminController
MAX_CSV_LINES = 50_000
@@ -10,25 +10,29 @@ class Admin::BadgesController < Admin::AdminController
data = {
badge_types: BadgeType.all.order(:id).to_a,
badge_groupings: BadgeGrouping.all.order(:position).to_a,
- badges: Badge.includes(:badge_grouping)
- .includes(:badge_type, :image_upload)
- .references(:badge_grouping)
- .order('badge_groupings.position, badge_type_id, badges.name').to_a,
+ badges:
+ Badge
+ .includes(:badge_grouping)
+ .includes(:badge_type, :image_upload)
+ .references(:badge_grouping)
+ .order("badge_groupings.position, badge_type_id, badges.name")
+ .to_a,
protected_system_fields: Badge.protected_system_fields,
- triggers: Badge.trigger_hash
+ triggers: Badge.trigger_hash,
}
render_serialized(OpenStruct.new(data), AdminBadgesSerializer)
end
def preview
- unless SiteSetting.enable_badge_sql
- return render json: "preview not allowed", status: 403
- end
+ return render json: "preview not allowed", status: 403 unless SiteSetting.enable_badge_sql
- render json: BadgeGranter.preview(params[:sql],
- target_posts: params[:target_posts] == "true",
- explain: params[:explain] == "true",
- trigger: params[:trigger].to_i)
+ render json:
+ BadgeGranter.preview(
+ params[:sql],
+ target_posts: params[:target_posts] == "true",
+ explain: params[:explain] == "true",
+ trigger: params[:trigger].to_i,
+ )
end
def new
@@ -47,18 +51,21 @@ class Admin::BadgesController < Admin::AdminController
if !badge.enabled?
render_json_error(
- I18n.t('badges.mass_award.errors.badge_disabled', badge_name: badge.display_name),
- status: 422
+ I18n.t("badges.mass_award.errors.badge_disabled", badge_name: badge.display_name),
+ status: 422,
)
return
end
- replace_badge_owners = params[:replace_badge_owners] == 'true'
- ensure_users_have_badge_once = params[:grant_existing_holders] != 'true'
+ replace_badge_owners = params[:replace_badge_owners] == "true"
+ ensure_users_have_badge_once = params[:grant_existing_holders] != "true"
if !ensure_users_have_badge_once && !badge.multiple_grant?
render_json_error(
- I18n.t('badges.mass_award.errors.cant_grant_multiple_times', badge_name: badge.display_name),
- status: 422
+ I18n.t(
+ "badges.mass_award.errors.cant_grant_multiple_times",
+ badge_name: badge.display_name,
+ ),
+ status: 422,
)
return
end
@@ -72,7 +79,7 @@ class Admin::BadgesController < Admin::AdminController
line_number += 1
if line.present?
- if line.include?('@')
+ if line.include?("@")
emails << line
else
usernames << line
@@ -80,26 +87,35 @@ class Admin::BadgesController < Admin::AdminController
end
if emails.size + usernames.size > MAX_CSV_LINES
- return render_json_error I18n.t('badges.mass_award.errors.too_many_csv_entries', count: MAX_CSV_LINES), status: 400
+ return(
+ render_json_error I18n.t(
+ "badges.mass_award.errors.too_many_csv_entries",
+ count: MAX_CSV_LINES,
+ ),
+ status: 400
+ )
end
end
end
BadgeGranter.revoke_all(badge) if replace_badge_owners
- results = BadgeGranter.enqueue_mass_grant_for_users(
- badge,
- emails: emails,
- usernames: usernames,
- ensure_users_have_badge_once: ensure_users_have_badge_once
- )
+ results =
+ BadgeGranter.enqueue_mass_grant_for_users(
+ badge,
+ emails: emails,
+ usernames: usernames,
+ ensure_users_have_badge_once: ensure_users_have_badge_once,
+ )
render json: {
- unmatched_entries: results[:unmatched_entries].first(100),
- matched_users_count: results[:matched_users_count],
- unmatched_entries_count: results[:unmatched_entries_count]
- }, status: :ok
+ unmatched_entries: results[:unmatched_entries].first(100),
+ matched_users_count: results[:matched_users_count],
+ unmatched_entries_count: results[:unmatched_entries_count],
+ },
+ status: :ok
rescue CSV::MalformedCSVError
- render_json_error I18n.t('badges.mass_award.errors.invalid_csv', line_number: line_number), status: 400
+ render_json_error I18n.t("badges.mass_award.errors.invalid_csv", line_number: line_number),
+ status: 400
end
def badge_types
@@ -119,9 +135,7 @@ class Admin::BadgesController < Admin::AdminController
group.save
end
- badge_groupings.each do |g|
- g.destroy unless g.system? || ids.include?(g.id)
- end
+ badge_groupings.each { |g| g.destroy unless g.system? || ids.include?(g.id) }
badge_groupings = BadgeGrouping.all.order(:position).to_a
render_serialized(badge_groupings, BadgeGroupingSerializer, root: "badge_groupings")
@@ -173,21 +187,23 @@ class Admin::BadgesController < Admin::AdminController
def update_badge_from_params(badge, opts = {})
errors = []
Badge.transaction do
- allowed = Badge.column_names.map(&:to_sym)
- allowed -= [:id, :created_at, :updated_at, :grant_count]
+ allowed = Badge.column_names.map(&:to_sym)
+ allowed -= %i[id created_at updated_at grant_count]
allowed -= Badge.protected_system_fields if badge.system?
allowed -= [:query] unless SiteSetting.enable_badge_sql
params.permit(*allowed)
- allowed.each do |key|
- badge.public_send("#{key}=" , params[key]) if params[key]
- end
+ allowed.each { |key| badge.public_send("#{key}=", params[key]) if params[key] }
# Badge query contract checks
begin
if SiteSetting.enable_badge_sql
- BadgeGranter.contract_checks!(badge.query, target_posts: badge.target_posts, trigger: badge.trigger)
+ BadgeGranter.contract_checks!(
+ badge.query,
+ target_posts: badge.target_posts,
+ trigger: badge.trigger,
+ )
end
rescue => e
errors << e.message
@@ -203,7 +219,7 @@ class Admin::BadgesController < Admin::AdminController
:bulk_user_title_update,
new_title: badge.name,
granted_badge_id: badge.id,
- action: Jobs::BulkUserTitleUpdate::UPDATE_ACTION
+ action: Jobs::BulkUserTitleUpdate::UPDATE_ACTION,
)
end
diff --git a/app/controllers/admin/color_schemes_controller.rb b/app/controllers/admin/color_schemes_controller.rb
index 4b6407158ab..26a066477ce 100644
--- a/app/controllers/admin/color_schemes_controller.rb
+++ b/app/controllers/admin/color_schemes_controller.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: true
class Admin::ColorSchemesController < Admin::AdminController
-
- before_action :fetch_color_scheme, only: [:update, :destroy]
+ before_action :fetch_color_scheme, only: %i[update destroy]
def index
- render_serialized(ColorScheme.base_color_schemes + ColorScheme.order('id ASC').all.to_a, ColorSchemeSerializer)
+ render_serialized(
+ ColorScheme.base_color_schemes + ColorScheme.order("id ASC").all.to_a,
+ ColorSchemeSerializer,
+ )
end
def create
@@ -38,6 +40,8 @@ class Admin::ColorSchemesController < Admin::AdminController
end
def color_scheme_params
- params.permit(color_scheme: [:base_scheme_id, :name, :user_selectable, colors: [:name, :hex]])[:color_scheme]
+ params.permit(color_scheme: [:base_scheme_id, :name, :user_selectable, colors: %i[name hex]])[
+ :color_scheme
+ ]
end
end
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index 99f9fcff891..d2ed26665dd 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -11,9 +11,12 @@ class Admin::DashboardController < Admin::StaffController
render json: data
end
- def moderation; end
- def security; end
- def reports; end
+ def moderation
+ end
+ def security
+ end
+ def reports
+ end
def general
render json: AdminDashboardGeneralData.fetch_cached_stats
@@ -33,7 +36,7 @@ class Admin::DashboardController < Admin::StaffController
data = {
new_features: new_features,
has_unseen_features: DiscourseUpdates.has_unseen_features?(current_user.id),
- release_notes_link: AdminDashboardGeneralData.fetch_cached_stats["release_notes_link"]
+ release_notes_link: AdminDashboardGeneralData.fetch_cached_stats["release_notes_link"],
}
render json: data
end
diff --git a/app/controllers/admin/email_controller.rb b/app/controllers/admin/email_controller.rb
index b56f10f9f68..b165827f4d0 100644
--- a/app/controllers/admin/email_controller.rb
+++ b/app/controllers/admin/email_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Admin::EmailController < Admin::AdminController
-
def index
data = { delivery_method: delivery_method, settings: delivery_settings }
render_json_dump(data)
@@ -35,29 +34,22 @@ class Admin::EmailController < Admin::AdminController
else
email_logs.where(
"replace(post_reply_keys.reply_key::VARCHAR, '-', '') ILIKE ?",
- "%#{reply_key}%"
+ "%#{reply_key}%",
)
end
end
email_logs = email_logs.to_a
- tuples = email_logs.map do |email_log|
- [email_log.post_id, email_log.user_id]
- end
+ tuples = email_logs.map { |email_log| [email_log.post_id, email_log.user_id] }
reply_keys = {}
if tuples.present?
PostReplyKey
- .where(
- "(post_id,user_id) IN (#{(['(?)'] * tuples.size).join(', ')})",
- *tuples
- )
+ .where("(post_id,user_id) IN (#{(["(?)"] * tuples.size).join(", ")})", *tuples)
.pluck(:post_id, :user_id, "reply_key::text")
- .each do |post_id, user_id, key|
- reply_keys[[post_id, user_id]] = key
- end
+ .each { |post_id, user_id, key| reply_keys[[post_id, user_id]] = key }
end
render_serialized(email_logs, EmailLogSerializer, reply_keys: reply_keys)
@@ -96,14 +88,10 @@ class Admin::EmailController < Admin::AdminController
def advanced_test
params.require(:email)
- receiver = Email::Receiver.new(params['email'])
+ receiver = Email::Receiver.new(params["email"])
text, elided, format = receiver.select_body
- render json: success_json.merge!(
- text: text,
- elided: elided,
- format: format
- )
+ render json: success_json.merge!(text: text, elided: elided, format: format)
end
def send_digest
@@ -112,9 +100,8 @@ class Admin::EmailController < Admin::AdminController
params.require(:email)
user = User.find_by_username(params[:username])
- message, skip_reason = UserNotifications.public_send(:digest, user,
- since: params[:last_seen_at]
- )
+ message, skip_reason =
+ UserNotifications.public_send(:digest, user, since: params[:last_seen_at])
if message
message.to = params[:email]
@@ -134,9 +121,16 @@ class Admin::EmailController < Admin::AdminController
params.require(:to)
# These strings aren't localized; they are sent to an anonymous SMTP user.
if !User.with_email(Email.downcase(params[:from])).exists? && !SiteSetting.enable_staged_users
- render json: { reject: true, reason: "Mail from your address is not accepted. Do you have an account here?" }
+ render json: {
+ reject: true,
+ reason: "Mail from your address is not accepted. Do you have an account here?",
+ }
elsif Email::Receiver.check_address(Email.downcase(params[:to])).nil?
- render json: { reject: true, reason: "Mail to this address is not accepted. Check the address and try to send again?" }
+ render json: {
+ reject: true,
+ reason:
+ "Mail to this address is not accepted. Check the address and try to send again?",
+ }
else
render json: { reject: false }
end
@@ -157,10 +151,15 @@ class Admin::EmailController < Admin::AdminController
retry_count = 0
begin
- Jobs.enqueue(:process_email, mail: email_raw, retry_on_rate_limit: true, source: "handle_mail")
+ Jobs.enqueue(
+ :process_email,
+ mail: email_raw,
+ retry_on_rate_limit: true,
+ source: "handle_mail",
+ )
rescue JSON::GeneratorError, Encoding::UndefinedConversionError => e
if retry_count == 0
- email_raw = email_raw.force_encoding('iso-8859-1').encode("UTF-8")
+ email_raw = email_raw.force_encoding("iso-8859-1").encode("UTF-8")
retry_count += 1
retry
else
@@ -171,7 +170,8 @@ class Admin::EmailController < Admin::AdminController
# TODO: 2022-05-01 Remove this route once all sites have migrated over
# to using the new email_encoded param.
if deprecated_email_param_used
- render plain: "warning: the email parameter is deprecated. all POST requests to this route should be sent with a base64 strict encoded email_encoded parameter instead. email has been received and is queued for processing"
+ render plain:
+ "warning: the email parameter is deprecated. all POST requests to this route should be sent with a base64 strict encoded email_encoded parameter instead. email has been received and is queued for processing"
else
render plain: "email has been received and is queued for processing"
end
@@ -204,15 +204,15 @@ class Admin::EmailController < Admin::AdminController
end
if incoming_email.nil?
- email_local_part, email_domain = SiteSetting.notification_email.split('@')
+ email_local_part, email_domain = SiteSetting.notification_email.split("@")
bounced_to_address = "#{email_local_part}+verp-#{email_log.bounce_key}@#{email_domain}"
incoming_email = IncomingEmail.find_by(to_addresses: bounced_to_address)
end
# Temporary fix until all old format of emails has been purged via lib/email/cleaner.rb
if incoming_email.nil?
- email_local_part, email_domain = SiteSetting.reply_by_email_address.split('@')
- subdomain, root_domain, extension = email_domain&.split('.')
+ email_local_part, email_domain = SiteSetting.reply_by_email_address.split("@")
+ subdomain, root_domain, extension = email_domain&.split(".")
bounced_to_address = "#{subdomain}+verp-#{email_log.bounce_key}@#{root_domain}.#{extension}"
incoming_email = IncomingEmail.find_by(to_addresses: bounced_to_address)
end
@@ -231,41 +231,61 @@ class Admin::EmailController < Admin::AdminController
def filter_logs(logs, params)
table_name = logs.table_name
- logs = logs.includes(:user, post: :topic)
- .references(:user)
- .order(created_at: :desc)
- .offset(params[:offset] || 0)
- .limit(50)
+ logs =
+ logs
+ .includes(:user, post: :topic)
+ .references(:user)
+ .order(created_at: :desc)
+ .offset(params[:offset] || 0)
+ .limit(50)
logs = logs.where("users.username ILIKE ?", "%#{params[:user]}%") if params[:user].present?
- logs = logs.where("#{table_name}.to_address ILIKE ?", "%#{params[:address]}%") if params[:address].present?
- logs = logs.where("#{table_name}.email_type ILIKE ?", "%#{params[:type]}%") if params[:type].present?
+ logs = logs.where("#{table_name}.to_address ILIKE ?", "%#{params[:address]}%") if params[
+ :address
+ ].present?
+ logs = logs.where("#{table_name}.email_type ILIKE ?", "%#{params[:type]}%") if params[
+ :type
+ ].present?
if table_name == "email_logs" && params[:smtp_transaction_response].present?
- logs = logs.where("#{table_name}.smtp_transaction_response ILIKE ?", "%#{params[:smtp_transaction_response]}%")
+ logs =
+ logs.where(
+ "#{table_name}.smtp_transaction_response ILIKE ?",
+ "%#{params[:smtp_transaction_response]}%",
+ )
end
logs
end
def filter_incoming_emails(incoming_emails, params)
- incoming_emails = incoming_emails.includes(:user, post: :topic)
- .order(created_at: :desc)
- .offset(params[:offset] || 0)
- .limit(50)
+ incoming_emails =
+ incoming_emails
+ .includes(:user, post: :topic)
+ .order(created_at: :desc)
+ .offset(params[:offset] || 0)
+ .limit(50)
- incoming_emails = incoming_emails.where("from_address ILIKE ?", "%#{params[:from]}%") if params[:from].present?
- incoming_emails = incoming_emails.where("to_addresses ILIKE :to OR cc_addresses ILIKE :to", to: "%#{params[:to]}%") if params[:to].present?
- incoming_emails = incoming_emails.where("subject ILIKE ?", "%#{params[:subject]}%") if params[:subject].present?
- incoming_emails = incoming_emails.where("error ILIKE ?", "%#{params[:error]}%") if params[:error].present?
+ incoming_emails = incoming_emails.where("from_address ILIKE ?", "%#{params[:from]}%") if params[
+ :from
+ ].present?
+ incoming_emails =
+ incoming_emails.where(
+ "to_addresses ILIKE :to OR cc_addresses ILIKE :to",
+ to: "%#{params[:to]}%",
+ ) if params[:to].present?
+ incoming_emails = incoming_emails.where("subject ILIKE ?", "%#{params[:subject]}%") if params[
+ :subject
+ ].present?
+ incoming_emails = incoming_emails.where("error ILIKE ?", "%#{params[:error]}%") if params[
+ :error
+ ].present?
incoming_emails
end
def delivery_settings
- action_mailer_settings
- .reject { |k, _| k == :password }
- .map { |k, v| { name: k, value: v } }
+ action_mailer_settings.reject { |k, _| k == :password }.map { |k, v| { name: k, value: v } }
end
def delivery_method
diff --git a/app/controllers/admin/email_templates_controller.rb b/app/controllers/admin/email_templates_controller.rb
index 48fffe9483f..f1050e885c3 100644
--- a/app/controllers/admin/email_templates_controller.rb
+++ b/app/controllers/admin/email_templates_controller.rb
@@ -1,70 +1,69 @@
# frozen_string_literal: true
class Admin::EmailTemplatesController < Admin::AdminController
-
def self.email_keys
- @email_keys ||= [
- "custom_invite_forum_mailer",
- "custom_invite_mailer",
- "invite_forum_mailer",
- "invite_mailer",
- "invite_password_instructions",
- "new_version_mailer",
- "new_version_mailer_with_notes",
- "system_messages.backup_failed",
- "system_messages.backup_succeeded",
- "system_messages.bulk_invite_failed",
- "system_messages.bulk_invite_succeeded",
- "system_messages.csv_export_failed",
- "system_messages.csv_export_succeeded",
- "system_messages.download_remote_images_disabled",
- "system_messages.email_error_notification",
- "system_messages.email_reject_auto_generated",
- "system_messages.email_reject_bad_destination_address",
- "system_messages.email_reject_empty",
- "system_messages.email_reject_invalid_access",
- "system_messages.email_reject_parsing",
- "system_messages.email_reject_reply_key",
- "system_messages.email_reject_screened_email",
- "system_messages.email_reject_topic_closed",
- "system_messages.email_reject_topic_not_found",
- "system_messages.email_reject_unrecognized_error",
- "system_messages.email_reject_user_not_found",
- "system_messages.email_revoked",
- "system_messages.pending_users_reminder",
- "system_messages.post_hidden",
- "system_messages.post_hidden_again",
- "system_messages.queued_posts_reminder",
- "system_messages.restore_failed",
- "system_messages.restore_succeeded",
- "system_messages.silenced_by_staff",
- "system_messages.spam_post_blocked",
- "system_messages.too_many_spam_flags",
- "system_messages.unsilenced",
- "system_messages.user_automatically_silenced",
- "system_messages.welcome_invite",
- "system_messages.welcome_user",
- "system_messages.welcome_staff",
- "test_mailer",
- "user_notifications.account_created",
- "user_notifications.admin_login",
- "user_notifications.confirm_new_email",
- "user_notifications.email_login",
- "user_notifications.forgot_password",
- "user_notifications.notify_old_email",
- "user_notifications.set_password",
- "user_notifications.signup",
- "user_notifications.signup_after_approval",
- "user_notifications.suspicious_login",
- "user_notifications.user_invited_to_private_message_pm",
- "user_notifications.user_invited_to_private_message_pm_group",
- "user_notifications.user_invited_to_topic",
- "user_notifications.user_linked",
- "user_notifications.user_mentioned",
- "user_notifications.user_posted",
- "user_notifications.user_posted_pm",
- "user_notifications.user_quoted",
- "user_notifications.user_replied",
+ @email_keys ||= %w[
+ custom_invite_forum_mailer
+ custom_invite_mailer
+ invite_forum_mailer
+ invite_mailer
+ invite_password_instructions
+ new_version_mailer
+ new_version_mailer_with_notes
+ system_messages.backup_failed
+ system_messages.backup_succeeded
+ system_messages.bulk_invite_failed
+ system_messages.bulk_invite_succeeded
+ system_messages.csv_export_failed
+ system_messages.csv_export_succeeded
+ system_messages.download_remote_images_disabled
+ system_messages.email_error_notification
+ system_messages.email_reject_auto_generated
+ system_messages.email_reject_bad_destination_address
+ system_messages.email_reject_empty
+ system_messages.email_reject_invalid_access
+ system_messages.email_reject_parsing
+ system_messages.email_reject_reply_key
+ system_messages.email_reject_screened_email
+ system_messages.email_reject_topic_closed
+ system_messages.email_reject_topic_not_found
+ system_messages.email_reject_unrecognized_error
+ system_messages.email_reject_user_not_found
+ system_messages.email_revoked
+ system_messages.pending_users_reminder
+ system_messages.post_hidden
+ system_messages.post_hidden_again
+ system_messages.queued_posts_reminder
+ system_messages.restore_failed
+ system_messages.restore_succeeded
+ system_messages.silenced_by_staff
+ system_messages.spam_post_blocked
+ system_messages.too_many_spam_flags
+ system_messages.unsilenced
+ system_messages.user_automatically_silenced
+ system_messages.welcome_invite
+ system_messages.welcome_user
+ system_messages.welcome_staff
+ test_mailer
+ user_notifications.account_created
+ user_notifications.admin_login
+ user_notifications.confirm_new_email
+ user_notifications.email_login
+ user_notifications.forgot_password
+ user_notifications.notify_old_email
+ user_notifications.set_password
+ user_notifications.signup
+ user_notifications.signup_after_approval
+ user_notifications.suspicious_login
+ user_notifications.user_invited_to_private_message_pm
+ user_notifications.user_invited_to_private_message_pm_group
+ user_notifications.user_invited_to_topic
+ user_notifications.user_linked
+ user_notifications.user_mentioned
+ user_notifications.user_posted
+ user_notifications.user_posted_pm
+ user_notifications.user_quoted
+ user_notifications.user_replied
]
end
@@ -91,9 +90,18 @@ class Admin::EmailTemplatesController < Admin::AdminController
log_site_text_change(subject_result)
log_site_text_change(body_result)
- render_serialized(key, AdminEmailTemplateSerializer, root: 'email_template', rest_serializer: true)
+ render_serialized(
+ key,
+ AdminEmailTemplateSerializer,
+ root: "email_template",
+ rest_serializer: true,
+ )
else
- TranslationOverride.upsert!(I18n.locale, "#{key}.subject_template", subject_result[:old_value])
+ TranslationOverride.upsert!(
+ I18n.locale,
+ "#{key}.subject_template",
+ subject_result[:old_value],
+ )
TranslationOverride.upsert!(I18n.locale, "#{key}.text_body_template", body_result[:old_value])
render_json_error(error_messages)
@@ -105,11 +113,22 @@ class Admin::EmailTemplatesController < Admin::AdminController
raise Discourse::NotFound unless self.class.email_keys.include?(params[:id])
revert_and_log("#{key}.subject_template", "#{key}.text_body_template")
- render_serialized(key, AdminEmailTemplateSerializer, root: 'email_template', rest_serializer: true)
+ render_serialized(
+ key,
+ AdminEmailTemplateSerializer,
+ root: "email_template",
+ rest_serializer: true,
+ )
end
def index
- render_serialized(self.class.email_keys, AdminEmailTemplateSerializer, root: 'email_templates', rest_serializer: true, overridden_keys: overridden_keys)
+ render_serialized(
+ self.class.email_keys,
+ AdminEmailTemplateSerializer,
+ root: "email_templates",
+ rest_serializer: true,
+ overridden_keys: overridden_keys,
+ )
end
private
@@ -121,11 +140,7 @@ class Admin::EmailTemplatesController < Admin::AdminController
translation_override = TranslationOverride.upsert!(I18n.locale, key, value)
end
- {
- key: key,
- old_value: old_value,
- error_messages: translation_override&.errors&.full_messages
- }
+ { key: key, old_value: old_value, error_messages: translation_override&.errors&.full_messages }
end
def revert_and_log(*keys)
@@ -144,7 +159,10 @@ class Admin::EmailTemplatesController < Admin::AdminController
def log_site_text_change(update_result)
new_value = I18n.t(update_result[:key])
StaffActionLogger.new(current_user).log_site_text_change(
- update_result[:key], new_value, update_result[:old_value])
+ update_result[:key],
+ new_value,
+ update_result[:old_value],
+ )
end
def format_error_message(update_result, attribute_key)
diff --git a/app/controllers/admin/embeddable_hosts_controller.rb b/app/controllers/admin/embeddable_hosts_controller.rb
index 765408039ce..96e08759af6 100644
--- a/app/controllers/admin/embeddable_hosts_controller.rb
+++ b/app/controllers/admin/embeddable_hosts_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Admin::EmbeddableHostsController < Admin::AdminController
-
def create
save_host(EmbeddableHost.new, :create)
end
@@ -14,7 +13,10 @@ class Admin::EmbeddableHostsController < Admin::AdminController
def destroy
host = EmbeddableHost.where(id: params[:id]).first
host.destroy
- StaffActionLogger.new(current_user).log_embeddable_host(host, UserHistory.actions[:embeddable_host_destroy])
+ StaffActionLogger.new(current_user).log_embeddable_host(
+ host,
+ UserHistory.actions[:embeddable_host_destroy],
+ )
render json: success_json
end
@@ -23,17 +25,25 @@ class Admin::EmbeddableHostsController < Admin::AdminController
def save_host(host, action)
host.host = params[:embeddable_host][:host]
host.allowed_paths = params[:embeddable_host][:allowed_paths]
- host.class_name = params[:embeddable_host][:class_name]
+ host.class_name = params[:embeddable_host][:class_name]
host.category_id = params[:embeddable_host][:category_id]
host.category_id = SiteSetting.uncategorized_category_id if host.category_id.blank?
if host.save
changes = host.saved_changes if action == :update
- StaffActionLogger.new(current_user).log_embeddable_host(host, UserHistory.actions[:"embeddable_host_#{action}"], changes: changes)
- render_serialized(host, EmbeddableHostSerializer, root: 'embeddable_host', rest_serializer: true)
+ StaffActionLogger.new(current_user).log_embeddable_host(
+ host,
+ UserHistory.actions[:"embeddable_host_#{action}"],
+ changes: changes,
+ )
+ render_serialized(
+ host,
+ EmbeddableHostSerializer,
+ root: "embeddable_host",
+ rest_serializer: true,
+ )
else
render_json_error(host)
end
end
-
end
diff --git a/app/controllers/admin/embedding_controller.rb b/app/controllers/admin/embedding_controller.rb
index c4540edd80b..51b0d48785e 100644
--- a/app/controllers/admin/embedding_controller.rb
+++ b/app/controllers/admin/embedding_controller.rb
@@ -1,25 +1,22 @@
# frozen_string_literal: true
class Admin::EmbeddingController < Admin::AdminController
-
before_action :fetch_embedding
def show
- render_serialized(@embedding, EmbeddingSerializer, root: 'embedding', rest_serializer: true)
+ render_serialized(@embedding, EmbeddingSerializer, root: "embedding", rest_serializer: true)
end
def update
if params[:embedding][:embed_by_username].blank?
- return render_json_error(I18n.t('site_settings.embed_username_required'))
+ return render_json_error(I18n.t("site_settings.embed_username_required"))
end
- Embedding.settings.each do |s|
- @embedding.public_send("#{s}=", params[:embedding][s])
- end
+ Embedding.settings.each { |s| @embedding.public_send("#{s}=", params[:embedding][s]) }
if @embedding.save
fetch_embedding
- render_serialized(@embedding, EmbeddingSerializer, root: 'embedding', rest_serializer: true)
+ render_serialized(@embedding, EmbeddingSerializer, root: "embedding", rest_serializer: true)
else
render_json_error(@embedding)
end
diff --git a/app/controllers/admin/emojis_controller.rb b/app/controllers/admin/emojis_controller.rb
index 486a06c666d..774506744d8 100644
--- a/app/controllers/admin/emojis_controller.rb
+++ b/app/controllers/admin/emojis_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Admin::EmojisController < Admin::AdminController
-
def index
render_serialized(Emoji.custom, EmojiSerializer, root: false)
end
@@ -17,15 +16,12 @@ class Admin::EmojisController < Admin::AdminController
hijack do
# fix the name
name = File.basename(name, ".*")
- name = name.gsub(/[^a-z0-9]+/i, '_')
- .gsub(/_{2,}/, '_')
- .downcase
+ name = name.gsub(/[^a-z0-9]+/i, "_").gsub(/_{2,}/, "_").downcase
- upload = UploadCreator.new(
- file.tempfile,
- file.original_filename,
- type: 'custom_emoji'
- ).create_for(current_user.id)
+ upload =
+ UploadCreator.new(file.tempfile, file.original_filename, type: "custom_emoji").create_for(
+ current_user.id,
+ )
good = true
@@ -61,5 +57,4 @@ class Admin::EmojisController < Admin::AdminController
render json: success_json
end
-
end
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 935931de224..4d9e581fd3c 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -7,27 +7,19 @@ class Admin::GroupsController < Admin::StaffController
attributes = group_params.to_h.except(:owner_usernames, :usernames)
group = Group.new(attributes)
- unless group_params[:allow_membership_requests]
- group.membership_request_template = nil
- end
+ group.membership_request_template = nil unless group_params[:allow_membership_requests]
if group_params[:owner_usernames].present?
- owner_ids = User.where(
- username: group_params[:owner_usernames].split(",")
- ).pluck(:id)
+ owner_ids = User.where(username: group_params[:owner_usernames].split(",")).pluck(:id)
- owner_ids.each do |user_id|
- group.group_users.build(user_id: user_id, owner: true)
- end
+ owner_ids.each { |user_id| group.group_users.build(user_id: user_id, owner: true) }
end
if group_params[:usernames].present?
user_ids = User.where(username: group_params[:usernames].split(",")).pluck(:id)
user_ids -= owner_ids if owner_ids
- user_ids.each do |user_id|
- group.group_users.build(user_id: user_id)
- end
+ user_ids.each { |user_id| group.group_users.build(user_id: user_id) }
end
if group.save
@@ -140,45 +132,43 @@ class Admin::GroupsController < Admin::StaffController
protected
def can_not_modify_automatic
- render_json_error(I18n.t('groups.errors.can_not_modify_automatic'))
+ render_json_error(I18n.t("groups.errors.can_not_modify_automatic"))
end
private
def group_params
- permitted = [
- :name,
- :mentionable_level,
- :messageable_level,
- :visibility_level,
- :members_visibility_level,
- :automatic_membership_email_domains,
- :title,
- :primary_group,
- :grant_trust_level,
- :incoming_email,
- :flair_icon,
- :flair_upload_id,
- :flair_bg_color,
- :flair_color,
- :bio_raw,
- :public_admission,
- :public_exit,
- :allow_membership_requests,
- :full_name,
- :default_notification_level,
- :membership_request_template,
- :owner_usernames,
- :usernames,
- :publish_read_state,
- :notify_users
+ permitted = %i[
+ name
+ mentionable_level
+ messageable_level
+ visibility_level
+ members_visibility_level
+ automatic_membership_email_domains
+ title
+ primary_group
+ grant_trust_level
+ incoming_email
+ flair_icon
+ flair_upload_id
+ flair_bg_color
+ flair_color
+ bio_raw
+ public_admission
+ public_exit
+ allow_membership_requests
+ full_name
+ default_notification_level
+ membership_request_template
+ owner_usernames
+ usernames
+ publish_read_state
+ notify_users
]
custom_fields = DiscoursePluginRegistry.editable_group_custom_fields
permitted << { custom_fields: custom_fields } unless custom_fields.blank?
- if guardian.can_associate_groups?
- permitted << { associated_group_ids: [] }
- end
+ permitted << { associated_group_ids: [] } if guardian.can_associate_groups?
permitted = permitted | DiscoursePluginRegistry.group_params
diff --git a/app/controllers/admin/impersonate_controller.rb b/app/controllers/admin/impersonate_controller.rb
index 8045f20d1e2..76df6b32d83 100644
--- a/app/controllers/admin/impersonate_controller.rb
+++ b/app/controllers/admin/impersonate_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Admin::ImpersonateController < Admin::AdminController
-
def create
params.require(:username_or_email)
@@ -18,5 +17,4 @@ class Admin::ImpersonateController < Admin::AdminController
render body: nil
end
-
end
diff --git a/app/controllers/admin/permalinks_controller.rb b/app/controllers/admin/permalinks_controller.rb
index 4e60a1ad010..54bea1f5280 100644
--- a/app/controllers/admin/permalinks_controller.rb
+++ b/app/controllers/admin/permalinks_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Admin::PermalinksController < Admin::AdminController
-
before_action :fetch_permalink, only: [:destroy]
def index
@@ -20,7 +19,8 @@ class Admin::PermalinksController < Admin::AdminController
params[:permalink_type_value] = Tag.find_by_name(params[:permalink_type_value])&.id
end
- permalink = Permalink.new(:url => params[:url], params[:permalink_type] => params[:permalink_type_value])
+ permalink =
+ Permalink.new(:url => params[:url], params[:permalink_type] => params[:permalink_type_value])
if permalink.save
render_serialized(permalink, PermalinkSerializer)
else
@@ -38,5 +38,4 @@ class Admin::PermalinksController < Admin::AdminController
def fetch_permalink
@permalink = Permalink.find(params[:id])
end
-
end
diff --git a/app/controllers/admin/plugins_controller.rb b/app/controllers/admin/plugins_controller.rb
index b9e4913cc9b..202019844b9 100644
--- a/app/controllers/admin/plugins_controller.rb
+++ b/app/controllers/admin/plugins_controller.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
class Admin::PluginsController < Admin::StaffController
-
def index
- render_serialized(Discourse.visible_plugins, AdminPluginSerializer, root: 'plugins')
+ render_serialized(Discourse.visible_plugins, AdminPluginSerializer, root: "plugins")
end
-
end
diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb
index 90e7c4de1fb..abc8b9e83e2 100644
--- a/app/controllers/admin/reports_controller.rb
+++ b/app/controllers/admin/reports_controller.rb
@@ -2,24 +2,28 @@
class Admin::ReportsController < Admin::StaffController
def index
- reports_methods = ['page_view_total_reqs'] +
- ApplicationRequest.req_types.keys
- .select { |r| r =~ /^page_view_/ && r !~ /mobile/ }
- .map { |r| r + "_reqs" } +
- Report.singleton_methods.grep(/^report_(?!about|storage_stats)/)
+ reports_methods =
+ ["page_view_total_reqs"] +
+ ApplicationRequest
+ .req_types
+ .keys
+ .select { |r| r =~ /^page_view_/ && r !~ /mobile/ }
+ .map { |r| r + "_reqs" } +
+ Report.singleton_methods.grep(/^report_(?!about|storage_stats)/)
- reports = reports_methods.map do |name|
- type = name.to_s.gsub('report_', '')
- description = I18n.t("reports.#{type}.description", default: '')
- description_link = I18n.t("reports.#{type}.description_link", default: '')
+ reports =
+ reports_methods.map do |name|
+ type = name.to_s.gsub("report_", "")
+ description = I18n.t("reports.#{type}.description", default: "")
+ description_link = I18n.t("reports.#{type}.description_link", default: "")
- {
- type: type,
- title: I18n.t("reports.#{type}.title"),
- description: description.presence ? description : nil,
- description_link: description_link.presence ? description_link : nil
- }
- end
+ {
+ type: type,
+ title: I18n.t("reports.#{type}.title"),
+ description: description.presence ? description : nil,
+ description_link: description_link.presence ? description_link : nil,
+ }
+ end
render_json_dump(reports: reports.sort_by { |report| report[:title] })
end
@@ -32,18 +36,14 @@ class Admin::ReportsController < Admin::StaffController
args = parse_params(report_params)
report = nil
- if (report_params[:cache])
- report = Report.find_cached(report_type, args)
- end
+ report = Report.find_cached(report_type, args) if (report_params[:cache])
if report
reports << report
else
report = Report.find(report_type, args)
- if (report_params[:cache]) && report
- Report.cache(report)
- end
+ Report.cache(report) if (report_params[:cache]) && report
if report.blank?
report = Report._get(report_type, args)
@@ -66,22 +66,16 @@ class Admin::ReportsController < Admin::StaffController
args = parse_params(params)
report = nil
- if (params[:cache])
- report = Report.find_cached(report_type, args)
- end
+ report = Report.find_cached(report_type, args) if (params[:cache])
- if report
- return render_json_dump(report: report)
- end
+ return render_json_dump(report: report) if report
hijack do
report = Report.find(report_type, args)
raise Discourse::NotFound if report.blank?
- if (params[:cache])
- Report.cache(report)
- end
+ Report.cache(report) if (params[:cache])
render_json_dump(report: report)
end
@@ -91,16 +85,28 @@ class Admin::ReportsController < Admin::StaffController
def parse_params(report_params)
begin
- start_date = (report_params[:start_date].present? ? Time.parse(report_params[:start_date]).to_date : 1.days.ago).beginning_of_day
- end_date = (report_params[:end_date].present? ? Time.parse(report_params[:end_date]).to_date : start_date + 30.days).end_of_day
+ start_date =
+ (
+ if report_params[:start_date].present?
+ Time.parse(report_params[:start_date]).to_date
+ else
+ 1.days.ago
+ end
+ ).beginning_of_day
+ end_date =
+ (
+ if report_params[:end_date].present?
+ Time.parse(report_params[:end_date]).to_date
+ else
+ start_date + 30.days
+ end
+ ).end_of_day
rescue ArgumentError => e
raise Discourse::InvalidParameters.new(e.message)
end
facets = nil
- if Array === report_params[:facets]
- facets = report_params[:facets].map { |s| s.to_s.to_sym }
- end
+ facets = report_params[:facets].map { |s| s.to_s.to_sym } if Array === report_params[:facets]
limit = nil
if report_params.has_key?(:limit) && report_params[:limit].to_i > 0
@@ -108,16 +114,8 @@ class Admin::ReportsController < Admin::StaffController
end
filters = nil
- if report_params.has_key?(:filters)
- filters = report_params[:filters]
- end
+ filters = report_params[:filters] if report_params.has_key?(:filters)
- {
- start_date: start_date,
- end_date: end_date,
- filters: filters,
- facets: facets,
- limit: limit
- }
+ { start_date: start_date, end_date: end_date, filters: filters, facets: facets, limit: limit }
end
end
diff --git a/app/controllers/admin/robots_txt_controller.rb b/app/controllers/admin/robots_txt_controller.rb
index b269a6c9ec0..d2912f06927 100644
--- a/app/controllers/admin/robots_txt_controller.rb
+++ b/app/controllers/admin/robots_txt_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Admin::RobotsTxtController < Admin::AdminController
-
def show
render json: { robots_txt: current_robots_txt, overridden: @overridden }
end
diff --git a/app/controllers/admin/screened_emails_controller.rb b/app/controllers/admin/screened_emails_controller.rb
index 0e2ccc91614..b8688a0998d 100644
--- a/app/controllers/admin/screened_emails_controller.rb
+++ b/app/controllers/admin/screened_emails_controller.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
class Admin::ScreenedEmailsController < Admin::StaffController
-
def index
- screened_emails = ScreenedEmail.limit(200).order('last_match_at desc').to_a
+ screened_emails = ScreenedEmail.limit(200).order("last_match_at desc").to_a
render_serialized(screened_emails, ScreenedEmailSerializer)
end
@@ -12,5 +11,4 @@ class Admin::ScreenedEmailsController < Admin::StaffController
screen.destroy!
render json: success_json
end
-
end
diff --git a/app/controllers/admin/screened_ip_addresses_controller.rb b/app/controllers/admin/screened_ip_addresses_controller.rb
index a270fb01937..27c50387d22 100644
--- a/app/controllers/admin/screened_ip_addresses_controller.rb
+++ b/app/controllers/admin/screened_ip_addresses_controller.rb
@@ -1,16 +1,19 @@
# frozen_string_literal: true
class Admin::ScreenedIpAddressesController < Admin::StaffController
-
- before_action :fetch_screened_ip_address, only: [:update, :destroy]
+ before_action :fetch_screened_ip_address, only: %i[update destroy]
def index
filter = params[:filter]
filter = IPAddr.handle_wildcards(filter)
screened_ip_addresses = ScreenedIpAddress
- screened_ip_addresses = screened_ip_addresses.where("cidr :filter >>= ip_address OR ip_address >>= cidr :filter", filter: filter) if filter.present?
- screened_ip_addresses = screened_ip_addresses.limit(200).order('match_count desc')
+ screened_ip_addresses =
+ screened_ip_addresses.where(
+ "cidr :filter >>= ip_address OR ip_address >>= cidr :filter",
+ filter: filter,
+ ) if filter.present?
+ screened_ip_addresses = screened_ip_addresses.limit(200).order("match_count desc")
begin
screened_ip_addresses = screened_ip_addresses.to_a
@@ -54,5 +57,4 @@ class Admin::ScreenedIpAddressesController < Admin::StaffController
def fetch_screened_ip_address
@screened_ip_address = ScreenedIpAddress.find(params[:id])
end
-
end
diff --git a/app/controllers/admin/screened_urls_controller.rb b/app/controllers/admin/screened_urls_controller.rb
index cedd7b0dfaf..20cc8a2d6a4 100644
--- a/app/controllers/admin/screened_urls_controller.rb
+++ b/app/controllers/admin/screened_urls_controller.rb
@@ -1,10 +1,15 @@
# frozen_string_literal: true
class Admin::ScreenedUrlsController < Admin::StaffController
-
def index
- screened_urls = ScreenedUrl.select("domain, sum(match_count) as match_count, max(last_match_at) as last_match_at, min(created_at) as created_at").group(:domain).order('last_match_at DESC').to_a
+ screened_urls =
+ ScreenedUrl
+ .select(
+ "domain, sum(match_count) as match_count, max(last_match_at) as last_match_at, min(created_at) as created_at",
+ )
+ .group(:domain)
+ .order("last_match_at DESC")
+ .to_a
render_serialized(screened_urls, GroupedScreenedUrlSerializer)
end
-
end
diff --git a/app/controllers/admin/search_logs_controller.rb b/app/controllers/admin/search_logs_controller.rb
index a36b77d2b78..bd15b9e3814 100644
--- a/app/controllers/admin/search_logs_controller.rb
+++ b/app/controllers/admin/search_logs_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Admin::SearchLogsController < Admin::StaffController
-
def index
period = params[:period] || "all"
search_type = params[:search_type] || "all"
@@ -22,5 +21,4 @@ class Admin::SearchLogsController < Admin::StaffController
details[:search_result] = serialize_data(result, GroupedSearchResultSerializer, result: result)
render_json_dump(term: details)
end
-
end
diff --git a/app/controllers/admin/site_settings_controller.rb b/app/controllers/admin/site_settings_controller.rb
index 4db8b72e43f..ad28e93af44 100644
--- a/app/controllers/admin/site_settings_controller.rb
+++ b/app/controllers/admin/site_settings_controller.rb
@@ -6,10 +6,7 @@ class Admin::SiteSettingsController < Admin::AdminController
end
def index
- render_json_dump(
- site_settings: SiteSetting.all_settings,
- diags: SiteSetting.diags
- )
+ render_json_dump(site_settings: SiteSetting.all_settings, diags: SiteSetting.diags)
end
def update
@@ -18,15 +15,17 @@ class Admin::SiteSettingsController < Admin::AdminController
value = params[id]
value.strip! if value.is_a?(String)
- new_setting_name = SiteSettings::DeprecatedSettings::SETTINGS.find do |old_name, new_name, override, _|
- if old_name == id
- if !override
- raise Discourse::InvalidParameters, "You cannot change this site setting because it is deprecated, use #{new_name} instead."
- end
+ new_setting_name =
+ SiteSettings::DeprecatedSettings::SETTINGS.find do |old_name, new_name, override, _|
+ if old_name == id
+ if !override
+ raise Discourse::InvalidParameters,
+ "You cannot change this site setting because it is deprecated, use #{new_name} instead."
+ end
- break new_name
+ break new_name
+ end
end
- end
id = new_setting_name if new_setting_name
@@ -36,9 +35,7 @@ class Admin::SiteSettingsController < Admin::AdminController
value = Upload.get_from_urls(value.split("|")).to_a
end
- if SiteSetting.type_supervisor.get_type(id) == :upload
- value = Upload.get_from_url(value) || ""
- end
+ value = Upload.get_from_url(value) || "" if SiteSetting.type_supervisor.get_type(id) == :upload
update_existing_users = params[:update_existing_user].present?
previous_value = value_or_default(SiteSetting.public_send(id)) if update_existing_users
@@ -68,22 +65,40 @@ class Admin::SiteSettingsController < Admin::AdminController
notification_level = category_notification_level(id)
categories_to_unwatch = previous_category_ids - new_category_ids
- CategoryUser.where(category_id: categories_to_unwatch, notification_level: notification_level).delete_all
+ CategoryUser.where(
+ category_id: categories_to_unwatch,
+ notification_level: notification_level,
+ ).delete_all
TopicUser
.joins(:topic)
- .where(notification_level: TopicUser.notification_levels[:watching],
- notifications_reason_id: TopicUser.notification_reasons[:auto_watch_category],
- topics: { category_id: categories_to_unwatch })
+ .where(
+ notification_level: TopicUser.notification_levels[:watching],
+ notifications_reason_id: TopicUser.notification_reasons[:auto_watch_category],
+ topics: {
+ category_id: categories_to_unwatch,
+ },
+ )
.update_all(notification_level: TopicUser.notification_levels[:regular])
(new_category_ids - previous_category_ids).each do |category_id|
skip_user_ids = CategoryUser.where(category_id: category_id).pluck(:user_id)
- User.real.where(staged: false).where.not(id: skip_user_ids).select(:id).find_in_batches do |users|
- category_users = []
- users.each { |user| category_users << { category_id: category_id, user_id: user.id, notification_level: notification_level } }
- CategoryUser.insert_all!(category_users)
- end
+ User
+ .real
+ .where(staged: false)
+ .where.not(id: skip_user_ids)
+ .select(:id)
+ .find_in_batches do |users|
+ category_users = []
+ users.each do |user|
+ category_users << {
+ category_id: category_id,
+ user_id: user.id,
+ notification_level: notification_level,
+ }
+ end
+ CategoryUser.insert_all!(category_users)
+ end
end
elsif id.start_with?("default_tags_")
previous_tag_ids = Tag.where(name: previous_value.split("|")).pluck(:id)
@@ -92,19 +107,40 @@ class Admin::SiteSettingsController < Admin::AdminController
notification_level = tag_notification_level(id)
- TagUser.where(tag_id: (previous_tag_ids - new_tag_ids), notification_level: notification_level).delete_all
+ TagUser.where(
+ tag_id: (previous_tag_ids - new_tag_ids),
+ notification_level: notification_level,
+ ).delete_all
(new_tag_ids - previous_tag_ids).each do |tag_id|
skip_user_ids = TagUser.where(tag_id: tag_id).pluck(:user_id)
- User.real.where(staged: false).where.not(id: skip_user_ids).select(:id).find_in_batches do |users|
- tag_users = []
- users.each { |user| tag_users << { tag_id: tag_id, user_id: user.id, notification_level: notification_level, created_at: now, updated_at: now } }
- TagUser.insert_all!(tag_users)
- end
+ User
+ .real
+ .where(staged: false)
+ .where.not(id: skip_user_ids)
+ .select(:id)
+ .find_in_batches do |users|
+ tag_users = []
+ users.each do |user|
+ tag_users << {
+ tag_id: tag_id,
+ user_id: user.id,
+ notification_level: notification_level,
+ created_at: now,
+ updated_at: now,
+ }
+ end
+ TagUser.insert_all!(tag_users)
+ end
end
elsif is_sidebar_default_setting?(id)
- Jobs.enqueue(:backfill_sidebar_site_settings, setting_name: id, previous_value: previous_value, new_value: new_value)
+ Jobs.enqueue(
+ :backfill_sidebar_site_settings,
+ setting_name: id,
+ previous_value: previous_value,
+ new_value: new_value,
+ )
end
end
@@ -135,15 +171,26 @@ class Admin::SiteSettingsController < Admin::AdminController
notification_level = category_notification_level(id)
- user_ids = CategoryUser.where(category_id: previous_category_ids - new_category_ids, notification_level: notification_level).distinct.pluck(:user_id)
- user_ids += User
- .real
- .joins("CROSS JOIN categories c")
- .joins("LEFT JOIN category_users cu ON users.id = cu.user_id AND c.id = cu.category_id")
- .where(staged: false)
- .where("c.id IN (?) AND cu.notification_level IS NULL", new_category_ids - previous_category_ids)
- .distinct
- .pluck("users.id")
+ user_ids =
+ CategoryUser
+ .where(
+ category_id: previous_category_ids - new_category_ids,
+ notification_level: notification_level,
+ )
+ .distinct
+ .pluck(:user_id)
+ user_ids +=
+ User
+ .real
+ .joins("CROSS JOIN categories c")
+ .joins("LEFT JOIN category_users cu ON users.id = cu.user_id AND c.id = cu.category_id")
+ .where(staged: false)
+ .where(
+ "c.id IN (?) AND cu.notification_level IS NULL",
+ new_category_ids - previous_category_ids,
+ )
+ .distinct
+ .pluck("users.id")
json[:user_count] = user_ids.uniq.count
elsif id.start_with?("default_tags_")
@@ -152,19 +199,28 @@ class Admin::SiteSettingsController < Admin::AdminController
notification_level = tag_notification_level(id)
- user_ids = TagUser.where(tag_id: previous_tag_ids - new_tag_ids, notification_level: notification_level).distinct.pluck(:user_id)
- user_ids += User
- .real
- .joins("CROSS JOIN tags t")
- .joins("LEFT JOIN tag_users tu ON users.id = tu.user_id AND t.id = tu.tag_id")
- .where(staged: false)
- .where("t.id IN (?) AND tu.notification_level IS NULL", new_tag_ids - previous_tag_ids)
- .distinct
- .pluck("users.id")
+ user_ids =
+ TagUser
+ .where(tag_id: previous_tag_ids - new_tag_ids, notification_level: notification_level)
+ .distinct
+ .pluck(:user_id)
+ user_ids +=
+ User
+ .real
+ .joins("CROSS JOIN tags t")
+ .joins("LEFT JOIN tag_users tu ON users.id = tu.user_id AND t.id = tu.tag_id")
+ .where(staged: false)
+ .where("t.id IN (?) AND tu.notification_level IS NULL", new_tag_ids - previous_tag_ids)
+ .distinct
+ .pluck("users.id")
json[:user_count] = user_ids.uniq.count
elsif is_sidebar_default_setting?(id)
- json[:user_count] = SidebarSiteSettingsBackfiller.new(id, previous_value: previous_value, new_value: new_value).number_of_users_to_backfill
+ json[:user_count] = SidebarSiteSettingsBackfiller.new(
+ id,
+ previous_value: previous_value,
+ new_value: new_value,
+ ).number_of_users_to_backfill
end
render json: json
@@ -173,7 +229,7 @@ class Admin::SiteSettingsController < Admin::AdminController
private
def is_sidebar_default_setting?(setting_name)
- %w{default_sidebar_categories default_sidebar_tags}.include?(setting_name.to_s)
+ %w[default_sidebar_categories default_sidebar_tags].include?(setting_name.to_s)
end
def user_options
@@ -198,7 +254,7 @@ class Admin::SiteSettingsController < Admin::AdminController
default_include_tl0_in_digests: "include_tl0_in_digests",
default_text_size: "text_size_key",
default_title_count_mode: "title_count_mode_key",
- default_hide_profile_and_presence: "hide_profile_and_presence"
+ default_hide_profile_and_presence: "hide_profile_and_presence",
}
end
diff --git a/app/controllers/admin/site_texts_controller.rb b/app/controllers/admin/site_texts_controller.rb
index a3ed9f7d607..041c59128c8 100644
--- a/app/controllers/admin/site_texts_controller.rb
+++ b/app/controllers/admin/site_texts_controller.rb
@@ -1,22 +1,25 @@
# frozen_string_literal: true
class Admin::SiteTextsController < Admin::AdminController
-
def self.preferred_keys
- ['system_messages.usage_tips.text_body_template',
- 'education.new-topic',
- 'education.new-reply',
- 'login_required.welcome_message']
+ %w[
+ system_messages.usage_tips.text_body_template
+ education.new-topic
+ education.new-reply
+ login_required.welcome_message
+ ]
end
def self.restricted_keys
- ['user_notifications.confirm_old_email.title',
- 'user_notifications.confirm_old_email.subject_template',
- 'user_notifications.confirm_old_email.text_body_template']
+ %w[
+ user_notifications.confirm_old_email.title
+ user_notifications.confirm_old_email.subject_template
+ user_notifications.confirm_old_email.text_body_template
+ ]
end
def index
- overridden = params[:overridden] == 'true'
+ overridden = params[:overridden] == "true"
extras = {}
query = params[:q] || ""
@@ -61,7 +64,7 @@ class Admin::SiteTextsController < Admin::AdminController
render_serialized(
results[first..last - 1],
SiteTextSerializer,
- root: 'site_texts',
+ root: "site_texts",
rest_serializer: true,
extras: extras,
overridden_keys: overridden,
@@ -71,7 +74,7 @@ class Admin::SiteTextsController < Admin::AdminController
def show
locale = fetch_locale(params[:locale])
site_text = find_site_text(locale)
- render_serialized(site_text, SiteTextSerializer, root: 'site_text', rest_serializer: true)
+ render_serialized(site_text, SiteTextSerializer, root: "site_text", rest_serializer: true)
end
def update
@@ -92,14 +95,14 @@ class Admin::SiteTextsController < Admin::AdminController
:bulk_user_title_update,
new_title: value,
granted_badge_id: system_badge_id,
- action: Jobs::BulkUserTitleUpdate::UPDATE_ACTION
+ action: Jobs::BulkUserTitleUpdate::UPDATE_ACTION,
)
end
- render_serialized(site_text, SiteTextSerializer, root: 'site_text', rest_serializer: true)
+ render_serialized(site_text, SiteTextSerializer, root: "site_text", rest_serializer: true)
else
- render json: failed_json.merge(
- message: translation_override.errors.full_messages.join("\n\n")
- ), status: 422
+ render json:
+ failed_json.merge(message: translation_override.errors.full_messages.join("\n\n")),
+ status: 422
end
end
@@ -118,31 +121,27 @@ class Admin::SiteTextsController < Admin::AdminController
Jobs.enqueue(
:bulk_user_title_update,
granted_badge_id: system_badge_id,
- action: Jobs::BulkUserTitleUpdate::RESET_ACTION
+ action: Jobs::BulkUserTitleUpdate::RESET_ACTION,
)
end
- render_serialized(site_text, SiteTextSerializer, root: 'site_text', rest_serializer: true)
+ render_serialized(site_text, SiteTextSerializer, root: "site_text", rest_serializer: true)
end
def get_reseed_options
render_json_dump(
categories: SeedData::Categories.with_default_locale.reseed_options,
- topics: SeedData::Topics.with_default_locale.reseed_options
+ topics: SeedData::Topics.with_default_locale.reseed_options,
)
end
def reseed
hijack do
if params[:category_ids].present?
- SeedData::Categories.with_default_locale.update(
- site_setting_names: params[:category_ids]
- )
+ SeedData::Categories.with_default_locale.update(site_setting_names: params[:category_ids])
end
if params[:topic_ids].present?
- SeedData::Topics.with_default_locale.update(
- site_setting_names: params[:topic_ids]
- )
+ SeedData::Topics.with_default_locale.update(site_setting_names: params[:topic_ids])
end
render json: success_json
@@ -152,8 +151,8 @@ class Admin::SiteTextsController < Admin::AdminController
protected
def is_badge_title?(id = "")
- badge_parts = id.split('.')
- badge_parts[0] == 'badges' && badge_parts[2] == 'name'
+ badge_parts = id.split(".")
+ badge_parts[0] == "badges" && badge_parts[2] == "name"
end
def record_for(key:, value: nil, locale:)
@@ -165,10 +164,15 @@ class Admin::SiteTextsController < Admin::AdminController
def find_site_text(locale)
if self.class.restricted_keys.include?(params[:id])
- raise Discourse::InvalidAccess.new(nil, nil, custom_message: 'email_template_cant_be_modified')
+ raise Discourse::InvalidAccess.new(
+ nil,
+ nil,
+ custom_message: "email_template_cant_be_modified",
+ )
end
- if I18n.exists?(params[:id], locale) || TranslationOverride.exists?(locale: locale, translation_key: params[:id])
+ if I18n.exists?(params[:id], locale) ||
+ TranslationOverride.exists?(locale: locale, translation_key: params[:id])
return record_for(key: params[:id], locale: locale)
end
@@ -182,9 +186,7 @@ class Admin::SiteTextsController < Admin::AdminController
def find_translations(query, overridden, locale)
translations = Hash.new { |hash, key| hash[key] = {} }
- search_results = I18n.with_locale(locale) do
- I18n.search(query, only_overridden: overridden)
- end
+ search_results = I18n.with_locale(locale) { I18n.search(query, only_overridden: overridden) }
search_results.each do |key, value|
if PLURALIZED_REGEX.match(key)
@@ -205,7 +207,9 @@ class Admin::SiteTextsController < Admin::AdminController
plural_value = plural[1]
results << record_for(
- key: "#{key}.#{plural_key}", value: plural_value, locale: plural.last
+ key: "#{key}.#{plural_key}",
+ value: plural_value,
+ locale: plural.last,
)
end
else
@@ -218,7 +222,7 @@ class Admin::SiteTextsController < Admin::AdminController
def fix_plural_keys(key, value, locale)
value = value.with_indifferent_access
- plural_keys = I18n.with_locale(locale) { I18n.t('i18n.plural.keys') }
+ plural_keys = I18n.with_locale(locale) { I18n.t("i18n.plural.keys") }
return value if value.keys.size == plural_keys.size && plural_keys.all? { |k| value.key?(k) }
fallback_value = I18n.t(key, locale: :en, default: {})
diff --git a/app/controllers/admin/staff_action_logs_controller.rb b/app/controllers/admin/staff_action_logs_controller.rb
index a01e38ca82e..69687294ca9 100644
--- a/app/controllers/admin/staff_action_logs_controller.rb
+++ b/app/controllers/admin/staff_action_logs_controller.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
class Admin::StaffActionLogsController < Admin::StaffController
-
def index
- filters = params.slice(*UserHistory.staff_filters + [:page, :limit])
+ filters = params.slice(*UserHistory.staff_filters + %i[page limit])
page = (params[:page] || 0).to_i
page_size = (params[:limit] || 200).to_i.clamp(1, 200)
@@ -20,8 +19,8 @@ class Admin::StaffActionLogsController < Admin::StaffController
total_rows_staff_action_logs: count,
load_more_staff_action_logs: admin_staff_action_logs_path(load_more_params),
extras: {
- user_history_actions: staff_available_actions
- }
+ user_history_actions: staff_available_actions,
+ },
)
end
@@ -37,16 +36,10 @@ class Admin::StaffActionLogsController < Admin::StaffController
output = +"
#{CGI.escapeHTML(cur&.dig("name").to_s)}
"
- diff_fields["name"] = {
- prev: prev&.dig("name").to_s,
- cur: cur&.dig("name").to_s,
- }
+ diff_fields["name"] = { prev: prev&.dig("name").to_s, cur: cur&.dig("name").to_s }
- ["default", "user_selectable"].each do |f|
- diff_fields[f] = {
- prev: (!!prev&.dig(f)).to_s,
- cur: (!!cur&.dig(f)).to_s
- }
+ %w[default user_selectable].each do |f|
+ diff_fields[f] = { prev: (!!prev&.dig(f)).to_s, cur: (!!cur&.dig(f)).to_s }
end
diff_fields["color scheme"] = {
@@ -54,10 +47,7 @@ class Admin::StaffActionLogsController < Admin::StaffController
cur: cur&.dig("color_scheme", "name").to_s,
}
- diff_fields["included themes"] = {
- prev: child_themes(prev),
- cur: child_themes(cur)
- }
+ diff_fields["included themes"] = { prev: child_themes(prev), cur: child_themes(cur) }
load_diff(diff_fields, :cur, cur)
load_diff(diff_fields, :prev, prev)
@@ -94,10 +84,7 @@ class Admin::StaffActionLogsController < Admin::StaffController
def staff_available_actions
UserHistory.staff_actions.sort.map do |name|
- {
- id: name,
- action_id: UserHistory.actions[name] || UserHistory.actions[:custom_staff],
- }
+ { id: name, action_id: UserHistory.actions[name] || UserHistory.actions[:custom_staff] }
end
end
end
diff --git a/app/controllers/admin/themes_controller.rb b/app/controllers/admin/themes_controller.rb
index a47f2016d77..bf8ebb27d94 100644
--- a/app/controllers/admin/themes_controller.rb
+++ b/app/controllers/admin/themes_controller.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'base64'
+require "base64"
class Admin::ThemesController < Admin::AdminController
-
- skip_before_action :check_xhr, only: [:show, :preview, :export]
+ skip_before_action :check_xhr, only: %i[show preview export]
before_action :ensure_admin
def preview
@@ -15,7 +14,6 @@ class Admin::ThemesController < Admin::AdminController
end
def upload_asset
-
ban_in_allowlist_mode!
path = params[:file].path
@@ -34,32 +32,30 @@ class Admin::ThemesController < Admin::AdminController
end
def generate_key_pair
- require 'sshkey'
+ require "sshkey"
k = SSHKey.generate
Discourse.redis.setex("ssh_key_#{k.ssh_public_key}", 1.hour, k.private_key)
render json: { public_key: k.ssh_public_key }
end
- THEME_CONTENT_TYPES ||= %w{
+ THEME_CONTENT_TYPES ||= %w[
application/gzip
application/x-gzip
application/x-zip-compressed
application/zip
- }
+ ]
def import
@theme = nil
if params[:theme] && params[:theme].content_type == "application/json"
-
ban_in_allowlist_mode!
# .dcstyle.json import. Deprecated, but still available to allow conversion
- json = JSON::parse(params[:theme].read)
- theme = json['theme']
+ json = JSON.parse(params[:theme].read)
+ theme = json["theme"]
@theme = Theme.new(name: theme["name"], user_id: theme_user.id, auto_update: false)
theme["theme_fields"]&.each do |field|
-
if field["raw_upload"]
begin
tmp = Tempfile.new
@@ -79,7 +75,7 @@ class Admin::ThemesController < Admin::AdminController
name: field["name"],
value: field["value"],
type_id: field["type_id"],
- upload_id: field["upload_id"]
+ upload_id: field["upload_id"],
)
end
@@ -93,17 +89,22 @@ class Admin::ThemesController < Admin::AdminController
begin
guardian.ensure_allowed_theme_repo_import!(remote.strip)
rescue Discourse::InvalidAccess
- render_json_error I18n.t("themes.import_error.not_allowed_theme", { repo: remote.strip }), status: :forbidden
+ render_json_error I18n.t("themes.import_error.not_allowed_theme", { repo: remote.strip }),
+ status: :forbidden
return
end
hijack do
begin
branch = params[:branch] ? params[:branch] : nil
- private_key = params[:public_key] ? Discourse.redis.get("ssh_key_#{params[:public_key]}") : nil
- return render_json_error I18n.t("themes.import_error.ssh_key_gone") if params[:public_key].present? && private_key.blank?
+ private_key =
+ params[:public_key] ? Discourse.redis.get("ssh_key_#{params[:public_key]}") : nil
+ if params[:public_key].present? && private_key.blank?
+ return render_json_error I18n.t("themes.import_error.ssh_key_gone")
+ end
- @theme = RemoteTheme.import_theme(remote, theme_user, private_key: private_key, branch: branch)
+ @theme =
+ RemoteTheme.import_theme(remote, theme_user, private_key: private_key, branch: branch)
render json: @theme, status: :created
rescue RemoteTheme::ImportError => e
if params[:force]
@@ -125,8 +126,8 @@ class Admin::ThemesController < Admin::AdminController
end
end
end
- elsif params[:bundle] || (params[:theme] && THEME_CONTENT_TYPES.include?(params[:theme].content_type))
-
+ elsif params[:bundle] ||
+ (params[:theme] && THEME_CONTENT_TYPES.include?(params[:theme].content_type))
ban_in_allowlist_mode!
# params[:bundle] used by theme CLI. params[:theme] used by admin UI
@@ -135,21 +136,23 @@ class Admin::ThemesController < Admin::AdminController
update_components = params[:components]
match_theme_by_name = !!params[:bundle] && !params.key?(:theme_id) # Old theme CLI behavior, match by name. Remove Jan 2020
begin
- @theme = RemoteTheme.update_zipped_theme(
- bundle.path,
- bundle.original_filename,
- match_theme: match_theme_by_name,
- user: theme_user,
- theme_id: theme_id,
- update_components: update_components
- )
+ @theme =
+ RemoteTheme.update_zipped_theme(
+ bundle.path,
+ bundle.original_filename,
+ match_theme: match_theme_by_name,
+ user: theme_user,
+ theme_id: theme_id,
+ update_components: update_components,
+ )
log_theme_change(nil, @theme)
render json: @theme, status: :created
rescue RemoteTheme::ImportError => e
render_json_error e.message
end
else
- render_json_error I18n.t("themes.import_error.unknown_file_type"), status: :unprocessable_entity
+ render_json_error I18n.t("themes.import_error.unknown_file_type"),
+ status: :unprocessable_entity
end
end
@@ -160,24 +163,25 @@ class Admin::ThemesController < Admin::AdminController
payload = {
themes: ActiveModel::ArraySerializer.new(@themes, each_serializer: ThemeSerializer),
extras: {
- color_schemes: ActiveModel::ArraySerializer.new(@color_schemes, each_serializer: ColorSchemeSerializer)
- }
+ color_schemes:
+ ActiveModel::ArraySerializer.new(@color_schemes, each_serializer: ColorSchemeSerializer),
+ },
}
- respond_to do |format|
- format.json { render json: payload }
- end
+ respond_to { |format| format.json { render json: payload } }
end
def create
-
ban_in_allowlist_mode!
- @theme = Theme.new(name: theme_params[:name],
- user_id: theme_user.id,
- user_selectable: theme_params[:user_selectable] || false,
- color_scheme_id: theme_params[:color_scheme_id],
- component: [true, "true"].include?(theme_params[:component]))
+ @theme =
+ Theme.new(
+ name: theme_params[:name],
+ user_id: theme_user.id,
+ user_selectable: theme_params[:user_selectable] || false,
+ color_scheme_id: theme_params[:color_scheme_id],
+ component: [true, "true"].include?(theme_params[:component]),
+ )
set_fields
respond_to do |format|
@@ -199,10 +203,8 @@ class Admin::ThemesController < Admin::AdminController
disables_component = [false, "false"].include?(theme_params[:enabled])
enables_component = [true, "true"].include?(theme_params[:enabled])
- [:name, :color_scheme_id, :user_selectable, :enabled, :auto_update].each do |field|
- if theme_params.key?(field)
- @theme.public_send("#{field}=", theme_params[field])
- end
+ %i[name color_scheme_id user_selectable enabled auto_update].each do |field|
+ @theme.public_send("#{field}=", theme_params[field]) if theme_params.key?(field)
end
if theme_params.key?(:child_theme_ids)
@@ -218,13 +220,9 @@ class Admin::ThemesController < Admin::AdminController
update_translations
handle_switch
- if params[:theme][:remote_check]
- @theme.remote_theme.update_remote_version
- end
+ @theme.remote_theme.update_remote_version if params[:theme][:remote_check]
- if params[:theme][:remote_update]
- @theme.remote_theme.update_from_remote
- end
+ @theme.remote_theme.update_from_remote if params[:theme][:remote_update]
respond_to do |format|
if @theme.save
@@ -245,7 +243,7 @@ class Admin::ThemesController < Admin::AdminController
error = I18n.t("themes.bad_color_scheme") if @theme.errors[:color_scheme].present?
error ||= I18n.t("themes.other_error")
- render json: { errors: [ error ] }, status: :unprocessable_entity
+ render json: { errors: [error] }, status: :unprocessable_entity
end
end
end
@@ -260,9 +258,7 @@ class Admin::ThemesController < Admin::AdminController
StaffActionLogger.new(current_user).log_theme_destroy(@theme)
@theme.destroy
- respond_to do |format|
- format.json { head :no_content }
- end
+ respond_to { |format| format.json { head :no_content } }
end
def show
@@ -279,10 +275,10 @@ class Admin::ThemesController < Admin::AdminController
exporter = ThemeStore::ZipExporter.new(@theme)
file_path = exporter.package_filename
- headers['Content-Length'] = File.size(file_path).to_s
+ headers["Content-Length"] = File.size(file_path).to_s
send_data File.read(file_path),
- filename: File.basename(file_path),
- content_type: "application/zip"
+ filename: File.basename(file_path),
+ content_type: "application/zip"
ensure
exporter.cleanup!
end
@@ -330,9 +326,7 @@ class Admin::ThemesController < Admin::AdminController
end
end
- Theme.where(id: expected).each do |theme|
- @theme.add_relative_theme!(kind, theme)
- end
+ Theme.where(id: expected).each { |theme| @theme.add_relative_theme!(kind, theme) }
end
def update_default_theme
@@ -361,11 +355,13 @@ class Admin::ThemesController < Admin::AdminController
:component,
:enabled,
:auto_update,
- settings: {},
- translations: {},
- theme_fields: [:name, :target, :value, :upload_id, :type_id],
+ settings: {
+ },
+ translations: {
+ },
+ theme_fields: %i[name target value upload_id type_id],
child_theme_ids: [],
- parent_theme_ids: []
+ parent_theme_ids: [],
)
end
end
@@ -382,7 +378,7 @@ class Admin::ThemesController < Admin::AdminController
name: field[:name],
value: field[:value],
type_id: field[:type_id],
- upload_id: field[:upload_id]
+ upload_id: field[:upload_id],
)
end
end
@@ -408,7 +404,12 @@ class Admin::ThemesController < Admin::AdminController
end
def log_theme_setting_change(setting_name, previous_value, new_value)
- StaffActionLogger.new(current_user).log_theme_setting_change(setting_name, previous_value, new_value, @theme)
+ StaffActionLogger.new(current_user).log_theme_setting_change(
+ setting_name,
+ previous_value,
+ new_value,
+ @theme,
+ )
end
def log_theme_component_disabled
@@ -422,10 +423,14 @@ class Admin::ThemesController < Admin::AdminController
def handle_switch
param = theme_params[:component]
if param.to_s == "false" && @theme.component?
- raise Discourse::InvalidParameters.new(:component) if @theme.id == SiteSetting.default_theme_id
+ if @theme.id == SiteSetting.default_theme_id
+ raise Discourse::InvalidParameters.new(:component)
+ end
@theme.switch_to_theme!
elsif param.to_s == "true" && !@theme.component?
- raise Discourse::InvalidParameters.new(:component) if @theme.id == SiteSetting.default_theme_id
+ if @theme.id == SiteSetting.default_theme_id
+ raise Discourse::InvalidParameters.new(:component)
+ end
@theme.switch_to_component!
end
end
diff --git a/app/controllers/admin/user_fields_controller.rb b/app/controllers/admin/user_fields_controller.rb
index 5d6cae243cd..b244867b7ae 100644
--- a/app/controllers/admin/user_fields_controller.rb
+++ b/app/controllers/admin/user_fields_controller.rb
@@ -1,9 +1,18 @@
# frozen_string_literal: true
class Admin::UserFieldsController < Admin::AdminController
-
def self.columns
- %i(name field_type editable description required show_on_profile show_on_user_card position searchable)
+ %i[
+ name
+ field_type
+ editable
+ description
+ required
+ show_on_profile
+ show_on_user_card
+ position
+ searchable
+ ]
end
def create
@@ -13,14 +22,12 @@ class Admin::UserFieldsController < Admin::AdminController
field.required = params[:user_field][:required] == "true"
update_options(field)
- json_result(field, serializer: UserFieldSerializer) do
- field.save
- end
+ json_result(field, serializer: UserFieldSerializer) { field.save }
end
def index
user_fields = UserField.all.includes(:user_field_options).order(:position)
- render_serialized(user_fields, UserFieldSerializer, root: 'user_fields')
+ render_serialized(user_fields, UserFieldSerializer, root: "user_fields")
end
def update
@@ -28,9 +35,7 @@ class Admin::UserFieldsController < Admin::AdminController
field = UserField.where(id: params.require(:id)).first
Admin::UserFieldsController.columns.each do |col|
- unless field_params[col].nil?
- field.public_send("#{col}=", field_params[col])
- end
+ field.public_send("#{col}=", field_params[col]) unless field_params[col].nil?
end
update_options(field)
@@ -38,7 +43,7 @@ class Admin::UserFieldsController < Admin::AdminController
if !field.show_on_profile && !field.show_on_user_card
DirectoryColumn.where(user_field_id: field.id).destroy_all
end
- render_serialized(field, UserFieldSerializer, root: 'user_field')
+ render_serialized(field, UserFieldSerializer, root: "user_field")
else
render_json_error(field)
end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 7d7526417de..45c8f9313cb 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -3,28 +3,31 @@
class Admin::UsersController < Admin::StaffController
MAX_SIMILAR_USERS = 10
- before_action :fetch_user, only: [:suspend,
- :unsuspend,
- :log_out,
- :revoke_admin,
- :revoke_moderation,
- :grant_moderation,
- :approve,
- :activate,
- :deactivate,
- :silence,
- :unsilence,
- :trust_level,
- :trust_level_lock,
- :add_group,
- :remove_group,
- :primary_group,
- :anonymize,
- :merge,
- :reset_bounce_score,
- :disable_second_factor,
- :delete_posts_batch,
- :sso_record]
+ before_action :fetch_user,
+ only: %i[
+ suspend
+ unsuspend
+ log_out
+ revoke_admin
+ revoke_moderation
+ grant_moderation
+ approve
+ activate
+ deactivate
+ silence
+ unsilence
+ trust_level
+ trust_level_lock
+ add_group
+ remove_group
+ primary_group
+ anonymize
+ merge
+ reset_bounce_score
+ disable_second_factor
+ delete_posts_batch
+ sso_record
+ ]
def index
users = ::AdminUserIndexQuery.new(params).find_users
@@ -42,9 +45,7 @@ class Admin::UsersController < Admin::StaffController
@user = User.find_by(id: params[:id])
raise Discourse::NotFound unless @user
- similar_users = User.real
- .where.not(id: @user.id)
- .where(ip_address: @user.ip_address)
+ similar_users = User.real.where.not(id: @user.id).where(ip_address: @user.ip_address)
render_serialized(
@user,
@@ -64,7 +65,6 @@ class Admin::UsersController < Admin::StaffController
# 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.
@@ -87,16 +87,19 @@ class Admin::UsersController < Admin::StaffController
DB.exec(
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)
+ 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
@@ -107,14 +110,21 @@ class Admin::UsersController < Admin::StaffController
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')
- )
+ 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
- params.require([:suspend_until, :reason])
+ params.require(%i[suspend_until reason])
all_users = [@user]
if Array === params[:other_user_ids]
@@ -133,12 +143,13 @@ class Admin::UsersController < Admin::StaffController
User.transaction do
user.save!
- user_history = StaffActionLogger.new(current_user).log_user_suspend(
- user,
- params[:reason],
- message: message,
- post_id: params[:post_id]
- )
+ user_history =
+ StaffActionLogger.new(current_user).log_user_suspend(
+ user,
+ params[:reason],
+ message: message,
+ post_id: params[:post_id],
+ )
end
user.logged_out
@@ -147,7 +158,7 @@ class Admin::UsersController < Admin::StaffController
:critical_user_email,
type: "account_suspended",
user_id: user.id,
- user_history_id: user_history.id
+ user_history_id: user_history.id,
)
end
@@ -159,7 +170,7 @@ class Admin::UsersController < Admin::StaffController
user_history: user_history,
post_id: params[:post_id],
suspended_till: params[:suspend_until],
- suspended_at: DateTime.now
+ suspended_at: DateTime.now,
)
end
@@ -171,8 +182,8 @@ class Admin::UsersController < Admin::StaffController
full_suspend_reason: user_history.try(:details),
suspended_till: @user.suspended_till,
suspended_at: @user.suspended_at,
- suspended_by: BasicUserSerializer.new(current_user, root: false).as_json
- }
+ suspended_by: BasicUserSerializer.new(current_user, root: false).as_json,
+ },
)
end
@@ -185,12 +196,7 @@ class Admin::UsersController < Admin::StaffController
DiscourseEvent.trigger(:user_unsuspended, user: @user)
- render_json_dump(
- suspension: {
- suspended_till: nil,
- suspended_at: nil
- }
- )
+ render_json_dump(suspension: { suspended_till: nil, suspended_at: nil })
end
def log_out
@@ -199,7 +205,7 @@ class Admin::UsersController < Admin::StaffController
@user.logged_out
render json: success_json
else
- render json: { error: I18n.t('admin_js.admin.users.id_not_found') }, status: 404
+ render json: { error: I18n.t("admin_js.admin.users.id_not_found") }, status: 404
end
end
@@ -237,7 +243,7 @@ class Admin::UsersController < Admin::StaffController
group = Group.find(params[:group_id].to_i)
raise Discourse::NotFound unless group
- return render_json_error(I18n.t('groups.errors.can_not_modify_automatic')) if group.automatic
+ return render_json_error(I18n.t("groups.errors.can_not_modify_automatic")) if group.automatic
guardian.ensure_can_edit!(group)
group.add(@user)
@@ -250,7 +256,7 @@ class Admin::UsersController < Admin::StaffController
group = Group.find(params[:group_id].to_i)
raise Discourse::NotFound unless group
- return render_json_error(I18n.t('groups.errors.can_not_modify_automatic')) if group.automatic
+ return render_json_error(I18n.t("groups.errors.can_not_modify_automatic")) if group.automatic
guardian.ensure_can_edit!(group)
if group.remove(@user)
@@ -266,9 +272,7 @@ class Admin::UsersController < Admin::StaffController
if group = Group.find(primary_group_id)
guardian.ensure_can_change_primary_group!(@user, group)
- if group.user_ids.include?(@user.id)
- @user.primary_group_id = primary_group_id
- end
+ @user.primary_group_id = primary_group_id if group.user_ids.include?(@user.id)
end
else
@user.primary_group_id = nil
@@ -304,9 +308,7 @@ class Admin::UsersController < Admin::StaffController
guardian.ensure_can_change_trust_level!(@user)
new_lock = params[:locked].to_s
- unless new_lock =~ /true|false/
- return render_json_error I18n.t('errors.invalid_boolean')
- end
+ return render_json_error I18n.t("errors.invalid_boolean") unless new_lock =~ /true|false/
@user.manual_locked_trust_level = (new_lock == "true") ? @user.trust_level : nil
@user.save
@@ -320,31 +322,38 @@ class Admin::UsersController < Admin::StaffController
def approve
guardian.ensure_can_approve!(@user)
- reviewable = ReviewableUser.find_by(target: @user) ||
- Jobs::CreateUserReviewable.new.execute(user_id: @user.id).reviewable
+ reviewable =
+ ReviewableUser.find_by(target: @user) ||
+ Jobs::CreateUserReviewable.new.execute(user_id: @user.id).reviewable
reviewable.perform(current_user, :approve_user)
render body: nil
end
def approve_bulk
- Reviewable.bulk_perform_targets(current_user, :approve_user, 'ReviewableUser', params[:users])
+ Reviewable.bulk_perform_targets(current_user, :approve_user, "ReviewableUser", params[:users])
render body: nil
end
def activate
guardian.ensure_can_activate!(@user)
# ensure there is an active email token
- @user.email_tokens.create!(email: @user.email, scope: EmailToken.scopes[:signup]) if !@user.email_tokens.active.exists?
+ if !@user.email_tokens.active.exists?
+ @user.email_tokens.create!(email: @user.email, scope: EmailToken.scopes[:signup])
+ end
@user.activate
- StaffActionLogger.new(current_user).log_user_activate(@user, I18n.t('user.activated_by_staff'))
+ StaffActionLogger.new(current_user).log_user_activate(@user, I18n.t("user.activated_by_staff"))
render json: success_json
end
def deactivate
guardian.ensure_can_deactivate!(@user)
@user.deactivate(current_user)
- StaffActionLogger.new(current_user).log_user_deactivate(@user, I18n.t('user.deactivated_by_staff'), params.slice(:context))
+ StaffActionLogger.new(current_user).log_user_deactivate(
+ @user,
+ I18n.t("user.deactivated_by_staff"),
+ params.slice(:context),
+ )
refresh_browser @user
render json: success_json
end
@@ -354,10 +363,17 @@ class Admin::UsersController < Admin::StaffController
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')
- )
+ 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
@@ -370,15 +386,16 @@ class Admin::UsersController < Admin::StaffController
user_history = nil
all_users.each do |user|
- silencer = UserSilencer.new(
- user,
- current_user,
- silenced_till: params[:silenced_till],
- reason: params[:reason],
- message_body: params[:message],
- keep_posts: true,
- post_id: params[:post_id]
- )
+ silencer =
+ UserSilencer.new(
+ user,
+ current_user,
+ silenced_till: params[:silenced_till],
+ reason: params[:reason],
+ message_body: params[:message],
+ keep_posts: true,
+ post_id: params[:post_id],
+ )
if silencer.silence
user_history = silencer.user_history
@@ -386,7 +403,7 @@ class Admin::UsersController < Admin::StaffController
:critical_user_email,
type: "account_silenced",
user_id: user.id,
- user_history_id: user_history.id
+ user_history_id: user_history.id,
)
end
end
@@ -399,8 +416,8 @@ class Admin::UsersController < Admin::StaffController
silence_reason: user_history.try(:details),
silenced_till: @user.silenced_till,
silenced_at: @user.silenced_at,
- silenced_by: BasicUserSerializer.new(current_user, root: false).as_json
- }
+ silenced_by: BasicUserSerializer.new(current_user, root: false).as_json,
+ },
)
end
@@ -413,8 +430,8 @@ class Admin::UsersController < Admin::StaffController
silenced: false,
silence_reason: nil,
silenced_till: nil,
- silenced_at: nil
- }
+ silenced_at: nil,
+ },
)
end
@@ -428,11 +445,7 @@ class Admin::UsersController < Admin::StaffController
user_security_key.destroy_all
StaffActionLogger.new(current_user).log_disable_second_factor_auth(@user)
- Jobs.enqueue(
- :critical_user_email,
- type: "account_second_factor_disabled",
- user_id: @user.id
- )
+ Jobs.enqueue(:critical_user_email, type: "account_second_factor_disabled", user_id: @user.id)
render json: success_json
end
@@ -442,7 +455,7 @@ class Admin::UsersController < Admin::StaffController
guardian.ensure_can_delete_user!(user)
options = params.slice(:context, :delete_as_spammer)
- [:delete_posts, :block_email, :block_urls, :block_ip].each do |param_name|
+ %i[delete_posts block_email block_urls block_ip].each do |param_name|
options[param_name] = ActiveModel::Type::Boolean.new.cast(params[param_name])
end
options[:prepare_for_destroy] = true
@@ -453,15 +466,21 @@ class Admin::UsersController < Admin::StaffController
render json: { deleted: true }
else
render json: {
- deleted: false,
- user: AdminDetailedUserSerializer.new(user, root: false).as_json
- }
+ deleted: false,
+ user: AdminDetailedUserSerializer.new(user, root: false).as_json,
+ }
end
rescue UserDestroyer::PostsExistError
render json: {
- deleted: false,
- message: I18n.t("user.cannot_delete_has_posts", username: user.username, count: user.posts.joins(:topic).count),
- }, status: 403
+ deleted: false,
+ message:
+ I18n.t(
+ "user.cannot_delete_has_posts",
+ username: user.username,
+ count: user.posts.joins(:topic).count,
+ ),
+ },
+ status: 403
end
end
end
@@ -482,9 +501,16 @@ class Admin::UsersController < Admin::StaffController
return render body: nil, status: 404 unless SiteSetting.enable_discourse_connect
begin
- sso = DiscourseConnect.parse("sso=#{params[:sso]}&sig=#{params[:sig]}", secure_session: secure_session)
+ sso =
+ DiscourseConnect.parse(
+ "sso=#{params[:sso]}&sig=#{params[:sig]}",
+ secure_session: secure_session,
+ )
rescue DiscourseConnect::ParseError
- return render json: failed_json.merge(message: I18n.t("discourse_connect.login_error")), status: 422
+ return(
+ render json: failed_json.merge(message: I18n.t("discourse_connect.login_error")),
+ status: 422
+ )
end
begin
@@ -494,7 +520,8 @@ class Admin::UsersController < Admin::StaffController
rescue ActiveRecord::RecordInvalid => ex
render json: failed_json.merge(message: ex.message), status: 403
rescue DiscourseConnect::BlankExternalId => ex
- render json: failed_json.merge(message: I18n.t('discourse_connect.blank_id_error')), status: 422
+ render json: failed_json.merge(message: I18n.t("discourse_connect.blank_id_error")),
+ status: 422
end
end
@@ -510,12 +537,13 @@ class Admin::UsersController < Admin::StaffController
block_urls: true,
block_ip: true,
delete_as_spammer: true,
- context: I18n.t("user.destroy_reasons.same_ip_address", ip_address: params[:ip])
+ context: I18n.t("user.destroy_reasons.same_ip_address", ip_address: params[:ip]),
}
- AdminUserIndexQuery.new(params).find_users(50).each do |user|
- user_destroyer.destroy(user, options)
- end
+ AdminUserIndexQuery
+ .new(params)
+ .find_users(50)
+ .each { |user| user_destroyer.destroy(user, options) }
render json: success_json
end
@@ -536,7 +564,8 @@ class Admin::UsersController < Admin::StaffController
if user = UserAnonymizer.new(@user, current_user, opts).make_anonymous
render json: success_json.merge(username: user.username)
else
- render json: failed_json.merge(user: AdminDetailedUserSerializer.new(user, root: false).as_json)
+ render json:
+ failed_json.merge(user: AdminDetailedUserSerializer.new(user, root: false).as_json)
end
end
@@ -547,7 +576,12 @@ class Admin::UsersController < Admin::StaffController
guardian.ensure_can_merge_users!(@user, target_user)
- Jobs.enqueue(:merge_user, user_id: @user.id, target_user_id: target_user.id, current_user_id: current_user.id)
+ Jobs.enqueue(
+ :merge_user,
+ user_id: @user.id,
+ target_user_id: target_user.id,
+ current_user_id: current_user.id,
+ )
render json: success_json
end
@@ -566,24 +600,25 @@ class Admin::UsersController < Admin::StaffController
private
def perform_post_action
- return unless params[:post_id].present? &&
- params[:post_action].present?
+ return unless params[:post_id].present? && params[:post_action].present?
if post = Post.where(id: params[:post_id]).first
case params[:post_action]
- when 'delete'
+ when "delete"
PostDestroyer.new(current_user, post).destroy if guardian.can_delete_post_or_topic?(post)
when "delete_replies"
- PostDestroyer.delete_with_replies(current_user, post) if guardian.can_delete_post_or_topic?(post)
- when 'edit'
+ if guardian.can_delete_post_or_topic?(post)
+ PostDestroyer.delete_with_replies(current_user, post)
+ end
+ when "edit"
revisor = PostRevisor.new(post)
# Take what the moderator edited in as gospel
revisor.revise!(
current_user,
- { raw: params[:post_edit] },
+ { raw: params[:post_edit] },
skip_validations: true,
- skip_revision: true
+ skip_revision: true,
)
end
end
@@ -597,5 +632,4 @@ class Admin::UsersController < Admin::StaffController
def refresh_browser(user)
MessageBus.publish "/file-change", ["refresh"], user_ids: [user.id]
end
-
end
diff --git a/app/controllers/admin/watched_words_controller.rb b/app/controllers/admin/watched_words_controller.rb
index badfcd21735..2a5cbb496fd 100644
--- a/app/controllers/admin/watched_words_controller.rb
+++ b/app/controllers/admin/watched_words_controller.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
-require 'csv'
+require "csv"
class Admin::WatchedWordsController < Admin::StaffController
skip_before_action :check_xhr, only: [:download]
def index
watched_words = WatchedWord.by_action
- watched_words = watched_words.where.not(action: WatchedWord.actions[:tag]) if !SiteSetting.tagging_enabled
+ watched_words =
+ watched_words.where.not(action: WatchedWord.actions[:tag]) if !SiteSetting.tagging_enabled
render_json_dump WatchedWordListSerializer.new(watched_words, scope: guardian, root: false)
end
@@ -38,19 +39,20 @@ class Admin::WatchedWordsController < Admin::StaffController
begin
CSV.foreach(file.tempfile, encoding: "bom|utf-8") do |row|
if row[0].present? && (!has_replacement || row[1].present?)
- watched_word = WatchedWord.create_or_update_word(
- word: row[0],
- replacement: has_replacement ? row[1] : nil,
- action_key: action_key,
- case_sensitive: "true" == row[2]&.strip&.downcase
- )
+ watched_word =
+ WatchedWord.create_or_update_word(
+ word: row[0],
+ replacement: has_replacement ? row[1] : nil,
+ action_key: action_key,
+ case_sensitive: "true" == row[2]&.strip&.downcase,
+ )
if watched_word.valid?
StaffActionLogger.new(current_user).log_watched_words_creation(watched_word)
end
end
end
- data = { url: '/ok' }
+ data = { url: "/ok" }
rescue => e
data = failed_json.merge(errors: [e.message])
end
@@ -73,10 +75,10 @@ class Admin::WatchedWordsController < Admin::StaffController
content = content.pluck(:word).join("\n")
end
- headers['Content-Length'] = content.bytesize.to_s
+ headers["Content-Length"] = content.bytesize.to_s
send_data content,
- filename: "#{Discourse.current_hostname}-watched-words-#{name}.csv",
- content_type: "text/csv"
+ filename: "#{Discourse.current_hostname}-watched-words-#{name}.csv",
+ content_type: "text/csv"
end
def clear_all
@@ -85,10 +87,12 @@ class Admin::WatchedWordsController < Admin::StaffController
action = WatchedWord.actions[name]
raise Discourse::NotFound if !action
- WatchedWord.where(action: action).find_each do |watched_word|
- watched_word.destroy!
- StaffActionLogger.new(current_user).log_watched_words_deletion(watched_word)
- end
+ WatchedWord
+ .where(action: action)
+ .find_each do |watched_word|
+ watched_word.destroy!
+ StaffActionLogger.new(current_user).log_watched_words_deletion(watched_word)
+ end
WordWatcher.clear_cache!
render json: success_json
end
diff --git a/app/controllers/admin/web_hooks_controller.rb b/app/controllers/admin/web_hooks_controller.rb
index cb747112bd4..1ca6e81a268 100644
--- a/app/controllers/admin/web_hooks_controller.rb
+++ b/app/controllers/admin/web_hooks_controller.rb
@@ -1,17 +1,19 @@
# frozen_string_literal: true
class Admin::WebHooksController < Admin::AdminController
- before_action :fetch_web_hook, only: %i(show update destroy list_events bulk_events ping)
+ before_action :fetch_web_hook, only: %i[show update destroy list_events bulk_events ping]
def index
limit = 50
offset = params[:offset].to_i
- web_hooks = WebHook.limit(limit)
- .offset(offset)
- .includes(:web_hook_event_types)
- .includes(:categories)
- .includes(:groups)
+ web_hooks =
+ WebHook
+ .limit(limit)
+ .offset(offset)
+ .includes(:web_hook_event_types)
+ .includes(:categories)
+ .includes(:groups)
json = {
web_hooks: serialize_data(web_hooks, AdminWebHookSerializer),
@@ -19,29 +21,34 @@ class Admin::WebHooksController < Admin::AdminController
event_types: WebHookEventType.active,
default_event_types: WebHook.default_event_types,
content_types: WebHook.content_types.map { |name, id| { id: id, name: name } },
- delivery_statuses: WebHook.last_delivery_statuses.map { |name, id| { id: id, name: name.to_s } },
+ delivery_statuses:
+ WebHook.last_delivery_statuses.map { |name, id| { id: id, name: name.to_s } },
},
total_rows_web_hooks: WebHook.count,
- load_more_web_hooks: admin_web_hooks_path(limit: limit, offset: offset + limit, format: :json)
+ load_more_web_hooks:
+ admin_web_hooks_path(limit: limit, offset: offset + limit, format: :json),
}
render json: MultiJson.dump(json), status: 200
end
def show
- render_serialized(@web_hook, AdminWebHookSerializer, root: 'web_hook')
+ render_serialized(@web_hook, AdminWebHookSerializer, root: "web_hook")
end
def edit
- render_serialized(@web_hook, AdminWebHookSerializer, root: 'web_hook')
+ render_serialized(@web_hook, AdminWebHookSerializer, root: "web_hook")
end
def create
web_hook = WebHook.new(web_hook_params)
if web_hook.save
- StaffActionLogger.new(current_user).log_web_hook(web_hook, UserHistory.actions[:web_hook_create])
- render_serialized(web_hook, AdminWebHookSerializer, root: 'web_hook')
+ StaffActionLogger.new(current_user).log_web_hook(
+ web_hook,
+ UserHistory.actions[:web_hook_create],
+ )
+ render_serialized(web_hook, AdminWebHookSerializer, root: "web_hook")
else
render_json_error web_hook.errors.full_messages
end
@@ -49,8 +56,12 @@ class Admin::WebHooksController < Admin::AdminController
def update
if @web_hook.update(web_hook_params)
- StaffActionLogger.new(current_user).log_web_hook(@web_hook, UserHistory.actions[:web_hook_update], changes: @web_hook.saved_changes)
- render_serialized(@web_hook, AdminWebHookSerializer, root: 'web_hook')
+ StaffActionLogger.new(current_user).log_web_hook(
+ @web_hook,
+ UserHistory.actions[:web_hook_update],
+ changes: @web_hook.saved_changes,
+ )
+ render_serialized(@web_hook, AdminWebHookSerializer, root: "web_hook")
else
render_json_error @web_hook.errors.full_messages
end
@@ -58,7 +69,10 @@ class Admin::WebHooksController < Admin::AdminController
def destroy
@web_hook.destroy!
- StaffActionLogger.new(current_user).log_web_hook(@web_hook, UserHistory.actions[:web_hook_destroy])
+ StaffActionLogger.new(current_user).log_web_hook(
+ @web_hook,
+ UserHistory.actions[:web_hook_destroy],
+ )
render json: success_json
end
@@ -67,12 +81,17 @@ class Admin::WebHooksController < Admin::AdminController
offset = params[:offset].to_i
json = {
- web_hook_events: serialize_data(@web_hook.web_hook_events.limit(limit).offset(offset), AdminWebHookEventSerializer),
+ web_hook_events:
+ serialize_data(
+ @web_hook.web_hook_events.limit(limit).offset(offset),
+ AdminWebHookEventSerializer,
+ ),
total_rows_web_hook_events: @web_hook.web_hook_events.count,
- load_more_web_hook_events: web_hook_events_admin_api_index_path(limit: limit, offset: offset + limit, format: :json),
+ load_more_web_hook_events:
+ web_hook_events_admin_api_index_path(limit: limit, offset: offset + limit, format: :json),
extras: {
- web_hook_id: @web_hook.id
- }
+ web_hook_id: @web_hook.id,
+ },
}
render json: MultiJson.dump(json), status: 200
@@ -91,26 +110,37 @@ class Admin::WebHooksController < Admin::AdminController
web_hook = web_hook_event.web_hook
emitter = WebHookEmitter.new(web_hook, web_hook_event)
emitter.emit!(headers: MultiJson.load(web_hook_event.headers), body: web_hook_event.payload)
- render_serialized(web_hook_event, AdminWebHookEventSerializer, root: 'web_hook_event')
+ render_serialized(web_hook_event, AdminWebHookEventSerializer, root: "web_hook_event")
else
render json: failed_json
end
end
def ping
- Jobs.enqueue(:emit_web_hook_event, web_hook_id: @web_hook.id, event_type: 'ping', event_name: 'ping')
+ Jobs.enqueue(
+ :emit_web_hook_event,
+ web_hook_id: @web_hook.id,
+ event_type: "ping",
+ event_name: "ping",
+ )
render json: success_json
end
private
def web_hook_params
- params.require(:web_hook).permit(:payload_url, :content_type, :secret,
- :wildcard_web_hook, :active, :verify_certificate,
- web_hook_event_type_ids: [],
- group_ids: [],
- tag_names: [],
- category_ids: [])
+ params.require(:web_hook).permit(
+ :payload_url,
+ :content_type,
+ :secret,
+ :wildcard_web_hook,
+ :active,
+ :verify_certificate,
+ web_hook_event_type_ids: [],
+ group_ids: [],
+ tag_names: [],
+ category_ids: [],
+ )
end
def fetch_web_hook
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 0ab26fef897..41bd4889bc7 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'current_user'
+require "current_user"
class ApplicationController < ActionController::Base
include CurrentUser
@@ -43,17 +43,18 @@ class ApplicationController < ActionController::Base
before_action :block_if_requires_login
before_action :preload_json
before_action :check_xhr
- after_action :add_readonly_header
- after_action :perform_refresh_session
- after_action :dont_cache_page
- after_action :conditionally_allow_site_embedding
- after_action :ensure_vary_header
- after_action :add_noindex_header, if: -> { is_feed_request? || !SiteSetting.allow_index_in_robots_txt }
- after_action :add_noindex_header_to_non_canonical, if: :spa_boot_request?
+ after_action :add_readonly_header
+ after_action :perform_refresh_session
+ after_action :dont_cache_page
+ after_action :conditionally_allow_site_embedding
+ after_action :ensure_vary_header
+ after_action :add_noindex_header,
+ if: -> { is_feed_request? || !SiteSetting.allow_index_in_robots_txt }
+ after_action :add_noindex_header_to_non_canonical, if: :spa_boot_request?
around_action :link_preload, if: -> { spa_boot_request? && GlobalSetting.preload_link_header }
- HONEYPOT_KEY ||= 'HONEYPOT_KEY'
- CHALLENGE_KEY ||= 'CHALLENGE_KEY'
+ HONEYPOT_KEY ||= "HONEYPOT_KEY"
+ CHALLENGE_KEY ||= "CHALLENGE_KEY"
layout :set_layout
@@ -68,12 +69,12 @@ class ApplicationController < ActionController::Base
def use_crawler_layout?
@use_crawler_layout ||=
- request.user_agent &&
- (request.media_type.blank? || request.media_type.include?('html')) &&
- !['json', 'rss'].include?(params[:format]) &&
- (has_escaped_fragment? || params.key?("print") || show_browser_update? ||
- CrawlerDetection.crawler?(request.user_agent, request.headers["HTTP_VIA"])
- )
+ request.user_agent && (request.media_type.blank? || request.media_type.include?("html")) &&
+ !%w[json rss].include?(params[:format]) &&
+ (
+ has_escaped_fragment? || params.key?("print") || show_browser_update? ||
+ CrawlerDetection.crawler?(request.user_agent, request.headers["HTTP_VIA"])
+ )
end
def perform_refresh_session
@@ -91,19 +92,16 @@ class ApplicationController < ActionController::Base
response.cache_control[:no_cache] = true
response.cache_control[:extras] = ["no-store"]
end
- if SiteSetting.login_required
- response.headers['Discourse-No-Onebox'] = '1'
- end
+ response.headers["Discourse-No-Onebox"] = "1" if SiteSetting.login_required
end
def conditionally_allow_site_embedding
- if SiteSetting.allow_embedding_site_in_an_iframe
- response.headers.delete('X-Frame-Options')
- end
+ response.headers.delete("X-Frame-Options") if SiteSetting.allow_embedding_site_in_an_iframe
end
def ember_cli_required?
- Rails.env.development? && ENV["ALLOW_EMBER_CLI_PROXY_BYPASS"] != "1" && request.headers['X-Discourse-Ember-CLI'] != 'true'
+ Rails.env.development? && ENV["ALLOW_EMBER_CLI_PROXY_BYPASS"] != "1" &&
+ request.headers["X-Discourse-Ember-CLI"] != "true"
end
def application_layout
@@ -118,14 +116,16 @@ class ApplicationController < ActionController::Base
return "crawler"
end
- use_crawler_layout? ? 'crawler' : application_layout
+ use_crawler_layout? ? "crawler" : application_layout
end
- class RenderEmpty < StandardError; end
- class PluginDisabled < StandardError; end
+ class RenderEmpty < StandardError
+ end
+ class PluginDisabled < StandardError
+ end
rescue_from RenderEmpty do
- with_resolved_locale { render 'default/empty' }
+ with_resolved_locale { render "default/empty" }
end
rescue_from ArgumentError do |e|
@@ -147,10 +147,10 @@ class ApplicationController < ActionController::Base
end
rescue_from Discourse::SiteSettingMissing do |e|
- render_json_error I18n.t('site_setting_missing', name: e.message), status: 500
+ render_json_error I18n.t("site_setting_missing", name: e.message), status: 500
end
- rescue_from ActionController::RoutingError, PluginDisabled do
+ rescue_from ActionController::RoutingError, PluginDisabled do
rescue_discourse_actions(:not_found, 404)
end
@@ -180,21 +180,20 @@ class ApplicationController < ActionController::Base
rescue_from RateLimiter::LimitExceeded do |e|
retry_time_in_seconds = e&.available_in
- response_headers = {
- 'Retry-After': retry_time_in_seconds.to_s
- }
+ response_headers = { "Retry-After": retry_time_in_seconds.to_s }
- if e&.error_code
- response_headers['Discourse-Rate-Limit-Error-Code'] = e.error_code
- end
+ response_headers["Discourse-Rate-Limit-Error-Code"] = e.error_code if e&.error_code
with_resolved_locale do
render_json_error(
e.description,
type: :rate_limit,
status: 429,
- extras: { wait_seconds: retry_time_in_seconds, time_left: e&.time_left },
- headers: response_headers
+ extras: {
+ wait_seconds: retry_time_in_seconds,
+ time_left: e&.time_left,
+ },
+ headers: response_headers,
)
end
end
@@ -208,10 +207,7 @@ class ApplicationController < ActionController::Base
end
rescue_from Discourse::InvalidParameters do |e|
- opts = {
- custom_message: 'invalid_params',
- custom_message_params: { message: e.message }
- }
+ opts = { custom_message: "invalid_params", custom_message_params: { message: e.message } }
if (request.format && request.format.json?) || request.xhr? || !request.get?
rescue_discourse_actions(:invalid_parameters, 400, opts.merge(include_ember: true))
@@ -226,14 +222,12 @@ class ApplicationController < ActionController::Base
e.status,
check_permalinks: e.check_permalinks,
original_path: e.original_path,
- custom_message: e.custom_message
+ custom_message: e.custom_message,
)
end
rescue_from Discourse::InvalidAccess do |e|
- if e.opts[:delete_cookie].present?
- cookies.delete(e.opts[:delete_cookie])
- end
+ cookies.delete(e.opts[:delete_cookie]) if e.opts[:delete_cookie].present?
rescue_discourse_actions(
:invalid_access,
@@ -241,7 +235,7 @@ class ApplicationController < ActionController::Base
include_ember: true,
custom_message: e.custom_message,
custom_message_params: e.custom_message_params,
- group: e.group
+ group: e.group,
)
end
@@ -249,20 +243,16 @@ class ApplicationController < ActionController::Base
unless response_body
respond_to do |format|
format.json do
- render_json_error I18n.t('read_only_mode_enabled'), type: :read_only, status: 503
- end
- format.html do
- render status: 503, layout: 'no_ember', template: 'exceptions/read_only'
+ render_json_error I18n.t("read_only_mode_enabled"), type: :read_only, status: 503
end
+ format.html { render status: 503, layout: "no_ember", template: "exceptions/read_only" }
end
end
end
rescue_from SecondFactor::AuthManager::SecondFactorRequired do |e|
if request.xhr?
- render json: {
- second_factor_challenge_nonce: e.nonce
- }, status: 403
+ render json: { second_factor_challenge_nonce: e.nonce }, status: 403
else
redirect_to session_2fa_path(nonce: e.nonce)
end
@@ -274,7 +264,7 @@ class ApplicationController < ActionController::Base
def redirect_with_client_support(url, options = {})
if request.xhr?
- response.headers['Discourse-Xhr-Redirect'] = 'true'
+ response.headers["Discourse-Xhr-Redirect"] = "true"
render plain: url
else
redirect_to url, options
@@ -283,9 +273,9 @@ class ApplicationController < ActionController::Base
def rescue_discourse_actions(type, status_code, opts = nil)
opts ||= {}
- show_json_errors = (request.format && request.format.json?) ||
- (request.xhr?) ||
- ((params[:external_id] || '').ends_with? '.json')
+ show_json_errors =
+ (request.format && request.format.json?) || (request.xhr?) ||
+ ((params[:external_id] || "").ends_with? ".json")
if type == :not_found && opts[:check_permalinks]
url = opts[:original_path] || request.fullpath
@@ -295,7 +285,9 @@ class ApplicationController < ActionController::Base
# cause category / topic was deleted
if permalink.present? && permalink.target_url
# permalink present, redirect to that URL
- redirect_with_client_support permalink.target_url, status: :moved_permanently, allow_other_host: true
+ redirect_with_client_support permalink.target_url,
+ status: :moved_permanently,
+ allow_other_host: true
return
end
end
@@ -321,11 +313,15 @@ class ApplicationController < ActionController::Base
with_resolved_locale(check_current_user: false) do
# Include error in HTML format for topics#show.
- if (request.params[:controller] == 'topics' && request.params[:action] == 'show') || (request.params[:controller] == 'categories' && request.params[:action] == 'find_by_slug')
+ if (request.params[:controller] == "topics" && request.params[:action] == "show") ||
+ (
+ request.params[:controller] == "categories" &&
+ request.params[:action] == "find_by_slug"
+ )
opts[:extras] = {
- title: I18n.t('page_not_found.page_title'),
+ title: I18n.t("page_not_found.page_title"),
html: build_not_found_page(error_page_opts),
- group: error_page_opts[:group]
+ group: error_page_opts[:group],
}
end
end
@@ -340,7 +336,7 @@ class ApplicationController < ActionController::Base
return render plain: message, status: status_code
end
with_resolved_locale do
- error_page_opts[:layout] = (opts[:include_ember] && @preloaded) ? 'application' : 'no_ember'
+ error_page_opts[:layout] = (opts[:include_ember] && @preloaded) ? "application" : "no_ember"
render html: build_not_found_page(error_page_opts)
end
end
@@ -373,9 +369,8 @@ class ApplicationController < ActionController::Base
def clear_notifications
if current_user && !@readonly_mode
-
- cookie_notifications = cookies['cn']
- notifications = request.headers['Discourse-Clear-Notifications']
+ cookie_notifications = cookies["cn"]
+ notifications = request.headers["Discourse-Clear-Notifications"]
if cookie_notifications
if notifications.present?
@@ -392,22 +387,28 @@ class ApplicationController < ActionController::Base
current_user.publish_notifications_state
cookie_args = {}
cookie_args[:path] = Discourse.base_path if Discourse.base_path.present?
- cookies.delete('cn', cookie_args)
+ cookies.delete("cn", cookie_args)
end
end
end
def with_resolved_locale(check_current_user: true)
- if check_current_user && (user = current_user rescue nil)
+ if check_current_user &&
+ (
+ user =
+ begin
+ current_user
+ rescue StandardError
+ nil
+ end
+ )
locale = user.effective_locale
else
locale = Discourse.anonymous_locale(request)
locale ||= SiteSetting.default_locale
end
- if !I18n.locale_available?(locale)
- locale = SiteSettings::DefaultsProvider::DEFAULT_LOCALE
- end
+ locale = SiteSettings::DefaultsProvider::DEFAULT_LOCALE if !I18n.locale_available?(locale)
I18n.ensure_all_loaded!
I18n.with_locale(locale) { yield }
@@ -458,7 +459,8 @@ class ApplicationController < ActionController::Base
safe_mode = safe_mode.split(",")
request.env[NO_THEMES] = safe_mode.include?(NO_THEMES) || safe_mode.include?(LEGACY_NO_THEMES)
request.env[NO_PLUGINS] = safe_mode.include?(NO_PLUGINS)
- request.env[NO_UNOFFICIAL_PLUGINS] = safe_mode.include?(NO_UNOFFICIAL_PLUGINS) || safe_mode.include?(LEGACY_NO_UNOFFICIAL_PLUGINS)
+ request.env[NO_UNOFFICIAL_PLUGINS] = safe_mode.include?(NO_UNOFFICIAL_PLUGINS) ||
+ safe_mode.include?(LEGACY_NO_UNOFFICIAL_PLUGINS)
end
end
@@ -471,8 +473,7 @@ class ApplicationController < ActionController::Base
theme_id = nil
if (preview_theme_id = request[:preview_theme_id]&.to_i) &&
- guardian.allow_themes?([preview_theme_id], include_preview: true)
-
+ guardian.allow_themes?([preview_theme_id], include_preview: true)
theme_id = preview_theme_id
end
@@ -491,7 +492,8 @@ class ApplicationController < ActionController::Base
theme_id = ids.first if guardian.allow_themes?(ids)
end
- if theme_id.blank? && SiteSetting.default_theme_id != -1 && guardian.allow_themes?([SiteSetting.default_theme_id])
+ if theme_id.blank? && SiteSetting.default_theme_id != -1 &&
+ guardian.allow_themes?([SiteSetting.default_theme_id])
theme_id = SiteSetting.default_theme_id
end
@@ -533,13 +535,11 @@ class ApplicationController < ActionController::Base
def render_json_dump(obj, opts = nil)
opts ||= {}
if opts[:rest_serializer]
- obj['__rest_serializer'] = "1"
- opts.each do |k, v|
- obj[k] = v if k.to_s.start_with?("refresh_")
- end
+ obj["__rest_serializer"] = "1"
+ opts.each { |k, v| obj[k] = v if k.to_s.start_with?("refresh_") }
- obj['extras'] = opts[:extras] if opts[:extras]
- obj['meta'] = opts[:meta] if opts[:meta]
+ obj["extras"] = opts[:extras] if opts[:extras]
+ obj["meta"] = opts[:meta] if opts[:meta]
end
render json: MultiJson.dump(obj), status: opts[:status] || 200
@@ -557,29 +557,33 @@ class ApplicationController < ActionController::Base
def fetch_user_from_params(opts = nil, eager_load = [])
opts ||= {}
- user = if params[:username]
- username_lower = params[:username].downcase.chomp('.json')
+ user =
+ if params[:username]
+ username_lower = params[:username].downcase.chomp(".json")
- if current_user && current_user.username_lower == username_lower
- current_user
- else
- find_opts = { username_lower: username_lower }
- find_opts[:active] = true unless opts[:include_inactive] || current_user.try(:staff?)
- result = User
- (result = result.includes(*eager_load)) if !eager_load.empty?
- result.find_by(find_opts)
+ if current_user && current_user.username_lower == username_lower
+ current_user
+ else
+ find_opts = { username_lower: username_lower }
+ find_opts[:active] = true unless opts[:include_inactive] || current_user.try(:staff?)
+ result = User
+ (result = result.includes(*eager_load)) if !eager_load.empty?
+ result.find_by(find_opts)
+ end
+ elsif params[:external_id]
+ external_id = params[:external_id].chomp(".json")
+ if provider_name = params[:external_provider]
+ raise Discourse::InvalidAccess unless guardian.is_admin? # external_id might be something sensitive
+ provider = Discourse.enabled_authenticators.find { |a| a.name == provider_name }
+ raise Discourse::NotFound if !provider&.is_managed? # Only managed authenticators use UserAssociatedAccount
+ UserAssociatedAccount.find_by(
+ provider_name: provider_name,
+ provider_uid: external_id,
+ )&.user
+ else
+ SingleSignOnRecord.find_by(external_id: external_id).try(:user)
+ end
end
- elsif params[:external_id]
- external_id = params[:external_id].chomp('.json')
- if provider_name = params[:external_provider]
- raise Discourse::InvalidAccess unless guardian.is_admin? # external_id might be something sensitive
- provider = Discourse.enabled_authenticators.find { |a| a.name == provider_name }
- raise Discourse::NotFound if !provider&.is_managed? # Only managed authenticators use UserAssociatedAccount
- UserAssociatedAccount.find_by(provider_name: provider_name, provider_uid: external_id)&.user
- else
- SingleSignOnRecord.find_by(external_id: external_id).try(:user)
- end
- end
raise Discourse::NotFound if user.blank?
guardian.ensure_can_see!(user)
@@ -587,15 +591,17 @@ class ApplicationController < ActionController::Base
end
def post_ids_including_replies
- post_ids = params[:post_ids].map(&:to_i)
- post_ids |= PostReply.where(post_id: params[:reply_post_ids]).pluck(:reply_post_id) if params[:reply_post_ids]
+ post_ids = params[:post_ids].map(&:to_i)
+ post_ids |= PostReply.where(post_id: params[:reply_post_ids]).pluck(:reply_post_id) if params[
+ :reply_post_ids
+ ]
post_ids
end
def no_cookies
# do your best to ensure response has no cookies
# longer term we may want to push this into middleware
- headers.delete 'Set-Cookie'
+ headers.delete "Set-Cookie"
request.session_options[:skip] = true
end
@@ -615,9 +621,7 @@ class ApplicationController < ActionController::Base
RateLimiter.new(nil, "second-factor-min-#{request.remote_ip}", 6, 1.minute).performed!
- if user
- RateLimiter.new(nil, "second-factor-min-#{user.username}", 6, 1.minute).performed!
- end
+ RateLimiter.new(nil, "second-factor-min-#{user.username}", 6, 1.minute).performed! if user
end
private
@@ -634,11 +638,17 @@ class ApplicationController < ActionController::Base
end
def preload_current_user_data
- store_preloaded("currentUser", MultiJson.dump(CurrentUserSerializer.new(current_user, scope: guardian, root: false)))
- report = TopicTrackingState.report(current_user)
- serializer = ActiveModel::ArraySerializer.new(
- report, each_serializer: TopicTrackingStateSerializer, scope: guardian
+ store_preloaded(
+ "currentUser",
+ MultiJson.dump(CurrentUserSerializer.new(current_user, scope: guardian, root: false)),
)
+ report = TopicTrackingState.report(current_user)
+ serializer =
+ ActiveModel::ArraySerializer.new(
+ report,
+ each_serializer: TopicTrackingStateSerializer,
+ scope: guardian,
+ )
store_preloaded("topicTrackingStates", MultiJson.dump(serializer))
end
@@ -648,20 +658,18 @@ class ApplicationController < ActionController::Base
data =
if @theme_id.present?
{
- top: Theme.lookup_field(@theme_id, target, "after_header"),
- footer: Theme.lookup_field(@theme_id, target, "footer")
+ top: Theme.lookup_field(@theme_id, target, "after_header"),
+ footer: Theme.lookup_field(@theme_id, target, "footer"),
}
else
{}
end
- if DiscoursePluginRegistry.custom_html
- data.merge! DiscoursePluginRegistry.custom_html
- end
+ data.merge! DiscoursePluginRegistry.custom_html if DiscoursePluginRegistry.custom_html
DiscoursePluginRegistry.html_builders.each do |name, _|
if name.start_with?("client:")
- data[name.sub(/^client:/, '')] = DiscoursePluginRegistry.build_html(name, self)
+ data[name.sub(/^client:/, "")] = DiscoursePluginRegistry.build_html(name, self)
end
end
@@ -703,7 +711,7 @@ class ApplicationController < ActionController::Base
render(
json: MultiJson.dump(create_errors_json(obj, opts)),
- status: opts[:status] || status_code(obj)
+ status: opts[:status] || status_code(obj),
)
end
@@ -714,11 +722,11 @@ class ApplicationController < ActionController::Base
end
def success_json
- { success: 'OK' }
+ { success: "OK" }
end
def failed_json
- { failed: 'FAILED' }
+ { failed: "FAILED" }
end
def json_result(obj, opts = {})
@@ -727,17 +735,21 @@ class ApplicationController < ActionController::Base
# If we were given a serializer, add the class to the json that comes back
if opts[:serializer].present?
- json[obj.class.name.underscore] = opts[:serializer].new(obj, scope: guardian).serializable_hash
+ json[obj.class.name.underscore] = opts[:serializer].new(
+ obj,
+ scope: guardian,
+ ).serializable_hash
end
render json: MultiJson.dump(json)
else
error_obj = nil
if opts[:additional_errors]
- error_target = opts[:additional_errors].find do |o|
- target = obj.public_send(o)
- target && target.errors.present?
- end
+ error_target =
+ opts[:additional_errors].find do |o|
+ target = obj.public_send(o)
+ target && target.errors.present?
+ end
error_obj = obj.public_send(error_target) if error_target
end
render_json_error(error_obj || obj)
@@ -756,11 +768,15 @@ class ApplicationController < ActionController::Base
def check_xhr
# bypass xhr check on PUT / POST / DELETE provided api key is there, otherwise calling api is annoying
return if !request.get? && (is_api? || is_user_api?)
- raise ApplicationController::RenderEmpty.new unless ((request.format && request.format.json?) || request.xhr?)
+ unless ((request.format && request.format.json?) || request.xhr?)
+ raise ApplicationController::RenderEmpty.new
+ end
end
def apply_cdn_headers
- Discourse.apply_cdn_headers(response.headers) if Discourse.is_cdn_request?(request.env, request.method)
+ if Discourse.is_cdn_request?(request.env, request.method)
+ Discourse.apply_cdn_headers(response.headers)
+ end
end
def self.requires_login(arg = {})
@@ -811,8 +827,9 @@ class ApplicationController < ActionController::Base
if SiteSetting.auth_immediately && SiteSetting.enable_discourse_connect?
# save original URL in a session so we can redirect after login
session[:destination_url] = destination_url
- redirect_to path('/session/sso')
- elsif SiteSetting.auth_immediately && !SiteSetting.enable_local_logins && Discourse.enabled_authenticators.length == 1 && !cookies[:authentication_data]
+ redirect_to path("/session/sso")
+ elsif SiteSetting.auth_immediately && !SiteSetting.enable_local_logins &&
+ Discourse.enabled_authenticators.length == 1 && !cookies[:authentication_data]
# Only one authentication provider, direct straight to it.
# If authentication_data is present, then we are halfway though registration. Don't redirect offsite
cookies[:destination_url] = destination_url
@@ -831,9 +848,7 @@ class ApplicationController < ActionController::Base
# Redirects to provided URL scheme if
# - request uses a valid public key and auth_redirect scheme
# - one_time_password scope is allowed
- if !current_user &&
- params.has_key?(:user_api_public_key) &&
- params.has_key?(:auth_redirect)
+ if !current_user && params.has_key?(:user_api_public_key) && params.has_key?(:auth_redirect)
begin
OpenSSL::PKey::RSA.new(params[:user_api_public_key])
rescue OpenSSL::PKey::RSAError
@@ -872,26 +887,45 @@ class ApplicationController < ActionController::Base
def should_enforce_2fa?
disqualified_from_2fa_enforcement = request.format.json? || is_api? || current_user.anonymous?
- enforcing_2fa = ((SiteSetting.enforce_second_factor == 'staff' && current_user.staff?) || SiteSetting.enforce_second_factor == 'all')
- !disqualified_from_2fa_enforcement && enforcing_2fa && !current_user.has_any_second_factor_methods_enabled?
+ enforcing_2fa =
+ (
+ (SiteSetting.enforce_second_factor == "staff" && current_user.staff?) ||
+ SiteSetting.enforce_second_factor == "all"
+ )
+ !disqualified_from_2fa_enforcement && enforcing_2fa &&
+ !current_user.has_any_second_factor_methods_enabled?
end
def build_not_found_page(opts = {})
if SiteSetting.bootstrap_error_pages?
preload_json
- opts[:layout] = 'application' if opts[:layout] == 'no_ember'
+ opts[:layout] = "application" if opts[:layout] == "no_ember"
end
- @current_user = current_user rescue nil
+ @current_user =
+ begin
+ current_user
+ rescue StandardError
+ nil
+ end
if !SiteSetting.login_required? || @current_user
key = "page_not_found_topics:#{I18n.locale}"
- @topics_partial = Discourse.cache.fetch(key, expires_in: 10.minutes) do
- category_topic_ids = Category.pluck(:topic_id).compact
- @top_viewed = TopicQuery.new(nil, except_topic_ids: category_topic_ids).list_top_for("monthly").topics.first(10)
- @recent = Topic.includes(:category).where.not(id: category_topic_ids).recent(10)
- render_to_string partial: '/exceptions/not_found_topics', formats: [:html]
- end.html_safe
+ @topics_partial =
+ Discourse
+ .cache
+ .fetch(key, expires_in: 10.minutes) do
+ category_topic_ids = Category.pluck(:topic_id).compact
+ @top_viewed =
+ TopicQuery
+ .new(nil, except_topic_ids: category_topic_ids)
+ .list_top_for("monthly")
+ .topics
+ .first(10)
+ @recent = Topic.includes(:category).where.not(id: category_topic_ids).recent(10)
+ render_to_string partial: "/exceptions/not_found_topics", formats: [:html]
+ end
+ .html_safe
end
@container_class = "wrap not-found-container"
@@ -902,13 +936,16 @@ class ApplicationController < ActionController::Base
params[:slug] = params[:slug].first if params[:slug].kind_of?(Array)
params[:id] = params[:id].first if params[:id].kind_of?(Array)
- @slug = (params[:slug].presence || params[:id].presence || "").to_s.tr('-', ' ')
+ @slug = (params[:slug].presence || params[:id].presence || "").to_s.tr("-", " ")
- render_to_string status: opts[:status], layout: opts[:layout], formats: [:html], template: '/exceptions/not_found'
+ render_to_string status: opts[:status],
+ layout: opts[:layout],
+ formats: [:html],
+ template: "/exceptions/not_found"
end
def is_asset_path
- request.env['DISCOURSE_IS_ASSET_PATH'] = 1
+ request.env["DISCOURSE_IS_ASSET_PATH"] = 1
end
def is_feed_request?
@@ -916,19 +953,20 @@ class ApplicationController < ActionController::Base
end
def add_noindex_header
- if request.get? && !response.headers['X-Robots-Tag']
+ if request.get? && !response.headers["X-Robots-Tag"]
if SiteSetting.allow_index_in_robots_txt
- response.headers['X-Robots-Tag'] = 'noindex'
+ response.headers["X-Robots-Tag"] = "noindex"
else
- response.headers['X-Robots-Tag'] = 'noindex, nofollow'
+ response.headers["X-Robots-Tag"] = "noindex, nofollow"
end
end
end
def add_noindex_header_to_non_canonical
canonical = (@canonical_url || @default_canonical)
- if canonical.present? && canonical != request.url && !SiteSetting.allow_indexing_non_canonical_urls
- response.headers['X-Robots-Tag'] ||= 'noindex'
+ if canonical.present? && canonical != request.url &&
+ !SiteSetting.allow_indexing_non_canonical_urls
+ response.headers["X-Robots-Tag"] ||= "noindex"
end
end
@@ -955,7 +993,7 @@ class ApplicationController < ActionController::Base
# returns an array of integers given a param key
# returns nil if key is not found
- def param_to_integer_list(key, delimiter = ',')
+ def param_to_integer_list(key, delimiter = ",")
case params[key]
when String
params[key].split(delimiter).map(&:to_i)
@@ -978,20 +1016,19 @@ class ApplicationController < ActionController::Base
user_agent = request.user_agent&.downcase
return if user_agent.blank?
- SiteSetting.slow_down_crawler_user_agents.downcase.split("|").each do |crawler|
- if user_agent.include?(crawler)
- key = "#{crawler}_crawler_rate_limit"
- limiter = RateLimiter.new(
- nil,
- key,
- 1,
- SiteSetting.slow_down_crawler_rate,
- error_code: key
- )
- limiter.performed!
- break
+ SiteSetting
+ .slow_down_crawler_user_agents
+ .downcase
+ .split("|")
+ .each do |crawler|
+ if user_agent.include?(crawler)
+ key = "#{crawler}_crawler_rate_limit"
+ limiter =
+ RateLimiter.new(nil, key, 1, SiteSetting.slow_down_crawler_rate, error_code: key)
+ limiter.performed!
+ break
+ end
end
- end
end
def run_second_factor!(action_class, action_data = nil)
@@ -1000,9 +1037,8 @@ class ApplicationController < ActionController::Base
yield(manager) if block_given?
result = manager.run!(request, params, secure_session)
- if !result.no_second_factors_enabled? &&
- !result.second_factor_auth_completed? &&
- !result.second_factor_auth_skipped?
+ if !result.no_second_factors_enabled? && !result.second_factor_auth_completed? &&
+ !result.second_factor_auth_skipped?
# should never happen, but I want to know if somehow it does! (osama)
raise "2fa process ended up in a bad state!"
end
@@ -1013,7 +1049,7 @@ class ApplicationController < ActionController::Base
def link_preload
@links_to_preload = []
yield
- response.headers['Link'] = @links_to_preload.join(', ') if !@links_to_preload.empty?
+ response.headers["Link"] = @links_to_preload.join(", ") if !@links_to_preload.empty?
end
def spa_boot_request?
diff --git a/app/controllers/associated_groups_controller.rb b/app/controllers/associated_groups_controller.rb
index cf82ae20c7d..136a97e5948 100644
--- a/app/controllers/associated_groups_controller.rb
+++ b/app/controllers/associated_groups_controller.rb
@@ -5,6 +5,6 @@ class AssociatedGroupsController < ApplicationController
def index
guardian.ensure_can_associate_groups!
- render_serialized(AssociatedGroup.all, AssociatedGroupSerializer, root: 'associated_groups')
+ render_serialized(AssociatedGroup.all, AssociatedGroupSerializer, root: "associated_groups")
end
end
diff --git a/app/controllers/badges_controller.rb b/app/controllers/badges_controller.rb
index 3b90fce090a..e505ea7c594 100644
--- a/app/controllers/badges_controller.rb
+++ b/app/controllers/badges_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class BadgesController < ApplicationController
- skip_before_action :check_xhr, only: [:index, :show]
+ skip_before_action :check_xhr, only: %i[index show]
after_action :add_noindex_header
def index
@@ -16,18 +16,29 @@ class BadgesController < ApplicationController
if (params[:only_listable] == "true") || !request.xhr?
# NOTE: this is sorted client side if needed
- badges = badges.includes(:badge_grouping)
- .includes(:badge_type, :image_upload)
- .where(enabled: true, listable: true)
+ badges =
+ badges
+ .includes(:badge_grouping)
+ .includes(:badge_type, :image_upload)
+ .where(enabled: true, listable: true)
end
badges = badges.to_a
user_badges = nil
if current_user
- user_badges = Set.new(current_user.user_badges.select('distinct badge_id').pluck(:badge_id))
+ user_badges = Set.new(current_user.user_badges.select("distinct badge_id").pluck(:badge_id))
end
- serialized = MultiJson.dump(serialize_data(badges, BadgeIndexSerializer, root: "badges", user_badges: user_badges, include_long_description: true))
+ serialized =
+ MultiJson.dump(
+ serialize_data(
+ badges,
+ BadgeIndexSerializer,
+ root: "badges",
+ user_badges: user_badges,
+ include_long_description: true,
+ ),
+ )
respond_to do |format|
format.html do
store_preloaded "badges", serialized
@@ -42,27 +53,27 @@ class BadgesController < ApplicationController
params.require(:id)
@badge = Badge.enabled.find(params[:id])
- @rss_title = I18n.t('rss_description.badge', display_name: @badge.display_name, site_title: SiteSetting.title)
+ @rss_title =
+ I18n.t(
+ "rss_description.badge",
+ display_name: @badge.display_name,
+ site_title: SiteSetting.title,
+ )
@rss_link = "#{Discourse.base_url}/badges/#{@badge.id}/#{@badge.slug}"
if current_user
user_badge = UserBadge.find_by(user_id: current_user.id, badge_id: @badge.id)
- if user_badge && user_badge.notification
- user_badge.notification.update read: true
- end
- if user_badge
- @badge.has_badge = true
- end
+ user_badge.notification.update read: true if user_badge && user_badge.notification
+ @badge.has_badge = true if user_badge
end
- serialized = MultiJson.dump(serialize_data(@badge, BadgeSerializer, root: "badge", include_long_description: true))
+ serialized =
+ MultiJson.dump(
+ serialize_data(@badge, BadgeSerializer, root: "badge", include_long_description: true),
+ )
respond_to do |format|
- format.rss do
- @rss_description = @badge.long_description
- end
- format.html do
- store_preloaded "badge", serialized
- end
+ format.rss { @rss_description = @badge.long_description }
+ format.html { store_preloaded "badge", serialized }
format.json { render json: serialized }
end
end
diff --git a/app/controllers/bookmarks_controller.rb b/app/controllers/bookmarks_controller.rb
index bfeaa58a3b3..a3e385e585c 100644
--- a/app/controllers/bookmarks_controller.rb
+++ b/app/controllers/bookmarks_controller.rb
@@ -6,26 +6,34 @@ class BookmarksController < ApplicationController
def create
params.require(:bookmarkable_id)
params.require(:bookmarkable_type)
- params.permit(:bookmarkable_id, :bookmarkable_type, :name, :reminder_at, :auto_delete_preference)
+ params.permit(
+ :bookmarkable_id,
+ :bookmarkable_type,
+ :name,
+ :reminder_at,
+ :auto_delete_preference,
+ )
RateLimiter.new(
- current_user, "create_bookmark", SiteSetting.max_bookmarks_per_day, 1.day.to_i
+ current_user,
+ "create_bookmark",
+ SiteSetting.max_bookmarks_per_day,
+ 1.day.to_i,
).performed!
bookmark_manager = BookmarkManager.new(current_user)
- bookmark = bookmark_manager.create_for(
- bookmarkable_id: params[:bookmarkable_id],
- bookmarkable_type: params[:bookmarkable_type],
- name: params[:name],
- reminder_at: params[:reminder_at],
- options: {
- auto_delete_preference: params[:auto_delete_preference]
- }
- )
+ bookmark =
+ bookmark_manager.create_for(
+ bookmarkable_id: params[:bookmarkable_id],
+ bookmarkable_type: params[:bookmarkable_type],
+ name: params[:name],
+ reminder_at: params[:reminder_at],
+ options: {
+ auto_delete_preference: params[:auto_delete_preference],
+ },
+ )
- if bookmark_manager.errors.empty?
- return render json: success_json.merge(id: bookmark.id)
- end
+ return render json: success_json.merge(id: bookmark.id) if bookmark_manager.errors.empty?
render json: failed_json.merge(errors: bookmark_manager.errors.full_messages), status: 400
end
@@ -33,7 +41,8 @@ class BookmarksController < ApplicationController
def destroy
params.require(:id)
destroyed_bookmark = BookmarkManager.new(current_user).destroy(params[:id])
- render json: success_json.merge(BookmarkManager.bookmark_metadata(destroyed_bookmark, current_user))
+ render json:
+ success_json.merge(BookmarkManager.bookmark_metadata(destroyed_bookmark, current_user))
end
def update
@@ -46,13 +55,11 @@ class BookmarksController < ApplicationController
name: params[:name],
reminder_at: params[:reminder_at],
options: {
- auto_delete_preference: params[:auto_delete_preference]
- }
+ auto_delete_preference: params[:auto_delete_preference],
+ },
)
- if bookmark_manager.errors.empty?
- return render json: success_json
- end
+ return render json: success_json if bookmark_manager.errors.empty?
render json: failed_json.merge(errors: bookmark_manager.errors.full_messages), status: 400
end
@@ -63,9 +70,7 @@ class BookmarksController < ApplicationController
bookmark_manager = BookmarkManager.new(current_user)
bookmark_manager.toggle_pin(bookmark_id: params[:bookmark_id])
- if bookmark_manager.errors.empty?
- return render json: success_json
- end
+ return render json: success_json if bookmark_manager.errors.empty?
render json: failed_json.merge(errors: bookmark_manager.errors.full_messages), status: 400
end
diff --git a/app/controllers/bootstrap_controller.rb b/app/controllers/bootstrap_controller.rb
index 8f7c4b4f62b..48a31a6e16c 100644
--- a/app/controllers/bootstrap_controller.rb
+++ b/app/controllers/bootstrap_controller.rb
@@ -37,35 +37,34 @@ class BootstrapController < ApplicationController
assets_fake_request.env["QUERY_STRING"] = query
end
- Discourse.find_plugin_css_assets(
- include_official: allow_plugins?,
- include_unofficial: allow_third_party_plugins?,
- mobile_view: mobile_view?,
- desktop_view: !mobile_view?,
- request: assets_fake_request
- ).each do |file|
- add_style(file, plugin: true)
- end
+ Discourse
+ .find_plugin_css_assets(
+ include_official: allow_plugins?,
+ include_unofficial: allow_third_party_plugins?,
+ mobile_view: mobile_view?,
+ desktop_view: !mobile_view?,
+ request: assets_fake_request,
+ )
+ .each { |file| add_style(file, plugin: true) }
add_style(mobile_view? ? :mobile_theme : :desktop_theme) if theme_id.present?
extra_locales = []
if ExtraLocalesController.client_overrides_exist?
- extra_locales << ExtraLocalesController.url('overrides')
+ extra_locales << ExtraLocalesController.url("overrides")
end
- if staff?
- extra_locales << ExtraLocalesController.url('admin')
- end
+ extra_locales << ExtraLocalesController.url("admin") if staff?
- if admin?
- extra_locales << ExtraLocalesController.url('wizard')
- end
+ extra_locales << ExtraLocalesController.url("wizard") if admin?
- plugin_js = Discourse.find_plugin_js_assets(
- include_official: allow_plugins?,
- include_unofficial: allow_third_party_plugins?,
- request: assets_fake_request
- ).map { |f| script_asset_path(f) }
+ plugin_js =
+ Discourse
+ .find_plugin_js_assets(
+ include_official: allow_plugins?,
+ include_unofficial: allow_third_party_plugins?,
+ request: assets_fake_request,
+ )
+ .map { |f| script_asset_path(f) }
plugin_test_js =
if Rails.env != "production"
@@ -76,7 +75,7 @@ class BootstrapController < ApplicationController
bootstrap = {
theme_id: theme_id,
- theme_color: "##{ColorScheme.hex_for_name('header_background', scheme_id)}",
+ theme_color: "##{ColorScheme.hex_for_name("header_background", scheme_id)}",
title: SiteSetting.title,
current_homepage: current_homepage,
locale_script: locale,
@@ -90,7 +89,7 @@ class BootstrapController < ApplicationController
html_classes: html_classes,
html_lang: html_lang,
login_path: main_app.login_path,
- authentication_data: authentication_data
+ authentication_data: authentication_data,
}
bootstrap[:extra_locales] = extra_locales if extra_locales.present?
bootstrap[:csrf_token] = form_authenticity_token if current_user
@@ -99,39 +98,44 @@ class BootstrapController < ApplicationController
end
def plugin_css_for_tests
- urls = Discourse.find_plugin_css_assets(
- include_disabled: true,
- desktop_view: true,
- ).map do |target|
- details = Stylesheet::Manager.new().stylesheet_details(target, 'all')
- details[0][:new_href]
- end
+ urls =
+ Discourse
+ .find_plugin_css_assets(include_disabled: true, desktop_view: true)
+ .map do |target|
+ details = Stylesheet::Manager.new().stylesheet_details(target, "all")
+ details[0][:new_href]
+ end
stylesheet = <<~CSS
/* For use in tests only - `@import`s all plugin stylesheets */
- #{urls.map { |url| "@import \"#{url}\";" }.join("\n") }
+ #{urls.map { |url| "@import \"#{url}\";" }.join("\n")}
CSS
- render plain: stylesheet, content_type: 'text/css'
+ render plain: stylesheet, content_type: "text/css"
end
-private
+ private
+
def add_scheme(scheme_id, media, css_class)
return if scheme_id.to_i == -1
- if style = Stylesheet::Manager.new(theme_id: theme_id).color_scheme_stylesheet_details(scheme_id, media)
+ if style =
+ Stylesheet::Manager.new(theme_id: theme_id).color_scheme_stylesheet_details(
+ scheme_id,
+ media,
+ )
@stylesheets << { href: style[:new_href], media: media, class: css_class }
end
end
def add_style(target, opts = nil)
- if styles = Stylesheet::Manager.new(theme_id: theme_id).stylesheet_details(target, 'all')
+ if styles = Stylesheet::Manager.new(theme_id: theme_id).stylesheet_details(target, "all")
styles.each do |style|
@stylesheets << {
href: style[:new_href],
- media: 'all',
+ media: "all",
theme_id: style[:theme_id],
- target: style[:target]
+ target: style[:target],
}.merge(opts || {})
end
end
@@ -150,7 +154,11 @@ private
end
def add_plugin_html(html, key)
- add_if_present(html, key, DiscoursePluginRegistry.build_html("server:#{key.to_s.dasherize}", self))
+ add_if_present(
+ html,
+ key,
+ DiscoursePluginRegistry.build_html("server:#{key.to_s.dasherize}", self),
+ )
end
def create_theme_html
@@ -159,10 +167,14 @@ private
theme_view = mobile_view? ? :mobile : :desktop
- add_if_present(theme_html, :body_tag, Theme.lookup_field(theme_id, theme_view, 'body_tag'))
- add_if_present(theme_html, :head_tag, Theme.lookup_field(theme_id, theme_view, 'head_tag'))
- add_if_present(theme_html, :header, Theme.lookup_field(theme_id, theme_view, 'header'))
- add_if_present(theme_html, :translations, Theme.lookup_field(theme_id, :translations, I18n.locale))
+ add_if_present(theme_html, :body_tag, Theme.lookup_field(theme_id, theme_view, "body_tag"))
+ add_if_present(theme_html, :head_tag, Theme.lookup_field(theme_id, theme_view, "head_tag"))
+ add_if_present(theme_html, :header, Theme.lookup_field(theme_id, theme_view, "header"))
+ add_if_present(
+ theme_html,
+ :translations,
+ Theme.lookup_field(theme_id, :translations, I18n.locale),
+ )
add_if_present(theme_html, :js, Theme.lookup_field(theme_id, :extra_js, nil))
theme_html
@@ -171,5 +183,4 @@ private
def add_if_present(hash, key, val)
hash[key] = val if val.present?
end
-
end
diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb
index d6e1a6e2ded..c907c3829c7 100644
--- a/app/controllers/categories_controller.rb
+++ b/app/controllers/categories_controller.rb
@@ -3,11 +3,19 @@
class CategoriesController < ApplicationController
include TopicQueryParams
- requires_login except: [:index, :categories_and_latest, :categories_and_top, :show, :redirect, :find_by_slug, :visible_groups]
+ requires_login except: %i[
+ index
+ categories_and_latest
+ categories_and_top
+ show
+ redirect
+ find_by_slug
+ visible_groups
+ ]
- before_action :fetch_category, only: [:show, :update, :destroy, :visible_groups]
- before_action :initialize_staff_action_logger, only: [:create, :update, :destroy]
- skip_before_action :check_xhr, only: [:index, :categories_and_latest, :categories_and_top, :redirect]
+ before_action :fetch_category, only: %i[show update destroy visible_groups]
+ before_action :initialize_staff_action_logger, only: %i[create update destroy]
+ skip_before_action :check_xhr, only: %i[index categories_and_latest categories_and_top redirect]
SYMMETRICAL_CATEGORIES_TO_TOPICS_FACTOR = 1.5
MIN_CATEGORIES_TOPICS = 5
@@ -22,17 +30,20 @@ class CategoriesController < ApplicationController
@description = SiteSetting.site_description
- parent_category = Category.find_by_slug(params[:parent_category_id]) || Category.find_by(id: params[:parent_category_id].to_i)
+ parent_category =
+ Category.find_by_slug(params[:parent_category_id]) ||
+ Category.find_by(id: params[:parent_category_id].to_i)
- include_subcategories = SiteSetting.desktop_category_page_style == "subcategories_with_featured_topics" ||
- params[:include_subcategories] == "true"
+ include_subcategories =
+ SiteSetting.desktop_category_page_style == "subcategories_with_featured_topics" ||
+ params[:include_subcategories] == "true"
category_options = {
is_homepage: current_homepage == "categories",
parent_category_id: params[:parent_category_id],
include_topics: include_topics(parent_category),
include_subcategories: include_subcategories,
- tag: params[:tag]
+ tag: params[:tag],
}
@category_list = CategoryList.new(guardian, category_options)
@@ -40,35 +51,38 @@ class CategoriesController < ApplicationController
if category_options[:is_homepage] && SiteSetting.short_site_description.present?
@title = "#{SiteSetting.title} - #{SiteSetting.short_site_description}"
elsif !category_options[:is_homepage]
- @title = "#{I18n.t('js.filters.categories.title')} - #{SiteSetting.title}"
+ @title = "#{I18n.t("js.filters.categories.title")} - #{SiteSetting.title}"
end
respond_to do |format|
format.html do
- store_preloaded(@category_list.preload_key, MultiJson.dump(CategoryListSerializer.new(@category_list, scope: guardian)))
+ store_preloaded(
+ @category_list.preload_key,
+ MultiJson.dump(CategoryListSerializer.new(@category_list, scope: guardian)),
+ )
style = SiteSetting.desktop_category_page_style
- topic_options = {
- per_page: CategoriesController.topics_per_page,
- no_definitions: true,
- }
+ topic_options = { per_page: CategoriesController.topics_per_page, no_definitions: true }
if style == "categories_and_latest_topics_created_date"
- topic_options[:order] = 'created'
+ topic_options[:order] = "created"
@topic_list = TopicQuery.new(current_user, topic_options).list_latest
@topic_list.more_topics_url = url_for(public_send("latest_path", sort: :created))
elsif style == "categories_and_latest_topics"
@topic_list = TopicQuery.new(current_user, topic_options).list_latest
@topic_list.more_topics_url = url_for(public_send("latest_path"))
elsif style == "categories_and_top_topics"
- @topic_list = TopicQuery.new(current_user, topic_options).list_top_for(SiteSetting.top_page_default_timeframe.to_sym)
+ @topic_list =
+ TopicQuery.new(current_user, topic_options).list_top_for(
+ SiteSetting.top_page_default_timeframe.to_sym,
+ )
@topic_list.more_topics_url = url_for(public_send("top_path"))
end
if @topic_list.present? && @topic_list.topics.present?
store_preloaded(
@topic_list.preload_key,
- MultiJson.dump(TopicListSerializer.new(@topic_list, scope: guardian))
+ MultiJson.dump(TopicListSerializer.new(@topic_list, scope: guardian)),
)
end
@@ -109,7 +123,9 @@ class CategoriesController < ApplicationController
by_category = Hash[change_requests.map { |cat, pos| [Category.find(cat.to_i), pos] }]
unless guardian.is_admin?
- raise Discourse::InvalidAccess unless by_category.keys.all? { |c| guardian.can_see_category? c }
+ unless by_category.keys.all? { |c| guardian.can_see_category? c }
+ raise Discourse::InvalidAccess
+ end
end
by_category.each do |cat, pos|
@@ -187,14 +203,12 @@ class CategoriesController < ApplicationController
@category,
old_category_params,
old_permissions: old_permissions,
- old_custom_fields: old_custom_fields
+ old_custom_fields: old_custom_fields,
)
end
end
- if result
- DiscourseEvent.trigger(:category_updated, cat)
- end
+ DiscourseEvent.trigger(:category_updated, cat) if result
result
end
@@ -207,7 +221,7 @@ class CategoriesController < ApplicationController
custom_slug = params[:slug].to_s
if custom_slug.blank?
- error = @category.errors.full_message(:slug, I18n.t('errors.messages.blank'))
+ error = @category.errors.full_message(:slug, I18n.t("errors.messages.blank"))
render_json_error(error)
elsif @category.update(slug: custom_slug)
render json: success_json
@@ -221,7 +235,13 @@ class CategoriesController < ApplicationController
notification_level = params[:notification_level].to_i
CategoryUser.set_notification_level_for_category(current_user, notification_level, category_id)
- render json: success_json.merge({ indirectly_muted_category_ids: CategoryUser.indirectly_muted_category_ids(current_user) })
+ render json:
+ success_json.merge(
+ {
+ indirectly_muted_category_ids:
+ CategoryUser.indirectly_muted_category_ids(current_user),
+ },
+ )
end
def destroy
@@ -237,34 +257,40 @@ class CategoriesController < ApplicationController
def find_by_slug
params.require(:category_slug)
- @category = Category.find_by_slug_path(params[:category_slug].split('/'))
+ @category = Category.find_by_slug_path(params[:category_slug].split("/"))
raise Discourse::NotFound unless @category.present?
if !guardian.can_see?(@category)
if SiteSetting.detailed_404 && group = @category.access_category_via_group
raise Discourse::InvalidAccess.new(
- 'not in group',
- @category,
- custom_message: 'not_in_group.title_category',
- custom_message_params: { group: group.name },
- group: group
- )
+ "not in group",
+ @category,
+ custom_message: "not_in_group.title_category",
+ custom_message_params: {
+ group: group.name,
+ },
+ group: group,
+ )
else
raise Discourse::NotFound
end
end
- @category.permission = CategoryGroup.permission_types[:full] if Category.topic_create_allowed(guardian).where(id: @category.id).exists?
+ @category.permission = CategoryGroup.permission_types[:full] if Category
+ .topic_create_allowed(guardian)
+ .where(id: @category.id)
+ .exists?
render_serialized(@category, CategorySerializer)
end
def visible_groups
@guardian.ensure_can_see!(@category)
- groups = if !@category.groups.exists?(id: Group::AUTO_GROUPS[:everyone])
- @category.groups.merge(Group.visible_groups(current_user)).pluck("name")
- end
+ groups =
+ if !@category.groups.exists?(id: Group::AUTO_GROUPS[:everyone])
+ @category.groups.merge(Group.visible_groups(current_user)).pluck("name")
+ end
render json: success_json.merge(groups: groups || [])
end
@@ -285,17 +311,14 @@ class CategoriesController < ApplicationController
category_options = {
is_homepage: current_homepage == "categories",
parent_category_id: params[:parent_category_id],
- include_topics: false
+ include_topics: false,
}
- topic_options = {
- per_page: CategoriesController.topics_per_page,
- no_definitions: true,
- }
+ topic_options = { per_page: CategoriesController.topics_per_page, no_definitions: true }
topic_options.merge!(build_topic_list_options)
style = SiteSetting.desktop_category_page_style
- topic_options[:order] = 'created' if style == "categories_and_latest_topics_created_date"
+ topic_options[:order] = "created" if style == "categories_and_latest_topics_created_date"
result = CategoryAndTopicLists.new
result.category_list = CategoryList.new(guardian, category_options)
@@ -303,9 +326,10 @@ class CategoriesController < ApplicationController
if topics_filter == :latest
result.topic_list = TopicQuery.new(current_user, topic_options).list_latest
elsif topics_filter == :top
- result.topic_list = TopicQuery.new(current_user, topic_options).list_top_for(
- SiteSetting.top_page_default_timeframe.to_sym
- )
+ result.topic_list =
+ TopicQuery.new(current_user, topic_options).list_top_for(
+ SiteSetting.top_page_default_timeframe.to_sym,
+ )
end
render_serialized(result, CategoryAndTopicListsSerializer, root: false)
@@ -316,88 +340,90 @@ class CategoriesController < ApplicationController
end
def required_create_params
- required_param_keys.each do |key|
- params.require(key)
- end
+ required_param_keys.each { |key| params.require(key) }
category_params
end
def category_params
- @category_params ||= begin
- if p = params[:permissions]
- p.each do |k, v|
- p[k] = v.to_i
+ @category_params ||=
+ begin
+ if p = params[:permissions]
+ p.each { |k, v| p[k] = v.to_i }
end
+
+ if SiteSetting.tagging_enabled
+ params[:allowed_tags] = params[:allowed_tags].presence || [] if params[:allowed_tags]
+ params[:allowed_tag_groups] = params[:allowed_tag_groups].presence || [] if params[
+ :allowed_tag_groups
+ ]
+ params[:required_tag_groups] = params[:required_tag_groups].presence || [] if params[
+ :required_tag_groups
+ ]
+ end
+
+ if SiteSetting.enable_category_group_moderation?
+ params[:reviewable_by_group_id] = Group.where(
+ name: params[:reviewable_by_group_name],
+ ).pluck_first(:id) if params[:reviewable_by_group_name]
+ end
+
+ result =
+ params.permit(
+ *required_param_keys,
+ :position,
+ :name,
+ :color,
+ :text_color,
+ :email_in,
+ :email_in_allow_strangers,
+ :mailinglist_mirror,
+ :all_topics_wiki,
+ :allow_unlimited_owner_edits_on_first_post,
+ :default_slow_mode_seconds,
+ :parent_category_id,
+ :auto_close_hours,
+ :auto_close_based_on_last_post,
+ :uploaded_logo_id,
+ :uploaded_logo_dark_id,
+ :uploaded_background_id,
+ :slug,
+ :allow_badges,
+ :topic_template,
+ :sort_order,
+ :sort_ascending,
+ :topic_featured_link_allowed,
+ :show_subcategory_list,
+ :num_featured_topics,
+ :default_view,
+ :subcategory_list_style,
+ :default_top_period,
+ :minimum_required_tags,
+ :navigate_to_first_post_after_read,
+ :search_priority,
+ :allow_global_tags,
+ :read_only_banner,
+ :default_list_filter,
+ :reviewable_by_group_id,
+ custom_fields: [custom_field_params],
+ permissions: [*p.try(:keys)],
+ allowed_tags: [],
+ allowed_tag_groups: [],
+ required_tag_groups: %i[name min_count],
+ )
+
+ if result[:required_tag_groups] && !result[:required_tag_groups].is_a?(Array)
+ raise Discourse::InvalidParameters.new(:required_tag_groups)
+ end
+
+ result
end
-
- if SiteSetting.tagging_enabled
- params[:allowed_tags] = params[:allowed_tags].presence || [] if params[:allowed_tags]
- params[:allowed_tag_groups] = params[:allowed_tag_groups].presence || [] if params[:allowed_tag_groups]
- params[:required_tag_groups] = params[:required_tag_groups].presence || [] if params[:required_tag_groups]
- end
-
- if SiteSetting.enable_category_group_moderation?
- params[:reviewable_by_group_id] = Group.where(name: params[:reviewable_by_group_name]).pluck_first(:id) if params[:reviewable_by_group_name]
- end
-
- result = params.permit(
- *required_param_keys,
- :position,
- :name,
- :color,
- :text_color,
- :email_in,
- :email_in_allow_strangers,
- :mailinglist_mirror,
- :all_topics_wiki,
- :allow_unlimited_owner_edits_on_first_post,
- :default_slow_mode_seconds,
- :parent_category_id,
- :auto_close_hours,
- :auto_close_based_on_last_post,
- :uploaded_logo_id,
- :uploaded_logo_dark_id,
- :uploaded_background_id,
- :slug,
- :allow_badges,
- :topic_template,
- :sort_order,
- :sort_ascending,
- :topic_featured_link_allowed,
- :show_subcategory_list,
- :num_featured_topics,
- :default_view,
- :subcategory_list_style,
- :default_top_period,
- :minimum_required_tags,
- :navigate_to_first_post_after_read,
- :search_priority,
- :allow_global_tags,
- :read_only_banner,
- :default_list_filter,
- :reviewable_by_group_id,
- custom_fields: [custom_field_params],
- permissions: [*p.try(:keys)],
- allowed_tags: [],
- allowed_tag_groups: [],
- required_tag_groups: [:name, :min_count]
- )
-
- if result[:required_tag_groups] && !result[:required_tag_groups].is_a?(Array)
- raise Discourse::InvalidParameters.new(:required_tag_groups)
- end
-
- result
- end
end
def custom_field_params
keys = params[:custom_fields].try(:keys)
return if keys.blank?
- keys.map do |key|
- params[:custom_fields][key].is_a?(Array) ? { key => [] } : key
- end
+ keys.map { |key| params[:custom_fields][key].is_a?(Array) ? { key => [] } : key }
end
def fetch_category
@@ -411,12 +437,9 @@ class CategoriesController < ApplicationController
def include_topics(parent_category = nil)
style = SiteSetting.desktop_category_page_style
- view_context.mobile_view? ||
- params[:include_topics] ||
+ view_context.mobile_view? || params[:include_topics] ||
(parent_category && parent_category.subcategory_list_includes_topics?) ||
- style == "categories_with_featured_topics" ||
- style == "subcategories_with_featured_topics" ||
- style == "categories_boxes_with_topics" ||
- style == "categories_with_top_topics"
+ style == "categories_with_featured_topics" || style == "subcategories_with_featured_topics" ||
+ style == "categories_boxes_with_topics" || style == "categories_with_top_topics"
end
end
diff --git a/app/controllers/clicks_controller.rb b/app/controllers/clicks_controller.rb
index 5b932484e7b..59dabcd121b 100644
--- a/app/controllers/clicks_controller.rb
+++ b/app/controllers/clicks_controller.rb
@@ -4,17 +4,16 @@ class ClicksController < ApplicationController
skip_before_action :check_xhr, :preload_json, :verify_authenticity_token
def track
- params.require([:url, :post_id, :topic_id])
+ params.require(%i[url post_id topic_id])
TopicLinkClick.create_from(
url: params[:url],
post_id: params[:post_id],
topic_id: params[:topic_id],
ip: request.remote_ip,
- user_id: current_user&.id
+ user_id: current_user&.id,
)
render json: success_json
end
-
end
diff --git a/app/controllers/composer_controller.rb b/app/controllers/composer_controller.rb
index fd4847e115a..f558a890eb5 100644
--- a/app/controllers/composer_controller.rb
+++ b/app/controllers/composer_controller.rb
@@ -13,12 +13,13 @@ class ComposerController < ApplicationController
end
# allowed_names is necessary just for new private messages.
- @allowed_names = if params[:allowed_names].present?
- raise Discourse::InvalidParameters(:allowed_names) if !params[:allowed_names].is_a?(Array)
- params[:allowed_names] << current_user.username
- else
- []
- end
+ @allowed_names =
+ if params[:allowed_names].present?
+ raise Discourse.InvalidParameters(:allowed_names) if !params[:allowed_names].is_a?(Array)
+ params[:allowed_names] << current_user.username
+ else
+ []
+ end
user_reasons = {}
group_reasons = {}
@@ -33,64 +34,73 @@ class ComposerController < ApplicationController
end
if @topic && @names.include?(SiteSetting.here_mention) && guardian.can_mention_here?
- here_count = PostAlerter.new.expand_here_mention(@topic.first_post, exclude_ids: [current_user.id]).size
+ here_count =
+ PostAlerter.new.expand_here_mention(@topic.first_post, exclude_ids: [current_user.id]).size
end
- serialized_groups = groups.values.reduce({}) do |hash, group|
- serialized_group = { user_count: group.user_count }
+ serialized_groups =
+ groups
+ .values
+ .reduce({}) do |hash, group|
+ serialized_group = { user_count: group.user_count }
- if group_reasons[group.name] == :not_allowed &&
- members_visible_group_ids.include?(group.id) &&
- (@topic&.private_message? || @allowed_names.present?)
+ if group_reasons[group.name] == :not_allowed &&
+ members_visible_group_ids.include?(group.id) &&
+ (@topic&.private_message? || @allowed_names.present?)
+ # Find users that are notified already because they have been invited
+ # directly or via a group
+ notified_count =
+ GroupUser
+ # invited directly
+ .where(user_id: topic_allowed_user_ids)
+ .or(
+ # invited via a group
+ GroupUser.where(
+ user_id: GroupUser.where(group_id: topic_allowed_group_ids).select(:user_id),
+ ),
+ )
+ .where(group_id: group.id)
+ .select(:user_id)
+ .distinct
+ .count
- # Find users that are notified already because they have been invited
- # directly or via a group
- notified_count = GroupUser
- # invited directly
- .where(user_id: topic_allowed_user_ids)
- .or(
- # invited via a group
- GroupUser.where(
- user_id: GroupUser.where(group_id: topic_allowed_group_ids).select(:user_id)
- )
- )
- .where(group_id: group.id)
- .select(:user_id).distinct.count
+ if notified_count > 0
+ group_reasons[group.name] = :some_not_allowed
+ serialized_group[:notified_count] = notified_count
+ end
+ end
- if notified_count > 0
- group_reasons[group.name] = :some_not_allowed
- serialized_group[:notified_count] = notified_count
+ hash[group.name] = serialized_group
+ hash
end
- end
-
- hash[group.name] = serialized_group
- hash
- end
render json: {
- users: users.keys,
- user_reasons: user_reasons,
- groups: serialized_groups,
- group_reasons: group_reasons,
- here_count: here_count,
- max_users_notified_per_group_mention: SiteSetting.max_users_notified_per_group_mention,
- }
+ users: users.keys,
+ user_reasons: user_reasons,
+ groups: serialized_groups,
+ group_reasons: group_reasons,
+ here_count: here_count,
+ max_users_notified_per_group_mention: SiteSetting.max_users_notified_per_group_mention,
+ }
end
private
def user_reason(user)
- reason = if @topic && !user.guardian.can_see?(@topic)
- @topic.private_message? ? :private : :category
- elsif @allowed_names.present? && !is_user_allowed?(user, topic_allowed_user_ids, topic_allowed_group_ids)
- # This would normally be handled by the previous if, but that does not work for new private messages.
- :private
- elsif topic_muted_by.include?(user.id)
- :muted_topic
- elsif @topic&.private_message? && !is_user_allowed?(user, topic_allowed_user_ids, topic_allowed_group_ids)
- # Admins can see the topic, but they will not be mentioned if they were not invited.
- :not_allowed
- end
+ reason =
+ if @topic && !user.guardian.can_see?(@topic)
+ @topic.private_message? ? :private : :category
+ elsif @allowed_names.present? &&
+ !is_user_allowed?(user, topic_allowed_user_ids, topic_allowed_group_ids)
+ # This would normally be handled by the previous if, but that does not work for new private messages.
+ :private
+ elsif topic_muted_by.include?(user.id)
+ :muted_topic
+ elsif @topic&.private_message? &&
+ !is_user_allowed?(user, topic_allowed_user_ids, topic_allowed_group_ids)
+ # Admins can see the topic, but they will not be mentioned if they were not invited.
+ :not_allowed
+ end
# Regular users can see only basic information why the users cannot see the topic.
reason = nil if !guardian.is_staff? && reason != :private && reason != :category
@@ -101,7 +111,8 @@ class ComposerController < ApplicationController
def group_reason(group)
if !mentionable_group_ids.include?(group.id)
:not_mentionable
- elsif (@topic&.private_message? || @allowed_names.present?) && !topic_allowed_group_ids.include?(group.id)
+ elsif (@topic&.private_message? || @allowed_names.present?) &&
+ !topic_allowed_group_ids.include?(group.id)
:not_allowed
end
end
@@ -111,74 +122,57 @@ class ComposerController < ApplicationController
end
def users
- @users ||= User
- .not_staged
- .where(username_lower: @names.map(&:downcase))
- .index_by(&:username_lower)
+ @users ||=
+ User.not_staged.where(username_lower: @names.map(&:downcase)).index_by(&:username_lower)
end
def groups
- @groups ||= Group
- .visible_groups(current_user)
- .where('lower(name) IN (?)', @names.map(&:downcase))
- .index_by(&:name)
+ @groups ||=
+ Group
+ .visible_groups(current_user)
+ .where("lower(name) IN (?)", @names.map(&:downcase))
+ .index_by(&:name)
end
def mentionable_group_ids
- @mentionable_group_ids ||= Group
- .mentionable(current_user, include_public: false)
- .where(name: @names)
- .pluck(:id)
- .to_set
+ @mentionable_group_ids ||=
+ Group.mentionable(current_user, include_public: false).where(name: @names).pluck(:id).to_set
end
def members_visible_group_ids
- @members_visible_group_ids ||= Group
- .members_visible_groups(current_user)
- .where(name: @names)
- .pluck(:id)
- .to_set
+ @members_visible_group_ids ||=
+ Group.members_visible_groups(current_user).where(name: @names).pluck(:id).to_set
end
def topic_muted_by
- @topic_muted_by ||= if @topic.present?
- TopicUser
- .where(topic: @topic)
- .where(user_id: users.values.map(&:id))
- .where(notification_level: TopicUser.notification_levels[:muted])
- .pluck(:user_id)
- .to_set
- else
- Set.new
- end
+ @topic_muted_by ||=
+ if @topic.present?
+ TopicUser
+ .where(topic: @topic)
+ .where(user_id: users.values.map(&:id))
+ .where(notification_level: TopicUser.notification_levels[:muted])
+ .pluck(:user_id)
+ .to_set
+ else
+ Set.new
+ end
end
def topic_allowed_user_ids
- @topic_allowed_user_ids ||= if @allowed_names.present?
- User
- .where(username_lower: @allowed_names.map(&:downcase))
- .pluck(:id)
- .to_set
- elsif @topic&.private_message?
- TopicAllowedUser
- .where(topic: @topic)
- .pluck(:user_id)
- .to_set
- end
+ @topic_allowed_user_ids ||=
+ if @allowed_names.present?
+ User.where(username_lower: @allowed_names.map(&:downcase)).pluck(:id).to_set
+ elsif @topic&.private_message?
+ TopicAllowedUser.where(topic: @topic).pluck(:user_id).to_set
+ end
end
def topic_allowed_group_ids
- @topic_allowed_group_ids ||= if @allowed_names.present?
- Group
- .messageable(current_user)
- .where(name: @allowed_names)
- .pluck(:id)
- .to_set
- elsif @topic&.private_message?
- TopicAllowedGroup
- .where(topic: @topic)
- .pluck(:group_id)
- .to_set
- end
+ @topic_allowed_group_ids ||=
+ if @allowed_names.present?
+ Group.messageable(current_user).where(name: @allowed_names).pluck(:id).to_set
+ elsif @topic&.private_message?
+ TopicAllowedGroup.where(topic: @topic).pluck(:group_id).to_set
+ end
end
end
diff --git a/app/controllers/composer_messages_controller.rb b/app/controllers/composer_messages_controller.rb
index b8303014559..3785e257288 100644
--- a/app/controllers/composer_messages_controller.rb
+++ b/app/controllers/composer_messages_controller.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
class ComposerMessagesController < ApplicationController
-
requires_login
def index
- finder = ComposerMessagesFinder.new(current_user, params.slice(:composer_action, :topic_id, :post_id))
+ finder =
+ ComposerMessagesFinder.new(current_user, params.slice(:composer_action, :topic_id, :post_id))
json = { composer_messages: [finder.find].compact }
if params[:topic_id].present?
@@ -25,14 +25,24 @@ class ComposerMessagesController < ApplicationController
warning_message = nil
if user_count > 0
- message_locale = if user_count == 1
- "education.user_not_seen_in_a_while.single"
- else
- "education.user_not_seen_in_a_while.multiple"
- end
+ message_locale =
+ if user_count == 1
+ "education.user_not_seen_in_a_while.single"
+ else
+ "education.user_not_seen_in_a_while.multiple"
+ end
end
- json = { user_count: user_count, usernames: users, time_ago: FreedomPatches::Rails4.time_ago_in_words(SiteSetting.pm_warn_user_last_seen_months_ago.month.ago, true, scope: :'datetime.distance_in_words_verbose') }
+ json = {
+ user_count: user_count,
+ usernames: users,
+ time_ago:
+ FreedomPatches::Rails4.time_ago_in_words(
+ SiteSetting.pm_warn_user_last_seen_months_ago.month.ago,
+ true,
+ scope: :"datetime.distance_in_words_verbose",
+ ),
+ }
render_json_dump(json)
end
end
diff --git a/app/controllers/csp_reports_controller.rb b/app/controllers/csp_reports_controller.rb
index d18fd7d1c2c..ac206da5b30 100644
--- a/app/controllers/csp_reports_controller.rb
+++ b/app/controllers/csp_reports_controller.rb
@@ -10,12 +10,11 @@ class CspReportsController < ApplicationController
if report.blank?
render_json_error("empty CSP report", status: 422)
else
- Logster.add_to_env(request.env, 'CSP Report', report)
- Rails.logger.warn("CSP Violation: '#{report['blocked-uri']}' \n\n#{report['script-sample']}")
+ Logster.add_to_env(request.env, "CSP Report", report)
+ Rails.logger.warn("CSP Violation: '#{report["blocked-uri"]}' \n\n#{report["script-sample"]}")
head :ok
end
-
rescue JSON::ParserError
render_json_error("invalid CSP report", status: 422)
end
@@ -25,20 +24,20 @@ class CspReportsController < ApplicationController
def parse_report
obj = JSON.parse(request.body.read)
if Hash === obj
- obj = obj['csp-report']
+ obj = obj["csp-report"]
if Hash === obj
obj.slice(
- 'blocked-uri',
- 'disposition',
- 'document-uri',
- 'effective-directive',
- 'original-policy',
- 'referrer',
- 'script-sample',
- 'status-code',
- 'violated-directive',
- 'line-number',
- 'source-file'
+ "blocked-uri",
+ "disposition",
+ "document-uri",
+ "effective-directive",
+ "original-policy",
+ "referrer",
+ "script-sample",
+ "status-code",
+ "violated-directive",
+ "line-number",
+ "source-file",
)
end
end
diff --git a/app/controllers/directory_columns_controller.rb b/app/controllers/directory_columns_controller.rb
index d11f5e30ff5..572c7e92ad4 100644
--- a/app/controllers/directory_columns_controller.rb
+++ b/app/controllers/directory_columns_controller.rb
@@ -3,6 +3,8 @@
class DirectoryColumnsController < ApplicationController
def index
directory_columns = DirectoryColumn.includes(:user_field).where(enabled: true).order(:position)
- render_json_dump(directory_columns: serialize_data(directory_columns, DirectoryColumnSerializer))
+ render_json_dump(
+ directory_columns: serialize_data(directory_columns, DirectoryColumnSerializer),
+ )
end
end
diff --git a/app/controllers/directory_items_controller.rb b/app/controllers/directory_items_controller.rb
index 692088cdc55..15f1451d5a8 100644
--- a/app/controllers/directory_items_controller.rb
+++ b/app/controllers/directory_items_controller.rb
@@ -4,7 +4,9 @@ class DirectoryItemsController < ApplicationController
PAGE_SIZE = 50
def index
- raise Discourse::InvalidAccess.new(:enable_user_directory) unless SiteSetting.enable_user_directory?
+ 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]
@@ -23,30 +25,36 @@ class DirectoryItemsController < ApplicationController
end
if params[:exclude_usernames]
- result = result.references(:user).where.not(users: { username: params[:exclude_usernames].split(",") })
+ 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'
+ 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'
+ 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}")
+ 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
- if period_type == DirectoryItem.period_types[:all]
- result = result.includes(:user_stat)
- end
+ result = result.includes(:user_stat) if period_type == DirectoryItem.period_types[:all]
page = params[:page].to_i
user_ids = nil
@@ -54,12 +62,10 @@ class DirectoryItemsController < ApplicationController
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
- if current_user && result.dup.where(user_id: user_ids).exists?
- user_ids << current_user.id
- end
+ 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')
+ result = result.where("false")
end
end
@@ -68,7 +74,7 @@ class DirectoryItemsController < ApplicationController
if user_id
result = result.where(user_id: user_id)
else
- result = result.where('false')
+ result = result.where("false")
end
end
@@ -82,7 +88,6 @@ class DirectoryItemsController < ApplicationController
# 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
@@ -90,7 +95,6 @@ class DirectoryItemsController < ApplicationController
your_item = DirectoryItem.where(period_type: period_type, user_id: current_user.id).first
result.insert(0, your_item) if your_item
end
-
end
last_updated_at = DirectoryItem.last_updated_at(period_type)
@@ -101,7 +105,9 @@ class DirectoryItemsController < ApplicationController
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
+ serializer_opts[:user_custom_field_map][
+ "#{User::USER_FIELD_PREFIX}#{user_field_id}"
+ ] = user_field_id
end
end
@@ -112,12 +118,13 @@ class DirectoryItemsController < ApplicationController
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
- }
- )
+ 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
end
diff --git a/app/controllers/do_not_disturb_controller.rb b/app/controllers/do_not_disturb_controller.rb
index db24c7167c6..42d32c9b709 100644
--- a/app/controllers/do_not_disturb_controller.rb
+++ b/app/controllers/do_not_disturb_controller.rb
@@ -6,11 +6,23 @@ class DoNotDisturbController < ApplicationController
def create
raise Discourse::InvalidParameters.new(:duration) if params[:duration].blank?
- duration_minutes = (Integer(params[:duration]) rescue false)
+ duration_minutes =
+ (
+ begin
+ Integer(params[:duration])
+ rescue StandardError
+ false
+ end
+ )
- ends_at = duration_minutes ?
- ends_at_from_minutes(duration_minutes) :
- ends_at_from_string(params[:duration])
+ ends_at =
+ (
+ if duration_minutes
+ ends_at_from_minutes(duration_minutes)
+ else
+ ends_at_from_string(params[:duration])
+ end
+ )
new_timing = current_user.do_not_disturb_timings.new(starts_at: Time.zone.now, ends_at: ends_at)
@@ -37,7 +49,7 @@ class DoNotDisturbController < ApplicationController
end
def ends_at_from_string(string)
- if string == 'tomorrow'
+ if string == "tomorrow"
Time.now.end_of_day.utc
else
raise Discourse::InvalidParameters.new(:duration)
diff --git a/app/controllers/drafts_controller.rb b/app/controllers/drafts_controller.rb
index 86a5c254185..78d1ea4fad6 100644
--- a/app/controllers/drafts_controller.rb
+++ b/app/controllers/drafts_controller.rb
@@ -9,15 +9,9 @@ class DraftsController < ApplicationController
params.permit(:offset)
params.permit(:limit)
- stream = Draft.stream(
- user: current_user,
- offset: params[:offset],
- limit: params[:limit]
- )
+ stream = Draft.stream(user: current_user, offset: params[:offset], limit: params[:limit])
- render json: {
- drafts: stream ? serialize_data(stream, DraftSerializer) : []
- }
+ render json: { drafts: stream ? serialize_data(stream, DraftSerializer) : [] }
end
def show
@@ -38,10 +32,9 @@ class DraftsController < ApplicationController
params[:sequence].to_i,
params[:data],
params[:owner],
- force_save: params[:force_save]
+ force_save: params[:force_save],
)
rescue Draft::OutOfSequence
-
begin
if !Draft.exists?(user_id: current_user.id, draft_key: params[:draft_key])
Draft.set(
@@ -49,18 +42,17 @@ class DraftsController < ApplicationController
params[:draft_key],
DraftSequence.current(current_user, params[:draft_key]),
params[:data],
- params[:owner]
+ params[:owner],
)
else
raise Draft::OutOfSequence
end
-
rescue Draft::OutOfSequence
- render_json_error I18n.t('draft.sequence_conflict_error.title'),
- status: 409,
- extras: {
- description: I18n.t('draft.sequence_conflict_error.description')
- }
+ render_json_error I18n.t("draft.sequence_conflict_error.title"),
+ status: 409,
+ extras: {
+ description: I18n.t("draft.sequence_conflict_error.description"),
+ }
return
end
end
@@ -68,7 +60,7 @@ class DraftsController < ApplicationController
json = success_json.merge(draft_sequence: sequence)
begin
- data = JSON::parse(params[:data])
+ data = JSON.parse(params[:data])
rescue JSON::ParserError
raise Discourse::InvalidParameters.new(:data)
end
@@ -76,7 +68,8 @@ class DraftsController < ApplicationController
if data.present?
# this is a bit of a kludge we need to remove (all the parsing) too many special cases here
# we need to catch action edit and action editSharedDraft
- if data["postId"].present? && data["originalText"].present? && data["action"].to_s.start_with?("edit")
+ if data["postId"].present? && data["originalText"].present? &&
+ data["action"].to_s.start_with?("edit")
post = Post.find_by(id: data["postId"])
if post && post.raw != data["originalText"]
conflict_user = BasicUserSerializer.new(post.last_editor, root: false)
diff --git a/app/controllers/edit_directory_columns_controller.rb b/app/controllers/edit_directory_columns_controller.rb
index b40d13ce66e..4b32ca9fb29 100644
--- a/app/controllers/edit_directory_columns_controller.rb
+++ b/app/controllers/edit_directory_columns_controller.rb
@@ -18,14 +18,20 @@ class EditDirectoryColumnsController < ApplicationController
directory_column_params = params.permit(directory_columns: {})
directory_columns = DirectoryColumn.all
- has_enabled_column = directory_column_params[:directory_columns].values.any? do |column_data|
- column_data[:enabled].to_s == "true"
+ has_enabled_column =
+ directory_column_params[:directory_columns].values.any? do |column_data|
+ column_data[:enabled].to_s == "true"
+ end
+ unless has_enabled_column
+ raise Discourse::InvalidParameters, "Must have at least one column enabled"
end
- raise Discourse::InvalidParameters, "Must have at least one column enabled" unless has_enabled_column
directory_column_params[:directory_columns].values.each do |column_data|
existing_column = directory_columns.detect { |c| c.id == column_data[:id].to_i }
- if (existing_column.enabled != column_data[:enabled] || existing_column.position != column_data[:position].to_i)
+ if (
+ existing_column.enabled != column_data[:enabled] ||
+ existing_column.position != column_data[:position].to_i
+ )
existing_column.update(enabled: column_data[:enabled], position: column_data[:position])
end
end
@@ -37,7 +43,8 @@ class EditDirectoryColumnsController < ApplicationController
def ensure_user_fields_have_columns
user_fields_without_column =
- UserField.left_outer_joins(:directory_column)
+ UserField
+ .left_outer_joins(:directory_column)
.where(directory_column: { user_field_id: nil })
.where("show_on_profile=? OR show_on_user_card=?", true, true)
@@ -47,12 +54,14 @@ class EditDirectoryColumnsController < ApplicationController
new_directory_column_attrs = []
user_fields_without_column.each do |user_field|
- new_directory_column_attrs.push({
- user_field_id: user_field.id,
- enabled: false,
- type: DirectoryColumn.types[:user_field],
- position: next_position
- })
+ new_directory_column_attrs.push(
+ {
+ user_field_id: user_field.id,
+ enabled: false,
+ type: DirectoryColumn.types[:user_field],
+ position: next_position,
+ },
+ )
next_position += 1
end
diff --git a/app/controllers/email_controller.rb b/app/controllers/email_controller.rb
index b7fd4c83806..ed317022724 100644
--- a/app/controllers/email_controller.rb
+++ b/app/controllers/email_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class EmailController < ApplicationController
- layout 'no_ember'
+ layout "no_ember"
skip_before_action :check_xhr, :preload_json, :redirect_to_login_if_required
@@ -11,9 +11,7 @@ class EmailController < ApplicationController
@key_owner_found = key&.user.present?
if @found && @key_owner_found
- UnsubscribeKey
- .get_unsubscribe_strategy_for(key)
- &.prepare_unsubscribe_options(self)
+ UnsubscribeKey.get_unsubscribe_strategy_for(key)&.prepare_unsubscribe_options(self)
if current_user.present? && (@user != current_user)
@different_user = @user.name
@@ -28,17 +26,14 @@ class EmailController < ApplicationController
key = UnsubscribeKey.find_by(key: params[:key])
raise Discourse::NotFound if key.nil? || key.user.nil?
user = key.user
- updated = UnsubscribeKey.get_unsubscribe_strategy_for(key)
- &.unsubscribe(params)
+ updated = UnsubscribeKey.get_unsubscribe_strategy_for(key)&.unsubscribe(params)
if updated
cache_key = "unsub_#{SecureRandom.hex}"
Discourse.cache.write cache_key, user.email, expires_in: 1.hour
url = path("/email/unsubscribed?key=#{cache_key}")
- if key.associated_topic
- url += "&topic_id=#{key.associated_topic.id}"
- end
+ url += "&topic_id=#{key.associated_topic.id}" if key.associated_topic
redirect_to url
else
diff --git a/app/controllers/embed_controller.rb b/app/controllers/embed_controller.rb
index 3951761c73f..8ff1f870c0c 100644
--- a/app/controllers/embed_controller.rb
+++ b/app/controllers/embed_controller.rb
@@ -5,10 +5,10 @@ class EmbedController < ApplicationController
skip_before_action :check_xhr, :preload_json, :verify_authenticity_token
- before_action :prepare_embeddable, except: [ :info ]
- before_action :ensure_api_request, only: [ :info ]
+ before_action :prepare_embeddable, except: [:info]
+ before_action :ensure_api_request, only: [:info]
- layout 'embed'
+ layout "embed"
rescue_from Discourse::InvalidAccess do
if current_user.try(:admin?)
@@ -16,14 +16,14 @@ class EmbedController < ApplicationController
@show_reason = true
@hosts = EmbeddableHost.all
end
- render 'embed_error', status: 400
+ render "embed_error", status: 400
end
def topics
discourse_expires_in 1.minute
unless SiteSetting.embed_topics_list?
- render 'embed_topics_error', status: 400
+ render "embed_topics_error", status: 400
return
end
@@ -32,10 +32,12 @@ class EmbedController < ApplicationController
end
if @embed_class = params[:embed_class]
- raise Discourse::InvalidParameters.new(:embed_class) unless @embed_class =~ /^[a-zA-Z0-9\-_]+$/
+ unless @embed_class =~ /^[a-zA-Z0-9\-_]+$/
+ raise Discourse::InvalidParameters.new(:embed_class)
+ end
end
- response.headers['X-Robots-Tag'] = 'noindex, indexifembedded'
+ response.headers["X-Robots-Tag"] = "noindex, indexifembedded"
if params.has_key?(:template) && params[:template] == "complete"
@template = "complete"
@@ -46,8 +48,7 @@ class EmbedController < ApplicationController
list_options = build_topic_list_options
if params.has_key?(:per_page)
- list_options[:per_page] =
- [params[:per_page].to_i, SiteSetting.embed_topic_limit_per_page].min
+ list_options[:per_page] = [params[:per_page].to_i, SiteSetting.embed_topic_limit_per_page].min
end
if params[:allow_create]
@@ -67,11 +68,12 @@ class EmbedController < ApplicationController
valid_top_period = false
end
- @list = if valid_top_period
- topic_query.list_top_for(top_period)
- else
- topic_query.list_latest
- end
+ @list =
+ if valid_top_period
+ topic_query.list_top_for(top_period)
+ else
+ topic_query.list_latest
+ end
end
def comments
@@ -80,7 +82,7 @@ class EmbedController < ApplicationController
embed_topic_id = params[:topic_id]&.to_i
unless embed_topic_id || EmbeddableHost.url_allowed?(embed_url)
- raise Discourse::InvalidAccess.new('invalid embed host')
+ raise Discourse::InvalidAccess.new("invalid embed host")
end
topic_id = nil
@@ -91,28 +93,33 @@ class EmbedController < ApplicationController
end
if topic_id
- @topic_view = TopicView.new(topic_id,
- current_user,
- limit: SiteSetting.embed_post_limit,
- only_regular: true,
- exclude_first: true,
- exclude_deleted_users: true,
- exclude_hidden: true)
+ @topic_view =
+ TopicView.new(
+ topic_id,
+ current_user,
+ limit: SiteSetting.embed_post_limit,
+ only_regular: true,
+ exclude_first: true,
+ exclude_deleted_users: true,
+ exclude_hidden: true,
+ )
raise Discourse::NotFound if @topic_view.blank?
@posts_left = 0
@second_post_url = "#{@topic_view.topic.url}/2"
@reply_count = @topic_view.filtered_posts.count - 1
@reply_count = 0 if @reply_count < 0
- @posts_left = @reply_count - SiteSetting.embed_post_limit if @reply_count > SiteSetting.embed_post_limit
+ @posts_left = @reply_count - SiteSetting.embed_post_limit if @reply_count >
+ SiteSetting.embed_post_limit
elsif embed_url.present?
- Jobs.enqueue(:retrieve_topic,
- user_id: current_user.try(:id),
- embed_url: embed_url,
- author_username: embed_username,
- referer: request.env['HTTP_REFERER']
- )
- render 'loading'
+ Jobs.enqueue(
+ :retrieve_topic,
+ user_id: current_user.try(:id),
+ embed_url: embed_url,
+ author_username: embed_username,
+ referer: request.env["HTTP_REFERER"],
+ )
+ render "loading"
end
discourse_expires_in 1.minute
@@ -132,16 +139,16 @@ class EmbedController < ApplicationController
by_url = {}
if embed_urls.present?
- urls = embed_urls.map { |u| u.sub(/#discourse-comments$/, '').sub(/\/$/, '') }
+ urls = embed_urls.map { |u| u.sub(/#discourse-comments$/, "").sub(%r{/$}, "") }
topic_embeds = TopicEmbed.where(embed_url: urls).includes(:topic).references(:topic)
topic_embeds.each do |te|
url = te.embed_url
url = "#{url}#discourse-comments" unless params[:embed_url].include?(url)
if te.topic.present?
- by_url[url] = I18n.t('embed.replies', count: te.topic.posts_count - 1)
+ by_url[url] = I18n.t("embed.replies", count: te.topic.posts_count - 1)
else
- by_url[url] = I18n.t('embed.replies', count: 0)
+ by_url[url] = I18n.t("embed.replies", count: 0)
end
end
end
@@ -152,16 +159,18 @@ class EmbedController < ApplicationController
private
def prepare_embeddable
- response.headers.delete('X-Frame-Options')
+ response.headers.delete("X-Frame-Options")
@embeddable_css_class = ""
embeddable_host = EmbeddableHost.record_for_url(request.referer)
- @embeddable_css_class = " class=\"#{embeddable_host.class_name}\"" if embeddable_host.present? && embeddable_host.class_name.present?
+ @embeddable_css_class =
+ " class=\"#{embeddable_host.class_name}\"" if embeddable_host.present? &&
+ embeddable_host.class_name.present?
@data_referer = request.referer
- @data_referer = '*' if SiteSetting.embed_any_origin? && @data_referer.blank?
+ @data_referer = "*" if SiteSetting.embed_any_origin? && @data_referer.blank?
end
def ensure_api_request
- raise Discourse::InvalidAccess.new('api key not set') if !is_api?
+ raise Discourse::InvalidAccess.new("api key not set") if !is_api?
end
end
diff --git a/app/controllers/exceptions_controller.rb b/app/controllers/exceptions_controller.rb
index 2cbfeeed026..2b50d7c56c1 100644
--- a/app/controllers/exceptions_controller.rb
+++ b/app/controllers/exceptions_controller.rb
@@ -12,5 +12,4 @@ class ExceptionsController < ApplicationController
def not_found_body
render html: build_not_found_page(status: 200)
end
-
end
diff --git a/app/controllers/export_csv_controller.rb b/app/controllers/export_csv_controller.rb
index 93f16b91d15..833bd53b303 100644
--- a/app/controllers/export_csv_controller.rb
+++ b/app/controllers/export_csv_controller.rb
@@ -1,16 +1,20 @@
# frozen_string_literal: true
class ExportCsvController < ApplicationController
-
skip_before_action :preload_json, :check_xhr, only: [:show]
def export_entity
guardian.ensure_can_export_entity!(export_params[:entity])
- if export_params[:entity] == 'user_archive'
+ if export_params[:entity] == "user_archive"
Jobs.enqueue(:export_user_archive, user_id: current_user.id, args: export_params[:args])
else
- Jobs.enqueue(:export_csv_file, entity: export_params[:entity], user_id: current_user.id, args: export_params[:args])
+ Jobs.enqueue(
+ :export_csv_file,
+ entity: export_params[:entity],
+ user_id: current_user.id,
+ args: export_params[:args],
+ )
end
StaffActionLogger.new(current_user).log_entity_export(export_params[:entity])
render json: success_json
@@ -21,9 +25,10 @@ class ExportCsvController < ApplicationController
private
def export_params
- @_export_params ||= begin
- params.require(:entity)
- params.permit(:entity, args: Report::FILTERS).to_h
- end
+ @_export_params ||=
+ begin
+ params.require(:entity)
+ params.permit(:entity, args: Report::FILTERS).to_h
+ end
end
end
diff --git a/app/controllers/extra_locales_controller.rb b/app/controllers/extra_locales_controller.rb
index 314e432900a..63fdb5d81c9 100644
--- a/app/controllers/extra_locales_controller.rb
+++ b/app/controllers/extra_locales_controller.rb
@@ -4,11 +4,11 @@ class ExtraLocalesController < ApplicationController
layout :false
skip_before_action :check_xhr,
- :preload_json,
- :redirect_to_login_if_required,
- :verify_authenticity_token
+ :preload_json,
+ :redirect_to_login_if_required,
+ :verify_authenticity_token
- OVERRIDES_BUNDLE ||= 'overrides'
+ OVERRIDES_BUNDLE ||= "overrides"
MD5_HASH_LENGTH ||= 32
def show
diff --git a/app/controllers/finish_installation_controller.rb b/app/controllers/finish_installation_controller.rb
index e84252c65ac..cdc6d8990f2 100644
--- a/app/controllers/finish_installation_controller.rb
+++ b/app/controllers/finish_installation_controller.rb
@@ -2,9 +2,9 @@
class FinishInstallationController < ApplicationController
skip_before_action :check_xhr, :preload_json, :redirect_to_login_if_required
- layout 'finish_installation'
+ layout "finish_installation"
- before_action :ensure_no_admins, except: ['confirm_email', 'resend_email']
+ before_action :ensure_no_admins, except: %w[confirm_email resend_email]
def index
end
@@ -61,7 +61,9 @@ class FinishInstallationController < ApplicationController
end
def find_allowed_emails
- return [] unless GlobalSetting.respond_to?(:developer_emails) && GlobalSetting.developer_emails.present?
+ unless GlobalSetting.respond_to?(:developer_emails) && GlobalSetting.developer_emails.present?
+ return []
+ end
GlobalSetting.developer_emails.split(",").map(&:strip)
end
diff --git a/app/controllers/forums_controller.rb b/app/controllers/forums_controller.rb
index ac172d54b3a..61987c111b2 100644
--- a/app/controllers/forums_controller.rb
+++ b/app/controllers/forums_controller.rb
@@ -6,7 +6,7 @@ class ForumsController < ActionController::Base
include ReadOnlyMixin
before_action :check_readonly_mode
- after_action :add_readonly_header
+ after_action :add_readonly_header
def status
if params[:cluster]
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 830f3ad230f..99f3634ee6c 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -1,44 +1,38 @@
# frozen_string_literal: true
class GroupsController < ApplicationController
- requires_login only: [
- :set_notifications,
- :mentionable,
- :messageable,
- :check_name,
- :update,
- :histories,
- :request_membership,
- :search,
- :new,
- :test_email_settings
- ]
+ requires_login only: %i[
+ set_notifications
+ mentionable
+ messageable
+ check_name
+ update
+ histories
+ request_membership
+ search
+ new
+ test_email_settings
+ ]
- skip_before_action :preload_json, :check_xhr, only: [:posts_feed, :mentions_feed]
+ skip_before_action :preload_json, :check_xhr, only: %i[posts_feed mentions_feed]
skip_before_action :check_xhr, only: [:show]
after_action :add_noindex_header
TYPE_FILTERS = {
- my: Proc.new { |groups, user|
- raise Discourse::NotFound unless user
- Group.member_of(groups, user)
- },
- owner: Proc.new { |groups, user|
- raise Discourse::NotFound unless user
- Group.owner_of(groups, user)
- },
- public: Proc.new { |groups|
- groups.where(public_admission: true, automatic: false)
- },
- close: Proc.new { |groups|
- groups.where(public_admission: false, automatic: false)
- },
- automatic: Proc.new { |groups|
- groups.where(automatic: true)
- },
- non_automatic: Proc.new { |groups|
- groups.where(automatic: false)
- }
+ my:
+ Proc.new do |groups, user|
+ raise Discourse::NotFound unless user
+ Group.member_of(groups, user)
+ end,
+ owner:
+ Proc.new do |groups, user|
+ raise Discourse::NotFound unless user
+ Group.owner_of(groups, user)
+ end,
+ public: Proc.new { |groups| groups.where(public_admission: true, automatic: false) },
+ close: Proc.new { |groups| groups.where(public_admission: false, automatic: false) },
+ automatic: Proc.new { |groups| groups.where(automatic: true) },
+ non_automatic: Proc.new { |groups| groups.where(automatic: false) },
}
ADD_MEMBERS_LIMIT = 1000
@@ -47,7 +41,7 @@ class GroupsController < ApplicationController
raise Discourse::InvalidAccess.new(:enable_group_directory)
end
- order = %w{name user_count}.delete(params[:order])
+ order = %w[name user_count].delete(params[:order])
dir = params[:asc].to_s == "true" ? "ASC" : "DESC"
sort = order ? "#{order} #{dir}" : nil
groups = Group.visible_groups(current_user, sort)
@@ -56,7 +50,7 @@ class GroupsController < ApplicationController
if (username = params[:username]).present?
raise Discourse::NotFound unless user = User.find_by_username(username)
groups = TYPE_FILTERS[:my].call(groups.members_visible_groups(current_user, sort), user)
- type_filters = type_filters - [:my, :owner]
+ type_filters = type_filters - %i[my owner]
end
if (filter = params[:filter]).present?
@@ -83,7 +77,7 @@ class GroupsController < ApplicationController
user_group_ids = group_users.pluck(:group_id)
owner_group_ids = group_users.where(owner: true).pluck(:group_id)
else
- type_filters = type_filters - [:my, :owner]
+ type_filters = type_filters - %i[my owner]
end
type_filters.delete(:non_automatic)
@@ -96,22 +90,19 @@ class GroupsController < ApplicationController
groups = groups.offset(page * page_size).limit(page_size)
render_json_dump(
- groups: serialize_data(groups,
- BasicGroupSerializer,
- user_group_ids: user_group_ids || [],
- owner_group_ids: owner_group_ids || []
- ),
+ groups:
+ serialize_data(
+ groups,
+ BasicGroupSerializer,
+ user_group_ids: user_group_ids || [],
+ owner_group_ids: owner_group_ids || [],
+ ),
extras: {
- type_filters: type_filters
+ type_filters: type_filters,
},
total_rows_groups: total,
- load_more_groups: groups_path(
- page: page + 1,
- type: type,
- order: order,
- asc: params[:asc],
- filter: filter
- )
+ load_more_groups:
+ groups_path(page: page + 1, type: type, order: order, asc: params[:asc], filter: filter),
)
end
@@ -122,21 +113,23 @@ class GroupsController < ApplicationController
format.html do
@title = group.full_name.present? ? group.full_name.capitalize : group.name
@full_title = "#{@title} - #{SiteSetting.title}"
- @description_meta = group.bio_cooked.present? ? PrettyText.excerpt(group.bio_cooked, 300) : @title
+ @description_meta =
+ group.bio_cooked.present? ? PrettyText.excerpt(group.bio_cooked, 300) : @title
render :show
end
format.json do
groups = Group.visible_groups(current_user)
if !guardian.is_staff?
- groups = groups.where("automatic IS FALSE OR groups.id = ?", Group::AUTO_GROUPS[:moderators])
+ groups =
+ groups.where("automatic IS FALSE OR groups.id = ?", Group::AUTO_GROUPS[:moderators])
end
render_json_dump(
group: serialize_data(group, GroupShowSerializer, root: nil),
extras: {
- visible_group_names: groups.pluck(:name)
- }
+ visible_group_names: groups.pluck(:name),
+ },
)
end
end
@@ -161,7 +154,15 @@ class GroupsController < ApplicationController
if params[:update_existing_users].blank?
user_count = count_existing_users(group.group_users, notification_level, categories, tags)
- return render status: 422, json: { user_count: user_count, errors: [I18n.t('invalid_params', message: :update_existing_users)] } if user_count > 0
+ if user_count > 0
+ return(
+ render status: 422,
+ json: {
+ user_count: user_count,
+ errors: [I18n.t("invalid_params", message: :update_existing_users)],
+ }
+ )
+ end
end
end
@@ -169,7 +170,9 @@ class GroupsController < ApplicationController
GroupActionLogger.new(current_user, group).log_change_group_settings
group.record_email_setting_changes!(current_user)
group.expire_imap_mailbox_cache
- update_existing_users(group.group_users, notification_level, categories, tags) if params[:update_existing_users] == "true"
+ if params[:update_existing_users] == "true"
+ update_existing_users(group.group_users, notification_level, categories, tags)
+ end
AdminDashboardData.clear_found_problem("group_#{group.id}_email_credentials")
# Redirect user to groups index page if they can no longer see the group
@@ -185,10 +188,7 @@ class GroupsController < ApplicationController
group = find_group(:group_id)
guardian.ensure_can_see_group_members!(group)
- posts = group.posts_for(
- guardian,
- params.permit(:before_post_id, :category_id)
- ).limit(20)
+ posts = group.posts_for(guardian, params.permit(:before_post_id, :category_id)).limit(20)
render_serialized posts.to_a, GroupPostSerializer
end
@@ -196,37 +196,32 @@ class GroupsController < ApplicationController
group = find_group(:group_id)
guardian.ensure_can_see_group_members!(group)
- @posts = group.posts_for(
- guardian,
- params.permit(:before_post_id, :category_id)
- ).limit(50)
- @title = "#{SiteSetting.title} - #{I18n.t("rss_description.group_posts", group_name: group.name)}"
+ @posts = group.posts_for(guardian, params.permit(:before_post_id, :category_id)).limit(50)
+ @title =
+ "#{SiteSetting.title} - #{I18n.t("rss_description.group_posts", group_name: group.name)}"
@link = Discourse.base_url
@description = I18n.t("rss_description.group_posts", group_name: group.name)
- render 'posts/latest', formats: [:rss]
+ render "posts/latest", formats: [:rss]
end
def mentions
raise Discourse::NotFound unless SiteSetting.enable_mentions?
group = find_group(:group_id)
- posts = group.mentioned_posts_for(
- guardian,
- params.permit(:before_post_id, :category_id)
- ).limit(20)
+ posts =
+ group.mentioned_posts_for(guardian, params.permit(:before_post_id, :category_id)).limit(20)
render_serialized posts.to_a, GroupPostSerializer
end
def mentions_feed
raise Discourse::NotFound unless SiteSetting.enable_mentions?
group = find_group(:group_id)
- @posts = group.mentioned_posts_for(
- guardian,
- params.permit(:before_post_id, :category_id)
- ).limit(50)
- @title = "#{SiteSetting.title} - #{I18n.t("rss_description.group_mentions", group_name: group.name)}"
+ @posts =
+ group.mentioned_posts_for(guardian, params.permit(:before_post_id, :category_id)).limit(50)
+ @title =
+ "#{SiteSetting.title} - #{I18n.t("rss_description.group_mentions", group_name: group.name)}"
@link = Discourse.base_url
@description = I18n.t("rss_description.group_mentions", group_name: group.name)
- render 'posts/latest', formats: [:rss]
+ render "posts/latest", formats: [:rss]
end
def members
@@ -240,10 +235,14 @@ class GroupsController < ApplicationController
raise Discourse::InvalidParameters.new(:limit) if limit < 0 || limit > 1000
raise Discourse::InvalidParameters.new(:offset) if offset < 0
- dir = (params[:asc] && params[:asc].present?) ? 'ASC' : 'DESC'
+ dir = (params[:asc] && params[:asc].present?) ? "ASC" : "DESC"
if params[:desc]
- Discourse.deprecate(":desc is deprecated please use :asc instead", output_in_test: true, drop_from: '2.9.0')
- dir = (params[:desc] && params[:desc].present?) ? 'DESC' : 'ASC'
+ Discourse.deprecate(
+ ":desc is deprecated please use :asc instead",
+ output_in_test: true,
+ drop_from: "2.9.0",
+ )
+ dir = (params[:desc] && params[:desc].present?) ? "DESC" : "ASC"
end
order = "NOT group_users.owner"
@@ -254,7 +253,7 @@ class GroupsController < ApplicationController
total = users.count
if (filter = params[:filter]).present?
- filter = filter.split(',') if filter.include?(',')
+ filter = filter.split(",") if filter.include?(",")
if current_user&.admin
users = users.filter_by_username_or_email(filter)
@@ -263,26 +262,29 @@ class GroupsController < ApplicationController
end
end
- users = users
- .select("users.*, group_requests.reason, group_requests.created_at requested_at")
- .order(params[:order] == 'requested_at' ? "group_requests.created_at #{dir}" : "")
- .order(username_lower: dir)
- .limit(limit)
- .offset(offset)
+ users =
+ users
+ .select("users.*, group_requests.reason, group_requests.created_at requested_at")
+ .order(params[:order] == "requested_at" ? "group_requests.created_at #{dir}" : "")
+ .order(username_lower: dir)
+ .limit(limit)
+ .offset(offset)
- return render json: {
- members: serialize_data(users, GroupRequesterSerializer),
- meta: {
- total: total,
- limit: limit,
- offset: offset
- }
- }
+ return(
+ render json: {
+ members: serialize_data(users, GroupRequesterSerializer),
+ meta: {
+ total: total,
+ limit: limit,
+ offset: offset,
+ },
+ }
+ )
end
- if params[:order] && %w{last_posted_at last_seen_at}.include?(params[:order])
+ if params[:order] && %w[last_posted_at last_seen_at].include?(params[:order])
order = "#{params[:order]} #{dir} NULLS LAST"
- elsif params[:order] == 'added_at'
+ elsif params[:order] == "added_at"
order = "group_users.created_at #{dir}"
end
@@ -290,7 +292,7 @@ class GroupsController < ApplicationController
total = users.count
if (filter = params[:filter]).present?
- filter = filter.split(',') if filter.include?(',')
+ filter = filter.split(",") if filter.include?(",")
if current_user&.admin
users = users.filter_by_username_or_email(filter)
@@ -299,25 +301,26 @@ class GroupsController < ApplicationController
end
end
- users = users
- .includes(:primary_group)
- .includes(:user_option)
- .select('users.*, group_users.created_at as added_at')
- .order(order)
- .order(username_lower: dir)
+ users =
+ users
+ .includes(:primary_group)
+ .includes(:user_option)
+ .select("users.*, group_users.created_at as added_at")
+ .order(order)
+ .order(username_lower: dir)
members = users.limit(limit).offset(offset)
- owners = users.where('group_users.owner')
+ owners = users.where("group_users.owner")
render json: {
- members: serialize_data(members, GroupUserSerializer),
- owners: serialize_data(owners, GroupUserSerializer),
- meta: {
- total: total,
- limit: limit,
- offset: offset
- }
- }
+ members: serialize_data(members, GroupUserSerializer),
+ owners: serialize_data(owners, GroupUserSerializer),
+ meta: {
+ total: total,
+ limit: limit,
+ offset: offset,
+ },
+ }
end
def add_members
@@ -327,10 +330,12 @@ class GroupsController < ApplicationController
users = users_from_params.to_a
emails = []
if params[:emails]
- params[:emails].split(",").each do |email|
- existing_user = User.find_by_email(email)
- existing_user.present? ? users.push(existing_user) : emails.push(email)
- end
+ params[:emails]
+ .split(",")
+ .each do |email|
+ existing_user = User.find_by_email(email)
+ existing_user.present? ? users.push(existing_user) : emails.push(email)
+ end
end
guardian.ensure_can_invite_to_forum!([group]) if emails.present?
@@ -340,43 +345,43 @@ class GroupsController < ApplicationController
end
if users.length > ADD_MEMBERS_LIMIT
- return render_json_error(
- I18n.t("groups.errors.adding_too_many_users", count: ADD_MEMBERS_LIMIT)
+ return(
+ render_json_error(I18n.t("groups.errors.adding_too_many_users", count: ADD_MEMBERS_LIMIT))
)
end
usernames_already_in_group = group.users.where(id: users.map(&:id)).pluck(:username)
- if usernames_already_in_group.present? &&
- usernames_already_in_group.length == users.length &&
- emails.blank?
- render_json_error(I18n.t(
- "groups.errors.member_already_exist",
- username: usernames_already_in_group.sort.join(", "),
- count: usernames_already_in_group.size
- ))
+ if usernames_already_in_group.present? && usernames_already_in_group.length == users.length &&
+ emails.blank?
+ render_json_error(
+ I18n.t(
+ "groups.errors.member_already_exist",
+ username: usernames_already_in_group.sort.join(", "),
+ count: usernames_already_in_group.size,
+ ),
+ )
else
notify = params[:notify_users]&.to_s == "true"
uniq_users = users.uniq
- uniq_users.each do |user|
- add_user_to_group(group, user, notify)
- end
+ uniq_users.each { |user| add_user_to_group(group, user, notify) }
emails.each do |email|
begin
Invite.generate(current_user, email: email, group_ids: [group.id])
rescue RateLimiter::LimitExceeded => e
- return render_json_error(I18n.t(
- "invite.rate_limit",
- count: SiteSetting.max_invites_per_day,
- time_left: e.time_left
- ))
+ return(
+ render_json_error(
+ I18n.t(
+ "invite.rate_limit",
+ count: SiteSetting.max_invites_per_day,
+ time_left: e.time_left,
+ ),
+ )
+ )
end
end
- render json: success_json.merge!(
- usernames: uniq_users.map(&:username),
- emails: emails
- )
+ render json: success_json.merge!(usernames: uniq_users.map(&:username), emails: emails)
end
end
@@ -412,12 +417,13 @@ class GroupsController < ApplicationController
end
if params[:accept]
- PostCreator.new(current_user,
- title: I18n.t('groups.request_accepted_pm.title', group_name: group.name),
- raw: I18n.t('groups.request_accepted_pm.body', group_name: group.name),
+ PostCreator.new(
+ current_user,
+ title: I18n.t("groups.request_accepted_pm.title", group_name: group.name),
+ raw: I18n.t("groups.request_accepted_pm.body", group_name: group.name),
archetype: Archetype.private_message,
target_usernames: user.username,
- skip_validations: true
+ skip_validations: true,
).create!
end
@@ -460,9 +466,9 @@ class GroupsController < ApplicationController
params[:user_emails] = params[:user_email] if params[:user_email].present?
users = users_from_params
- raise Discourse::InvalidParameters.new(
- 'user_ids or usernames or user_emails must be present'
- ) if users.empty?
+ if users.empty?
+ raise Discourse::InvalidParameters.new("user_ids or usernames or user_emails must be present")
+ end
removed_users = []
skipped_users = []
@@ -480,10 +486,7 @@ class GroupsController < ApplicationController
end
end
- render json: success_json.merge!(
- usernames: removed_users,
- skipped_usernames: skipped_users
- )
+ render json: success_json.merge!(usernames: removed_users, skipped_usernames: skipped_users)
end
def leave
@@ -511,24 +514,35 @@ class GroupsController < ApplicationController
begin
GroupRequest.create!(group: group, user: current_user, reason: params[:reason])
rescue ActiveRecord::RecordNotUnique
- return render json: failed_json.merge(error: I18n.t("groups.errors.already_requested_membership")), status: 409
+ return(
+ render json: failed_json.merge(error: I18n.t("groups.errors.already_requested_membership")),
+ status: 409
+ )
end
usernames = [current_user.username].concat(
- group.users.where('group_users.owner')
+ group
+ .users
+ .where("group_users.owner")
.order("users.last_seen_at DESC")
.limit(MAX_NOTIFIED_OWNERS)
- .pluck("users.username")
+ .pluck("users.username"),
)
- post = PostCreator.new(current_user,
- title: I18n.t('groups.request_membership_pm.title', group_name: group.name),
- raw: params[:reason],
- archetype: Archetype.private_message,
- target_usernames: usernames.join(','),
- topic_opts: { custom_fields: { requested_group_id: group.id } },
- skip_validations: true
- ).create!
+ post =
+ PostCreator.new(
+ current_user,
+ title: I18n.t("groups.request_membership_pm.title", group_name: group.name),
+ raw: params[:reason],
+ archetype: Archetype.private_message,
+ target_usernames: usernames.join(","),
+ topic_opts: {
+ custom_fields: {
+ requested_group_id: group.id,
+ },
+ },
+ skip_validations: true,
+ ).create!
render json: success_json.merge(relative_url: post.topic.relative_url)
end
@@ -538,11 +552,10 @@ class GroupsController < ApplicationController
notification_level = params.require(:notification_level)
user_id = current_user.id
- if guardian.is_staff?
- user_id = params[:user_id] || user_id
- end
+ user_id = params[:user_id] || user_id if guardian.is_staff?
- GroupUser.where(group_id: group.id)
+ GroupUser
+ .where(group_id: group.id)
.where(user_id: user_id)
.update_all(notification_level: notification_level)
@@ -556,29 +569,28 @@ class GroupsController < ApplicationController
page_size = 25
offset = (params[:offset] && params[:offset].to_i) || 0
- group_histories = GroupHistory.with_filters(group, params[:filters])
- .limit(page_size)
- .offset(offset * page_size)
+ group_histories =
+ GroupHistory.with_filters(group, params[:filters]).limit(page_size).offset(offset * page_size)
render_json_dump(
logs: serialize_data(group_histories, BasicGroupHistorySerializer),
- all_loaded: group_histories.count < page_size
+ all_loaded: group_histories.count < page_size,
)
end
def search
- groups = Group.visible_groups(current_user)
- .where("groups.id <> ?", Group::AUTO_GROUPS[:everyone])
- .includes(:flair_upload)
- .order(:name)
+ groups =
+ Group
+ .visible_groups(current_user)
+ .where("groups.id <> ?", Group::AUTO_GROUPS[:everyone])
+ .includes(:flair_upload)
+ .order(:name)
if (term = params[:term]).present?
groups = groups.where("name ILIKE :term OR full_name ILIKE :term", term: "%#{term}%")
end
- if params[:ignore_automatic].to_s == "true"
- groups = groups.where(automatic: false)
- end
+ groups = groups.where(automatic: false) if params[:ignore_automatic].to_s == "true"
if Group.preloaded_custom_field_names.present?
Group.preload_custom_fields(groups, Group.preloaded_custom_field_names)
@@ -589,8 +601,14 @@ class GroupsController < ApplicationController
def permissions
group = find_group(:id)
- category_groups = group.category_groups.select { |category_group| guardian.can_see_category?(category_group.category) }
- render_serialized(category_groups.sort_by { |category_group| category_group.category.name }, CategoryGroupSerializer)
+ category_groups =
+ group.category_groups.select do |category_group|
+ guardian.can_see_category?(category_group.category)
+ end
+ render_serialized(
+ category_groups.sort_by { |category_group| category_group.category.name },
+ CategoryGroupSerializer,
+ )
end
def test_email_settings
@@ -611,7 +629,7 @@ class GroupsController < ApplicationController
enable_tls = settings[:ssl] == "true"
email_host = params[:host]
- if !["smtp", "imap"].include?(params[:protocol])
+ if !%w[smtp imap].include?(params[:protocol])
raise Discourse::InvalidParameters.new("Valid protocols to test are smtp and imap")
end
@@ -622,20 +640,29 @@ class GroupsController < ApplicationController
enable_starttls_auto = false
settings.delete(:ssl)
- final_settings = settings.merge(enable_tls: enable_tls, enable_starttls_auto: enable_starttls_auto)
- .permit(:host, :port, :username, :password, :enable_tls, :enable_starttls_auto, :debug)
- EmailSettingsValidator.validate_as_user(current_user, "smtp", **final_settings.to_h.symbolize_keys)
+ final_settings =
+ settings.merge(
+ enable_tls: enable_tls,
+ enable_starttls_auto: enable_starttls_auto,
+ ).permit(:host, :port, :username, :password, :enable_tls, :enable_starttls_auto, :debug)
+ EmailSettingsValidator.validate_as_user(
+ current_user,
+ "smtp",
+ **final_settings.to_h.symbolize_keys,
+ )
when "imap"
- final_settings = settings.merge(ssl: enable_tls)
- .permit(:host, :port, :username, :password, :ssl, :debug)
- EmailSettingsValidator.validate_as_user(current_user, "imap", **final_settings.to_h.symbolize_keys)
+ final_settings =
+ settings.merge(ssl: enable_tls).permit(:host, :port, :username, :password, :ssl, :debug)
+ EmailSettingsValidator.validate_as_user(
+ current_user,
+ "imap",
+ **final_settings.to_h.symbolize_keys,
+ )
end
render json: success_json
rescue *EmailSettingsExceptionHandler::EXPECTED_EXCEPTIONS, StandardError => err
- render_json_error(
- EmailSettingsExceptionHandler.friendly_exception_message(err, email_host)
- )
+ render_json_error(EmailSettingsExceptionHandler.friendly_exception_message(err, email_host))
end
end
end
@@ -653,7 +680,7 @@ class GroupsController < ApplicationController
end
def group_params(automatic: false)
- attributes = %i{
+ attributes = %i[
bio_raw
default_notification_level
messageable_level
@@ -662,7 +689,7 @@ class GroupsController < ApplicationController
flair_color
flair_icon
flair_upload_id
- }
+ ]
if automatic
attributes.push(:visibility_level)
@@ -673,7 +700,7 @@ class GroupsController < ApplicationController
:full_name,
:public_exit,
:public_admission,
- :membership_request_template
+ :membership_request_template,
)
end
@@ -703,7 +730,7 @@ class GroupsController < ApplicationController
:grant_trust_level,
:automatic_membership_email_domains,
:publish_read_state,
- :allow_unknown_sender_topic_replies
+ :allow_unknown_sender_topic_replies,
)
custom_fields = DiscoursePluginRegistry.editable_group_custom_fields
@@ -711,7 +738,7 @@ class GroupsController < ApplicationController
end
if !automatic || current_user.admin
- [:muted, :regular, :tracking, :watching, :watching_first_post].each do |level|
+ %i[muted regular tracking watching watching_first_post].each do |level|
attributes << { "#{level}_category_ids" => [] }
attributes << { "#{level}_tags" => [] }
end
@@ -770,8 +797,10 @@ class GroupsController < ApplicationController
end
def user_default_notifications(group, params)
- category_notifications = group.group_category_notification_defaults.pluck(:category_id, :notification_level).to_h
- tag_notifications = group.group_tag_notification_defaults.pluck(:tag_id, :notification_level).to_h
+ category_notifications =
+ group.group_category_notification_defaults.pluck(:category_id, :notification_level).to_h
+ tag_notifications =
+ group.group_tag_notification_defaults.pluck(:tag_id, :notification_level).to_h
categories = {}
tags = {}
@@ -782,10 +811,7 @@ class GroupsController < ApplicationController
category_id = category_id.to_i
old_value = category_notifications[category_id]
- metadata = {
- old_value: old_value,
- new_value: value
- }
+ metadata = { old_value: old_value, new_value: value }
if old_value.blank?
metadata[:action] = :create
@@ -805,10 +831,7 @@ class GroupsController < ApplicationController
tag_ids.each do |tag_id|
old_value = tag_notifications[tag_id]
- metadata = {
- old_value: old_value,
- new_value: value
- }
+ metadata = { old_value: old_value, new_value: value }
if old_value.blank?
metadata[:action] = :create
@@ -834,20 +857,18 @@ class GroupsController < ApplicationController
notification_level = nil
default_notification_level = params[:default_notification_level]&.to_i
- if default_notification_level.present? && group.default_notification_level != default_notification_level
+ if default_notification_level.present? &&
+ group.default_notification_level != default_notification_level
notification_level = {
old_value: group.default_notification_level,
- new_value: default_notification_level
+ new_value: default_notification_level,
}
end
[notification_level, categories, tags]
end
- %i{
- count
- update
- }.each do |action|
+ %i[count update].each do |action|
define_method("#{action}_existing_users") do |group_users, notification_level, categories, tags|
return 0 if notification_level.blank? && categories.blank? && tags.blank?
@@ -865,7 +886,12 @@ class GroupsController < ApplicationController
categories.each do |category_id, data|
if data[:action] == :update || data[:action] == :delete
- category_users = CategoryUser.where(category_id: category_id, notification_level: data[:old_value], user_id: group_users.select(:user_id))
+ category_users =
+ CategoryUser.where(
+ category_id: category_id,
+ notification_level: data[:old_value],
+ user_id: group_users.select(:user_id),
+ )
if action == :update
category_users.delete_all
@@ -879,7 +905,12 @@ class GroupsController < ApplicationController
tags.each do |tag_id, data|
if data[:action] == :update || data[:action] == :delete
- tag_users = TagUser.where(tag_id: tag_id, notification_level: data[:old_value], user_id: group_users.select(:user_id))
+ tag_users =
+ TagUser.where(
+ tag_id: tag_id,
+ notification_level: data[:old_value],
+ user_id: group_users.select(:user_id),
+ )
if action == :update
tag_users.delete_all
@@ -892,47 +923,65 @@ class GroupsController < ApplicationController
end
if categories.present? || tags.present?
- group_users.select(:id, :user_id).find_in_batches do |batch|
- user_ids = batch.pluck(:user_id)
+ group_users
+ .select(:id, :user_id)
+ .find_in_batches do |batch|
+ user_ids = batch.pluck(:user_id)
- categories.each do |category_id, data|
- category_users = []
- existing_users = CategoryUser.where(category_id: category_id, user_id: user_ids).where("notification_level IS NOT NULL")
- skip_user_ids = existing_users.pluck(:user_id)
+ categories.each do |category_id, data|
+ category_users = []
+ existing_users =
+ CategoryUser.where(category_id: category_id, user_id: user_ids).where(
+ "notification_level IS NOT NULL",
+ )
+ skip_user_ids = existing_users.pluck(:user_id)
- batch.each do |group_user|
- next if skip_user_ids.include?(group_user.user_id)
- category_users << { category_id: category_id, user_id: group_user.user_id, notification_level: data[:new_value] }
+ batch.each do |group_user|
+ next if skip_user_ids.include?(group_user.user_id)
+ category_users << {
+ category_id: category_id,
+ user_id: group_user.user_id,
+ notification_level: data[:new_value],
+ }
+ end
+
+ next if category_users.blank?
+
+ if action == :update
+ CategoryUser.insert_all!(category_users)
+ else
+ ids += category_users.pluck(:user_id)
+ end
end
- next if category_users.blank?
+ tags.each do |tag_id, data|
+ tag_users = []
+ existing_users =
+ TagUser.where(tag_id: tag_id, user_id: user_ids).where(
+ "notification_level IS NOT NULL",
+ )
+ skip_user_ids = existing_users.pluck(:user_id)
- if action == :update
- CategoryUser.insert_all!(category_users)
- else
- ids += category_users.pluck(:user_id)
+ batch.each do |group_user|
+ next if skip_user_ids.include?(group_user.user_id)
+ tag_users << {
+ tag_id: tag_id,
+ user_id: group_user.user_id,
+ notification_level: data[:new_value],
+ created_at: Time.now,
+ updated_at: Time.now,
+ }
+ end
+
+ next if tag_users.blank?
+
+ if action == :update
+ TagUser.insert_all!(tag_users)
+ else
+ ids += tag_users.pluck(:user_id)
+ end
end
end
-
- tags.each do |tag_id, data|
- tag_users = []
- existing_users = TagUser.where(tag_id: tag_id, user_id: user_ids).where("notification_level IS NOT NULL")
- skip_user_ids = existing_users.pluck(:user_id)
-
- batch.each do |group_user|
- next if skip_user_ids.include?(group_user.user_id)
- tag_users << { tag_id: tag_id, user_id: group_user.user_id, notification_level: data[:new_value], created_at: Time.now, updated_at: Time.now }
- end
-
- next if tag_users.blank?
-
- if action == :update
- TagUser.insert_all!(tag_users)
- else
- ids += tag_users.pluck(:user_id)
- end
- end
- end
end
ids.uniq.count
diff --git a/app/controllers/highlight_js_controller.rb b/app/controllers/highlight_js_controller.rb
index 5011fc9535e..b77c14e82a9 100644
--- a/app/controllers/highlight_js_controller.rb
+++ b/app/controllers/highlight_js_controller.rb
@@ -1,26 +1,26 @@
# frozen_string_literal: true
class HighlightJsController < ApplicationController
- skip_before_action :preload_json, :redirect_to_login_if_required, :check_xhr, :verify_authenticity_token, only: [:show]
+ skip_before_action :preload_json,
+ :redirect_to_login_if_required,
+ :check_xhr,
+ :verify_authenticity_token,
+ only: [:show]
before_action :apply_cdn_headers, only: [:show]
def show
-
no_cookies
RailsMultisite::ConnectionManagement.with_hostname(params[:hostname]) do
-
current_version = HighlightJs.version(SiteSetting.highlighted_languages)
- if current_version != params[:version]
- return redirect_to path(HighlightJs.path)
- end
+ return redirect_to path(HighlightJs.path) if current_version != params[:version]
# note, this can be slightly optimised by caching the bundled file, it cuts down on N reads
# our nginx config caches this so in practical terms it does not really matter and keeps
# code simpler
- languages = SiteSetting.highlighted_languages.split('|')
+ languages = SiteSetting.highlighted_languages.split("|")
highlight_js = HighlightJs.bundle(languages)
@@ -28,7 +28,7 @@ class HighlightJsController < ApplicationController
response.headers["Content-Length"] = highlight_js.bytesize.to_s
immutable_for 1.year
- render plain: highlight_js, disposition: nil, content_type: 'application/javascript'
+ render plain: highlight_js, disposition: nil, content_type: "application/javascript"
end
end
end
diff --git a/app/controllers/inline_onebox_controller.rb b/app/controllers/inline_onebox_controller.rb
index 871be8c3080..3b3d61c55c2 100644
--- a/app/controllers/inline_onebox_controller.rb
+++ b/app/controllers/inline_onebox_controller.rb
@@ -5,12 +5,13 @@ class InlineOneboxController < ApplicationController
def show
hijack do
- oneboxes = InlineOneboxer.new(
- params[:urls] || [],
- user_id: current_user.id,
- category_id: params[:category_id].to_i,
- topic_id: params[:topic_id].to_i
- ).process
+ oneboxes =
+ InlineOneboxer.new(
+ params[:urls] || [],
+ user_id: current_user.id,
+ category_id: params[:category_id].to_i,
+ topic_id: params[:topic_id].to_i,
+ ).process
render json: { "inline-oneboxes" => oneboxes }
end
end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index 9f9eb041901..a8483d2b46f 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -1,17 +1,24 @@
# frozen_string_literal: true
-require 'csv'
+require "csv"
class InvitesController < ApplicationController
-
- requires_login only: [:create, :retrieve, :destroy, :destroy_all_expired, :resend_invite, :resend_all_invites, :upload_csv]
+ requires_login only: %i[
+ create
+ retrieve
+ destroy
+ destroy_all_expired
+ resend_invite
+ resend_all_invites
+ upload_csv
+ ]
skip_before_action :check_xhr, except: [:perform_accept_invitation]
skip_before_action :preload_json, except: [:show]
skip_before_action :redirect_to_login_if_required
- before_action :ensure_invites_allowed, only: [:show, :perform_accept_invitation]
- before_action :ensure_new_registrations_allowed, only: [:show, :perform_accept_invitation]
+ before_action :ensure_invites_allowed, only: %i[show perform_accept_invitation]
+ before_action :ensure_new_registrations_allowed, only: %i[show perform_accept_invitation]
def show
expires_now
@@ -27,7 +34,7 @@ class InvitesController < ApplicationController
end
rescue RateLimiter::LimitExceeded => e
flash.now[:error] = e.description
- render layout: 'no_ember'
+ render layout: "no_ember"
end
def create
@@ -45,24 +52,37 @@ class InvitesController < ApplicationController
if !groups_can_see_topic?(groups, topic)
editable_topic_groups = topic.category.groups.filter { |g| guardian.can_edit_group?(g) }
- return render_json_error(I18n.t("invite.requires_groups", groups: editable_topic_groups.pluck(:name).join(", ")))
+ return(
+ render_json_error(
+ I18n.t("invite.requires_groups", groups: editable_topic_groups.pluck(:name).join(", ")),
+ )
+ )
end
- invite = Invite.generate(current_user,
- email: params[:email],
- domain: params[:domain],
- skip_email: params[:skip_email],
- invited_by: current_user,
- custom_message: params[:custom_message],
- max_redemptions_allowed: params[:max_redemptions_allowed],
- topic_id: topic&.id,
- group_ids: groups&.map(&:id),
- expires_at: params[:expires_at],
- invite_to_topic: params[:invite_to_topic]
- )
+ invite =
+ Invite.generate(
+ current_user,
+ email: params[:email],
+ domain: params[:domain],
+ skip_email: params[:skip_email],
+ invited_by: current_user,
+ custom_message: params[:custom_message],
+ max_redemptions_allowed: params[:max_redemptions_allowed],
+ topic_id: topic&.id,
+ group_ids: groups&.map(&:id),
+ expires_at: params[:expires_at],
+ invite_to_topic: params[:invite_to_topic],
+ )
if invite.present?
- render_serialized(invite, InviteSerializer, scope: guardian, root: nil, show_emails: params.has_key?(:email), show_warnings: true)
+ render_serialized(
+ invite,
+ InviteSerializer,
+ scope: guardian,
+ root: nil,
+ show_emails: params.has_key?(:email),
+ show_warnings: true,
+ )
else
render json: failed_json, status: 422
end
@@ -81,7 +101,14 @@ class InvitesController < ApplicationController
guardian.ensure_can_invite_to_forum!(nil)
- render_serialized(invite, InviteSerializer, scope: guardian, root: nil, show_emails: params.has_key?(:email), show_warnings: true)
+ render_serialized(
+ invite,
+ InviteSerializer,
+ scope: guardian,
+ root: nil,
+ show_emails: params.has_key?(:email),
+ show_warnings: true,
+ )
end
def update
@@ -108,12 +135,19 @@ class InvitesController < ApplicationController
if params.has_key?(:group_ids) || params.has_key?(:group_names)
invite.invited_groups.destroy_all
- groups.each { |group| invite.invited_groups.find_or_create_by!(group_id: group.id) } if groups.present?
+ if groups.present?
+ groups.each { |group| invite.invited_groups.find_or_create_by!(group_id: group.id) }
+ end
end
if !groups_can_see_topic?(invite.groups, invite.topics.first)
- editable_topic_groups = invite.topics.first.category.groups.filter { |g| guardian.can_edit_group?(g) }
- return render_json_error(I18n.t("invite.requires_groups", groups: editable_topic_groups.pluck(:name).join(", ")))
+ editable_topic_groups =
+ invite.topics.first.category.groups.filter { |g| guardian.can_edit_group?(g) }
+ return(
+ render_json_error(
+ I18n.t("invite.requires_groups", groups: editable_topic_groups.pluck(:name).join(", ")),
+ )
+ )
end
if params.has_key?(:email)
@@ -121,20 +155,26 @@ class InvitesController < ApplicationController
new_email = params[:email].presence
if new_email
- if Invite.where.not(id: invite.id).find_by(email: new_email.downcase, invited_by_id: current_user.id)&.redeemable?
- return render_json_error(
- I18n.t("invite.invite_exists", email: CGI.escapeHTML(new_email)),
- status: 409
+ if Invite
+ .where.not(id: invite.id)
+ .find_by(email: new_email.downcase, invited_by_id: current_user.id)
+ &.redeemable?
+ return(
+ render_json_error(
+ I18n.t("invite.invite_exists", email: CGI.escapeHTML(new_email)),
+ status: 409,
+ )
)
end
end
if old_email != new_email
- invite.emailed_status = if new_email && !params[:skip_email]
- Invite.emailed_status_types[:pending]
- else
- Invite.emailed_status_types[:not_required]
- end
+ invite.emailed_status =
+ if new_email && !params[:skip_email]
+ Invite.emailed_status_types[:pending]
+ else
+ Invite.emailed_status_types[:not_required]
+ end
end
invite.domain = nil if invite.email.present?
@@ -162,9 +202,13 @@ class InvitesController < ApplicationController
end
begin
- invite.update!(params.permit(:email, :custom_message, :max_redemptions_allowed, :expires_at))
+ invite.update!(
+ params.permit(:email, :custom_message, :max_redemptions_allowed, :expires_at),
+ )
rescue ActiveRecord::RecordInvalid => e
- return render json: {}, status: 200 if SiteSetting.hide_email_address_taken? && e.record.email_already_exists?
+ if SiteSetting.hide_email_address_taken? && e.record.email_already_exists?
+ return render json: {}, status: 200
+ end
return render_json_error(e.record.errors.full_messages.first)
end
end
@@ -174,7 +218,14 @@ class InvitesController < ApplicationController
Jobs.enqueue(:invite_email, invite_id: invite.id, invite_to_topic: params[:invite_to_topic])
end
- render_serialized(invite, InviteSerializer, scope: guardian, root: nil, show_emails: params.has_key?(:email), show_warnings: true)
+ render_serialized(
+ invite,
+ InviteSerializer,
+ scope: guardian,
+ root: nil,
+ show_emails: params.has_key?(:email),
+ show_warnings: true,
+ )
end
def destroy
@@ -192,17 +243,23 @@ class InvitesController < ApplicationController
# via the SessionController#sso_login route
def perform_accept_invitation
params.require(:id)
- params.permit(:email, :username, :name, :password, :timezone, :email_token, user_custom_fields: {})
+ params.permit(
+ :email,
+ :username,
+ :name,
+ :password,
+ :timezone,
+ :email_token,
+ user_custom_fields: {
+ },
+ )
invite = Invite.find_by(invite_key: params[:id])
redeeming_user = current_user
if invite.present?
begin
- attrs = {
- ip_address: request.remote_ip,
- session: session
- }
+ attrs = { ip_address: request.remote_ip, session: session }
if redeeming_user
attrs[:redeeming_user] = redeeming_user
@@ -230,12 +287,10 @@ class InvitesController < ApplicationController
end
if user.blank?
- return render json: failed_json.merge(message: I18n.t('invite.not_found_json')), status: 404
+ return render json: failed_json.merge(message: I18n.t("invite.not_found_json")), status: 404
end
- if !redeeming_user && user.active? && user.guardian.can_access_forum?
- log_on_user(user)
- end
+ log_on_user(user) if !redeeming_user && user.active? && user.guardian.can_access_forum?
user.update_timezone_if_missing(params[:timezone])
post_process_invite(user)
@@ -246,9 +301,7 @@ class InvitesController < ApplicationController
if user.present?
if user.active? && user.guardian.can_access_forum?
- if redeeming_user
- response[:message] = I18n.t("invite.existing_user_success")
- end
+ response[:message] = I18n.t("invite.existing_user_success") if redeeming_user
if user.guardian.can_see?(topic)
response[:redirect_to] = path(topic.relative_url)
@@ -257,20 +310,18 @@ class InvitesController < ApplicationController
end
else
response[:message] = if user.active?
- I18n.t('activation.approval_required')
+ I18n.t("activation.approval_required")
else
- I18n.t('invite.confirm_email')
+ I18n.t("invite.confirm_email")
end
- if user.guardian.can_see?(topic)
- cookies[:destination_url] = path(topic.relative_url)
- end
+ cookies[:destination_url] = path(topic.relative_url) if user.guardian.can_see?(topic)
end
end
render json: success_json.merge(response)
else
- render json: failed_json.merge(message: I18n.t('invite.not_found_json')), status: 404
+ render json: failed_json.merge(message: I18n.t("invite.not_found_json")), status: 404
end
end
@@ -279,7 +330,7 @@ class InvitesController < ApplicationController
Invite
.where(invited_by: current_user)
- .where('expires_at < ?', Time.zone.now)
+ .where("expires_at < ?", Time.zone.now)
.find_each { |invite| invite.trash!(current_user) }
render json: success_json
@@ -301,13 +352,20 @@ class InvitesController < ApplicationController
guardian.ensure_can_resend_all_invites!(current_user)
begin
- RateLimiter.new(current_user, "bulk-reinvite-per-day", 1, 1.day, apply_limit_to_staff: true).performed!
+ RateLimiter.new(
+ current_user,
+ "bulk-reinvite-per-day",
+ 1,
+ 1.day,
+ apply_limit_to_staff: true,
+ ).performed!
rescue RateLimiter::LimitExceeded
return render_json_error(I18n.t("rate_limiter.slow_down"))
end
- Invite.pending(current_user)
- .where('invites.email IS NOT NULL')
+ Invite
+ .pending(current_user)
+ .where("invites.email IS NOT NULL")
.find_each { |invite| invite.resend_invite }
render json: success_json
@@ -326,17 +384,15 @@ class InvitesController < ApplicationController
CSV.foreach(file.tempfile, encoding: "bom|utf-8") do |row|
# Try to extract a CSV header, if it exists
if csv_header.nil?
- if row[0] == 'email'
+ if row[0] == "email"
csv_header = row
next
else
- csv_header = ["email", "groups", "topic_id"]
+ csv_header = %w[email groups topic_id]
end
end
- if row[0].present?
- invites.push(csv_header.zip(row).map.to_h.filter { |k, v| v.present? })
- end
+ invites.push(csv_header.zip(row).map.to_h.filter { |k, v| v.present? }) if row[0].present?
break if invites.count >= SiteSetting.max_bulk_invites
end
@@ -345,7 +401,16 @@ class InvitesController < ApplicationController
Jobs.enqueue(:bulk_invite, invites: invites, current_user_id: current_user.id)
if invites.count >= SiteSetting.max_bulk_invites
- render json: failed_json.merge(errors: [I18n.t("bulk_invite.max_rows", max_bulk_invites: SiteSetting.max_bulk_invites)]), status: 422
+ render json:
+ failed_json.merge(
+ errors: [
+ I18n.t(
+ "bulk_invite.max_rows",
+ max_bulk_invites: SiteSetting.max_bulk_invites,
+ ),
+ ],
+ ),
+ status: 422
else
render json: success_json
end
@@ -375,9 +440,7 @@ class InvitesController < ApplicationController
email_verified_by_link = invite.email_token.present? && params[:t] == invite.email_token
- if email_verified_by_link
- email = invite.email
- end
+ email = invite.email if email_verified_by_link
hidden_email = email != invite.email
@@ -393,12 +456,10 @@ class InvitesController < ApplicationController
hidden_email: hidden_email,
username: username,
is_invite_link: invite.is_invite_link?,
- email_verified_by_link: email_verified_by_link
+ email_verified_by_link: email_verified_by_link,
}
- if different_external_email
- info[:different_external_email] = true
- end
+ info[:different_external_email] = true if different_external_email
if staged_user = User.where(staged: true).with_email(invite.email).first
info[:username] = staged_user.username
@@ -417,36 +478,46 @@ class InvitesController < ApplicationController
secure_session["invite-key"] = invite.invite_key
- render layout: 'application'
+ render layout: "application"
end
def show_irredeemable_invite(invite)
- flash.now[:error] = \
- if invite.blank?
- I18n.t('invite.not_found', base_url: Discourse.base_url)
- elsif invite.redeemed?
- if invite.is_invite_link?
- I18n.t('invite.not_found_template_link', site_name: SiteSetting.title, base_url: Discourse.base_url)
- else
- I18n.t('invite.not_found_template', site_name: SiteSetting.title, base_url: Discourse.base_url)
- end
- elsif invite.expired?
- I18n.t('invite.expired', base_url: Discourse.base_url)
+ flash.now[:error] = if invite.blank?
+ I18n.t("invite.not_found", base_url: Discourse.base_url)
+ elsif invite.redeemed?
+ if invite.is_invite_link?
+ I18n.t(
+ "invite.not_found_template_link",
+ site_name: SiteSetting.title,
+ base_url: Discourse.base_url,
+ )
+ else
+ I18n.t(
+ "invite.not_found_template",
+ site_name: SiteSetting.title,
+ base_url: Discourse.base_url,
+ )
end
+ elsif invite.expired?
+ I18n.t("invite.expired", base_url: Discourse.base_url)
+ end
- render layout: 'no_ember'
+ render layout: "no_ember"
end
def ensure_invites_allowed
- if (!SiteSetting.enable_local_logins && Discourse.enabled_auth_providers.count == 0 && !SiteSetting.enable_discourse_connect)
+ if (
+ !SiteSetting.enable_local_logins && Discourse.enabled_auth_providers.count == 0 &&
+ !SiteSetting.enable_discourse_connect
+ )
raise Discourse::NotFound
end
end
def ensure_new_registrations_allowed
unless SiteSetting.allow_new_registrations
- flash[:error] = I18n.t('login.new_registrations_disabled')
- render layout: 'no_ember'
+ flash[:error] = I18n.t("login.new_registrations_disabled")
+ render layout: "no_ember"
false
end
end
@@ -461,13 +532,14 @@ class InvitesController < ApplicationController
end
def post_process_invite(user)
- user.enqueue_welcome_message('welcome_invite') if user.send_welcome_message
+ user.enqueue_welcome_message("welcome_invite") if user.send_welcome_message
Group.refresh_automatic_groups!(:admins, :moderators, :staff) if user.staff?
if user.has_password?
if !user.active
- email_token = user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:signup])
+ email_token =
+ user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:signup])
EmailToken.enqueue_signup_email(email_token)
end
elsif !SiteSetting.enable_discourse_connect && SiteSetting.enable_local_logins
@@ -478,17 +550,19 @@ class InvitesController < ApplicationController
def create_topic_invite_notifications(invite, user)
invite.topics.each do |topic|
if user.guardian.can_see?(topic)
- last_notification = user.notifications
- .where(notification_type: Notification.types[:invited_to_topic])
- .where(topic_id: topic.id)
- .where(post_number: 1)
- .where('created_at > ?', 1.hour.ago)
+ last_notification =
+ user
+ .notifications
+ .where(notification_type: Notification.types[:invited_to_topic])
+ .where(topic_id: topic.id)
+ .where(post_number: 1)
+ .where("created_at > ?", 1.hour.ago)
if !last_notification.exists?
topic.create_invite_notification!(
user,
Notification.types[:invited_to_topic],
- invite.invited_by
+ invite.invited_by,
)
end
end
diff --git a/app/controllers/list_controller.rb b/app/controllers/list_controller.rb
index 66d8adbcc3c..6e34b868676 100644
--- a/app/controllers/list_controller.rb
+++ b/app/controllers/list_controller.rb
@@ -6,45 +6,47 @@ class ListController < ApplicationController
skip_before_action :check_xhr
- before_action :set_category, only: [
- :category_default,
- # filtered topics lists
- Discourse.filters.map { |f| :"category_#{f}" },
- Discourse.filters.map { |f| :"category_none_#{f}" },
- # top summaries
- :category_top,
- :category_none_top,
- # top pages (ie. with a period)
- TopTopic.periods.map { |p| :"category_top_#{p}" },
- TopTopic.periods.map { |p| :"category_none_top_#{p}" },
- # category feeds
- :category_feed,
- ].flatten
+ before_action :set_category,
+ only: [
+ :category_default,
+ # filtered topics lists
+ Discourse.filters.map { |f| :"category_#{f}" },
+ Discourse.filters.map { |f| :"category_none_#{f}" },
+ # top summaries
+ :category_top,
+ :category_none_top,
+ # top pages (ie. with a period)
+ TopTopic.periods.map { |p| :"category_top_#{p}" },
+ TopTopic.periods.map { |p| :"category_none_top_#{p}" },
+ # category feeds
+ :category_feed,
+ ].flatten
- before_action :ensure_logged_in, except: [
- :topics_by,
- # anonymous filters
- Discourse.anonymous_filters,
- Discourse.anonymous_filters.map { |f| "#{f}_feed" },
- # anonymous categorized filters
- :category_default,
- Discourse.anonymous_filters.map { |f| :"category_#{f}" },
- Discourse.anonymous_filters.map { |f| :"category_none_#{f}" },
- # category feeds
- :category_feed,
- # user topics feed
- :user_topics_feed,
- # top summaries
- :top,
- :category_top,
- :category_none_top,
- # top pages (ie. with a period)
- TopTopic.periods.map { |p| :"top_#{p}" },
- TopTopic.periods.map { |p| :"top_#{p}_feed" },
- TopTopic.periods.map { |p| :"category_top_#{p}" },
- TopTopic.periods.map { |p| :"category_none_top_#{p}" },
- :group_topics
- ].flatten
+ before_action :ensure_logged_in,
+ except: [
+ :topics_by,
+ # anonymous filters
+ Discourse.anonymous_filters,
+ Discourse.anonymous_filters.map { |f| "#{f}_feed" },
+ # anonymous categorized filters
+ :category_default,
+ Discourse.anonymous_filters.map { |f| :"category_#{f}" },
+ Discourse.anonymous_filters.map { |f| :"category_none_#{f}" },
+ # category feeds
+ :category_feed,
+ # user topics feed
+ :user_topics_feed,
+ # top summaries
+ :top,
+ :category_top,
+ :category_none_top,
+ # top pages (ie. with a period)
+ TopTopic.periods.map { |p| :"top_#{p}" },
+ TopTopic.periods.map { |p| :"top_#{p}_feed" },
+ TopTopic.periods.map { |p| :"category_top_#{p}" },
+ TopTopic.periods.map { |p| :"category_none_top_#{p}" },
+ :group_topics,
+ ].flatten
# Create our filters
Discourse.filters.each do |filter|
@@ -52,7 +54,8 @@ class ListController < ApplicationController
list_opts = build_topic_list_options
list_opts.merge!(options) if options
user = list_target_user
- if params[:category].blank? && filter == :latest && !SiteSetting.show_category_definitions_in_topic_lists
+ if params[:category].blank? && filter == :latest &&
+ !SiteSetting.show_category_definitions_in_topic_lists
list_opts[:no_definitions] = true
end
@@ -61,17 +64,16 @@ class ListController < ApplicationController
if guardian.can_create_shared_draft? && @category.present?
if @category.id == SiteSetting.shared_drafts_category.to_i
# On shared drafts, show the destination category
- list.topics.each do |t|
- t.includes_destination_category = t.shared_draft.present?
- end
+ list.topics.each { |t| t.includes_destination_category = t.shared_draft.present? }
else
# When viewing a non-shared draft category, find topics whose
# destination are this category
- shared_drafts = TopicQuery.new(
- user,
- category: SiteSetting.shared_drafts_category,
- destination_category_id: list_opts[:category]
- ).list_latest
+ shared_drafts =
+ TopicQuery.new(
+ user,
+ category: SiteSetting.shared_drafts_category,
+ destination_category_id: list_opts[:category],
+ ).list_latest
if shared_drafts.present? && shared_drafts.topics.present?
list.shared_drafts = shared_drafts.topics
@@ -90,12 +92,14 @@ class ListController < ApplicationController
if (filter.to_s != current_homepage) && use_crawler_layout?
filter_title = I18n.t("js.filters.#{filter.to_s}.title", count: 0)
if list_opts[:category] && @category
- @title = I18n.t('js.filters.with_category', filter: filter_title, category: @category.name)
+ @title =
+ I18n.t("js.filters.with_category", filter: filter_title, category: @category.name)
else
- @title = I18n.t('js.filters.with_topics', filter: filter_title)
+ @title = I18n.t("js.filters.with_topics", filter: filter_title)
end
@title << " - #{SiteSetting.title}"
- elsif @category.blank? && (filter.to_s == current_homepage) && SiteSetting.short_site_description.present?
+ elsif @category.blank? && (filter.to_s == current_homepage) &&
+ SiteSetting.short_site_description.present?
@title = "#{SiteSetting.title} - #{SiteSetting.short_site_description}"
end
end
@@ -116,14 +120,21 @@ class ListController < ApplicationController
def category_default
canonical_url "#{Discourse.base_url_no_prefix}#{@category.url}"
view_method = @category.default_view
- view_method = 'latest' unless %w(latest top).include?(view_method)
+ view_method = "latest" unless %w[latest top].include?(view_method)
self.public_send(view_method, category: @category.id)
end
def topics_by
list_opts = build_topic_list_options
- target_user = fetch_user_from_params({ include_inactive: current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts) }, [:user_stat, :user_option])
+ target_user =
+ fetch_user_from_params(
+ {
+ include_inactive:
+ current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts),
+ },
+ %i[user_stat user_option],
+ )
ensure_can_see_profile!(target_user)
list = generate_list_for("topics_by", target_user, list_opts)
@@ -152,14 +163,15 @@ class ListController < ApplicationController
end
def message_route(action)
- target_user = fetch_user_from_params({ include_inactive: current_user.try(:staff?) }, [:user_stat, :user_option])
+ target_user =
+ fetch_user_from_params(
+ { include_inactive: current_user.try(:staff?) },
+ %i[user_stat user_option],
+ )
case action
- when :private_messages_unread,
- :private_messages_new,
- :private_messages_group_new,
+ when :private_messages_unread, :private_messages_new, :private_messages_group_new,
:private_messages_group_unread
-
raise Discourse::NotFound if target_user.id != current_user.id
when :private_messages_tag
raise Discourse::NotFound if !guardian.can_tag_pms?
@@ -181,7 +193,7 @@ class ListController < ApplicationController
respond_with_list(list)
end
- %i{
+ %i[
private_messages
private_messages_sent
private_messages_unread
@@ -193,14 +205,12 @@ class ListController < ApplicationController
private_messages_group_archive
private_messages_warnings
private_messages_tag
- }.each do |action|
- generate_message_route(action)
- end
+ ].each { |action| generate_message_route(action) }
def latest_feed
discourse_expires_in 1.minute
- options = { order: 'created' }.merge(build_topic_list_options)
+ options = { order: "created" }.merge(build_topic_list_options)
@title = "#{SiteSetting.title} - #{I18n.t("rss_description.latest")}"
@link = "#{Discourse.base_url}/latest"
@@ -208,7 +218,7 @@ class ListController < ApplicationController
@description = I18n.t("rss_description.latest")
@topic_list = TopicQuery.new(nil, options).list_latest
- render 'list', formats: [:rss]
+ render "list", formats: [:rss]
end
def top_feed
@@ -223,7 +233,7 @@ class ListController < ApplicationController
@topic_list = TopicQuery.new(nil).list_top_for(period)
- render 'list', formats: [:rss]
+ render "list", formats: [:rss]
end
def category_feed
@@ -233,10 +243,11 @@ class ListController < ApplicationController
@title = "#{@category.name} - #{SiteSetting.title}"
@link = "#{Discourse.base_url_no_prefix}#{@category.url}"
@atom_link = "#{Discourse.base_url_no_prefix}#{@category.url}.rss"
- @description = "#{I18n.t('topics_in_category', category: @category.name)} #{@category.description}"
+ @description =
+ "#{I18n.t("topics_in_category", category: @category.name)} #{@category.description}"
@topic_list = TopicQuery.new(current_user).list_new_in_category(@category)
- render 'list', formats: [:rss]
+ render "list", formats: [:rss]
end
def user_topics_feed
@@ -244,22 +255,22 @@ class ListController < ApplicationController
target_user = fetch_user_from_params
ensure_can_see_profile!(target_user)
- @title = "#{SiteSetting.title} - #{I18n.t("rss_description.user_topics", username: target_user.username)}"
+ @title =
+ "#{SiteSetting.title} - #{I18n.t("rss_description.user_topics", username: target_user.username)}"
@link = "#{target_user.full_url}/activity/topics"
@atom_link = "#{target_user.full_url}/activity/topics.rss"
@description = I18n.t("rss_description.user_topics", username: target_user.username)
- @topic_list = TopicQuery
- .new(nil, order: 'created')
- .public_send("list_topics_by", target_user)
+ @topic_list = TopicQuery.new(nil, order: "created").public_send("list_topics_by", target_user)
- render 'list', formats: [:rss]
+ render "list", formats: [:rss]
end
def top(options = nil)
options ||= {}
period = params[:period]
- period ||= ListController.best_period_for(current_user.try(:previous_visit_at), options[:category])
+ period ||=
+ ListController.best_period_for(current_user.try(:previous_visit_at), options[:category])
TopTopic.validate_period(period)
public_send("top_#{period}", options)
end
@@ -299,10 +310,7 @@ class ListController < ApplicationController
end
define_method("category_none_top_#{period}") do
- self.public_send("top_#{period}",
- category: @category.id,
- no_subcategories: true
- )
+ self.public_send("top_#{period}", category: @category.id, no_subcategories: true)
end
# rss feed
@@ -315,7 +323,7 @@ class ListController < ApplicationController
@atom_link = "#{Discourse.base_url}/top.rss?period=#{period}"
@topic_list = TopicQuery.new(nil).list_top_for(period)
- render 'list', formats: [:rss]
+ render "list", formats: [:rss]
end
end
@@ -337,16 +345,17 @@ class ListController < ApplicationController
private
def page_params
- route_params = { format: 'json' }
+ route_params = { format: "json" }
if @category.present?
slug_path = @category.slug_path
- route_params[:category_slug_path_with_id] =
- (slug_path + [@category.id.to_s]).join("/")
+ route_params[:category_slug_path_with_id] = (slug_path + [@category.id.to_s]).join("/")
end
- route_params[:username] = UrlHelper.encode_component(params[:username]) if params[:username].present?
+ route_params[:username] = UrlHelper.encode_component(params[:username]) if params[
+ :username
+ ].present?
route_params[:period] = params[:period] if params[:period].present?
route_params
end
@@ -355,9 +364,7 @@ class ListController < ApplicationController
category_slug_path_with_id = params.require(:category_slug_path_with_id)
@category = Category.find_by_slug_path_with_id(category_slug_path_with_id)
- if @category.nil?
- raise Discourse::NotFound.new("category not found", check_permalinks: true)
- end
+ raise Discourse::NotFound.new("category not found", check_permalinks: true) if @category.nil?
params[:category] = @category.id.to_s
@@ -385,13 +392,14 @@ class ListController < ApplicationController
return redirect_to path(url), status: 301
end
- @description_meta = if @category.uncategorized?
- I18n.t("category.uncategorized_description", locale: SiteSetting.default_locale)
- elsif @category.description_text.present?
- @category.description_text
- else
- SiteSetting.site_description
- end
+ @description_meta =
+ if @category.uncategorized?
+ I18n.t("category.uncategorized_description", locale: SiteSetting.default_locale)
+ elsif @category.description_text.present?
+ @category.description_text
+ else
+ SiteSetting.site_description
+ end
if use_crawler_layout?
@subcategories = @category.subcategories.select { |c| guardian.can_see?(c) }
@@ -431,7 +439,7 @@ class ListController < ApplicationController
opts.delete(:category) if page_params.include?(:category_slug_path_with_id)
- url = public_send(method, opts.merge(page_params)).sub('.json?', '?')
+ url = public_send(method, opts.merge(page_params)).sub(".json?", "?")
# Unicode usernames need to be encoded when calling Rails' path helper. However, it means that the already
# encoded username are encoded again which we do not want. As such, we unencode the url once when unicode usernames
@@ -446,16 +454,24 @@ class ListController < ApplicationController
end
def self.best_period_for(previous_visit_at, category_id = nil)
- default_period = ((category_id && Category.where(id: category_id).pluck_first(:default_top_period)) ||
- SiteSetting.top_page_default_timeframe).to_sym
+ default_period =
+ (
+ (category_id && Category.where(id: category_id).pluck_first(:default_top_period)) ||
+ SiteSetting.top_page_default_timeframe
+ ).to_sym
best_period_with_topics_for(previous_visit_at, category_id, default_period) || default_period
end
- def self.best_period_with_topics_for(previous_visit_at, category_id = nil, default_period = SiteSetting.top_page_default_timeframe)
+ def self.best_period_with_topics_for(
+ previous_visit_at,
+ category_id = nil,
+ default_period = SiteSetting.top_page_default_timeframe
+ )
best_periods_for(previous_visit_at, default_period.to_sym).find do |period|
top_topics = TopTopic.where("#{period}_score > 0")
- top_topics = top_topics.joins(:topic).where("topics.category_id = ?", category_id) if category_id
+ top_topics =
+ top_topics.joins(:topic).where("topics.category_id = ?", category_id) if category_id
top_topics = top_topics.limit(SiteSetting.topics_per_period_in_top_page)
top_topics.count == SiteSetting.topics_per_period_in_top_page
end
@@ -465,13 +481,12 @@ class ListController < ApplicationController
return [default_period, :all].uniq unless date
periods = []
- periods << :daily if date > (1.week + 1.day).ago
- periods << :weekly if date > (1.month + 1.week).ago
- periods << :monthly if date > (3.months + 3.weeks).ago
+ periods << :daily if date > (1.week + 1.day).ago
+ periods << :weekly if date > (1.month + 1.week).ago
+ periods << :monthly if date > (3.months + 3.weeks).ago
periods << :quarterly if date > (1.year + 1.month).ago
- periods << :yearly if date > 3.years.ago
+ periods << :yearly if date > 3.years.ago
periods << :all
periods
end
-
end
diff --git a/app/controllers/metadata_controller.rb b/app/controllers/metadata_controller.rb
index eff9af7ac56..4d75df06f07 100644
--- a/app/controllers/metadata_controller.rb
+++ b/app/controllers/metadata_controller.rb
@@ -6,7 +6,7 @@ class MetadataController < ApplicationController
def manifest
expires_in 1.minutes
- render json: default_manifest.to_json, content_type: 'application/manifest+json'
+ render json: default_manifest.to_json, content_type: "application/manifest+json"
end
def opensearch
@@ -17,13 +17,13 @@ class MetadataController < ApplicationController
def app_association_android
raise Discourse::NotFound unless SiteSetting.app_association_android.present?
expires_in 1.minutes
- render plain: SiteSetting.app_association_android, content_type: 'application/json'
+ render plain: SiteSetting.app_association_android, content_type: "application/json"
end
def app_association_ios
raise Discourse::NotFound unless SiteSetting.app_association_ios.present?
expires_in 1.minutes
- render plain: SiteSetting.app_association_ios, content_type: 'application/json'
+ render plain: SiteSetting.app_association_ios, content_type: "application/json"
end
private
@@ -32,56 +32,56 @@ class MetadataController < ApplicationController
display = "standalone"
if request.user_agent
regex = Regexp.new(SiteSetting.pwa_display_browser_regex)
- if regex.match(request.user_agent)
- display = "browser"
- end
+ display = "browser" if regex.match(request.user_agent)
end
scheme_id = view_context.scheme_id
- primary_color = ColorScheme.hex_for_name('primary', scheme_id)
- icon_url_base = UrlHelper.absolute("/svg-sprite/#{Discourse.current_hostname}/icon/#{primary_color}")
+ primary_color = ColorScheme.hex_for_name("primary", scheme_id)
+ icon_url_base =
+ UrlHelper.absolute("/svg-sprite/#{Discourse.current_hostname}/icon/#{primary_color}")
manifest = {
name: SiteSetting.title,
- short_name: SiteSetting.short_title.presence || SiteSetting.title.truncate(12, separator: ' ', omission: ''),
+ short_name:
+ SiteSetting.short_title.presence ||
+ SiteSetting.title.truncate(12, separator: " ", omission: ""),
description: SiteSetting.site_description,
display: display,
- start_url: Discourse.base_path.present? ? "#{Discourse.base_path}/" : '.',
- background_color: "##{ColorScheme.hex_for_name('secondary', scheme_id)}",
- theme_color: "##{ColorScheme.hex_for_name('header_background', scheme_id)}",
- icons: [
- ],
+ start_url: Discourse.base_path.present? ? "#{Discourse.base_path}/" : ".",
+ background_color: "##{ColorScheme.hex_for_name("secondary", scheme_id)}",
+ theme_color: "##{ColorScheme.hex_for_name("header_background", scheme_id)}",
+ icons: [],
share_target: {
action: "#{Discourse.base_path}/new-topic",
method: "GET",
enctype: "application/x-www-form-urlencoded",
params: {
title: "title",
- text: "body"
- }
+ text: "body",
+ },
},
shortcuts: [
{
- name: I18n.t('js.topic.create_long'),
- short_name: I18n.t('js.topic.create'),
+ name: I18n.t("js.topic.create_long"),
+ short_name: I18n.t("js.topic.create"),
url: "#{Discourse.base_path}/new-topic",
},
{
- name: I18n.t('js.user.messages.inbox'),
- short_name: I18n.t('js.user.messages.inbox'),
+ name: I18n.t("js.user.messages.inbox"),
+ short_name: I18n.t("js.user.messages.inbox"),
url: "#{Discourse.base_path}/my/messages",
},
{
- name: I18n.t('js.user.bookmarks'),
- short_name: I18n.t('js.user.bookmarks'),
+ name: I18n.t("js.user.bookmarks"),
+ short_name: I18n.t("js.user.bookmarks"),
url: "#{Discourse.base_path}/my/activity/bookmarks",
},
{
- name: I18n.t('js.filters.top.title'),
- short_name: I18n.t('js.filters.top.title'),
+ name: I18n.t("js.filters.top.title"),
+ short_name: I18n.t("js.filters.top.title"),
url: "#{Discourse.base_path}/top",
- }
- ]
+ },
+ ],
}
logo = SiteSetting.site_manifest_icon_url
@@ -89,41 +89,40 @@ class MetadataController < ApplicationController
icon_entry = {
src: UrlHelper.absolute(logo),
sizes: "512x512",
- type: MiniMime.lookup_by_filename(logo)&.content_type || "image/png"
+ type: MiniMime.lookup_by_filename(logo)&.content_type || "image/png",
}
manifest[:icons] << icon_entry.dup
icon_entry[:purpose] = "maskable"
manifest[:icons] << icon_entry
end
- SiteSetting.manifest_screenshots.split('|').each do |image|
- next unless Discourse.store.has_been_uploaded?(image)
+ SiteSetting
+ .manifest_screenshots
+ .split("|")
+ .each do |image|
+ next unless Discourse.store.has_been_uploaded?(image)
- upload = Upload.find_by(sha1: Upload.extract_sha1(image))
- next if upload.nil?
+ upload = Upload.find_by(sha1: Upload.extract_sha1(image))
+ next if upload.nil?
- manifest[:screenshots] = [] if manifest.dig(:screenshots).nil?
+ manifest[:screenshots] = [] if manifest.dig(:screenshots).nil?
- manifest[:screenshots] << {
- src: UrlHelper.absolute(image),
- sizes: "#{upload.width}x#{upload.height}",
- type: "image/#{upload.extension}"
- }
- end
+ manifest[:screenshots] << {
+ src: UrlHelper.absolute(image),
+ sizes: "#{upload.width}x#{upload.height}",
+ type: "image/#{upload.extension}",
+ }
+ end
- if current_user && current_user.trust_level >= 1 && SiteSetting.native_app_install_banner_android
- manifest = manifest.merge(
- prefer_related_applications: true,
- related_applications: [
- {
- platform: "play",
- id: SiteSetting.android_app_id
- }
- ]
- )
+ if current_user && current_user.trust_level >= 1 &&
+ SiteSetting.native_app_install_banner_android
+ manifest =
+ manifest.merge(
+ prefer_related_applications: true,
+ related_applications: [{ platform: "play", id: SiteSetting.android_app_id }],
+ )
end
manifest
end
-
end
diff --git a/app/controllers/new_topic_controller.rb b/app/controllers/new_topic_controller.rb
index f6b90176661..2de899377b8 100644
--- a/app/controllers/new_topic_controller.rb
+++ b/app/controllers/new_topic_controller.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
class NewTopicController < ApplicationController
- def index; end
+ def index
+ end
end
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index 2006ddedddb..f4955519574 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
class NotificationsController < ApplicationController
-
requires_login
- before_action :ensure_admin, only: [:create, :update, :destroy]
- before_action :set_notification, only: [:update, :destroy]
+ before_action :ensure_admin, only: %i[create update destroy]
+ before_action :set_notification, only: %i[update destroy]
def index
user =
@@ -20,9 +19,8 @@ class NotificationsController < ApplicationController
if notification_types = params[:filter_by_types]&.split(",").presence
notification_types.map! do |type|
- Notification.types[type.to_sym] || (
- raise Discourse::InvalidParameters.new("invalid notification type: #{type}")
- )
+ Notification.types[type.to_sym] ||
+ (raise Discourse::InvalidParameters.new("invalid notification type: #{type}"))
end
end
@@ -35,7 +33,8 @@ class NotificationsController < ApplicationController
if SiteSetting.legacy_navigation_menu?
notifications = Notification.recent_report(current_user, limit, notification_types)
else
- notifications = Notification.prioritized_list(current_user, count: limit, types: notification_types)
+ notifications =
+ Notification.prioritized_list(current_user, count: limit, types: notification_types)
# notification_types is blank for the "all notifications" user menu tab
include_reviewables = notification_types.blank? && guardian.can_see_review_queue?
end
@@ -47,7 +46,8 @@ class NotificationsController < ApplicationController
end
end
- if !params.has_key?(:silent) && params[:bump_last_seen_reviewable] && !@readonly_mode && include_reviewables
+ if !params.has_key?(:silent) && params[:bump_last_seen_reviewable] && !@readonly_mode &&
+ include_reviewables
current_user_id = current_user.id
Scheduler::Defer.later "bump last seen reviewable for user" do
# we lookup current_user again in the background thread to avoid
@@ -62,13 +62,13 @@ class NotificationsController < ApplicationController
json = {
notifications: serialize_data(notifications, NotificationSerializer),
- seen_notification_id: current_user.seen_notification_id
+ seen_notification_id: current_user.seen_notification_id,
}
if include_reviewables
json[:pending_reviewables] = Reviewable.basic_serializers_for_list(
Reviewable.user_menu_list_for(current_user),
- current_user
+ current_user,
).as_json
end
@@ -76,10 +76,8 @@ class NotificationsController < ApplicationController
else
offset = params[:offset].to_i
- notifications = Notification.where(user_id: user.id)
- .visible
- .includes(:topic)
- .order(created_at: :desc)
+ notifications =
+ Notification.where(user_id: user.id).visible.includes(:topic).order(created_at: :desc)
notifications = notifications.where(read: true) if params[:filter] == "read"
@@ -88,12 +86,14 @@ class NotificationsController < ApplicationController
total_rows = notifications.dup.count
notifications = notifications.offset(offset).limit(60)
notifications = filter_inaccessible_notifications(notifications)
- render_json_dump(notifications: serialize_data(notifications, NotificationSerializer),
- total_rows_notifications: total_rows,
- seen_notification_id: user.seen_notification_id,
- load_more_notifications: notifications_path(username: user.username, offset: offset + 60, filter: params[:filter]))
+ render_json_dump(
+ notifications: serialize_data(notifications, NotificationSerializer),
+ total_rows_notifications: total_rows,
+ seen_notification_id: user.seen_notification_id,
+ load_more_notifications:
+ notifications_path(username: user.username, offset: offset + 60, filter: params[:filter]),
+ )
end
-
end
def mark_read
@@ -144,7 +144,15 @@ class NotificationsController < ApplicationController
end
def notification_params
- params.permit(:notification_type, :user_id, :data, :read, :topic_id, :post_number, :post_action_id)
+ params.permit(
+ :notification_type,
+ :user_id,
+ :data,
+ :read,
+ :topic_id,
+ :post_number,
+ :post_action_id,
+ )
end
def render_notification
diff --git a/app/controllers/offline_controller.rb b/app/controllers/offline_controller.rb
index 03990e8a5ff..b826e3f30dc 100644
--- a/app/controllers/offline_controller.rb
+++ b/app/controllers/offline_controller.rb
@@ -5,6 +5,6 @@ class OfflineController < ApplicationController
skip_before_action :preload_json, :check_xhr, :redirect_to_login_if_required
def index
- render :offline, content_type: 'text/html'
+ render :offline, content_type: "text/html"
end
end
diff --git a/app/controllers/onebox_controller.rb b/app/controllers/onebox_controller.rb
index dfa81c5e80a..5ccdcd0b9e0 100644
--- a/app/controllers/onebox_controller.rb
+++ b/app/controllers/onebox_controller.rb
@@ -4,7 +4,7 @@ class OneboxController < ApplicationController
requires_login
def show
- unless params[:refresh] == 'true'
+ unless params[:refresh] == "true"
preview = Oneboxer.cached_preview(params[:url])
preview = preview.strip if preview.present?
return render(plain: preview) if preview.present?
@@ -16,7 +16,7 @@ class OneboxController < ApplicationController
user_id = current_user.id
category_id = params[:category_id].to_i
topic_id = params[:topic_id].to_i
- invalidate = params[:refresh] == 'true'
+ invalidate = params[:refresh] == "true"
url = params[:url]
return render(body: nil, status: 404) if Oneboxer.recently_failed?(url)
@@ -24,12 +24,14 @@ class OneboxController < ApplicationController
hijack(info: "#{url} topic_id: #{topic_id} user_id: #{user_id}") do
Oneboxer.preview_onebox!(user_id)
- preview = Oneboxer.preview(url,
- invalidate_oneboxes: invalidate,
- user_id: user_id,
- category_id: category_id,
- topic_id: topic_id
- )
+ preview =
+ Oneboxer.preview(
+ url,
+ invalidate_oneboxes: invalidate,
+ user_id: user_id,
+ category_id: category_id,
+ topic_id: topic_id,
+ )
preview = preview.strip if preview.present?
@@ -43,5 +45,4 @@ class OneboxController < ApplicationController
end
end
end
-
end
diff --git a/app/controllers/permalinks_controller.rb b/app/controllers/permalinks_controller.rb
index 33f8d04c406..ee34e6bfaad 100644
--- a/app/controllers/permalinks_controller.rb
+++ b/app/controllers/permalinks_controller.rb
@@ -33,12 +33,8 @@ class PermalinksController < ApplicationController
render json: MultiJson.dump(data)
rescue Discourse::NotFound
- data = {
- found: false,
- html: build_not_found_page(status: 200),
- }
+ data = { found: false, html: build_not_found_page(status: 200) }
render json: MultiJson.dump(data)
end
end
-
end
diff --git a/app/controllers/post_action_users_controller.rb b/app/controllers/post_action_users_controller.rb
index 24cac61295e..7b39cd2fabb 100644
--- a/app/controllers/post_action_users_controller.rb
+++ b/app/controllers/post_action_users_controller.rb
@@ -23,11 +23,14 @@ class PostActionUsersController < ApplicationController
unknown_user_ids.merge(result)
end
- post_actions = post.post_actions.where(post_action_type_id: post_action_type_id)
- .includes(:user)
- .offset(page * page_size)
- .order('post_actions.created_at ASC')
- .limit(page_size)
+ post_actions =
+ post
+ .post_actions
+ .where(post_action_type_id: post_action_type_id)
+ .includes(:user)
+ .offset(page * page_size)
+ .order("post_actions.created_at ASC")
+ .limit(page_size)
if !guardian.can_see_post_actors?(post.topic, post_action_type_id)
raise Discourse::InvalidAccess unless current_user
@@ -38,16 +41,15 @@ class PostActionUsersController < ApplicationController
total_count = post["#{action_type}_count"].to_i
data = {
- post_action_users: serialize_data(
- post_actions.to_a,
- PostActionUserSerializer,
- unknown_user_ids: unknown_user_ids
- )
+ post_action_users:
+ serialize_data(
+ post_actions.to_a,
+ PostActionUserSerializer,
+ unknown_user_ids: unknown_user_ids,
+ ),
}
- if total_count > page_size
- data[:total_rows_post_action_users] = total_count
- end
+ data[:total_rows_post_action_users] = total_count if total_count > page_size
render_json_dump(data)
end
diff --git a/app/controllers/post_actions_controller.rb b/app/controllers/post_actions_controller.rb
index 9e757970446..966af4d4bae 100644
--- a/app/controllers/post_actions_controller.rb
+++ b/app/controllers/post_actions_controller.rb
@@ -9,16 +9,17 @@ class PostActionsController < ApplicationController
def create
raise Discourse::NotFound if @post.blank?
- creator = PostActionCreator.new(
- current_user,
- @post,
- @post_action_type_id,
- is_warning: params[:is_warning],
- message: params[:message],
- take_action: params[:take_action] == 'true',
- flag_topic: params[:flag_topic] == 'true',
- queue_for_review: params[:queue_for_review] == 'true'
- )
+ creator =
+ PostActionCreator.new(
+ current_user,
+ @post,
+ @post_action_type_id,
+ is_warning: params[:is_warning],
+ message: params[:message],
+ take_action: params[:take_action] == "true",
+ flag_topic: params[:flag_topic] == "true",
+ queue_for_review: params[:queue_for_review] == "true",
+ )
result = creator.perform
if result.failed?
@@ -29,19 +30,20 @@ class PostActionsController < ApplicationController
if @post_action_type_id == PostActionType.types[:like]
limiter = result.post_action.post_action_rate_limiter
- response.headers['Discourse-Actions-Remaining'] = limiter.remaining.to_s
- response.headers['Discourse-Actions-Max'] = limiter.max.to_s
+ response.headers["Discourse-Actions-Remaining"] = limiter.remaining.to_s
+ response.headers["Discourse-Actions-Max"] = limiter.max.to_s
end
render_post_json(@post, add_raw: false)
end
end
def destroy
- result = PostActionDestroyer.new(
- current_user,
- Post.find_by(id: params[:id].to_i),
- @post_action_type_id
- ).perform
+ result =
+ PostActionDestroyer.new(
+ current_user,
+ Post.find_by(id: params[:id].to_i),
+ @post_action_type_id,
+ ).perform
if result.failed?
render_json_error(result)
@@ -58,15 +60,16 @@ class PostActionsController < ApplicationController
flag_topic = params[:flag_topic]
flag_topic = flag_topic && (flag_topic == true || flag_topic == "true")
- post_id = if flag_topic
- begin
- Topic.find(params[:id]).posts.first.id
- rescue
- raise Discourse::NotFound
+ post_id =
+ if flag_topic
+ begin
+ Topic.find(params[:id]).posts.first.id
+ rescue StandardError
+ raise Discourse::NotFound
+ end
+ else
+ params[:id]
end
- else
- params[:id]
- end
finder = Post.where(id: post_id)
diff --git a/app/controllers/post_readers_controller.rb b/app/controllers/post_readers_controller.rb
index bc9c3a197b0..a6ff0a1f5e1 100644
--- a/app/controllers/post_readers_controller.rb
+++ b/app/controllers/post_readers_controller.rb
@@ -7,23 +7,30 @@ class PostReadersController < ApplicationController
post = Post.includes(topic: %i[topic_allowed_groups topic_allowed_users]).find(params[:id])
ensure_can_see_readers!(post)
- readers = User
- .real
- .where(staged: false)
- .where.not(id: post.user_id)
- .joins(:topic_users)
- .where.not(topic_users: { last_read_post_number: nil })
- .where('topic_users.topic_id = ? AND topic_users.last_read_post_number >= ?', post.topic_id, post.post_number)
+ readers =
+ User
+ .real
+ .where(staged: false)
+ .where.not(id: post.user_id)
+ .joins(:topic_users)
+ .where.not(topic_users: { last_read_post_number: nil })
+ .where(
+ "topic_users.topic_id = ? AND topic_users.last_read_post_number >= ?",
+ post.topic_id,
+ post.post_number,
+ )
- readers = readers.where('admin OR moderator') if post.whisper?
+ readers = readers.where("admin OR moderator") if post.whisper?
- readers = readers.map do |r|
- {
- id: r.id, avatar_template: r.avatar_template,
- username: r.username,
- username_lower: r.username_lower
- }
- end
+ readers =
+ readers.map do |r|
+ {
+ id: r.id,
+ avatar_template: r.avatar_template,
+ username: r.username,
+ username_lower: r.username_lower,
+ }
+ end
render_json_dump(post_readers: readers)
end
@@ -31,10 +38,17 @@ class PostReadersController < ApplicationController
private
def ensure_can_see_readers!(post)
- show_readers = GroupUser
- .where(user: current_user)
- .joins(:group)
- .where(groups: { id: post.topic.topic_allowed_groups.map(&:group_id), publish_read_state: true }).exists?
+ show_readers =
+ GroupUser
+ .where(user: current_user)
+ .joins(:group)
+ .where(
+ groups: {
+ id: post.topic.topic_allowed_groups.map(&:group_id),
+ publish_read_state: true,
+ },
+ )
+ .exists?
raise Discourse::InvalidAccess unless show_readers
end
diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb
index c404cb6969b..b5c9ad2e0e2 100644
--- a/app/controllers/posts_controller.rb
+++ b/app/controllers/posts_controller.rb
@@ -5,31 +5,27 @@ class PostsController < ApplicationController
# see https://github.com/rails/rails/issues/44867
self._flash_types -= [:notice]
- requires_login except: [
- :show,
- :replies,
- :by_number,
- :by_date,
- :short_link,
- :reply_history,
- :reply_ids,
- :revisions,
- :latest_revision,
- :expand_embed,
- :markdown_id,
- :markdown_num,
- :cooked,
- :latest,
- :user_posts_feed
- ]
+ requires_login except: %i[
+ show
+ replies
+ by_number
+ by_date
+ short_link
+ reply_history
+ reply_ids
+ revisions
+ latest_revision
+ expand_embed
+ markdown_id
+ markdown_num
+ cooked
+ latest
+ user_posts_feed
+ ]
- skip_before_action :preload_json, :check_xhr, only: [
- :markdown_id,
- :markdown_num,
- :short_link,
- :latest,
- :user_posts_feed
- ]
+ skip_before_action :preload_json,
+ :check_xhr,
+ only: %i[markdown_id markdown_num short_link latest user_posts_feed]
MARKDOWN_TOPIC_PAGE_SIZE ||= 100
@@ -42,13 +38,15 @@ class PostsController < ApplicationController
post_revision = find_post_revision_from_topic_id
render plain: post_revision.modifications[:raw].last
elsif params[:post_number].present?
- markdown Post.find_by(topic_id: params[:topic_id].to_i, post_number: params[:post_number].to_i)
+ markdown Post.find_by(
+ topic_id: params[:topic_id].to_i,
+ post_number: params[:post_number].to_i,
+ )
else
opts = params.slice(:page)
opts[:limit] = MARKDOWN_TOPIC_PAGE_SIZE
topic_view = TopicView.new(params[:topic_id], current_user, opts)
- content = topic_view.posts.map do |p|
- <<~MD
+ content = topic_view.posts.map { |p| <<~MD }
#{p.user.username} | #{p.updated_at} | ##{p.post_number}
#{p.raw}
@@ -56,7 +54,6 @@ class PostsController < ApplicationController
-------------------------
MD
- end
render plain: content.join
end
end
@@ -68,26 +65,30 @@ class PostsController < ApplicationController
if params[:id] == "private_posts"
raise Discourse::NotFound if current_user.nil?
- posts = Post.private_posts
- .order(created_at: :desc)
- .where('posts.id <= ?', last_post_id)
- .where('posts.id > ?', last_post_id - 50)
- .includes(topic: :category)
- .includes(user: [:primary_group, :flair_group])
- .includes(:reply_to_user)
- .limit(50)
+ posts =
+ Post
+ .private_posts
+ .order(created_at: :desc)
+ .where("posts.id <= ?", last_post_id)
+ .where("posts.id > ?", last_post_id - 50)
+ .includes(topic: :category)
+ .includes(user: %i[primary_group flair_group])
+ .includes(:reply_to_user)
+ .limit(50)
rss_description = I18n.t("rss_description.private_posts")
else
- posts = Post.public_posts
- .visible
- .where(post_type: Post.types[:regular])
- .order(created_at: :desc)
- .where('posts.id <= ?', last_post_id)
- .where('posts.id > ?', last_post_id - 50)
- .includes(topic: :category)
- .includes(user: [:primary_group, :flair_group])
- .includes(:reply_to_user)
- .limit(50)
+ posts =
+ Post
+ .public_posts
+ .visible
+ .where(post_type: Post.types[:regular])
+ .order(created_at: :desc)
+ .where("posts.id <= ?", last_post_id)
+ .where("posts.id > ?", last_post_id - 50)
+ .includes(topic: :category)
+ .includes(user: %i[primary_group flair_group])
+ .includes(:reply_to_user)
+ .limit(50)
rss_description = I18n.t("rss_description.posts")
@use_canonical = true
end
@@ -103,17 +104,20 @@ class PostsController < ApplicationController
@title = "#{SiteSetting.title} - #{rss_description}"
@link = Discourse.base_url
@description = rss_description
- render 'posts/latest', formats: [:rss]
+ render "posts/latest", formats: [:rss]
end
format.json do
- render_json_dump(serialize_data(posts,
- PostSerializer,
- scope: guardian,
- root: params[:id],
- add_raw: true,
- add_title: true,
- all_post_actions: counts)
- )
+ render_json_dump(
+ serialize_data(
+ posts,
+ PostSerializer,
+ scope: guardian,
+ root: params[:id],
+ add_raw: true,
+ add_title: true,
+ all_post_actions: counts,
+ ),
+ )
end
end
end
@@ -123,35 +127,33 @@ class PostsController < ApplicationController
user = fetch_user_from_params
raise Discourse::NotFound unless guardian.can_see_profile?(user)
- posts = Post.public_posts
- .visible
- .where(user_id: user.id)
- .where(post_type: Post.types[:regular])
- .order(created_at: :desc)
- .includes(:user)
- .includes(topic: :category)
- .limit(50)
+ posts =
+ Post
+ .public_posts
+ .visible
+ .where(user_id: user.id)
+ .where(post_type: Post.types[:regular])
+ .order(created_at: :desc)
+ .includes(:user)
+ .includes(topic: :category)
+ .limit(50)
posts = posts.reject { |post| !guardian.can_see?(post) || post.topic.blank? }
respond_to do |format|
format.rss do
@posts = posts
- @title = "#{SiteSetting.title} - #{I18n.t("rss_description.user_posts", username: user.username)}"
+ @title =
+ "#{SiteSetting.title} - #{I18n.t("rss_description.user_posts", username: user.username)}"
@link = "#{user.full_url}/activity"
@description = I18n.t("rss_description.user_posts", username: user.username)
- render 'posts/latest', formats: [:rss]
+ render "posts/latest", formats: [:rss]
end
format.json do
- render_json_dump(serialize_data(posts,
- PostSerializer,
- scope: guardian,
- add_excerpt: true)
- )
+ render_json_dump(serialize_data(posts, PostSerializer, scope: guardian, add_excerpt: true))
end
end
-
end
def cooked
@@ -173,7 +175,7 @@ class PostsController < ApplicationController
# Stuff the user in the request object, because that's what IncomingLink wants
if params[:user_id]
user = User.find_by(id: params[:user_id].to_i)
- request['u'] = user.username_lower if user
+ request["u"] = user.username_lower if user
end
guardian.ensure_can_see!(post)
@@ -188,13 +190,14 @@ class PostsController < ApplicationController
manager = NewPostManager.new(current_user, @manager_params)
if is_api?
- memoized_payload = DistributedMemoizer.memoize(signature_for(@manager_params), 120) do
- result = manager.perform
- MultiJson.dump(serialize_data(result, NewPostResultSerializer, root: false))
- end
+ memoized_payload =
+ DistributedMemoizer.memoize(signature_for(@manager_params), 120) do
+ result = manager.perform
+ MultiJson.dump(serialize_data(result, NewPostResultSerializer, root: false))
+ end
parsed_payload = JSON.parse(memoized_payload)
- backwards_compatible_json(parsed_payload, parsed_payload['success'])
+ backwards_compatible_json(parsed_payload, parsed_payload["success"])
else
result = manager.perform
json = serialize_data(result, NewPostResultSerializer, root: false)
@@ -213,27 +216,20 @@ class PostsController < ApplicationController
post.image_sizes = params[:image_sizes] if params[:image_sizes].present?
- if !guardian.public_send("can_edit?", post) &&
- post.user_id == current_user.id &&
- post.edit_time_limit_expired?(current_user)
-
- return render_json_error(I18n.t('too_late_to_edit'))
+ if !guardian.public_send("can_edit?", post) && post.user_id == current_user.id &&
+ post.edit_time_limit_expired?(current_user)
+ return render_json_error(I18n.t("too_late_to_edit"))
end
guardian.ensure_can_edit!(post)
- changes = {
- raw: params[:post][:raw],
- edit_reason: params[:post][:edit_reason]
- }
+ changes = { raw: params[:post][:raw], edit_reason: params[:post][:edit_reason] }
- Post.plugin_permitted_update_params.keys.each do |param|
- changes[param] = params[:post][param]
- end
+ Post.plugin_permitted_update_params.keys.each { |param| changes[param] = params[:post][param] }
raw_old = params[:post][:raw_old]
if raw_old.present? && raw_old != post.raw
- return render_json_error(I18n.t('edit_conflict'), status: 409)
+ return render_json_error(I18n.t("edit_conflict"), status: 409)
end
# to stay consistent with the create api, we allow for title & category changes here
@@ -246,7 +242,7 @@ class PostsController < ApplicationController
if category || (changes[:category_id].to_i == 0)
guardian.ensure_can_move_topic_to_category!(category)
else
- return render_json_error(I18n.t('category.errors.not_found'))
+ return render_json_error(I18n.t("category.errors.not_found"))
end
end
end
@@ -273,7 +269,11 @@ class PostsController < ApplicationController
result = { post: post_serializer.as_json }
if revisor.category_changed.present?
- result[:category] = BasicCategorySerializer.new(revisor.category_changed, scope: guardian, root: false).as_json
+ result[:category] = BasicCategorySerializer.new(
+ revisor.category_changed,
+ scope: guardian,
+ root: false,
+ ).as_json
end
render_json_dump(result)
@@ -303,11 +303,7 @@ class PostsController < ApplicationController
user_custom_fields = User.custom_fields_for_ids(reply_history.pluck(:user_id), added_fields)
end
- render_serialized(
- reply_history,
- PostSerializer,
- user_custom_fields: user_custom_fields
- )
+ render_serialized(reply_history, PostSerializer, user_custom_fields: user_custom_fields)
end
def reply_ids
@@ -335,15 +331,25 @@ class PostsController < ApplicationController
end
unless guardian.can_moderate_topic?(post.topic)
- RateLimiter.new(current_user, "delete_post_per_min", SiteSetting.max_post_deletions_per_minute, 1.minute).performed!
- RateLimiter.new(current_user, "delete_post_per_day", SiteSetting.max_post_deletions_per_day, 1.day).performed!
+ RateLimiter.new(
+ current_user,
+ "delete_post_per_min",
+ SiteSetting.max_post_deletions_per_minute,
+ 1.minute,
+ ).performed!
+ RateLimiter.new(
+ current_user,
+ "delete_post_per_day",
+ SiteSetting.max_post_deletions_per_day,
+ 1.day,
+ ).performed!
end
PostDestroyer.new(
current_user,
post,
context: params[:context],
- force_destroy: force_destroy
+ force_destroy: force_destroy,
).destroy
render body: nil
@@ -351,8 +357,8 @@ class PostsController < ApplicationController
def expand_embed
render json: { cooked: TopicEmbed.expanded_for(find_post_from_params) }
- rescue
- render_json_error I18n.t('errors.embed.load_from_remote')
+ rescue StandardError
+ render_json_error I18n.t("errors.embed.load_from_remote")
end
def recover
@@ -360,8 +366,18 @@ class PostsController < ApplicationController
guardian.ensure_can_recover_post!(post)
unless guardian.can_moderate_topic?(post.topic)
- RateLimiter.new(current_user, "delete_post_per_min", SiteSetting.max_post_deletions_per_minute, 1.minute).performed!
- RateLimiter.new(current_user, "delete_post_per_day", SiteSetting.max_post_deletions_per_day, 1.day).performed!
+ RateLimiter.new(
+ current_user,
+ "delete_post_per_min",
+ SiteSetting.max_post_deletions_per_minute,
+ 1.minute,
+ ).performed!
+ RateLimiter.new(
+ current_user,
+ "delete_post_per_day",
+ SiteSetting.max_post_deletions_per_day,
+ 1.day,
+ ).performed!
end
destroyer = PostDestroyer.new(current_user, post)
@@ -383,7 +399,11 @@ class PostsController < ApplicationController
Post.transaction do
posts.each_with_index do |p, i|
- PostDestroyer.new(current_user, p, defer_flags: !(agree_with_first_reply_flag && i == 0)).destroy
+ PostDestroyer.new(
+ current_user,
+ p,
+ defer_flags: !(agree_with_first_reply_flag && i == 0),
+ ).destroy
end
end
@@ -418,7 +438,8 @@ class PostsController < ApplicationController
raise Discourse::NotFound if post.hidden && !guardian.can_view_hidden_post_revisions?
post_revision = find_post_revision_from_params
- post_revision_serializer = PostRevisionSerializer.new(post_revision, scope: guardian, root: false)
+ post_revision_serializer =
+ PostRevisionSerializer.new(post_revision, scope: guardian, root: false)
render_json_dump(post_revision_serializer)
end
@@ -427,7 +448,8 @@ class PostsController < ApplicationController
raise Discourse::NotFound if post.hidden && !guardian.can_view_hidden_post_revisions?
post_revision = find_latest_post_revision_from_params
- post_revision_serializer = PostRevisionSerializer.new(post_revision, scope: guardian, root: false)
+ post_revision_serializer =
+ PostRevisionSerializer.new(post_revision, scope: guardian, root: false)
render_json_dump(post_revision_serializer)
end
@@ -473,17 +495,27 @@ class PostsController < ApplicationController
post_revision.post = post
guardian.ensure_can_see!(post_revision)
guardian.ensure_can_edit!(post)
- return render_json_error(I18n.t('revert_version_same')) if post_revision.modifications["raw"].blank? && post_revision.modifications["title"].blank? && post_revision.modifications["category_id"].blank?
+ if post_revision.modifications["raw"].blank? && post_revision.modifications["title"].blank? &&
+ post_revision.modifications["category_id"].blank?
+ return render_json_error(I18n.t("revert_version_same"))
+ end
topic = Topic.with_deleted.find(post.topic_id)
changes = {}
- changes[:raw] = post_revision.modifications["raw"][0] if post_revision.modifications["raw"].present? && post_revision.modifications["raw"][0] != post.raw
+ changes[:raw] = post_revision.modifications["raw"][0] if post_revision.modifications[
+ "raw"
+ ].present? && post_revision.modifications["raw"][0] != post.raw
if post.is_first_post?
- changes[:title] = post_revision.modifications["title"][0] if post_revision.modifications["title"].present? && post_revision.modifications["title"][0] != topic.title
- changes[:category_id] = post_revision.modifications["category_id"][0] if post_revision.modifications["category_id"].present? && post_revision.modifications["category_id"][0] != topic.category.id
+ changes[:title] = post_revision.modifications["title"][0] if post_revision.modifications[
+ "title"
+ ].present? && post_revision.modifications["title"][0] != topic.title
+ changes[:category_id] = post_revision.modifications["category_id"][
+ 0
+ ] if post_revision.modifications["category_id"].present? &&
+ post_revision.modifications["category_id"][0] != topic.category.id
end
- return render_json_error(I18n.t('revert_version_same')) unless changes.length > 0
+ return render_json_error(I18n.t("revert_version_same")) unless changes.length > 0
changes[:edit_reason] = "reverted to version ##{post_revision.number.to_i - 1}"
revisor = PostRevisor.new(post, topic)
@@ -500,8 +532,14 @@ class PostsController < ApplicationController
result = { post: post_serializer.as_json }
if post.is_first_post?
- result[:topic] = BasicTopicSerializer.new(topic, scope: guardian, root: false).as_json if post_revision.modifications["title"].present?
- result[:category_id] = post_revision.modifications["category_id"][0] if post_revision.modifications["category_id"].present?
+ result[:topic] = BasicTopicSerializer.new(
+ topic,
+ scope: guardian,
+ root: false,
+ ).as_json if post_revision.modifications["title"].present?
+ result[:category_id] = post_revision.modifications["category_id"][
+ 0
+ ] if post_revision.modifications["category_id"].present?
end
render_json_dump(result)
@@ -524,7 +562,7 @@ class PostsController < ApplicationController
post.custom_fields[Post::NOTICE] = {
type: Post.notices[:custom],
raw: params[:notice],
- cooked: PrettyText.cook(params[:notice], features: { onebox: false })
+ cooked: PrettyText.cook(params[:notice], features: { onebox: false }),
}
else
post.custom_fields.delete(Post::NOTICE)
@@ -535,7 +573,7 @@ class PostsController < ApplicationController
StaffActionLogger.new(current_user).log_post_staff_note(
post,
old_value: old_notice&.[]("raw"),
- new_value: params[:notice]
+ new_value: params[:notice],
)
render body: nil
@@ -544,14 +582,16 @@ class PostsController < ApplicationController
def destroy_bookmark
params.require(:post_id)
- bookmark_id = Bookmark.where(
- bookmarkable_id: params[:post_id],
- bookmarkable_type: "Post",
- user_id: current_user.id
- ).pluck_first(:id)
+ bookmark_id =
+ Bookmark.where(
+ bookmarkable_id: params[:post_id],
+ bookmarkable_type: "Post",
+ user_id: current_user.id,
+ ).pluck_first(:id)
destroyed_bookmark = BookmarkManager.new(current_user).destroy(bookmark_id)
- render json: success_json.merge(BookmarkManager.bookmark_metadata(destroyed_bookmark, current_user))
+ render json:
+ success_json.merge(BookmarkManager.bookmark_metadata(destroyed_bookmark, current_user))
end
def wiki
@@ -596,8 +636,9 @@ class PostsController < ApplicationController
def flagged_posts
Discourse.deprecate(
- 'PostsController#flagged_posts is deprecated. Please use /review instead.',
- since: '2.8.0.beta4', drop_from: '2.9'
+ "PostsController#flagged_posts is deprecated. Please use /review instead.",
+ since: "2.8.0.beta4",
+ drop_from: "2.9",
)
params.permit(:offset, :limit)
@@ -607,10 +648,14 @@ class PostsController < ApplicationController
offset = [params[:offset].to_i, 0].max
limit = [(params[:limit] || 60).to_i, 100].min
- posts = user_posts(guardian, user.id, offset: offset, limit: limit)
- .where(id: PostAction.where(post_action_type_id: PostActionType.notify_flag_type_ids)
- .where(disagreed_at: nil)
- .select(:post_id))
+ posts =
+ user_posts(guardian, user.id, offset: offset, limit: limit).where(
+ id:
+ PostAction
+ .where(post_action_type_id: PostActionType.notify_flag_type_ids)
+ .where(disagreed_at: nil)
+ .select(:post_id),
+ )
render_serialized(posts, AdminUserActionSerializer)
end
@@ -633,7 +678,11 @@ class PostsController < ApplicationController
user = fetch_user_from_params
raise Discourse::NotFound unless guardian.can_edit_user?(user)
- render_serialized(user.pending_posts.order(created_at: :desc), PendingPostSerializer, root: :pending_posts)
+ render_serialized(
+ user.pending_posts.order(created_at: :desc),
+ PendingPostSerializer,
+ root: :pending_posts,
+ )
end
protected
@@ -692,7 +741,8 @@ class PostsController < ApplicationController
end
def find_post_revision_from_topic_id
- post = Post.find_by(topic_id: params[:topic_id].to_i, post_number: (params[:post_number] || 1).to_i)
+ post =
+ Post.find_by(topic_id: params[:topic_id].to_i, post_number: (params[:post_number] || 1).to_i)
raise Discourse::NotFound unless guardian.can_see?(post)
revision = params[:revision].to_i
@@ -711,26 +761,26 @@ class PostsController < ApplicationController
def user_posts(guardian, user_id, opts)
# Topic.unscoped is necessary to remove the default deleted_at: nil scope
- posts = Topic.unscoped do
- Post.includes(:user, :topic, :deleted_by, :user_actions)
- .where(user_id: user_id)
- .with_deleted
- .order(created_at: :desc)
- end
+ posts =
+ Topic.unscoped do
+ Post
+ .includes(:user, :topic, :deleted_by, :user_actions)
+ .where(user_id: user_id)
+ .with_deleted
+ .order(created_at: :desc)
+ end
if guardian.user.moderator?
-
# Awful hack, but you can't seem to remove the `default_scope` when joining
# So instead I grab the topics separately
topic_ids = posts.dup.pluck(:topic_id)
- topics = Topic.where(id: topic_ids).with_deleted.where.not(archetype: 'private_message')
+ topics = Topic.where(id: topic_ids).with_deleted.where.not(archetype: "private_message")
topics = topics.secured(guardian)
posts = posts.where(topic_id: topics.pluck(:id))
end
- posts.offset(opts[:offset])
- .limit(opts[:limit])
+ posts.offset(opts[:offset]).limit(opts[:limit])
end
def create_params
@@ -747,18 +797,18 @@ class PostsController < ApplicationController
:typing_duration_msecs,
:composer_open_duration_msecs,
:visible,
- :draft_key
+ :draft_key,
]
Post.plugin_permitted_create_params.each do |key, value|
if value[:plugin].enabled?
- permitted << case value[:type]
- when :string
- key.to_sym
- when :array
- { key => [] }
- when :hash
- { key => {} }
+ permitted << case value[:type]
+ when :string
+ key.to_sym
+ when :array
+ { key => [] }
+ when :hash
+ { key => {} }
end
end
end
@@ -785,11 +835,14 @@ class PostsController < ApplicationController
permitted << :external_id
end
- result = params.permit(*permitted).tap do |allowed|
- allowed[:image_sizes] = params[:image_sizes]
- # TODO this does not feel right, we should name what meta_data is allowed
- allowed[:meta_data] = params[:meta_data]
- end
+ result =
+ params
+ .permit(*permitted)
+ .tap do |allowed|
+ allowed[:image_sizes] = params[:image_sizes]
+ # TODO this does not feel right, we should name what meta_data is allowed
+ allowed[:meta_data] = params[:meta_data]
+ end
# Staff are allowed to pass `is_warning`
if current_user.staff?
@@ -804,14 +857,20 @@ class PostsController < ApplicationController
result[:no_bump] = true
end
- if params[:shared_draft] == 'true'
+ if params[:shared_draft] == "true"
raise Discourse::InvalidParameters.new(:shared_draft) unless guardian.can_create_shared_draft?
result[:shared_draft] = true
end
if params[:whisper] == "true"
- raise Discourse::InvalidAccess.new("invalid_whisper_access", nil, custom_message: "invalid_whisper_access") unless guardian.can_create_whisper?
+ unless guardian.can_create_whisper?
+ raise Discourse::InvalidAccess.new(
+ "invalid_whisper_access",
+ nil,
+ custom_message: "invalid_whisper_access",
+ )
+ end
result[:post_type] = Post.types[:whisper]
end
@@ -827,14 +886,19 @@ class PostsController < ApplicationController
result[:referrer] = request.env["HTTP_REFERER"]
if recipients = result[:target_usernames]
- Discourse.deprecate("`target_usernames` is deprecated, use `target_recipients` instead.", output_in_test: true, drop_from: '2.9.0')
+ Discourse.deprecate(
+ "`target_usernames` is deprecated, use `target_recipients` instead.",
+ output_in_test: true,
+ drop_from: "2.9.0",
+ )
else
recipients = result[:target_recipients]
end
if recipients
recipients = recipients.split(",").map(&:downcase)
- groups = Group.messageable(current_user).where('lower(name) in (?)', recipients).pluck('lower(name)')
+ groups =
+ Group.messageable(current_user).where("lower(name) in (?)", recipients).pluck("lower(name)")
recipients -= groups
emails = recipients.select { |user| user.match(/@/) }
recipients -= emails
@@ -848,13 +912,14 @@ class PostsController < ApplicationController
end
def signature_for(args)
- +"post##" << Digest::SHA1.hexdigest(args
- .to_h
- .to_a
- .concat([["user", current_user.id]])
- .sort { |x, y| x[0] <=> y[0] }.join do |x, y|
- "#{x}:#{y}"
- end)
+ +"post##" << Digest::SHA1.hexdigest(
+ args
+ .to_h
+ .to_a
+ .concat([["user", current_user.id]])
+ .sort { |x, y| x[0] <=> y[0] }
+ .join { |x, y| "#{x}:#{y}" },
+ )
end
def display_post(post)
@@ -873,11 +938,13 @@ class PostsController < ApplicationController
end
def find_post_from_params_by_date
- by_date_finder = TopicView.new(params[:topic_id], current_user)
- .filtered_posts
- .where("created_at >= ?", Time.zone.parse(params[:date]))
- .order("created_at ASC")
- .limit(1)
+ by_date_finder =
+ TopicView
+ .new(params[:topic_id], current_user)
+ .filtered_posts
+ .where("created_at >= ?", Time.zone.parse(params[:date]))
+ .order("created_at ASC")
+ .limit(1)
find_post_using(by_date_finder)
end
@@ -892,15 +959,14 @@ class PostsController < ApplicationController
post.topic = Topic.with_deleted.find_by(id: post.topic_id)
if !post.topic ||
- (
- (post.deleted_at.present? || post.topic.deleted_at.present?) &&
- !guardian.can_moderate_topic?(post.topic)
- )
+ (
+ (post.deleted_at.present? || post.topic.deleted_at.present?) &&
+ !guardian.can_moderate_topic?(post.topic)
+ )
raise Discourse::NotFound
end
guardian.ensure_can_see!(post)
post
end
-
end
diff --git a/app/controllers/presence_controller.rb b/app/controllers/presence_controller.rb
index fe26e68fab1..ad68f801c94 100644
--- a/app/controllers/presence_controller.rb
+++ b/app/controllers/presence_controller.rb
@@ -9,18 +9,23 @@ class PresenceController < ApplicationController
def get
names = params.require(:channels)
- raise Discourse::InvalidParameters.new(:channels) if !(names.is_a?(Array) && names.all? { |n| n.is_a? String })
+ if !(names.is_a?(Array) && names.all? { |n| n.is_a? String })
+ raise Discourse::InvalidParameters.new(:channels)
+ end
names.uniq!
- raise Discourse::InvalidParameters.new("Too many channels") if names.length > MAX_CHANNELS_PER_REQUEST
-
- user_group_ids = if current_user
- GroupUser.where(user_id: current_user.id).pluck("group_id")
- else
- []
+ if names.length > MAX_CHANNELS_PER_REQUEST
+ raise Discourse::InvalidParameters.new("Too many channels")
end
+ user_group_ids =
+ if current_user
+ GroupUser.where(user_id: current_user.id).pluck("group_id")
+ else
+ []
+ end
+
result = {}
names.each do |name|
channel = PresenceChannel.new(name)
@@ -38,19 +43,23 @@ class PresenceController < ApplicationController
def update
client_id = params[:client_id]
- raise Discourse::InvalidParameters.new(:client_id) if !client_id.is_a?(String) || client_id.blank?
+ if !client_id.is_a?(String) || client_id.blank?
+ raise Discourse::InvalidParameters.new(:client_id)
+ end
# JS client is designed to throttle to one request per second
# When no changes are being made, it makes one request every 30 seconds
RateLimiter.new(nil, "update-presence-#{current_user.id}", 20, 10.seconds).performed!
present_channels = params[:present_channels]
- if present_channels && !(present_channels.is_a?(Array) && present_channels.all? { |c| c.is_a? String })
+ if present_channels &&
+ !(present_channels.is_a?(Array) && present_channels.all? { |c| c.is_a? String })
raise Discourse::InvalidParameters.new(:present_channels)
end
leave_channels = params[:leave_channels]
- if leave_channels && !(leave_channels.is_a?(Array) && leave_channels.all? { |c| c.is_a? String })
+ if leave_channels &&
+ !(leave_channels.is_a?(Array) && leave_channels.all? { |c| c.is_a? String })
raise Discourse::InvalidParameters.new(:leave_channels)
end
diff --git a/app/controllers/published_pages_controller.rb b/app/controllers/published_pages_controller.rb
index abf27ccda50..328e2ba408f 100644
--- a/app/controllers/published_pages_controller.rb
+++ b/app/controllers/published_pages_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class PublishedPagesController < ApplicationController
-
skip_before_action :preload_json
skip_before_action :check_xhr, :verify_authenticity_token, only: [:show]
before_action :ensure_publish_enabled
@@ -19,12 +18,14 @@ class PublishedPagesController < ApplicationController
begin
guardian.ensure_can_see!(pp.topic)
rescue Discourse::InvalidAccess => e
- return rescue_discourse_actions(
- :invalid_access,
- 403,
- include_ember: false,
- custom_message: e.custom_message,
- group: e.group
+ return(
+ rescue_discourse_actions(
+ :invalid_access,
+ 403,
+ include_ember: false,
+ custom_message: e.custom_message,
+ group: e.group,
+ )
)
end
end
@@ -37,18 +38,19 @@ class PublishedPagesController < ApplicationController
TopicViewItem.add(pp.topic.id, request.remote_ip, current_user ? current_user.id : nil)
- @body_classes = Set.new([
- 'published-page',
- params[:slug],
- "topic-#{@topic.id}",
- @topic.tags.pluck(:name)
- ].flatten.compact)
+ @body_classes =
+ Set.new(
+ [
+ "published-page",
+ params[:slug],
+ "topic-#{@topic.id}",
+ @topic.tags.pluck(:name),
+ ].flatten.compact,
+ )
- if @topic.category
- @body_classes << @topic.category.slug
- end
+ @body_classes << @topic.category.slug if @topic.category
- render layout: 'publish'
+ render layout: "publish"
end
def details
@@ -60,12 +62,13 @@ class PublishedPagesController < ApplicationController
def upsert
pp_params = params.require(:published_page)
- result, pp = PublishedPage.publish!(
- current_user,
- fetch_topic,
- pp_params[:slug].strip,
- pp_params.permit(:public)
- )
+ result, pp =
+ PublishedPage.publish!(
+ current_user,
+ fetch_topic,
+ pp_params[:slug].strip,
+ pp_params.permit(:public),
+ )
json_result(pp, serializer: PublishedPageSerializer) { result }
end
@@ -85,7 +88,7 @@ class PublishedPagesController < ApplicationController
end
end
-private
+ private
def fetch_topic
topic = Topic.find_by(id: params[:topic_id])
@@ -94,18 +97,13 @@ private
end
def ensure_publish_enabled
- if !SiteSetting.enable_page_publishing? || SiteSetting.secure_uploads
- raise Discourse::NotFound
- end
+ raise Discourse::NotFound if !SiteSetting.enable_page_publishing? || SiteSetting.secure_uploads
end
def enforce_login_required!
- if SiteSetting.login_required? &&
- !current_user &&
- !SiteSetting.show_published_pages_login_required? &&
- redirect_to_login
+ if SiteSetting.login_required? && !current_user &&
+ !SiteSetting.show_published_pages_login_required? && redirect_to_login
true
end
end
-
end
diff --git a/app/controllers/push_notification_controller.rb b/app/controllers/push_notification_controller.rb
index 0b0a75b39d2..a1cd3b07659 100644
--- a/app/controllers/push_notification_controller.rb
+++ b/app/controllers/push_notification_controller.rb
@@ -18,6 +18,6 @@ class PushNotificationController < ApplicationController
private
def push_params
- params.require(:subscription).permit(:endpoint, keys: [:p256dh, :auth])
+ params.require(:subscription).permit(:endpoint, keys: %i[p256dh auth])
end
end
diff --git a/app/controllers/qunit_controller.rb b/app/controllers/qunit_controller.rb
index 4ee3392d507..31c411688d8 100644
--- a/app/controllers/qunit_controller.rb
+++ b/app/controllers/qunit_controller.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
class QunitController < ApplicationController
- skip_before_action *%i{
- check_xhr
- preload_json
- redirect_to_login_if_required
- }
+ skip_before_action *%i[check_xhr preload_json redirect_to_login_if_required]
layout false
def theme
@@ -25,16 +21,20 @@ class QunitController < ApplicationController
end
if param_key && theme.blank?
- return render plain: "Can't find theme with #{param_key} #{get_param(param_key).inspect}", status: :not_found
+ return(
+ render plain: "Can't find theme with #{param_key} #{get_param(param_key).inspect}",
+ status: :not_found
+ )
end
if !param_key
- @suggested_themes = Theme
- .where(
- id: ThemeField.where(target_id: Theme.targets[:tests_js]).distinct.pluck(:theme_id)
- )
- .order(updated_at: :desc)
- .pluck(:id, :name)
+ @suggested_themes =
+ Theme
+ .where(
+ id: ThemeField.where(target_id: Theme.targets[:tests_js]).distinct.pluck(:theme_id),
+ )
+ .order(updated_at: :desc)
+ .pluck(:id, :name)
return
end
diff --git a/app/controllers/reviewable_claimed_topics_controller.rb b/app/controllers/reviewable_claimed_topics_controller.rb
index 2a6033118ba..8d5cc4a25dd 100644
--- a/app/controllers/reviewable_claimed_topics_controller.rb
+++ b/app/controllers/reviewable_claimed_topics_controller.rb
@@ -10,12 +10,10 @@ class ReviewableClaimedTopicsController < ApplicationController
begin
ReviewableClaimedTopic.create!(user_id: current_user.id, topic_id: topic.id)
rescue ActiveRecord::RecordInvalid
- return render_json_error(I18n.t('reviewables.conflict'), status: 409)
+ return render_json_error(I18n.t("reviewables.conflict"), status: 409)
end
- topic.reviewables.find_each do |reviewable|
- reviewable.log_history(:claimed, current_user)
- end
+ topic.reviewables.find_each { |reviewable| reviewable.log_history(:claimed, current_user) }
notify_users(topic, current_user)
render json: success_json
@@ -27,9 +25,7 @@ class ReviewableClaimedTopicsController < ApplicationController
guardian.ensure_can_claim_reviewable_topic!(topic)
ReviewableClaimedTopic.where(topic_id: topic.id).delete_all
- topic.reviewables.find_each do |reviewable|
- reviewable.log_history(:unclaimed, current_user)
- end
+ topic.reviewables.find_each { |reviewable| reviewable.log_history(:unclaimed, current_user) }
notify_users(topic, nil)
render json: success_json
@@ -40,7 +36,8 @@ class ReviewableClaimedTopicsController < ApplicationController
def notify_users(topic, claimed_by)
group_ids = Set.new([Group::AUTO_GROUPS[:staff]])
- if SiteSetting.enable_category_group_moderation? && group_id = topic.category&.reviewable_by_group_id.presence
+ if SiteSetting.enable_category_group_moderation? &&
+ group_id = topic.category&.reviewable_by_group_id.presence
group_ids.add(group_id)
end
diff --git a/app/controllers/reviewables_controller.rb b/app/controllers/reviewables_controller.rb
index 4d3ebf143af..61af8f0e3ec 100644
--- a/app/controllers/reviewables_controller.rb
+++ b/app/controllers/reviewables_controller.rb
@@ -5,7 +5,7 @@ class ReviewablesController < ApplicationController
PER_PAGE = 10
- before_action :version_required, only: [:update, :perform]
+ before_action :version_required, only: %i[update perform]
before_action :ensure_can_see, except: [:destroy]
def index
@@ -15,20 +15,21 @@ class ReviewablesController < ApplicationController
raise Discourse::InvalidParameters.new(:type) unless Reviewable.valid_type?(params[:type])
end
- status = (params[:status] || 'pending').to_sym
+ status = (params[:status] || "pending").to_sym
raise Discourse::InvalidParameters.new(:status) unless allowed_statuses.include?(status)
topic_id = params[:topic_id] ? params[:topic_id].to_i : nil
category_id = params[:category_id] ? params[:category_id].to_i : nil
custom_keys = Reviewable.custom_filters.map(&:first)
- additional_filters = JSON.parse(params.fetch(:additional_filters, {}), symbolize_names: true).slice(*custom_keys)
+ additional_filters =
+ JSON.parse(params.fetch(:additional_filters, {}), symbolize_names: true).slice(*custom_keys)
filters = {
ids: params[:ids],
status: status,
category_id: category_id,
topic_id: topic_id,
- additional_filters: additional_filters.reject { |_, v| v.blank? }
+ additional_filters: additional_filters.reject { |_, v| v.blank? },
}
%i[priority username reviewed_by from_date to_date type sort_order].each do |filter_key|
@@ -36,7 +37,8 @@ class ReviewablesController < ApplicationController
end
total_rows = Reviewable.list_for(current_user, **filters).count
- reviewables = Reviewable.list_for(current_user, **filters.merge(limit: PER_PAGE, offset: offset)).to_a
+ reviewables =
+ Reviewable.list_for(current_user, **filters.merge(limit: PER_PAGE, offset: offset)).to_a
claimed_topics = ReviewableClaimedTopic.claimed_hash(reviewables.map { |r| r.topic_id }.uniq)
@@ -44,23 +46,25 @@ class ReviewablesController < ApplicationController
# is mutated by the serializer and contains the side loaded records which must be merged in the end.
hash = {}
json = {
- reviewables: reviewables.map! do |r|
- result = r.serializer.new(
- r,
- root: nil,
- hash: hash,
- scope: guardian,
- claimed_topics: claimed_topics
- ).as_json
- hash[:bundled_actions].uniq!
- (hash['actions'] || []).uniq!
- result
- end,
- meta: filters.merge(
- total_rows_reviewables: total_rows, types: meta_types, reviewable_types: Reviewable.types,
- reviewable_count: current_user.reviewable_count,
- unseen_reviewable_count: Reviewable.unseen_reviewable_count(current_user)
- )
+ reviewables:
+ reviewables.map! do |r|
+ result =
+ r
+ .serializer
+ .new(r, root: nil, hash: hash, scope: guardian, claimed_topics: claimed_topics)
+ .as_json
+ hash[:bundled_actions].uniq!
+ (hash["actions"] || []).uniq!
+ result
+ end,
+ meta:
+ filters.merge(
+ total_rows_reviewables: total_rows,
+ types: meta_types,
+ reviewable_types: Reviewable.types,
+ reviewable_count: current_user.reviewable_count,
+ unseen_reviewable_count: Reviewable.unseen_reviewable_count(current_user),
+ ),
}
if (offset + PER_PAGE) < total_rows
json[:meta][:load_more_reviewables] = review_path(filters.merge(offset: offset + PER_PAGE))
@@ -72,10 +76,11 @@ class ReviewablesController < ApplicationController
def user_menu_list
json = {
- reviewables: Reviewable.basic_serializers_for_list(
- Reviewable.user_menu_list_for(current_user),
- current_user
- ).as_json
+ reviewables:
+ Reviewable.basic_serializers_for_list(
+ Reviewable.user_menu_list_for(current_user),
+ current_user,
+ ).as_json,
}
render_json_dump(json, rest_serializer: true)
end
@@ -108,17 +113,17 @@ class ReviewablesController < ApplicationController
meta[:unique_users] = users.size
end
- topics = Topic.where(id: topic_ids).order('reviewable_score DESC')
+ topics = Topic.where(id: topic_ids).order("reviewable_score DESC")
render_serialized(
topics,
ReviewableTopicSerializer,
- root: 'reviewable_topics',
+ root: "reviewable_topics",
stats: stats,
claimed_topics: ReviewableClaimedTopic.claimed_hash(topic_ids),
rest_serializer: true,
meta: {
- types: meta_types
- }
+ types: meta_types,
+ },
)
end
@@ -129,7 +134,7 @@ class ReviewablesController < ApplicationController
{ reviewable: reviewable, scores: reviewable.explain_score },
ReviewableExplanationSerializer,
rest_serializer: true,
- root: 'reviewable_explanation'
+ root: "reviewable_explanation",
)
end
@@ -141,10 +146,10 @@ class ReviewablesController < ApplicationController
reviewable.serializer,
rest_serializer: true,
claimed_topics: ReviewableClaimedTopic.claimed_hash([reviewable.topic_id]),
- root: 'reviewable',
+ root: "reviewable",
meta: {
- types: meta_types
- }
+ types: meta_types,
+ },
)
end
@@ -186,7 +191,7 @@ class ReviewablesController < ApplicationController
render_json_error(reviewable.errors)
end
rescue Reviewable::UpdateConflict
- render_json_error(I18n.t('reviewables.conflict'), status: 409)
+ render_json_error(I18n.t("reviewables.conflict"), status: 409)
end
end
@@ -201,23 +206,32 @@ class ReviewablesController < ApplicationController
return render_json_error(error)
end
- args.merge!(reject_reason: params[:reject_reason], send_email: params[:send_email] != "false") if reviewable.type == 'ReviewableUser'
-
- plugin_params = DiscoursePluginRegistry.reviewable_params.select do |reviewable_param|
- reviewable.type == reviewable_param[:type].to_s.classify
+ if reviewable.type == "ReviewableUser"
+ args.merge!(
+ reject_reason: params[:reject_reason],
+ send_email: params[:send_email] != "false",
+ )
end
+
+ plugin_params =
+ DiscoursePluginRegistry.reviewable_params.select do |reviewable_param|
+ reviewable.type == reviewable_param[:type].to_s.classify
+ end
args.merge!(params.slice(*plugin_params.map { |pp| pp[:param] }).permit!)
result = reviewable.perform(current_user, params[:action_id].to_sym, args)
rescue Reviewable::InvalidAction => e
- if reviewable.type == 'ReviewableUser' && !reviewable.pending? && reviewable.target.blank?
- raise Discourse::NotFound.new(e.message, custom_message: "reviewables.already_handled_and_user_not_exist")
+ if reviewable.type == "ReviewableUser" && !reviewable.pending? && reviewable.target.blank?
+ raise Discourse::NotFound.new(
+ e.message,
+ custom_message: "reviewables.already_handled_and_user_not_exist",
+ )
else
# Consider InvalidAction an InvalidAccess
raise Discourse::InvalidAccess.new(e.message)
end
rescue Reviewable::UpdateConflict
- return render_json_error(I18n.t('reviewables.conflict'), status: 409)
+ return render_json_error(I18n.t("reviewables.conflict"), status: 409)
end
if result.success?
@@ -230,7 +244,7 @@ class ReviewablesController < ApplicationController
def settings
raise Discourse::InvalidAccess.new unless current_user.admin?
- post_action_types = PostActionType.where(id: PostActionType.flag_types.values).order('id')
+ post_action_types = PostActionType.where(id: PostActionType.flag_types.values).order("id")
if request.put?
params[:reviewable_priorities].each do |id, priority|
@@ -239,7 +253,7 @@ class ReviewablesController < ApplicationController
# to calculate it a different way.
PostActionType.where(id: id).update_all(
reviewable_priority: priority.to_i,
- score_bonus: priority.to_f
+ score_bonus: priority.to_f,
)
end
end
@@ -249,7 +263,7 @@ class ReviewablesController < ApplicationController
render_serialized(data, ReviewableSettingsSerializer, rest_serializer: true)
end
-protected
+ protected
def claim_error?(reviewable)
return if SiteSetting.reviewable_claiming == "disabled" || reviewable.topic_id.blank?
@@ -257,9 +271,9 @@ protected
claimed_by_id = ReviewableClaimedTopic.where(topic_id: reviewable.topic_id).pluck(:user_id)[0]
if SiteSetting.reviewable_claiming == "required" && claimed_by_id.blank?
- I18n.t('reviewables.must_claim')
+ I18n.t("reviewables.must_claim")
elsif claimed_by_id.present? && claimed_by_id != current_user.id
- I18n.t('reviewables.user_claimed')
+ I18n.t("reviewables.user_claimed")
end
end
@@ -274,18 +288,11 @@ protected
end
def version_required
- if params[:version].blank?
- render_json_error(I18n.t('reviewables.missing_version'), status: 422)
- end
+ render_json_error(I18n.t("reviewables.missing_version"), status: 422) if params[:version].blank?
end
def meta_types
- {
- created_by: 'user',
- target_created_by: 'user',
- reviewed_by: 'user',
- claimed_by: 'user'
- }
+ { created_by: "user", target_created_by: "user", reviewed_by: "user", claimed_by: "user" }
end
def ensure_can_see
diff --git a/app/controllers/robots_txt_controller.rb b/app/controllers/robots_txt_controller.rb
index 706a67be772..d9e4ea2a73c 100644
--- a/app/controllers/robots_txt_controller.rb
+++ b/app/controllers/robots_txt_controller.rb
@@ -7,7 +7,7 @@ class RobotsTxtController < ApplicationController
OVERRIDDEN_HEADER = "# This robots.txt file has been customized at /admin/customize/robots\n"
# NOTE: order is important!
- DISALLOWED_PATHS ||= %w{
+ DISALLOWED_PATHS ||= %w[
/admin/
/auth/
/assets/browser-update*.js
@@ -16,18 +16,9 @@ class RobotsTxtController < ApplicationController
/user-api-key
/*?api_key*
/*?*api_key*
- }
+ ]
- DISALLOWED_WITH_HEADER_PATHS ||= %w{
- /badges
- /u/
- /my
- /search
- /tag/*/l
- /g
- /t/*/*.rss
- /c/*.rss
- }
+ DISALLOWED_WITH_HEADER_PATHS ||= %w[/badges /u/ /my /search /tag/*/l /g /t/*/*.rss /c/*.rss]
def index
if (overridden = SiteSetting.overridden_robots_txt.dup).present?
@@ -37,9 +28,9 @@ class RobotsTxtController < ApplicationController
end
if SiteSetting.allow_index_in_robots_txt?
@robots_info = self.class.fetch_default_robots_info
- render :index, content_type: 'text/plain'
+ render :index, content_type: "text/plain"
else
- render :no_index, content_type: 'text/plain'
+ render :no_index, content_type: "text/plain"
end
end
@@ -56,32 +47,37 @@ class RobotsTxtController < ApplicationController
def self.fetch_default_robots_info
deny_paths_googlebot = DISALLOWED_PATHS.map { |p| Discourse.base_path + p }
- deny_paths = deny_paths_googlebot + DISALLOWED_WITH_HEADER_PATHS.map { |p| Discourse.base_path + p }
- deny_all = [ "#{Discourse.base_path}/" ]
+ deny_paths =
+ deny_paths_googlebot + DISALLOWED_WITH_HEADER_PATHS.map { |p| Discourse.base_path + p }
+ deny_all = ["#{Discourse.base_path}/"]
result = {
- header: "# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file",
- agents: []
+ header:
+ "# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file",
+ agents: [],
}
if SiteSetting.allowed_crawler_user_agents.present?
- SiteSetting.allowed_crawler_user_agents.split('|').each do |agent|
- paths = agent == "Googlebot" ? deny_paths_googlebot : deny_paths
- result[:agents] << { name: agent, disallow: paths }
- end
-
- result[:agents] << { name: '*', disallow: deny_all }
- else
-
- if SiteSetting.blocked_crawler_user_agents.present?
- SiteSetting.blocked_crawler_user_agents.split('|').each do |agent|
- result[:agents] << { name: agent, disallow: deny_all }
+ SiteSetting
+ .allowed_crawler_user_agents
+ .split("|")
+ .each do |agent|
+ paths = agent == "Googlebot" ? deny_paths_googlebot : deny_paths
+ result[:agents] << { name: agent, disallow: paths }
end
+
+ result[:agents] << { name: "*", disallow: deny_all }
+ else
+ if SiteSetting.blocked_crawler_user_agents.present?
+ SiteSetting
+ .blocked_crawler_user_agents
+ .split("|")
+ .each { |agent| result[:agents] << { name: agent, disallow: deny_all } }
end
- result[:agents] << { name: '*', disallow: deny_paths }
+ result[:agents] << { name: "*", disallow: deny_paths }
- result[:agents] << { name: 'Googlebot', disallow: deny_paths_googlebot }
+ result[:agents] << { name: "Googlebot", disallow: deny_paths_googlebot }
end
DiscourseEvent.trigger(:robots_info, result)
diff --git a/app/controllers/safe_mode_controller.rb b/app/controllers/safe_mode_controller.rb
index 3ffe891d173..53cc0cff32b 100644
--- a/app/controllers/safe_mode_controller.rb
+++ b/app/controllers/safe_mode_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class SafeModeController < ApplicationController
- layout 'no_ember'
+ layout "no_ember"
before_action :ensure_safe_mode_enabled
before_action :force_safe_mode_for_route
@@ -39,5 +39,4 @@ class SafeModeController < ApplicationController
request.env[ApplicationController::NO_THEMES] = true
request.env[ApplicationController::NO_PLUGINS] = true
end
-
end
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 95c49bd75df..f626e620f28 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -1,13 +1,12 @@
# frozen_string_literal: true
class SearchController < ApplicationController
-
before_action :cancel_overloaded_search, only: [:query]
skip_before_action :check_xhr, only: :show
after_action :add_noindex_header
def self.valid_context_types
- %w{user topic category private_messages tag}
+ %w[user topic category private_messages tag]
end
def show
@@ -16,12 +15,9 @@ class SearchController < ApplicationController
# a q param has been given but it's not in the correct format
# eg: ?q[foo]=bar
- if params[:q].present? && !@search_term.present?
- raise Discourse::InvalidParameters.new(:q)
- end
+ raise Discourse::InvalidParameters.new(:q) if params[:q].present? && !@search_term.present?
- if @search_term.present? &&
- @search_term.length < SiteSetting.min_search_term_length
+ if @search_term.present? && @search_term.length < SiteSetting.min_search_term_length
raise Discourse::InvalidParameters.new(:q)
end
@@ -31,21 +27,17 @@ class SearchController < ApplicationController
page = permitted_params[:page]
# check for a malformed page parameter
- if page && (!page.is_a?(String) || page.to_i.to_s != page)
- raise Discourse::InvalidParameters
- end
+ raise Discourse::InvalidParameters if page && (!page.is_a?(String) || page.to_i.to_s != page)
rate_limit_errors = rate_limit_search
discourse_expires_in 1.minute
search_args = {
- type_filter: 'topic',
+ type_filter: "topic",
guardian: guardian,
blurb_length: 300,
- page: if page.to_i <= 10
- [page.to_i, 1].max
- end
+ page: ([page.to_i, 1].max if page.to_i <= 10),
}
context, type = lookup_search_context
@@ -59,19 +51,21 @@ class SearchController < ApplicationController
search_args[:user_id] = current_user.id if current_user.present?
if rate_limit_errors
- result = Search::GroupedSearchResults.new(
- type_filter: search_args[:type_filter],
- term: @search_term,
- search_context: context
- )
+ result =
+ Search::GroupedSearchResults.new(
+ type_filter: search_args[:type_filter],
+ term: @search_term,
+ search_context: context,
+ )
result.error = I18n.t("rate_limiter.slow_down")
elsif site_overloaded?
- result = Search::GroupedSearchResults.new(
- type_filter: search_args[:type_filter],
- term: @search_term,
- search_context: context
- )
+ result =
+ Search::GroupedSearchResults.new(
+ type_filter: search_args[:type_filter],
+ term: @search_term,
+ search_context: context,
+ )
result.error = I18n.t("search.extreme_load_error")
else
@@ -83,12 +77,8 @@ class SearchController < ApplicationController
serializer = serialize_data(result, GroupedSearchResultSerializer, result: result)
respond_to do |format|
- format.html do
- store_preloaded("search", MultiJson.dump(serializer))
- end
- format.json do
- render_json_dump(serializer)
- end
+ format.html { store_preloaded("search", MultiJson.dump(serializer)) }
+ format.json { render_json_dump(serializer) }
end
end
@@ -105,8 +95,8 @@ class SearchController < ApplicationController
search_args = { guardian: guardian }
- search_args[:type_filter] = params[:type_filter] if params[:type_filter].present?
- search_args[:search_for_id] = true if params[:search_for_id].present?
+ search_args[:type_filter] = params[:type_filter] if params[:type_filter].present?
+ search_args[:search_for_id] = true if params[:search_for_id].present?
context, type = lookup_search_context
@@ -118,22 +108,26 @@ class SearchController < ApplicationController
search_args[:search_type] = :header
search_args[:ip_address] = request.remote_ip
search_args[:user_id] = current_user.id if current_user.present?
- search_args[:restrict_to_archetype] = params[:restrict_to_archetype] if params[:restrict_to_archetype].present?
+ search_args[:restrict_to_archetype] = params[:restrict_to_archetype] if params[
+ :restrict_to_archetype
+ ].present?
if rate_limit_errors
- result = Search::GroupedSearchResults.new(
- type_filter: search_args[:type_filter],
- term: params[:term],
- search_context: context
- )
+ result =
+ Search::GroupedSearchResults.new(
+ type_filter: search_args[:type_filter],
+ term: params[:term],
+ search_context: context,
+ )
result.error = I18n.t("rate_limiter.slow_down")
elsif site_overloaded?
- result = GroupedSearchResults.new(
- type_filter: search_args[:type_filter],
- term: params[:term],
- search_context: context
- )
+ result =
+ GroupedSearchResults.new(
+ type_filter: search_args[:type_filter],
+ term: params[:term],
+ search_context: context,
+ )
else
search = Search.new(params[:term], search_args)
result = search.execute(readonly_mode: @readonly_mode)
@@ -163,7 +157,7 @@ class SearchController < ApplicationController
SearchLog.where(attributes).update_all(
search_result_type: SearchLog.search_result_types[search_result_type],
- search_result_id: search_result_id
+ search_result_id: search_result_id,
)
end
@@ -173,7 +167,7 @@ class SearchController < ApplicationController
protected
def site_overloaded?
- queue_time = request.env['REQUEST_QUEUE_SECONDS']
+ queue_time = request.env["REQUEST_QUEUE_SECONDS"]
if queue_time
threshold = GlobalSetting.disable_search_queue_threshold.to_f
threshold > 0 && queue_time > threshold
@@ -185,10 +179,25 @@ class SearchController < ApplicationController
def rate_limit_search
begin
if current_user.present?
- RateLimiter.new(current_user, "search-min", SiteSetting.rate_limit_search_user, 1.minute).performed!
+ RateLimiter.new(
+ current_user,
+ "search-min",
+ SiteSetting.rate_limit_search_user,
+ 1.minute,
+ ).performed!
else
- RateLimiter.new(nil, "search-min-#{request.remote_ip}", SiteSetting.rate_limit_search_anon_user, 1.minute).performed!
- RateLimiter.new(nil, "search-min-anon-global", SiteSetting.rate_limit_search_anon_global, 1.minute).performed!
+ RateLimiter.new(
+ nil,
+ "search-min-#{request.remote_ip}",
+ SiteSetting.rate_limit_search_anon_user,
+ 1.minute,
+ ).performed!
+ RateLimiter.new(
+ nil,
+ "search-min-anon-global",
+ SiteSetting.rate_limit_search_anon_global,
+ 1.minute,
+ ).performed!
end
rescue RateLimiter::LimitExceeded => e
return e
@@ -197,13 +206,10 @@ class SearchController < ApplicationController
end
def cancel_overloaded_search
- if site_overloaded?
- render_json_error I18n.t("search.extreme_load_error"), status: 409
- end
+ render_json_error I18n.t("search.extreme_load_error"), status: 409 if site_overloaded?
end
def lookup_search_context
-
return if params[:skip_context] == "true"
search_context = params[:search_context]
@@ -214,30 +220,29 @@ class SearchController < ApplicationController
end
if search_context.present?
- raise Discourse::InvalidParameters.new(:search_context) unless SearchController.valid_context_types.include?(search_context[:type])
+ unless SearchController.valid_context_types.include?(search_context[:type])
+ raise Discourse::InvalidParameters.new(:search_context)
+ end
raise Discourse::InvalidParameters.new(:search_context) if search_context[:id].blank?
# A user is found by username
context_obj = nil
- if ['user', 'private_messages'].include? search_context[:type]
+ if %w[user private_messages].include? search_context[:type]
context_obj = User.find_by(username_lower: search_context[:id].downcase)
- elsif 'category' == search_context[:type]
+ elsif "category" == search_context[:type]
context_obj = Category.find_by(id: search_context[:id].to_i)
- elsif 'topic' == search_context[:type]
+ elsif "topic" == search_context[:type]
context_obj = Topic.find_by(id: search_context[:id].to_i)
- elsif 'tag' == search_context[:type]
+ elsif "tag" == search_context[:type]
context_obj = Tag.where_name(search_context[:name]).first
end
type_filter = nil
- if search_context[:type] == 'private_messages'
- type_filter = 'private_messages'
- end
+ type_filter = "private_messages" if search_context[:type] == "private_messages"
guardian.ensure_can_see!(context_obj)
[context_obj, type_filter]
end
end
-
end
diff --git a/app/controllers/session_controller.rb b/app/controllers/session_controller.rb
index ecc653c88d6..9c8216522ce 100644
--- a/app/controllers/session_controller.rb
+++ b/app/controllers/session_controller.rb
@@ -1,14 +1,16 @@
# frozen_string_literal: true
class SessionController < ApplicationController
- before_action :check_local_login_allowed, only: %i(create forgot_password)
- before_action :rate_limit_login, only: %i(create email_login)
+ before_action :check_local_login_allowed, only: %i[create forgot_password]
+ before_action :rate_limit_login, only: %i[create email_login]
skip_before_action :redirect_to_login_if_required
- skip_before_action :preload_json, :check_xhr, only: %i(sso sso_login sso_provider destroy one_time_password)
+ skip_before_action :preload_json,
+ :check_xhr,
+ only: %i[sso sso_login sso_provider destroy one_time_password]
- skip_before_action :check_xhr, only: %i(second_factor_auth_show)
+ skip_before_action :check_xhr, only: %i[second_factor_auth_show]
- requires_login only: [:second_factor_auth_show, :second_factor_auth_perform]
+ requires_login only: %i[second_factor_auth_show second_factor_auth_perform]
allow_in_staff_writes_only_mode :create
allow_in_staff_writes_only_mode :email_login
@@ -23,10 +25,10 @@ class SessionController < ApplicationController
raise Discourse::NotFound unless SiteSetting.enable_discourse_connect?
destination_url = cookies[:destination_url] || session[:destination_url]
- return_path = params[:return_path] || path('/')
+ return_path = params[:return_path] || path("/")
- if destination_url && return_path == path('/')
- uri = URI::parse(destination_url)
+ if destination_url && return_path == path("/")
+ uri = URI.parse(destination_url)
return_path = "#{uri.path}#{uri.query ? "?#{uri.query}" : ""}"
end
@@ -41,11 +43,12 @@ class SessionController < ApplicationController
def sso_provider(payload = nil, confirmed_2fa_during_login = false)
raise Discourse::NotFound unless SiteSetting.enable_discourse_connect_provider
- result = run_second_factor!(
- SecondFactor::Actions::DiscourseConnectProvider,
- payload: payload,
- confirmed_2fa_during_login: confirmed_2fa_during_login
- )
+ result =
+ run_second_factor!(
+ SecondFactor::Actions::DiscourseConnectProvider,
+ payload: payload,
+ confirmed_2fa_during_login: confirmed_2fa_during_login,
+ )
if result.second_factor_auth_skipped?
data = result.data
@@ -57,7 +60,7 @@ class SessionController < ApplicationController
if data[:no_current_user]
cookies[:sso_payload] = payload || request.query_string
- redirect_to path('/login')
+ redirect_to path("/login")
return
end
@@ -93,12 +96,11 @@ class SessionController < ApplicationController
skip_before_action :check_xhr, only: [:become]
def become
-
raise Discourse::InvalidAccess if Rails.env.production?
raise Discourse::ReadOnly if @readonly_mode
- if ENV['DISCOURSE_DEV_ALLOW_ANON_TO_IMPERSONATE'] != "1"
- render(content_type: 'text/plain', inline: <<~TEXT)
+ if ENV["DISCOURSE_DEV_ALLOW_ANON_TO_IMPERSONATE"] != "1"
+ render(content_type: "text/plain", inline: <<~TEXT)
To enable impersonating any user without typing passwords set the following ENV var
export DISCOURSE_DEV_ALLOW_ANON_TO_IMPERSONATE=1
@@ -132,7 +134,9 @@ class SessionController < ApplicationController
begin
sso = DiscourseConnect.parse(request.query_string, secure_session: secure_session)
rescue DiscourseConnect::ParseError => e
- connect_verbose_warn { "Verbose SSO log: Signature parse error\n\n#{e.message}\n\n#{sso&.diagnostics}" }
+ connect_verbose_warn do
+ "Verbose SSO log: Signature parse error\n\n#{e.message}\n\n#{sso&.diagnostics}"
+ end
# Do NOT pass the error text to the client, it would give them the correct signature
return render_sso_error(text: I18n.t("discourse_connect.login_error"), status: 422)
@@ -144,7 +148,9 @@ class SessionController < ApplicationController
end
if ScreenedIpAddress.should_block?(request.remote_ip)
- connect_verbose_warn { "Verbose SSO log: IP address is blocked #{request.remote_ip}\n\n#{sso.diagnostics}" }
+ connect_verbose_warn do
+ "Verbose SSO log: IP address is blocked #{request.remote_ip}\n\n#{sso.diagnostics}"
+ end
return render_sso_error(text: I18n.t("discourse_connect.unknown_error"), status: 500)
end
@@ -163,9 +169,7 @@ class SessionController < ApplicationController
end
if SiteSetting.must_approve_users? && !user.approved?
- if invite.present? && user.invited_user.blank?
- redeem_invitation(invite, sso, user)
- end
+ redeem_invitation(invite, sso, user) if invite.present? && user.invited_user.blank?
if SiteSetting.discourse_connect_not_approved_url.present?
redirect_to SiteSetting.discourse_connect_not_approved_url, allow_other_host: true
@@ -174,9 +178,9 @@ class SessionController < ApplicationController
end
return
- # we only want to redeem the invite if
- # the user has not already redeemed an invite
- # (covers the same SSO user visiting an invite link)
+ # we only want to redeem the invite if
+ # the user has not already redeemed an invite
+ # (covers the same SSO user visiting an invite link)
elsif invite.present? && user.invited_user.blank?
redeem_invitation(invite, sso, user)
@@ -199,7 +203,7 @@ class SessionController < ApplicationController
end
# If it's not a relative URL check the host
- if return_path !~ /^\/[^\/]/
+ if return_path !~ %r{^/[^/]}
begin
uri = URI(return_path)
if (uri.hostname == Discourse.current_hostname)
@@ -207,7 +211,7 @@ class SessionController < ApplicationController
elsif !SiteSetting.discourse_connect_allows_all_return_paths
return_path = path("/")
end
- rescue
+ rescue StandardError
return_path = path("/")
end
end
@@ -215,16 +219,13 @@ class SessionController < ApplicationController
# this can be done more surgically with a regex
# but it the edge case of never supporting redirects back to
# any url with `/session/sso` in it anywhere is reasonable
- if return_path.include?(path("/session/sso"))
- return_path = path("/")
- end
+ return_path = path("/") if return_path.include?(path("/session/sso"))
redirect_to return_path, allow_other_host: true
else
render_sso_error(text: I18n.t("discourse_connect.not_found"), status: 500)
end
rescue ActiveRecord::RecordInvalid => e
-
connect_verbose_warn { <<~TEXT }
Verbose SSO log: Record was invalid: #{e.record.class.name} #{e.record.id}
#{e.record.errors.to_h}
@@ -243,7 +244,8 @@ class SessionController < ApplicationController
if e.record.email.blank?
text = I18n.t("discourse_connect.no_email")
else
- text = I18n.t("discourse_connect.email_error", email: ERB::Util.html_escape(e.record.email))
+ text =
+ I18n.t("discourse_connect.email_error", email: ERB::Util.html_escape(e.record.email))
end
end
@@ -270,7 +272,9 @@ class SessionController < ApplicationController
end
def login_sso_user(sso, user)
- connect_verbose_warn { "Verbose SSO log: User was logged on #{user.username}\n\n#{sso.diagnostics}" }
+ connect_verbose_warn do
+ "Verbose SSO log: User was logged on #{user.username}\n\n#{sso.diagnostics}"
+ end
log_on_user(user) if user.id != current_user&.id
end
@@ -287,7 +291,6 @@ class SessionController < ApplicationController
rate_limit_second_factor!(user)
if user.present?
-
# If their password is correct
unless user.confirm_password?(params[:password])
invalid_credentials
@@ -313,9 +316,7 @@ class SessionController < ApplicationController
end
second_factor_auth_result = authenticate_second_factor(user)
- if !second_factor_auth_result.ok
- return render(json: @second_factor_failure_payload)
- end
+ return render(json: @second_factor_failure_payload) if !second_factor_auth_result.ok
if user.active && user.email_confirmed?
login(user, second_factor_auth_result)
@@ -332,33 +333,31 @@ class SessionController < ApplicationController
check_local_login_allowed(user: user, check_login_via_email: true)
if matched_token
- response = {
- can_login: true,
- token: token,
- token_email: matched_token.email
- }
+ response = { can_login: true, token: token, token_email: matched_token.email }
matched_user = matched_token.user
if matched_user&.totp_enabled?
response.merge!(
second_factor_required: true,
- backup_codes_enabled: matched_user&.backup_codes_enabled?
+ backup_codes_enabled: matched_user&.backup_codes_enabled?,
)
end
if matched_user&.security_keys_enabled?
Webauthn.stage_challenge(matched_user, secure_session)
response.merge!(
- Webauthn.allowed_credentials(matched_user, secure_session).merge(security_key_required: true)
+ Webauthn.allowed_credentials(matched_user, secure_session).merge(
+ security_key_required: true,
+ ),
)
end
render json: response
else
render json: {
- can_login: false,
- error: I18n.t('email_login.invalid_token', base_url: Discourse.base_url)
- }
+ can_login: false,
+ error: I18n.t("email_login.invalid_token", base_url: Discourse.base_url),
+ }
end
end
@@ -388,7 +387,7 @@ class SessionController < ApplicationController
end
end
- render json: { error: I18n.t('email_login.invalid_token', base_url: Discourse.base_url) }
+ render json: { error: I18n.t("email_login.invalid_token", base_url: Discourse.base_url) }
end
def one_time_password
@@ -406,10 +405,10 @@ class SessionController < ApplicationController
# Display the form
end
else
- @error = I18n.t('user_api_key.invalid_token')
+ @error = I18n.t("user_api_key.invalid_token")
end
- render layout: 'no_ember', locals: { hide_auth_buttons: true }
+ render layout: "no_ember", locals: { hide_auth_buttons: true }
end
def second_factor_auth_show
@@ -431,7 +430,7 @@ class SessionController < ApplicationController
json.merge!(
totp_enabled: user.totp_enabled?,
backup_enabled: user.backup_codes_enabled?,
- allowed_methods: challenge[:allowed_methods]
+ allowed_methods: challenge[:allowed_methods],
)
if user.security_keys_enabled?
Webauthn.stage_challenge(user, secure_session)
@@ -440,9 +439,7 @@ class SessionController < ApplicationController
else
json[:security_keys_enabled] = false
end
- if challenge[:description]
- json[:description] = challenge[:description]
- end
+ json[:description] = challenge[:description] if challenge[:description]
else
json[:error] = I18n.t(error_key)
end
@@ -453,9 +450,7 @@ class SessionController < ApplicationController
raise ApplicationController::RenderEmpty.new
end
- format.json do
- render json: json, status: status_code
- end
+ format.json { render json: json, status: status_code }
end
end
@@ -472,11 +467,12 @@ class SessionController < ApplicationController
end
if error_key
- json = failed_json.merge(
- ok: false,
- error: I18n.t(error_key),
- reason: "challenge_not_found_or_expired"
- )
+ json =
+ failed_json.merge(
+ ok: false,
+ error: I18n.t(error_key),
+ reason: "challenge_not_found_or_expired",
+ )
render json: failed_json.merge(json), status: status_code
return
end
@@ -505,21 +501,23 @@ class SessionController < ApplicationController
challenge[:generated_at] += 1.minute.to_i
secure_session["current_second_factor_auth_challenge"] = challenge.to_json
else
- error_json = second_factor_auth_result
- .to_h
- .deep_symbolize_keys
- .slice(:ok, :error, :reason)
- .merge(failed_json)
+ error_json =
+ second_factor_auth_result
+ .to_h
+ .deep_symbolize_keys
+ .slice(:ok, :error, :reason)
+ .merge(failed_json)
render json: error_json, status: 400
return
end
end
render json: {
- ok: true,
- callback_method: challenge[:callback_method],
- callback_path: challenge[:callback_path],
- redirect_url: challenge[:redirect_url]
- }, status: 200
+ ok: true,
+ callback_method: challenge[:callback_method],
+ callback_path: challenge[:callback_path],
+ redirect_url: challenge[:redirect_url],
+ },
+ status: 200
end
def forgot_password
@@ -532,19 +530,33 @@ class SessionController < ApplicationController
RateLimiter.new(nil, "forgot-password-hr-#{request.remote_ip}", 6, 1.hour).performed!
RateLimiter.new(nil, "forgot-password-min-#{request.remote_ip}", 3, 1.minute).performed!
- user = if SiteSetting.hide_email_address_taken && !current_user&.staff?
- raise Discourse::InvalidParameters.new(:login) if !EmailAddressValidator.valid_value?(normalized_login_param)
- User.real.where(staged: false).find_by_email(Email.downcase(normalized_login_param))
- else
- User.real.where(staged: false).find_by_username_or_email(normalized_login_param)
- end
+ user =
+ if SiteSetting.hide_email_address_taken && !current_user&.staff?
+ if !EmailAddressValidator.valid_value?(normalized_login_param)
+ raise Discourse::InvalidParameters.new(:login)
+ end
+ User.real.where(staged: false).find_by_email(Email.downcase(normalized_login_param))
+ else
+ User.real.where(staged: false).find_by_username_or_email(normalized_login_param)
+ end
if user
RateLimiter.new(nil, "forgot-password-login-day-#{user.username}", 6, 1.day).performed!
- email_token = user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:password_reset])
- Jobs.enqueue(:critical_user_email, type: "forgot_password", user_id: user.id, email_token: email_token.token)
+ email_token =
+ user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:password_reset])
+ Jobs.enqueue(
+ :critical_user_email,
+ type: "forgot_password",
+ user_id: user.id,
+ email_token: email_token.token,
+ )
else
- RateLimiter.new(nil, "forgot-password-login-hour-#{normalized_login_param}", 5, 1.hour).performed!
+ RateLimiter.new(
+ nil,
+ "forgot-password-login-hour-#{normalized_login_param}",
+ 5,
+ 1.hour,
+ ).performed!
end
json = success_json
@@ -566,7 +578,8 @@ class SessionController < ApplicationController
redirect_url = params[:return_url].presence || SiteSetting.logout_redirect.presence
sso = SiteSetting.enable_discourse_connect
- only_one_authenticator = !SiteSetting.enable_local_logins && Discourse.enabled_authenticators.length == 1
+ only_one_authenticator =
+ !SiteSetting.enable_local_logins && Discourse.enabled_authenticators.length == 1
if SiteSetting.login_required && (sso || only_one_authenticator)
# In this situation visiting most URLs will start the auth process again
# Go to the `/login` page to avoid an immediate redirect
@@ -575,16 +588,19 @@ class SessionController < ApplicationController
redirect_url ||= path("/")
- event_data = { redirect_url: redirect_url, user: current_user, client_ip: request&.ip, user_agent: request&.user_agent }
+ event_data = {
+ redirect_url: redirect_url,
+ user: current_user,
+ client_ip: request&.ip,
+ user_agent: request&.user_agent,
+ }
DiscourseEvent.trigger(:before_session_destroy, event_data)
redirect_url = event_data[:redirect_url]
reset_session
log_off_user
if request.xhr?
- render json: {
- redirect_url: redirect_url
- }
+ render json: { redirect_url: redirect_url }
else
redirect_to redirect_url, allow_other_host: true
end
@@ -595,17 +611,17 @@ class SessionController < ApplicationController
secure_session.set(CHALLENGE_KEY, challenge_value, expires: 1.hour)
render json: {
- value: honeypot_value,
- challenge: challenge_value,
- expires_in: SecureSession.expiry
- }
+ value: honeypot_value,
+ challenge: challenge_value,
+ expires_in: SecureSession.expiry,
+ }
end
def scopes
if is_api?
key = request.env[Auth::DefaultCurrentUserProvider::HEADER_API_KEY]
api_key = ApiKey.active.with_key(key).first
- render_serialized(api_key.api_key_scopes, ApiKeyScopeSerializer, root: 'scopes')
+ render_serialized(api_key.api_key_scopes, ApiKeyScopeSerializer, root: "scopes")
else
render body: nil, status: 404
end
@@ -628,8 +644,7 @@ class SessionController < ApplicationController
return if user&.admin?
if (check_login_via_email && !SiteSetting.enable_local_logins_via_email) ||
- SiteSetting.enable_discourse_connect ||
- !SiteSetting.enable_local_logins
+ SiteSetting.enable_discourse_connect || !SiteSetting.enable_local_logins
raise Discourse::InvalidAccess, "SSO takes over local login or the local login is disallowed."
end
end
@@ -637,9 +652,7 @@ class SessionController < ApplicationController
private
def connect_verbose_warn(&blk)
- if SiteSetting.verbose_discourse_connect_logging
- Rails.logger.warn(blk.call)
- end
+ Rails.logger.warn(blk.call) if SiteSetting.verbose_discourse_connect_logging
end
def authenticate_second_factor(user)
@@ -660,9 +673,7 @@ class SessionController < ApplicationController
def login_error_check(user)
return failed_to_login(user) if user.suspended?
- if ScreenedIpAddress.should_block?(request.remote_ip)
- return not_allowed_from_ip_address(user)
- end
+ return not_allowed_from_ip_address(user) if ScreenedIpAddress.should_block?(request.remote_ip)
if ScreenedIpAddress.block_admin_login?(user, request.remote_ip)
admin_not_allowed_from_ip_address(user)
@@ -684,11 +695,11 @@ class SessionController < ApplicationController
def not_activated(user)
session[ACTIVATE_USER_KEY] = user.id
render json: {
- error: I18n.t("login.not_activated"),
- reason: 'not_activated',
- sent_to_email: user.find_email || user.email,
- current_email: user.email
- }
+ error: I18n.t("login.not_activated"),
+ reason: "not_activated",
+ sent_to_email: user.find_email || user.email,
+ current_email: user.email,
+ }
end
def not_allowed_from_ip_address(user)
@@ -700,10 +711,7 @@ class SessionController < ApplicationController
end
def failed_to_login(user)
- {
- error: user.suspended_message,
- reason: 'suspended'
- }
+ { error: user.suspended_message, reason: "suspended" }
end
def login(user, second_factor_auth_result)
@@ -712,11 +720,11 @@ class SessionController < ApplicationController
log_on_user(user)
if payload = cookies.delete(:sso_payload)
- confirmed_2fa_during_login = (
- second_factor_auth_result&.ok &&
- second_factor_auth_result.used_2fa_method.present? &&
- second_factor_auth_result.used_2fa_method != UserSecondFactor.methods[:backup_codes]
- )
+ confirmed_2fa_during_login =
+ (
+ second_factor_auth_result&.ok && second_factor_auth_result.used_2fa_method.present? &&
+ second_factor_auth_result.used_2fa_method != UserSecondFactor.methods[:backup_codes]
+ )
sso_provider(payload, confirmed_2fa_during_login)
else
render_serialized(user, UserSerializer)
@@ -728,20 +736,20 @@ class SessionController < ApplicationController
nil,
"login-hr-#{request.remote_ip}",
SiteSetting.max_logins_per_ip_per_hour,
- 1.hour
+ 1.hour,
).performed!
RateLimiter.new(
nil,
"login-min-#{request.remote_ip}",
SiteSetting.max_logins_per_ip_per_minute,
- 1.minute
+ 1.minute,
).performed!
end
def render_sso_error(status:, text:)
@sso_error = text
- render status: status, layout: 'no_ember'
+ render status: status, layout: "no_ember"
end
# extension to allow plugins to customize the SSO URL
@@ -769,9 +777,15 @@ class SessionController < ApplicationController
raise Invite::ValidationFailed.new(I18n.t("invite.not_matching_email"))
end
elsif invite.expired?
- raise Invite::ValidationFailed.new(I18n.t('invite.expired', base_url: Discourse.base_url))
+ raise Invite::ValidationFailed.new(I18n.t("invite.expired", base_url: Discourse.base_url))
elsif invite.redeemed?
- raise Invite::ValidationFailed.new(I18n.t('invite.not_found_template', site_name: SiteSetting.title, base_url: Discourse.base_url))
+ raise Invite::ValidationFailed.new(
+ I18n.t(
+ "invite.not_found_template",
+ site_name: SiteSetting.title,
+ base_url: Discourse.base_url,
+ ),
+ )
end
invite
@@ -785,11 +799,11 @@ class SessionController < ApplicationController
ip_address: request.remote_ip,
session: session,
email: sso.email,
- redeeming_user: redeeming_user
+ redeeming_user: redeeming_user,
).redeem
secure_session["invite-key"] = nil
- # note - more specific errors are handled in the sso_login method
+ # note - more specific errors are handled in the sso_login method
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved => e
Rails.logger.warn("SSO invite redemption failed: #{e}")
raise Invite::RedemptionFailed
diff --git a/app/controllers/similar_topics_controller.rb b/app/controllers/similar_topics_controller.rb
index e2f33146576..05a87e14196 100644
--- a/app/controllers/similar_topics_controller.rb
+++ b/app/controllers/similar_topics_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class SimilarTopicsController < ApplicationController
-
class SimilarTopic
def initialize(topic)
@topic = topic
@@ -26,5 +25,4 @@ class SimilarTopicsController < ApplicationController
topics.map! { |t| SimilarTopic.new(t) }
render_serialized(topics, SimilarTopicSerializer, root: :similar_topics, rest_serializer: true)
end
-
end
diff --git a/app/controllers/site_controller.rb b/app/controllers/site_controller.rb
index 734036cd69e..a8cc7ea2130 100644
--- a/app/controllers/site_controller.rb
+++ b/app/controllers/site_controller.rb
@@ -3,7 +3,7 @@
class SiteController < ApplicationController
layout false
skip_before_action :preload_json, :check_xhr
- skip_before_action :redirect_to_login_if_required, only: ['basic_info', 'statistics']
+ skip_before_action :redirect_to_login_if_required, only: %w[basic_info statistics]
def site
render json: Site.json_for(guardian)
@@ -33,9 +33,9 @@ class SiteController < ApplicationController
favicon_url: UrlHelper.absolute(SiteSetting.site_favicon_url),
title: SiteSetting.title,
description: SiteSetting.site_description,
- header_primary_color: ColorScheme.hex_for_name('header_primary') || '333333',
- header_background_color: ColorScheme.hex_for_name('header_background') || 'ffffff',
- login_required: SiteSetting.login_required
+ header_primary_color: ColorScheme.hex_for_name("header_primary") || "333333",
+ header_background_color: ColorScheme.hex_for_name("header_background") || "ffffff",
+ login_required: SiteSetting.login_required,
}
if mobile_logo_url = SiteSetting.site_mobile_logo_url.presence
@@ -49,7 +49,7 @@ class SiteController < ApplicationController
end
def statistics
- return redirect_to path('/') unless SiteSetting.share_anonymized_statistics?
+ return redirect_to path("/") unless SiteSetting.share_anonymized_statistics?
render json: About.fetch_cached_stats
end
end
diff --git a/app/controllers/sitemap_controller.rb b/app/controllers/sitemap_controller.rb
index 3ae7efcde04..30fed7190f2 100644
--- a/app/controllers/sitemap_controller.rb
+++ b/app/controllers/sitemap_controller.rb
@@ -6,9 +6,7 @@ class SitemapController < ApplicationController
before_action :check_sitemap_enabled
def index
- @sitemaps = Sitemap
- .where(enabled: true)
- .where.not(name: Sitemap::NEWS_SITEMAP_NAME)
+ @sitemaps = Sitemap.where(enabled: true).where.not(name: Sitemap::NEWS_SITEMAP_NAME)
render :index
end
@@ -18,37 +16,46 @@ class SitemapController < ApplicationController
sitemap = Sitemap.find_by(enabled: true, name: index.to_s)
raise Discourse::NotFound if sitemap.nil?
- @output = Rails.cache.fetch("sitemap/#{sitemap.name}/#{sitemap.max_page_size}", expires_in: 24.hours) do
- @topics = sitemap.topics
- render :page, content_type: 'text/xml; charset=UTF-8'
- end
+ @output =
+ Rails
+ .cache
+ .fetch("sitemap/#{sitemap.name}/#{sitemap.max_page_size}", expires_in: 24.hours) do
+ @topics = sitemap.topics
+ render :page, content_type: "text/xml; charset=UTF-8"
+ end
- render plain: @output, content_type: 'text/xml; charset=UTF-8' unless performed?
+ render plain: @output, content_type: "text/xml; charset=UTF-8" unless performed?
end
def recent
sitemap = Sitemap.touch(Sitemap::RECENT_SITEMAP_NAME)
- @output = Rails.cache.fetch("sitemap/recent/#{sitemap.last_posted_at.to_i}", expires_in: 1.hour) do
- @topics = sitemap.topics
- render :page, content_type: 'text/xml; charset=UTF-8'
- end
+ @output =
+ Rails
+ .cache
+ .fetch("sitemap/recent/#{sitemap.last_posted_at.to_i}", expires_in: 1.hour) do
+ @topics = sitemap.topics
+ render :page, content_type: "text/xml; charset=UTF-8"
+ end
- render plain: @output, content_type: 'text/xml; charset=UTF-8' unless performed?
+ render plain: @output, content_type: "text/xml; charset=UTF-8" unless performed?
end
def news
sitemap = Sitemap.touch(Sitemap::NEWS_SITEMAP_NAME)
- @output = Rails.cache.fetch("sitemap/news", expires_in: 5.minutes) do
- dlocale = SiteSetting.default_locale.downcase
- @locale = dlocale.gsub(/_.*/, '')
- @locale = dlocale.sub('_', '-') if @locale === "zh"
- @topics = sitemap.topics
- render :news, content_type: 'text/xml; charset=UTF-8'
- end
+ @output =
+ Rails
+ .cache
+ .fetch("sitemap/news", expires_in: 5.minutes) do
+ dlocale = SiteSetting.default_locale.downcase
+ @locale = dlocale.gsub(/_.*/, "")
+ @locale = dlocale.sub("_", "-") if @locale === "zh"
+ @topics = sitemap.topics
+ render :news, content_type: "text/xml; charset=UTF-8"
+ end
- render plain: @output, content_type: 'text/xml; charset=UTF-8' unless performed?
+ render plain: @output, content_type: "text/xml; charset=UTF-8" unless performed?
end
private
@@ -58,7 +65,7 @@ class SitemapController < ApplicationController
end
def build_sitemap_topic_url(slug, id, posts_count = nil)
- base_url = [Discourse.base_url, 't', slug, id].join('/')
+ base_url = [Discourse.base_url, "t", slug, id].join("/")
return base_url if posts_count.nil?
page, mod = posts_count.divmod(TopicView.chunk_size)
@@ -67,5 +74,4 @@ class SitemapController < ApplicationController
page > 1 ? "#{base_url}?page=#{page}" : base_url
end
helper_method :build_sitemap_topic_url
-
end
diff --git a/app/controllers/static_controller.rb b/app/controllers/static_controller.rb
index b0eaaa2f566..fde841a46e8 100644
--- a/app/controllers/static_controller.rb
+++ b/app/controllers/static_controller.rb
@@ -2,26 +2,41 @@
class StaticController < ApplicationController
skip_before_action :check_xhr, :redirect_to_login_if_required
- skip_before_action :verify_authenticity_token, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
- skip_before_action :preload_json, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
- skip_before_action :handle_theme, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
+ skip_before_action :verify_authenticity_token,
+ only: %i[brotli_asset cdn_asset enter favicon service_worker_asset]
+ skip_before_action :preload_json,
+ only: %i[brotli_asset cdn_asset enter favicon service_worker_asset]
+ skip_before_action :handle_theme,
+ only: %i[brotli_asset cdn_asset enter favicon service_worker_asset]
- before_action :apply_cdn_headers, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
+ before_action :apply_cdn_headers,
+ only: %i[brotli_asset cdn_asset enter favicon service_worker_asset]
- PAGES_WITH_EMAIL_PARAM = ['login', 'password_reset', 'signup']
- MODAL_PAGES = ['password_reset', 'signup']
+ PAGES_WITH_EMAIL_PARAM = %w[login password_reset signup]
+ MODAL_PAGES = %w[password_reset signup]
DEFAULT_PAGES = {
- "faq" => { redirect: "faq_url", topic_id: "guidelines_topic_id" },
- "tos" => { redirect: "tos_url", topic_id: "tos_topic_id" },
- "privacy" => { redirect: "privacy_policy_url", topic_id: "privacy_topic_id" },
+ "faq" => {
+ redirect: "faq_url",
+ topic_id: "guidelines_topic_id",
+ },
+ "tos" => {
+ redirect: "tos_url",
+ topic_id: "tos_topic_id",
+ },
+ "privacy" => {
+ redirect: "privacy_policy_url",
+ topic_id: "privacy_topic_id",
+ },
}
CUSTOM_PAGES = {} # Add via `#add_topic_static_page` in plugin API
def show
- return redirect_to(path '/') if current_user && (params[:id] == 'login' || params[:id] == 'signup')
+ if current_user && (params[:id] == "login" || params[:id] == "signup")
+ return redirect_to(path "/")
+ end
- if SiteSetting.login_required? && current_user.nil? && ['faq', 'guidelines'].include?(params[:id])
- return redirect_to path('/login')
+ if SiteSetting.login_required? && current_user.nil? && %w[faq guidelines].include?(params[:id])
+ return redirect_to path("/login")
end
map = DEFAULT_PAGES.deep_merge(CUSTOM_PAGES)
@@ -34,10 +49,10 @@ class StaticController < ApplicationController
end
# The /guidelines route ALWAYS shows our FAQ, ignoring the faq_url site setting.
- @page = 'faq' if @page == 'guidelines'
+ @page = "faq" if @page == "guidelines"
# Don't allow paths like ".." or "/" or anything hacky like that
- @page = @page.gsub(/[^a-z0-9\_\-]/, '')
+ @page = @page.gsub(/[^a-z0-9\_\-]/, "")
if map.has_key?(@page)
topic_id = map[@page][:topic_id]
@@ -46,11 +61,12 @@ class StaticController < ApplicationController
@topic = Topic.find_by_id(SiteSetting.get(topic_id))
raise Discourse::NotFound unless @topic
- title_prefix = if I18n.exists?("js.#{@page}")
- I18n.t("js.#{@page}")
- else
- @topic.title
- end
+ title_prefix =
+ if I18n.exists?("js.#{@page}")
+ I18n.t("js.#{@page}")
+ else
+ @topic.title
+ end
@title = "#{title_prefix} - #{SiteSetting.title}"
@body = @topic.posts.first.cooked
@faq_overridden = !SiteSetting.faq_url.blank?
@@ -104,10 +120,7 @@ class StaticController < ApplicationController
forum_uri = URI(Discourse.base_url)
uri = URI(redirect_location)
- if uri.path.present? &&
- (uri.host.blank? || uri.host == forum_uri.host) &&
- uri.path !~ /\./
-
+ if uri.path.present? && (uri.host.blank? || uri.host == forum_uri.host) && uri.path !~ /\./
destination = "#{uri.path}#{uri.query ? "?#{uri.query}" : ""}"
end
rescue URI::Error
@@ -135,31 +148,33 @@ class StaticController < ApplicationController
is_asset_path
hijack do
- data = DistributedMemoizer.memoize("FAVICON#{SiteIconManager.favicon_url}", 60 * 30) do
- favicon = SiteIconManager.favicon
- next "" unless favicon
+ data =
+ DistributedMemoizer.memoize("FAVICON#{SiteIconManager.favicon_url}", 60 * 30) do
+ favicon = SiteIconManager.favicon
+ next "" unless favicon
- if Discourse.store.external?
- begin
- file = FileHelper.download(
- Discourse.store.cdn_url(favicon.url),
- max_file_size: favicon.filesize,
- tmp_file_name: FAVICON,
- follow_redirect: true
- )
+ if Discourse.store.external?
+ begin
+ file =
+ FileHelper.download(
+ Discourse.store.cdn_url(favicon.url),
+ max_file_size: favicon.filesize,
+ tmp_file_name: FAVICON,
+ follow_redirect: true,
+ )
- file&.read || ""
- rescue => e
- AdminDashboardData.add_problem_message('dashboard.bad_favicon_url', 1800)
- Rails.logger.debug("Failed to fetch favicon #{favicon.url}: #{e}\n#{e.backtrace}")
- ""
- ensure
- file&.unlink
+ file&.read || ""
+ rescue => e
+ AdminDashboardData.add_problem_message("dashboard.bad_favicon_url", 1800)
+ Rails.logger.debug("Failed to fetch favicon #{favicon.url}: #{e}\n#{e.backtrace}")
+ ""
+ ensure
+ file&.unlink
+ end
+ else
+ File.read(Rails.root.join("public", favicon.url[1..-1]))
end
- else
- File.read(Rails.root.join("public", favicon.url[1..-1]))
end
- end
if data.bytesize == 0
@@default_favicon ||= File.read(Rails.root + "public/images/default-favicon.png")
@@ -178,9 +193,7 @@ class StaticController < ApplicationController
def brotli_asset
is_asset_path
- serve_asset(".br") do
- response.headers["Content-Encoding"] = 'br'
- end
+ serve_asset(".br") { response.headers["Content-Encoding"] = "br" }
end
def cdn_asset
@@ -199,20 +212,22 @@ class StaticController < ApplicationController
# However, ensure that these may be cached and served for longer on servers.
immutable_for 1.year
- if Rails.application.assets_manifest.assets['service-worker.js']
- path = File.expand_path(Rails.root + "public/assets/#{Rails.application.assets_manifest.assets['service-worker.js']}")
+ if Rails.application.assets_manifest.assets["service-worker.js"]
+ path =
+ File.expand_path(
+ Rails.root +
+ "public/assets/#{Rails.application.assets_manifest.assets["service-worker.js"]}",
+ )
response.headers["Last-Modified"] = File.ctime(path).httpdate
end
- content = Rails.application.assets_manifest.find_sources('service-worker.js').first
+ content = Rails.application.assets_manifest.find_sources("service-worker.js").first
- base_url = File.dirname(helpers.script_asset_path('service-worker'))
- content = content.sub(
- /^\/\/# sourceMappingURL=(service-worker-.+\.map)$/
- ) { "//# sourceMappingURL=#{base_url}/#{Regexp.last_match(1)}" }
- render(
- plain: content,
- content_type: 'application/javascript'
- )
+ base_url = File.dirname(helpers.script_asset_path("service-worker"))
+ content =
+ content.sub(%r{^//# sourceMappingURL=(service-worker-.+\.map)$}) do
+ "//# sourceMappingURL=#{base_url}/#{Regexp.last_match(1)}"
+ end
+ render(plain: content, content_type: "application/javascript")
end
end
end
@@ -220,7 +235,6 @@ class StaticController < ApplicationController
protected
def serve_asset(suffix = nil)
-
path = File.expand_path(Rails.root + "public/assets/#{params[:path]}#{suffix}")
# SECURITY what if path has /../
@@ -254,12 +268,10 @@ class StaticController < ApplicationController
immutable_for 1.year
# disable NGINX mucking with transfer
- request.env['sendfile.type'] = ''
+ request.env["sendfile.type"] = ""
opts = { disposition: nil }
opts[:type] = "application/javascript" if params[:path] =~ /\.js$/
send_file(path, opts)
-
end
-
end
diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb
index 1f17ae6af99..153a2cccfd3 100644
--- a/app/controllers/steps_controller.rb
+++ b/app/controllers/steps_controller.rb
@@ -12,7 +12,7 @@ class StepsController < ApplicationController
updater.update
if updater.success?
- result = { success: 'OK' }
+ result = { success: "OK" }
result[:refresh_required] = true if updater.refresh_required?
render json: result
else
@@ -23,5 +23,4 @@ class StepsController < ApplicationController
render json: { errors: errors }, status: 422
end
end
-
end
diff --git a/app/controllers/stylesheets_controller.rb b/app/controllers/stylesheets_controller.rb
index ee78f307650..97edb80b576 100644
--- a/app/controllers/stylesheets_controller.rb
+++ b/app/controllers/stylesheets_controller.rb
@@ -1,9 +1,13 @@
# frozen_string_literal: true
class StylesheetsController < ApplicationController
- skip_before_action :preload_json, :redirect_to_login_if_required, :check_xhr, :verify_authenticity_token, only: [:show, :show_source_map, :color_scheme]
+ skip_before_action :preload_json,
+ :redirect_to_login_if_required,
+ :check_xhr,
+ :verify_authenticity_token,
+ only: %i[show show_source_map color_scheme]
- before_action :apply_cdn_headers, only: [:show, :show_source_map, :color_scheme]
+ before_action :apply_cdn_headers, only: %i[show show_source_map color_scheme]
def show_source_map
show_resource(source_map: true)
@@ -20,14 +24,13 @@ class StylesheetsController < ApplicationController
params.permit("theme_id")
manager = Stylesheet::Manager.new(theme_id: params[:theme_id])
- stylesheet = manager.color_scheme_stylesheet_details(params[:id], 'all')
+ stylesheet = manager.color_scheme_stylesheet_details(params[:id], "all")
render json: stylesheet
end
protected
def show_resource(source_map: false)
-
extension = source_map ? ".css.map" : ".css"
no_cookies
@@ -47,7 +50,7 @@ class StylesheetsController < ApplicationController
if digest
query = query.where(digest: digest)
else
- query = query.order('id desc')
+ query = query.order("id desc")
end
# Security note, safe due to route constraint
@@ -58,9 +61,7 @@ class StylesheetsController < ApplicationController
stylesheet_time = query.pluck_first(:created_at)
- if !stylesheet_time
- handle_missing_cache(location, target, digest)
- end
+ handle_missing_cache(location, target, digest) if !stylesheet_time
if cache_time && stylesheet_time && stylesheet_time <= cache_time
return render body: nil, status: 304
@@ -76,10 +77,10 @@ class StylesheetsController < ApplicationController
end
if Rails.env == "development"
- response.headers['Last-Modified'] = Time.zone.now.httpdate
+ response.headers["Last-Modified"] = Time.zone.now.httpdate
immutable_for(1.second)
else
- response.headers['Last-Modified'] = stylesheet_time.httpdate if stylesheet_time
+ response.headers["Last-Modified"] = stylesheet_time.httpdate if stylesheet_time
immutable_for(1.year)
end
send_file(location, disposition: :inline)
@@ -104,5 +105,4 @@ class StylesheetsController < ApplicationController
rescue Errno::ENOENT
end
end
-
end
diff --git a/app/controllers/svg_sprite_controller.rb b/app/controllers/svg_sprite_controller.rb
index 5366654d9df..f073314e200 100644
--- a/app/controllers/svg_sprite_controller.rb
+++ b/app/controllers/svg_sprite_controller.rb
@@ -1,14 +1,17 @@
# frozen_string_literal: true
class SvgSpriteController < ApplicationController
- skip_before_action :preload_json, :redirect_to_login_if_required, :check_xhr, :verify_authenticity_token, only: [:show, :search, :svg_icon]
+ skip_before_action :preload_json,
+ :redirect_to_login_if_required,
+ :check_xhr,
+ :verify_authenticity_token,
+ only: %i[show search svg_icon]
- before_action :apply_cdn_headers, only: [:show, :search, :svg_icon]
+ before_action :apply_cdn_headers, only: %i[show search svg_icon]
- requires_login except: [:show, :svg_icon]
+ requires_login except: %i[show svg_icon]
def show
-
no_cookies
RailsMultisite::ConnectionManagement.with_hostname(params[:hostname]) do
@@ -24,20 +27,19 @@ class SvgSpriteController < ApplicationController
response.headers["Content-Length"] = svg_sprite.bytesize.to_s
immutable_for 1.year
- render plain: svg_sprite, disposition: nil, content_type: 'application/javascript'
+ render plain: svg_sprite, disposition: nil, content_type: "application/javascript"
end
end
def search
RailsMultisite::ConnectionManagement.with_hostname(params[:hostname]) do
-
keyword = params.require(:keyword)
data = SvgSprite.search(keyword)
if data.blank?
render body: nil, status: 404
else
- render plain: data.inspect, disposition: nil, content_type: 'text/plain'
+ render plain: data.inspect, disposition: nil, content_type: "text/plain"
end
end
end
@@ -65,14 +67,14 @@ class SvgSpriteController < ApplicationController
else
doc = Nokogiri.XML(icon)
doc.at_xpath("symbol").name = "svg"
- doc.at_xpath("svg")['xmlns'] = "http://www.w3.org/2000/svg"
- doc.at_xpath("svg")['fill'] = adjust_hex(params[:color]) if params[:color]
+ doc.at_xpath("svg")["xmlns"] = "http://www.w3.org/2000/svg"
+ doc.at_xpath("svg")["fill"] = adjust_hex(params[:color]) if params[:color]
response.headers["Last-Modified"] = 1.years.ago.httpdate
response.headers["Content-Length"] = doc.to_s.bytesize.to_s
immutable_for 1.day
- render plain: doc, disposition: nil, content_type: 'image/svg+xml'
+ render plain: doc, disposition: nil, content_type: "image/svg+xml"
end
end
end
diff --git a/app/controllers/tag_groups_controller.rb b/app/controllers/tag_groups_controller.rb
index 9921d7af6dd..fd6dae701d3 100644
--- a/app/controllers/tag_groups_controller.rb
+++ b/app/controllers/tag_groups_controller.rb
@@ -4,12 +4,17 @@ class TagGroupsController < ApplicationController
requires_login except: [:search]
before_action :ensure_staff, except: [:search]
- skip_before_action :check_xhr, only: [:index, :show, :new]
- before_action :fetch_tag_group, only: [:show, :update, :destroy]
+ skip_before_action :check_xhr, only: %i[index show new]
+ before_action :fetch_tag_group, only: %i[show update destroy]
def index
- tag_groups = TagGroup.order('name ASC').includes(:parent_tag).preload(:tags).all
- serializer = ActiveModel::ArraySerializer.new(tag_groups, each_serializer: TagGroupSerializer, root: 'tag_groups')
+ tag_groups = TagGroup.order("name ASC").includes(:parent_tag).preload(:tags).all
+ serializer =
+ ActiveModel::ArraySerializer.new(
+ tag_groups,
+ each_serializer: TagGroupSerializer,
+ root: "tag_groups",
+ )
respond_to do |format|
format.html do
store_preloaded "tagGroups", MultiJson.dump(serializer)
@@ -31,8 +36,13 @@ class TagGroupsController < ApplicationController
end
def new
- tag_groups = TagGroup.order('name ASC').includes(:parent_tag).preload(:tags).all
- serializer = ActiveModel::ArraySerializer.new(tag_groups, each_serializer: TagGroupSerializer, root: 'tag_groups')
+ tag_groups = TagGroup.order("name ASC").includes(:parent_tag).preload(:tags).all
+ serializer =
+ ActiveModel::ArraySerializer.new(
+ tag_groups,
+ each_serializer: TagGroupSerializer,
+ root: "tag_groups",
+ )
store_preloaded "tagGroup", MultiJson.dump(serializer)
render "default/empty"
end
@@ -63,19 +73,18 @@ class TagGroupsController < ApplicationController
def search
matches = TagGroup.includes(:tags).visible(guardian).all
- if params[:q].present?
- matches = matches.where('lower(name) ILIKE ?', "%#{params[:q].strip}%")
- end
+ matches = matches.where("lower(name) ILIKE ?", "%#{params[:q].strip}%") if params[:q].present?
if params[:names].present?
- matches = matches.where('lower(NAME) in (?)', params[:names].map(&:downcase))
+ matches = matches.where("lower(NAME) in (?)", params[:names].map(&:downcase))
end
- matches = matches.order('name').limit(params[:limit] || 5)
+ matches = matches.order("name").limit(params[:limit] || 5)
render json: {
- results: matches.map { |x| { name: x.name, tag_names: x.tags.base_tags.pluck(:name).sort } }
- }
+ results:
+ matches.map { |x| { name: x.name, tag_names: x.tags.base_tags.pluck(:name).sort } },
+ }
end
private
@@ -88,14 +97,8 @@ class TagGroupsController < ApplicationController
tag_group = params.delete(:tag_group)
params.merge!(tag_group.permit!) if tag_group
- result = params.permit(
- :id,
- :name,
- :one_per_topic,
- tag_names: [],
- parent_tag_name: [],
- permissions: {}
- )
+ result =
+ params.permit(:id, :name, :one_per_topic, tag_names: [], parent_tag_name: [], permissions: {})
result[:tag_names] ||= []
result[:parent_tag_name] ||= []
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 662d8da5029..9b27b69e6a4 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -5,29 +5,32 @@ class TagsController < ::ApplicationController
include TopicQueryParams
before_action :ensure_tags_enabled
- before_action :ensure_visible, only: [:show, :info]
+ before_action :ensure_visible, only: %i[show info]
def self.show_methods
Discourse.anonymous_filters.map { |f| :"show_#{f}" }
end
- requires_login except: [
- :index,
- :show,
- :tag_feed,
- :search,
- :info,
- *show_methods
- ]
+ requires_login except: [:index, :show, :tag_feed, :search, :info, *show_methods]
skip_before_action :check_xhr, only: [:tag_feed, :show, :index, *show_methods]
- before_action :set_category, except: [:index, :update, :destroy,
- :tag_feed, :search, :notifications, :update_notifications, :personal_messages, :info]
+ before_action :set_category,
+ except: %i[
+ index
+ update
+ destroy
+ tag_feed
+ search
+ notifications
+ update_notifications
+ personal_messages
+ info
+ ]
- before_action :fetch_tag, only: [:info, :create_synonyms, :destroy_synonym]
+ before_action :fetch_tag, only: %i[info create_synonyms destroy_synonym]
- after_action :add_noindex_header, except: [:index, :show]
+ after_action :add_noindex_header, except: %i[index show]
def index
@description_meta = I18n.t("tags.title")
@@ -39,9 +42,22 @@ class TagsController < ::ApplicationController
ungrouped_tags = Tag.where("tags.id NOT IN (SELECT tag_id FROM tag_group_memberships)")
ungrouped_tags = ungrouped_tags.where("tags.topic_count > 0") unless show_all_tags
- grouped_tag_counts = TagGroup.visible(guardian).order('name ASC').includes(:tags).map do |tag_group|
- { id: tag_group.id, name: tag_group.name, tags: self.class.tag_counts_json(tag_group.tags.where(target_tag_id: nil), show_pm_tags: guardian.can_tag_pms?) }
- end
+ grouped_tag_counts =
+ TagGroup
+ .visible(guardian)
+ .order("name ASC")
+ .includes(:tags)
+ .map do |tag_group|
+ {
+ id: tag_group.id,
+ name: tag_group.name,
+ tags:
+ self.class.tag_counts_json(
+ tag_group.tags.where(target_tag_id: nil),
+ show_pm_tags: guardian.can_tag_pms?,
+ ),
+ }
+ end
@tags = self.class.tag_counts_json(ungrouped_tags, show_pm_tags: guardian.can_tag_pms?)
@extras = { tag_groups: grouped_tag_counts }
@@ -49,41 +65,40 @@ class TagsController < ::ApplicationController
tags = show_all_tags ? Tag.all : Tag.where("tags.topic_count > 0")
unrestricted_tags = DiscourseTagging.filter_visible(tags.where(target_tag_id: nil), guardian)
- categories = Category.where("id IN (SELECT category_id FROM category_tags)")
- .where("id IN (?)", guardian.allowed_category_ids)
- .includes(:tags)
+ categories =
+ Category
+ .where("id IN (SELECT category_id FROM category_tags)")
+ .where("id IN (?)", guardian.allowed_category_ids)
+ .includes(:tags)
- category_tag_counts = categories.map do |c|
- category_tags = self.class.tag_counts_json(
- DiscourseTagging.filter_visible(c.tags.where(target_tag_id: nil), guardian)
- )
- next if category_tags.empty?
- { id: c.id, tags: category_tags }
- end.compact
+ category_tag_counts =
+ categories
+ .map do |c|
+ category_tags =
+ self.class.tag_counts_json(
+ DiscourseTagging.filter_visible(c.tags.where(target_tag_id: nil), guardian),
+ )
+ next if category_tags.empty?
+ { id: c.id, tags: category_tags }
+ end
+ .compact
@tags = self.class.tag_counts_json(unrestricted_tags, show_pm_tags: guardian.can_tag_pms?)
@extras = { categories: category_tag_counts }
end
respond_to do |format|
+ format.html { render :index }
- format.html do
- render :index
- end
-
- format.json do
- render json: {
- tags: @tags,
- extras: @extras
- }
- end
+ format.json { render json: { tags: @tags, extras: @extras } }
end
end
Discourse.filters.each do |filter|
define_method("show_#{filter}") do
@tag_id = params[:tag_id].force_encoding("UTF-8")
- @additional_tags = params[:additional_tag_ids].to_s.split('/').map { |t| t.force_encoding("UTF-8") }
+ @additional_tags =
+ params[:additional_tag_ids].to_s.split("/").map { |t| t.force_encoding("UTF-8") }
list_opts = build_topic_list_options
@list = nil
@@ -101,14 +116,14 @@ class TagsController < ::ApplicationController
@list.more_topics_url = construct_url_with(:next, list_opts)
@list.prev_topics_url = construct_url_with(:prev, list_opts)
@rss = "tag"
- @description_meta = I18n.t("rss_by_tag", tag: tag_params.join(' & '))
+ @description_meta = I18n.t("rss_by_tag", tag: tag_params.join(" & "))
@title = @description_meta
canonical_params = params.slice(:category_slug_path_with_id, :tag_id)
canonical_method = url_method(canonical_params)
canonical_url "#{Discourse.base_url_no_prefix}#{public_send(canonical_method, *(canonical_params.values.map { |t| t.force_encoding("UTF-8") }))}"
- if @list.topics.size == 0 && params[:tag_id] != 'none' && !Tag.where_name(@tag_id).exists?
+ if @list.topics.size == 0 && params[:tag_id] != "none" && !Tag.where_name(@tag_id).exists?
raise Discourse::NotFound.new("tag not found", check_permalinks: true)
else
respond_with_list(@list)
@@ -121,12 +136,7 @@ class TagsController < ::ApplicationController
end
def info
- render_serialized(
- @tag,
- DetailedTagSerializer,
- rest_serializer: true,
- root: :tag_info
- )
+ render_serialized(@tag, DetailedTagSerializer, rest_serializer: true, root: :tag_info)
end
def update
@@ -141,7 +151,11 @@ class TagsController < ::ApplicationController
end
tag.description = params[:tag][:description] if params[:tag]&.has_key?(:description)
if tag.save
- StaffActionLogger.new(current_user).log_custom('renamed_tag', previous_value: params[:tag_id], new_value: new_tag_name)
+ StaffActionLogger.new(current_user).log_custom(
+ "renamed_tag",
+ previous_value: params[:tag_id],
+ new_value: new_tag_name,
+ )
render json: { tag: { id: tag.name, description: tag.description } }
else
render_json_error tag.errors.full_messages
@@ -149,7 +163,7 @@ class TagsController < ::ApplicationController
end
def upload
- require 'csv'
+ require "csv"
guardian.ensure_can_admin_tags!
@@ -159,7 +173,9 @@ class TagsController < ::ApplicationController
begin
Tag.transaction do
CSV.foreach(file.tempfile) do |row|
- raise Discourse::InvalidParameters.new(I18n.t("tags.upload_row_too_long")) if row.length > 2
+ if row.length > 2
+ raise Discourse::InvalidParameters.new(I18n.t("tags.upload_row_too_long"))
+ end
tag_name = DiscourseTagging.clean_tag(row[0])
tag_group_name = row[1] || nil
@@ -167,7 +183,8 @@ class TagsController < ::ApplicationController
tag = Tag.find_by_name(tag_name) || Tag.create!(name: tag_name)
if tag_group_name
- tag_group = TagGroup.find_by(name: tag_group_name) || TagGroup.create!(name: tag_group_name)
+ tag_group =
+ TagGroup.find_by(name: tag_group_name) || TagGroup.create!(name: tag_group_name)
tag.tag_groups << tag_group unless tag.tag_groups.include?(tag_group)
end
end
@@ -187,7 +204,7 @@ class TagsController < ::ApplicationController
def destroy_unused
guardian.ensure_can_admin_tags!
tags = Tag.unused
- StaffActionLogger.new(current_user).log_custom('deleted_unused_tags', tags: tags.pluck(:name))
+ StaffActionLogger.new(current_user).log_custom("deleted_unused_tags", tags: tags.pluck(:name))
tags.destroy_all
render json: success_json
end
@@ -200,7 +217,7 @@ class TagsController < ::ApplicationController
TopicCustomField.transaction do
tag.destroy
- StaffActionLogger.new(current_user).log_custom('deleted_tag', subject: tag_name)
+ StaffActionLogger.new(current_user).log_custom("deleted_tag", subject: tag_name)
end
render json: success_json
end
@@ -218,7 +235,7 @@ class TagsController < ::ApplicationController
latest_results = query.latest_results
@topic_list = query.create_list(:by_tag, {}, latest_results)
- render 'list/list', formats: [:rss]
+ render "list/list", formats: [:rss]
end
def search
@@ -227,16 +244,14 @@ class TagsController < ::ApplicationController
selected_tags: params[:selected_tags],
limit: params[:limit],
exclude_synonyms: params[:excludeSynonyms],
- exclude_has_synonyms: params[:excludeHasSynonyms]
+ exclude_has_synonyms: params[:excludeHasSynonyms],
}
if filter_params[:limit] && filter_params[:limit].to_i < 0
raise Discourse::InvalidParameters.new(:limit)
end
- if params[:categoryId]
- filter_params[:category] = Category.find_by_id(params[:categoryId])
- end
+ filter_params[:category] = Category.find_by_id(params[:categoryId]) if params[:categoryId]
if !params[:q].blank?
clean_name = DiscourseTagging.clean_tag(params[:q])
@@ -246,27 +261,35 @@ class TagsController < ::ApplicationController
filter_params[:order_popularity] = true
end
- tags_with_counts, filter_result_context = DiscourseTagging.filter_allowed_tags(
- guardian,
- **filter_params,
- with_context: true
- )
+ tags_with_counts, filter_result_context =
+ DiscourseTagging.filter_allowed_tags(guardian, **filter_params, with_context: true)
tags = self.class.tag_counts_json(tags_with_counts, show_pm_tags: guardian.can_tag_pms?)
json_response = { results: tags }
- if clean_name && !tags.find { |h| h[:id].downcase == clean_name.downcase } && tag = Tag.where_name(clean_name).first
+ if clean_name && !tags.find { |h| h[:id].downcase == clean_name.downcase } &&
+ tag = Tag.where_name(clean_name).first
# filter_allowed_tags determined that the tag entered is not allowed
json_response[:forbidden] = params[:q]
if filter_params[:exclude_synonyms] && tag.synonym?
- json_response[:forbidden_message] = I18n.t("tags.forbidden.synonym", tag_name: tag.target_tag.name)
+ json_response[:forbidden_message] = I18n.t(
+ "tags.forbidden.synonym",
+ tag_name: tag.target_tag.name,
+ )
elsif filter_params[:exclude_has_synonyms] && tag.synonyms.exists?
- json_response[:forbidden_message] = I18n.t("tags.forbidden.has_synonyms", tag_name: tag.name)
+ json_response[:forbidden_message] = I18n.t(
+ "tags.forbidden.has_synonyms",
+ tag_name: tag.name,
+ )
else
category_names = tag.categories.where(id: guardian.allowed_category_ids).pluck(:name)
- category_names += Category.joins(tag_groups: :tags).where(id: guardian.allowed_category_ids, "tags.id": tag.id).pluck(:name)
+ category_names +=
+ Category
+ .joins(tag_groups: :tags)
+ .where(id: guardian.allowed_category_ids, "tags.id": tag.id)
+ .pluck(:name)
if category_names.present?
category_names.uniq!
@@ -274,10 +297,13 @@ class TagsController < ::ApplicationController
"tags.forbidden.restricted_to",
count: category_names.count,
tag_name: tag.name,
- category_names: category_names.join(", ")
+ category_names: category_names.join(", "),
)
else
- json_response[:forbidden_message] = I18n.t("tags.forbidden.in_this_category", tag_name: tag.name)
+ json_response[:forbidden_message] = I18n.t(
+ "tags.forbidden.in_this_category",
+ tag_name: tag.name,
+ )
end
end
end
@@ -292,7 +318,9 @@ class TagsController < ::ApplicationController
def notifications
tag = Tag.where_name(params[:tag_id]).first
raise Discourse::NotFound unless tag
- level = tag.tag_users.where(user: current_user).first.try(:notification_level) || TagUser.notification_levels[:regular]
+ level =
+ tag.tag_users.where(user: current_user).first.try(:notification_level) ||
+ TagUser.notification_levels[:regular]
render json: { tag_notification: { id: tag.name, notification_level: level.to_i } }
end
@@ -318,9 +346,14 @@ class TagsController < ::ApplicationController
guardian.ensure_can_admin_tags!
value = DiscourseTagging.add_or_create_synonyms_by_name(@tag, params[:synonyms])
if value.is_a?(Array)
- render json: failed_json.merge(
- failed_tags: value.inject({}) { |h, t| h[t.name] = t.errors.full_messages.first; h }
- )
+ render json:
+ failed_json.merge(
+ failed_tags:
+ value.inject({}) do |h, t|
+ h[t.name] = t.errors.full_messages.first
+ h
+ end,
+ )
else
render json: success_json
end
@@ -350,24 +383,29 @@ class TagsController < ::ApplicationController
end
def ensure_visible
- raise Discourse::NotFound if DiscourseTagging.hidden_tag_names(guardian).include?(params[:tag_id])
+ if DiscourseTagging.hidden_tag_names(guardian).include?(params[:tag_id])
+ raise Discourse::NotFound
+ end
end
def self.tag_counts_json(tags, show_pm_tags: true)
target_tags = Tag.where(id: tags.map(&:target_tag_id).compact.uniq).select(:id, :name)
- tags.map do |t|
- next if t.topic_count == 0 && t.pm_topic_count > 0 && !show_pm_tags
+ tags
+ .map do |t|
+ next if t.topic_count == 0 && t.pm_topic_count > 0 && !show_pm_tags
- {
- id: t.name,
- text: t.name,
- name: t.name,
- description: t.description,
- count: t.topic_count,
- pm_count: show_pm_tags ? t.pm_topic_count : 0,
- target_tag: t.target_tag_id ? target_tags.find { |x| x.id == t.target_tag_id }&.name : nil
- }
- end.compact
+ {
+ id: t.name,
+ text: t.name,
+ name: t.name,
+ description: t.description,
+ count: t.topic_count,
+ pm_count: show_pm_tags ? t.pm_topic_count : 0,
+ target_tag:
+ t.target_tag_id ? target_tags.find { |x| x.id == t.target_tag_id }&.name : nil,
+ }
+ end
+ .compact
end
def set_category
@@ -383,7 +421,10 @@ class TagsController < ::ApplicationController
if !@filter_on_category
permalink = Permalink.find_by_url("c/#{params[:category_slug_path_with_id]}")
if permalink.present? && permalink.category_id
- return redirect_to "#{Discourse::base_path}/tags#{permalink.target_url}/#{params[:tag_id]}", status: :moved_permanently
+ return(
+ redirect_to "#{Discourse.base_path}/tags#{permalink.target_url}/#{params[:tag_id]}",
+ status: :moved_permanently
+ )
end
end
@@ -394,14 +435,15 @@ class TagsController < ::ApplicationController
end
def page_params
- route_params = { format: 'json' }
+ route_params = { format: "json" }
if @filter_on_category
if request.path_parameters.include?(:category_slug_path_with_id)
slug_path = @filter_on_category.slug_path
- route_params[:category_slug_path_with_id] =
- (slug_path + [@filter_on_category.id.to_s]).join("/")
+ route_params[:category_slug_path_with_id] = (
+ slug_path + [@filter_on_category.id.to_s]
+ ).join("/")
else
route_params[:category] = @filter_on_category.slug_for_url
end
@@ -453,28 +495,30 @@ class TagsController < ::ApplicationController
raise Discourse::NotFound
end
- url.sub('.json?', '?')
+ url.sub(".json?", "?")
end
def build_topic_list_options
- options = super.merge(
- page: params[:page],
- topic_ids: param_to_integer_list(:topic_ids),
- category: @filter_on_category ? @filter_on_category.id : params[:category],
- order: params[:order],
- ascending: params[:ascending],
- min_posts: params[:min_posts],
- max_posts: params[:max_posts],
- status: params[:status],
- filter: params[:filter],
- state: params[:state],
- search: params[:search],
- q: params[:q]
- )
- options[:no_subcategories] = true if params[:no_subcategories] == true || params[:no_subcategories] == 'true'
+ options =
+ super.merge(
+ page: params[:page],
+ topic_ids: param_to_integer_list(:topic_ids),
+ category: @filter_on_category ? @filter_on_category.id : params[:category],
+ order: params[:order],
+ ascending: params[:ascending],
+ min_posts: params[:min_posts],
+ max_posts: params[:max_posts],
+ status: params[:status],
+ filter: params[:filter],
+ state: params[:state],
+ search: params[:search],
+ q: params[:q],
+ )
+ options[:no_subcategories] = true if params[:no_subcategories] == true ||
+ params[:no_subcategories] == "true"
options[:per_page] = params[:per_page].to_i.clamp(1, 30) if params[:per_page].present?
- if params[:tag_id] == 'none'
+ if params[:tag_id] == "none"
options.delete(:tags)
options[:no_tags] = true
else
diff --git a/app/controllers/theme_javascripts_controller.rb b/app/controllers/theme_javascripts_controller.rb
index 418a076b825..63d6484d712 100644
--- a/app/controllers/theme_javascripts_controller.rb
+++ b/app/controllers/theme_javascripts_controller.rb
@@ -9,10 +9,10 @@ class ThemeJavascriptsController < ApplicationController
:preload_json,
:redirect_to_login_if_required,
:verify_authenticity_token,
- only: [:show, :show_map, :show_tests]
+ only: %i[show show_map show_tests],
)
- before_action :is_asset_path, :no_cookies, :apply_cdn_headers, only: [:show, :show_map, :show_tests]
+ before_action :is_asset_path, :no_cookies, :apply_cdn_headers, only: %i[show show_map show_tests]
def show
raise Discourse::NotFound unless last_modified.present?
@@ -24,7 +24,8 @@ class ThemeJavascriptsController < ApplicationController
write_if_not_cached(cache_file) do
content, has_source_map = query.pluck_first(:content, "source_map IS NOT NULL")
if has_source_map
- content += "\n//# sourceMappingURL=#{params[:digest]}.map?__ws=#{Discourse.current_hostname}\n"
+ content +=
+ "\n//# sourceMappingURL=#{params[:digest]}.map?__ws=#{Discourse.current_hostname}\n"
end
content
end
@@ -39,9 +40,7 @@ class ThemeJavascriptsController < ApplicationController
# Security: safe due to route constraint
cache_file = "#{DISK_CACHE_PATH}/#{params[:digest]}.map"
- write_if_not_cached(cache_file) do
- query.pluck_first(:source_map)
- end
+ write_if_not_cached(cache_file) { query.pluck_first(:source_map) }
serve_file(cache_file)
end
@@ -59,9 +58,7 @@ class ThemeJavascriptsController < ApplicationController
@cache_file = "#{TESTS_DISK_CACHE_PATH}/#{digest}.js"
return render body: nil, status: 304 if not_modified?
- write_if_not_cached(@cache_file) do
- content
- end
+ write_if_not_cached(@cache_file) { content }
serve_file @cache_file
end
@@ -73,13 +70,14 @@ class ThemeJavascriptsController < ApplicationController
end
def last_modified
- @last_modified ||= begin
- if params[:action].to_s == "show_tests"
- File.exist?(@cache_file) ? File.ctime(@cache_file) : nil
- else
- query.pluck_first(:updated_at)
+ @last_modified ||=
+ begin
+ if params[:action].to_s == "show_tests"
+ File.exist?(@cache_file) ? File.ctime(@cache_file) : nil
+ else
+ query.pluck_first(:updated_at)
+ end
end
- end
end
def not_modified?
@@ -95,10 +93,10 @@ class ThemeJavascriptsController < ApplicationController
def set_cache_control_headers
if Rails.env.development?
- response.headers['Last-Modified'] = Time.zone.now.httpdate
+ response.headers["Last-Modified"] = Time.zone.now.httpdate
immutable_for(1.second)
else
- response.headers['Last-Modified'] = last_modified.httpdate if last_modified
+ response.headers["Last-Modified"] = last_modified.httpdate if last_modified
immutable_for(1.year)
end
end
diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb
index d2b3caeb243..4ad8b879117 100644
--- a/app/controllers/topics_controller.rb
+++ b/app/controllers/topics_controller.rb
@@ -1,40 +1,40 @@
# frozen_string_literal: true
class TopicsController < ApplicationController
- requires_login only: [
- :timings,
- :destroy_timings,
- :update,
- :update_shared_draft,
- :destroy,
- :recover,
- :status,
- :invite,
- :mute,
- :unmute,
- :set_notifications,
- :move_posts,
- :merge_topic,
- :clear_pin,
- :re_pin,
- :status_update,
- :timer,
- :bulk,
- :reset_new,
- :change_post_owners,
- :change_timestamps,
- :archive_message,
- :move_to_inbox,
- :convert_topic,
- :bookmark,
- :publish,
- :reset_bump_date,
- :set_slow_mode
- ]
+ requires_login only: %i[
+ timings
+ destroy_timings
+ update
+ update_shared_draft
+ destroy
+ recover
+ status
+ invite
+ mute
+ unmute
+ set_notifications
+ move_posts
+ merge_topic
+ clear_pin
+ re_pin
+ status_update
+ timer
+ bulk
+ reset_new
+ change_post_owners
+ change_timestamps
+ archive_message
+ move_to_inbox
+ convert_topic
+ bookmark
+ publish
+ reset_bump_date
+ set_slow_mode
+ ]
before_action :consider_user_for_promotion, only: :show
- skip_before_action :check_xhr, only: [:show, :feed]
+ skip_before_action :check_xhr, only: %i[show feed]
def id_for_slug
topic = Topic.find_by_slug(params[:slug])
@@ -51,9 +51,7 @@ class TopicsController < ApplicationController
end
def show
- if request.referer
- flash["referer"] ||= request.referer[0..255]
- end
+ flash["referer"] ||= request.referer[0..255] if request.referer
# We'd like to migrate the wordpress feed to another url. This keeps up backwards compatibility with
# existing installs.
@@ -61,13 +59,27 @@ class TopicsController < ApplicationController
# work around people somehow sending in arrays,
# arrays are not supported
- params[:page] = params[:page].to_i rescue 1
+ params[:page] = begin
+ params[:page].to_i
+ rescue StandardError
+ 1
+ end
- opts = params.slice(:username_filters, :filter, :page, :post_number, :show_deleted, :replies_to_post_number, :filter_upwards_post_id, :filter_top_level_replies)
+ opts =
+ params.slice(
+ :username_filters,
+ :filter,
+ :page,
+ :post_number,
+ :show_deleted,
+ :replies_to_post_number,
+ :filter_upwards_post_id,
+ :filter_top_level_replies,
+ )
username_filters = opts[:username_filters]
- opts[:print] = true if params[:print] == 'true'
- opts[:username_filters] = username_filters.split(',') if username_filters.is_a?(String)
+ opts[:print] = true if params[:print] == "true"
+ opts[:username_filters] = username_filters.split(",") if username_filters.is_a?(String)
# Special case: a slug with a number in front should look by slug first before looking
# up that particular number
@@ -79,7 +91,14 @@ class TopicsController < ApplicationController
if opts[:print]
raise Discourse::InvalidAccess unless SiteSetting.max_prints_per_hour_per_user > 0
begin
- RateLimiter.new(current_user, "print-topic-per-hour", SiteSetting.max_prints_per_hour_per_user, 1.hour).performed! unless @guardian.is_admin?
+ unless @guardian.is_admin?
+ RateLimiter.new(
+ current_user,
+ "print-topic-per-hour",
+ SiteSetting.max_prints_per_hour_per_user,
+ 1.hour,
+ ).performed!
+ end
rescue RateLimiter::LimitExceeded
return render_json_error I18n.t("rate_limiter.slow_down")
end
@@ -100,37 +119,38 @@ class TopicsController < ApplicationController
# If the user can't see the topic, clean up notifications for it.
Notification.remove_for(current_user.id, params[:topic_id]) if current_user
- deleted = guardian.can_see_topic?(ex.obj, false) ||
- (!guardian.can_see_topic?(ex.obj) &&
- ex.obj&.access_topic_via_group &&
- ex.obj.deleted_at)
+ deleted =
+ guardian.can_see_topic?(ex.obj, false) ||
+ (!guardian.can_see_topic?(ex.obj) && ex.obj&.access_topic_via_group && ex.obj.deleted_at)
if SiteSetting.detailed_404
if deleted
raise Discourse::NotFound.new(
- 'deleted topic',
- custom_message: 'deleted_topic',
- status: 410,
- check_permalinks: true,
- original_path: ex.obj.relative_url
- )
+ "deleted topic",
+ custom_message: "deleted_topic",
+ status: 410,
+ check_permalinks: true,
+ original_path: ex.obj.relative_url,
+ )
elsif !guardian.can_see_topic?(ex.obj) && group = ex.obj&.access_topic_via_group
raise Discourse::InvalidAccess.new(
- 'not in group',
- ex.obj,
- custom_message: 'not_in_group.title_topic',
- custom_message_params: { group: group.name },
- group: group
- )
+ "not in group",
+ ex.obj,
+ custom_message: "not_in_group.title_topic",
+ custom_message_params: {
+ group: group.name,
+ },
+ group: group,
+ )
end
raise ex
else
raise Discourse::NotFound.new(
- nil,
- check_permalinks: deleted,
- original_path: ex.obj.relative_url
- )
+ nil,
+ check_permalinks: deleted,
+ original_path: ex.obj.relative_url,
+ )
end
end
@@ -152,9 +172,7 @@ class TopicsController < ApplicationController
@topic_view.draft = Draft.get(current_user, @topic_view.draft_key, @topic_view.draft_sequence)
end
- unless @topic_view.topic.visible
- response.headers['X-Robots-Tag'] = 'noindex'
- end
+ response.headers["X-Robots-Tag"] = "noindex" unless @topic_view.topic.visible
canonical_url UrlHelper.absolute_without_cdn(@topic_view.canonical_path)
@@ -162,7 +180,7 @@ class TopicsController < ApplicationController
# we would like to give them a bit more signal about age of data
if use_crawler_layout?
if last_modified = @topic_view.posts&.map { |p| p.updated_at }&.max&.httpdate
- response.headers['Last-Modified'] = last_modified
+ response.headers["Last-Modified"] = last_modified
end
end
@@ -186,7 +204,13 @@ class TopicsController < ApplicationController
def wordpress
params.require(:best)
params.require(:topic_id)
- params.permit(:min_trust_level, :min_score, :min_replies, :bypass_trust_level_score, :only_moderator_liked)
+ params.permit(
+ :min_trust_level,
+ :min_score,
+ :min_replies,
+ :bypass_trust_level_score,
+ :only_moderator_liked,
+ )
opts = {
best: params[:best].to_i,
@@ -195,13 +219,14 @@ class TopicsController < ApplicationController
min_replies: params[:min_replies].to_i,
bypass_trust_level_score: params[:bypass_trust_level_score].to_i, # safe cause 0 means ignore
only_moderator_liked: params[:only_moderator_liked].to_s == "true",
- exclude_hidden: true
+ exclude_hidden: true,
}
@topic_view = TopicView.new(params[:topic_id], current_user, opts)
discourse_expires_in 1.minute
- wordpress_serializer = TopicViewWordpressSerializer.new(@topic_view, scope: guardian, root: false)
+ wordpress_serializer =
+ TopicViewWordpressSerializer.new(@topic_view, scope: guardian, root: false)
render_json_dump(wordpress_serializer)
end
@@ -214,7 +239,7 @@ class TopicsController < ApplicationController
filter: params[:filter],
skip_limit: true,
asc: true,
- skip_custom_fields: true
+ skip_custom_fields: true,
}
fetch_topic_view(options)
@@ -243,8 +268,8 @@ class TopicsController < ApplicationController
@topic_view,
scope: guardian,
root: false,
- include_raw: !!params[:include_raw]
- )
+ include_raw: !!params[:include_raw],
+ ),
)
end
@@ -266,25 +291,27 @@ class TopicsController < ApplicationController
@topic = Topic.with_deleted.where(id: params[:topic_id]).first
guardian.ensure_can_see!(@topic)
- @posts = Post.where(hidden: false, deleted_at: nil, topic_id: @topic.id)
- .where('posts.id in (?)', post_ids)
- .joins("LEFT JOIN users u on u.id = posts.user_id")
- .pluck(:id, :cooked, :username, :action_code, :created_at)
- .map do |post_id, cooked, username, action_code, created_at|
- attrs = {
- post_id: post_id,
- username: username,
- excerpt: PrettyText.excerpt(cooked, 800, keep_emoji_images: true),
- }
+ @posts =
+ Post
+ .where(hidden: false, deleted_at: nil, topic_id: @topic.id)
+ .where("posts.id in (?)", post_ids)
+ .joins("LEFT JOIN users u on u.id = posts.user_id")
+ .pluck(:id, :cooked, :username, :action_code, :created_at)
+ .map do |post_id, cooked, username, action_code, created_at|
+ attrs = {
+ post_id: post_id,
+ username: username,
+ excerpt: PrettyText.excerpt(cooked, 800, keep_emoji_images: true),
+ }
- if action_code
- attrs[:action_code] = action_code
- attrs[:created_at] = created_at
+ if action_code
+ attrs[:action_code] = action_code
+ attrs[:created_at] = created_at
+ end
+
+ attrs
end
- attrs
- end
-
render json: @posts.to_json
end
@@ -297,18 +324,14 @@ class TopicsController < ApplicationController
PostTiming.destroy_for(current_user.id, [topic_id])
end
- last_notification = Notification
- .where(
- user_id: current_user.id,
- topic_id: topic_id
- )
- .order(created_at: :desc)
- .limit(1)
- .first
+ last_notification =
+ Notification
+ .where(user_id: current_user.id, topic_id: topic_id)
+ .order(created_at: :desc)
+ .limit(1)
+ .first
- if last_notification
- last_notification.update!(read: false)
- end
+ last_notification.update!(read: false) if last_notification
render body: nil
end
@@ -321,9 +344,7 @@ class TopicsController < ApplicationController
guardian.ensure_can_publish_topic!(topic, category)
row_count = SharedDraft.where(topic_id: topic.id).update_all(category_id: category.id)
- if row_count == 0
- SharedDraft.create(topic_id: topic.id, category_id: category.id)
- end
+ SharedDraft.create(topic_id: topic.id, category_id: category.id) if row_count == 0
render json: success_json
end
@@ -342,15 +363,14 @@ class TopicsController < ApplicationController
if category || (params[:category_id].to_i == 0)
guardian.ensure_can_move_topic_to_category!(category)
else
- return render_json_error(I18n.t('category.errors.not_found'))
+ return render_json_error(I18n.t("category.errors.not_found"))
end
- if category && topic_tags = (params[:tags] || topic.tags.pluck(:name)).reject { |c| c.empty? }
+ if category &&
+ topic_tags = (params[:tags] || topic.tags.pluck(:name)).reject { |c| c.empty? }
if topic_tags.present?
- allowed_tags = DiscourseTagging.filter_allowed_tags(
- guardian,
- category: category
- ).map(&:name)
+ allowed_tags =
+ DiscourseTagging.filter_allowed_tags(guardian, category: category).map(&:name)
invalid_tags = topic_tags - allowed_tags
@@ -367,9 +387,13 @@ class TopicsController < ApplicationController
if !invalid_tags.empty?
if (invalid_tags & DiscourseTagging.hidden_tag_names).present?
- return render_json_error(I18n.t('category.errors.disallowed_tags_generic'))
+ return render_json_error(I18n.t("category.errors.disallowed_tags_generic"))
else
- return render_json_error(I18n.t('category.errors.disallowed_topic_tags', tags: invalid_tags.join(", ")))
+ return(
+ render_json_error(
+ I18n.t("category.errors.disallowed_topic_tags", tags: invalid_tags.join(", ")),
+ )
+ )
end
end
end
@@ -379,9 +403,7 @@ class TopicsController < ApplicationController
changes = {}
- PostRevisor.tracked_topic_fields.each_key do |f|
- changes[f] = params[f] if params.has_key?(f)
- end
+ PostRevisor.tracked_topic_fields.each_key { |f| changes[f] = params[f] if params.has_key?(f) }
changes.delete(:title) if topic.title == changes[:title]
changes.delete(:category_id) if topic.category_id.to_i == changes[:category_id].to_i
@@ -397,17 +419,16 @@ class TopicsController < ApplicationController
bypass_bump = should_bypass_bump?(changes)
first_post = topic.ordered_posts.first
- success = PostRevisor.new(first_post, topic).revise!(
- current_user,
- changes,
- validate_post: false,
- bypass_bump: bypass_bump,
- keep_existing_draft: params[:keep_existing_draft].to_s == "true"
- )
+ success =
+ PostRevisor.new(first_post, topic).revise!(
+ current_user,
+ changes,
+ validate_post: false,
+ bypass_bump: bypass_bump,
+ keep_existing_draft: params[:keep_existing_draft].to_s == "true",
+ )
- if !success && topic.errors.blank?
- topic.errors.add(:base, :unable_to_update)
- end
+ topic.errors.add(:base, :unable_to_update) if !success && topic.errors.blank?
end
# this is used to return the title to the client as it may have been changed by "TextCleaner"
@@ -419,7 +440,12 @@ class TopicsController < ApplicationController
topic = Topic.find_by(id: params[:topic_id])
guardian.ensure_can_edit_tags!(topic)
- success = PostRevisor.new(topic.first_post, topic).revise!(current_user, { tags: params[:tags] }, validate_post: false)
+ success =
+ PostRevisor.new(topic.first_post, topic).revise!(
+ current_user,
+ { tags: params[:tags] },
+ validate_post: false,
+ )
success ? render_serialized(topic, BasicTopicSerializer) : render_json_error(topic)
end
@@ -431,10 +457,16 @@ class TopicsController < ApplicationController
visible_topics = Topic.listable_topics.visible
render json: {
- pinned_in_category_count: visible_topics.where(category_id: category_id).where(pinned_globally: false).where.not(pinned_at: nil).count,
- pinned_globally_count: visible_topics.where(pinned_globally: true).where.not(pinned_at: nil).count,
- banner_count: Topic.listable_topics.where(archetype: Archetype.banner).count,
- }
+ pinned_in_category_count:
+ visible_topics
+ .where(category_id: category_id)
+ .where(pinned_globally: false)
+ .where.not(pinned_at: nil)
+ .count,
+ pinned_globally_count:
+ visible_topics.where(pinned_globally: true).where.not(pinned_at: nil).count,
+ banner_count: Topic.listable_topics.where(archetype: Archetype.banner).count,
+ }
end
def status
@@ -444,33 +476,33 @@ class TopicsController < ApplicationController
status = params[:status]
topic_id = params[:topic_id].to_i
- enabled = params[:enabled] == 'true'
+ enabled = params[:enabled] == "true"
check_for_status_presence(:status, status)
@topic = Topic.find_by(id: topic_id)
case status
- when 'closed'
+ when "closed"
guardian.ensure_can_close_topic!(@topic)
- when 'archived'
+ when "archived"
guardian.ensure_can_archive_topic!(@topic)
- when 'visible'
+ when "visible"
guardian.ensure_can_toggle_topic_visibility!(@topic)
- when 'pinned'
+ when "pinned"
guardian.ensure_can_pin_unpin_topic!(@topic)
else
guardian.ensure_can_moderate!(@topic)
end
- params[:until] === '' ? params[:until] = nil : params[:until]
+ params[:until] === "" ? params[:until] = nil : params[:until]
@topic.update_status(status, enabled, current_user, until: params[:until])
- render json: success_json.merge!(
- topic_status_update: TopicTimerSerializer.new(
- TopicTimer.find_by(topic: @topic), root: false
- )
- )
+ render json:
+ success_json.merge!(
+ topic_status_update:
+ TopicTimerSerializer.new(TopicTimer.find_by(topic: @topic), root: false),
+ )
end
def mute
@@ -488,7 +520,7 @@ class TopicsController < ApplicationController
status_type =
begin
TopicTimer.types.fetch(params[:status_type].to_sym)
- rescue
+ rescue StandardError
invalid_param(:status_type)
end
based_on_last_post = params[:based_on_last_post]
@@ -497,37 +529,31 @@ class TopicsController < ApplicationController
topic = Topic.find_by(id: params[:topic_id])
guardian.ensure_can_moderate!(topic)
- if TopicTimer.destructive_types.values.include?(status_type)
- guardian.ensure_can_delete!(topic)
- end
+ guardian.ensure_can_delete!(topic) if TopicTimer.destructive_types.values.include?(status_type)
- options = {
- by_user: current_user,
- based_on_last_post: based_on_last_post
- }
+ options = { by_user: current_user, based_on_last_post: based_on_last_post }
options.merge!(category_id: params[:category_id]) if !params[:category_id].blank?
- options.merge!(duration_minutes: params[:duration_minutes].to_i) if params[:duration_minutes].present?
+ if params[:duration_minutes].present?
+ options.merge!(duration_minutes: params[:duration_minutes].to_i)
+ end
options.merge!(duration: params[:duration].to_i) if params[:duration].present?
begin
- topic_timer = topic.set_or_create_timer(
- status_type,
- params[:time],
- **options
- )
+ topic_timer = topic.set_or_create_timer(status_type, params[:time], **options)
rescue ActiveRecord::RecordInvalid => e
return render_json_error(e.message)
end
if topic.save
- render json: success_json.merge!(
- execute_at: topic_timer&.execute_at,
- duration_minutes: topic_timer&.duration_minutes,
- based_on_last_post: topic_timer&.based_on_last_post,
- closed: topic.closed,
- category_id: topic_timer&.category_id
- )
+ render json:
+ success_json.merge!(
+ execute_at: topic_timer&.execute_at,
+ duration_minutes: topic_timer&.duration_minutes,
+ based_on_last_post: topic_timer&.based_on_last_post,
+ closed: topic.closed,
+ category_id: topic_timer&.category_id,
+ )
else
render_json_error(topic)
end
@@ -572,24 +598,16 @@ class TopicsController < ApplicationController
group_ids = current_user.groups.pluck(:id)
if group_ids.present?
- allowed_groups = topic.allowed_groups
- .where('topic_allowed_groups.group_id IN (?)', group_ids).pluck(:id)
+ allowed_groups =
+ topic.allowed_groups.where("topic_allowed_groups.group_id IN (?)", group_ids).pluck(:id)
allowed_groups.each do |id|
if archive
- GroupArchivedMessage.archive!(
- id,
- topic,
- acting_user_id: current_user.id
- )
+ GroupArchivedMessage.archive!(id, topic, acting_user_id: current_user.id)
group_id = id
else
- GroupArchivedMessage.move_to_inbox!(
- id,
- topic,
- acting_user_id: current_user.id
- )
+ GroupArchivedMessage.move_to_inbox!(id, topic, acting_user_id: current_user.id)
end
end
end
@@ -616,9 +634,7 @@ class TopicsController < ApplicationController
bookmark_manager = BookmarkManager.new(current_user)
bookmark_manager.create_for(bookmarkable_id: topic.id, bookmarkable_type: "Topic")
- if bookmark_manager.errors.any?
- return render_json_error(bookmark_manager, status: 400)
- end
+ return render_json_error(bookmark_manager, status: 400) if bookmark_manager.errors.any?
render body: nil
end
@@ -639,7 +655,7 @@ class TopicsController < ApplicationController
current_user,
topic.ordered_posts.with_deleted.first,
context: params[:context],
- force_destroy: force_destroy
+ force_destroy: force_destroy,
).destroy
render body: nil
@@ -697,15 +713,20 @@ class TopicsController < ApplicationController
raise Discourse::NotFound if !topic
if !pm_has_slots?(topic)
- return render_json_error(
- I18n.t("pm_reached_recipients_limit", recipients_limit: SiteSetting.max_allowed_message_recipients)
+ return(
+ render_json_error(
+ I18n.t(
+ "pm_reached_recipients_limit",
+ recipients_limit: SiteSetting.max_allowed_message_recipients,
+ ),
+ )
)
end
if topic.private_message?
guardian.ensure_can_invite_group_to_private_message!(group, topic)
topic.invite_group(current_user, group)
- render_json_dump BasicGroupSerializer.new(group, scope: guardian, root: 'group')
+ render_json_dump BasicGroupSerializer.new(group, scope: guardian, root: "group")
else
render json: failed_json, status: 422
end
@@ -715,28 +736,31 @@ class TopicsController < ApplicationController
topic = Topic.find_by(id: params[:topic_id])
raise Discourse::NotFound if !topic
- if !topic.private_message?
- return render_json_error(I18n.t("topic_invite.not_pm"))
- end
+ return render_json_error(I18n.t("topic_invite.not_pm")) if !topic.private_message?
if !pm_has_slots?(topic)
- return render_json_error(
- I18n.t("pm_reached_recipients_limit", recipients_limit: SiteSetting.max_allowed_message_recipients)
+ return(
+ render_json_error(
+ I18n.t(
+ "pm_reached_recipients_limit",
+ recipients_limit: SiteSetting.max_allowed_message_recipients,
+ ),
+ )
)
end
guardian.ensure_can_invite_to!(topic)
username_or_email = params[:user] ? fetch_username : fetch_email
- group_ids = Group.lookup_groups(
- group_ids: params[:group_ids],
- group_names: params[:group_names]
- ).pluck(:id)
+ group_ids =
+ Group.lookup_groups(group_ids: params[:group_ids], group_names: params[:group_names]).pluck(
+ :id,
+ )
begin
if topic.invite(current_user, username_or_email, group_ids, params[:custom_message])
if user = User.find_by_username_or_email(username_or_email)
- render_json_dump BasicUserSerializer.new(user, scope: guardian, root: 'user')
+ render_json_dump BasicUserSerializer.new(user, scope: guardian, root: "user")
else
render json: success_json
end
@@ -744,19 +768,16 @@ class TopicsController < ApplicationController
json = failed_json
unless topic.private_message?
- group_names = topic.category
- .visible_group_names(current_user)
- .where(automatic: false)
- .pluck(:name)
- .join(", ")
+ group_names =
+ topic
+ .category
+ .visible_group_names(current_user)
+ .where(automatic: false)
+ .pluck(:name)
+ .join(", ")
if group_names.present?
- json.merge!(errors: [
- I18n.t(
- "topic_invite.failed_to_invite",
- group_names: group_names
- )
- ])
+ json.merge!(errors: [I18n.t("topic_invite.failed_to_invite", group_names: group_names)])
end
end
@@ -792,7 +813,8 @@ class TopicsController < ApplicationController
if params[:archetype].present?
args[:archetype] = params[:archetype]
- args[:participants] = params[:participants] if params[:participants].present? && params[:archetype] == "private_message"
+ args[:participants] = params[:participants] if params[:participants].present? &&
+ params[:archetype] == "private_message"
end
destination_topic = topic.move_posts(current_user, topic.posts.pluck(:id), args)
@@ -814,8 +836,13 @@ class TopicsController < ApplicationController
if params[:title].present?
# when creating a new topic, ensure the 1st post is a regular post
- if Post.where(topic: topic, id: post_ids).order(:post_number).pluck_first(:post_type) != Post.types[:regular]
- return render_json_error("When moving posts to a new topic, the first post must be a regular post.")
+ if Post.where(topic: topic, id: post_ids).order(:post_number).pluck_first(:post_type) !=
+ Post.types[:regular]
+ return(
+ render_json_error(
+ "When moving posts to a new topic, the first post must be a regular post.",
+ )
+ )
end
if params[:category_id].present?
@@ -837,10 +864,12 @@ class TopicsController < ApplicationController
guardian.ensure_can_change_post_owner!
begin
- PostOwnerChanger.new(post_ids: params[:post_ids].to_a,
- topic_id: params[:topic_id].to_i,
- new_owner: User.find_by(username: params[:username]),
- acting_user: current_user).change_owner!
+ PostOwnerChanger.new(
+ post_ids: params[:post_ids].to_a,
+ topic_id: params[:topic_id].to_i,
+ new_owner: User.find_by(username: params[:username]),
+ acting_user: current_user,
+ ).change_owner!
render json: success_json
rescue ArgumentError
render json: failed_json, status: 422
@@ -857,12 +886,13 @@ class TopicsController < ApplicationController
previous_timestamp = topic.first_post.created_at
begin
- TopicTimestampChanger.new(
- topic: topic,
- timestamp: timestamp
- ).change!
+ TopicTimestampChanger.new(topic: topic, timestamp: timestamp).change!
- StaffActionLogger.new(current_user).log_topic_timestamps_changed(topic, Time.zone.at(timestamp), previous_timestamp)
+ StaffActionLogger.new(current_user).log_topic_timestamps_changed(
+ topic,
+ Time.zone.at(timestamp),
+ previous_timestamp,
+ )
render json: success_json
rescue ActiveRecord::RecordInvalid, TopicTimestampChanger::InvalidTimestampError
@@ -900,7 +930,7 @@ class TopicsController < ApplicationController
topic_id,
topic_time,
timings.map { |post_number, t| [post_number.to_i, t.to_i] },
- mobile: view_context.mobile_view?
+ mobile: view_context.mobile_view?,
)
render body: nil
end
@@ -914,43 +944,48 @@ class TopicsController < ApplicationController
rescue Discourse::NotLoggedIn
raise Discourse::NotFound
rescue Discourse::InvalidAccess => ex
-
- deleted = guardian.can_see_topic?(ex.obj, false) ||
- (!guardian.can_see_topic?(ex.obj) &&
- ex.obj&.access_topic_via_group &&
- ex.obj.deleted_at)
+ deleted =
+ guardian.can_see_topic?(ex.obj, false) ||
+ (!guardian.can_see_topic?(ex.obj) && ex.obj&.access_topic_via_group && ex.obj.deleted_at)
raise Discourse::NotFound.new(
- nil,
- check_permalinks: deleted,
- original_path: ex.obj.relative_url
- )
+ nil,
+ check_permalinks: deleted,
+ original_path: ex.obj.relative_url,
+ )
end
discourse_expires_in 1.minute
- response.headers['X-Robots-Tag'] = 'noindex, nofollow'
- render 'topics/show', formats: [:rss]
+ response.headers["X-Robots-Tag"] = "noindex, nofollow"
+ render "topics/show", formats: [:rss]
end
def bulk
if params[:topic_ids].present?
unless Array === params[:topic_ids]
- raise Discourse::InvalidParameters.new(
- "Expecting topic_ids to contain a list of topic ids"
- )
+ raise Discourse::InvalidParameters.new("Expecting topic_ids to contain a list of topic ids")
end
topic_ids = params[:topic_ids].map { |t| t.to_i }
- elsif params[:filter] == 'unread'
+ elsif params[:filter] == "unread"
topic_ids = bulk_unread_topic_ids
else
raise ActionController::ParameterMissing.new(:topic_ids)
end
- operation = params
- .require(:operation)
- .permit(:type, :group, :category_id, :notification_level_id, *DiscoursePluginRegistry.permitted_bulk_action_parameters, tags: [])
- .to_h.symbolize_keys
+ operation =
+ params
+ .require(:operation)
+ .permit(
+ :type,
+ :group,
+ :category_id,
+ :notification_level_id,
+ *DiscoursePluginRegistry.permitted_bulk_action_parameters,
+ tags: [],
+ )
+ .to_h
+ .symbolize_keys
raise ActionController::ParameterMissing.new(:operation_type) if operation[:type].blank?
operator = TopicsBulkAction.new(current_user, topic_ids, operation, group: operation[:group])
@@ -963,14 +998,14 @@ class TopicsController < ApplicationController
if params[:topic_ids].present?
unless Array === params[:topic_ids]
- raise Discourse::InvalidParameters.new(
- "Expecting topic_ids to contain a list of topic ids"
- )
+ raise Discourse::InvalidParameters.new("Expecting topic_ids to contain a list of topic ids")
end
- topic_scope = topic_query
- .private_messages_for(current_user, :all)
- .where("topics.id IN (?)", params[:topic_ids].map(&:to_i))
+ topic_scope =
+ topic_query.private_messages_for(current_user, :all).where(
+ "topics.id IN (?)",
+ params[:topic_ids].map(&:to_i),
+ )
else
params.require(:inbox)
inbox = params[:inbox].to_s
@@ -978,11 +1013,8 @@ class TopicsController < ApplicationController
topic_scope = topic_query.filter_private_message_new(current_user, filter)
end
- topic_ids = TopicsBulkAction.new(
- current_user,
- topic_scope.pluck(:id),
- type: "dismiss_topics"
- ).perform!
+ topic_ids =
+ TopicsBulkAction.new(current_user, topic_scope.pluck(:id), type: "dismiss_topics").perform!
render json: success_json.merge(topic_ids: topic_ids)
end
@@ -991,8 +1023,9 @@ class TopicsController < ApplicationController
topic_scope =
if params[:category_id].present?
category_ids = [params[:category_id]]
- if params[:include_subcategories] == 'true'
- category_ids = category_ids.concat(Category.where(parent_category_id: params[:category_id]).pluck(:id))
+ if params[:include_subcategories] == "true"
+ category_ids =
+ category_ids.concat(Category.where(parent_category_id: params[:category_id]).pluck(:id))
end
scope = Topic.where(category_id: category_ids)
@@ -1012,16 +1045,15 @@ class TopicsController < ApplicationController
if params[:topic_ids].present?
unless Array === params[:topic_ids]
- raise Discourse::InvalidParameters.new(
- "Expecting topic_ids to contain a list of topic ids"
- )
+ raise Discourse::InvalidParameters.new("Expecting topic_ids to contain a list of topic ids")
end
topic_ids = params[:topic_ids].map { |t| t.to_i }
topic_scope = topic_scope.where(id: topic_ids)
end
- dismissed_topic_ids = TopicsBulkAction.new(current_user, topic_scope.pluck(:id), type: "dismiss_topics").perform!
+ dismissed_topic_ids =
+ TopicsBulkAction.new(current_user, topic_scope.pluck(:id), type: "dismiss_topics").perform!
TopicTrackingState.publish_dismiss_new(current_user.id, topic_ids: dismissed_topic_ids)
render body: nil
@@ -1034,7 +1066,8 @@ class TopicsController < ApplicationController
guardian.ensure_can_convert_topic!(topic)
if params[:type] == "public"
- converted_topic = topic.convert_to_public_topic(current_user, category_id: params[:category_id])
+ converted_topic =
+ topic.convert_to_public_topic(current_user, category_id: params[:category_id])
else
converted_topic = topic.convert_to_private_message(current_user)
end
@@ -1065,11 +1098,7 @@ class TopicsController < ApplicationController
time = enabled && params[:enabled_until].present? ? params[:enabled_until] : nil
- topic.set_or_create_timer(
- slow_mode_type,
- time,
- by_user: timer&.user
- )
+ topic.set_or_create_timer(slow_mode_type, time, by_user: timer&.user)
head :ok
end
@@ -1077,16 +1106,12 @@ class TopicsController < ApplicationController
private
def topic_params
- params.permit(
- :topic_id,
- :topic_time,
- timings: {}
- )
+ params.permit(:topic_id, :topic_time, timings: {})
end
def fetch_topic_view(options)
if (username_filters = params[:username_filters]).present?
- options[:username_filters] = username_filters.split(',')
+ options[:username_filters] = username_filters.split(",")
end
@topic_view = TopicView.new(params[:topic_id], current_user, options)
@@ -1132,7 +1157,7 @@ class TopicsController < ApplicationController
url << ".json" if request.format.json?
opts.each do |k, v|
- s = url.include?('?') ? '&' : '?'
+ s = url.include?("?") ? "&" : "?"
url << "#{s}#{k}=#{v}"
end
@@ -1140,7 +1165,7 @@ class TopicsController < ApplicationController
end
def track_visit_to_topic
- topic_id = @topic_view.topic.id
+ topic_id = @topic_view.topic.id
ip = request.remote_ip
user_id = (current_user.id if current_user)
track_visit = should_track_visit_to_topic?
@@ -1152,8 +1177,8 @@ class TopicsController < ApplicationController
current_user: current_user,
topic_id: @topic_view.topic.id,
post_number: @topic_view.current_post_number,
- username: request['u'],
- ip_address: request.remote_ip
+ username: request["u"],
+ ip_address: request.remote_ip,
}
# defer this way so we do not capture the whole controller
# in the closure
@@ -1181,32 +1206,33 @@ class TopicsController < ApplicationController
end
def perform_show_response
-
if request.head?
head :ok
return
end
- topic_view_serializer = TopicViewSerializer.new(
- @topic_view,
- scope: guardian,
- root: false,
- include_raw: !!params[:include_raw],
- exclude_suggested_and_related: !!params[:replies_to_post_number] || !!params[:filter_upwards_post_id] || !!params[:filter_top_level_replies]
- )
+ topic_view_serializer =
+ TopicViewSerializer.new(
+ @topic_view,
+ scope: guardian,
+ root: false,
+ include_raw: !!params[:include_raw],
+ exclude_suggested_and_related:
+ !!params[:replies_to_post_number] || !!params[:filter_upwards_post_id] ||
+ !!params[:filter_top_level_replies],
+ )
respond_to do |format|
format.html do
@tags = SiteSetting.tagging_enabled ? @topic_view.topic.tags : []
@breadcrumbs = helpers.categories_breadcrumb(@topic_view.topic) || []
- @description_meta = @topic_view.topic.excerpt.present? ? @topic_view.topic.excerpt : @topic_view.summary
+ @description_meta =
+ @topic_view.topic.excerpt.present? ? @topic_view.topic.excerpt : @topic_view.summary
store_preloaded("topic_#{@topic_view.topic.id}", MultiJson.dump(topic_view_serializer))
render :show
end
- format.json do
- render_json_dump(topic_view_serializer)
- end
+ format.json { render_json_dump(topic_view_serializer) }
end
end
@@ -1221,12 +1247,15 @@ class TopicsController < ApplicationController
def move_posts_to_destination(topic)
args = {}
args[:title] = params[:title] if params[:title].present?
- args[:destination_topic_id] = params[:destination_topic_id].to_i if params[:destination_topic_id].present?
+ args[:destination_topic_id] = params[:destination_topic_id].to_i if params[
+ :destination_topic_id
+ ].present?
args[:tags] = params[:tags] if params[:tags].present?
if params[:archetype].present?
args[:archetype] = params[:archetype]
- args[:participants] = params[:participants] if params[:participants].present? && params[:archetype] == "private_message"
+ args[:participants] = params[:participants] if params[:participants].present? &&
+ params[:archetype] == "private_message"
else
args[:category_id] = params[:category_id].to_i if params[:category_id].present?
end
@@ -1235,7 +1264,7 @@ class TopicsController < ApplicationController
end
def check_for_status_presence(key, attr)
- invalid_param(key) unless %w(pinned pinned_globally visible closed archived).include?(attr)
+ invalid_param(key) unless %w[pinned pinned_globally visible closed archived].include?(attr)
end
def invalid_param(key)
@@ -1264,7 +1293,11 @@ class TopicsController < ApplicationController
topic_query.options[:limit] = false
topics = topic_query.filter_private_messages_unread(current_user, filter)
else
- topics = TopicQuery.unread_filter(topic_query.joined_topic_user, whisperer: guardian.is_whisperer?).listable_topics
+ topics =
+ TopicQuery.unread_filter(
+ topic_query.joined_topic_user,
+ whisperer: guardian.is_whisperer?,
+ ).listable_topics
topics = TopicQuery.tracked_filter(topics, current_user.id) if params[:tracked].to_s == "true"
if params[:category_id]
@@ -1274,7 +1307,7 @@ class TopicsController < ApplicationController
category_id = :category_id
SQL
else
- topics = topics.where('category_id = ?', params[:category_id])
+ topics = topics.where("category_id = ?", params[:category_id])
end
end
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index f1041f57bc6..218b5ae88dd 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -5,13 +5,18 @@ require "mini_mime"
class UploadsController < ApplicationController
include ExternalUploadHelpers
- requires_login except: [:show, :show_short, :_show_secure_deprecated, :show_secure]
+ requires_login except: %i[show show_short _show_secure_deprecated show_secure]
- skip_before_action :preload_json, :check_xhr, :redirect_to_login_if_required, only: [:show, :show_short, :_show_secure_deprecated, :show_secure]
+ skip_before_action :preload_json,
+ :check_xhr,
+ :redirect_to_login_if_required,
+ only: %i[show show_short _show_secure_deprecated show_secure]
protect_from_forgery except: :show
- before_action :is_asset_path, :apply_cdn_headers, only: [:show, :show_short, :_show_secure_deprecated, :show_secure]
- before_action :external_store_check, only: [:_show_secure_deprecated, :show_secure]
+ before_action :is_asset_path,
+ :apply_cdn_headers,
+ only: %i[show show_short _show_secure_deprecated show_secure]
+ before_action :external_store_check, only: %i[_show_secure_deprecated show_secure]
SECURE_REDIRECT_GRACE_SECONDS = 5
@@ -20,18 +25,21 @@ class UploadsController < ApplicationController
me = current_user
params.permit(:type, :upload_type)
- if params[:type].blank? && params[:upload_type].blank?
- raise Discourse::InvalidParameters
- end
+ raise Discourse::InvalidParameters if params[:type].blank? && params[:upload_type].blank?
# 50 characters ought to be enough for the upload type
- type = (params[:upload_type].presence || params[:type].presence).parameterize(separator: "_")[0..50]
+ type =
+ (params[:upload_type].presence || params[:type].presence).parameterize(separator: "_")[0..50]
- if type == "avatar" && !me.admin? && (SiteSetting.discourse_connect_overrides_avatar || !TrustLevelAndStaffAndDisabledSetting.matches?(SiteSetting.allow_uploaded_avatars, me))
+ if type == "avatar" && !me.admin? &&
+ (
+ SiteSetting.discourse_connect_overrides_avatar ||
+ !TrustLevelAndStaffAndDisabledSetting.matches?(SiteSetting.allow_uploaded_avatars, me)
+ )
return render json: failed_json, status: 422
end
- url = params[:url]
- file = params[:file] || params[:files]&.first
+ url = params[:url]
+ file = params[:file] || params[:files]&.first
pasted = params[:pasted] == "true"
for_private_message = params[:for_private_message] == "true"
for_site_setting = params[:for_site_setting] == "true"
@@ -42,17 +50,18 @@ class UploadsController < ApplicationController
# longer term we may change this
hijack do
begin
- info = UploadsController.create_upload(
- current_user: me,
- file: file,
- url: url,
- type: type,
- for_private_message: for_private_message,
- for_site_setting: for_site_setting,
- pasted: pasted,
- is_api: is_api,
- retain_hours: retain_hours
- )
+ info =
+ UploadsController.create_upload(
+ current_user: me,
+ file: file,
+ url: url,
+ type: type,
+ for_private_message: for_private_message,
+ for_site_setting: for_site_setting,
+ pasted: pasted,
+ is_api: is_api,
+ retain_hours: retain_hours,
+ )
rescue => e
render json: failed_json.merge(message: e.message&.split("\n")&.first), status: 422
else
@@ -66,13 +75,11 @@ class UploadsController < ApplicationController
uploads = []
if (params[:short_urls] && params[:short_urls].length > 0)
- PrettyText::Helpers.lookup_upload_urls(params[:short_urls]).each do |short_url, paths|
- uploads << {
- short_url: short_url,
- url: paths[:url],
- short_path: paths[:short_path]
- }
- end
+ PrettyText::Helpers
+ .lookup_upload_urls(params[:short_urls])
+ .each do |short_url, paths|
+ uploads << { short_url: short_url, url: paths[:url], short_path: paths[:short_path] }
+ end
end
render json: uploads.to_json
@@ -87,7 +94,9 @@ class UploadsController < ApplicationController
RailsMultisite::ConnectionManagement.with_connection(params[:site]) do |db|
return render_404 if SiteSetting.prevent_anons_from_downloading_files && current_user.nil?
- if upload = Upload.find_by(sha1: params[:sha]) || Upload.find_by(id: params[:id], url: request.env["PATH_INFO"])
+ if upload =
+ Upload.find_by(sha1: params[:sha]) ||
+ Upload.find_by(id: params[:id], url: request.env["PATH_INFO"])
unless Discourse.store.internal?
local_store = FileStore::LocalStore.new
return render_404 unless local_store.has_been_uploaded?(upload.url)
@@ -104,21 +113,18 @@ class UploadsController < ApplicationController
# do not serve uploads requested via XHR to prevent XSS
return xhr_not_allowed if request.xhr?
- if SiteSetting.prevent_anons_from_downloading_files && current_user.nil?
- return render_404
- end
+ return render_404 if SiteSetting.prevent_anons_from_downloading_files && current_user.nil?
sha1 = Upload.sha1_from_base62_encoded(params[:base62])
if upload = Upload.find_by(sha1: sha1)
- if upload.secure? && SiteSetting.secure_uploads?
- return handle_secure_upload_request(upload)
- end
+ return handle_secure_upload_request(upload) if upload.secure? && SiteSetting.secure_uploads?
if Discourse.store.internal?
send_file_local_upload(upload)
else
- redirect_to Discourse.store.url_for(upload, force_download: force_download?), allow_other_host: true
+ redirect_to Discourse.store.url_for(upload, force_download: force_download?),
+ allow_other_host: true
end
else
render_404
@@ -156,7 +162,8 @@ class UploadsController < ApplicationController
# private, so we don't want to go to the CDN url just yet otherwise we
# will get a 403. if the upload is not secure we assume the ACL is public
signed_secure_url = Discourse.store.signed_url_for_path(path_with_ext)
- redirect_to upload.secure? ? signed_secure_url : Discourse.store.cdn_url(upload.url), allow_other_host: true
+ redirect_to upload.secure? ? signed_secure_url : Discourse.store.cdn_url(upload.url),
+ allow_other_host: true
end
def handle_secure_upload_request(upload, path_with_ext = nil)
@@ -167,20 +174,25 @@ class UploadsController < ApplicationController
end
# defaults to public: false, so only cached by the client browser
- cache_seconds = SiteSetting.s3_presigned_get_url_expires_after_seconds - SECURE_REDIRECT_GRACE_SECONDS
+ cache_seconds =
+ SiteSetting.s3_presigned_get_url_expires_after_seconds - SECURE_REDIRECT_GRACE_SECONDS
expires_in cache_seconds.seconds
# url_for figures out the full URL, handling multisite DBs,
# and will return a presigned URL for the upload
if path_with_ext.blank?
- return redirect_to Discourse.store.url_for(upload, force_download: force_download?), allow_other_host: true
+ return(
+ redirect_to Discourse.store.url_for(upload, force_download: force_download?),
+ allow_other_host: true
+ )
end
redirect_to Discourse.store.signed_url_for_path(
- path_with_ext,
- expires_in: SiteSetting.s3_presigned_get_url_expires_after_seconds,
- force_download: force_download?
- ), allow_other_host: true
+ path_with_ext,
+ expires_in: SiteSetting.s3_presigned_get_url_expires_after_seconds,
+ force_download: force_download?,
+ ),
+ allow_other_host: true
end
def metadata
@@ -189,11 +201,11 @@ class UploadsController < ApplicationController
raise Discourse::NotFound unless upload
render json: {
- original_filename: upload.original_filename,
- width: upload.width,
- height: upload.height,
- human_filesize: upload.human_filesize
- }
+ original_filename: upload.original_filename,
+ width: upload.width,
+ height: upload.height,
+ human_filesize: upload.human_filesize,
+ }
end
protected
@@ -207,17 +219,18 @@ class UploadsController < ApplicationController
end
def validate_file_size(file_name:, file_size:)
- if file_size.zero?
- raise ExternalUploadValidationError.new(I18n.t("upload.size_zero_failure"))
- end
+ raise ExternalUploadValidationError.new(I18n.t("upload.size_zero_failure")) if file_size.zero?
if file_size_too_big?(file_name, file_size)
raise ExternalUploadValidationError.new(
- I18n.t(
- "upload.attachments.too_large_humanized",
- max_size: ActiveSupport::NumberHelper.number_to_human_size(SiteSetting.max_attachment_size_kb.kilobytes)
- )
- )
+ I18n.t(
+ "upload.attachments.too_large_humanized",
+ max_size:
+ ActiveSupport::NumberHelper.number_to_human_size(
+ SiteSetting.max_attachment_size_kb.kilobytes,
+ ),
+ ),
+ )
end
end
@@ -236,25 +249,34 @@ class UploadsController < ApplicationController
serialized ||= (data || {}).as_json
end
- def self.create_upload(current_user:,
- file:,
- url:,
- type:,
- for_private_message:,
- for_site_setting:,
- pasted:,
- is_api:,
- retain_hours:)
-
+ def self.create_upload(
+ current_user:,
+ file:,
+ url:,
+ type:,
+ for_private_message:,
+ for_site_setting:,
+ pasted:,
+ is_api:,
+ retain_hours:
+ )
if file.nil?
if url.present? && is_api
- maximum_upload_size = [SiteSetting.max_image_size_kb, SiteSetting.max_attachment_size_kb].max.kilobytes
- tempfile = FileHelper.download(
- url,
- follow_redirect: true,
- max_file_size: maximum_upload_size,
- tmp_file_name: "discourse-upload-#{type}"
- ) rescue nil
+ maximum_upload_size = [
+ SiteSetting.max_image_size_kb,
+ SiteSetting.max_attachment_size_kb,
+ ].max.kilobytes
+ tempfile =
+ begin
+ FileHelper.download(
+ url,
+ follow_redirect: true,
+ max_file_size: maximum_upload_size,
+ tmp_file_name: "discourse-upload-#{type}",
+ )
+ rescue StandardError
+ nil
+ end
filename = File.basename(URI.parse(url).path)
end
else
@@ -288,13 +310,14 @@ class UploadsController < ApplicationController
# as they may be further reduced in size by UploadCreator (at this point
# they may have already been reduced in size by preprocessors)
def file_size_too_big?(file_name, file_size)
- !FileHelper.is_supported_image?(file_name) && file_size >= SiteSetting.max_attachment_size_kb.kilobytes
+ !FileHelper.is_supported_image?(file_name) &&
+ file_size >= SiteSetting.max_attachment_size_kb.kilobytes
end
def send_file_local_upload(upload)
opts = {
filename: upload.original_filename,
- content_type: MiniMime.lookup_by_filename(upload.original_filename)&.content_type
+ content_type: MiniMime.lookup_by_filename(upload.original_filename)&.content_type,
}
if !FileHelper.is_inline_image?(upload.original_filename)
@@ -313,7 +336,11 @@ class UploadsController < ApplicationController
begin
yield
rescue Aws::S3::Errors::ServiceError => err
- message = debug_upload_error(err, I18n.t("upload.create_multipart_failure", additional_detail: err.message))
+ message =
+ debug_upload_error(
+ err,
+ I18n.t("upload.create_multipart_failure", additional_detail: err.message),
+ )
raise ExternalUploadHelpers::ExternalUploadValidationError.new(message)
end
end
diff --git a/app/controllers/user_actions_controller.rb b/app/controllers/user_actions_controller.rb
index 18efefa7079..24326698bb9 100644
--- a/app/controllers/user_actions_controller.rb
+++ b/app/controllers/user_actions_controller.rb
@@ -4,7 +4,11 @@ class UserActionsController < ApplicationController
def index
user_actions_params.require(:username)
- user = fetch_user_from_params(include_inactive: current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts))
+ user =
+ fetch_user_from_params(
+ include_inactive:
+ current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts),
+ )
offset = [0, user_actions_params[:offset].to_i].max
action_types = (user_actions_params[:filter] || "").split(",").map(&:to_i)
limit = user_actions_params.fetch(:limit, 30).to_i
@@ -20,11 +24,11 @@ class UserActionsController < ApplicationController
action_types: action_types,
guardian: guardian,
ignore_private_messages: params[:filter].blank?,
- acting_username: params[:acting_username]
+ acting_username: params[:acting_username],
}
stream = UserAction.stream(opts).to_a
- render_serialized(stream, UserActionSerializer, root: 'user_actions')
+ render_serialized(stream, UserActionSerializer, root: "user_actions")
end
def show
diff --git a/app/controllers/user_api_keys_controller.rb b/app/controllers/user_api_keys_controller.rb
index 0a34a33d65f..2c38f7e8fd2 100644
--- a/app/controllers/user_api_keys_controller.rb
+++ b/app/controllers/user_api_keys_controller.rb
@@ -1,17 +1,15 @@
# frozen_string_literal: true
class UserApiKeysController < ApplicationController
+ layout "no_ember"
- layout 'no_ember'
-
- requires_login only: [:create, :create_otp, :revoke, :undo_revoke]
- skip_before_action :redirect_to_login_if_required, only: [:new, :otp]
+ requires_login only: %i[create create_otp revoke undo_revoke]
+ skip_before_action :redirect_to_login_if_required, only: %i[new otp]
skip_before_action :check_xhr, :preload_json
AUTH_API_VERSION ||= 4
def new
-
if request.head?
head :ok, auth_api_version: AUTH_API_VERSION
return
@@ -24,9 +22,9 @@ class UserApiKeysController < ApplicationController
cookies[:destination_url] = request.fullpath
if SiteSetting.enable_discourse_connect?
- redirect_to path('/session/sso')
+ redirect_to path("/session/sso")
else
- redirect_to path('/login')
+ redirect_to path("/login")
end
return
end
@@ -44,13 +42,11 @@ class UserApiKeysController < ApplicationController
@push_url = params[:push_url]
@localized_scopes = params[:scopes].split(",").map { |s| I18n.t("user_api_key.scopes.#{s}") }
@scopes = params[:scopes]
-
rescue Discourse::InvalidAccess
@generic_error = true
end
def create
-
require_params
if params.key?(:auth_redirect)
@@ -66,13 +62,14 @@ class UserApiKeysController < ApplicationController
# destroy any old keys we had
UserApiKey.where(user_id: current_user.id, client_id: params[:client_id]).destroy_all
- key = UserApiKey.create!(
- application_name: @application_name,
- client_id: params[:client_id],
- user_id: current_user.id,
- push_url: params[:push_url],
- scopes: scopes.map { |name| UserApiKeyScope.new(name: name) }
- )
+ key =
+ UserApiKey.create!(
+ application_name: @application_name,
+ client_id: params[:client_id],
+ user_id: current_user.id,
+ push_url: params[:push_url],
+ scopes: scopes.map { |name| UserApiKeyScope.new(name: name) },
+ )
# we keep the payload short so it encrypts easily with public key
# it is often restricted to 128 chars
@@ -80,7 +77,7 @@ class UserApiKeysController < ApplicationController
key: key.key,
nonce: params[:nonce],
push: key.has_push?,
- api: AUTH_API_VERSION
+ api: AUTH_API_VERSION,
}.to_json
public_key = OpenSSL::PKey::RSA.new(params[:public_key])
@@ -94,8 +91,10 @@ class UserApiKeysController < ApplicationController
if params[:auth_redirect]
uri = URI.parse(params[:auth_redirect])
query_attributes = [uri.query, "payload=#{CGI.escape(@payload)}"]
- query_attributes << "oneTimePassword=#{CGI.escape(otp_payload)}" if scopes.include?("one_time_password")
- uri.query = query_attributes.compact.join('&')
+ if scopes.include?("one_time_password")
+ query_attributes << "oneTimePassword=#{CGI.escape(otp_payload)}"
+ end
+ uri.query = query_attributes.compact.join("&")
redirect_to(uri.to_s, allow_other_host: true)
else
@@ -116,9 +115,9 @@ class UserApiKeysController < ApplicationController
cookies[:destination_url] = request.fullpath
if SiteSetting.enable_discourse_connect?
- redirect_to path('/session/sso')
+ redirect_to path("/session/sso")
else
- redirect_to path('/login')
+ redirect_to path("/login")
end
return
end
@@ -144,7 +143,7 @@ class UserApiKeysController < ApplicationController
def revoke
revoke_key = find_key if params[:id]
- if current_key = request.env['HTTP_USER_API_KEY']
+ if current_key = request.env["HTTP_USER_API_KEY"]
request_key = UserApiKey.with_key(current_key).first
revoke_key ||= request_key
end
@@ -168,13 +167,7 @@ class UserApiKeysController < ApplicationController
end
def require_params
- [
- :public_key,
- :nonce,
- :scopes,
- :client_id,
- :application_name
- ].each { |p| params.require(p) }
+ %i[public_key nonce scopes client_id application_name].each { |p| params.require(p) }
end
def validate_params
@@ -186,11 +179,7 @@ class UserApiKeysController < ApplicationController
end
def require_params_otp
- [
- :public_key,
- :auth_redirect,
- :application_name
- ].each { |p| params.require(p) }
+ %i[public_key auth_redirect application_name].each { |p| params.require(p) }
end
def meets_tl?
@@ -198,7 +187,9 @@ class UserApiKeysController < ApplicationController
end
def one_time_password(public_key, username)
- raise Discourse::InvalidAccess unless UserApiKey.allowed_scopes.superset?(Set.new(["one_time_password"]))
+ unless UserApiKey.allowed_scopes.superset?(Set.new(["one_time_password"]))
+ raise Discourse::InvalidAccess
+ end
otp = SecureRandom.hex
Discourse.redis.setex "otp_#{otp}", 10.minutes, username
diff --git a/app/controllers/user_avatars_controller.rb b/app/controllers/user_avatars_controller.rb
index 7b1ea6afbf7..abf24083139 100644
--- a/app/controllers/user_avatars_controller.rb
+++ b/app/controllers/user_avatars_controller.rb
@@ -1,10 +1,13 @@
# frozen_string_literal: true
class UserAvatarsController < ApplicationController
+ skip_before_action :preload_json,
+ :redirect_to_login_if_required,
+ :check_xhr,
+ :verify_authenticity_token,
+ only: %i[show show_letter show_proxy_letter]
- skip_before_action :preload_json, :redirect_to_login_if_required, :check_xhr, :verify_authenticity_token, only: [:show, :show_letter, :show_proxy_letter]
-
- before_action :apply_cdn_headers, only: [:show, :show_letter, :show_proxy_letter]
+ before_action :apply_cdn_headers, only: %i[show show_letter show_proxy_letter]
def refresh_gravatar
user = User.find_by(username_lower: params[:username].downcase)
@@ -15,17 +18,16 @@ class UserAvatarsController < ApplicationController
user.create_user_avatar(user_id: user.id) unless user.user_avatar
user.user_avatar.update_gravatar!
- gravatar = if user.user_avatar.gravatar_upload_id
- {
- gravatar_upload_id: user.user_avatar.gravatar_upload_id,
- gravatar_avatar_template: User.avatar_template(user.username, user.user_avatar.gravatar_upload_id)
- }
- else
- {
- gravatar_upload_id: nil,
- gravatar_avatar_template: nil
- }
- end
+ gravatar =
+ if user.user_avatar.gravatar_upload_id
+ {
+ gravatar_upload_id: user.user_avatar.gravatar_upload_id,
+ gravatar_avatar_template:
+ User.avatar_template(user.username, user.user_avatar.gravatar_upload_id),
+ }
+ else
+ { gravatar_upload_id: nil, gravatar_avatar_template: nil }
+ end
render json: gravatar
end
@@ -37,7 +39,7 @@ class UserAvatarsController < ApplicationController
def show_proxy_letter
is_asset_path
- if SiteSetting.external_system_avatars_url !~ /^\/letter_avatar_proxy/
+ if SiteSetting.external_system_avatars_url !~ %r{^/letter_avatar_proxy}
raise Discourse::NotFound
end
@@ -48,7 +50,10 @@ class UserAvatarsController < ApplicationController
hijack do
begin
- proxy_avatar("https://avatars.discourse-cdn.com/#{params[:version]}/letter/#{params[:letter]}/#{params[:color]}/#{params[:size]}.png", Time.new(1990, 01, 01))
+ proxy_avatar(
+ "https://avatars.discourse-cdn.com/#{params[:version]}/letter/#{params[:letter]}/#{params[:color]}/#{params[:size]}.png",
+ Time.new(1990, 01, 01),
+ )
rescue OpenURI::HTTPError
render_blank
end
@@ -81,16 +86,13 @@ class UserAvatarsController < ApplicationController
# we need multisite support to keep a single origin pull for CDNs
RailsMultisite::ConnectionManagement.with_hostname(params[:hostname]) do
- hijack do
- show_in_site(params[:hostname])
- end
+ hijack { show_in_site(params[:hostname]) }
end
end
protected
def show_in_site(hostname)
-
username = params[:username].to_s
return render_blank unless user = User.find_by(username_lower: username.downcase)
@@ -99,9 +101,7 @@ class UserAvatarsController < ApplicationController
version = (version || OptimizedImage::VERSION).to_i
# old versions simply get new avatar
- if version > OptimizedImage::VERSION
- return render_blank
- end
+ return render_blank if version > OptimizedImage::VERSION
upload_id = upload_id.to_i
return render_blank unless upload_id > 0
@@ -111,7 +111,13 @@ class UserAvatarsController < ApplicationController
if !Discourse.avatar_sizes.include?(size) && Discourse.store.external?
closest = Discourse.avatar_sizes.to_a.min { |a, b| (size - a).abs <=> (size - b).abs }
- avatar_url = UserAvatar.local_avatar_url(hostname, user.encoded_username(lower: true), upload_id, closest)
+ avatar_url =
+ UserAvatar.local_avatar_url(
+ hostname,
+ user.encoded_username(lower: true),
+ upload_id,
+ closest,
+ )
return redirect_to cdn_path(avatar_url), allow_other_host: true
end
@@ -119,7 +125,13 @@ class UserAvatarsController < ApplicationController
upload ||= user.uploaded_avatar if user.uploaded_avatar_id == upload_id
if user.uploaded_avatar && !upload
- avatar_url = UserAvatar.local_avatar_url(hostname, user.encoded_username(lower: true), user.uploaded_avatar_id, size)
+ avatar_url =
+ UserAvatar.local_avatar_url(
+ hostname,
+ user.encoded_username(lower: true),
+ user.uploaded_avatar_id,
+ size,
+ )
return redirect_to cdn_path(avatar_url), allow_other_host: true
elsif upload && optimized = get_optimized_image(upload, size)
if optimized.local?
@@ -151,10 +163,7 @@ class UserAvatarsController < ApplicationController
PROXY_PATH = Rails.root + "tmp/avatar_proxy"
def proxy_avatar(url, last_modified)
-
- if url[0..1] == "//"
- url = (SiteSetting.force_https ? "https:" : "http:") + url
- end
+ url = (SiteSetting.force_https ? "https:" : "http:") + url if url[0..1] == "//"
sha = Digest::SHA1.hexdigest(url)
filename = "#{sha}#{File.extname(url)}"
@@ -162,13 +171,14 @@ class UserAvatarsController < ApplicationController
unless File.exist? path
FileUtils.mkdir_p PROXY_PATH
- tmp = FileHelper.download(
- url,
- max_file_size: max_file_size,
- tmp_file_name: filename,
- follow_redirect: true,
- read_timeout: 10
- )
+ tmp =
+ FileHelper.download(
+ url,
+ max_file_size: max_file_size,
+ tmp_file_name: filename,
+ follow_redirect: true,
+ read_timeout: 10,
+ )
return render_blank if tmp.nil?
@@ -206,5 +216,4 @@ class UserAvatarsController < ApplicationController
upload.get_optimized_image(size, size)
# TODO decide if we want to detach here
end
-
end
diff --git a/app/controllers/user_badges_controller.rb b/app/controllers/user_badges_controller.rb
index d87504d9a28..1617f55516d 100644
--- a/app/controllers/user_badges_controller.rb
+++ b/app/controllers/user_badges_controller.rb
@@ -6,11 +6,18 @@ class UserBadgesController < ApplicationController
before_action :ensure_badges_enabled
def index
- params.permit [:granted_before, :offset, :username]
+ params.permit %i[granted_before offset username]
badge = fetch_badge_from_params
- user_badges = badge.user_badges.order('granted_at DESC, id DESC').limit(MAX_BADGES)
- user_badges = user_badges.includes(:user, :granted_by, badge: :badge_type, post: :topic, user: [:primary_group, :flair_group])
+ user_badges = badge.user_badges.order("granted_at DESC, id DESC").limit(MAX_BADGES)
+ user_badges =
+ user_badges.includes(
+ :user,
+ :granted_by,
+ badge: :badge_type,
+ post: :topic,
+ user: %i[primary_group flair_group],
+ )
grant_count = nil
@@ -26,33 +33,40 @@ class UserBadgesController < ApplicationController
user_badges_topic_ids = user_badges.map { |user_badge| user_badge.post&.topic_id }.compact
- user_badges = UserBadges.new(user_badges: user_badges,
- username: params[:username],
- grant_count: grant_count)
+ user_badges =
+ UserBadges.new(
+ user_badges: user_badges,
+ username: params[:username],
+ grant_count: grant_count,
+ )
render_serialized(
user_badges,
UserBadgesSerializer,
root: :user_badge_info,
include_long_description: true,
- allowed_user_badge_topic_ids: guardian.can_see_topic_ids(topic_ids: user_badges_topic_ids)
+ allowed_user_badge_topic_ids: guardian.can_see_topic_ids(topic_ids: user_badges_topic_ids),
)
end
def username
params.permit [:grouped]
- user = fetch_user_from_params(include_inactive: current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts))
+ user =
+ fetch_user_from_params(
+ include_inactive:
+ current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts),
+ )
raise Discourse::NotFound unless guardian.can_see_profile?(user)
user_badges = user.user_badges
- if params[:grouped]
- user_badges = user_badges.group(:badge_id).select_for_grouping
- end
+ user_badges = user_badges.group(:badge_id).select_for_grouping if params[:grouped]
- user_badges = user_badges.includes(badge: [:badge_grouping, :badge_type, :image_upload])
- .includes(post: :topic)
- .includes(:granted_by)
+ user_badges =
+ user_badges
+ .includes(badge: %i[badge_grouping badge_type image_upload])
+ .includes(post: :topic)
+ .includes(:granted_by)
user_badges_topic_ids = user_badges.map { |user_badge| user_badge.post&.topic_id }.compact
@@ -68,16 +82,17 @@ class UserBadgesController < ApplicationController
params.require(:username)
user = fetch_user_from_params
- unless can_assign_badge_to_user?(user)
- return render json: failed_json, status: 403
- end
+ return render json: failed_json, status: 403 unless can_assign_badge_to_user?(user)
badge = fetch_badge_from_params
post_id = nil
if params[:reason].present?
unless is_badge_reason_valid? params[:reason]
- return render json: failed_json.merge(message: I18n.t('invalid_grant_badge_reason_link')), status: 400
+ return(
+ render json: failed_json.merge(message: I18n.t("invalid_grant_badge_reason_link")),
+ status: 400
+ )
end
if route = Discourse.route_for(params[:reason])
@@ -112,17 +127,17 @@ class UserBadgesController < ApplicationController
user_badge = UserBadge.find(params[:user_badge_id])
user_badges = user_badge.user.user_badges
- unless can_favorite_badge?(user_badge)
- return render json: failed_json, status: 403
- end
+ return render json: failed_json, status: 403 unless can_favorite_badge?(user_badge)
- if !user_badge.is_favorite && user_badges.select(:badge_id).distinct.where(is_favorite: true).count >= SiteSetting.max_favorite_badges
+ if !user_badge.is_favorite &&
+ user_badges.select(:badge_id).distinct.where(is_favorite: true).count >=
+ SiteSetting.max_favorite_badges
return render json: failed_json, status: 400
end
- UserBadge
- .where(user_id: user_badge.user_id, badge_id: user_badge.badge_id)
- .update_all(is_favorite: !user_badge.is_favorite)
+ UserBadge.where(user_id: user_badge.user_id, badge_id: user_badge.badge_id).update_all(
+ is_favorite: !user_badge.is_favorite,
+ )
UserBadge.update_featured_ranks!(user_badge.user_id)
end
@@ -159,6 +174,6 @@ class UserBadgesController < ApplicationController
def is_badge_reason_valid?(reason)
route = Discourse.route_for(reason)
- route && (route[:controller] == 'posts' || route[:controller] == 'topics')
+ route && (route[:controller] == "posts" || route[:controller] == "topics")
end
end
diff --git a/app/controllers/users/associate_accounts_controller.rb b/app/controllers/users/associate_accounts_controller.rb
index 9f12727b944..371cfbf58c4 100644
--- a/app/controllers/users/associate_accounts_controller.rb
+++ b/app/controllers/users/associate_accounts_controller.rb
@@ -9,11 +9,11 @@ class Users::AssociateAccountsController < ApplicationController
account_description = authenticator.description_for_auth_hash(auth_hash)
existing_account_description = authenticator.description_for_user(current_user).presence
render json: {
- token: params[:token],
- provider_name: auth_hash.provider,
- account_description: account_description,
- existing_account_description: existing_account_description
- }
+ token: params[:token],
+ provider_name: auth_hash.provider,
+ account_description: account_description,
+ existing_account_description: existing_account_description,
+ }
end
def connect
@@ -33,20 +33,23 @@ class Users::AssociateAccountsController < ApplicationController
private
def auth_hash
- @auth_hash ||= begin
- token = params[:token]
- json = secure_session[self.class.key(token)]
- raise Discourse::NotFound if json.nil?
+ @auth_hash ||=
+ begin
+ token = params[:token]
+ json = secure_session[self.class.key(token)]
+ raise Discourse::NotFound if json.nil?
- OmniAuth::AuthHash.new(JSON.parse(json))
- end
+ OmniAuth::AuthHash.new(JSON.parse(json))
+ end
end
def authenticator
provider_name = auth_hash.provider
authenticator = Discourse.enabled_authenticators.find { |a| a.name == provider_name }
- raise Discourse::InvalidAccess.new(I18n.t('authenticator_not_found')) if authenticator.nil?
- raise Discourse::InvalidAccess.new(I18n.t('authenticator_no_connect')) if !authenticator.can_connect_existing_user?
+ raise Discourse::InvalidAccess.new(I18n.t("authenticator_not_found")) if authenticator.nil?
+ if !authenticator.can_connect_existing_user?
+ raise Discourse::InvalidAccess.new(I18n.t("authenticator_no_connect"))
+ end
authenticator
end
diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb
index 3634d2f4c0d..673db129c48 100644
--- a/app/controllers/users/omniauth_callbacks_controller.rb
+++ b/app/controllers/users/omniauth_callbacks_controller.rb
@@ -2,10 +2,9 @@
# frozen_string_literal: true
class Users::OmniauthCallbacksController < ApplicationController
-
skip_before_action :redirect_to_login_if_required
- layout 'no_ember'
+ layout "no_ember"
# need to be able to call this
skip_before_action :check_xhr
@@ -40,7 +39,7 @@ class Users::OmniauthCallbacksController < ApplicationController
DiscourseEvent.trigger(:after_auth, authenticator, @auth_result, session, cookies, request)
end
- preferred_origin = request.env['omniauth.origin']
+ preferred_origin = request.env["omniauth.origin"]
if session[:destination_url].present?
preferred_origin = session[:destination_url]
@@ -53,10 +52,11 @@ class Users::OmniauthCallbacksController < ApplicationController
end
if preferred_origin.present?
- parsed = begin
- URI.parse(preferred_origin)
- rescue URI::Error
- end
+ parsed =
+ begin
+ URI.parse(preferred_origin)
+ rescue URI::Error
+ end
if valid_origin?(parsed)
@origin = +"#{parsed.path}"
@@ -64,9 +64,7 @@ class Users::OmniauthCallbacksController < ApplicationController
end
end
- if @origin.blank?
- @origin = Discourse.base_path("/")
- end
+ @origin = Discourse.base_path("/") if @origin.blank?
@auth_result.destination_url = @origin
@auth_result.authenticator_name = authenticator.name
@@ -81,16 +79,13 @@ class Users::OmniauthCallbacksController < ApplicationController
client_hash = @auth_result.to_client_hash
if authenticator.can_connect_existing_user? &&
- (SiteSetting.enable_local_logins || Discourse.enabled_authenticators.count > 1)
+ (SiteSetting.enable_local_logins || Discourse.enabled_authenticators.count > 1)
# There is more than one login method, and users are allowed to manage associations themselves
client_hash[:associate_url] = persist_auth_token(auth)
end
- cookies['_bypass_cache'] = true
- cookies[:authentication_data] = {
- value: client_hash.to_json,
- path: Discourse.base_path("/")
- }
+ cookies["_bypass_cache"] = true
+ cookies[:authentication_data] = { value: client_hash.to_json, path: Discourse.base_path("/") }
redirect_to @origin
end
@@ -108,24 +103,24 @@ class Users::OmniauthCallbacksController < ApplicationController
flash[:error] = I18n.t(
"login.omniauth_error.#{error_key}",
- default: I18n.t("login.omniauth_error.generic")
+ default: I18n.t("login.omniauth_error.generic"),
).html_safe
- render 'failure'
+ render "failure"
end
def self.find_authenticator(name)
Discourse.enabled_authenticators.each do |authenticator|
return authenticator if authenticator.name == name
end
- raise Discourse::InvalidAccess.new(I18n.t('authenticator_not_found'))
+ raise Discourse::InvalidAccess.new(I18n.t("authenticator_not_found"))
end
protected
def render_auth_result_failure
flash[:error] = @auth_result.failed_reason.html_safe
- render 'failure'
+ render "failure"
end
def complete_response_data
@@ -160,13 +155,16 @@ class Users::OmniauthCallbacksController < ApplicationController
user.update!(password: SecureRandom.hex)
# Ensure there is an active email token
- if !EmailToken.where(email: user.email, confirmed: true).exists? && !user.email_tokens.active.where(email: user.email).exists?
+ if !EmailToken.where(email: user.email, confirmed: true).exists? &&
+ !user.email_tokens.active.where(email: user.email).exists?
user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:signup])
end
user.activate
end
- user.update!(registration_ip_address: request.remote_ip) if user.registration_ip_address.blank?
+ if user.registration_ip_address.blank?
+ user.update!(registration_ip_address: request.remote_ip)
+ end
end
if ScreenedIpAddress.should_block?(request.remote_ip)
@@ -198,7 +196,9 @@ class Users::OmniauthCallbacksController < ApplicationController
def persist_auth_token(auth)
secret = SecureRandom.hex
- secure_session.set "#{Users::AssociateAccountsController.key(secret)}", auth.to_json, expires: 10.minutes
+ secure_session.set "#{Users::AssociateAccountsController.key(secret)}",
+ auth.to_json,
+ expires: 10.minutes
"#{Discourse.base_path}/associate/#{secret}"
end
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index f7debba7844..23032ada602 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -3,29 +3,72 @@
class UsersController < ApplicationController
skip_before_action :authorize_mini_profiler, only: [:avatar]
- requires_login only: [
- :username, :update, :upload_user_image,
- :pick_avatar, :destroy_user_image, :destroy, :check_emails,
- :topic_tracking_state, :preferences, :create_second_factor_totp,
- :enable_second_factor_totp, :disable_second_factor, :list_second_factors,
- :update_second_factor, :create_second_factor_backup, :select_avatar,
- :notification_level, :revoke_auth_token, :register_second_factor_security_key,
- :create_second_factor_security_key, :feature_topic, :clear_featured_topic,
- :bookmarks, :invited, :check_sso_email, :check_sso_payload,
- :recent_searches, :reset_recent_searches, :user_menu_bookmarks, :user_menu_messages
- ]
+ requires_login only: %i[
+ username
+ update
+ upload_user_image
+ pick_avatar
+ destroy_user_image
+ destroy
+ check_emails
+ topic_tracking_state
+ preferences
+ create_second_factor_totp
+ enable_second_factor_totp
+ disable_second_factor
+ list_second_factors
+ update_second_factor
+ create_second_factor_backup
+ select_avatar
+ notification_level
+ revoke_auth_token
+ register_second_factor_security_key
+ create_second_factor_security_key
+ feature_topic
+ clear_featured_topic
+ bookmarks
+ invited
+ check_sso_email
+ check_sso_payload
+ recent_searches
+ reset_recent_searches
+ user_menu_bookmarks
+ user_menu_messages
+ ]
- skip_before_action :check_xhr, only: [
- :show, :badges, :password_reset_show, :password_reset_update, :update, :account_created,
- :activate_account, :perform_account_activation, :avatar,
- :my_redirect, :toggle_anon, :admin_login, :confirm_admin, :email_login, :summary,
- :feature_topic, :clear_featured_topic, :bookmarks, :user_menu_bookmarks, :user_menu_messages
- ]
+ skip_before_action :check_xhr,
+ only: %i[
+ show
+ badges
+ password_reset_show
+ password_reset_update
+ update
+ account_created
+ activate_account
+ perform_account_activation
+ avatar
+ my_redirect
+ toggle_anon
+ admin_login
+ confirm_admin
+ email_login
+ summary
+ feature_topic
+ clear_featured_topic
+ bookmarks
+ user_menu_bookmarks
+ user_menu_messages
+ ]
- before_action :second_factor_check_confirmed_password, only: [
- :create_second_factor_totp, :enable_second_factor_totp,
- :disable_second_factor, :update_second_factor, :create_second_factor_backup,
- :register_second_factor_security_key, :create_second_factor_security_key
+ before_action :second_factor_check_confirmed_password,
+ only: %i[
+ create_second_factor_totp
+ enable_second_factor_totp
+ disable_second_factor
+ update_second_factor
+ create_second_factor_backup
+ register_second_factor_security_key
+ create_second_factor_security_key
]
before_action :respond_to_suspicious_request, only: [:create]
@@ -34,22 +77,25 @@ class UsersController < ApplicationController
# page is going to be empty, this means that server will see an invalid CSRF and blow the session
# once that happens you can't log in with social
skip_before_action :verify_authenticity_token, only: [:create]
- skip_before_action :redirect_to_login_if_required, only: [:check_username,
- :check_email,
- :create,
- :account_created,
- :activate_account,
- :perform_account_activation,
- :send_activation_email,
- :update_activation_email,
- :password_reset_show,
- :password_reset_update,
- :confirm_email_token,
- :email_login,
- :admin_login,
- :confirm_admin]
+ skip_before_action :redirect_to_login_if_required,
+ only: %i[
+ check_username
+ check_email
+ create
+ account_created
+ activate_account
+ perform_account_activation
+ send_activation_email
+ update_activation_email
+ password_reset_show
+ password_reset_update
+ confirm_email_token
+ email_login
+ admin_login
+ confirm_admin
+ ]
- after_action :add_noindex_header, only: [:show, :my_redirect]
+ after_action :add_noindex_header, only: %i[show my_redirect]
allow_in_staff_writes_only_mode :admin_login
allow_in_staff_writes_only_mode :email_login
@@ -60,32 +106,34 @@ class UsersController < ApplicationController
end
def show(for_card: false)
- return redirect_to path('/login') if SiteSetting.hide_user_profiles_from_public && !current_user
+ return redirect_to path("/login") if SiteSetting.hide_user_profiles_from_public && !current_user
- @user = fetch_user_from_params(
- include_inactive: current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts)
- )
+ @user =
+ fetch_user_from_params(
+ include_inactive:
+ current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts),
+ )
user_serializer = nil
if guardian.can_see_profile?(@user)
serializer_class = for_card ? UserCardSerializer : UserSerializer
- user_serializer = serializer_class.new(@user, scope: guardian, root: 'user')
+ user_serializer = serializer_class.new(@user, scope: guardian, root: "user")
topic_id = params[:include_post_count_for].to_i
if topic_id != 0 && guardian.can_see?(Topic.find_by_id(topic_id))
- user_serializer.topic_post_count = { topic_id => Post.secured(guardian).where(topic_id: topic_id, user_id: @user.id).count }
+ user_serializer.topic_post_count = {
+ topic_id => Post.secured(guardian).where(topic_id: topic_id, user_id: @user.id).count,
+ }
end
else
- user_serializer = HiddenProfileSerializer.new(@user, scope: guardian, root: 'user')
+ user_serializer = HiddenProfileSerializer.new(@user, scope: guardian, root: "user")
end
- if !params[:skip_track_visit] && (@user != current_user)
- track_visit_to_user_profile
- end
+ track_visit_to_user_profile if !params[:skip_track_visit] && (@user != current_user)
# This is a hack to get around a Rails issue where values with periods aren't handled correctly
# when used as part of a route.
- if params[:external_id] && params[:external_id].ends_with?('.json')
+ if params[:external_id] && params[:external_id].ends_with?(".json")
return render_json_dump(user_serializer)
end
@@ -96,9 +144,7 @@ class UsersController < ApplicationController
render :show
end
- format.json do
- render_json_dump(user_serializer)
- end
+ format.json { render_json_dump(user_serializer) }
end
end
@@ -108,25 +154,29 @@ class UsersController < ApplicationController
# This route is not used in core, but is used by theme components (e.g. https://meta.discourse.org/t/144479)
def cards
- return redirect_to path('/login') if SiteSetting.hide_user_profiles_from_public && !current_user
+ return redirect_to path("/login") if SiteSetting.hide_user_profiles_from_public && !current_user
user_ids = params.require(:user_ids).split(",").map(&:to_i)
raise Discourse::InvalidParameters.new(:user_ids) if user_ids.length > 50
- users = User.where(id: user_ids).includes(:user_option,
- :user_stat,
- :default_featured_user_badges,
- :user_profile,
- :card_background_upload,
- :primary_group,
- :flair_group,
- :primary_email,
- :user_status
- )
+ users =
+ User.where(id: user_ids).includes(
+ :user_option,
+ :user_stat,
+ :default_featured_user_badges,
+ :user_profile,
+ :card_background_upload,
+ :primary_group,
+ :flair_group,
+ :primary_email,
+ :user_status,
+ )
users = users.filter { |u| guardian.can_see_profile?(u) }
- preload_fields = User.allowed_user_custom_fields(guardian) + UserField.all.pluck(:id).map { |fid| "#{User::USER_FIELD_PREFIX}#{fid}" }
+ preload_fields =
+ User.allowed_user_custom_fields(guardian) +
+ UserField.all.pluck(:id).map { |fid| "#{User::USER_FIELD_PREFIX}#{fid}" }
User.preload_custom_fields(users, preload_fields)
User.preload_recent_time_read(users)
@@ -159,7 +209,9 @@ class UsersController < ApplicationController
value = nil if value === "false"
value = value[0...UserField.max_length] if value
- return render_json_error(I18n.t("login.missing_user_field")) if value.blank? && field.required?
+ if value.blank? && field.required?
+ return render_json_error(I18n.t("login.missing_user_field"))
+ end
attributes[:custom_fields]["#{User::USER_FIELD_PREFIX}#{field.id}"] = value
end
end
@@ -168,8 +220,10 @@ class UsersController < ApplicationController
attributes[:user_associated_accounts] = []
params[:external_ids].each do |provider_name, provider_uid|
- if provider_name == 'discourse_connect'
- raise Discourse::InvalidParameters.new(:external_ids) unless SiteSetting.enable_discourse_connect
+ if provider_name == "discourse_connect"
+ unless SiteSetting.enable_discourse_connect
+ raise Discourse::InvalidParameters.new(:external_ids)
+ end
attributes[:discourse_connect] = { external_id: provider_uid }
@@ -179,11 +233,18 @@ class UsersController < ApplicationController
authenticator = Discourse.enabled_authenticators.find { |a| a.name == provider_name }
raise Discourse::InvalidParameters.new(:external_ids) if !authenticator&.is_managed?
- attributes[:user_associated_accounts] << { provider_name: provider_name, provider_uid: provider_uid }
+ attributes[:user_associated_accounts] << {
+ provider_name: provider_name,
+ provider_uid: provider_uid,
+ }
end
end
- json_result(user, serializer: UserSerializer, additional_errors: [:user_profile, :user_option]) do |u|
+ json_result(
+ user,
+ serializer: UserSerializer,
+ additional_errors: %i[user_profile user_option],
+ ) do |u|
updater = UserUpdater.new(current_user, user)
updater.update(attributes.permit!)
end
@@ -192,7 +253,8 @@ class UsersController < ApplicationController
def username
params.require(:new_username)
- if clashing_with_existing_route?(params[:new_username]) || User.reserved_username?(params[:new_username])
+ if clashing_with_existing_route?(params[:new_username]) ||
+ User.reserved_username?(params[:new_username])
return render_json_error(I18n.t("login.reserved_username"))
end
@@ -204,11 +266,11 @@ class UsersController < ApplicationController
if result
render json: { id: user.id, username: user.username }
else
- render_json_error(user.errors.full_messages.join(','))
+ render_json_error(user.errors.full_messages.join(","))
end
rescue Discourse::InvalidAccess
if current_user&.staff?
- render_json_error(I18n.t('errors.messages.auth_overrides_username'))
+ render_json_error(I18n.t("errors.messages.auth_overrides_username"))
else
render json: failed_json, status: 403
end
@@ -226,11 +288,11 @@ class UsersController < ApplicationController
unconfirmed_emails = user.unconfirmed_emails
render json: {
- email: email,
- secondary_emails: secondary_emails,
- unconfirmed_emails: unconfirmed_emails,
- associated_accounts: user.associated_accounts
- }
+ email: email,
+ secondary_emails: secondary_emails,
+ unconfirmed_emails: unconfirmed_emails,
+ associated_accounts: user.associated_accounts,
+ }
rescue Discourse::InvalidAccess
render json: failed_json, status: 403
end
@@ -268,9 +330,7 @@ class UsersController < ApplicationController
end
def update_primary_email
- if !SiteSetting.enable_secondary_emails
- return render json: failed_json, status: 410
- end
+ return render json: failed_json, status: 410 if !SiteSetting.enable_secondary_emails
params.require(:email)
@@ -278,13 +338,13 @@ class UsersController < ApplicationController
guardian.ensure_can_edit_email!(user)
old_primary = user.primary_email
- if old_primary.email == params[:email]
- return render json: success_json
- end
+ return render json: success_json if old_primary.email == params[:email]
new_primary = user.user_emails.find_by(email: params[:email])
if new_primary.blank?
- return render json: failed_json.merge(errors: [I18n.t("change_email.doesnt_exist")]), status: 428
+ return(
+ render json: failed_json.merge(errors: [I18n.t("change_email.doesnt_exist")]), status: 428
+ )
end
User.transaction do
@@ -303,9 +363,7 @@ class UsersController < ApplicationController
end
def destroy_email
- if !SiteSetting.enable_secondary_emails
- return render json: failed_json, status: 410
- end
+ return render json: failed_json, status: 410 if !SiteSetting.enable_secondary_emails
params.require(:email)
@@ -336,9 +394,12 @@ class UsersController < ApplicationController
guardian.ensure_can_edit!(user)
report = TopicTrackingState.report(user)
- serializer = ActiveModel::ArraySerializer.new(
- report, each_serializer: TopicTrackingStateSerializer, scope: guardian
- )
+ serializer =
+ ActiveModel::ArraySerializer.new(
+ report,
+ each_serializer: TopicTrackingStateSerializer,
+ scope: guardian,
+ )
render json: MultiJson.dump(serializer)
end
@@ -349,11 +410,12 @@ class UsersController < ApplicationController
report = PrivateMessageTopicTrackingState.report(user)
- serializer = ActiveModel::ArraySerializer.new(
- report,
- each_serializer: PrivateMessageTopicTrackingStateSerializer,
- scope: guardian
- )
+ serializer =
+ ActiveModel::ArraySerializer.new(
+ report,
+ each_serializer: PrivateMessageTopicTrackingStateSerializer,
+ scope: guardian,
+ )
render json: MultiJson.dump(serializer)
end
@@ -373,28 +435,33 @@ class UsersController < ApplicationController
log_params = {
details: "title matching badge id #{user_badge.badge.id}",
previous_value: previous_title,
- new_value: user.title
+ new_value: user.title,
}
if current_user.staff? && current_user != user
StaffActionLogger.new(current_user).log_title_change(user, log_params)
else
- UserHistory.create!(log_params.merge(target_user_id: user.id, action: UserHistory.actions[:change_title]))
+ UserHistory.create!(
+ log_params.merge(target_user_id: user.id, action: UserHistory.actions[:change_title]),
+ )
end
else
- user.title = ''
+ user.title = ""
user.save!
- log_params = {
- previous_value: previous_title
- }
+ log_params = { previous_value: previous_title }
if current_user.staff? && current_user != user
- StaffActionLogger
- .new(current_user)
- .log_title_revoke(user, log_params.merge(revoke_reason: 'user title was same as revoked badge name or custom badge name'))
+ StaffActionLogger.new(current_user).log_title_revoke(
+ user,
+ log_params.merge(
+ revoke_reason: "user title was same as revoked badge name or custom badge name",
+ ),
+ )
else
- UserHistory.create!(log_params.merge(target_user_id: user.id, action: UserHistory.actions[:revoke_title]))
+ UserHistory.create!(
+ log_params.merge(target_user_id: user.id, action: UserHistory.actions[:revoke_title]),
+ )
end
end
@@ -406,7 +473,7 @@ class UsersController < ApplicationController
end
def my_redirect
- raise Discourse::NotFound if params[:path] !~ /^[a-z_\-\/]+$/
+ raise Discourse::NotFound if params[:path] !~ %r{^[a-z_\-/]+$}
if current_user.blank?
cookies[:destination_url] = path("/my/#{params[:path]}")
@@ -421,10 +488,14 @@ class UsersController < ApplicationController
end
def summary
- @user = fetch_user_from_params(include_inactive: current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts))
+ @user =
+ fetch_user_from_params(
+ include_inactive:
+ current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts),
+ )
raise Discourse::NotFound unless guardian.can_see_profile?(@user)
- response.headers['X-Robots-Tag'] = 'noindex'
+ response.headers["X-Robots-Tag"] = "noindex"
respond_to do |format|
format.html do
@@ -432,11 +503,14 @@ class UsersController < ApplicationController
render :show
end
format.json do
- summary_json = Discourse.cache.fetch(summary_cache_key(@user), expires_in: 1.hour) do
- summary = UserSummary.new(@user, guardian)
- serializer = UserSummarySerializer.new(summary, scope: guardian)
- MultiJson.dump(serializer)
- end
+ summary_json =
+ Discourse
+ .cache
+ .fetch(summary_cache_key(@user), expires_in: 1.hour) do
+ summary = UserSummary.new(@user, guardian)
+ serializer = UserSummarySerializer.new(summary, scope: guardian)
+ MultiJson.dump(serializer)
+ end
render json: summary_json
end
end
@@ -445,24 +519,29 @@ class UsersController < ApplicationController
def invited
if guardian.can_invite_to_forum?
filter = params[:filter] || "redeemed"
- inviter = fetch_user_from_params(include_inactive: current_user.staff? || SiteSetting.show_inactive_accounts)
+ inviter =
+ fetch_user_from_params(
+ include_inactive: current_user.staff? || SiteSetting.show_inactive_accounts,
+ )
- invites = if filter == "pending" && guardian.can_see_invite_details?(inviter)
- Invite.includes(:topics, :groups).pending(inviter)
- elsif filter == "expired"
- Invite.expired(inviter)
- elsif filter == "redeemed"
- Invite.redeemed_users(inviter)
- else
- Invite.none
- end
+ invites =
+ if filter == "pending" && guardian.can_see_invite_details?(inviter)
+ Invite.includes(:topics, :groups).pending(inviter)
+ elsif filter == "expired"
+ Invite.expired(inviter)
+ elsif filter == "redeemed"
+ Invite.redeemed_users(inviter)
+ else
+ Invite.none
+ end
invites = invites.offset(params[:offset].to_i || 0).limit(SiteSetting.invites_per_page)
show_emails = guardian.can_see_invite_emails?(inviter)
if params[:search].present? && invites.present?
- filter_sql = '(LOWER(users.username) LIKE :filter)'
- filter_sql = '(LOWER(invites.email) LIKE :filter) or (LOWER(users.username) LIKE :filter)' if show_emails
+ filter_sql = "(LOWER(users.username) LIKE :filter)"
+ filter_sql =
+ "(LOWER(invites.email) LIKE :filter) or (LOWER(users.username) LIKE :filter)" if show_emails
invites = invites.where(filter_sql, filter: "%#{params[:search].downcase}%")
end
@@ -470,26 +549,30 @@ class UsersController < ApplicationController
expired_count = Invite.expired(inviter).reorder(nil).count.to_i
redeemed_count = Invite.redeemed_users(inviter).reorder(nil).count.to_i
- render json: MultiJson.dump(InvitedSerializer.new(
- OpenStruct.new(
- invite_list: invites.to_a,
- show_emails: show_emails,
- inviter: inviter,
- type: filter,
- counts: {
- pending: pending_count,
- expired: expired_count,
- redeemed: redeemed_count,
- total: pending_count + expired_count
- }
- ),
- scope: guardian,
- root: false
- ))
+ render json:
+ MultiJson.dump(
+ InvitedSerializer.new(
+ OpenStruct.new(
+ invite_list: invites.to_a,
+ show_emails: show_emails,
+ inviter: inviter,
+ type: filter,
+ counts: {
+ pending: pending_count,
+ expired: expired_count,
+ redeemed: redeemed_count,
+ total: pending_count + expired_count,
+ },
+ ),
+ scope: guardian,
+ root: false,
+ ),
+ )
elsif current_user&.staff?
- message = if SiteSetting.enable_discourse_connect
- I18n.t("invite.disabled_errors.discourse_connect_enabled")
- end
+ message =
+ if SiteSetting.enable_discourse_connect
+ I18n.t("invite.disabled_errors.discourse_connect_enabled")
+ end
render_invite_error(message)
else
@@ -533,27 +616,25 @@ class UsersController < ApplicationController
email = Email.downcase((params[:email] || "").strip)
- if email.blank? || SiteSetting.hide_email_address_taken?
- return render json: success_json
- end
+ return render json: success_json if email.blank? || SiteSetting.hide_email_address_taken?
if !EmailAddressValidator.valid_value?(email)
- error = User.new.errors.full_message(:email, I18n.t(:'user.email.invalid'))
+ error = User.new.errors.full_message(:email, I18n.t(:"user.email.invalid"))
return render json: failed_json.merge(errors: [error])
end
if !EmailValidator.allowed?(email)
- error = User.new.errors.full_message(:email, I18n.t(:'user.email.not_allowed'))
+ error = User.new.errors.full_message(:email, I18n.t(:"user.email.not_allowed"))
return render json: failed_json.merge(errors: [error])
end
if ScreenedEmail.should_block?(email)
- error = User.new.errors.full_message(:email, I18n.t(:'user.email.blocked'))
+ error = User.new.errors.full_message(:email, I18n.t(:"user.email.blocked"))
return render json: failed_json.merge(errors: [error])
end
if User.where(staged: false).find_by_email(email).present?
- error = User.new.errors.full_message(:email, I18n.t(:'errors.messages.taken'))
+ error = User.new.errors.full_message(:email, I18n.t(:"errors.messages.taken"))
return render json: failed_json.merge(errors: [error])
end
@@ -571,23 +652,21 @@ class UsersController < ApplicationController
params.permit(:user_fields)
params.permit(:external_ids)
- unless SiteSetting.allow_new_registrations
- return fail_with("login.new_registrations_disabled")
- end
+ return fail_with("login.new_registrations_disabled") unless SiteSetting.allow_new_registrations
if params[:password] && params[:password].length > User.max_password_length
return fail_with("login.password_too_long")
end
- if params[:email].length > 254 + 1 + 253
- return fail_with("login.email_too_long")
- end
+ return fail_with("login.email_too_long") if params[:email].length > 254 + 1 + 253
- if SiteSetting.require_invite_code && SiteSetting.invite_code.strip.downcase != params[:invite_code].strip.downcase
+ if SiteSetting.require_invite_code &&
+ SiteSetting.invite_code.strip.downcase != params[:invite_code].strip.downcase
return fail_with("login.wrong_invite_code")
end
- if clashing_with_existing_route?(params[:username]) || User.reserved_username?(params[:username])
+ if clashing_with_existing_route?(params[:username]) ||
+ User.reserved_username?(params[:username])
return fail_with("login.reserved_username")
end
@@ -636,14 +715,19 @@ class UsersController < ApplicationController
authenticator = Discourse.enabled_authenticators.find { |a| a.name == provider_name }
raise Discourse::InvalidParameters.new(:external_ids) if !authenticator&.is_managed?
- association = UserAssociatedAccount.find_or_initialize_by(provider_name: provider_name, provider_uid: provider_uid)
+ association =
+ UserAssociatedAccount.find_or_initialize_by(
+ provider_name: provider_name,
+ provider_uid: provider_uid,
+ )
associations << association
end
end
authentication = UserAuthenticator.new(user, session)
- if !authentication.has_authenticator? && !SiteSetting.enable_local_logins && !(current_user&.admin? && is_api?)
+ if !authentication.has_authenticator? && !SiteSetting.enable_local_logins &&
+ !(current_user&.admin? && is_api?)
return render body: nil, status: :forbidden
end
@@ -651,7 +735,7 @@ class UsersController < ApplicationController
if authentication.email_valid? && !authentication.authenticated?
# posted email is different that the already validated one?
- return fail_with('login.incorrect_username_email_or_password')
+ return fail_with("login.incorrect_username_email_or_password")
end
activation = UserActivator.new(user, request, session, cookies)
@@ -659,7 +743,8 @@ class UsersController < ApplicationController
# just assign a password if we have an authenticator and no password
# this is the case for Twitter
- user.password = SecureRandom.hex if user.password.blank? && (authentication.has_authenticator? || associations.present?)
+ user.password = SecureRandom.hex if user.password.blank? &&
+ (authentication.has_authenticator? || associations.present?)
if user.save
authentication.finish
@@ -679,47 +764,36 @@ class UsersController < ApplicationController
# add them to the review queue if they need to be approved
user.activate if user.active?
- render json: {
- success: true,
- active: user.active?,
- message: activation.message,
- }.merge(SiteSetting.hide_email_address_taken ? {} : { user_id: user.id })
- elsif SiteSetting.hide_email_address_taken && user.errors[:primary_email]&.include?(I18n.t('errors.messages.taken'))
+ render json: { success: true, active: user.active?, message: activation.message }.merge(
+ SiteSetting.hide_email_address_taken ? {} : { user_id: user.id },
+ )
+ elsif SiteSetting.hide_email_address_taken &&
+ user.errors[:primary_email]&.include?(I18n.t("errors.messages.taken"))
session["user_created_message"] = activation.success_message
if existing_user = User.find_by_email(user.primary_email&.email)
Jobs.enqueue(:critical_user_email, type: "account_exists", user_id: existing_user.id)
end
- render json: {
- success: true,
- active: false,
- message: activation.success_message
- }
+ render json: { success: true, active: false, message: activation.success_message }
else
errors = user.errors.to_hash
errors[:email] = errors.delete(:primary_email) if errors[:primary_email]
render json: {
- success: false,
- message: I18n.t(
- 'login.errors',
- errors: user.errors.full_messages.join("\n")
- ),
- errors: errors,
- values: {
- name: user.name,
- username: user.username,
- email: user.primary_email&.email
- },
- is_developer: UsernameCheckerService.is_developer?(user.email)
- }
+ success: false,
+ message: I18n.t("login.errors", errors: user.errors.full_messages.join("\n")),
+ errors: errors,
+ values: {
+ name: user.name,
+ username: user.username,
+ email: user.primary_email&.email,
+ },
+ is_developer: UsernameCheckerService.is_developer?(user.email),
+ }
end
rescue ActiveRecord::StatementInvalid
- render json: {
- success: false,
- message: I18n.t("login.something_already_taken")
- }
+ render json: { success: false, message: I18n.t("login.something_already_taken") }
end
def password_reset_show
@@ -735,21 +809,23 @@ class UsersController < ApplicationController
second_factor_required: @user.totp_enabled?,
security_key_required: @user.security_keys_enabled?,
backup_enabled: @user.backup_codes_enabled?,
- multiple_second_factor_methods: @user.has_multiple_second_factor_methods?
+ multiple_second_factor_methods: @user.has_multiple_second_factor_methods?,
}
end
respond_to do |format|
format.html do
- return render 'password_reset', layout: 'no_ember' if @error
+ return render "password_reset", layout: "no_ember" if @error
Webauthn.stage_challenge(@user, secure_session)
store_preloaded(
"password_reset",
- MultiJson.dump(security_params.merge(Webauthn.allowed_credentials(@user, secure_session)))
+ MultiJson.dump(
+ security_params.merge(Webauthn.allowed_credentials(@user, secure_session)),
+ ),
)
- render 'password_reset'
+ render "password_reset"
end
format.json do
@@ -772,13 +848,20 @@ class UsersController < ApplicationController
# a user from the token
if @user
if !secure_session["second-factor-#{token}"]
- second_factor_authentication_result = @user.authenticate_second_factor(params, secure_session)
+ second_factor_authentication_result =
+ @user.authenticate_second_factor(params, secure_session)
if !second_factor_authentication_result.ok
- user_error_key = second_factor_authentication_result.reason == "invalid_security_key" ? :user_second_factors : :security_keys
+ user_error_key =
+ (
+ if second_factor_authentication_result.reason == "invalid_security_key"
+ :user_second_factors
+ else
+ :security_keys
+ end
+ )
@user.errors.add(user_error_key, :invalid)
@error = second_factor_authentication_result.error
else
-
# this must be set because the first call we authenticate e.g. TOTP, and we do
# not want to re-authenticate on the second call to change the password as this
# will cause a TOTP error saying the code has already been used
@@ -786,7 +869,8 @@ class UsersController < ApplicationController
end
end
- if @invalid_password = params[:password].blank? || params[:password].size > User.max_password_length
+ if @invalid_password =
+ params[:password].blank? || params[:password].size > User.max_password_length
@user.errors.add(:password, :invalid)
end
@@ -804,7 +888,7 @@ class UsersController < ApplicationController
UserHistory.create!(
target_user: @user,
acting_user: @user,
- action: UserHistory.actions[:change_password]
+ action: UserHistory.actions[:change_password],
)
logon_after_password_reset
end
@@ -813,7 +897,7 @@ class UsersController < ApplicationController
respond_to do |format|
format.html do
- return render 'password_reset', layout: 'no_ember' if @error
+ return render "password_reset", layout: "no_ember" if @error
Webauthn.stage_challenge(@user, secure_session)
@@ -823,32 +907,32 @@ class UsersController < ApplicationController
second_factor_required: @user.totp_enabled?,
security_key_required: @user.security_keys_enabled?,
backup_enabled: @user.backup_codes_enabled?,
- multiple_second_factor_methods: @user.has_multiple_second_factor_methods?
+ multiple_second_factor_methods: @user.has_multiple_second_factor_methods?,
}.merge(Webauthn.allowed_credentials(@user, secure_session))
store_preloaded("password_reset", MultiJson.dump(security_params))
return redirect_to(wizard_path) if Wizard.user_requires_completion?(@user)
- render 'password_reset'
+ render "password_reset"
end
format.json do
if @error || @user&.errors&.any?
render json: {
- success: false,
- message: @error,
- errors: @user&.errors&.to_hash,
- is_developer: UsernameCheckerService.is_developer?(@user&.email),
- admin: @user&.admin?
- }
+ success: false,
+ message: @error,
+ errors: @user&.errors&.to_hash,
+ is_developer: UsernameCheckerService.is_developer?(@user&.email),
+ admin: @user&.admin?,
+ }
else
render json: {
- success: true,
- message: @success,
- requires_approval: !Guardian.new(@user).can_access_forum?,
- redirect_to: Wizard.user_requires_completion?(@user) ? wizard_path : nil
- }
+ success: true,
+ message: @success,
+ requires_approval: !Guardian.new(@user).can_access_forum?,
+ redirect_to: Wizard.user_requires_completion?(@user) ? wizard_path : nil,
+ }
end
end
end
@@ -865,10 +949,10 @@ class UsersController < ApplicationController
if Guardian.new(@user).can_access_forum?
# Log in the user
log_on_user(@user)
- 'password_reset.success'
+ "password_reset.success"
else
@requires_approval = true
- 'password_reset.success_unapproved'
+ "password_reset.success_unapproved"
end
@success = I18n.t(message)
@@ -882,22 +966,26 @@ class UsersController < ApplicationController
RateLimiter.new(nil, "admin-login-min-#{request.remote_ip}", 3, 1.minute).performed!
if user = User.with_email(params[:email]).admins.human_users.first
- email_token = user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:email_login])
+ email_token =
+ user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:email_login])
token_string = email_token.token
- if params["use_safe_mode"]
- token_string += "?safe_mode=no_plugins,no_themes"
- end
- Jobs.enqueue(:critical_user_email, type: "admin_login", user_id: user.id, email_token: token_string)
+ token_string += "?safe_mode=no_plugins,no_themes" if params["use_safe_mode"]
+ Jobs.enqueue(
+ :critical_user_email,
+ type: "admin_login",
+ user_id: user.id,
+ email_token: token_string,
+ )
@message = I18n.t("admin_login.success")
else
@message = I18n.t("admin_login.errors.unknown_email_address")
end
end
- render layout: 'no_ember'
+ render layout: "no_ember"
rescue RateLimiter::LimitExceeded
@message = I18n.t("rate_limiter.slow_down")
- render layout: 'no_ember'
+ render layout: "no_ember"
end
def email_login
@@ -919,12 +1007,14 @@ class UsersController < ApplicationController
if user_presence
DiscourseEvent.trigger(:before_email_login, user)
- email_token = user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:email_login])
+ email_token =
+ user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:email_login])
- Jobs.enqueue(:critical_user_email,
+ Jobs.enqueue(
+ :critical_user_email,
type: "email_login",
user_id: user.id,
- email_token: email_token.token
+ email_token: email_token.token,
)
end
end
@@ -938,8 +1028,8 @@ class UsersController < ApplicationController
end
def toggle_anon
- user = AnonymousShadowCreator.get_master(current_user) ||
- AnonymousShadowCreator.get(current_user)
+ user =
+ AnonymousShadowCreator.get_master(current_user) || AnonymousShadowCreator.get(current_user)
if user
log_on_user(user)
@@ -956,12 +1046,12 @@ class UsersController < ApplicationController
elsif destination_url = cookies.delete(:destination_url)
return redirect_to(destination_url, allow_other_host: true)
else
- return redirect_to(path('/'))
+ return redirect_to(path("/"))
end
end
@custom_body_class = "static-account-created"
- @message = session['user_created_message'] || I18n.t('activation.missing_session')
+ @message = session["user_created_message"] || I18n.t("activation.missing_session")
@account_created = { message: @message, show_controls: false }
if session_user_id = session[SessionController::ACTIVATE_USER_KEY]
@@ -983,7 +1073,7 @@ class UsersController < ApplicationController
def activate_account
expires_now
- render layout: 'no_ember'
+ render layout: "no_ember"
end
def perform_account_activation
@@ -992,7 +1082,7 @@ class UsersController < ApplicationController
if @user = EmailToken.confirm(params[:token], scope: EmailToken.scopes[:signup])
# Log in the user unless they need to be approved
if Guardian.new(@user).can_access_forum?
- @user.enqueue_welcome_message('welcome_user') if @user.send_welcome_message
+ @user.enqueue_welcome_message("welcome_user") if @user.send_welcome_message
log_on_user(@user)
# invites#perform_accept_invitation already sets destination_url, but
@@ -1002,39 +1092,44 @@ class UsersController < ApplicationController
# the topic they were originally invited to.
destination_url = cookies.delete(:destination_url)
if destination_url.blank?
- topic = Invite
- .joins(:invited_users)
- .find_by(invited_users: { user_id: @user.id })
- &.topics
- &.first
+ topic =
+ Invite
+ .joins(:invited_users)
+ .find_by(invited_users: { user_id: @user.id })
+ &.topics
+ &.first
- if @user.guardian.can_see?(topic)
- destination_url = path(topic.relative_url)
- end
+ destination_url = path(topic.relative_url) if @user.guardian.can_see?(topic)
end
if Wizard.user_requires_completion?(@user)
return redirect_to(wizard_path)
elsif destination_url.present?
return redirect_to(destination_url, allow_other_host: true)
- elsif SiteSetting.enable_discourse_connect_provider && payload = cookies.delete(:sso_payload)
+ elsif SiteSetting.enable_discourse_connect_provider &&
+ payload = cookies.delete(:sso_payload)
return redirect_to(session_sso_provider_url + "?" + payload)
end
else
@needs_approval = true
end
else
- flash.now[:error] = I18n.t('activation.already_done')
+ flash.now[:error] = I18n.t("activation.already_done")
end
- render layout: 'no_ember'
+ render layout: "no_ember"
end
def update_activation_email
RateLimiter.new(nil, "activate-edit-email-hr-#{request.remote_ip}", 5, 1.hour).performed!
if params[:username].present?
- RateLimiter.new(nil, "activate-edit-email-hr-username-#{params[:username]}", 5, 1.hour).performed!
+ RateLimiter.new(
+ nil,
+ "activate-edit-email-hr-username-#{params[:username]}",
+ 5,
+ 1.hour,
+ ).performed!
@user = User.find_by_username_or_email(params[:username])
raise Discourse::InvalidAccess.new unless @user.present?
raise Discourse::InvalidAccess.new unless @user.confirm_password?(params[:password])
@@ -1053,7 +1148,8 @@ class UsersController < ApplicationController
primary_email.skip_validate_email = false
if primary_email.save
- @email_token = @user.email_tokens.create!(email: @user.email, scope: EmailToken.scopes[:signup])
+ @email_token =
+ @user.email_tokens.create!(email: @user.email, scope: EmailToken.scopes[:signup])
EmailToken.enqueue_signup_email(@email_token, to_address: @user.email)
render json: success_json
else
@@ -1070,9 +1166,7 @@ class UsersController < ApplicationController
raise Discourse::InvalidAccess.new if SiteSetting.must_approve_users?
- if params[:username].present?
- @user = User.find_by_username_or_email(params[:username].to_s)
- end
+ @user = User.find_by_username_or_email(params[:username].to_s) if params[:username].present?
raise Discourse::NotFound unless @user
@@ -1083,9 +1177,10 @@ class UsersController < ApplicationController
session.delete(SessionController::ACTIVATE_USER_KEY)
if @user.active && @user.email_confirmed?
- render_json_error(I18n.t('activation.activated'), status: 409)
+ render_json_error(I18n.t("activation.activated"), status: 409)
else
- @email_token = @user.email_tokens.create!(email: @user.email, scope: EmailToken.scopes[:signup])
+ @email_token =
+ @user.email_tokens.create!(email: @user.email, scope: EmailToken.scopes[:signup])
EmailToken.enqueue_signup_email(@email_token, to_address: @user.email)
render body: nil
end
@@ -1104,12 +1199,14 @@ class UsersController < ApplicationController
@groups = Group.where(name: group_names) if group_names.present?
options = {
- topic_allowed_users: topic_allowed_users,
- searching_user: current_user,
- groups: @groups
+ topic_allowed_users: topic_allowed_users,
+ searching_user: current_user,
+ groups: @groups,
}
- options[:include_staged_users] = !!ActiveModel::Type::Boolean.new.cast(params[:include_staged_users])
+ options[:include_staged_users] = !!ActiveModel::Type::Boolean.new.cast(
+ params[:include_staged_users],
+ )
options[:last_seen_users] = !!ActiveModel::Type::Boolean.new.cast(params[:last_seen_users])
if params[:limit].present?
options[:limit] = params[:limit].to_i
@@ -1125,50 +1222,44 @@ class UsersController < ApplicationController
# we do not want group results ever if term is blank
groups =
if term.present? && current_user
- if params[:include_groups] == 'true'
+ if params[:include_groups] == "true"
Group.visible_groups(current_user)
- elsif params[:include_mentionable_groups] == 'true'
+ elsif params[:include_mentionable_groups] == "true"
Group.mentionable(current_user)
- elsif params[:include_messageable_groups] == 'true'
+ elsif params[:include_messageable_groups] == "true"
Group.messageable(current_user)
end
end
if groups
- DiscoursePluginRegistry.groups_callback_for_users_search_controller_action.each do |param_name, block|
- if params[param_name.to_s]
- groups = block.call(groups, current_user)
- end
+ DiscoursePluginRegistry
+ .groups_callback_for_users_search_controller_action
+ .each do |param_name, block|
+ groups = block.call(groups, current_user) if params[param_name.to_s]
end
groups = Group.search_groups(term, groups: groups, sort: :auto)
- to_render[:groups] = groups.map do |m|
- { name: m.name, full_name: m.full_name }
- end
+ to_render[:groups] = groups.map { |m| { name: m.name, full_name: m.full_name } }
end
render json: to_render
end
- AVATAR_TYPES_WITH_UPLOAD ||= %w{uploaded custom gravatar}
+ AVATAR_TYPES_WITH_UPLOAD ||= %w[uploaded custom gravatar]
def pick_avatar
user = fetch_user_from_params
guardian.ensure_can_edit!(user)
- if SiteSetting.discourse_connect_overrides_avatar
- return render json: failed_json, status: 422
- end
+ return render json: failed_json, status: 422 if SiteSetting.discourse_connect_overrides_avatar
type = params[:type]
- invalid_type = type.present? && !AVATAR_TYPES_WITH_UPLOAD.include?(type) && type != 'system'
- if invalid_type
- return render json: failed_json, status: 422
- end
+ invalid_type = type.present? && !AVATAR_TYPES_WITH_UPLOAD.include?(type) && type != "system"
+ return render json: failed_json, status: 422 if invalid_type
- if type.blank? || type == 'system'
+ if type.blank? || type == "system"
upload_id = nil
elsif !TrustLevelAndStaffAndDisabledSetting.matches?(SiteSetting.allow_uploaded_avatars, user)
return render json: failed_json, status: 422
@@ -1176,25 +1267,21 @@ class UsersController < ApplicationController
upload_id = params[:upload_id]
upload = Upload.find_by(id: upload_id)
- if upload.nil?
- return render_json_error I18n.t('avatar.missing')
- end
+ return render_json_error I18n.t("avatar.missing") if upload.nil?
# old safeguard
user.create_user_avatar unless user.user_avatar
guardian.ensure_can_pick_avatar!(user.user_avatar, upload)
- if type == 'gravatar'
+ if type == "gravatar"
user.user_avatar.gravatar_upload_id = upload_id
else
user.user_avatar.custom_upload_id = upload_id
end
end
- if user.is_system_user?
- SiteSetting.use_site_small_logo_as_system_avatar = false
- end
+ SiteSetting.use_site_small_logo_as_system_avatar = false if user.is_system_user?
user.uploaded_avatar_id = upload_id
user.save!
@@ -1209,17 +1296,13 @@ class UsersController < ApplicationController
url = params[:url]
- if url.blank?
- return render json: failed_json, status: 422
- end
+ return render json: failed_json, status: 422 if url.blank?
if SiteSetting.selectable_avatars_mode == "disabled"
return render json: failed_json, status: 422
end
- if SiteSetting.selectable_avatars.blank?
- return render json: failed_json, status: 422
- end
+ return render json: failed_json, status: 422 if SiteSetting.selectable_avatars.blank?
unless upload = Upload.get_from_url(url)
return render json: failed_json, status: 422
@@ -1231,9 +1314,7 @@ class UsersController < ApplicationController
user.uploaded_avatar_id = upload.id
- if user.is_system_user?
- SiteSetting.use_site_small_logo_as_system_avatar = false
- end
+ SiteSetting.use_site_small_logo_as_system_avatar = false if user.is_system_user?
user.save!
@@ -1242,10 +1323,10 @@ class UsersController < ApplicationController
avatar.save!
render json: {
- avatar_template: user.avatar_template,
- custom_avatar_template: user.avatar_template,
- uploaded_avatar_id: upload.id,
- }
+ avatar_template: user.avatar_template,
+ custom_avatar_template: user.avatar_template,
+ uploaded_avatar_id: upload.id,
+ }
end
def destroy_user_image
@@ -1280,8 +1361,7 @@ class UsersController < ApplicationController
# the admin should be able to change notification levels
# on behalf of other users, so we cannot rely on current_user
# for this case
- if params[:acting_user_id].present? &&
- params[:acting_user_id].to_i != current_user.id
+ if params[:acting_user_id].present? && params[:acting_user_id].to_i != current_user.id
if current_user.staff?
acting_user = User.find(params[:acting_user_id])
else
@@ -1298,20 +1378,26 @@ class UsersController < ApplicationController
if ignored_user.present?
ignored_user.update(expiring_at: DateTime.parse(params[:expiring_at]))
else
- IgnoredUser.create!(user: acting_user, ignored_user: target_user, expiring_at: Time.parse(params[:expiring_at]))
+ IgnoredUser.create!(
+ user: acting_user,
+ ignored_user: target_user,
+ expiring_at: Time.parse(params[:expiring_at]),
+ )
end
-
elsif params[:notification_level] == "mute"
@error_message = "mute_error"
guardian.ensure_can_mute_user!(target_user)
IgnoredUser.where(user: acting_user, ignored_user: target_user).delete_all
MutedUser.find_or_create_by!(user: acting_user, muted_user: target_user)
-
elsif params[:notification_level] == "normal"
MutedUser.where(user: acting_user, muted_user: target_user).delete_all
IgnoredUser.where(user: acting_user, ignored_user: target_user).delete_all
else
- return render_json_error(I18n.t("notification_level.invalid_value", value: params[:notification_level]))
+ return(
+ render_json_error(
+ I18n.t("notification_level.invalid_value", value: params[:notification_level]),
+ )
+ )
end
render json: success_json
@@ -1330,22 +1416,20 @@ class UsersController < ApplicationController
def recent_searches
if !SiteSetting.log_search_queries
- return render json: failed_json.merge(
- error: I18n.t("user_activity.no_log_search_queries")
- ), status: 403
+ return(
+ render json: failed_json.merge(error: I18n.t("user_activity.no_log_search_queries")),
+ status: 403
+ )
end
query = SearchLog.where(user_id: current_user.id)
if current_user.user_option.oldest_search_log_date
- query = query
- .where("created_at > ?", current_user.user_option.oldest_search_log_date)
+ query = query.where("created_at > ?", current_user.user_option.oldest_search_log_date)
end
- results = query.group(:term)
- .order("max(created_at) DESC")
- .limit(MAX_RECENT_SEARCHES)
- .pluck(:term)
+ results =
+ query.group(:term).order("max(created_at) DESC").limit(MAX_RECENT_SEARCHES).pluck(:term)
render json: success_json.merge(recent_searches: results)
end
@@ -1361,12 +1445,14 @@ class UsersController < ApplicationController
result = {}
- %W{
- number_of_deleted_posts number_of_flagged_posts number_of_flags_given
- number_of_suspensions warnings_received_count number_of_rejected_posts
- }.each do |info|
- result[info] = @user.public_send(info)
- end
+ %W[
+ number_of_deleted_posts
+ number_of_flagged_posts
+ number_of_flags_given
+ number_of_suspensions
+ warnings_received_count
+ number_of_rejected_posts
+ ].each { |info| result[info] = @user.public_send(info) }
render json: result
end
@@ -1375,8 +1461,9 @@ class UsersController < ApplicationController
@confirmation = AdminConfirmation.find_by_code(params[:token])
raise Discourse::NotFound unless @confirmation
- raise Discourse::InvalidAccess.new unless
- @confirmation.performed_by.id == (current_user&.id || @confirmation.performed_by.id)
+ unless @confirmation.performed_by.id == (current_user&.id || @confirmation.performed_by.id)
+ raise Discourse::InvalidAccess.new
+ end
if request.post?
@confirmation.email_confirmed!
@@ -1385,75 +1472,86 @@ class UsersController < ApplicationController
respond_to do |format|
format.json { render json: success_json }
- format.html { render layout: 'no_ember' }
+ format.html { render layout: "no_ember" }
end
end
def list_second_factors
- raise Discourse::NotFound if SiteSetting.enable_discourse_connect || !SiteSetting.enable_local_logins
+ if SiteSetting.enable_discourse_connect || !SiteSetting.enable_local_logins
+ raise Discourse::NotFound
+ end
unless params[:password].empty?
- RateLimiter.new(nil, "login-hr-#{request.remote_ip}", SiteSetting.max_logins_per_ip_per_hour, 1.hour).performed!
- RateLimiter.new(nil, "login-min-#{request.remote_ip}", SiteSetting.max_logins_per_ip_per_minute, 1.minute).performed!
+ RateLimiter.new(
+ nil,
+ "login-hr-#{request.remote_ip}",
+ SiteSetting.max_logins_per_ip_per_hour,
+ 1.hour,
+ ).performed!
+ RateLimiter.new(
+ nil,
+ "login-min-#{request.remote_ip}",
+ SiteSetting.max_logins_per_ip_per_minute,
+ 1.minute,
+ ).performed!
unless current_user.confirm_password?(params[:password])
- return render json: failed_json.merge(
- error: I18n.t("login.incorrect_password")
- )
+ return render json: failed_json.merge(error: I18n.t("login.incorrect_password"))
end
confirm_secure_session
end
if secure_session_confirmed?
- totp_second_factors = current_user.totps
- .select(:id, :name, :last_used, :created_at, :method)
- .where(enabled: true).order(:created_at)
+ totp_second_factors =
+ current_user
+ .totps
+ .select(:id, :name, :last_used, :created_at, :method)
+ .where(enabled: true)
+ .order(:created_at)
- security_keys = current_user.security_keys.where(factor_type: UserSecurityKey.factor_types[:second_factor]).order(:created_at)
+ security_keys =
+ current_user
+ .security_keys
+ .where(factor_type: UserSecurityKey.factor_types[:second_factor])
+ .order(:created_at)
- render json: success_json.merge(
- totps: totp_second_factors,
- security_keys: security_keys
- )
+ render json: success_json.merge(totps: totp_second_factors, security_keys: security_keys)
else
- render json: success_json.merge(
- password_required: true
- )
+ render json: success_json.merge(password_required: true)
end
end
def create_second_factor_backup
backup_codes = current_user.generate_backup_codes
- render json: success_json.merge(
- backup_codes: backup_codes
- )
+ render json: success_json.merge(backup_codes: backup_codes)
end
def create_second_factor_totp
- require 'rotp' if !defined? ROTP
+ require "rotp" if !defined?(ROTP)
totp_data = ROTP::Base32.random
secure_session["staged-totp-#{current_user.id}"] = totp_data
- qrcode_png = RQRCode::QRCode.new(current_user.totp_provisioning_uri(totp_data)).as_png(
- border_modules: 1,
- size: 240
- )
+ qrcode_png =
+ RQRCode::QRCode.new(current_user.totp_provisioning_uri(totp_data)).as_png(
+ border_modules: 1,
+ size: 240,
+ )
- render json: success_json.merge(
- key: totp_data.scan(/.{4}/).join(" "),
- qr: qrcode_png.to_data_url
- )
+ render json:
+ success_json.merge(key: totp_data.scan(/.{4}/).join(" "), qr: qrcode_png.to_data_url)
end
def create_second_factor_security_key
challenge_session = Webauthn.stage_challenge(current_user, secure_session)
- render json: success_json.merge(
- challenge: challenge_session.challenge,
- rp_id: challenge_session.rp_id,
- rp_name: challenge_session.rp_name,
- supported_algorithms: ::Webauthn::SUPPORTED_ALGORITHMS,
- user_secure_id: current_user.create_or_fetch_secure_identifier,
- existing_active_credential_ids: current_user.second_factor_security_key_credential_ids
- )
+ render json:
+ success_json.merge(
+ challenge: challenge_session.challenge,
+ rp_id: challenge_session.rp_id,
+ rp_name: challenge_session.rp_name,
+ supported_algorithms: ::Webauthn::SUPPORTED_ALGORITHMS,
+ user_secure_id: current_user.create_or_fetch_secure_identifier,
+ existing_active_credential_ids:
+ current_user.second_factor_security_key_credential_ids,
+ )
end
def register_second_factor_security_key
@@ -1466,7 +1564,7 @@ class UsersController < ApplicationController
params,
challenge: Webauthn.challenge(current_user, secure_session),
rp_id: Webauthn.rp_id(current_user, secure_session),
- origin: Discourse.base_url
+ origin: Discourse.base_url,
).register_second_factor_security_key
render json: success_json
rescue ::Webauthn::SecurityKeyError => err
@@ -1477,12 +1575,8 @@ class UsersController < ApplicationController
user_security_key = current_user.security_keys.find_by(id: params[:id].to_i)
raise Discourse::InvalidParameters unless user_security_key
- if params[:name] && !params[:name].blank?
- user_security_key.update!(name: params[:name])
- end
- if params[:disable] == "true"
- user_security_key.update!(enabled: false)
- end
+ user_security_key.update!(name: params[:name]) if params[:name] && !params[:name].blank?
+ user_security_key.update!(enabled: false) if params[:disable] == "true"
render json: success_json
end
@@ -1501,15 +1595,15 @@ class UsersController < ApplicationController
rate_limit_second_factor!(current_user)
- authenticated = !auth_token.blank? && totp_object.verify(
- auth_token,
- drift_ahead: SecondFactorManager::TOTP_ALLOWED_DRIFT_SECONDS,
- drift_behind: SecondFactorManager::TOTP_ALLOWED_DRIFT_SECONDS
- )
+ authenticated =
+ !auth_token.blank? &&
+ totp_object.verify(
+ auth_token,
+ drift_ahead: SecondFactorManager::TOTP_ALLOWED_DRIFT_SECONDS,
+ drift_behind: SecondFactorManager::TOTP_ALLOWED_DRIFT_SECONDS,
+ )
unless authenticated
- return render json: failed_json.merge(
- error: I18n.t("login.invalid_second_factor_code")
- )
+ return render json: failed_json.merge(error: I18n.t("login.invalid_second_factor_code"))
end
current_user.create_totp(data: totp_data, name: params[:name], enabled: true)
render json: success_json
@@ -1523,7 +1617,7 @@ class UsersController < ApplicationController
Jobs.enqueue(
:critical_user_email,
type: "account_second_factor_disabled",
- user_id: current_user.id
+ user_id: current_user.id,
)
render json: success_json
@@ -1543,24 +1637,26 @@ class UsersController < ApplicationController
raise Discourse::InvalidParameters unless user_second_factor
- if params[:name] && !params[:name].blank?
- user_second_factor.update!(name: params[:name])
- end
+ user_second_factor.update!(name: params[:name]) if params[:name] && !params[:name].blank?
if params[:disable] == "true"
# Disabling backup codes deletes *all* backup codes
if update_second_factor_method == UserSecondFactor.methods[:backup_codes]
- current_user.user_second_factors.where(method: UserSecondFactor.methods[:backup_codes]).destroy_all
+ current_user
+ .user_second_factors
+ .where(method: UserSecondFactor.methods[:backup_codes])
+ .destroy_all
else
user_second_factor.update!(enabled: false)
end
-
end
render json: success_json
end
def second_factor_check_confirmed_password
- raise Discourse::NotFound if SiteSetting.enable_discourse_connect || !SiteSetting.enable_local_logins
+ if SiteSetting.enable_discourse_connect || !SiteSetting.enable_local_logins
+ raise Discourse::NotFound
+ end
raise Discourse::InvalidAccess.new unless current_user && secure_session_confirmed?
end
@@ -1585,9 +1681,9 @@ class UsersController < ApplicationController
render json: success_json
else
render json: {
- success: false,
- message: I18n.t("associated_accounts.revoke_failed", provider_name: provider_name)
- }
+ success: false,
+ message: I18n.t("associated_accounts.revoke_failed", provider_name: provider_name),
+ }
end
end
end
@@ -1599,7 +1695,9 @@ class UsersController < ApplicationController
if params[:token_id]
token = UserAuthToken.find_by(id: params[:token_id], user_id: user.id)
# The user should not be able to revoke the auth token of current session.
- raise Discourse::InvalidParameters.new(:token_id) if !token || guardian.auth_token == token.auth_token
+ if !token || guardian.auth_token == token.auth_token
+ raise Discourse::InvalidParameters.new(:token_id)
+ end
UserAuthToken.where(id: params[:token_id], user_id: user.id).each(&:destroy!)
MessageBus.publish "/file-change", ["refresh"], user_ids: [user.id]
@@ -1615,7 +1713,12 @@ class UsersController < ApplicationController
topic = Topic.find(params[:topic_id].to_i)
if !guardian.can_feature_topic?(user, topic)
- return render_json_error(I18n.t('activerecord.errors.models.user_profile.attributes.featured_topic_id.invalid'), 403)
+ return(
+ render_json_error(
+ I18n.t("activerecord.errors.models.user_profile.attributes.featured_topic_id.invalid"),
+ 403,
+ )
+ )
end
user.user_profile.update(featured_topic_id: topic.id)
@@ -1640,24 +1743,27 @@ class UsersController < ApplicationController
bookmark_list.load
if bookmark_list.bookmarks.empty?
- render json: {
- bookmarks: []
- }
+ render json: { bookmarks: [] }
else
page = params[:page].to_i + 1
- bookmark_list.more_bookmarks_url = "#{Discourse.base_path}/u/#{params[:username]}/bookmarks.json?page=#{page}"
+ bookmark_list.more_bookmarks_url =
+ "#{Discourse.base_path}/u/#{params[:username]}/bookmarks.json?page=#{page}"
render_serialized(bookmark_list, UserBookmarkListSerializer)
end
end
format.ics do
- @bookmark_reminders = Bookmark.with_reminders
- .where(user_id: user.id)
- .order(:reminder_at)
- .map do |bookmark|
- bookmark.registered_bookmarkable.serializer.new(
- bookmark, scope: user_guardian, root: false
- )
- end
+ @bookmark_reminders =
+ Bookmark
+ .with_reminders
+ .where(user_id: user.id)
+ .order(:reminder_at)
+ .map do |bookmark|
+ bookmark.registered_bookmarkable.serializer.new(
+ bookmark,
+ scope: user_guardian,
+ root: false,
+ )
+ end
end
end
end
@@ -1668,22 +1774,24 @@ class UsersController < ApplicationController
raise Discourse::InvalidAccess.new("username doesn't match current_user's username")
end
- reminder_notifications = Notification
- .for_user_menu(current_user.id, limit: USER_MENU_LIST_LIMIT)
- .unread
- .where(notification_type: Notification.types[:bookmark_reminder])
+ reminder_notifications =
+ Notification
+ .for_user_menu(current_user.id, limit: USER_MENU_LIST_LIMIT)
+ .unread
+ .where(notification_type: Notification.types[:bookmark_reminder])
if reminder_notifications.size < USER_MENU_LIST_LIMIT
- exclude_bookmark_ids = reminder_notifications
- .filter_map { |notification| notification.data_hash[:bookmark_id] }
+ exclude_bookmark_ids =
+ reminder_notifications.filter_map { |notification| notification.data_hash[:bookmark_id] }
- bookmark_list = UserBookmarkList.new(
- user: current_user,
- guardian: guardian,
- params: {
- per_page: USER_MENU_LIST_LIMIT - reminder_notifications.size
- }
- )
+ bookmark_list =
+ UserBookmarkList.new(
+ user: current_user,
+ guardian: guardian,
+ params: {
+ per_page: USER_MENU_LIST_LIMIT - reminder_notifications.size,
+ },
+ )
bookmark_list.load do |query|
if exclude_bookmark_ids.present?
query.where("bookmarks.id NOT IN (?)", exclude_bookmark_ids)
@@ -1692,27 +1800,26 @@ class UsersController < ApplicationController
end
if reminder_notifications.present?
- serialized_notifications = ActiveModel::ArraySerializer.new(
- reminder_notifications,
- each_serializer: NotificationSerializer,
- scope: guardian
- )
+ serialized_notifications =
+ ActiveModel::ArraySerializer.new(
+ reminder_notifications,
+ each_serializer: NotificationSerializer,
+ scope: guardian,
+ )
end
if bookmark_list
bookmark_list.bookmark_serializer_opts = { link_to_first_unread_post: true }
- serialized_bookmarks = serialize_data(
- bookmark_list,
- UserBookmarkListSerializer,
- scope: guardian,
- root: false
- )[:bookmarks]
+ serialized_bookmarks =
+ serialize_data(bookmark_list, UserBookmarkListSerializer, scope: guardian, root: false)[
+ :bookmarks
+ ]
end
render json: {
- notifications: serialized_notifications || [],
- bookmarks: serialized_bookmarks || []
- }
+ notifications: serialized_notifications || [],
+ bookmarks: serialized_bookmarks || [],
+ }
end
def user_menu_messages
@@ -1720,68 +1827,71 @@ class UsersController < ApplicationController
raise Discourse::InvalidAccess.new("username doesn't match current_user's username")
end
- if !current_user.staff? && !current_user.in_any_groups?(SiteSetting.personal_message_enabled_groups_map)
+ if !current_user.staff? &&
+ !current_user.in_any_groups?(SiteSetting.personal_message_enabled_groups_map)
raise Discourse::InvalidAccess.new("personal messages are disabled.")
end
- unread_notifications = Notification
- .for_user_menu(current_user.id, limit: USER_MENU_LIST_LIMIT)
- .unread
- .where(notification_type: [Notification.types[:private_message], Notification.types[:group_message_summary]])
- .to_a
+ unread_notifications =
+ Notification
+ .for_user_menu(current_user.id, limit: USER_MENU_LIST_LIMIT)
+ .unread
+ .where(
+ notification_type: [
+ Notification.types[:private_message],
+ Notification.types[:group_message_summary],
+ ],
+ )
+ .to_a
if unread_notifications.size < USER_MENU_LIST_LIMIT
exclude_topic_ids = unread_notifications.filter_map(&:topic_id).uniq
limit = USER_MENU_LIST_LIMIT - unread_notifications.size
- messages_list = TopicQuery.new(
- current_user,
- per_page: limit
- ).list_private_messages_direct_and_groups(current_user) do |query|
- if exclude_topic_ids.present?
- query.where("topics.id NOT IN (?)", exclude_topic_ids)
- else
- query
- end
- end
- read_notifications = Notification
- .for_user_menu(current_user.id, limit: limit)
- .where(
- read: true,
- notification_type: Notification.types[:group_message_summary],
- )
- .to_a
+ messages_list =
+ TopicQuery
+ .new(current_user, per_page: limit)
+ .list_private_messages_direct_and_groups(current_user) do |query|
+ if exclude_topic_ids.present?
+ query.where("topics.id NOT IN (?)", exclude_topic_ids)
+ else
+ query
+ end
+ end
+ read_notifications =
+ Notification
+ .for_user_menu(current_user.id, limit: limit)
+ .where(read: true, notification_type: Notification.types[:group_message_summary])
+ .to_a
end
if unread_notifications.present?
- serialized_unread_notifications = ActiveModel::ArraySerializer.new(
- unread_notifications,
- each_serializer: NotificationSerializer,
- scope: guardian
- )
+ serialized_unread_notifications =
+ ActiveModel::ArraySerializer.new(
+ unread_notifications,
+ each_serializer: NotificationSerializer,
+ scope: guardian,
+ )
end
if messages_list
- serialized_messages = serialize_data(
- messages_list,
- TopicListSerializer,
- scope: guardian,
- root: false
- )[:topics]
+ serialized_messages =
+ serialize_data(messages_list, TopicListSerializer, scope: guardian, root: false)[:topics]
end
if read_notifications.present?
- serialized_read_notifications = ActiveModel::ArraySerializer.new(
- read_notifications,
- each_serializer: NotificationSerializer,
- scope: guardian
- )
+ serialized_read_notifications =
+ ActiveModel::ArraySerializer.new(
+ read_notifications,
+ each_serializer: NotificationSerializer,
+ scope: guardian,
+ )
end
render json: {
- unread_notifications: serialized_unread_notifications || [],
- read_notifications: serialized_read_notifications || [],
- topics: serialized_messages || []
- }
+ unread_notifications: serialized_unread_notifications || [],
+ read_notifications: serialized_read_notifications || [],
+ topics: serialized_messages || [],
+ }
end
private
@@ -1803,11 +1913,12 @@ class UsersController < ApplicationController
end
def password_reset_find_user(token, committing_change:)
- @user = if committing_change
- EmailToken.confirm(token, scope: EmailToken.scopes[:password_reset])
- else
- EmailToken.confirmable(token, scope: EmailToken.scopes[:password_reset])&.user
- end
+ @user =
+ if committing_change
+ EmailToken.confirm(token, scope: EmailToken.scopes[:password_reset])
+ else
+ EmailToken.confirmable(token, scope: EmailToken.scopes[:password_reset])&.user
+ end
if @user
secure_session["password-#{token}"] = @user.id
@@ -1816,16 +1927,16 @@ class UsersController < ApplicationController
@user = User.find(user_id) if user_id > 0
end
- @error = I18n.t('password_reset.no_token', base_url: Discourse.base_url) if !@user
+ @error = I18n.t("password_reset.no_token", base_url: Discourse.base_url) if !@user
end
def respond_to_suspicious_request
if suspicious?(params)
render json: {
- success: true,
- active: false,
- message: I18n.t("login.activate_email", email: params[:email])
- }
+ success: true,
+ active: false,
+ message: I18n.t("login.activate_email", email: params[:email]),
+ }
end
end
@@ -1837,30 +1948,30 @@ class UsersController < ApplicationController
def honeypot_or_challenge_fails?(params)
return false if is_api?
params[:password_confirmation] != honeypot_value ||
- params[:challenge] != challenge_value.try(:reverse)
+ params[:challenge] != challenge_value.try(:reverse)
end
def user_params
- permitted = [
- :name,
- :email,
- :password,
- :username,
- :title,
- :date_of_birth,
- :muted_usernames,
- :allowed_pm_usernames,
- :theme_ids,
- :locale,
- :bio_raw,
- :location,
- :website,
- :dismissed_banner_key,
- :profile_background_upload_url,
- :card_background_upload_url,
- :primary_group_id,
- :flair_group_id,
- :featured_topic_id,
+ permitted = %i[
+ name
+ email
+ password
+ username
+ title
+ date_of_birth
+ muted_usernames
+ allowed_pm_usernames
+ theme_ids
+ locale
+ bio_raw
+ location
+ website
+ dismissed_banner_key
+ profile_background_upload_url
+ card_background_upload_url
+ primary_group_id
+ flair_group_id
+ featured_topic_id
]
editable_custom_fields = User.editable_user_custom_fields(by_staff: current_user.try(:staff?))
@@ -1888,21 +1999,17 @@ class UsersController < ApplicationController
if SiteSetting.enable_user_status
permitted << :status
- permitted << { status: [:emoji, :description, :ends_at] }
+ permitted << { status: %i[emoji description ends_at] }
end
- result = params
- .permit(permitted, theme_ids: [], seen_popups: [])
- .reverse_merge(
+ result =
+ params.permit(permitted, theme_ids: [], seen_popups: []).reverse_merge(
ip_address: request.remote_ip,
- registration_ip_address: request.remote_ip
+ registration_ip_address: request.remote_ip,
)
- if !UsernameCheckerService.is_developer?(result['email']) &&
- is_api? &&
- current_user.present? &&
- current_user.admin?
-
+ if !UsernameCheckerService.is_developer?(result["email"]) && is_api? && current_user.present? &&
+ current_user.admin?
result.merge!(params.permit(:active, :staged, :approved))
end
@@ -1923,7 +2030,7 @@ class UsersController < ApplicationController
ip = request.remote_ip
user_id = (current_user.id if current_user)
- Scheduler::Defer.later 'Track profile view visit' do
+ Scheduler::Defer.later "Track profile view visit" do
UserProfileView.add(user_profile_id, ip, user_id)
end
end
@@ -1956,17 +2063,12 @@ class UsersController < ApplicationController
end
def render_invite_error(message)
- render json: {
- invites: [],
- can_see_invite_details: false,
- error: message
- }
+ render json: { invites: [], can_see_invite_details: false, error: message }
end
def serialize_found_users(users)
- each_serializer = SiteSetting.enable_user_status? ?
- FoundUserWithStatusSerializer :
- FoundUserSerializer
+ each_serializer =
+ SiteSetting.enable_user_status? ? FoundUserWithStatusSerializer : FoundUserSerializer
{ users: ActiveModel::ArraySerializer.new(users, each_serializer: each_serializer).as_json }
end
diff --git a/app/controllers/users_email_controller.rb b/app/controllers/users_email_controller.rb
index f3f30a47dd5..98ac6458ed0 100644
--- a/app/controllers/users_email_controller.rb
+++ b/app/controllers/users_email_controller.rb
@@ -1,35 +1,31 @@
# frozen_string_literal: true
class UsersEmailController < ApplicationController
+ requires_login only: %i[index update]
- requires_login only: [:index, :update]
+ skip_before_action :check_xhr,
+ only: %i[
+ confirm_old_email
+ show_confirm_old_email
+ confirm_new_email
+ show_confirm_new_email
+ ]
- skip_before_action :check_xhr, only: [
- :confirm_old_email,
- :show_confirm_old_email,
- :confirm_new_email,
- :show_confirm_new_email
- ]
+ skip_before_action :redirect_to_login_if_required,
+ only: %i[
+ confirm_old_email
+ show_confirm_old_email
+ confirm_new_email
+ show_confirm_new_email
+ ]
- skip_before_action :redirect_to_login_if_required, only: [
- :confirm_old_email,
- :show_confirm_old_email,
- :confirm_new_email,
- :show_confirm_new_email
- ]
-
- before_action :require_login, only: [
- :confirm_old_email,
- :show_confirm_old_email
- ]
+ before_action :require_login, only: %i[confirm_old_email show_confirm_old_email]
def index
end
def create
- if !SiteSetting.enable_secondary_emails
- return render json: failed_json, status: 410
- end
+ return render json: failed_json, status: 410 if !SiteSetting.enable_secondary_emails
params.require(:email)
user = fetch_user_from_params
@@ -40,9 +36,7 @@ class UsersEmailController < ApplicationController
updater = EmailUpdater.new(guardian: guardian, user: user)
updater.change_to(params[:email], add: true)
- if updater.errors.present?
- return render_json_error(updater.errors.full_messages)
- end
+ return render_json_error(updater.errors.full_messages) if updater.errors.present?
render body: nil
rescue RateLimiter::LimitExceeded
@@ -59,9 +53,7 @@ class UsersEmailController < ApplicationController
updater = EmailUpdater.new(guardian: guardian, user: user)
updater.change_to(params[:email])
- if updater.errors.present?
- return render_json_error(updater.errors.full_messages)
- end
+ return render_json_error(updater.errors.full_messages) if updater.errors.present?
render body: nil
rescue RateLimiter::LimitExceeded
@@ -119,9 +111,7 @@ class UsersEmailController < ApplicationController
def show_confirm_new_email
load_change_request(:new)
- if params[:done].to_s == "true"
- @done = true
- end
+ @done = true if params[:done].to_s == "true"
if @change_request&.change_state != EmailChangeRequest.states[:authorizing_new]
@error = I18n.t("change_email.already_done")
@@ -135,21 +125,20 @@ class UsersEmailController < ApplicationController
if params[:show_backup].to_s == "true" && @backup_codes_enabled
@show_backup_codes = true
else
- if @user.totp_enabled?
- @show_second_factor = true
- end
+ @show_second_factor = true if @user.totp_enabled?
if @user.security_keys_enabled?
Webauthn.stage_challenge(@user, secure_session)
@show_security_key = params[:show_totp].to_s == "true" ? false : true
@security_key_challenge = Webauthn.challenge(@user, secure_session)
- @security_key_allowed_credential_ids = Webauthn.allowed_credentials(@user, secure_session)[:allowed_credential_ids]
+ @security_key_allowed_credential_ids =
+ Webauthn.allowed_credentials(@user, secure_session)[:allowed_credential_ids]
end
end
@to_email = @change_request.new_email
end
- render layout: 'no_ember'
+ render layout: "no_ember"
end
def confirm_old_email
@@ -183,16 +172,14 @@ class UsersEmailController < ApplicationController
@error = I18n.t("change_email.already_done")
end
- if params[:done].to_s == "true"
- @almost_done = true
- end
+ @almost_done = true if params[:done].to_s == "true"
if !@error
@from_email = @user.email
@to_email = @change_request.new_email
end
- render layout: 'no_ember'
+ render layout: "no_ember"
end
private
@@ -204,27 +191,24 @@ class UsersEmailController < ApplicationController
if token
if type == :old
- @change_request = token.user&.email_change_requests.where(old_email_token_id: token.id).first
+ @change_request =
+ token.user&.email_change_requests.where(old_email_token_id: token.id).first
elsif type == :new
- @change_request = token.user&.email_change_requests.where(new_email_token_id: token.id).first
+ @change_request =
+ token.user&.email_change_requests.where(new_email_token_id: token.id).first
end
end
@user = token&.user
- if (!@user || !@change_request)
- @error = I18n.t("change_email.already_done")
- end
+ @error = I18n.t("change_email.already_done") if (!@user || !@change_request)
if current_user && current_user.id != @user&.id
- @error = I18n.t 'change_email.wrong_account_error'
+ @error = I18n.t "change_email.wrong_account_error"
end
end
def require_login
- if !current_user
- redirect_to_login
- end
+ redirect_to_login if !current_user
end
-
end
diff --git a/app/controllers/webhooks_controller.rb b/app/controllers/webhooks_controller.rb
index 74024b31524..b84d59c269e 100644
--- a/app/controllers/webhooks_controller.rb
+++ b/app/controllers/webhooks_controller.rb
@@ -95,8 +95,8 @@ class WebhooksController < ActionController::Base
message_event = event.dig("msys", "message_event")
next unless message_event
- message_id = message_event.dig("rcpt_meta", "message_id")
- to_address = message_event["rcpt_to"]
+ message_id = message_event.dig("rcpt_meta", "message_id")
+ to_address = message_event["rcpt_to"]
bounce_class = message_event["bounce_class"]
next unless bounce_class
@@ -116,7 +116,7 @@ class WebhooksController < ActionController::Base
end
def aws
- raw = request.raw_post
+ raw = request.raw_post
json = JSON.parse(raw)
case json["Type"]
@@ -152,11 +152,14 @@ class WebhooksController < ActionController::Base
return false if (Time.at(timestamp.to_i) - Time.now).abs > 12.hours.to_i
# check the signature
- signature == OpenSSL::HMAC.hexdigest("SHA256", SiteSetting.mailgun_api_key, "#{timestamp}#{token}")
+ signature ==
+ OpenSSL::HMAC.hexdigest("SHA256", SiteSetting.mailgun_api_key, "#{timestamp}#{token}")
end
def handle_mailgun_legacy(params)
- return mailgun_failure unless valid_mailgun_signature?(params["token"], params["timestamp"], params["signature"])
+ unless valid_mailgun_signature?(params["token"], params["timestamp"], params["signature"])
+ return mailgun_failure
+ end
event = params["event"]
message_id = Email::MessageIdService.message_id_clean(params["Message-Id"])
@@ -177,7 +180,13 @@ class WebhooksController < ActionController::Base
def handle_mailgun_new(params)
signature = params["signature"]
- return mailgun_failure unless valid_mailgun_signature?(signature["token"], signature["timestamp"], signature["signature"])
+ unless valid_mailgun_signature?(
+ signature["token"],
+ signature["timestamp"],
+ signature["signature"],
+ )
+ return mailgun_failure
+ end
data = params["event-data"]
error_code = params.dig("delivery-status", "code")
@@ -207,5 +216,4 @@ class WebhooksController < ActionController::Base
Email::Receiver.update_bounce_score(email_log.user.email, bounce_score)
end
-
end
diff --git a/app/controllers/wizard_controller.rb b/app/controllers/wizard_controller.rb
index e7581dcca53..cdce04c1589 100644
--- a/app/controllers/wizard_controller.rb
+++ b/app/controllers/wizard_controller.rb
@@ -13,9 +13,7 @@ class WizardController < ApplicationController
render_serialized(wizard, WizardSerializer)
end
- format.html do
- render body: nil
- end
+ format.html { render body: nil }
end
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 06e8be21459..2520cd69b5d 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,7 +1,7 @@
# coding: utf-8
# frozen_string_literal: true
-require 'current_user'
-require 'canonical_url'
+require "current_user"
+require "canonical_url"
module ApplicationHelper
include CurrentUser
@@ -14,7 +14,6 @@ module ApplicationHelper
end
def discourse_config_environment(testing: false)
-
# TODO: Can this come from Ember CLI somehow?
config = {
modulePrefix: "discourse",
@@ -23,24 +22,27 @@ module ApplicationHelper
locationType: "history",
historySupportMiddleware: false,
EmberENV: {
- FEATURES: {},
- EXTEND_PROTOTYPES: { "Date": false },
+ FEATURES: {
+ },
+ EXTEND_PROTOTYPES: {
+ Date: false,
+ },
_APPLICATION_TEMPLATE_WRAPPER: false,
_DEFAULT_ASYNC_OBSERVERS: true,
- _JQUERY_INTEGRATION: true
+ _JQUERY_INTEGRATION: true,
},
APP: {
name: "discourse",
version: "#{Discourse::VERSION::STRING} #{Discourse.git_version}",
- exportApplicationGlobal: true
- }
+ exportApplicationGlobal: true,
+ },
}
if testing
config[:environment] = "test"
config[:locationType] = "none"
config[:APP][:autoboot] = false
- config[:APP][:rootElement] = '#ember-testing'
+ config[:APP][:rootElement] = "#ember-testing"
end
config.to_json
@@ -48,15 +50,9 @@ module ApplicationHelper
def google_universal_analytics_json(ua_domain_name = nil)
result = {}
- if ua_domain_name
- result[:cookieDomain] = ua_domain_name.gsub(/^http(s)?:\/\//, '')
- end
- if current_user.present?
- result[:userId] = current_user.id
- end
- if SiteSetting.ga_universal_auto_link_domains.present?
- result[:allowLinker] = true
- end
+ result[:cookieDomain] = ua_domain_name.gsub(%r{^http(s)?://}, "") if ua_domain_name
+ result[:userId] = current_user.id if current_user.present?
+ result[:allowLinker] = true if SiteSetting.ga_universal_auto_link_domains.present?
result.to_json
end
@@ -73,7 +69,7 @@ module ApplicationHelper
end
def shared_session_key
- if SiteSetting.long_polling_base_url != '/' && current_user
+ if SiteSetting.long_polling_base_url != "/" && current_user
sk = "shared_session_key"
return request.env[sk] if request.env[sk]
@@ -95,10 +91,15 @@ module ApplicationHelper
path = ActionController::Base.helpers.asset_path("#{script}.js")
if GlobalSetting.use_s3? && GlobalSetting.s3_cdn_url
- resolved_s3_asset_cdn_url = GlobalSetting.s3_asset_cdn_url.presence || GlobalSetting.s3_cdn_url
+ resolved_s3_asset_cdn_url =
+ GlobalSetting.s3_asset_cdn_url.presence || GlobalSetting.s3_cdn_url
if GlobalSetting.cdn_url
folder = ActionController::Base.config.relative_url_root || "/"
- path = path.gsub(File.join(GlobalSetting.cdn_url, folder, "/"), File.join(resolved_s3_asset_cdn_url, "/"))
+ path =
+ path.gsub(
+ File.join(GlobalSetting.cdn_url, folder, "/"),
+ File.join(resolved_s3_asset_cdn_url, "/"),
+ )
else
# we must remove the subfolder path here, assets are uploaded to s3
# without it getting involved
@@ -121,8 +122,8 @@ module ApplicationHelper
path = path.gsub(/\.([^.]+)$/, '.gz.\1')
end
end
-
- elsif GlobalSetting.cdn_url&.start_with?("https") && is_brotli_req? && Rails.env != "development"
+ elsif GlobalSetting.cdn_url&.start_with?("https") && is_brotli_req? &&
+ Rails.env != "development"
path = path.gsub("#{GlobalSetting.cdn_url}/assets/", "#{GlobalSetting.cdn_url}/brotli_asset/")
end
@@ -136,14 +137,17 @@ module ApplicationHelper
scripts.push(*chunks)
end
- scripts.map do |name|
- path = script_asset_path(name)
- preload_script_url(path)
- end.join("\n").html_safe
+ scripts
+ .map do |name|
+ path = script_asset_path(name)
+ preload_script_url(path)
+ end
+ .join("\n")
+ .html_safe
end
def preload_script_url(url)
- add_resource_preload_list(url, 'script')
+ add_resource_preload_list(url, "script")
if GlobalSetting.preload_link_header
<<~HTML.html_safe
@@ -157,50 +161,47 @@ module ApplicationHelper
end
def add_resource_preload_list(resource_url, type)
- @links_to_preload << %Q(<#{resource_url}>; rel="preload"; as="#{type}") if !@links_to_preload.nil?
+ if !@links_to_preload.nil?
+ @links_to_preload << %Q(<#{resource_url}>; rel="preload"; as="#{type}")
+ end
end
def discourse_csrf_tags
# anon can not have a CSRF token cause these are all pages
# that may be cached, causing a mismatch between session CSRF
# and CSRF on page and horrible impossible to debug login issues
- if current_user
- csrf_meta_tags
- end
+ csrf_meta_tags if current_user
end
def html_classes
list = []
- list << (mobile_view? ? 'mobile-view' : 'desktop-view')
- list << (mobile_device? ? 'mobile-device' : 'not-mobile-device')
- list << 'ios-device' if ios_device?
- list << 'rtl' if rtl?
+ list << (mobile_view? ? "mobile-view" : "desktop-view")
+ list << (mobile_device? ? "mobile-device" : "not-mobile-device")
+ list << "ios-device" if ios_device?
+ list << "rtl" if rtl?
list << text_size_class
- list << 'anon' unless current_user
- list.join(' ')
+ list << "anon" unless current_user
+ list.join(" ")
end
def body_classes
result = ApplicationHelper.extra_body_classes.to_a
- if @category && @category.url.present?
- result << "category-#{@category.slug_path.join('-')}"
- end
+ result << "category-#{@category.slug_path.join("-")}" if @category && @category.url.present?
- if current_user.present? &&
- current_user.primary_group_id &&
- primary_group_name = Group.where(id: current_user.primary_group_id).pluck_first(:name)
+ if current_user.present? && current_user.primary_group_id &&
+ primary_group_name = Group.where(id: current_user.primary_group_id).pluck_first(:name)
result << "primary-group-#{primary_group_name.downcase}"
end
- result.join(' ')
+ result.join(" ")
end
def text_size_class
requested_cookie_size, cookie_seq = cookies[:text_size]&.split("|")
server_seq = current_user&.user_option&.text_size_seq
if cookie_seq && server_seq && cookie_seq.to_i >= server_seq &&
- UserOption.text_sizes.keys.include?(requested_cookie_size&.to_sym)
+ UserOption.text_sizes.keys.include?(requested_cookie_size&.to_sym)
cookie_size = requested_cookie_size
end
@@ -211,11 +212,11 @@ module ApplicationHelper
def escape_unicode(javascript)
if javascript
javascript = javascript.scrub
- javascript.gsub!(/\342\200\250/u, '
')
- javascript.gsub!(/(<\/)/u, '\u003C/')
+ javascript.gsub!(/\342\200\250/u, "
")
+ javascript.gsub!(%r{()}u, '\u003C/')
javascript
else
- ''
+ ""
end
end
@@ -260,7 +261,7 @@ module ApplicationHelper
end
def rtl?
- ["ar", "ur", "fa_IR", "he"].include? I18n.locale.to_s
+ %w[ar ur fa_IR he].include? I18n.locale.to_s
end
def html_lang
@@ -291,18 +292,19 @@ module ApplicationHelper
# Use the correct scheme for opengraph/twitter image
opts[:image] = get_absolute_image_url(opts[:image]) if opts[:image].present?
- opts[:twitter_summary_large_image] =
- get_absolute_image_url(opts[:twitter_summary_large_image]) if opts[:twitter_summary_large_image].present?
+ opts[:twitter_summary_large_image] = get_absolute_image_url(
+ opts[:twitter_summary_large_image],
+ ) if opts[:twitter_summary_large_image].present?
result = []
- result << tag(:meta, property: 'og:site_name', content: SiteSetting.title)
- result << tag(:meta, property: 'og:type', content: 'website')
+ result << tag(:meta, property: "og:site_name", content: SiteSetting.title)
+ result << tag(:meta, property: "og:type", content: "website")
generate_twitter_card_metadata(result, opts)
result << tag(:meta, property: "og:image", content: opts[:image]) if opts[:image].present?
- [:url, :title, :description].each do |property|
+ %i[url title description].each do |property|
if opts[property].present?
content = (property == :url ? opts[property] : gsub_emoji_to_unicode(opts[property]))
result << tag(:meta, { property: "og:#{property}", content: content }, nil, true)
@@ -311,27 +313,30 @@ module ApplicationHelper
end
if opts[:read_time] && opts[:read_time] > 0 && opts[:like_count] && opts[:like_count] > 0
- result << tag(:meta, name: 'twitter:label1', value: I18n.t("reading_time"))
- result << tag(:meta, name: 'twitter:data1', value: "#{opts[:read_time]} mins 🕑")
- result << tag(:meta, name: 'twitter:label2', value: I18n.t("likes"))
- result << tag(:meta, name: 'twitter:data2', value: "#{opts[:like_count]} ❤")
+ result << tag(:meta, name: "twitter:label1", value: I18n.t("reading_time"))
+ result << tag(:meta, name: "twitter:data1", value: "#{opts[:read_time]} mins 🕑")
+ result << tag(:meta, name: "twitter:label2", value: I18n.t("likes"))
+ result << tag(:meta, name: "twitter:data2", value: "#{opts[:like_count]} ❤")
end
if opts[:published_time]
- result << tag(:meta, property: 'article:published_time', content: opts[:published_time])
+ result << tag(:meta, property: "article:published_time", content: opts[:published_time])
end
- if opts[:ignore_canonical]
- result << tag(:meta, property: 'og:ignore_canonical', content: true)
- end
+ result << tag(:meta, property: "og:ignore_canonical", content: true) if opts[:ignore_canonical]
result.join("\n")
end
private def generate_twitter_card_metadata(result, opts)
- img_url = opts[:twitter_summary_large_image].present? ? \
- opts[:twitter_summary_large_image] :
- opts[:image]
+ img_url =
+ (
+ if opts[:twitter_summary_large_image].present?
+ opts[:twitter_summary_large_image]
+ else
+ opts[:image]
+ end
+ )
# Twitter does not allow SVGs, see https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup
if img_url.ends_with?(".svg")
@@ -339,29 +344,29 @@ module ApplicationHelper
end
if opts[:twitter_summary_large_image].present? && img_url.present?
- result << tag(:meta, name: 'twitter:card', content: "summary_large_image")
+ result << tag(:meta, name: "twitter:card", content: "summary_large_image")
result << tag(:meta, name: "twitter:image", content: img_url)
elsif opts[:image].present? && img_url.present?
- result << tag(:meta, name: 'twitter:card', content: "summary")
+ result << tag(:meta, name: "twitter:card", content: "summary")
result << tag(:meta, name: "twitter:image", content: img_url)
else
- result << tag(:meta, name: 'twitter:card', content: "summary")
+ result << tag(:meta, name: "twitter:card", content: "summary")
end
end
def render_sitelinks_search_tag
- if current_page?('/') || current_page?(Discourse.base_path)
+ if current_page?("/") || current_page?(Discourse.base_path)
json = {
- '@context' => 'http://schema.org',
- '@type' => 'WebSite',
- url: Discourse.base_url,
- potentialAction: {
- '@type' => 'SearchAction',
- target: "#{Discourse.base_url}/search?q={search_term_string}",
- 'query-input' => 'required name=search_term_string',
- }
+ "@context" => "http://schema.org",
+ "@type" => "WebSite",
+ :url => Discourse.base_url,
+ :potentialAction => {
+ "@type" => "SearchAction",
+ :target => "#{Discourse.base_url}/search?q={search_term_string}",
+ "query-input" => "required name=search_term_string",
+ },
}
- content_tag(:script, MultiJson.dump(json).html_safe, type: 'application/ld+json')
+ content_tag(:script, MultiJson.dump(json).html_safe, type: "application/ld+json")
end
end
@@ -370,33 +375,35 @@ module ApplicationHelper
end
def application_logo_url
- @application_logo_url ||= begin
- if mobile_view?
- if dark_color_scheme? && SiteSetting.site_mobile_logo_dark_url.present?
- SiteSetting.site_mobile_logo_dark_url
- elsif SiteSetting.site_mobile_logo_url.present?
- SiteSetting.site_mobile_logo_url
- end
- else
- if dark_color_scheme? && SiteSetting.site_logo_dark_url.present?
- SiteSetting.site_logo_dark_url
+ @application_logo_url ||=
+ begin
+ if mobile_view?
+ if dark_color_scheme? && SiteSetting.site_mobile_logo_dark_url.present?
+ SiteSetting.site_mobile_logo_dark_url
+ elsif SiteSetting.site_mobile_logo_url.present?
+ SiteSetting.site_mobile_logo_url
+ end
else
- SiteSetting.site_logo_url
+ if dark_color_scheme? && SiteSetting.site_logo_dark_url.present?
+ SiteSetting.site_logo_dark_url
+ else
+ SiteSetting.site_logo_url
+ end
end
end
- end
end
def application_logo_dark_url
- @application_logo_dark_url ||= begin
- if dark_scheme_id != -1
- if mobile_view? && SiteSetting.site_mobile_logo_dark_url != application_logo_url
- SiteSetting.site_mobile_logo_dark_url
- elsif !mobile_view? && SiteSetting.site_logo_dark_url != application_logo_url
- SiteSetting.site_logo_dark_url
+ @application_logo_dark_url ||=
+ begin
+ if dark_scheme_id != -1
+ if mobile_view? && SiteSetting.site_mobile_logo_dark_url != application_logo_url
+ SiteSetting.site_mobile_logo_dark_url
+ elsif !mobile_view? && SiteSetting.site_logo_dark_url != application_logo_url
+ SiteSetting.site_logo_dark_url
+ end
end
end
- end
end
def login_path
@@ -437,8 +444,11 @@ module ApplicationHelper
def ios_app_argument
# argument only makes sense for DiscourseHub app
- SiteSetting.ios_app_id == "1173672076" ?
- ", app-argument=discourse://new?siteUrl=#{Discourse.base_url}" : ""
+ if SiteSetting.ios_app_id == "1173672076"
+ ", app-argument=discourse://new?siteUrl=#{Discourse.base_url}"
+ else
+ ""
+ end
end
def include_splash_screen?
@@ -496,9 +506,9 @@ module ApplicationHelper
uri = UrlHelper.encode_and_parse(link)
uri = URI.parse("http://#{uri}") if uri.scheme.nil?
host = uri.host.downcase
- host.start_with?('www.') ? host[4..-1] : host
- rescue
- ''
+ host.start_with?("www.") ? host[4..-1] : host
+ rescue StandardError
+ ""
end
end
@@ -529,7 +539,8 @@ module ApplicationHelper
end
def dark_scheme_id
- cookies[:dark_scheme_id] || current_user&.user_option&.dark_scheme_id || SiteSetting.default_dark_mode_color_scheme_id
+ cookies[:dark_scheme_id] || current_user&.user_option&.dark_scheme_id ||
+ SiteSetting.default_dark_mode_color_scheme_id
end
def current_homepage
@@ -556,7 +567,7 @@ module ApplicationHelper
theme_id,
mobile_view? ? :mobile : :desktop,
name,
- skip_transformation: request.env[:skip_theme_ids_transformation].present?
+ skip_transformation: request.env[:skip_theme_ids_transformation].present?,
)
end
@@ -565,7 +576,7 @@ module ApplicationHelper
theme_id,
:translations,
I18n.locale,
- skip_transformation: request.env[:skip_theme_ids_transformation].present?
+ skip_transformation: request.env[:skip_theme_ids_transformation].present?,
)
end
@@ -574,42 +585,41 @@ module ApplicationHelper
theme_id,
:extra_js,
nil,
- skip_transformation: request.env[:skip_theme_ids_transformation].present?
+ skip_transformation: request.env[:skip_theme_ids_transformation].present?,
)
end
def discourse_stylesheet_preload_tag(name, opts = {})
manager =
if opts.key?(:theme_id)
- Stylesheet::Manager.new(
- theme_id: customization_disabled? ? nil : opts[:theme_id]
- )
+ Stylesheet::Manager.new(theme_id: customization_disabled? ? nil : opts[:theme_id])
else
stylesheet_manager
end
- manager.stylesheet_preload_tag(name, 'all')
+ manager.stylesheet_preload_tag(name, "all")
end
def discourse_stylesheet_link_tag(name, opts = {})
manager =
if opts.key?(:theme_id)
- Stylesheet::Manager.new(
- theme_id: customization_disabled? ? nil : opts[:theme_id]
- )
+ Stylesheet::Manager.new(theme_id: customization_disabled? ? nil : opts[:theme_id])
else
stylesheet_manager
end
- manager.stylesheet_link_tag(name, 'all', self.method(:add_resource_preload_list))
+ manager.stylesheet_link_tag(name, "all", self.method(:add_resource_preload_list))
end
def discourse_preload_color_scheme_stylesheets
result = +""
- result << stylesheet_manager.color_scheme_stylesheet_preload_tag(scheme_id, 'all')
+ result << stylesheet_manager.color_scheme_stylesheet_preload_tag(scheme_id, "all")
if dark_scheme_id != -1
- result << stylesheet_manager.color_scheme_stylesheet_preload_tag(dark_scheme_id, '(prefers-color-scheme: dark)')
+ result << stylesheet_manager.color_scheme_stylesheet_preload_tag(
+ dark_scheme_id,
+ "(prefers-color-scheme: dark)",
+ )
end
result.html_safe
@@ -617,10 +627,18 @@ module ApplicationHelper
def discourse_color_scheme_stylesheets
result = +""
- result << stylesheet_manager.color_scheme_stylesheet_link_tag(scheme_id, 'all', self.method(:add_resource_preload_list))
+ result << stylesheet_manager.color_scheme_stylesheet_link_tag(
+ scheme_id,
+ "all",
+ self.method(:add_resource_preload_list),
+ )
if dark_scheme_id != -1
- result << stylesheet_manager.color_scheme_stylesheet_link_tag(dark_scheme_id, '(prefers-color-scheme: dark)', self.method(:add_resource_preload_list))
+ result << stylesheet_manager.color_scheme_stylesheet_link_tag(
+ dark_scheme_id,
+ "(prefers-color-scheme: dark)",
+ self.method(:add_resource_preload_list),
+ )
end
result.html_safe
@@ -630,12 +648,12 @@ module ApplicationHelper
result = +""
if dark_scheme_id != -1
result << <<~HTML
-
-
+
+
HTML
else
result << <<~HTML
-
+
HTML
end
result.html_safe
@@ -647,7 +665,7 @@ module ApplicationHelper
end
def preloaded_json
- return '{}' if @preloaded.blank?
+ return "{}" if @preloaded.blank?
@preloaded.transform_values { |value| escape_unicode(value) }.to_json
end
@@ -658,8 +676,8 @@ module ApplicationHelper
base_uri: Discourse.base_path,
environment: Rails.env,
letter_avatar_version: LetterAvatar.version,
- markdown_it_url: script_asset_path('markdown-it-bundle'),
- service_worker_url: 'service-worker.js',
+ markdown_it_url: script_asset_path("markdown-it-bundle"),
+ service_worker_url: "service-worker.js",
default_locale: SiteSetting.default_locale,
asset_version: Discourse.assets_digest,
disable_custom_css: loading_admin?,
@@ -668,16 +686,14 @@ module ApplicationHelper
enable_js_error_reporting: GlobalSetting.enable_js_error_reporting,
color_scheme_is_dark: dark_color_scheme?,
user_color_scheme_id: scheme_id,
- user_dark_scheme_id: dark_scheme_id
+ user_dark_scheme_id: dark_scheme_id,
}
if Rails.env.development?
setup_data[:svg_icon_list] = SvgSprite.all_icons(theme_id)
- if ENV['DEBUG_PRELOADED_APP_DATA']
- setup_data[:debug_preloaded_app_data] = true
- end
- setup_data[:mb_last_file_change_id] = MessageBus.last_id('/file-change')
+ setup_data[:debug_preloaded_app_data] = true if ENV["DEBUG_PRELOADED_APP_DATA"]
+ setup_data[:mb_last_file_change_id] = MessageBus.last_id("/file-change")
end
if guardian.can_enable_safe_mode? && params["safe_mode"]
@@ -694,10 +710,10 @@ module ApplicationHelper
def get_absolute_image_url(link)
absolute_url = link
- if link.start_with?('//')
+ if link.start_with?("//")
uri = URI(Discourse.base_url)
absolute_url = "#{uri.scheme}:#{link}"
- elsif link.start_with?('/uploads/', '/images/', '/user_avatar/')
+ elsif link.start_with?("/uploads/", "/images/", "/user_avatar/")
absolute_url = "#{Discourse.base_url}#{link}"
elsif GlobalSetting.relative_url_root && link.start_with?(GlobalSetting.relative_url_root)
absolute_url = "#{Discourse.base_url_no_prefix}#{link}"
@@ -713,9 +729,8 @@ module ApplicationHelper
end
def can_sign_up?
- SiteSetting.allow_new_registrations &&
- !SiteSetting.invite_only &&
- !SiteSetting.enable_discourse_connect
+ SiteSetting.allow_new_registrations && !SiteSetting.invite_only &&
+ !SiteSetting.enable_discourse_connect
end
def rss_creator(user)
@@ -725,12 +740,11 @@ module ApplicationHelper
def authentication_data
return @authentication_data if defined?(@authentication_data)
- @authentication_data = begin
- value = cookies[:authentication_data]
- if value
- cookies.delete(:authentication_data, path: Discourse.base_path("/"))
+ @authentication_data =
+ begin
+ value = cookies[:authentication_data]
+ cookies.delete(:authentication_data, path: Discourse.base_path("/")) if value
+ current_user ? nil : value
end
- current_user ? nil : value
- end
end
end
diff --git a/app/helpers/email_helper.rb b/app/helpers/email_helper.rb
index ba14776aff7..64cb028c535 100644
--- a/app/helpers/email_helper.rb
+++ b/app/helpers/email_helper.rb
@@ -1,13 +1,15 @@
# frozen_string_literal: true
-require 'erb'
+require "erb"
module EmailHelper
-
def mailing_list_topic(topic, post_count)
render(
partial: partial_for("mailing_list_post"),
- locals: { topic: topic, post_count: post_count }
+ locals: {
+ topic: topic,
+ post_count: post_count,
+ },
)
end
@@ -26,11 +28,13 @@ module EmailHelper
end
def email_html_template
- EmailStyle.new.html
- .sub('%{email_content}') { capture { yield } }
- .gsub('%{html_lang}', html_lang)
- .gsub('%{dark_mode_meta_tags}', dark_mode_meta_tags)
- .gsub('%{dark_mode_styles}', dark_mode_styles)
+ EmailStyle
+ .new
+ .html
+ .sub("%{email_content}") { capture { yield } }
+ .gsub("%{html_lang}", html_lang)
+ .gsub("%{dark_mode_meta_tags}", dark_mode_meta_tags)
+ .gsub("%{dark_mode_styles}", dark_mode_styles)
.html_safe
end
@@ -118,5 +122,4 @@ module EmailHelper
def partial_for(name)
SiteSetting.private_email? ? "email/secure_#{name}" : "email/#{name}"
end
-
end
diff --git a/app/helpers/embed_helper.rb b/app/helpers/embed_helper.rb
index 42e728ddba2..5e133167fbf 100644
--- a/app/helpers/embed_helper.rb
+++ b/app/helpers/embed_helper.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module EmbedHelper
-
def embed_post_date(dt)
current = Time.now
diff --git a/app/helpers/posts_helper.rb b/app/helpers/posts_helper.rb
index 9a1ed6b563f..ea2c1da006e 100644
--- a/app/helpers/posts_helper.rb
+++ b/app/helpers/posts_helper.rb
@@ -22,9 +22,7 @@ module PostsHelper
url = Discourse.redis.get(key)
# break cache if either slug or topic_id changes
- if url && !url.start_with?(post.topic.url)
- url = nil
- end
+ url = nil if url && !url.start_with?(post.topic.url)
if !url
url = post.canonical_url
diff --git a/app/helpers/qunit_helper.rb b/app/helpers/qunit_helper.rb
index 3ca1b419bfc..2813ed1e9d6 100644
--- a/app/helpers/qunit_helper.rb
+++ b/app/helpers/qunit_helper.rb
@@ -6,10 +6,11 @@ module QunitHelper
return "" if theme.blank?
_, digest = theme.baked_js_tests_with_digest
- src = "#{GlobalSetting.cdn_url}" \
- "#{Discourse.base_path}" \
- "/theme-javascripts/tests/#{theme.id}-#{digest}.js" \
- "?__ws=#{Discourse.current_hostname}"
+ src =
+ "#{GlobalSetting.cdn_url}" \
+ "#{Discourse.base_path}" \
+ "/theme-javascripts/tests/#{theme.id}-#{digest}.js" \
+ "?__ws=#{Discourse.current_hostname}"
"".html_safe
end
end
diff --git a/app/helpers/splash_screen_helper.rb b/app/helpers/splash_screen_helper.rb
index 7dfc4194565..af2ec3824d4 100644
--- a/app/helpers/splash_screen_helper.rb
+++ b/app/helpers/splash_screen_helper.rb
@@ -18,7 +18,10 @@ module SplashScreenHelper
private
def self.load_js
- File.read("#{Rails.root}/app/assets/javascripts/discourse/dist/assets/splash-screen.js").sub("//# sourceMappingURL=splash-screen.map\n", "")
+ File.read("#{Rails.root}/app/assets/javascripts/discourse/dist/assets/splash-screen.js").sub(
+ "//# sourceMappingURL=splash-screen.map\n",
+ "",
+ )
rescue Errno::ENOENT
Rails.logger.error("Unable to load splash screen JS") if Rails.env.production?
"console.log('Unable to load splash screen JS')"
diff --git a/app/helpers/topic_post_bookmarkable_helper.rb b/app/helpers/topic_post_bookmarkable_helper.rb
index 43f5699b876..27bd6935ae9 100644
--- a/app/helpers/topic_post_bookmarkable_helper.rb
+++ b/app/helpers/topic_post_bookmarkable_helper.rb
@@ -9,7 +9,7 @@ module TopicPostBookmarkableHelper
TopicUser.change(
user.id,
topic.id,
- bookmarked: Bookmark.for_user_in_topic(user.id, topic).exists?
+ bookmarked: Bookmark.for_user_in_topic(user.id, topic).exists?,
)
end
end
diff --git a/app/helpers/topics_helper.rb b/app/helpers/topics_helper.rb
index 00204236218..bd595814ae0 100644
--- a/app/helpers/topics_helper.rb
+++ b/app/helpers/topics_helper.rb
@@ -20,5 +20,4 @@ module TopicsHelper
Plugin::Filter.apply(:topic_categories_breadcrumb, topic, breadcrumb)
end
-
end
diff --git a/app/helpers/user_notifications_helper.rb b/app/helpers/user_notifications_helper.rb
index 6d46583532d..e92dbeccd96 100644
--- a/app/helpers/user_notifications_helper.rb
+++ b/app/helpers/user_notifications_helper.rb
@@ -6,9 +6,7 @@ module UserNotificationsHelper
def indent(text, by = 2)
spacer = " " * by
result = +""
- text.each_line do |line|
- result << spacer << line
- end
+ text.each_line { |line| result << spacer << line }
result
end
@@ -32,24 +30,28 @@ module UserNotificationsHelper
end
def first_paragraphs_from(html)
- doc = Nokogiri::HTML5(html)
+ doc = Nokogiri.HTML5(html)
result = +""
length = 0
- doc.css('body > p, aside.onebox, body > ul, body > blockquote').each do |node|
- if node.text.present?
- result << node.to_s
- length += node.inner_text.length
- return result if length >= SiteSetting.digest_min_excerpt_length
+ doc
+ .css("body > p, aside.onebox, body > ul, body > blockquote")
+ .each do |node|
+ if node.text.present?
+ result << node.to_s
+ length += node.inner_text.length
+ return result if length >= SiteSetting.digest_min_excerpt_length
+ end
end
- end
return result unless result.blank?
# If there is no first paragraph with text, return the first paragraph with
# something else (an image) or div (a onebox).
- doc.css('body > p:not(:empty), body > div:not(:empty), body > p > div.lightbox-wrapper img').first
+ doc.css(
+ "body > p:not(:empty), body > div:not(:empty), body > p > div.lightbox-wrapper img",
+ ).first
end
def email_excerpt(html_arg, post = nil)
@@ -58,7 +60,7 @@ module UserNotificationsHelper
end
def normalize_name(name)
- name.downcase.gsub(/[\s_-]/, '')
+ name.downcase.gsub(/[\s_-]/, "")
end
def show_username_on_post(post)
@@ -70,9 +72,7 @@ module UserNotificationsHelper
end
def show_name_on_post(post)
- SiteSetting.enable_names? &&
- SiteSetting.display_name_on_posts? &&
- post.user.name.present? &&
+ SiteSetting.enable_names? && SiteSetting.display_name_on_posts? && post.user.name.present? &&
normalize_name(post.user.name) != normalize_name(post.user.username)
end
@@ -94,7 +94,7 @@ module UserNotificationsHelper
end
def show_image_with_url(url)
- !(url.nil? || url.downcase.end_with?('svg'))
+ !(url.nil? || url.downcase.end_with?("svg"))
end
def email_image_url(basename)
@@ -106,5 +106,4 @@ module UserNotificationsHelper
rescue URI::Error
href
end
-
end
diff --git a/app/jobs/base.rb b/app/jobs/base.rb
index d38e57fcd26..14255c53310 100644
--- a/app/jobs/base.rb
+++ b/app/jobs/base.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
def self.queued
Sidekiq::Stats.new.enqueued
end
@@ -24,7 +23,7 @@ module Jobs
def self.last_job_performed_at
Sidekiq.redis do |r|
- int = r.get('last_job_perform_at')
+ int = r.get("last_job_perform_at")
int ? Time.at(int.to_i) : nil
end
end
@@ -82,9 +81,9 @@ module Jobs
if exception.present?
@data["exception"] = exception # Exception - if job fails a json encoded exception
- @data["status"] = 'failed'
+ @data["status"] = "failed"
else
- @data["status"] = 'success' # Status - fail, success, pending
+ @data["status"] = "success" # Status - fail, success, pending
end
write_to_log
@@ -92,22 +91,27 @@ module Jobs
end
def self.raw_log(message)
- @@logger ||= begin
- f = File.open "#{Rails.root}/log/sidekiq.log", "a"
- f.sync = true
- Logger.new f
- end
+ @@logger ||=
+ begin
+ f = File.open "#{Rails.root}/log/sidekiq.log", "a"
+ f.sync = true
+ Logger.new f
+ end
@@log_queue ||= Queue.new
if !defined?(@@log_thread) || !@@log_thread.alive?
- @@log_thread = Thread.new do
- loop do
- @@logger << @@log_queue.pop
- rescue Exception => e
- Discourse.warn_exception(e, message: "Exception encountered while logging Sidekiq job")
+ @@log_thread =
+ Thread.new do
+ loop do
+ @@logger << @@log_queue.pop
+ rescue Exception => e
+ Discourse.warn_exception(
+ e,
+ message: "Exception encountered while logging Sidekiq job",
+ )
+ end
end
- end
end
@@log_queue.push(message)
@@ -136,18 +140,22 @@ module Jobs
interval = ENV["DISCOURSE_LOG_SIDEKIQ_INTERVAL"]
return if !interval
interval = interval.to_i
- @@interval_thread ||= Thread.new do
- begin
- loop do
- sleep interval
- mutex.synchronize do
- @@active_jobs.each { |j| j.write_to_log if j.current_duration > interval }
+ @@interval_thread ||=
+ Thread.new do
+ begin
+ loop do
+ sleep interval
+ mutex.synchronize do
+ @@active_jobs.each { |j| j.write_to_log if j.current_duration > interval }
+ end
end
+ rescue Exception => e
+ Discourse.warn_exception(
+ e,
+ message: "Sidekiq interval logging thread terminated unexpectedly",
+ )
end
- rescue Exception => e
- Discourse.warn_exception(e, message: "Sidekiq interval logging thread terminated unexpectedly")
end
- end
end
end
@@ -192,15 +200,14 @@ module Jobs
def perform(*args)
opts = args.extract_options!.with_indifferent_access
- if ::Jobs.run_later?
- Sidekiq.redis do |r|
- r.set('last_job_perform_at', Time.now.to_i)
- end
- end
+ Sidekiq.redis { |r| r.set("last_job_perform_at", Time.now.to_i) } if ::Jobs.run_later?
if opts.delete(:sync_exec)
- if opts.has_key?(:current_site_id) && opts[:current_site_id] != RailsMultisite::ConnectionManagement.current_db
- raise ArgumentError.new("You can't connect to another database when executing a job synchronously.")
+ if opts.has_key?(:current_site_id) &&
+ opts[:current_site_id] != RailsMultisite::ConnectionManagement.current_db
+ raise ArgumentError.new(
+ "You can't connect to another database when executing a job synchronously.",
+ )
else
begin
retval = execute(opts)
@@ -224,9 +231,11 @@ module Jobs
exception = {}
RailsMultisite::ConnectionManagement.with_connection(db) do
- job_instrumenter = JobInstrumenter.new(job_class: self.class, opts: opts, db: db, jid: jid)
+ job_instrumenter =
+ JobInstrumenter.new(job_class: self.class, opts: opts, db: db, jid: jid)
begin
- I18n.locale = SiteSetting.default_locale || SiteSettings::DefaultsProvider::DEFAULT_LOCALE
+ I18n.locale =
+ SiteSetting.default_locale || SiteSettings::DefaultsProvider::DEFAULT_LOCALE
I18n.ensure_all_loaded!
begin
logster_env = {}
@@ -256,7 +265,10 @@ module Jobs
if exceptions.length > 0
exceptions.each do |exception_hash|
- Discourse.handle_job_exception(exception_hash[:ex], error_context(opts, exception_hash[:code], exception_hash[:other]))
+ Discourse.handle_job_exception(
+ exception_hash[:ex],
+ error_context(opts, exception_hash[:code], exception_hash[:other]),
+ )
end
raise HandledExceptionWrapper.new(exceptions[0][:ex])
end
@@ -265,7 +277,6 @@ module Jobs
ensure
ActiveRecord::Base.connection_handler.clear_active_connections!
end
-
end
class HandledExceptionWrapper < StandardError
@@ -280,9 +291,7 @@ module Jobs
extend MiniScheduler::Schedule
def perform(*args)
- if (::Jobs::Heartbeat === self) || !Discourse.readonly_mode?
- super
- end
+ super if (::Jobs::Heartbeat === self) || !Discourse.readonly_mode?
end
end
@@ -307,30 +316,21 @@ module Jobs
# Simulate the args being dumped/parsed through JSON
parsed_opts = JSON.parse(JSON.dump(opts))
- if opts != parsed_opts
- Discourse.deprecate(<<~TEXT.squish, since: "2.9", drop_from: "3.0")
+ Discourse.deprecate(<<~TEXT.squish, since: "2.9", drop_from: "3.0") if opts != parsed_opts
#{klass.name} was enqueued with argument values which do not cleanly serialize to/from JSON.
This means that the job will be run with slightly different values than the ones supplied to `enqueue`.
Argument values should be strings, booleans, numbers, or nil (or arrays/hashes of those value types).
TEXT
- end
opts = parsed_opts
if ::Jobs.run_later?
- hash = {
- 'class' => klass,
- 'args' => [opts]
- }
+ hash = { "class" => klass, "args" => [opts] }
if delay
- if delay.to_f > 0
- hash['at'] = Time.now.to_f + delay.to_f
- end
+ hash["at"] = Time.now.to_f + delay.to_f if delay.to_f > 0
end
- if queue
- hash['queue'] = queue
- end
+ hash["queue"] = queue if queue
DB.after_commit { klass.client_push(hash) }
else
@@ -338,9 +338,7 @@ module Jobs
opts["sync_exec"] = true
if Rails.env == "development"
- Scheduler::Defer.later("job") do
- klass.new.perform(opts)
- end
+ Scheduler::Defer.later("job") { klass.new.perform(opts) }
else
# Run the job synchronously
# But never run a job inside another job
@@ -368,7 +366,6 @@ module Jobs
end
end
end
-
end
def self.enqueue_in(secs, job_name, opts = {})
diff --git a/app/jobs/concerns/skippable.rb b/app/jobs/concerns/skippable.rb
index 30d176e2312..dfc6adf2231 100644
--- a/app/jobs/concerns/skippable.rb
+++ b/app/jobs/concerns/skippable.rb
@@ -3,24 +3,22 @@
module Skippable
extend ActiveSupport::Concern
- def create_skipped_email_log(email_type:,
- to_address:,
- user_id:,
- post_id:,
- reason_type:)
-
+ def create_skipped_email_log(email_type:, to_address:, user_id:, post_id:, reason_type:)
attributes = {
email_type: email_type,
to_address: to_address,
user_id: user_id,
post_id: post_id,
- reason_type: reason_type
+ reason_type: reason_type,
}
if reason_type == SkippedEmailLog.reason_types[:exceeded_emails_limit]
- exists = SkippedEmailLog.exists?({
- created_at: (Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)
- }.merge!(attributes.except(:post_id)))
+ exists =
+ SkippedEmailLog.exists?(
+ { created_at: (Time.zone.now.beginning_of_day..Time.zone.now.end_of_day) }.merge!(
+ attributes.except(:post_id),
+ ),
+ )
return if exists
end
diff --git a/app/jobs/onceoff/clean_up_post_timings.rb b/app/jobs/onceoff/clean_up_post_timings.rb
index 1399ddaa806..0e4088518c2 100644
--- a/app/jobs/onceoff/clean_up_post_timings.rb
+++ b/app/jobs/onceoff/clean_up_post_timings.rb
@@ -2,7 +2,6 @@
module Jobs
class CleanUpPostTimings < ::Jobs::Onceoff
-
# Remove post timings that are remnants of previous post moves
# or other shenanigans and don't reference a valid user or post anymore.
def execute_onceoff(args)
diff --git a/app/jobs/onceoff/clean_up_sidekiq_statistic.rb b/app/jobs/onceoff/clean_up_sidekiq_statistic.rb
index 7b51cde58b5..74147a00915 100644
--- a/app/jobs/onceoff/clean_up_sidekiq_statistic.rb
+++ b/app/jobs/onceoff/clean_up_sidekiq_statistic.rb
@@ -3,7 +3,7 @@
module Jobs
class CleanUpSidekiqStatistic < ::Jobs::Onceoff
def execute_onceoff(args)
- Discourse.redis.without_namespace.del('sidekiq:sidekiq:statistic')
+ Discourse.redis.without_namespace.del("sidekiq:sidekiq:statistic")
end
end
end
diff --git a/app/jobs/onceoff/clean_up_user_export_topics.rb b/app/jobs/onceoff/clean_up_user_export_topics.rb
index 8e5be5bf27b..e6d62c87c5f 100644
--- a/app/jobs/onceoff/clean_up_user_export_topics.rb
+++ b/app/jobs/onceoff/clean_up_user_export_topics.rb
@@ -3,14 +3,18 @@
module Jobs
class CleanUpUserExportTopics < ::Jobs::Onceoff
def execute_onceoff(args)
- translated_keys = I18n.available_locales.map do |l|
- I18n.with_locale(:"#{l}") { I18n.t("system_messages.csv_export_succeeded.subject_template") }
- end.uniq
+ translated_keys =
+ I18n
+ .available_locales
+ .map do |l|
+ I18n.with_locale(:"#{l}") do
+ I18n.t("system_messages.csv_export_succeeded.subject_template")
+ end
+ end
+ .uniq
slugs = []
- translated_keys.each do |k|
- slugs << "%-#{Slug.for(k.gsub('[%{export_title}]', ''))}"
- end
+ translated_keys.each { |k| slugs << "%-#{Slug.for(k.gsub("[%{export_title}]", ""))}" }
# "[%{export_title}] 資料匯出已完成" gets converted to "%-topic", do not match that slug.
slugs = slugs.reject { |s| s == "%-topic" }
diff --git a/app/jobs/onceoff/correct_missing_dualstack_urls.rb b/app/jobs/onceoff/correct_missing_dualstack_urls.rb
index 6cdfa55e847..d96b8ac0227 100644
--- a/app/jobs/onceoff/correct_missing_dualstack_urls.rb
+++ b/app/jobs/onceoff/correct_missing_dualstack_urls.rb
@@ -9,7 +9,7 @@ module Jobs
return if !base_url.match?(/s3\.dualstack/)
- old = base_url.sub('s3.dualstack.', 's3-')
+ old = base_url.sub("s3.dualstack.", "s3-")
old_like = %"#{old}%"
DB.exec(<<~SQL, from: old, to: base_url, old_like: old_like)
diff --git a/app/jobs/onceoff/create_tags_search_index.rb b/app/jobs/onceoff/create_tags_search_index.rb
index f7617074260..a0bea42331b 100644
--- a/app/jobs/onceoff/create_tags_search_index.rb
+++ b/app/jobs/onceoff/create_tags_search_index.rb
@@ -3,9 +3,9 @@
module Jobs
class CreateTagsSearchIndex < ::Jobs::Onceoff
def execute_onceoff(args)
- DB.query('select id, name from tags').each do |t|
- SearchIndexer.update_tags_index(t.id, t.name)
- end
+ DB
+ .query("select id, name from tags")
+ .each { |t| SearchIndexer.update_tags_index(t.id, t.name) }
end
end
end
diff --git a/app/jobs/onceoff/fix_encoded_category_slugs.rb b/app/jobs/onceoff/fix_encoded_category_slugs.rb
index 28947125d90..2af1b6f759a 100644
--- a/app/jobs/onceoff/fix_encoded_category_slugs.rb
+++ b/app/jobs/onceoff/fix_encoded_category_slugs.rb
@@ -1,17 +1,18 @@
# frozen_string_literal: true
module Jobs
-
class FixEncodedCategorySlugs < ::Jobs::Onceoff
def execute_onceoff(args)
- return unless SiteSetting.slug_generation_method == 'encoded'
+ return unless SiteSetting.slug_generation_method == "encoded"
#Make custom categories slugs nil and let the app regenerate with proper encoded ones
- Category.all.reject { |c| c.seeded? }.each do |c|
- c.slug = nil
- c.save!
- end
+ Category
+ .all
+ .reject { |c| c.seeded? }
+ .each do |c|
+ c.slug = nil
+ c.save!
+ end
end
end
-
end
diff --git a/app/jobs/onceoff/fix_encoded_topic_slugs.rb b/app/jobs/onceoff/fix_encoded_topic_slugs.rb
index 4640493fb9a..f7463a58d6a 100644
--- a/app/jobs/onceoff/fix_encoded_topic_slugs.rb
+++ b/app/jobs/onceoff/fix_encoded_topic_slugs.rb
@@ -1,14 +1,12 @@
# frozen_string_literal: true
module Jobs
-
class FixEncodedTopicSlugs < ::Jobs::Onceoff
def execute_onceoff(args)
- return unless SiteSetting.slug_generation_method == 'encoded'
+ return unless SiteSetting.slug_generation_method == "encoded"
#Make all slugs nil and let the app regenerate with proper encoded ones
Topic.update_all(slug: nil)
end
end
-
end
diff --git a/app/jobs/onceoff/fix_featured_link_for_topics.rb b/app/jobs/onceoff/fix_featured_link_for_topics.rb
index 337d7d2efae..0b4f67ab9f0 100644
--- a/app/jobs/onceoff/fix_featured_link_for_topics.rb
+++ b/app/jobs/onceoff/fix_featured_link_for_topics.rb
@@ -3,15 +3,17 @@
module Jobs
class FixFeaturedLinkForTopics < ::Jobs::Onceoff
def execute_onceoff(args)
- Topic.where("featured_link IS NOT NULL").find_each do |topic|
- featured_link = topic.featured_link
+ Topic
+ .where("featured_link IS NOT NULL")
+ .find_each do |topic|
+ featured_link = topic.featured_link
- begin
- URI.parse(featured_link)
- rescue URI::Error
- topic.update(featured_link: URI.extract(featured_link).first)
+ begin
+ URI.parse(featured_link)
+ rescue URI::Error
+ topic.update(featured_link: URI.extract(featured_link).first)
+ end
end
- end
end
end
end
diff --git a/app/jobs/onceoff/fix_invalid_gravatar_uploads.rb b/app/jobs/onceoff/fix_invalid_gravatar_uploads.rb
index 515b8058717..2171c2d03fd 100644
--- a/app/jobs/onceoff/fix_invalid_gravatar_uploads.rb
+++ b/app/jobs/onceoff/fix_invalid_gravatar_uploads.rb
@@ -3,16 +3,23 @@
module Jobs
class FixInvalidGravatarUploads < ::Jobs::Onceoff
def execute_onceoff(args)
- Upload.where(original_filename: "gravatar.png").find_each do |upload|
- # note, this still feels pretty expensive for a once off
- # we may need to re-evaluate this
- extension = FastImage.type(Discourse.store.path_for(upload)) rescue nil
- current_extension = upload.extension
+ Upload
+ .where(original_filename: "gravatar.png")
+ .find_each do |upload|
+ # note, this still feels pretty expensive for a once off
+ # we may need to re-evaluate this
+ extension =
+ begin
+ FastImage.type(Discourse.store.path_for(upload))
+ rescue StandardError
+ nil
+ end
+ current_extension = upload.extension
- if extension.to_s.downcase != current_extension.to_s.downcase
- upload&.user&.user_avatar&.update_columns(last_gravatar_download_attempt: nil)
+ if extension.to_s.downcase != current_extension.to_s.downcase
+ upload&.user&.user_avatar&.update_columns(last_gravatar_download_attempt: nil)
+ end
end
- end
end
end
end
diff --git a/app/jobs/onceoff/fix_primary_emails_for_staged_users.rb b/app/jobs/onceoff/fix_primary_emails_for_staged_users.rb
index 5fb9ff218ef..72f171d1943 100644
--- a/app/jobs/onceoff/fix_primary_emails_for_staged_users.rb
+++ b/app/jobs/onceoff/fix_primary_emails_for_staged_users.rb
@@ -7,22 +7,22 @@ module Jobs
acting_user = Discourse.system_user
destroyer = UserDestroyer.new(acting_user)
- users.group("email_tokens.email")
+ users
+ .group("email_tokens.email")
.having("COUNT(email_tokens.email) > 1")
.count
.each_key do |email|
+ query = users.where("email_tokens.email = ?", email).order(id: :asc)
- query = users.where("email_tokens.email = ?", email).order(id: :asc)
+ original_user = query.first
- original_user = query.first
-
- query.offset(1).each do |user|
- user.posts.each do |post|
- post.set_owner(original_user, acting_user)
- end
- destroyer.destroy(user, context: I18n.t("user.destroy_reasons.fixed_primary_email"))
+ query
+ .offset(1)
+ .each do |user|
+ user.posts.each { |post| post.set_owner(original_user, acting_user) }
+ destroyer.destroy(user, context: I18n.t("user.destroy_reasons.fixed_primary_email"))
+ end
end
- end
DB.exec <<~SQL
INSERT INTO user_emails (
diff --git a/app/jobs/onceoff/fix_retro_anniversary.rb b/app/jobs/onceoff/fix_retro_anniversary.rb
index a6ab1c566f4..92eaeb8011a 100644
--- a/app/jobs/onceoff/fix_retro_anniversary.rb
+++ b/app/jobs/onceoff/fix_retro_anniversary.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class FixRetroAnniversary < ::Jobs::Onceoff
def execute_onceoff(args)
return unless SiteSetting.enable_badges
@@ -16,19 +15,19 @@ module Jobs
users.each do |u|
first = u.first_granted_at
- badges = UserBadge.where(
- "badge_id = ? AND user_id = ? AND granted_at > ?",
- Badge::Anniversary,
- u.user_id,
- first
- ).order('granted_at')
+ badges =
+ UserBadge.where(
+ "badge_id = ? AND user_id = ? AND granted_at > ?",
+ Badge::Anniversary,
+ u.user_id,
+ first,
+ ).order("granted_at")
badges.each_with_index do |b, idx|
award_date = (first + (idx + 1).years)
UserBadge.where(id: b.id).update_all(["granted_at = ?", award_date])
end
end
-
end
end
end
diff --git a/app/jobs/onceoff/fix_s3_etags.rb b/app/jobs/onceoff/fix_s3_etags.rb
index 226b09e9372..156b3b2ebbc 100644
--- a/app/jobs/onceoff/fix_s3_etags.rb
+++ b/app/jobs/onceoff/fix_s3_etags.rb
@@ -2,10 +2,10 @@
module Jobs
class FixS3Etags < ::Jobs::Onceoff
-
def execute_onceoff(args)
[Upload, OptimizedImage].each do |model|
- sql = "UPDATE #{model.table_name} SET etag = REGEXP_REPLACE(etag, '\"', '', 'g') WHERE etag LIKE '\"%\"'"
+ sql =
+ "UPDATE #{model.table_name} SET etag = REGEXP_REPLACE(etag, '\"', '', 'g') WHERE etag LIKE '\"%\"'"
DB.exec(sql)
end
end
diff --git a/app/jobs/onceoff/grant_emoji.rb b/app/jobs/onceoff/grant_emoji.rb
index 5abdb34d5d4..40efada65ce 100644
--- a/app/jobs/onceoff/grant_emoji.rb
+++ b/app/jobs/onceoff/grant_emoji.rb
@@ -1,25 +1,25 @@
# frozen_string_literal: true
module Jobs
-
class GrantEmoji < ::Jobs::Onceoff
def execute_onceoff(args)
return unless SiteSetting.enable_badges
to_award = {}
- Post.secured(Guardian.new)
+ Post
+ .secured(Guardian.new)
.select(:id, :created_at, :cooked, :user_id)
.visible
.public_posts
.where("cooked LIKE '%emoji%'")
.find_in_batches do |group|
- group.each do |p|
- doc = Nokogiri::HTML5::fragment(p.cooked)
- if (doc.css("img.emoji") - doc.css(".quote img")).size > 0
- to_award[p.user_id] ||= { post_id: p.id, created_at: p.created_at }
+ group.each do |p|
+ doc = Nokogiri::HTML5.fragment(p.cooked)
+ if (doc.css("img.emoji") - doc.css(".quote img")).size > 0
+ to_award[p.user_id] ||= { post_id: p.id, created_at: p.created_at }
+ end
end
end
- end
to_award.each do |user_id, opts|
user = User.where(id: user_id).first
@@ -30,7 +30,5 @@ module Jobs
def badge
Badge.find(Badge::FirstEmoji)
end
-
end
-
end
diff --git a/app/jobs/onceoff/grant_first_reply_by_email.rb b/app/jobs/onceoff/grant_first_reply_by_email.rb
index c0287205d76..0f8129077c2 100644
--- a/app/jobs/onceoff/grant_first_reply_by_email.rb
+++ b/app/jobs/onceoff/grant_first_reply_by_email.rb
@@ -1,24 +1,21 @@
# frozen_string_literal: true
module Jobs
-
class GrantFirstReplyByEmail < ::Jobs::Onceoff
-
def execute_onceoff(args)
return unless SiteSetting.enable_badges
to_award = {}
- Post.select(:id, :created_at, :user_id)
+ Post
+ .select(:id, :created_at, :user_id)
.secured(Guardian.new)
.visible
.public_posts
.where(via_email: true)
.where("post_number > 1")
.find_in_batches do |group|
- group.each do |p|
- to_award[p.user_id] ||= { post_id: p.id, created_at: p.created_at }
+ group.each { |p| to_award[p.user_id] ||= { post_id: p.id, created_at: p.created_at } }
end
- end
to_award.each do |user_id, opts|
user = User.where(id: user_id).first
@@ -29,7 +26,5 @@ module Jobs
def badge
Badge.find(Badge::FirstReplyByEmail)
end
-
end
-
end
diff --git a/app/jobs/onceoff/grant_onebox.rb b/app/jobs/onceoff/grant_onebox.rb
index 66d2cf26706..5eb6ec0538f 100644
--- a/app/jobs/onceoff/grant_onebox.rb
+++ b/app/jobs/onceoff/grant_onebox.rb
@@ -1,35 +1,34 @@
# frozen_string_literal: true
module Jobs
-
class GrantOnebox < ::Jobs::Onceoff
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
def execute_onceoff(args)
return unless SiteSetting.enable_badges
to_award = {}
- Post.secured(Guardian.new)
+ Post
+ .secured(Guardian.new)
.select(:id, :created_at, :raw, :user_id)
.visible
.public_posts
.where("raw LIKE '%http%'")
.find_in_batches do |group|
- group.each do |p|
- begin
- # Note we can't use `p.cooked` here because oneboxes have been cooked out
- cooked = PrettyText.cook(p.raw)
- doc = Nokogiri::HTML5::fragment(cooked)
- if doc.search('a.onebox').size > 0
- to_award[p.user_id] ||= { post_id: p.id, created_at: p.created_at }
+ group.each do |p|
+ begin
+ # Note we can't use `p.cooked` here because oneboxes have been cooked out
+ cooked = PrettyText.cook(p.raw)
+ doc = Nokogiri::HTML5.fragment(cooked)
+ if doc.search("a.onebox").size > 0
+ to_award[p.user_id] ||= { post_id: p.id, created_at: p.created_at }
+ end
+ rescue StandardError
+ nil # if there is a problem cooking we don't care
end
- rescue
- nil # if there is a problem cooking we don't care
end
end
- end
-
to_award.each do |user_id, opts|
user = User.where(id: user_id).first
BadgeGranter.grant(badge, user, opts) if user
@@ -39,7 +38,5 @@ module Jobs
def badge
Badge.find(Badge::FirstOnebox)
end
-
end
-
end
diff --git a/app/jobs/onceoff/migrate_badge_image_to_uploads.rb b/app/jobs/onceoff/migrate_badge_image_to_uploads.rb
index 5585a508c2f..b45595498ff 100644
--- a/app/jobs/onceoff/migrate_badge_image_to_uploads.rb
+++ b/app/jobs/onceoff/migrate_badge_image_to_uploads.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'uri'
+require "uri"
module Jobs
class MigrateBadgeImageToUploads < ::Jobs::Onceoff
@@ -14,72 +14,79 @@ module Jobs
SQL
return unless column_exists
- Badge.where.not(image: nil).select(:id, :image_upload_id, :image).each do |badge|
- if badge.image_upload.present?
- DB.exec("UPDATE badges SET image = NULL WHERE id = ?", badge.id)
- next
- end
-
- image_url = badge[:image]
- next if image_url.blank? || image_url !~ URI.regexp
-
- count = 0
- file = nil
- sleep_interval = 5
-
- loop do
- url = UrlHelper.absolute_without_cdn(image_url)
-
- begin
- file = FileHelper.download(
- url,
- max_file_size: [
- SiteSetting.max_image_size_kb.kilobytes,
- 20.megabytes
- ].max,
- tmp_file_name: 'tmp_badge_image_upload',
- skip_rate_limit: true,
- follow_redirect: true
- )
- rescue OpenURI::HTTPError,
- OpenSSL::SSL::SSLError,
- Net::OpenTimeout,
- Net::ReadTimeout,
- Errno::ECONNREFUSED,
- EOFError,
- SocketError,
- Discourse::InvalidParameters => e
-
- logger.error(
- "Error encountered when trying to download from URL '#{image_url}' " +
- "for badge '#{badge[:id]}'.\n#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
- )
+ Badge
+ .where.not(image: nil)
+ .select(:id, :image_upload_id, :image)
+ .each do |badge|
+ if badge.image_upload.present?
+ DB.exec("UPDATE badges SET image = NULL WHERE id = ?", badge.id)
+ next
end
- count += 1
- break if file
+ image_url = badge[:image]
+ next if image_url.blank? || image_url !~ URI.regexp
- logger.warn(
- "Failed to download image from #{url} for badge '#{badge[:id]}'. Retrying (#{count}/3)..."
- )
- break if count >= 3
- sleep(count * sleep_interval)
+ count = 0
+ file = nil
+ sleep_interval = 5
+
+ loop do
+ url = UrlHelper.absolute_without_cdn(image_url)
+
+ begin
+ file =
+ FileHelper.download(
+ url,
+ max_file_size: [SiteSetting.max_image_size_kb.kilobytes, 20.megabytes].max,
+ tmp_file_name: "tmp_badge_image_upload",
+ skip_rate_limit: true,
+ follow_redirect: true,
+ )
+ rescue OpenURI::HTTPError,
+ OpenSSL::SSL::SSLError,
+ Net::OpenTimeout,
+ Net::ReadTimeout,
+ Errno::ECONNREFUSED,
+ EOFError,
+ SocketError,
+ Discourse::InvalidParameters => e
+ logger.error(
+ "Error encountered when trying to download from URL '#{image_url}' " +
+ "for badge '#{badge[:id]}'.\n#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}",
+ )
+ end
+
+ count += 1
+ break if file
+
+ logger.warn(
+ "Failed to download image from #{url} for badge '#{badge[:id]}'. Retrying (#{count}/3)...",
+ )
+ break if count >= 3
+ sleep(count * sleep_interval)
+ end
+
+ next if file.blank?
+
+ upload =
+ UploadCreator.new(
+ file,
+ "image_for_badge_#{badge[:id]}",
+ origin: UrlHelper.absolute(image_url),
+ ).create_for(Discourse.system_user.id)
+
+ if upload.errors.count > 0 || upload&.id.blank?
+ logger.error(
+ "Failed to create an upload for the image of badge '#{badge[:id]}'. Error: #{upload.errors.full_messages}",
+ )
+ else
+ DB.exec(
+ "UPDATE badges SET image = NULL, image_upload_id = ? WHERE id = ?",
+ upload.id,
+ badge[:id],
+ )
+ end
end
-
- next if file.blank?
-
- upload = UploadCreator.new(
- file,
- "image_for_badge_#{badge[:id]}",
- origin: UrlHelper.absolute(image_url)
- ).create_for(Discourse.system_user.id)
-
- if upload.errors.count > 0 || upload&.id.blank?
- logger.error("Failed to create an upload for the image of badge '#{badge[:id]}'. Error: #{upload.errors.full_messages}")
- else
- DB.exec("UPDATE badges SET image = NULL, image_upload_id = ? WHERE id = ?", upload.id, badge[:id])
- end
- end
end
private
diff --git a/app/jobs/onceoff/migrate_censored_words.rb b/app/jobs/onceoff/migrate_censored_words.rb
index 5de876107be..605321d94cd 100644
--- a/app/jobs/onceoff/migrate_censored_words.rb
+++ b/app/jobs/onceoff/migrate_censored_words.rb
@@ -5,9 +5,10 @@ module Jobs
def execute_onceoff(args)
row = DB.query_single("SELECT value FROM site_settings WHERE name = 'censored_words'")
if row.count > 0
- row.first.split('|').each do |word|
- WatchedWord.create(word: word, action: WatchedWord.actions[:censor])
- end
+ row
+ .first
+ .split("|")
+ .each { |word| WatchedWord.create(word: word, action: WatchedWord.actions[:censor]) }
end
end
end
diff --git a/app/jobs/onceoff/migrate_custom_emojis.rb b/app/jobs/onceoff/migrate_custom_emojis.rb
index f359a23c999..62fdc6da450 100644
--- a/app/jobs/onceoff/migrate_custom_emojis.rb
+++ b/app/jobs/onceoff/migrate_custom_emojis.rb
@@ -9,11 +9,10 @@ module Jobs
name = File.basename(path, File.extname(path))
File.open(path) do |file|
- upload = UploadCreator.new(
- file,
- File.basename(path),
- type: 'custom_emoji'
- ).create_for(Discourse.system_user.id)
+ upload =
+ UploadCreator.new(file, File.basename(path), type: "custom_emoji").create_for(
+ Discourse.system_user.id,
+ )
if upload.persisted?
custom_emoji = CustomEmoji.new(name: name, upload: upload)
@@ -22,16 +21,16 @@ module Jobs
warn("Failed to create custom emoji '#{name}': #{custom_emoji.errors.full_messages}")
end
else
- warn("Failed to create upload for '#{name}' custom emoji: #{upload.errors.full_messages}")
+ warn(
+ "Failed to create upload for '#{name}' custom emoji: #{upload.errors.full_messages}",
+ )
end
end
end
Emoji.clear_cache
- Post.where("cooked LIKE ?", "%#{Emoji.base_url}%").find_each do |post|
- post.rebake!
- end
+ Post.where("cooked LIKE ?", "%#{Emoji.base_url}%").find_each { |post| post.rebake! }
end
def warn(message)
diff --git a/app/jobs/onceoff/migrate_featured_links.rb b/app/jobs/onceoff/migrate_featured_links.rb
index 45f4c11defe..9139854fccf 100644
--- a/app/jobs/onceoff/migrate_featured_links.rb
+++ b/app/jobs/onceoff/migrate_featured_links.rb
@@ -1,30 +1,35 @@
# frozen_string_literal: true
module Jobs
-
class MigrateFeaturedLinks < ::Jobs::Onceoff
-
def execute_onceoff(args)
- TopicCustomField.where(name: "featured_link").find_each do |tcf|
- if tcf.value.present?
- Topic.where(id: tcf.topic_id).update_all(featured_link: tcf.value)
+ TopicCustomField
+ .where(name: "featured_link")
+ .find_each do |tcf|
+ Topic.where(id: tcf.topic_id).update_all(featured_link: tcf.value) if tcf.value.present?
end
- end
# Plugin behaviour: only categories explicitly allowed to have featured links can have them.
# All others implicitly DO NOT allow them.
# If no categories were explicitly allowed to have them, then all implicitly DID allow them.
- allowed = CategoryCustomField.where(name: "topic_featured_link_allowed").where(value: "true").pluck(:category_id)
+ allowed =
+ CategoryCustomField
+ .where(name: "topic_featured_link_allowed")
+ .where(value: "true")
+ .pluck(:category_id)
if !allowed.empty?
# all others are not allowed
Category.where.not(id: allowed).update_all(topic_featured_link_allowed: false)
else
- not_allowed = CategoryCustomField.where(name: "topic_featured_link_allowed").where.not(value: "true").pluck(:category_id)
+ not_allowed =
+ CategoryCustomField
+ .where(name: "topic_featured_link_allowed")
+ .where.not(value: "true")
+ .pluck(:category_id)
Category.where(id: not_allowed).update_all(topic_featured_link_allowed: false)
end
end
end
-
end
diff --git a/app/jobs/onceoff/migrate_tagging_plugin.rb b/app/jobs/onceoff/migrate_tagging_plugin.rb
index d92d5692f48..8420b7543f9 100644
--- a/app/jobs/onceoff/migrate_tagging_plugin.rb
+++ b/app/jobs/onceoff/migrate_tagging_plugin.rb
@@ -1,18 +1,25 @@
# frozen_string_literal: true
module Jobs
-
class MigrateTaggingPlugin < ::Jobs::Onceoff
-
def execute_onceoff(args)
- all_tags = TopicCustomField.where(name: "tags").select('DISTINCT value').all.map(&:value)
- tag_id_lookup = Tag.create(all_tags.map { |tag_name| { name: tag_name } }).inject({}) { |h, v| h[v.name] = v.id; h }
+ all_tags = TopicCustomField.where(name: "tags").select("DISTINCT value").all.map(&:value)
+ tag_id_lookup =
+ Tag
+ .create(all_tags.map { |tag_name| { name: tag_name } })
+ .inject({}) do |h, v|
+ h[v.name] = v.id
+ h
+ end
- TopicCustomField.where(name: "tags").find_each do |tcf|
- TopicTag.create(topic_id: tcf.topic_id, tag_id: tag_id_lookup[tcf.value] || Tag.find_by_name(tcf.value).try(:id))
- end
+ TopicCustomField
+ .where(name: "tags")
+ .find_each do |tcf|
+ TopicTag.create(
+ topic_id: tcf.topic_id,
+ tag_id: tag_id_lookup[tcf.value] || Tag.find_by_name(tcf.value).try(:id),
+ )
+ end
end
-
end
-
end
diff --git a/app/jobs/onceoff/migrate_upload_extensions.rb b/app/jobs/onceoff/migrate_upload_extensions.rb
index 846944e285e..fd6eb72a43c 100644
--- a/app/jobs/onceoff/migrate_upload_extensions.rb
+++ b/app/jobs/onceoff/migrate_upload_extensions.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class MigrateUploadExtensions < ::Jobs::Onceoff
def execute_onceoff(args)
Upload.find_each do |upload|
diff --git a/app/jobs/onceoff/onceoff.rb b/app/jobs/onceoff/onceoff.rb
index d10b1f41a66..df9c94e54d0 100644
--- a/app/jobs/onceoff/onceoff.rb
+++ b/app/jobs/onceoff/onceoff.rb
@@ -4,7 +4,7 @@ class Jobs::Onceoff < ::Jobs::Base
sidekiq_options retry: false
def self.name_for(klass)
- klass.name.sub(/^Jobs\:\:/, '')
+ klass.name.sub(/^Jobs\:\:/, "")
end
def running_key_name
@@ -26,18 +26,17 @@ class Jobs::Onceoff < ::Jobs::Base
Discourse.redis.del(running_key_name) if has_lock
end
end
-
end
def self.enqueue_all
previously_ran = OnceoffLog.pluck(:job_name).uniq
- ObjectSpace.each_object(Class).select { |klass| klass < self }.each do |klass|
- job_name = name_for(klass)
- unless previously_ran.include?(job_name)
- Jobs.enqueue(job_name.underscore.to_sym)
+ ObjectSpace
+ .each_object(Class)
+ .select { |klass| klass < self }
+ .each do |klass|
+ job_name = name_for(klass)
+ Jobs.enqueue(job_name.underscore.to_sym) unless previously_ran.include?(job_name)
end
- end
end
-
end
diff --git a/app/jobs/onceoff/post_uploads_recovery.rb b/app/jobs/onceoff/post_uploads_recovery.rb
index 5f942209eb1..75d0b42c7bc 100644
--- a/app/jobs/onceoff/post_uploads_recovery.rb
+++ b/app/jobs/onceoff/post_uploads_recovery.rb
@@ -6,17 +6,11 @@ module Jobs
MAX_PERIOD = 120
def execute_onceoff(args)
- UploadRecovery.new.recover(Post.where(
- "baked_at >= ?",
- grace_period.days.ago
- ))
+ UploadRecovery.new.recover(Post.where("baked_at >= ?", grace_period.days.ago))
end
def grace_period
- SiteSetting.purge_deleted_uploads_grace_period_days.clamp(
- MIN_PERIOD,
- MAX_PERIOD
- )
+ SiteSetting.purge_deleted_uploads_grace_period_days.clamp(MIN_PERIOD, MAX_PERIOD)
end
end
end
diff --git a/app/jobs/onceoff/retro_grant_anniversary.rb b/app/jobs/onceoff/retro_grant_anniversary.rb
index b0ca206bff9..cba25214b30 100644
--- a/app/jobs/onceoff/retro_grant_anniversary.rb
+++ b/app/jobs/onceoff/retro_grant_anniversary.rb
@@ -1,16 +1,12 @@
# frozen_string_literal: true
module Jobs
-
class RetroGrantAnniversary < ::Jobs::Onceoff
def execute_onceoff(args)
return unless SiteSetting.enable_badges
# Fill in the years of anniversary badges we missed
- (2..3).each do |year|
- ::Jobs::GrantAnniversaryBadges.new.execute(start_date: year.years.ago)
- end
+ (2..3).each { |year| ::Jobs::GrantAnniversaryBadges.new.execute(start_date: year.years.ago) }
end
end
-
end
diff --git a/app/jobs/regular/admin_confirmation_email.rb b/app/jobs/regular/admin_confirmation_email.rb
index 48746de4084..89ab3a4f2fc 100644
--- a/app/jobs/regular/admin_confirmation_email.rb
+++ b/app/jobs/regular/admin_confirmation_email.rb
@@ -2,7 +2,7 @@
module Jobs
class AdminConfirmationEmail < ::Jobs::Base
- sidekiq_options queue: 'critical'
+ sidekiq_options queue: "critical"
def execute(args)
to_address = args[:to_address]
@@ -18,6 +18,5 @@ module Jobs
message = AdminConfirmationMailer.send_email(to_address, target_email, target_username, token)
Email::Sender.new(message, :admin_confirmation_message).send
end
-
end
end
diff --git a/app/jobs/regular/anonymize_user.rb b/app/jobs/regular/anonymize_user.rb
index 7343163e49b..7ae14c11732 100644
--- a/app/jobs/regular/anonymize_user.rb
+++ b/app/jobs/regular/anonymize_user.rb
@@ -2,8 +2,7 @@
module Jobs
class AnonymizeUser < ::Jobs::Base
-
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
def execute(args)
@user_id = args[:user_id]
@@ -22,7 +21,8 @@ module Jobs
EmailLog.where(user_id: @user_id).delete_all
IncomingEmail.where("user_id = ? OR from_address = ?", @user_id, @prev_email).delete_all
- Post.with_deleted
+ Post
+ .with_deleted
.where(user_id: @user_id)
.where.not(raw_email: nil)
.update_all(raw_email: nil)
@@ -30,17 +30,17 @@ module Jobs
anonymize_user_fields
end
- def ip_where(column = 'user_id')
+ def ip_where(column = "user_id")
["#{column} = :user_id AND ip_address IS NOT NULL", user_id: @user_id]
end
def anonymize_ips(new_ip)
- IncomingLink.where(ip_where('current_user_id')).update_all(ip_address: new_ip)
+ IncomingLink.where(ip_where("current_user_id")).update_all(ip_address: new_ip)
ScreenedEmail.where(email: @prev_email).update_all(ip_address: new_ip)
SearchLog.where(ip_where).update_all(ip_address: new_ip)
TopicLinkClick.where(ip_where).update_all(ip_address: new_ip)
TopicViewItem.where(ip_where).update_all(ip_address: new_ip)
- UserHistory.where(ip_where('acting_user_id')).update_all(ip_address: new_ip)
+ UserHistory.where(ip_where("acting_user_id")).update_all(ip_address: new_ip)
UserProfileView.where(ip_where).update_all(ip_address: new_ip)
# UserHistory for delete_user logs the user's IP. Note this is quite ugly but we don't
diff --git a/app/jobs/regular/automatic_group_membership.rb b/app/jobs/regular/automatic_group_membership.rb
index 6831078842d..d2d043a39b3 100644
--- a/app/jobs/regular/automatic_group_membership.rb
+++ b/app/jobs/regular/automatic_group_membership.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module Jobs
-
class AutomaticGroupMembership < ::Jobs::Base
-
def execute(args)
group_id = args[:group_id]
raise Discourse::InvalidParameters.new(:group_id) if group_id.blank?
@@ -14,13 +12,13 @@ module Jobs
domains = group.automatic_membership_email_domains
return if domains.blank?
- Group.automatic_membership_users(domains).find_each do |user|
- next unless user.email_confirmed?
- group.add(user, automatic: true)
- GroupActionLogger.new(Discourse.system_user, group).log_add_user_to_group(user)
- end
+ Group
+ .automatic_membership_users(domains)
+ .find_each do |user|
+ next unless user.email_confirmed?
+ group.add(user, automatic: true)
+ GroupActionLogger.new(Discourse.system_user, group).log_add_user_to_group(user)
+ end
end
-
end
-
end
diff --git a/app/jobs/regular/backfill_sidebar_site_settings.rb b/app/jobs/regular/backfill_sidebar_site_settings.rb
index 8e07427e83d..9313a9afcab 100644
--- a/app/jobs/regular/backfill_sidebar_site_settings.rb
+++ b/app/jobs/regular/backfill_sidebar_site_settings.rb
@@ -2,8 +2,10 @@
class Jobs::BackfillSidebarSiteSettings < Jobs::Base
def execute(args)
- SidebarSiteSettingsBackfiller
- .new(args[:setting_name], previous_value: args[:previous_value], new_value: args[:new_value])
- .backfill!
+ SidebarSiteSettingsBackfiller.new(
+ args[:setting_name],
+ previous_value: args[:previous_value],
+ new_value: args[:new_value],
+ ).backfill!
end
end
diff --git a/app/jobs/regular/backup_chunks_merger.rb b/app/jobs/regular/backup_chunks_merger.rb
index aa359711ac6..4f6bb3e2b64 100644
--- a/app/jobs/regular/backup_chunks_merger.rb
+++ b/app/jobs/regular/backup_chunks_merger.rb
@@ -1,23 +1,23 @@
# frozen_string_literal: true
module Jobs
-
class BackupChunksMerger < ::Jobs::Base
- sidekiq_options queue: 'critical', retry: false
+ sidekiq_options queue: "critical", retry: false
def execute(args)
- filename = args[:filename]
+ filename = args[:filename]
identifier = args[:identifier]
- chunks = args[:chunks].to_i
+ chunks = args[:chunks].to_i
- raise Discourse::InvalidParameters.new(:filename) if filename.blank?
+ raise Discourse::InvalidParameters.new(:filename) if filename.blank?
raise Discourse::InvalidParameters.new(:identifier) if identifier.blank?
- raise Discourse::InvalidParameters.new(:chunks) if chunks <= 0
+ raise Discourse::InvalidParameters.new(:chunks) if chunks <= 0
backup_path = "#{BackupRestore::LocalBackupStore.base_directory}/#{filename}"
tmp_backup_path = "#{backup_path}.tmp"
# path to tmp directory
- tmp_directory = File.dirname(BackupRestore::LocalBackupStore.chunk_path(identifier, filename, 0))
+ tmp_directory =
+ File.dirname(BackupRestore::LocalBackupStore.chunk_path(identifier, filename, 0))
# merge all chunks
HandleChunkUpload.merge_chunks(
@@ -26,15 +26,14 @@ module Jobs
tmp_upload_path: tmp_backup_path,
identifier: identifier,
filename: filename,
- tmp_directory: tmp_directory
+ tmp_directory: tmp_directory,
)
# push an updated list to the clients
store = BackupRestore::BackupStore.create
- data = ActiveModel::ArraySerializer.new(store.files, each_serializer: BackupFileSerializer).as_json
+ data =
+ ActiveModel::ArraySerializer.new(store.files, each_serializer: BackupFileSerializer).as_json
MessageBus.publish("/admin/backups", data, group_ids: [Group::AUTO_GROUPS[:staff]])
end
-
end
-
end
diff --git a/app/jobs/regular/bulk_grant_trust_level.rb b/app/jobs/regular/bulk_grant_trust_level.rb
index f61b747d203..5a5ccecf7ee 100644
--- a/app/jobs/regular/bulk_grant_trust_level.rb
+++ b/app/jobs/regular/bulk_grant_trust_level.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module Jobs
-
class BulkGrantTrustLevel < ::Jobs::Base
-
def execute(args)
trust_level = args[:trust_level]
user_ids = args[:user_ids]
@@ -11,9 +9,7 @@ module Jobs
raise Discourse::InvalidParameters.new(:trust_level) if trust_level.blank?
raise Discourse::InvalidParameters.new(:user_ids) if user_ids.blank?
- User.where(id: user_ids).find_each do |user|
- TrustLevelGranter.grant(trust_level, user)
- end
+ User.where(id: user_ids).find_each { |user| TrustLevelGranter.grant(trust_level, user) }
end
end
end
diff --git a/app/jobs/regular/bulk_invite.rb b/app/jobs/regular/bulk_invite.rb
index ed83eb381df..173a27d4fda 100644
--- a/app/jobs/regular/bulk_invite.rb
+++ b/app/jobs/regular/bulk_invite.rb
@@ -7,13 +7,13 @@ module Jobs
def initialize
super
- @logs = []
- @sent = 0
- @skipped = 0
- @warnings = 0
- @failed = 0
- @groups = {}
- @user_fields = {}
+ @logs = []
+ @sent = 0
+ @skipped = 0
+ @warnings = 0
+ @failed = 0
+ @groups = {}
+ @user_fields = {}
@valid_groups = {}
end
@@ -64,7 +64,7 @@ module Jobs
groups = []
if group_names
- group_names = group_names.split(';')
+ group_names = group_names.split(";")
group_names.each do |group_name|
group = fetch_group(group_name)
@@ -101,7 +101,10 @@ module Jobs
user_fields = {}
fields.each do |key, value|
- @user_fields[key] ||= UserField.includes(:user_field_options).where('name ILIKE ?', key).first || :nil
+ @user_fields[key] ||= UserField
+ .includes(:user_field_options)
+ .where("name ILIKE ?", key)
+ .first || :nil
if @user_fields[key] == :nil
save_log "Invalid User Field '#{key}'"
@warnings += 1
@@ -110,7 +113,8 @@ module Jobs
# Automatically correct user field value
if @user_fields[key].field_type == "dropdown"
- value = @user_fields[key].user_field_options.find { |ufo| ufo.value.casecmp?(value) }&.value
+ value =
+ @user_fields[key].user_field_options.find { |ufo| ufo.value.casecmp?(value) }&.value
end
user_fields[@user_fields[key].id] = value
@@ -133,17 +137,13 @@ module Jobs
groups.each do |group|
group.add(user)
- GroupActionLogger
- .new(@current_user, group)
- .log_add_user_to_group(user)
+ GroupActionLogger.new(@current_user, group).log_add_user_to_group(user)
end
end
end
if user_fields.present?
- user_fields.each do |user_field, value|
- user.set_user_field(user_field, value)
- end
+ user_fields.each { |user_field, value| user.set_user_field(user_field, value) }
user.save_custom_fields
end
@@ -156,26 +156,19 @@ module Jobs
else
if user_fields.present? || locale.present?
user = User.where(staged: true).find_by_email(email)
- user ||= User.new(username: UserNameSuggester.suggest(email), email: email, staged: true)
+ user ||=
+ User.new(username: UserNameSuggester.suggest(email), email: email, staged: true)
if user_fields.present?
- user_fields.each do |user_field, value|
- user.set_user_field(user_field, value)
- end
+ user_fields.each { |user_field, value| user.set_user_field(user_field, value) }
end
- if locale.present?
- user.locale = locale
- end
+ user.locale = locale if locale.present?
user.save!
end
- invite_opts = {
- email: email,
- topic: topic,
- group_ids: groups.map(&:id),
- }
+ invite_opts = { email: email, topic: topic, group_ids: groups.map(&:id) }
if @invites.length > Invite::BULK_INVITE_EMAIL_LIMIT
invite_opts[:emailed_status] = Invite.emailed_status_types[:bulk_pending]
@@ -203,7 +196,7 @@ module Jobs
sent: @sent,
skipped: @skipped,
warnings: @warnings,
- logs: @logs.join("\n")
+ logs: @logs.join("\n"),
)
else
SystemMessage.create_from_system_user(
@@ -213,7 +206,7 @@ module Jobs
skipped: @skipped,
warnings: @warnings,
failed: @failed,
- logs: @logs.join("\n")
+ logs: @logs.join("\n"),
)
end
end
@@ -224,7 +217,7 @@ module Jobs
group = @groups[group_name]
unless group
- group = Group.find_by('lower(name) = ?', group_name)
+ group = Group.find_by("lower(name) = ?", group_name)
@groups[group_name] = group
end
diff --git a/app/jobs/regular/bulk_user_title_update.rb b/app/jobs/regular/bulk_user_title_update.rb
index 6dae5219ccb..f755f620a72 100644
--- a/app/jobs/regular/bulk_user_title_update.rb
+++ b/app/jobs/regular/bulk_user_title_update.rb
@@ -2,14 +2,19 @@
module Jobs
class BulkUserTitleUpdate < ::Jobs::Base
- UPDATE_ACTION = 'update'
- RESET_ACTION = 'reset'
+ UPDATE_ACTION = "update"
+ RESET_ACTION = "reset"
def execute(args)
new_title = args[:new_title]
granted_badge_id = args[:granted_badge_id]
action = args[:action]
- badge = Badge.find(granted_badge_id) rescue nil
+ badge =
+ begin
+ Badge.find(granted_badge_id)
+ rescue StandardError
+ nil
+ end
return unless badge # Deleted badge protection
@@ -20,6 +25,5 @@ module Jobs
badge.reset_user_titles!
end
end
-
end
end
diff --git a/app/jobs/regular/close_topic.rb b/app/jobs/regular/close_topic.rb
index 3385d63c343..c0b9035d038 100644
--- a/app/jobs/regular/close_topic.rb
+++ b/app/jobs/regular/close_topic.rb
@@ -23,7 +23,7 @@ module Jobs
end
# this handles deleting the topic timer as well, see TopicStatusUpdater
- topic.update_status('autoclosed', true, user, { silent: silent })
+ topic.update_status("autoclosed", true, user, { silent: silent })
MessageBus.publish("/topic/#{topic.id}", reload_topic: true)
end
diff --git a/app/jobs/regular/confirm_sns_subscription.rb b/app/jobs/regular/confirm_sns_subscription.rb
index f68588f89cb..bd1f0dcebf0 100644
--- a/app/jobs/regular/confirm_sns_subscription.rb
+++ b/app/jobs/regular/confirm_sns_subscription.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class ConfirmSnsSubscription < ::Jobs::Base
sidekiq_options retry: false
@@ -13,15 +12,14 @@ module Jobs
require "aws-sdk-sns"
return unless Aws::SNS::MessageVerifier.new.authentic?(raw)
- uri = begin
- URI.parse(subscribe_url)
- rescue URI::Error
- return
- end
+ uri =
+ begin
+ URI.parse(subscribe_url)
+ rescue URI::Error
+ return
+ end
Net::HTTP.get(uri)
end
-
end
-
end
diff --git a/app/jobs/regular/crawl_topic_link.rb b/app/jobs/regular/crawl_topic_link.rb
index da7659ec538..40cf4f86474 100644
--- a/app/jobs/regular/crawl_topic_link.rb
+++ b/app/jobs/regular/crawl_topic_link.rb
@@ -1,13 +1,12 @@
# frozen_string_literal: true
-require 'open-uri'
-require 'nokogiri'
-require 'excon'
+require "open-uri"
+require "nokogiri"
+require "excon"
module Jobs
class CrawlTopicLink < ::Jobs::Base
-
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
def execute(args)
raise Discourse::InvalidParameters.new(:topic_link_id) unless args[:topic_link_id].present?
@@ -16,10 +15,13 @@ module Jobs
return if topic_link.blank?
# Look for a topic embed for the URL. If it exists, use its title and don't crawl
- topic_embed = TopicEmbed.where(embed_url: topic_link.url).includes(:topic).references(:topic).first
+ topic_embed =
+ TopicEmbed.where(embed_url: topic_link.url).includes(:topic).references(:topic).first
# topic could be deleted, so skip
if topic_embed && topic_embed.topic
- TopicLink.where(id: topic_link.id).update_all(['title = ?, crawled_at = CURRENT_TIMESTAMP', topic_embed.topic.title[0..255]])
+ TopicLink.where(id: topic_link.id).update_all(
+ ["title = ?, crawled_at = CURRENT_TIMESTAMP", topic_embed.topic.title[0..255]],
+ )
return
end
@@ -31,22 +33,33 @@ module Jobs
if FileHelper.is_supported_image?(topic_link.url)
uri = URI(topic_link.url)
filename = File.basename(uri.path)
- crawled = (TopicLink.where(id: topic_link.id).update_all(["title = ?, crawled_at = CURRENT_TIMESTAMP", filename]) == 1)
+ crawled =
+ (
+ TopicLink.where(id: topic_link.id).update_all(
+ ["title = ?, crawled_at = CURRENT_TIMESTAMP", filename],
+ ) == 1
+ )
end
unless crawled
# Fetch the beginning of the document to find the title
title = RetrieveTitle.crawl(topic_link.url)
if title.present?
- crawled = (TopicLink.where(id: topic_link.id).update_all(['title = ?, crawled_at = CURRENT_TIMESTAMP', title[0..254]]) == 1)
+ crawled =
+ (
+ TopicLink.where(id: topic_link.id).update_all(
+ ["title = ?, crawled_at = CURRENT_TIMESTAMP", title[0..254]],
+ ) == 1
+ )
end
end
rescue Exception
# If there was a connection error, do nothing
ensure
- TopicLink.where(id: topic_link.id).update_all('crawled_at = CURRENT_TIMESTAMP') if !crawled && topic_link.present?
+ if !crawled && topic_link.present?
+ TopicLink.where(id: topic_link.id).update_all("crawled_at = CURRENT_TIMESTAMP")
+ end
end
end
-
end
end
diff --git a/app/jobs/regular/create_avatar_thumbnails.rb b/app/jobs/regular/create_avatar_thumbnails.rb
index 51988a47642..e4191e9f629 100644
--- a/app/jobs/regular/create_avatar_thumbnails.rb
+++ b/app/jobs/regular/create_avatar_thumbnails.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
module Jobs
-
class CreateAvatarThumbnails < ::Jobs::Base
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
def execute(args)
return if Rails.env.test?
@@ -13,11 +12,7 @@ module Jobs
return unless upload = Upload.find_by(id: upload_id)
- Discourse.avatar_sizes.each do |size|
- OptimizedImage.create_for(upload, size, size)
- end
+ Discourse.avatar_sizes.each { |size| OptimizedImage.create_for(upload, size, size) }
end
-
end
-
end
diff --git a/app/jobs/regular/create_backup.rb b/app/jobs/regular/create_backup.rb
index dcd3a466f57..14022a7dc0b 100644
--- a/app/jobs/regular/create_backup.rb
+++ b/app/jobs/regular/create_backup.rb
@@ -7,7 +7,12 @@ module Jobs
sidekiq_options retry: false
def execute(args)
- BackupRestore.backup!(Discourse.system_user.id, publish_to_message_bus: false, with_uploads: SiteSetting.backup_with_uploads, fork: false)
+ BackupRestore.backup!(
+ Discourse.system_user.id,
+ publish_to_message_bus: false,
+ with_uploads: SiteSetting.backup_with_uploads,
+ fork: false,
+ )
end
end
end
diff --git a/app/jobs/regular/create_linked_topic.rb b/app/jobs/regular/create_linked_topic.rb
index e862b82ab46..f5edca6efce 100644
--- a/app/jobs/regular/create_linked_topic.rb
+++ b/app/jobs/regular/create_linked_topic.rb
@@ -2,7 +2,6 @@
module Jobs
class CreateLinkedTopic < ::Jobs::Base
-
def execute(args)
reference_post = Post.find_by(id: args[:post_id])
return unless reference_post.present?
@@ -16,53 +15,83 @@ module Jobs
ActiveRecord::Base.transaction do
linked_topic_record = parent_topic.linked_topic
if linked_topic_record.present?
- raw_title = parent_title.delete_suffix(I18n.t("create_linked_topic.topic_title_with_sequence", topic_title: "", count: linked_topic_record.sequence))
+ raw_title =
+ parent_title.delete_suffix(
+ I18n.t(
+ "create_linked_topic.topic_title_with_sequence",
+ topic_title: "",
+ count: linked_topic_record.sequence,
+ ),
+ )
original_topic_id = linked_topic_record.original_topic_id
sequence = linked_topic_record.sequence + 1
else
raw_title = parent_title
# update parent topic title to append title_suffix_locale
- parent_title = I18n.t("create_linked_topic.topic_title_with_sequence", topic_title: parent_title, count: 1)
+ parent_title =
+ I18n.t(
+ "create_linked_topic.topic_title_with_sequence",
+ topic_title: parent_title,
+ count: 1,
+ )
parent_topic.title = parent_title
parent_topic.save!
# create linked topic record
original_topic_id = parent_topic_id
- LinkedTopic.create!(topic_id: parent_topic_id, original_topic_id: original_topic_id, sequence: 1)
+ LinkedTopic.create!(
+ topic_id: parent_topic_id,
+ original_topic_id: original_topic_id,
+ sequence: 1,
+ )
sequence = 2
end
# fetch previous topic titles
previous_topics = ""
linked_topic_ids = LinkedTopic.where(original_topic_id: original_topic_id).pluck(:topic_id)
- Topic.where(id: linked_topic_ids).order(:id).each do |topic|
- previous_topics += "- #{topic.url}\n"
- end
+ Topic
+ .where(id: linked_topic_ids)
+ .order(:id)
+ .each { |topic| previous_topics += "- #{topic.url}\n" }
# create new topic
- new_topic_title = I18n.t("create_linked_topic.topic_title_with_sequence", topic_title: raw_title, count: sequence)
- new_topic_raw = I18n.t('create_linked_topic.post_raw', parent_url: reference_post.full_url, previous_topics: previous_topics)
+ new_topic_title =
+ I18n.t(
+ "create_linked_topic.topic_title_with_sequence",
+ topic_title: raw_title,
+ count: sequence,
+ )
+ new_topic_raw =
+ I18n.t(
+ "create_linked_topic.post_raw",
+ parent_url: reference_post.full_url,
+ previous_topics: previous_topics,
+ )
system_user = Discourse.system_user
- @post_creator = PostCreator.new(
- system_user,
- title: new_topic_title,
- raw: new_topic_raw,
- category: parent_category_id,
- skip_validations: true,
- skip_jobs: true)
+ @post_creator =
+ PostCreator.new(
+ system_user,
+ title: new_topic_title,
+ raw: new_topic_raw,
+ category: parent_category_id,
+ skip_validations: true,
+ skip_jobs: true,
+ )
new_post = @post_creator.create
new_topic = new_post.topic
new_topic_id = new_topic.id
# create linked_topic record
- LinkedTopic.create!(topic_id: new_topic_id, original_topic_id: original_topic_id, sequence: sequence)
+ LinkedTopic.create!(
+ topic_id: new_topic_id,
+ original_topic_id: original_topic_id,
+ sequence: sequence,
+ )
# copy over topic tracking state from old topic
- params = {
- old_topic_id: parent_topic_id,
- new_topic_id: new_topic_id
- }
+ params = { old_topic_id: parent_topic_id, new_topic_id: new_topic_id }
DB.exec(<<~SQL, params)
INSERT INTO topic_users(user_id, topic_id, notification_level,
notifications_reason_id)
@@ -78,9 +107,15 @@ module Jobs
SQL
# update small action post on old topic to add new topic link
- small_action_post = Post.where(topic_id: parent_topic_id, post_type: Post.types[:small_action], action_code: "closed.enabled").last
+ small_action_post =
+ Post.where(
+ topic_id: parent_topic_id,
+ post_type: Post.types[:small_action],
+ action_code: "closed.enabled",
+ ).last
if small_action_post.present?
- small_action_post.raw = "#{small_action_post.raw} #{I18n.t('create_linked_topic.small_action_post_raw', new_title: "[#{new_topic_title}](#{new_topic.url})")}"
+ small_action_post.raw =
+ "#{small_action_post.raw} #{I18n.t("create_linked_topic.small_action_post_raw", new_title: "[#{new_topic_title}](#{new_topic.url})")}"
small_action_post.save!
end
end
diff --git a/app/jobs/regular/create_user_reviewable.rb b/app/jobs/regular/create_user_reviewable.rb
index b3c20267ed9..5d4a69fbded 100644
--- a/app/jobs/regular/create_user_reviewable.rb
+++ b/app/jobs/regular/create_user_reviewable.rb
@@ -15,24 +15,25 @@ class Jobs::CreateUserReviewable < ::Jobs::Base
if user = User.find_by(id: args[:user_id])
return if user.approved?
- @reviewable = ReviewableUser.needs_review!(
- target: user,
- created_by: Discourse.system_user,
- reviewable_by_moderator: true,
- payload: {
- username: user.username,
- name: user.name,
- email: user.email,
- website: user.user_profile&.website
- }
- )
+ @reviewable =
+ ReviewableUser.needs_review!(
+ target: user,
+ created_by: Discourse.system_user,
+ reviewable_by_moderator: true,
+ payload: {
+ username: user.username,
+ name: user.name,
+ email: user.email,
+ website: user.user_profile&.website,
+ },
+ )
if @reviewable.created_new
@reviewable.add_score(
Discourse.system_user,
ReviewableScore.types[:needs_approval],
reason: reason,
- force_review: true
+ force_review: true,
)
end
end
diff --git a/app/jobs/regular/critical_user_email.rb b/app/jobs/regular/critical_user_email.rb
index 47d2ef14e99..6911ff174aa 100644
--- a/app/jobs/regular/critical_user_email.rb
+++ b/app/jobs/regular/critical_user_email.rb
@@ -2,8 +2,7 @@
module Jobs
class CriticalUserEmail < UserEmail
-
- sidekiq_options queue: 'critical'
+ sidekiq_options queue: "critical"
def quit_email_early?
false
diff --git a/app/jobs/regular/delete_inaccessible_notifications.rb b/app/jobs/regular/delete_inaccessible_notifications.rb
index e33bfd6fb13..e0f0e55d4db 100644
--- a/app/jobs/regular/delete_inaccessible_notifications.rb
+++ b/app/jobs/regular/delete_inaccessible_notifications.rb
@@ -5,13 +5,13 @@ module Jobs
def execute(args)
raise Discourse::InvalidParameters.new(:topic_id) if args[:topic_id].blank?
- Notification.where(topic_id: args[:topic_id]).find_each do |notification|
- next unless notification.user && notification.topic
+ Notification
+ .where(topic_id: args[:topic_id])
+ .find_each do |notification|
+ next unless notification.user && notification.topic
- if !Guardian.new(notification.user).can_see?(notification.topic)
- notification.destroy
+ notification.destroy if !Guardian.new(notification.user).can_see?(notification.topic)
end
- end
end
end
end
diff --git a/app/jobs/regular/delete_replies.rb b/app/jobs/regular/delete_replies.rb
index 7208f4e561f..d235c39bcfd 100644
--- a/app/jobs/regular/delete_replies.rb
+++ b/app/jobs/regular/delete_replies.rb
@@ -9,15 +9,25 @@ module Jobs
end
replies = topic.posts.where("posts.post_number > 1")
- replies = replies.where("like_count < ?", SiteSetting.skip_auto_delete_reply_likes) if SiteSetting.skip_auto_delete_reply_likes > 0
+ replies =
+ replies.where(
+ "like_count < ?",
+ SiteSetting.skip_auto_delete_reply_likes,
+ ) if SiteSetting.skip_auto_delete_reply_likes > 0
- replies.where('posts.created_at < ?', topic_timer.duration_minutes.minutes.ago).each do |post|
- PostDestroyer.new(topic_timer.user, post, context: I18n.t("topic_statuses.auto_deleted_by_timer")).destroy
- end
+ replies
+ .where("posts.created_at < ?", topic_timer.duration_minutes.minutes.ago)
+ .each do |post|
+ PostDestroyer.new(
+ topic_timer.user,
+ post,
+ context: I18n.t("topic_statuses.auto_deleted_by_timer"),
+ ).destroy
+ end
- topic_timer.execute_at = (replies.minimum(:created_at) || Time.zone.now) + topic_timer.duration_minutes.minutes
+ topic_timer.execute_at =
+ (replies.minimum(:created_at) || Time.zone.now) + topic_timer.duration_minutes.minutes
topic_timer.save
end
-
end
end
diff --git a/app/jobs/regular/delete_topic.rb b/app/jobs/regular/delete_topic.rb
index af109d8b101..d3a35d5d980 100644
--- a/app/jobs/regular/delete_topic.rb
+++ b/app/jobs/regular/delete_topic.rb
@@ -7,7 +7,9 @@ module Jobs
first_post = topic.ordered_posts.first
PostDestroyer.new(
- topic_timer.user, first_post, context: I18n.t("topic_statuses.auto_deleted_by_timer")
+ topic_timer.user,
+ first_post,
+ context: I18n.t("topic_statuses.auto_deleted_by_timer"),
).destroy
topic_timer.trash!(Discourse.system_user)
diff --git a/app/jobs/regular/download_avatar_from_url.rb b/app/jobs/regular/download_avatar_from_url.rb
index e1864c80b33..06ef524a25e 100644
--- a/app/jobs/regular/download_avatar_from_url.rb
+++ b/app/jobs/regular/download_avatar_from_url.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class DownloadAvatarFromUrl < ::Jobs::Base
sidekiq_options retry: false
@@ -15,16 +14,10 @@ module Jobs
return unless user = User.find_by(id: user_id)
begin
- UserAvatar.import_url_for_user(
- url,
- user,
- override_gravatar: args[:override_gravatar]
- )
+ UserAvatar.import_url_for_user(url, user, override_gravatar: args[:override_gravatar])
rescue Discourse::InvalidParameters => e
- raise e unless e.message == 'url'
+ raise e unless e.message == "url"
end
end
-
end
-
end
diff --git a/app/jobs/regular/download_backup_email.rb b/app/jobs/regular/download_backup_email.rb
index 44e13495f29..000d0591f2d 100644
--- a/app/jobs/regular/download_backup_email.rb
+++ b/app/jobs/regular/download_backup_email.rb
@@ -1,10 +1,8 @@
# frozen_string_literal: true
module Jobs
-
class DownloadBackupEmail < ::Jobs::Base
-
- sidekiq_options queue: 'critical'
+ sidekiq_options queue: "critical"
def execute(args)
user_id = args[:user_id]
@@ -20,7 +18,5 @@ module Jobs
message = DownloadBackupMailer.send_email(user.email, backup_file_path.to_s)
Email::Sender.new(message, :download_backup_message).send
end
-
end
-
end
diff --git a/app/jobs/regular/download_profile_background_from_url.rb b/app/jobs/regular/download_profile_background_from_url.rb
index 5d39c3d8c86..bf8e15ff036 100644
--- a/app/jobs/regular/download_profile_background_from_url.rb
+++ b/app/jobs/regular/download_profile_background_from_url.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class DownloadProfileBackgroundFromUrl < ::Jobs::Base
sidekiq_options retry: false
@@ -15,16 +14,10 @@ module Jobs
return unless user = User.find_by(id: user_id)
begin
- UserProfile.import_url_for_user(
- url,
- user,
- is_card_background: args[:is_card_background],
- )
+ UserProfile.import_url_for_user(url, user, is_card_background: args[:is_card_background])
rescue Discourse::InvalidParameters => e
- raise e unless e.message == 'url'
+ raise e unless e.message == "url"
end
end
-
end
-
end
diff --git a/app/jobs/regular/emit_web_hook_event.rb b/app/jobs/regular/emit_web_hook_event.rb
index 806765309bc..ab648e6572c 100644
--- a/app/jobs/regular/emit_web_hook_event.rb
+++ b/app/jobs/regular/emit_web_hook_event.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
-require 'excon'
+require "excon"
module Jobs
class EmitWebHookEvent < ::Jobs::Base
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
- PING_EVENT = 'ping'
+ PING_EVENT = "ping"
MAX_RETRY_COUNT = 4
RETRY_BACKOFF = 5
@@ -63,9 +63,10 @@ module Jobs
if @retry_count >= MAX_RETRY_COUNT
@web_hook.update!(active: false)
- StaffActionLogger
- .new(Discourse.system_user)
- .log_web_hook_deactivate(@web_hook, web_hook_response.status)
+ StaffActionLogger.new(Discourse.system_user).log_web_hook_deactivate(
+ @web_hook,
+ web_hook_response.status,
+ )
end
else
retry_web_hook
@@ -83,10 +84,11 @@ module Jobs
end
def publish_webhook_event(web_hook_event)
- MessageBus.publish("/web_hook_events/#{@web_hook.id}", {
- web_hook_event_id: web_hook_event.id,
- event_type: @arguments[:event_type]
- }, group_ids: [Group::AUTO_GROUPS[:staff]])
+ MessageBus.publish(
+ "/web_hook_events/#{@web_hook.id}",
+ { web_hook_event_id: web_hook_event.id, event_type: @arguments[:event_type] },
+ group_ids: [Group::AUTO_GROUPS[:staff]],
+ )
end
def ping_event?(event_type)
@@ -98,45 +100,50 @@ module Jobs
end
def group_webhook_invalid?
- @web_hook.group_ids.present? && (@arguments[:group_ids].blank? ||
- (@web_hook.group_ids & @arguments[:group_ids]).blank?)
+ @web_hook.group_ids.present? &&
+ (@arguments[:group_ids].blank? || (@web_hook.group_ids & @arguments[:group_ids]).blank?)
end
def category_webhook_invalid?
- @web_hook.category_ids.present? && (!@arguments[:category_id].present? ||
- !@web_hook.category_ids.include?(@arguments[:category_id]))
+ @web_hook.category_ids.present? &&
+ (
+ !@arguments[:category_id].present? ||
+ !@web_hook.category_ids.include?(@arguments[:category_id])
+ )
end
def tag_webhook_invalid?
- @web_hook.tag_ids.present? && (@arguments[:tag_ids].blank? ||
- (@web_hook.tag_ids & @arguments[:tag_ids]).blank?)
+ @web_hook.tag_ids.present? &&
+ (@arguments[:tag_ids].blank? || (@web_hook.tag_ids & @arguments[:tag_ids]).blank?)
end
def build_webhook_headers(uri, web_hook_body, web_hook_event)
content_type =
case @web_hook.content_type
- when WebHook.content_types['application/x-www-form-urlencoded']
- 'application/x-www-form-urlencoded'
+ when WebHook.content_types["application/x-www-form-urlencoded"]
+ "application/x-www-form-urlencoded"
else
- 'application/json'
+ "application/json"
end
headers = {
- 'Accept' => '*/*',
- 'Connection' => 'close',
- 'Content-Length' => web_hook_body.bytesize.to_s,
- 'Content-Type' => content_type,
- 'Host' => uri.host,
- 'User-Agent' => "Discourse/#{Discourse::VERSION::STRING}",
- 'X-Discourse-Instance' => Discourse.base_url,
- 'X-Discourse-Event-Id' => web_hook_event.id.to_s,
- 'X-Discourse-Event-Type' => @arguments[:event_type]
+ "Accept" => "*/*",
+ "Connection" => "close",
+ "Content-Length" => web_hook_body.bytesize.to_s,
+ "Content-Type" => content_type,
+ "Host" => uri.host,
+ "User-Agent" => "Discourse/#{Discourse::VERSION::STRING}",
+ "X-Discourse-Instance" => Discourse.base_url,
+ "X-Discourse-Event-Id" => web_hook_event.id.to_s,
+ "X-Discourse-Event-Type" => @arguments[:event_type],
}
- headers['X-Discourse-Event'] = @arguments[:event_name] if @arguments[:event_name].present?
+ headers["X-Discourse-Event"] = @arguments[:event_name] if @arguments[:event_name].present?
if @web_hook.secret.present?
- headers['X-Discourse-Event-Signature'] = "sha256=#{OpenSSL::HMAC.hexdigest("sha256", @web_hook.secret, web_hook_body)}"
+ headers[
+ "X-Discourse-Event-Signature"
+ ] = "sha256=#{OpenSSL::HMAC.hexdigest("sha256", @web_hook.secret, web_hook_body)}"
end
headers
@@ -146,7 +153,7 @@ module Jobs
body = {}
if ping_event?(@arguments[:event_type])
- body['ping'] = "OK"
+ body["ping"] = "OK"
else
body[@arguments[:event_type]] = JSON.parse(@arguments[:payload])
end
@@ -158,6 +165,5 @@ module Jobs
def create_webhook_event(web_hook_body)
WebHookEvent.create!(web_hook: @web_hook, payload: web_hook_body)
end
-
end
end
diff --git a/app/jobs/regular/enable_bootstrap_mode.rb b/app/jobs/regular/enable_bootstrap_mode.rb
index bf804e24dbc..8b7d456f4cc 100644
--- a/app/jobs/regular/enable_bootstrap_mode.rb
+++ b/app/jobs/regular/enable_bootstrap_mode.rb
@@ -2,7 +2,7 @@
module Jobs
class EnableBootstrapMode < ::Jobs::Base
- sidekiq_options queue: 'critical'
+ sidekiq_options queue: "critical"
def execute(args)
raise Discourse::InvalidParameters.new(:user_id) unless args[:user_id].present?
@@ -13,14 +13,14 @@ module Jobs
# let's enable bootstrap mode settings
if SiteSetting.default_trust_level == TrustLevel[0]
- SiteSetting.set_and_log('default_trust_level', TrustLevel[1])
+ SiteSetting.set_and_log("default_trust_level", TrustLevel[1])
end
- if SiteSetting.default_email_digest_frequency == 10080
- SiteSetting.set_and_log('default_email_digest_frequency', 1440)
+ if SiteSetting.default_email_digest_frequency == 10_080
+ SiteSetting.set_and_log("default_email_digest_frequency", 1440)
end
- SiteSetting.set_and_log('bootstrap_mode_enabled', true)
+ SiteSetting.set_and_log("bootstrap_mode_enabled", true)
end
end
end
diff --git a/app/jobs/regular/export_csv_file.rb b/app/jobs/regular/export_csv_file.rb
index 44305b44720..b725ab5dd2f 100644
--- a/app/jobs/regular/export_csv_file.rb
+++ b/app/jobs/regular/export_csv_file.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'csv'
+require "csv"
module Jobs
-
class ExportCsvFile < ::Jobs::Base
sidekiq_options retry: false
@@ -11,17 +10,53 @@ module Jobs
attr_accessor :current_user
attr_accessor :entity
- HEADER_ATTRS_FOR ||= HashWithIndifferentAccess.new(
- user_list: ['id', 'name', 'username', 'email', 'title', 'created_at', 'last_seen_at', 'last_posted_at', 'last_emailed_at', 'trust_level', 'approved', 'suspended_at', 'suspended_till', 'silenced_till', 'active', 'admin', 'moderator', 'ip_address', 'staged', 'secondary_emails'],
- user_stats: ['topics_entered', 'posts_read_count', 'time_read', 'topic_count', 'post_count', 'likes_given', 'likes_received'],
- user_profile: ['location', 'website', 'views'],
- user_sso: ['external_id', 'external_email', 'external_username', 'external_name', 'external_avatar_url'],
- staff_action: ['staff_user', 'action', 'subject', 'created_at', 'details', 'context'],
- screened_email: ['email', 'action', 'match_count', 'last_match_at', 'created_at', 'ip_address'],
- screened_ip: ['ip_address', 'action', 'match_count', 'last_match_at', 'created_at'],
- screened_url: ['domain', 'action', 'match_count', 'last_match_at', 'created_at'],
- report: ['date', 'value']
- )
+ HEADER_ATTRS_FOR ||=
+ HashWithIndifferentAccess.new(
+ user_list: %w[
+ id
+ name
+ username
+ email
+ title
+ created_at
+ last_seen_at
+ last_posted_at
+ last_emailed_at
+ trust_level
+ approved
+ suspended_at
+ suspended_till
+ silenced_till
+ active
+ admin
+ moderator
+ ip_address
+ staged
+ secondary_emails
+ ],
+ user_stats: %w[
+ topics_entered
+ posts_read_count
+ time_read
+ topic_count
+ post_count
+ likes_given
+ likes_received
+ ],
+ user_profile: %w[location website views],
+ user_sso: %w[
+ external_id
+ external_email
+ external_username
+ external_name
+ external_avatar_url
+ ],
+ staff_action: %w[staff_user action subject created_at details context],
+ screened_email: %w[email action match_count last_match_at created_at ip_address],
+ screened_ip: %w[ip_address action match_count last_match_at created_at],
+ screened_url: %w[domain action match_count last_match_at created_at],
+ report: %w[date value],
+ )
def execute(args)
@entity = args[:entity]
@@ -35,19 +70,19 @@ module Jobs
raise Discourse::InvalidParameters.new(:entity) unless respond_to?(entity[:method])
@timestamp ||= Time.now.strftime("%y%m%d-%H%M%S")
- entity[:filename] =
- if entity[:name] == "report" && @extra[:name].present?
- "#{@extra[:name].dasherize}-#{@timestamp}"
- else
- "#{entity[:name].dasherize}-#{@timestamp}"
- end
+ entity[:filename] = if entity[:name] == "report" && @extra[:name].present?
+ "#{@extra[:name].dasherize}-#{@timestamp}"
+ else
+ "#{entity[:name].dasherize}-#{@timestamp}"
+ end
end
- export_title = if @entity == "report" && @extra[:name].present?
- I18n.t("reports.#{@extra[:name]}.title")
- else
- @entity.gsub('_', ' ').titleize
- end
+ export_title =
+ if @entity == "report" && @extra[:name].present?
+ I18n.t("reports.#{@extra[:name]}.title")
+ else
+ @entity.gsub("_", " ").titleize
+ end
filename = entities[0][:filename] # use first entity as a name for this export
user_export = UserExport.create(file_name: filename, user_id: @current_user.id)
@@ -77,12 +112,13 @@ module Jobs
if File.exist?(zip_filename)
File.open(zip_filename) do |file|
- upload = UploadCreator.new(
- file,
- File.basename(zip_filename),
- type: 'csv_export',
- for_export: 'true'
- ).create_for(@current_user.id)
+ upload =
+ UploadCreator.new(
+ file,
+ File.basename(zip_filename),
+ type: "csv_export",
+ for_export: "true",
+ ).create_for(@current_user.id)
if upload.persisted?
user_export.update_columns(upload_id: upload.id)
@@ -99,7 +135,7 @@ module Jobs
if user_export.present? && post.present?
topic = post.topic
user_export.update_columns(topic_id: topic.id)
- topic.update_status('closed', true, Discourse.system_user)
+ topic.update_status("closed", true, Discourse.system_user)
end
end
@@ -109,66 +145,67 @@ module Jobs
user_field_ids = UserField.pluck(:id)
condition = {}
- if @extra && @extra[:trust_level] && trust_level = TrustLevel.levels[@extra[:trust_level].to_sym]
+ if @extra && @extra[:trust_level] &&
+ trust_level = TrustLevel.levels[@extra[:trust_level].to_sym]
condition = { trust_level: trust_level }
end
- includes = [:user_profile, :user_stat, :groups, :user_emails]
- if SiteSetting.enable_discourse_connect
- includes << [:single_sign_on_record]
- end
+ includes = %i[user_profile user_stat groups user_emails]
+ includes << [:single_sign_on_record] if SiteSetting.enable_discourse_connect
- User.where(condition).includes(*includes).find_each do |user|
- user_info_array = get_base_user_array(user)
- if SiteSetting.enable_discourse_connect
- user_info_array = add_single_sign_on(user, user_info_array)
+ User
+ .where(condition)
+ .includes(*includes)
+ .find_each do |user|
+ user_info_array = get_base_user_array(user)
+ if SiteSetting.enable_discourse_connect
+ user_info_array = add_single_sign_on(user, user_info_array)
+ end
+ user_info_array = add_custom_fields(user, user_info_array, user_field_ids)
+ user_info_array = add_group_names(user, user_info_array)
+ yield user_info_array
end
- user_info_array = add_custom_fields(user, user_info_array, user_field_ids)
- user_info_array = add_group_names(user, user_info_array)
- yield user_info_array
- end
-
end
def staff_action_export
return enum_for(:staff_action_export) unless block_given?
- staff_action_data = if @current_user.admin?
- UserHistory.only_staff_actions.order('id DESC')
- else
- UserHistory.where(admin_only: false).only_staff_actions.order('id DESC')
- end
+ staff_action_data =
+ if @current_user.admin?
+ UserHistory.only_staff_actions.order("id DESC")
+ else
+ UserHistory.where(admin_only: false).only_staff_actions.order("id DESC")
+ end
- staff_action_data.each do |staff_action|
- yield get_staff_action_fields(staff_action)
- end
+ staff_action_data.each { |staff_action| yield get_staff_action_fields(staff_action) }
end
def screened_email_export
return enum_for(:screened_email_export) unless block_given?
- ScreenedEmail.order('last_match_at DESC').each do |screened_email|
- yield get_screened_email_fields(screened_email)
- end
+ ScreenedEmail
+ .order("last_match_at DESC")
+ .each { |screened_email| yield get_screened_email_fields(screened_email) }
end
def screened_ip_export
return enum_for(:screened_ip_export) unless block_given?
- ScreenedIpAddress.order('id DESC').each do |screened_ip|
- yield get_screened_ip_fields(screened_ip)
- end
+ ScreenedIpAddress
+ .order("id DESC")
+ .each { |screened_ip| yield get_screened_ip_fields(screened_ip) }
end
def screened_url_export
return enum_for(:screened_url_export) unless block_given?
- ScreenedUrl.select("domain, sum(match_count) as match_count, max(last_match_at) as last_match_at, min(created_at) as created_at")
+ ScreenedUrl
+ .select(
+ "domain, sum(match_count) as match_count, max(last_match_at) as last_match_at, min(created_at) as created_at",
+ )
.group(:domain)
- .order('last_match_at DESC')
- .each do |screened_url|
- yield get_screened_url_fields(screened_url)
- end
+ .order("last_match_at DESC")
+ .each { |screened_url| yield get_screened_url_fields(screened_url) }
end
def report_export
@@ -176,16 +213,26 @@ module Jobs
# If dates are invalid consider then `nil`
if @extra[:start_date].is_a?(String)
- @extra[:start_date] = @extra[:start_date].to_date.beginning_of_day rescue nil
+ @extra[:start_date] = begin
+ @extra[:start_date].to_date.beginning_of_day
+ rescue StandardError
+ nil
+ end
end
if @extra[:end_date].is_a?(String)
- @extra[:end_date] = @extra[:end_date].to_date.end_of_day rescue nil
+ @extra[:end_date] = begin
+ @extra[:end_date].to_date.end_of_day
+ rescue StandardError
+ nil
+ end
end
@extra[:filters] = {}
@extra[:filters][:category] = @extra[:category].to_i if @extra[:category].present?
@extra[:filters][:group] = @extra[:group].to_i if @extra[:group].present?
- @extra[:filters][:include_subcategories] = !!ActiveRecord::Type::Boolean.new.cast(@extra[:include_subcategories]) if @extra[:include_subcategories].present?
+ @extra[:filters][:include_subcategories] = !!ActiveRecord::Type::Boolean.new.cast(
+ @extra[:include_subcategories],
+ ) if @extra[:include_subcategories].present?
report = Report.find(@extra[:name], @extra)
@@ -227,9 +274,11 @@ module Jobs
end
def get_header(entity)
- if entity == 'user_list'
- header_array = HEADER_ATTRS_FOR['user_list'] + HEADER_ATTRS_FOR['user_stats'] + HEADER_ATTRS_FOR['user_profile']
- header_array.concat(HEADER_ATTRS_FOR['user_sso']) if SiteSetting.enable_discourse_connect
+ if entity == "user_list"
+ header_array =
+ HEADER_ATTRS_FOR["user_list"] + HEADER_ATTRS_FOR["user_stats"] +
+ HEADER_ATTRS_FOR["user_profile"]
+ header_array.concat(HEADER_ATTRS_FOR["user_sso"]) if SiteSetting.enable_discourse_connect
user_custom_fields = UserField.all
if user_custom_fields.present?
user_custom_fields.each do |custom_field|
@@ -299,7 +348,13 @@ module Jobs
def add_single_sign_on(user, user_info_array)
if user.single_sign_on_record
- user_info_array.push(user.single_sign_on_record.external_id, user.single_sign_on_record.external_email, user.single_sign_on_record.external_username, escape_comma(user.single_sign_on_record.external_name), user.single_sign_on_record.external_avatar_url)
+ user_info_array.push(
+ user.single_sign_on_record.external_id,
+ user.single_sign_on_record.external_email,
+ user.single_sign_on_record.external_username,
+ escape_comma(user.single_sign_on_record.external_name),
+ user.single_sign_on_record.external_avatar_url,
+ )
else
user_info_array.push(nil, nil, nil, nil, nil)
end
@@ -308,9 +363,7 @@ module Jobs
def add_custom_fields(user, user_info_array, user_field_ids)
if user_field_ids.present?
- user.user_fields.each do |custom_field|
- user_info_array << escape_comma(custom_field[1])
- end
+ user.user_fields.each { |custom_field| user_info_array << escape_comma(custom_field[1]) }
end
user_info_array
end
@@ -328,21 +381,25 @@ module Jobs
def get_staff_action_fields(staff_action)
staff_action_array = []
- HEADER_ATTRS_FOR['staff_action'].each do |attr|
+ HEADER_ATTRS_FOR["staff_action"].each do |attr|
data =
- if attr == 'action'
+ if attr == "action"
UserHistory.actions.key(staff_action.attributes[attr]).to_s
- elsif attr == 'staff_user'
- user = User.find_by(id: staff_action.attributes['acting_user_id'])
+ elsif attr == "staff_user"
+ user = User.find_by(id: staff_action.attributes["acting_user_id"])
user.username if !user.nil?
- elsif attr == 'subject'
- user = User.find_by(id: staff_action.attributes['target_user_id'])
- user.nil? ? staff_action.attributes[attr] : "#{user.username} #{staff_action.attributes[attr]}"
+ elsif attr == "subject"
+ user = User.find_by(id: staff_action.attributes["target_user_id"])
+ if user.nil?
+ staff_action.attributes[attr]
+ else
+ "#{user.username} #{staff_action.attributes[attr]}"
+ end
else
staff_action.attributes[attr]
end
- staff_action_array.push(data)
+ staff_action_array.push(data)
end
staff_action_array
end
@@ -350,10 +407,10 @@ module Jobs
def get_screened_email_fields(screened_email)
screened_email_array = []
- HEADER_ATTRS_FOR['screened_email'].each do |attr|
+ HEADER_ATTRS_FOR["screened_email"].each do |attr|
data =
- if attr == 'action'
- ScreenedEmail.actions.key(screened_email.attributes['action_type']).to_s
+ if attr == "action"
+ ScreenedEmail.actions.key(screened_email.attributes["action_type"]).to_s
else
screened_email.attributes[attr]
end
@@ -367,10 +424,10 @@ module Jobs
def get_screened_ip_fields(screened_ip)
screened_ip_array = []
- HEADER_ATTRS_FOR['screened_ip'].each do |attr|
+ HEADER_ATTRS_FOR["screened_ip"].each do |attr|
data =
- if attr == 'action'
- ScreenedIpAddress.actions.key(screened_ip.attributes['action_type']).to_s
+ if attr == "action"
+ ScreenedIpAddress.actions.key(screened_ip.attributes["action_type"]).to_s
else
screened_ip.attributes[attr]
end
@@ -384,10 +441,10 @@ module Jobs
def get_screened_url_fields(screened_url)
screened_url_array = []
- HEADER_ATTRS_FOR['screened_url'].each do |attr|
+ HEADER_ATTRS_FOR["screened_url"].each do |attr|
data =
- if attr == 'action'
- action = ScreenedUrl.actions.key(screened_url.attributes['action_type']).to_s
+ if attr == "action"
+ action = ScreenedUrl.actions.key(screened_url.attributes["action_type"]).to_s
action = "do nothing" if action.blank?
else
screened_url.attributes[attr]
@@ -403,16 +460,17 @@ module Jobs
post = nil
if @current_user
- post = if upload
- SystemMessage.create_from_system_user(
- @current_user,
- :csv_export_succeeded,
- download_link: UploadMarkdown.new(upload).attachment_markdown,
- export_title: export_title
- )
- else
- SystemMessage.create_from_system_user(@current_user, :csv_export_failed)
- end
+ post =
+ if upload
+ SystemMessage.create_from_system_user(
+ @current_user,
+ :csv_export_succeeded,
+ download_link: UploadMarkdown.new(upload).attachment_markdown,
+ export_title: export_title,
+ )
+ else
+ SystemMessage.create_from_system_user(@current_user, :csv_export_failed)
+ end
end
post
diff --git a/app/jobs/regular/export_user_archive.rb b/app/jobs/regular/export_user_archive.rb
index 657cc4aafec..59c60740b37 100644
--- a/app/jobs/regular/export_user_archive.rb
+++ b/app/jobs/regular/export_user_archive.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'csv'
+require "csv"
module Jobs
class ExportUserArchive < ::Jobs::Base
@@ -10,7 +10,7 @@ module Jobs
# note: contents provided entirely by user
attr_accessor :extra
- COMPONENTS ||= %w(
+ COMPONENTS ||= %w[
user_archive
preferences
auth_tokens
@@ -23,22 +23,98 @@ module Jobs
post_actions
queued_posts
visits
- )
+ ]
- HEADER_ATTRS_FOR ||= HashWithIndifferentAccess.new(
- user_archive: ['topic_title', 'categories', 'is_pm', 'post_raw', 'post_cooked', 'like_count', 'reply_count', 'url', 'created_at'],
- user_archive_profile: ['location', 'website', 'bio', 'views'],
- auth_tokens: ['id', 'auth_token_hash', 'prev_auth_token_hash', 'auth_token_seen', 'client_ip', 'user_agent', 'seen_at', 'rotated_at', 'created_at', 'updated_at'],
- auth_token_logs: ['id', 'action', 'user_auth_token_id', 'client_ip', 'auth_token_hash', 'created_at', 'path', 'user_agent'],
- badges: ['badge_id', 'badge_name', 'granted_at', 'post_id', 'seq', 'granted_manually', 'notification_id', 'featured_rank'],
- bookmarks: ['bookmarkable_id', 'bookmarkable_type', 'link', 'name', 'created_at', 'updated_at', 'reminder_at', 'reminder_last_sent_at', 'reminder_set_at', 'auto_delete_preference'],
- category_preferences: ['category_id', 'category_names', 'notification_level', 'dismiss_new_timestamp'],
- flags: ['id', 'post_id', 'flag_type', 'created_at', 'updated_at', 'deleted_at', 'deleted_by', 'related_post_id', 'targets_topic', 'was_take_action'],
- likes: ['id', 'post_id', 'topic_id', 'post_number', 'created_at', 'updated_at', 'deleted_at', 'deleted_by'],
- post_actions: ['id', 'post_id', 'post_action_type', 'created_at', 'updated_at', 'deleted_at', 'deleted_by', 'related_post_id'],
- queued_posts: ['id', 'verdict', 'category_id', 'topic_id', 'post_raw', 'other_json'],
- visits: ['visited_at', 'posts_read', 'mobile', 'time_read'],
- )
+ HEADER_ATTRS_FOR ||=
+ HashWithIndifferentAccess.new(
+ user_archive: %w[
+ topic_title
+ categories
+ is_pm
+ post_raw
+ post_cooked
+ like_count
+ reply_count
+ url
+ created_at
+ ],
+ user_archive_profile: %w[location website bio views],
+ auth_tokens: %w[
+ id
+ auth_token_hash
+ prev_auth_token_hash
+ auth_token_seen
+ client_ip
+ user_agent
+ seen_at
+ rotated_at
+ created_at
+ updated_at
+ ],
+ auth_token_logs: %w[
+ id
+ action
+ user_auth_token_id
+ client_ip
+ auth_token_hash
+ created_at
+ path
+ user_agent
+ ],
+ badges: %w[
+ badge_id
+ badge_name
+ granted_at
+ post_id
+ seq
+ granted_manually
+ notification_id
+ featured_rank
+ ],
+ bookmarks: %w[
+ bookmarkable_id
+ bookmarkable_type
+ link
+ name
+ created_at
+ updated_at
+ reminder_at
+ reminder_last_sent_at
+ reminder_set_at
+ auto_delete_preference
+ ],
+ category_preferences: %w[
+ category_id
+ category_names
+ notification_level
+ dismiss_new_timestamp
+ ],
+ flags: %w[
+ id
+ post_id
+ flag_type
+ created_at
+ updated_at
+ deleted_at
+ deleted_by
+ related_post_id
+ targets_topic
+ was_take_action
+ ],
+ likes: %w[id post_id topic_id post_number created_at updated_at deleted_at deleted_by],
+ post_actions: %w[
+ id
+ post_id
+ post_action_type
+ created_at
+ updated_at
+ deleted_at
+ deleted_by
+ related_post_id
+ ],
+ queued_posts: %w[id verdict category_id topic_id post_raw other_json],
+ visits: %w[visited_at posts_read mobile time_read],
+ )
def execute(args)
@current_user = User.find_by(id: args[:user_id])
@@ -52,18 +128,14 @@ module Jobs
h = { name: name, method: :"#{export_method}" }
h[:filetype] = :csv
filetype_method = :"#{name}_filetype"
- if respond_to? filetype_method
- h[:filetype] = public_send(filetype_method)
- end
+ h[:filetype] = public_send(filetype_method) if respond_to? filetype_method
condition_method = :"include_#{name}?"
- if respond_to? condition_method
- h[:skip] = !public_send(condition_method)
- end
+ h[:skip] = !public_send(condition_method) if respond_to? condition_method
h[:filename] = name
components.push(h)
end
- export_title = 'user_archive'.titleize
+ export_title = "user_archive".titleize
filename = "user_archive-#{@current_user.username}-#{@timestamp}"
user_export = UserExport.create(file_name: filename, user_id: @current_user.id)
@@ -89,7 +161,7 @@ module Jobs
file.write MultiJson.dump(public_send(component[:method]), indent: 4)
end
else
- raise 'unknown export filetype'
+ raise "unknown export filetype"
end
end
@@ -103,17 +175,20 @@ module Jobs
if File.exist?(zip_filename)
File.open(zip_filename) do |file|
- upload = UploadCreator.new(
- file,
- File.basename(zip_filename),
- type: 'csv_export',
- for_export: 'true'
- ).create_for(@current_user.id)
+ upload =
+ UploadCreator.new(
+ file,
+ File.basename(zip_filename),
+ type: "csv_export",
+ for_export: "true",
+ ).create_for(@current_user.id)
if upload.persisted?
user_export.update_columns(upload_id: upload.id)
else
- Rails.logger.warn("Failed to upload the file #{zip_filename}: #{upload.errors.full_messages}")
+ Rails.logger.warn(
+ "Failed to upload the file #{zip_filename}: #{upload.errors.full_messages}",
+ )
end
end
@@ -125,21 +200,20 @@ module Jobs
if user_export.present? && post.present?
topic = post.topic
user_export.update_columns(topic_id: topic.id)
- topic.update_status('closed', true, Discourse.system_user)
+ topic.update_status("closed", true, Discourse.system_user)
end
end
def user_archive_export
return enum_for(:user_archive_export) unless block_given?
- Post.includes(topic: :category)
+ Post
+ .includes(topic: :category)
.where(user_id: @current_user.id)
.select(:topic_id, :post_number, :raw, :cooked, :like_count, :reply_count, :created_at)
.order(:created_at)
.with_deleted
- .each do |user_archive|
- yield get_user_archive_fields(user_archive)
- end
+ .each { |user_archive| yield get_user_archive_fields(user_archive) }
end
def user_archive_profile_export
@@ -148,9 +222,7 @@ module Jobs
UserProfile
.where(user_id: @current_user.id)
.select(:location, :website, :bio_raw, :views)
- .each do |user_profile|
- yield get_user_archive_profile_fields(user_profile)
- end
+ .each { |user_profile| yield get_user_archive_profile_fields(user_profile) }
end
def preferences_export
@@ -167,19 +239,21 @@ module Jobs
UserAuthToken
.where(user_id: @current_user.id)
.each do |token|
- yield [
- token.id,
- token.auth_token.to_s[0..4] + "...", # hashed and truncated
- token.prev_auth_token[0..4] + "...",
- token.auth_token_seen,
- token.client_ip,
- token.user_agent,
- token.seen_at,
- token.rotated_at,
- token.created_at,
- token.updated_at,
- ]
- end
+ yield(
+ [
+ token.id,
+ token.auth_token.to_s[0..4] + "...", # hashed and truncated
+ token.prev_auth_token[0..4] + "...",
+ token.auth_token_seen,
+ token.client_ip,
+ token.user_agent,
+ token.seen_at,
+ token.rotated_at,
+ token.created_at,
+ token.updated_at,
+ ]
+ )
+ end
end
def include_auth_token_logs?
@@ -193,17 +267,19 @@ module Jobs
UserAuthTokenLog
.where(user_id: @current_user.id)
.each do |log|
- yield [
- log.id,
- log.action,
- log.user_auth_token_id,
- log.client_ip,
- log.auth_token.to_s[0..4] + "...", # hashed and truncated
- log.created_at,
- log.path,
- log.user_agent,
- ]
- end
+ yield(
+ [
+ log.id,
+ log.action,
+ log.user_auth_token_id,
+ log.client_ip,
+ log.auth_token.to_s[0..4] + "...", # hashed and truncated
+ log.created_at,
+ log.path,
+ log.user_agent,
+ ]
+ )
+ end
end
def badges_export
@@ -212,49 +288,65 @@ module Jobs
UserBadge
.where(user_id: @current_user.id)
.joins(:badge)
- .select(:badge_id, :granted_at, :post_id, :seq, :granted_by_id, :notification_id, :featured_rank)
+ .select(
+ :badge_id,
+ :granted_at,
+ :post_id,
+ :seq,
+ :granted_by_id,
+ :notification_id,
+ :featured_rank,
+ )
.order(:granted_at)
.each do |ub|
- yield [
- ub.badge_id,
- ub.badge.display_name,
- ub.granted_at,
- ub.post_id,
- ub.seq,
- # Hide the admin's identity, simply indicate human or system
- User.human_user_id?(ub.granted_by_id),
- ub.notification_id,
- ub.featured_rank,
- ]
- end
+ yield(
+ [
+ ub.badge_id,
+ ub.badge.display_name,
+ ub.granted_at,
+ ub.post_id,
+ ub.seq,
+ # Hide the admin's identity, simply indicate human or system
+ User.human_user_id?(ub.granted_by_id),
+ ub.notification_id,
+ ub.featured_rank,
+ ]
+ )
+ end
end
def bookmarks_export
return enum_for(:bookmarks_export) unless block_given?
- @current_user.bookmarks.where.not(bookmarkable_type: nil).order(:id).each do |bookmark|
- link = ''
- if guardian.can_see_bookmarkable?(bookmark)
- if bookmark.bookmarkable.respond_to?(:full_url)
- link = bookmark.bookmarkable.full_url
- else
- link = bookmark.bookmarkable.url
+ @current_user
+ .bookmarks
+ .where.not(bookmarkable_type: nil)
+ .order(:id)
+ .each do |bookmark|
+ link = ""
+ if guardian.can_see_bookmarkable?(bookmark)
+ if bookmark.bookmarkable.respond_to?(:full_url)
+ link = bookmark.bookmarkable.full_url
+ else
+ link = bookmark.bookmarkable.url
+ end
end
- end
- yield [
- bookmark.bookmarkable_id,
- bookmark.bookmarkable_type,
- link,
- bookmark.name,
- bookmark.created_at,
- bookmark.updated_at,
- bookmark.reminder_at,
- bookmark.reminder_last_sent_at,
- bookmark.reminder_set_at,
- Bookmark.auto_delete_preferences[bookmark.auto_delete_preference],
- ]
- end
+ yield(
+ [
+ bookmark.bookmarkable_id,
+ bookmark.bookmarkable_type,
+ link,
+ bookmark.name,
+ bookmark.created_at,
+ bookmark.updated_at,
+ bookmark.reminder_at,
+ bookmark.reminder_last_sent_at,
+ bookmark.reminder_set_at,
+ Bookmark.auto_delete_preferences[bookmark.auto_delete_preference],
+ ]
+ )
+ end
end
def category_preferences_export
@@ -265,12 +357,14 @@ module Jobs
.includes(:category)
.merge(Category.secured(guardian))
.each do |cu|
- yield [
- cu.category_id,
- piped_category_name(cu.category_id, cu.category),
- NotificationLevels.all[cu.notification_level],
- cu.last_seen_at
- ]
+ yield(
+ [
+ cu.category_id,
+ piped_category_name(cu.category_id, cu.category),
+ NotificationLevels.all[cu.notification_level],
+ cu.last_seen_at,
+ ]
+ )
end
end
@@ -283,20 +377,22 @@ module Jobs
.where(post_action_type_id: PostActionType.flag_types.values)
.order(:created_at)
.each do |pa|
- yield [
- pa.id,
- pa.post_id,
- PostActionType.flag_types[pa.post_action_type_id],
- pa.created_at,
- pa.updated_at,
- pa.deleted_at,
- self_or_other(pa.deleted_by_id),
- pa.related_post_id,
- pa.targets_topic,
- # renamed to 'was_take_action' to avoid possibility of thinking this is a synonym of agreed_at
- pa.staff_took_action,
- ]
- end
+ yield(
+ [
+ pa.id,
+ pa.post_id,
+ PostActionType.flag_types[pa.post_action_type_id],
+ pa.created_at,
+ pa.updated_at,
+ pa.deleted_at,
+ self_or_other(pa.deleted_by_id),
+ pa.related_post_id,
+ pa.targets_topic,
+ # renamed to 'was_take_action' to avoid possibility of thinking this is a synonym of agreed_at
+ pa.staff_took_action,
+ ]
+ )
+ end
end
def likes_export
@@ -307,25 +403,29 @@ module Jobs
.where(post_action_type_id: PostActionType.types[:like])
.order(:created_at)
.each do |pa|
- post = Post.with_deleted.find_by(id: pa.post_id)
- yield [
- pa.id,
- pa.post_id,
- post&.topic_id,
- post&.post_number,
- pa.created_at,
- pa.updated_at,
- pa.deleted_at,
- self_or_other(pa.deleted_by_id),
- ]
- end
+ post = Post.with_deleted.find_by(id: pa.post_id)
+ yield(
+ [
+ pa.id,
+ pa.post_id,
+ post&.topic_id,
+ post&.post_number,
+ pa.created_at,
+ pa.updated_at,
+ pa.deleted_at,
+ self_or_other(pa.deleted_by_id),
+ ]
+ )
+ end
end
def include_post_actions?
# Most forums should not have post_action records other than flags and likes, but they are possible in historical oddities.
PostAction
.where(user_id: @current_user.id)
- .where.not(post_action_type_id: PostActionType.flag_types.values + [PostActionType.types[:like]])
+ .where.not(
+ post_action_type_id: PostActionType.flag_types.values + [PostActionType.types[:like]],
+ )
.exists?
end
@@ -334,20 +434,24 @@ module Jobs
PostAction
.with_deleted
.where(user_id: @current_user.id)
- .where.not(post_action_type_id: PostActionType.flag_types.values + [PostActionType.types[:like]])
+ .where.not(
+ post_action_type_id: PostActionType.flag_types.values + [PostActionType.types[:like]],
+ )
.order(:created_at)
.each do |pa|
- yield [
- pa.id,
- pa.post_id,
- PostActionType.types[pa.post_action_type] || pa.post_action_type,
- pa.created_at,
- pa.updated_at,
- pa.deleted_at,
- self_or_other(pa.deleted_by_id),
- pa.related_post_id,
- ]
- end
+ yield(
+ [
+ pa.id,
+ pa.post_id,
+ PostActionType.types[pa.post_action_type] || pa.post_action_type,
+ pa.created_at,
+ pa.updated_at,
+ pa.deleted_at,
+ self_or_other(pa.deleted_by_id),
+ pa.related_post_id,
+ ]
+ )
+ end
end
def queued_posts_export
@@ -358,16 +462,17 @@ module Jobs
.where(created_by: @current_user.id)
.order(:created_at)
.each do |rev|
-
- yield [
- rev.id,
- rev.status,
- rev.category_id,
- rev.topic_id,
- rev.payload['raw'],
- MultiJson.dump(rev.payload.slice(*queued_posts_payload_permitted_keys)),
- ]
- end
+ yield(
+ [
+ rev.id,
+ rev.status,
+ rev.category_id,
+ rev.topic_id,
+ rev.payload["raw"],
+ MultiJson.dump(rev.payload.slice(*queued_posts_payload_permitted_keys)),
+ ]
+ )
+ end
end
def visits_export
@@ -376,20 +481,15 @@ module Jobs
UserVisit
.where(user_id: @current_user.id)
.order(visited_at: :asc)
- .each do |uv|
- yield [
- uv.visited_at,
- uv.posts_read,
- uv.mobile,
- uv.time_read,
- ]
- end
+ .each { |uv| yield [uv.visited_at, uv.posts_read, uv.mobile, uv.time_read] }
end
def get_header(entity)
- if entity == 'user_list'
- header_array = HEADER_ATTRS_FOR['user_list'] + HEADER_ATTRS_FOR['user_stats'] + HEADER_ATTRS_FOR['user_profile']
- header_array.concat(HEADER_ATTRS_FOR['user_sso']) if SiteSetting.enable_discourse_connect
+ if entity == "user_list"
+ header_array =
+ HEADER_ATTRS_FOR["user_list"] + HEADER_ATTRS_FOR["user_stats"] +
+ HEADER_ATTRS_FOR["user_profile"]
+ header_array.concat(HEADER_ATTRS_FOR["user_sso"]) if SiteSetting.enable_discourse_connect
user_custom_fields = UserField.all
if user_custom_fields.present?
user_custom_fields.each do |custom_field|
@@ -424,9 +524,9 @@ module Jobs
if user_id.nil?
nil
elsif user_id == @current_user.id
- 'self'
+ "self"
else
- 'other'
+ "other"
end
end
@@ -434,27 +534,37 @@ module Jobs
user_archive_array = []
topic_data = user_archive.topic
user_archive = user_archive.as_json
- topic_data = Topic.with_deleted.includes(:category).find_by(id: user_archive['topic_id']) if topic_data.nil?
+ topic_data =
+ Topic
+ .with_deleted
+ .includes(:category)
+ .find_by(id: user_archive["topic_id"]) if topic_data.nil?
return user_archive_array if topic_data.nil?
categories = piped_category_name(topic_data.category_id, topic_data.category)
- is_pm = topic_data.archetype == "private_message" ? I18n.t("csv_export.boolean_yes") : I18n.t("csv_export.boolean_no")
- url = "#{Discourse.base_url}/t/#{topic_data.slug}/#{topic_data.id}/#{user_archive['post_number']}"
+ is_pm =
+ (
+ if topic_data.archetype == "private_message"
+ I18n.t("csv_export.boolean_yes")
+ else
+ I18n.t("csv_export.boolean_no")
+ end
+ )
+ url =
+ "#{Discourse.base_url}/t/#{topic_data.slug}/#{topic_data.id}/#{user_archive["post_number"]}"
topic_hash = {
- "post_raw" => user_archive['raw'],
+ "post_raw" => user_archive["raw"],
"post_cooked" => user_archive["cooked"],
"topic_title" => topic_data.title,
"categories" => categories,
"is_pm" => is_pm,
- "url" => url
+ "url" => url,
}
user_archive.merge!(topic_hash)
- HEADER_ATTRS_FOR['user_archive'].each do |attr|
- user_archive_array.push(user_archive[attr])
- end
+ HEADER_ATTRS_FOR["user_archive"].each { |attr| user_archive_array.push(user_archive[attr]) }
user_archive_array
end
@@ -462,15 +572,15 @@ module Jobs
def get_user_archive_profile_fields(user_profile)
user_archive_profile = []
- HEADER_ATTRS_FOR['user_archive_profile'].each do |attr|
+ HEADER_ATTRS_FOR["user_archive_profile"].each do |attr|
data =
- if attr == 'bio'
- user_profile.attributes['bio_raw']
+ if attr == "bio"
+ user_profile.attributes["bio_raw"]
else
user_profile.attributes[attr]
end
- user_archive_profile.push(data)
+ user_archive_profile.push(data)
end
user_archive_profile
@@ -483,30 +593,24 @@ module Jobs
# where type = 'ReviewableQueuedPost' and (payload->'old_queued_post_id') IS NULL
#
# except raw, created_topic_id, created_post_id
- %w{
- composer_open_duration_msecs
- is_poll
- reply_to_post_number
- tags
- title
- typing_duration_msecs
- }
+ %w[composer_open_duration_msecs is_poll reply_to_post_number tags title typing_duration_msecs]
end
def notify_user(upload, export_title)
post = nil
if @current_user
- post = if upload.persisted?
- SystemMessage.create_from_system_user(
- @current_user,
- :csv_export_succeeded,
- download_link: UploadMarkdown.new(upload).attachment_markdown,
- export_title: export_title
- )
- else
- SystemMessage.create_from_system_user(@current_user, :csv_export_failed)
- end
+ post =
+ if upload.persisted?
+ SystemMessage.create_from_system_user(
+ @current_user,
+ :csv_export_succeeded,
+ download_link: UploadMarkdown.new(upload).attachment_markdown,
+ export_title: export_title,
+ )
+ else
+ SystemMessage.create_from_system_user(@current_user, :csv_export_failed)
+ end
end
post
diff --git a/app/jobs/regular/feature_topic_users.rb b/app/jobs/regular/feature_topic_users.rb
index 84210a6bafa..83266c725b2 100644
--- a/app/jobs/regular/feature_topic_users.rb
+++ b/app/jobs/regular/feature_topic_users.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module Jobs
-
class FeatureTopicUsers < ::Jobs::Base
-
def execute(args)
topic_id = args[:topic_id]
raise Discourse::InvalidParameters.new(:topic_id) unless topic_id.present?
@@ -17,7 +15,5 @@ module Jobs
topic.feature_topic_users(args)
end
-
end
-
end
diff --git a/app/jobs/regular/generate_topic_thumbnails.rb b/app/jobs/regular/generate_topic_thumbnails.rb
index e670e0fe41b..2ad13a2d71e 100644
--- a/app/jobs/regular/generate_topic_thumbnails.rb
+++ b/app/jobs/regular/generate_topic_thumbnails.rb
@@ -2,7 +2,7 @@
module Jobs
class GenerateTopicThumbnails < ::Jobs::Base
- sidekiq_options queue: 'ultra_low'
+ sidekiq_options queue: "ultra_low"
def execute(args)
topic_id = args[:topic_id]
@@ -13,6 +13,5 @@ module Jobs
topic = Topic.find_by(id: topic_id)
topic&.generate_thumbnails!(extra_sizes: extra_sizes)
end
-
end
end
diff --git a/app/jobs/regular/group_pm_alert.rb b/app/jobs/regular/group_pm_alert.rb
index 530560e16d7..3f562801a98 100644
--- a/app/jobs/regular/group_pm_alert.rb
+++ b/app/jobs/regular/group_pm_alert.rb
@@ -12,12 +12,10 @@ module Jobs
alerter = PostAlerter.new
- group.users.where(
- "group_users.notification_level = :level",
- level: NotificationLevels.all[:tracking]
- ).find_each do |u|
- alerter.notify_group_summary(u, topic)
- end
+ group
+ .users
+ .where("group_users.notification_level = :level", level: NotificationLevels.all[:tracking])
+ .find_each { |u| alerter.notify_group_summary(u, topic) }
notification_data = {
notification_type: Notification.types[:invited_to_private_message],
@@ -26,17 +24,18 @@ module Jobs
data: {
topic_title: topic.title,
display_username: user.username,
- group_id: group.id
- }.to_json
+ group_id: group.id,
+ }.to_json,
}
- group.users.where(
- "group_users.notification_level in (:levels) AND user_id != :id",
- levels: [NotificationLevels.all[:watching], NotificationLevels.all[:watching_first_post]],
- id: user.id
- ).find_each do |u|
- u.notifications.create!(notification_data)
- end
+ group
+ .users
+ .where(
+ "group_users.notification_level in (:levels) AND user_id != :id",
+ levels: [NotificationLevels.all[:watching], NotificationLevels.all[:watching_first_post]],
+ id: user.id,
+ )
+ .find_each { |u| u.notifications.create!(notification_data) }
end
end
end
diff --git a/app/jobs/regular/group_pm_update_summary.rb b/app/jobs/regular/group_pm_update_summary.rb
index cb6c5a61f10..74f151c77ca 100644
--- a/app/jobs/regular/group_pm_update_summary.rb
+++ b/app/jobs/regular/group_pm_update_summary.rb
@@ -10,13 +10,12 @@ module Jobs
alerter = PostAlerter.new
- group.users.where(
- "group_users.notification_level = :level",
- level: NotificationLevels.all[:tracking]
- ).find_each do |u|
- alerter.notify_group_summary(u, topic, acting_user_id: args[:acting_user_id])
- end
-
+ group
+ .users
+ .where("group_users.notification_level = :level", level: NotificationLevels.all[:tracking])
+ .find_each do |u|
+ alerter.notify_group_summary(u, topic, acting_user_id: args[:acting_user_id])
+ end
end
end
end
diff --git a/app/jobs/regular/group_smtp_email.rb b/app/jobs/regular/group_smtp_email.rb
index b0fc4a890e9..6970c673ff9 100644
--- a/app/jobs/regular/group_smtp_email.rb
+++ b/app/jobs/regular/group_smtp_email.rb
@@ -4,7 +4,7 @@ module Jobs
class GroupSmtpEmail < ::Jobs::Base
include Skippable
- sidekiq_options queue: 'critical'
+ sidekiq_options queue: "critical"
sidekiq_retry_in do |count, exception|
# retry in an hour when SMTP server is busy
@@ -25,9 +25,7 @@ module Jobs
recipient_user = User.find_by_email(email, primary: true)
post = Post.find_by(id: args[:post_id])
- if post.blank?
- return skip(email, nil, recipient_user, :group_smtp_post_deleted)
- end
+ return skip(email, nil, recipient_user, :group_smtp_post_deleted) if post.blank?
group = Group.find_by(id: args[:group_id])
return if group.blank?
@@ -40,9 +38,8 @@ module Jobs
return skip(email, post, recipient_user, :group_smtp_topic_deleted)
end
- cc_addresses = args[:cc_emails].filter do |address|
- EmailAddressValidator.valid_value?(address)
- end
+ cc_addresses =
+ args[:cc_emails].filter { |address| EmailAddressValidator.valid_value?(address) }
# Mask the email addresses of non-staged users so
# they are not revealed unnecessarily when we are sending
@@ -63,22 +60,29 @@ module Jobs
# for example in cases where we are creating a new topic to reply to another
# group PM and we need to send the participants the group OP email.
if post.is_first_post? && group.imap_enabled
- ImapSyncLog.warn("Aborting SMTP email for post #{post.id} in topic #{post.topic_id} to #{email}, the post is the OP and should not send an email.", group)
+ ImapSyncLog.warn(
+ "Aborting SMTP email for post #{post.id} in topic #{post.topic_id} to #{email}, the post is the OP and should not send an email.",
+ group,
+ )
return
end
- ImapSyncLog.debug("Sending SMTP email for post #{post.id} in topic #{post.topic_id} to #{email}.", group)
+ ImapSyncLog.debug(
+ "Sending SMTP email for post #{post.id} in topic #{post.topic_id} to #{email}.",
+ group,
+ )
# The EmailLog record created by the sender will have the raw email
# stored, the group smtp ID, and any cc addresses recorded for later
# cross referencing.
- message = GroupSmtpMailer.send_mail(
- group,
- email,
- post,
- cc_addresses: cc_addresses,
- bcc_addresses: bcc_addresses
- )
+ message =
+ GroupSmtpMailer.send_mail(
+ group,
+ email,
+ post,
+ cc_addresses: cc_addresses,
+ bcc_addresses: bcc_addresses,
+ )
Email::Sender.new(message, :group_smtp, recipient_user).send
# Create an incoming email record to avoid importing again from IMAP
@@ -95,12 +99,12 @@ module Jobs
to_addresses: message.to,
cc_addresses: message.cc,
from_address: message.from,
- created_via: IncomingEmail.created_via_types[:group_smtp]
+ created_via: IncomingEmail.created_via_types[:group_smtp],
)
end
def quit_email_early?
- SiteSetting.disable_emails == 'yes' || !SiteSetting.enable_smtp
+ SiteSetting.disable_emails == "yes" || !SiteSetting.enable_smtp
end
def skip(email, post, recipient_user, reason)
@@ -109,7 +113,7 @@ module Jobs
to_address: email,
user_id: recipient_user&.id,
post_id: post&.id,
- reason_type: SkippedEmailLog.reason_types[reason]
+ reason_type: SkippedEmailLog.reason_types[reason],
)
end
end
diff --git a/app/jobs/regular/invite_email.rb b/app/jobs/regular/invite_email.rb
index 5d0b0e68df6..ad33a9ee5ce 100644
--- a/app/jobs/regular/invite_email.rb
+++ b/app/jobs/regular/invite_email.rb
@@ -1,10 +1,8 @@
# frozen_string_literal: true
module Jobs
-
# Asynchronously send an email
class InviteEmail < ::Jobs::Base
-
def execute(args)
raise Discourse::InvalidParameters.new(:invite_id) unless args[:invite_id].present?
diff --git a/app/jobs/regular/invite_password_instructions_email.rb b/app/jobs/regular/invite_password_instructions_email.rb
index 14ccec97c45..8989772ba8d 100644
--- a/app/jobs/regular/invite_password_instructions_email.rb
+++ b/app/jobs/regular/invite_password_instructions_email.rb
@@ -1,17 +1,13 @@
# frozen_string_literal: true
module Jobs
-
# Asynchronously send an email
class InvitePasswordInstructionsEmail < ::Jobs::Base
-
def execute(args)
raise Discourse::InvalidParameters.new(:username) unless args[:username].present?
user = User.find_by_username_or_email(args[:username])
message = InviteMailer.send_password_instructions(user)
Email::Sender.new(message, :invite_password_instructions).send
end
-
end
-
end
diff --git a/app/jobs/regular/make_embedded_topic_visible.rb b/app/jobs/regular/make_embedded_topic_visible.rb
index c3c4121b5f4..0d8e90a6185 100644
--- a/app/jobs/regular/make_embedded_topic_visible.rb
+++ b/app/jobs/regular/make_embedded_topic_visible.rb
@@ -2,14 +2,12 @@
module Jobs
class MakeEmbeddedTopicVisible < ::Jobs::Base
-
def execute(args)
raise Discourse::InvalidParameters.new(:topic_id) if args[:topic_id].blank?
if topic = Topic.find_by(id: args[:topic_id])
- topic.update_status('visible', true, topic.user)
+ topic.update_status("visible", true, topic.user)
end
end
-
end
end
diff --git a/app/jobs/regular/merge_user.rb b/app/jobs/regular/merge_user.rb
index e759b08d18d..abfb3d10ab6 100644
--- a/app/jobs/regular/merge_user.rb
+++ b/app/jobs/regular/merge_user.rb
@@ -2,7 +2,6 @@
module Jobs
class MergeUser < ::Jobs::Base
-
def execute(args)
target_user_id = args[:target_user_id]
current_user_id = args[:current_user_id]
@@ -15,9 +14,16 @@ module Jobs
if user = UserMerger.new(user, target_user, current_user).merge!
user_json = AdminDetailedUserSerializer.new(user, serializer_opts).as_json
- ::MessageBus.publish '/merge_user', { success: 'OK' }.merge(merged: true, user: user_json), user_ids: [current_user.id]
+ ::MessageBus.publish "/merge_user",
+ { success: "OK" }.merge(merged: true, user: user_json),
+ user_ids: [current_user.id]
else
- ::MessageBus.publish '/merge_user', { failed: 'FAILED' }.merge(user: AdminDetailedUserSerializer.new(@user, serializer_opts).as_json), user_ids: [current_user.id]
+ ::MessageBus.publish "/merge_user",
+ { failed: "FAILED" }.merge(
+ user:
+ AdminDetailedUserSerializer.new(@user, serializer_opts).as_json,
+ ),
+ user_ids: [current_user.id]
end
end
end
diff --git a/app/jobs/regular/notify_category_change.rb b/app/jobs/regular/notify_category_change.rb
index fbad7582e4a..f1f6c020f04 100644
--- a/app/jobs/regular/notify_category_change.rb
+++ b/app/jobs/regular/notify_category_change.rb
@@ -7,7 +7,11 @@ module Jobs
if post&.topic&.visible?
post_alerter = PostAlerter.new
- post_alerter.notify_post_users(post, User.where(id: args[:notified_user_ids]), include_tag_watchers: false)
+ post_alerter.notify_post_users(
+ post,
+ User.where(id: args[:notified_user_ids]),
+ include_tag_watchers: false,
+ )
post_alerter.notify_first_post_watchers(post, post_alerter.category_watchers(post.topic))
end
end
diff --git a/app/jobs/regular/notify_mailing_list_subscribers.rb b/app/jobs/regular/notify_mailing_list_subscribers.rb
index 03a431ab3f4..467af7cff79 100644
--- a/app/jobs/regular/notify_mailing_list_subscribers.rb
+++ b/app/jobs/regular/notify_mailing_list_subscribers.rb
@@ -1,13 +1,12 @@
# frozen_string_literal: true
module Jobs
-
class NotifyMailingListSubscribers < ::Jobs::Base
include Skippable
RETRY_TIMES = [5.minute, 15.minute, 30.minute, 45.minute, 90.minute, 180.minute, 300.minute]
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
sidekiq_options retry: RETRY_TIMES.size
@@ -28,72 +27,97 @@ module Jobs
post_id = args[:post_id]
post = post_id ? Post.with_deleted.find_by(id: post_id) : nil
- return if !post || post.trashed? || post.user_deleted? ||
- !post.topic || post.raw.blank? || post.topic.private_message?
+ if !post || post.trashed? || post.user_deleted? || !post.topic || post.raw.blank? ||
+ post.topic.private_message?
+ return
+ end
users =
- User.activated.not_silenced.not_suspended.real
- .joins(:user_option)
- .where('user_options.mailing_list_mode AND user_options.mailing_list_mode_frequency > 0')
- .where('NOT EXISTS (
+ User
+ .activated
+ .not_silenced
+ .not_suspended
+ .real
+ .joins(:user_option)
+ .where("user_options.mailing_list_mode AND user_options.mailing_list_mode_frequency > 0")
+ .where(
+ "NOT EXISTS (
SELECT 1
FROM muted_users mu
WHERE mu.muted_user_id = ? AND mu.user_id = users.id
- )', post.user_id)
- .where('NOT EXISTS (
+ )",
+ post.user_id,
+ )
+ .where(
+ "NOT EXISTS (
SELECT 1
FROM ignored_users iu
WHERE iu.ignored_user_id = ? AND iu.user_id = users.id
- )', post.user_id)
- .where('NOT EXISTS (
+ )",
+ post.user_id,
+ )
+ .where(
+ "NOT EXISTS (
SELECT 1
FROM topic_users tu
WHERE tu.topic_id = ? AND tu.user_id = users.id AND tu.notification_level = ?
- )', post.topic_id, TopicUser.notification_levels[:muted])
- .where('NOT EXISTS (
+ )",
+ post.topic_id,
+ TopicUser.notification_levels[:muted],
+ )
+ .where(
+ "NOT EXISTS (
SELECT 1
FROM category_users cu
WHERE cu.category_id = ? AND cu.user_id = users.id AND cu.notification_level = ?
- )', post.topic.category_id, CategoryUser.notification_levels[:muted])
+ )",
+ post.topic.category_id,
+ CategoryUser.notification_levels[:muted],
+ )
if SiteSetting.tagging_enabled?
- users = users.where('NOT EXISTS (
+ users =
+ users.where(
+ "NOT EXISTS (
SELECT 1
FROM tag_users tu
WHERE tu.tag_id in (:tag_ids) AND tu.user_id = users.id AND tu.notification_level = :muted
- )', tag_ids: post.topic.tag_ids, muted: TagUser.notification_levels[:muted])
+ )",
+ tag_ids: post.topic.tag_ids,
+ muted: TagUser.notification_levels[:muted],
+ )
end
- if SiteSetting.must_approve_users
- users = users.where(approved: true)
- end
+ users = users.where(approved: true) if SiteSetting.must_approve_users
- if SiteSetting.mute_all_categories_by_default
- users = users.watching_topic(post.topic)
- end
+ users = users.watching_topic(post.topic) if SiteSetting.mute_all_categories_by_default
DiscourseEvent.trigger(:notify_mailing_list_subscribers, users, post)
users.find_each do |user|
if Guardian.new(user).can_see?(post)
if EmailLog.reached_max_emails?(user)
- skip(user.email, user.id, post.id,
- SkippedEmailLog.reason_types[:exceeded_emails_limit]
- )
+ skip(user.email, user.id, post.id, SkippedEmailLog.reason_types[:exceeded_emails_limit])
next
end
if user.user_stat.bounce_score >= SiteSetting.bounce_score_threshold
- skip(user.email, user.id, post.id,
- SkippedEmailLog.reason_types[:exceeded_bounces_limit]
+ skip(
+ user.email,
+ user.id,
+ post.id,
+ SkippedEmailLog.reason_types[:exceeded_bounces_limit],
)
next
end
if (user.id == post.user_id) && (user.user_option.mailing_list_mode_frequency == 2)
- skip(user.email, user.id, post.id,
- SkippedEmailLog.reason_types[:mailing_list_no_echo_mode]
+ skip(
+ user.email,
+ user.id,
+ post.id,
+ SkippedEmailLog.reason_types[:mailing_list_no_echo_mode],
)
next
@@ -106,20 +130,27 @@ module Jobs
end
end
rescue => e
- Discourse.handle_job_exception(e, error_context(args, "Sending post to mailing list subscribers", user_id: user.id, user_email: user.email))
+ Discourse.handle_job_exception(
+ e,
+ error_context(
+ args,
+ "Sending post to mailing list subscribers",
+ user_id: user.id,
+ user_email: user.email,
+ ),
+ )
end
end
end
-
end
def skip(to_address, user_id, post_id, reason_type)
create_skipped_email_log(
- email_type: 'mailing_list',
+ email_type: "mailing_list",
to_address: to_address,
user_id: user_id,
post_id: post_id,
- reason_type: reason_type
+ reason_type: reason_type,
)
end
end
diff --git a/app/jobs/regular/notify_moved_posts.rb b/app/jobs/regular/notify_moved_posts.rb
index f02feec7a67..d97b52f2168 100644
--- a/app/jobs/regular/notify_moved_posts.rb
+++ b/app/jobs/regular/notify_moved_posts.rb
@@ -1,33 +1,33 @@
# frozen_string_literal: true
module Jobs
-
class NotifyMovedPosts < ::Jobs::Base
-
def execute(args)
raise Discourse::InvalidParameters.new(:post_ids) if args[:post_ids].blank?
raise Discourse::InvalidParameters.new(:moved_by_id) if args[:moved_by_id].blank?
# Make sure we don't notify the same user twice (in case multiple posts were moved at once.)
users_notified = Set.new
- posts = Post.where(id: args[:post_ids]).where('user_id <> ?', args[:moved_by_id]).includes(:user, :topic)
+ posts =
+ Post
+ .where(id: args[:post_ids])
+ .where("user_id <> ?", args[:moved_by_id])
+ .includes(:user, :topic)
if posts.present?
moved_by = User.find_by(id: args[:moved_by_id])
posts.each do |p|
unless users_notified.include?(p.user_id)
- p.user.notifications.create(notification_type: Notification.types[:moved_post],
- topic_id: p.topic_id,
- post_number: p.post_number,
- data: { topic_title: p.topic.title,
- display_username: moved_by.username }.to_json)
+ p.user.notifications.create(
+ notification_type: Notification.types[:moved_post],
+ topic_id: p.topic_id,
+ post_number: p.post_number,
+ data: { topic_title: p.topic.title, display_username: moved_by.username }.to_json,
+ )
users_notified << p.user_id
end
end
end
-
end
-
end
-
end
diff --git a/app/jobs/regular/notify_post_revision.rb b/app/jobs/regular/notify_post_revision.rb
index f4b0262e06a..f37111bc25d 100644
--- a/app/jobs/regular/notify_post_revision.rb
+++ b/app/jobs/regular/notify_post_revision.rb
@@ -9,18 +9,20 @@ module Jobs
return if post_revision.nil?
ActiveRecord::Base.transaction do
- User.where(id: args[:user_ids]).find_each do |user|
- next if post_revision.hidden && !user.staff?
+ User
+ .where(id: args[:user_ids])
+ .find_each do |user|
+ next if post_revision.hidden && !user.staff?
- PostActionNotifier.alerter.create_notification(
- user,
- Notification.types[:edited],
- post_revision.post,
- display_username: post_revision.user.username,
- acting_user_id: post_revision&.user_id,
- revision_number: post_revision.number
- )
- end
+ PostActionNotifier.alerter.create_notification(
+ user,
+ Notification.types[:edited],
+ post_revision.post,
+ display_username: post_revision.user.username,
+ acting_user_id: post_revision&.user_id,
+ revision_number: post_revision.number,
+ )
+ end
end
end
end
diff --git a/app/jobs/regular/notify_reviewable.rb b/app/jobs/regular/notify_reviewable.rb
index 5b71ac557e1..a59adc4ac19 100644
--- a/app/jobs/regular/notify_reviewable.rb
+++ b/app/jobs/regular/notify_reviewable.rb
@@ -11,16 +11,15 @@ class Jobs::NotifyReviewable < ::Jobs::Base
all_updates = Hash.new { |h, k| h[k] = {} }
if args[:updated_reviewable_ids].present?
- Reviewable.where(id: args[:updated_reviewable_ids]).each do |r|
- payload = {
- last_performing_username: args[:performing_username],
- status: r.status
- }
+ Reviewable
+ .where(id: args[:updated_reviewable_ids])
+ .each do |r|
+ payload = { last_performing_username: args[:performing_username], status: r.status }
- all_updates[:admins][r.id] = payload
- all_updates[:moderators][r.id] = payload if r.reviewable_by_moderator?
- all_updates[r.reviewable_by_group_id][r.id] = payload if r.reviewable_by_group_id
- end
+ all_updates[:admins][r.id] = payload
+ all_updates[:moderators][r.id] = payload if r.reviewable_by_moderator?
+ all_updates[r.reviewable_by_group_id][r.id] = payload if r.reviewable_by_group_id
+ end
end
counts = Hash.new(0)
@@ -38,10 +37,7 @@ class Jobs::NotifyReviewable < ::Jobs::Base
updates: all_updates[:admins],
)
else
- notify_users(
- User.real.admins,
- all_updates[:admins]
- )
+ notify_users(User.real.admins, all_updates[:admins])
end
if reviewable.reviewable_by_moderator?
@@ -54,7 +50,7 @@ class Jobs::NotifyReviewable < ::Jobs::Base
else
notify_users(
User.real.moderators.where("id NOT IN (?)", @contacted),
- all_updates[:moderators]
+ all_updates[:moderators],
)
end
end
diff --git a/app/jobs/regular/notify_tag_change.rb b/app/jobs/regular/notify_tag_change.rb
index 0fcbbc621e8..0038dba193c 100644
--- a/app/jobs/regular/notify_tag_change.rb
+++ b/app/jobs/regular/notify_tag_change.rb
@@ -9,10 +9,12 @@ module Jobs
if post&.topic&.visible?
post_alerter = PostAlerter.new
- post_alerter.notify_post_users(post, User.where(id: args[:notified_user_ids]),
+ post_alerter.notify_post_users(
+ post,
+ User.where(id: args[:notified_user_ids]),
group_ids: all_tags_in_hidden_groups?(args) ? tag_group_ids(args) : nil,
include_topic_watchers: !post.topic.private_message?,
- include_category_watchers: false
+ include_category_watchers: false,
)
post_alerter.notify_first_post_watchers(post, post_alerter.tag_watchers(post.topic))
end
@@ -32,7 +34,10 @@ module Jobs
end
def tag_group_ids(args)
- Tag.where(name: args[:diff_tags]).joins(tag_groups: :tag_group_permissions).pluck("tag_group_permissions.group_id")
+ Tag
+ .where(name: args[:diff_tags])
+ .joins(tag_groups: :tag_group_permissions)
+ .pluck("tag_group_permissions.group_id")
end
end
end
diff --git a/app/jobs/regular/open_topic.rb b/app/jobs/regular/open_topic.rb
index f1e9fe0d2ff..8726d2c09f8 100644
--- a/app/jobs/regular/open_topic.rb
+++ b/app/jobs/regular/open_topic.rb
@@ -21,13 +21,12 @@ module Jobs
topic.set_or_create_timer(
TopicTimer.types[:open],
SiteSetting.num_hours_to_close_topic,
- by_user: Discourse.system_user
+ by_user: Discourse.system_user,
)
else
-
# autoclosed, false is just another way of saying open.
# this handles deleting the topic timer as well, see TopicStatusUpdater
- topic.update_status('autoclosed', false, user)
+ topic.update_status("autoclosed", false, user)
end
topic.inherit_auto_close_from_category(timer_type: :close)
diff --git a/app/jobs/regular/post_alert.rb b/app/jobs/regular/post_alert.rb
index dc6b8b1440b..b3aa1c1f00b 100644
--- a/app/jobs/regular/post_alert.rb
+++ b/app/jobs/regular/post_alert.rb
@@ -2,7 +2,6 @@
module Jobs
class PostAlert < ::Jobs::Base
-
def execute(args)
post = Post.find_by(id: args[:post_id])
if post&.topic && post.raw.present?
@@ -11,6 +10,5 @@ module Jobs
PostAlerter.new(opts).after_save_post(post, new_record)
end
end
-
end
end
diff --git a/app/jobs/regular/post_update_topic_tracking_state.rb b/app/jobs/regular/post_update_topic_tracking_state.rb
index c3d4610f802..da3a11268d8 100644
--- a/app/jobs/regular/post_update_topic_tracking_state.rb
+++ b/app/jobs/regular/post_update_topic_tracking_state.rb
@@ -2,7 +2,6 @@
module Jobs
class PostUpdateTopicTrackingState < ::Jobs::Base
-
def execute(args)
post = Post.find_by(id: args[:post_id])
return if !post&.topic
@@ -10,15 +9,9 @@ module Jobs
topic = post.topic
if topic.private_message?
- if post.post_number > 1
- PrivateMessageTopicTrackingState.publish_unread(post)
- end
+ PrivateMessageTopicTrackingState.publish_unread(post) if post.post_number > 1
- TopicGroup.new_message_update(
- topic.last_poster,
- topic.id,
- post.post_number
- )
+ TopicGroup.new_message_update(topic.last_poster, topic.id, post.post_number)
else
TopicTrackingState.publish_unmuted(post.topic)
if post.post_number > 1
@@ -28,6 +21,5 @@ module Jobs
TopicTrackingState.publish_latest(post.topic, post.whisper?)
end
end
-
end
end
diff --git a/app/jobs/regular/process_bulk_invite_emails.rb b/app/jobs/regular/process_bulk_invite_emails.rb
index f8b8a13846e..26152b8a873 100644
--- a/app/jobs/regular/process_bulk_invite_emails.rb
+++ b/app/jobs/regular/process_bulk_invite_emails.rb
@@ -1,17 +1,19 @@
# frozen_string_literal: true
module Jobs
-
class ProcessBulkInviteEmails < ::Jobs::Base
-
def execute(args)
- pending_invite_ids = Invite.where(emailed_status: Invite.emailed_status_types[:bulk_pending]).limit(Invite::BULK_INVITE_EMAIL_LIMIT).pluck(:id)
+ pending_invite_ids =
+ Invite
+ .where(emailed_status: Invite.emailed_status_types[:bulk_pending])
+ .limit(Invite::BULK_INVITE_EMAIL_LIMIT)
+ .pluck(:id)
if pending_invite_ids.length > 0
- Invite.where(id: pending_invite_ids).update_all(emailed_status: Invite.emailed_status_types[:sending])
- pending_invite_ids.each do |invite_id|
- ::Jobs.enqueue(:invite_email, invite_id: invite_id)
- end
+ Invite.where(id: pending_invite_ids).update_all(
+ emailed_status: Invite.emailed_status_types[:sending],
+ )
+ pending_invite_ids.each { |invite_id| ::Jobs.enqueue(:invite_email, invite_id: invite_id) }
::Jobs.enqueue_in(1.minute, :process_bulk_invite_emails)
end
end
diff --git a/app/jobs/regular/process_email.rb b/app/jobs/regular/process_email.rb
index 2ac10eddd15..0bad7eade23 100644
--- a/app/jobs/regular/process_email.rb
+++ b/app/jobs/regular/process_email.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class ProcessEmail < ::Jobs::Base
sidekiq_options retry: 3
@@ -9,14 +8,14 @@ module Jobs
Email::Processor.process!(
args[:mail],
retry_on_rate_limit: args[:retry_on_rate_limit] || false,
- source: args[:source]&.to_sym
+ source: args[:source]&.to_sym,
)
end
sidekiq_retries_exhausted do |msg|
- Rails.logger.warn("Incoming email could not be processed after 3 retries.\n\n#{msg["args"][:mail]}")
+ Rails.logger.warn(
+ "Incoming email could not be processed after 3 retries.\n\n#{msg["args"][:mail]}",
+ )
end
-
end
-
end
diff --git a/app/jobs/regular/process_post.rb b/app/jobs/regular/process_post.rb
index 60f444fe981..976d2f75bbf 100644
--- a/app/jobs/regular/process_post.rb
+++ b/app/jobs/regular/process_post.rb
@@ -1,11 +1,9 @@
# frozen_string_literal: true
-require 'image_sizer'
+require "image_sizer"
module Jobs
-
class ProcessPost < ::Jobs::Base
-
def execute(args)
DistributedMutex.synchronize("process_post_#{args[:post_id]}", validity: 10.minutes) do
post = Post.find_by(id: args[:post_id])
@@ -19,7 +17,11 @@ module Jobs
cooking_options = args[:cooking_options] || {}
cooking_options[:topic_id] = post.topic_id
recooked = post.cook(post.raw, cooking_options.symbolize_keys)
- post.update_columns(cooked: recooked, baked_at: Time.zone.now, baked_version: Post::BAKED_VERSION)
+ post.update_columns(
+ cooked: recooked,
+ baked_at: Time.zone.now,
+ baked_version: Post::BAKED_VERSION,
+ )
end
cp = CookedPostProcessor.new(post, args)
@@ -31,7 +33,9 @@ module Jobs
if cooked != (recooked || orig_cooked)
if orig_cooked.present? && cooked.blank?
# TODO stop/restart the worker if needed, let's gather a few here first
- Rails.logger.warn("Cooked post processor in FATAL state, bypassing. You need to urgently restart sidekiq\norig: #{orig_cooked}\nrecooked: #{recooked}\ncooked: #{cooked}\npost id: #{post.id}")
+ Rails.logger.warn(
+ "Cooked post processor in FATAL state, bypassing. You need to urgently restart sidekiq\norig: #{orig_cooked}\nrecooked: #{recooked}\ncooked: #{cooked}\npost id: #{post.id}",
+ )
else
post.update_column(:cooked, cp.html)
post.topic.update_excerpt(post.excerpt_for_topic) if post.is_first_post?
@@ -50,7 +54,7 @@ module Jobs
Discourse.system_user,
post,
:inappropriate,
- reason: :watched_word
+ reason: :watched_word,
)
end
end
@@ -68,5 +72,4 @@ module Jobs
Jobs.enqueue(:pull_hotlinked_images, post_id: post.id)
end
end
-
end
diff --git a/app/jobs/regular/process_sns_notification.rb b/app/jobs/regular/process_sns_notification.rb
index 67e9b0e3273..09e965a6ea4 100644
--- a/app/jobs/regular/process_sns_notification.rb
+++ b/app/jobs/regular/process_sns_notification.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class ProcessSnsNotification < ::Jobs::Base
sidekiq_options retry: false
@@ -10,11 +9,12 @@ module Jobs
return unless json = args[:json].presence
return unless message = json["Message"].presence
- message = begin
- JSON.parse(message)
- rescue JSON::ParserError
- nil
- end
+ message =
+ begin
+ JSON.parse(message)
+ rescue JSON::ParserError
+ nil
+ end
return unless message && message["notificationType"] == "Bounce"
return unless message_id = message.dig("mail", "messageId").presence
@@ -23,21 +23,29 @@ module Jobs
require "aws-sdk-sns"
return unless Aws::SNS::MessageVerifier.new.authentic?(raw)
- message.dig("bounce", "bouncedRecipients").each do |r|
- if email_log = EmailLog.order("created_at DESC").where(to_address: r["emailAddress"]).first
- email_log.update_columns(bounced: true, bounce_error_code: r["status"])
+ message
+ .dig("bounce", "bouncedRecipients")
+ .each do |r|
+ if email_log =
+ EmailLog.order("created_at DESC").where(to_address: r["emailAddress"]).first
+ email_log.update_columns(bounced: true, bounce_error_code: r["status"])
- if email_log.user&.email.present?
- if email_log.user.user_stat.bounce_score.to_s.start_with?("4.") || bounce_type == "Transient"
- Email::Receiver.update_bounce_score(email_log.user.email, SiteSetting.soft_bounce_score)
- else
- Email::Receiver.update_bounce_score(email_log.user.email, SiteSetting.hard_bounce_score)
+ if email_log.user&.email.present?
+ if email_log.user.user_stat.bounce_score.to_s.start_with?("4.") ||
+ bounce_type == "Transient"
+ Email::Receiver.update_bounce_score(
+ email_log.user.email,
+ SiteSetting.soft_bounce_score,
+ )
+ else
+ Email::Receiver.update_bounce_score(
+ email_log.user.email,
+ SiteSetting.hard_bounce_score,
+ )
+ end
end
end
end
- end
end
-
end
-
end
diff --git a/app/jobs/regular/publish_group_membership_updates.rb b/app/jobs/regular/publish_group_membership_updates.rb
index 6b93e87a0b2..5a5727717bb 100644
--- a/app/jobs/regular/publish_group_membership_updates.rb
+++ b/app/jobs/regular/publish_group_membership_updates.rb
@@ -11,13 +11,16 @@ module Jobs
added_members = args[:type] == Group::AUTO_GROUPS_ADD
- User.human_users.where(id: args[:user_ids]).each do |user|
- if added_members
- group.trigger_user_added_event(user, group.automatic?)
- else
- group.trigger_user_removed_event(user)
+ User
+ .human_users
+ .where(id: args[:user_ids])
+ .each do |user|
+ if added_members
+ group.trigger_user_added_event(user, group.automatic?)
+ else
+ group.trigger_user_removed_event(user)
+ end
end
- end
end
end
end
diff --git a/app/jobs/regular/pull_hotlinked_images.rb b/app/jobs/regular/pull_hotlinked_images.rb
index 7c1accdb89a..43a64f519eb 100644
--- a/app/jobs/regular/pull_hotlinked_images.rb
+++ b/app/jobs/regular/pull_hotlinked_images.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
module Jobs
-
class PullHotlinkedImages < ::Jobs::Base
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
def initialize
@max_size = SiteSetting.max_image_size_kb.kilobytes
@@ -23,8 +22,12 @@ module Jobs
changed_hotlink_records = false
extract_images_from(post.cooked).each do |node|
- download_src = original_src = node['src'] || node[PrettyText::BLOCKED_HOTLINKED_SRC_ATTR] || node['href']
- download_src = "#{SiteSetting.force_https ? "https" : "http"}:#{original_src}" if original_src.start_with?("//")
+ download_src =
+ original_src = node["src"] || node[PrettyText::BLOCKED_HOTLINKED_SRC_ATTR] || node["href"]
+ download_src =
+ "#{SiteSetting.force_https ? "https" : "http"}:#{original_src}" if original_src.start_with?(
+ "//",
+ )
normalized_src = normalize_src(download_src)
next if !should_download_image?(download_src, post)
@@ -32,10 +35,8 @@ module Jobs
hotlink_record = hotlinked_map[normalized_src]
if hotlink_record.nil?
- hotlinked_map[normalized_src] = hotlink_record = PostHotlinkedMedia.new(
- post: post,
- url: normalized_src
- )
+ hotlinked_map[normalized_src] = hotlink_record =
+ PostHotlinkedMedia.new(post: post, url: normalized_src)
begin
hotlink_record.upload = attempt_download(download_src, post.user_id)
hotlink_record.status = :downloaded
@@ -54,13 +55,17 @@ module Jobs
end
rescue => e
raise e if Rails.env.test?
- log(:error, "Failed to pull hotlinked image (#{download_src}) post: #{@post_id}\n" + e.message + "\n" + e.backtrace.join("\n"))
+ log(
+ :error,
+ "Failed to pull hotlinked image (#{download_src}) post: #{@post_id}\n" + e.message +
+ "\n" + e.backtrace.join("\n"),
+ )
end
if changed_hotlink_records
post.trigger_post_process(
bypass_bump: true,
- skip_pull_hotlinked_images: true # Avoid an infinite loop of job scheduling
+ skip_pull_hotlinked_images: true, # Avoid an infinite loop of job scheduling
)
end
@@ -81,14 +86,15 @@ module Jobs
Rails.logger.warn("Verbose Upload Logging: Downloading hotlinked image from #{src}")
end
- downloaded = FileHelper.download(
- src,
- max_file_size: @max_size,
- retain_on_max_file_size_exceeded: true,
- tmp_file_name: "discourse-hotlinked",
- follow_redirect: true,
- read_timeout: 15
- )
+ downloaded =
+ FileHelper.download(
+ src,
+ max_file_size: @max_size,
+ retain_on_max_file_size_exceeded: true,
+ tmp_file_name: "discourse-hotlinked",
+ follow_redirect: true,
+ read_timeout: 15,
+ )
rescue => e
if SiteSetting.verbose_upload_logging
Rails.logger.warn("Verbose Upload Logging: Error '#{e.message}' while downloading #{src}")
@@ -103,9 +109,12 @@ module Jobs
downloaded
end
- class ImageTooLargeError < StandardError; end
- class ImageBrokenError < StandardError; end
- class UploadCreateError < StandardError; end
+ class ImageTooLargeError < StandardError
+ end
+ class ImageBrokenError < StandardError
+ end
+ class UploadCreateError < StandardError
+ end
def attempt_download(src, user_id)
# secure-uploads endpoint prevents anonymous downloads, so we
@@ -123,31 +132,32 @@ module Jobs
if upload.persisted?
upload
else
- log(:info, "Failed to persist downloaded hotlinked image for post: #{@post_id}: #{src} - #{upload.errors.full_messages.join("\n")}")
+ log(
+ :info,
+ "Failed to persist downloaded hotlinked image for post: #{@post_id}: #{src} - #{upload.errors.full_messages.join("\n")}",
+ )
raise UploadCreateError
end
end
def extract_images_from(html)
- doc = Nokogiri::HTML5::fragment(html)
+ doc = Nokogiri::HTML5.fragment(html)
doc.css("img[src], [#{PrettyText::BLOCKED_HOTLINKED_SRC_ATTR}], a.lightbox[href]") -
- doc.css("img.avatar") -
- doc.css(".lightbox img[src]")
+ doc.css("img.avatar") - doc.css(".lightbox img[src]")
end
def should_download_image?(src, post = nil)
# make sure we actually have a url
return false unless src.present?
- local_bases = [
- Discourse.base_url,
- Discourse.asset_host,
- SiteSetting.external_emoji_url.presence
- ].compact.map { |s| normalize_src(s) }
+ local_bases =
+ [Discourse.base_url, Discourse.asset_host, SiteSetting.external_emoji_url.presence].compact
+ .map { |s| normalize_src(s) }
- if Discourse.store.has_been_uploaded?(src) || normalize_src(src).start_with?(*local_bases) || src =~ /\A\/[^\/]/i
- return false if !(src =~ /\/uploads\// || Upload.secure_uploads_url?(src))
+ if Discourse.store.has_been_uploaded?(src) || normalize_src(src).start_with?(*local_bases) ||
+ src =~ %r{\A/[^/]}i
+ return false if !(src =~ %r{/uploads/} || Upload.secure_uploads_url?(src))
# Someone could hotlink a file from a different site on the same CDN,
# so check whether we have it in this database
@@ -182,7 +192,7 @@ module Jobs
def log(log_level, message)
Rails.logger.public_send(
log_level,
- "#{RailsMultisite::ConnectionManagement.current_db}: #{message}"
+ "#{RailsMultisite::ConnectionManagement.current_db}: #{message}",
)
end
@@ -202,19 +212,26 @@ module Jobs
# log the site setting change
reason = I18n.t("disable_remote_images_download_reason")
staff_action_logger = StaffActionLogger.new(Discourse.system_user)
- staff_action_logger.log_site_setting_change("download_remote_images_to_local", true, false, details: reason)
+ staff_action_logger.log_site_setting_change(
+ "download_remote_images_to_local",
+ true,
+ false,
+ details: reason,
+ )
# also send a private message to the site contact user notify_about_low_disk_space
notify_about_low_disk_space
end
def notify_about_low_disk_space
- SystemMessage.create_from_system_user(Discourse.site_contact_user, :download_remote_images_disabled)
+ SystemMessage.create_from_system_user(
+ Discourse.site_contact_user,
+ :download_remote_images_disabled,
+ )
end
def available_disk_space
100 - DiskSpace.percent_free("#{Rails.root}/public/uploads")
end
end
-
end
diff --git a/app/jobs/regular/pull_user_profile_hotlinked_images.rb b/app/jobs/regular/pull_user_profile_hotlinked_images.rb
index 22c7b21e9dc..89d0f910862 100644
--- a/app/jobs/regular/pull_user_profile_hotlinked_images.rb
+++ b/app/jobs/regular/pull_user_profile_hotlinked_images.rb
@@ -14,14 +14,20 @@ module Jobs
downloaded_images = {}
extract_images_from(user_profile.bio_cooked).each do |node|
- download_src = original_src = node['src'] || node['href']
- download_src = "#{SiteSetting.force_https ? "https" : "http"}:#{original_src}" if original_src.start_with?("//")
+ download_src = original_src = node["src"] || node["href"]
+ download_src =
+ "#{SiteSetting.force_https ? "https" : "http"}:#{original_src}" if original_src.start_with?(
+ "//",
+ )
normalized_src = normalize_src(download_src)
next if !should_download_image?(download_src)
begin
- already_attempted_download = downloaded_images.include?(normalized_src) || large_image_urls.include?(normalized_src) || broken_image_urls.include?(normalized_src)
+ already_attempted_download =
+ downloaded_images.include?(normalized_src) ||
+ large_image_urls.include?(normalized_src) ||
+ broken_image_urls.include?(normalized_src)
if !already_attempted_download
downloaded_images[normalized_src] = attempt_download(download_src, @user_id)
end
@@ -32,13 +38,18 @@ module Jobs
end
rescue => e
raise e if Rails.env.test?
- log(:error, "Failed to pull hotlinked image (#{download_src}) user: #{@user_id}\n" + e.message + "\n" + e.backtrace.join("\n"))
+ log(
+ :error,
+ "Failed to pull hotlinked image (#{download_src}) user: #{@user_id}\n" + e.message +
+ "\n" + e.backtrace.join("\n"),
+ )
end
- user_profile.bio_raw = InlineUploads.replace_hotlinked_image_urls(raw: user_profile.bio_raw) do |match_src|
- normalized_match_src = PostHotlinkedMedia.normalize_src(match_src)
- downloaded_images[normalized_match_src]
- end
+ user_profile.bio_raw =
+ InlineUploads.replace_hotlinked_image_urls(raw: user_profile.bio_raw) do |match_src|
+ normalized_match_src = PostHotlinkedMedia.normalize_src(match_src)
+ downloaded_images[normalized_match_src]
+ end
user_profile.skip_pull_hotlinked_image = true
user_profile.save!
diff --git a/app/jobs/regular/push_notification.rb b/app/jobs/regular/push_notification.rb
index 16026323e74..1459bebc2b8 100644
--- a/app/jobs/regular/push_notification.rb
+++ b/app/jobs/regular/push_notification.rb
@@ -4,7 +4,9 @@ module Jobs
class PushNotification < ::Jobs::Base
def execute(args)
notification = args["payload"]
- notification["url"] = UrlHelper.absolute_without_cdn(Discourse.base_path + notification["post_url"])
+ notification["url"] = UrlHelper.absolute_without_cdn(
+ Discourse.base_path + notification["post_url"],
+ )
notification.delete("post_url")
payload = {
@@ -15,24 +17,30 @@ module Jobs
}
clients = args["clients"]
- clients.group_by { |r| r[1] }.each do |push_url, group|
- notifications = group.map do |client_id, _|
- notification.merge(client_id: client_id)
+ clients
+ .group_by { |r| r[1] }
+ .each do |push_url, group|
+ notifications = group.map { |client_id, _| notification.merge(client_id: client_id) }
+
+ next unless push_url.present?
+
+ result =
+ Excon.post(
+ push_url,
+ body: payload.merge(notifications: notifications).to_json,
+ headers: {
+ "Content-Type" => "application/json",
+ "Accept" => "application/json",
+ },
+ )
+
+ if result.status != 200
+ # we failed to push a notification ... log it
+ Rails.logger.warn(
+ "Failed to push a notification to #{push_url} Status: #{result.status}: #{result.status_line}",
+ )
+ end
end
-
- next unless push_url.present?
-
- result = Excon.post(push_url,
- body: payload.merge(notifications: notifications).to_json,
- headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }
- )
-
- if result.status != 200
- # we failed to push a notification ... log it
- Rails.logger.warn("Failed to push a notification to #{push_url} Status: #{result.status}: #{result.status_line}")
- end
- end
-
end
end
end
diff --git a/app/jobs/regular/refresh_users_reviewable_counts.rb b/app/jobs/regular/refresh_users_reviewable_counts.rb
index b16f72ef64c..10fa49467ff 100644
--- a/app/jobs/regular/refresh_users_reviewable_counts.rb
+++ b/app/jobs/regular/refresh_users_reviewable_counts.rb
@@ -4,8 +4,8 @@ class Jobs::RefreshUsersReviewableCounts < ::Jobs::Base
def execute(args)
group_ids = args[:group_ids]
return if group_ids.blank?
- User.where(
- id: GroupUser.where(group_id: group_ids).distinct.pluck(:user_id)
- ).each(&:publish_reviewable_counts)
+ User.where(id: GroupUser.where(group_id: group_ids).distinct.pluck(:user_id)).each(
+ &:publish_reviewable_counts
+ )
end
end
diff --git a/app/jobs/regular/remove_banner.rb b/app/jobs/regular/remove_banner.rb
index 880c8696c94..a8c1405a688 100644
--- a/app/jobs/regular/remove_banner.rb
+++ b/app/jobs/regular/remove_banner.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module Jobs
-
class RemoveBanner < ::Jobs::Base
-
def execute(args)
topic_id = args[:topic_id]
@@ -12,7 +10,5 @@ module Jobs
topic = Topic.find_by(id: topic_id)
topic.remove_banner!(Discourse.system_user) if topic.present?
end
-
end
-
end
diff --git a/app/jobs/regular/retrieve_topic.rb b/app/jobs/regular/retrieve_topic.rb
index ac3f0aacad7..5cdcd3496b0 100644
--- a/app/jobs/regular/retrieve_topic.rb
+++ b/app/jobs/regular/retrieve_topic.rb
@@ -1,20 +1,18 @@
# frozen_string_literal: true
module Jobs
-
# Asynchronously retrieve a topic from an embedded site
class RetrieveTopic < ::Jobs::Base
-
def execute(args)
raise Discourse::InvalidParameters.new(:embed_url) unless args[:embed_url].present?
user = nil
- if args[:user_id]
- user = User.find_by(id: args[:user_id])
- end
- TopicRetriever.new(args[:embed_url], author_username: args[:author_username], no_throttle: user.try(:staff?)).retrieve
+ user = User.find_by(id: args[:user_id]) if args[:user_id]
+ TopicRetriever.new(
+ args[:embed_url],
+ author_username: args[:author_username],
+ no_throttle: user.try(:staff?),
+ ).retrieve
end
-
end
-
end
diff --git a/app/jobs/regular/run_heartbeat.rb b/app/jobs/regular/run_heartbeat.rb
index 4a0691171ad..549c57ac965 100644
--- a/app/jobs/regular/run_heartbeat.rb
+++ b/app/jobs/regular/run_heartbeat.rb
@@ -2,11 +2,10 @@
module Jobs
class RunHeartbeat < ::Jobs::Base
-
- sidekiq_options queue: 'critical'
+ sidekiq_options queue: "critical"
def self.heartbeat_key
- 'heartbeat_last_run'
+ "heartbeat_last_run"
end
def execute(args)
diff --git a/app/jobs/regular/send_push_notification.rb b/app/jobs/regular/send_push_notification.rb
index 057e32dafb0..d73013fb8b9 100644
--- a/app/jobs/regular/send_push_notification.rb
+++ b/app/jobs/regular/send_push_notification.rb
@@ -4,7 +4,9 @@ module Jobs
class SendPushNotification < ::Jobs::Base
def execute(args)
user = User.find_by(id: args[:user_id])
- return if !user || user.seen_since?(SiteSetting.push_notification_time_window_mins.minutes.ago)
+ if !user || user.seen_since?(SiteSetting.push_notification_time_window_mins.minutes.ago)
+ return
+ end
PushNotificationPusher.push(user, args[:payload])
end
diff --git a/app/jobs/regular/send_system_message.rb b/app/jobs/regular/send_system_message.rb
index 23ebe656b20..2ee6559dca6 100644
--- a/app/jobs/regular/send_system_message.rb
+++ b/app/jobs/regular/send_system_message.rb
@@ -1,11 +1,9 @@
# frozen_string_literal: true
-require 'image_sizer'
+require "image_sizer"
module Jobs
-
class SendSystemMessage < ::Jobs::Base
-
def execute(args)
raise Discourse::InvalidParameters.new(:user_id) unless args[:user_id].present?
raise Discourse::InvalidParameters.new(:message_type) unless args[:message_type].present?
@@ -16,7 +14,5 @@ module Jobs
system_message = SystemMessage.new(user)
system_message.create(args[:message_type], args[:message_options]&.symbolize_keys || {})
end
-
end
-
end
diff --git a/app/jobs/regular/suspicious_login.rb b/app/jobs/regular/suspicious_login.rb
index a45b820de01..0301a8cc3ec 100644
--- a/app/jobs/regular/suspicious_login.rb
+++ b/app/jobs/regular/suspicious_login.rb
@@ -1,25 +1,24 @@
# frozen_string_literal: true
module Jobs
-
class SuspiciousLogin < ::Jobs::Base
-
def execute(args)
if UserAuthToken.is_suspicious(args[:user_id], args[:client_ip])
+ UserAuthToken.log(
+ action: "suspicious",
+ user_id: args[:user_id],
+ user_agent: args[:user_agent],
+ client_ip: args[:client_ip],
+ )
- UserAuthToken.log(action: 'suspicious',
- user_id: args[:user_id],
- user_agent: args[:user_agent],
- client_ip: args[:client_ip])
-
- ::Jobs.enqueue(:critical_user_email,
- type: "suspicious_login",
- user_id: args[:user_id],
- client_ip: args[:client_ip],
- user_agent: args[:user_agent])
+ ::Jobs.enqueue(
+ :critical_user_email,
+ type: "suspicious_login",
+ user_id: args[:user_id],
+ client_ip: args[:client_ip],
+ user_agent: args[:user_agent],
+ )
end
end
-
end
-
end
diff --git a/app/jobs/regular/sync_acls_for_uploads.rb b/app/jobs/regular/sync_acls_for_uploads.rb
index 237795cb5b6..435c9dbc5a8 100644
--- a/app/jobs/regular/sync_acls_for_uploads.rb
+++ b/app/jobs/regular/sync_acls_for_uploads.rb
@@ -14,26 +14,32 @@ module Jobs
# Note...these log messages are set to warn to ensure this is working
# as intended in initial production trials, this will be set to debug
# after an acl_stale column is added to uploads.
- time = Benchmark.measure do
- Rails.logger.warn("Syncing ACL for upload ids: #{args[:upload_ids].join(", ")}")
- Upload.includes(:optimized_images).where(id: args[:upload_ids]).find_in_batches do |uploads|
- uploads.each do |upload|
- begin
- Discourse.store.update_upload_ACL(upload, optimized_images_preloaded: true)
- rescue => err
- Discourse.warn_exception(
- err,
- message: "Failed to update upload ACL",
- env: {
- upload_id: upload.id,
- filename: upload.original_filename
- }
- )
+ time =
+ Benchmark.measure do
+ Rails.logger.warn("Syncing ACL for upload ids: #{args[:upload_ids].join(", ")}")
+ Upload
+ .includes(:optimized_images)
+ .where(id: args[:upload_ids])
+ .find_in_batches do |uploads|
+ uploads.each do |upload|
+ begin
+ Discourse.store.update_upload_ACL(upload, optimized_images_preloaded: true)
+ rescue => err
+ Discourse.warn_exception(
+ err,
+ message: "Failed to update upload ACL",
+ env: {
+ upload_id: upload.id,
+ filename: upload.original_filename,
+ },
+ )
+ end
+ end
end
- end
+ Rails.logger.warn(
+ "Completed syncing ACL for upload ids in #{time.to_s}. IDs: #{args[:upload_ids].join(", ")}",
+ )
end
- Rails.logger.warn("Completed syncing ACL for upload ids in #{time.to_s}. IDs: #{args[:upload_ids].join(", ")}")
- end
end
end
end
diff --git a/app/jobs/regular/toggle_topic_closed.rb b/app/jobs/regular/toggle_topic_closed.rb
index 55f7bce88dd..a02831ca61c 100644
--- a/app/jobs/regular/toggle_topic_closed.rb
+++ b/app/jobs/regular/toggle_topic_closed.rb
@@ -12,9 +12,7 @@ module Jobs
state = !!args[:state]
timer_type = args[:silent] ? :silent_close : :close
- if topic_timer.blank? || topic_timer.execute_at > Time.zone.now
- return
- end
+ return if topic_timer.blank? || topic_timer.execute_at > Time.zone.now
if (topic = topic_timer.topic).blank? || topic.closed == state
topic_timer.destroy!
@@ -28,10 +26,10 @@ module Jobs
topic.set_or_create_timer(
TopicTimer.types[:open],
SiteSetting.num_hours_to_close_topic,
- by_user: Discourse.system_user
+ by_user: Discourse.system_user,
)
else
- topic.update_status('autoclosed', state, user, { silent: args[:silent] })
+ topic.update_status("autoclosed", state, user, { silent: args[:silent] })
end
topic.inherit_auto_close_from_category(timer_type: timer_type) if state == false
diff --git a/app/jobs/regular/topic_action_converter.rb b/app/jobs/regular/topic_action_converter.rb
index 370e8cbb029..1d64ff378db 100644
--- a/app/jobs/regular/topic_action_converter.rb
+++ b/app/jobs/regular/topic_action_converter.rb
@@ -1,20 +1,29 @@
# frozen_string_literal: true
class Jobs::TopicActionConverter < ::Jobs::Base
-
# Re-creating all the user actions could be very slow, so let's do it in a job
# to avoid a N+1 query on a front facing operation.
def execute(args)
topic = Topic.find_by(id: args[:topic_id])
return if topic.blank?
- UserAction.where(
- target_topic_id: topic.id,
- action_type: [UserAction::GOT_PRIVATE_MESSAGE, UserAction::NEW_PRIVATE_MESSAGE]).find_each do |ua|
- UserAction.remove_action!(ua.attributes.symbolize_keys.slice(:action_type, :user_id, :acting_user_id, :target_topic_id, :target_post_id))
+ UserAction
+ .where(
+ target_topic_id: topic.id,
+ action_type: [UserAction::GOT_PRIVATE_MESSAGE, UserAction::NEW_PRIVATE_MESSAGE],
+ )
+ .find_each do |ua|
+ UserAction.remove_action!(
+ ua.attributes.symbolize_keys.slice(
+ :action_type,
+ :user_id,
+ :acting_user_id,
+ :target_topic_id,
+ :target_post_id,
+ ),
+ )
end
topic.posts.find_each { |post| UserActionManager.post_created(post) }
UserActionManager.topic_created(topic)
end
-
end
diff --git a/app/jobs/regular/truncate_user_flag_stats.rb b/app/jobs/regular/truncate_user_flag_stats.rb
index d75f7bb5aa8..95a00ede7d7 100644
--- a/app/jobs/regular/truncate_user_flag_stats.rb
+++ b/app/jobs/regular/truncate_user_flag_stats.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Jobs::TruncateUserFlagStats < ::Jobs::Base
-
def self.truncate_to
100
end
@@ -17,8 +16,11 @@ class Jobs::TruncateUserFlagStats < ::Jobs::Base
total = user_stat.flags_agreed + user_stat.flags_disagreed + user_stat.flags_ignored
next if total < self.class.truncate_to
- params = ReviewableScore.statuses.slice(:agreed, :disagreed, :ignored).
- merge(user_id: u, truncate_to: self.class.truncate_to)
+ params =
+ ReviewableScore
+ .statuses
+ .slice(:agreed, :disagreed, :ignored)
+ .merge(user_id: u, truncate_to: self.class.truncate_to)
result = DB.query(<<~SQL, params)
SELECT SUM(CASE WHEN x.status = :agreed THEN 1 ELSE 0 END) AS agreed,
@@ -44,7 +46,5 @@ class Jobs::TruncateUserFlagStats < ::Jobs::Base
flags_ignored: result[0].ignored || 0,
)
end
-
end
-
end
diff --git a/app/jobs/regular/unpin_topic.rb b/app/jobs/regular/unpin_topic.rb
index 9d4f6b93eed..8e804b1a94d 100644
--- a/app/jobs/regular/unpin_topic.rb
+++ b/app/jobs/regular/unpin_topic.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module Jobs
-
class UnpinTopic < ::Jobs::Base
-
def execute(args)
topic_id = args[:topic_id]
@@ -12,7 +10,5 @@ module Jobs
topic = Topic.find_by(id: topic_id)
topic.update_pinned(false) if topic.present?
end
-
end
-
end
diff --git a/app/jobs/regular/update_gravatar.rb b/app/jobs/regular/update_gravatar.rb
index de954b41eea..6133a92c0ed 100644
--- a/app/jobs/regular/update_gravatar.rb
+++ b/app/jobs/regular/update_gravatar.rb
@@ -2,8 +2,7 @@
module Jobs
class UpdateGravatar < ::Jobs::Base
-
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
def execute(args)
user = User.find_by(id: args[:user_id])
@@ -17,5 +16,4 @@ module Jobs
end
end
end
-
end
diff --git a/app/jobs/regular/update_group_mentions.rb b/app/jobs/regular/update_group_mentions.rb
index 4df6b9145f3..50147a3c0ca 100644
--- a/app/jobs/regular/update_group_mentions.rb
+++ b/app/jobs/regular/update_group_mentions.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module Jobs
-
class UpdateGroupMentions < ::Jobs::Base
-
def execute(args)
group = Group.find_by(id: args[:group_id])
return unless group
diff --git a/app/jobs/regular/update_hotlinked_raw.rb b/app/jobs/regular/update_hotlinked_raw.rb
index 1fb425839bf..e2e99cc7f85 100644
--- a/app/jobs/regular/update_hotlinked_raw.rb
+++ b/app/jobs/regular/update_hotlinked_raw.rb
@@ -2,7 +2,7 @@
module Jobs
class UpdateHotlinkedRaw < ::Jobs::Base
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
def execute(args)
@post_id = args[:post_id]
@@ -15,10 +15,11 @@ module Jobs
hotlinked_map = post.post_hotlinked_media.preload(:upload).map { |r| [r.url, r] }.to_h
- raw = InlineUploads.replace_hotlinked_image_urls(raw: post.raw) do |match_src|
- normalized_match_src = PostHotlinkedMedia.normalize_src(match_src)
- hotlinked_map[normalized_match_src]&.upload
- end
+ raw =
+ InlineUploads.replace_hotlinked_image_urls(raw: post.raw) do |match_src|
+ normalized_match_src = PostHotlinkedMedia.normalize_src(match_src)
+ hotlinked_map[normalized_match_src]&.upload
+ end
if post.raw != raw
changes = { raw: raw, edit_reason: I18n.t("upload.edit_reason") }
diff --git a/app/jobs/regular/update_post_uploads_secure_status.rb b/app/jobs/regular/update_post_uploads_secure_status.rb
index b27b4c92b48..a7faa53c4a3 100644
--- a/app/jobs/regular/update_post_uploads_secure_status.rb
+++ b/app/jobs/regular/update_post_uploads_secure_status.rb
@@ -6,9 +6,7 @@ module Jobs
post = Post.find_by(id: args[:post_id])
return if post.blank?
- post.uploads.each do |upload|
- upload.update_secure_status(source: args[:source])
- end
+ post.uploads.each { |upload| upload.update_secure_status(source: args[:source]) }
end
end
end
diff --git a/app/jobs/regular/update_s3_inventory.rb b/app/jobs/regular/update_s3_inventory.rb
index 46c34a59bf4..699db498860 100644
--- a/app/jobs/regular/update_s3_inventory.rb
+++ b/app/jobs/regular/update_s3_inventory.rb
@@ -5,13 +5,13 @@ require "s3_inventory"
module Jobs
# if upload bucket changes or inventory bucket changes we want to update s3 bucket policy and inventory configuration
class UpdateS3Inventory < ::Jobs::Base
-
def execute(args)
- return unless SiteSetting.enable_s3_inventory? &&
- SiteSetting.Upload.enable_s3_uploads &&
- SiteSetting.s3_configure_inventory_policy
+ unless SiteSetting.enable_s3_inventory? && SiteSetting.Upload.enable_s3_uploads &&
+ SiteSetting.s3_configure_inventory_policy
+ return
+ end
- [:upload, :optimized].each do |type|
+ %i[upload optimized].each do |type|
s3_inventory = S3Inventory.new(Discourse.store.s3_helper, type)
s3_inventory.update_bucket_policy if type == :upload
s3_inventory.update_bucket_inventory_configuration
diff --git a/app/jobs/regular/update_top_redirection.rb b/app/jobs/regular/update_top_redirection.rb
index 80ad6acefb5..dae128799be 100644
--- a/app/jobs/regular/update_top_redirection.rb
+++ b/app/jobs/regular/update_top_redirection.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module Jobs
-
class UpdateTopRedirection < ::Jobs::Base
-
def execute(args)
return if args[:user_id].blank? || args[:redirected_at].blank?
@@ -13,5 +11,4 @@ module Jobs
.update_all(last_redirected_to_top_at: args[:redirected_at])
end
end
-
end
diff --git a/app/jobs/regular/update_topic_upload_security.rb b/app/jobs/regular/update_topic_upload_security.rb
index 2ac3deb2bd7..dd2eceffe56 100644
--- a/app/jobs/regular/update_topic_upload_security.rb
+++ b/app/jobs/regular/update_topic_upload_security.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
module Jobs
-
class UpdateTopicUploadSecurity < ::Jobs::Base
-
def execute(args)
topic = Topic.find_by(id: args[:topic_id])
if topic.blank?
- Rails.logger.info("Could not find topic #{args[:topic_id]} for topic upload security updater.")
+ Rails.logger.info(
+ "Could not find topic #{args[:topic_id]} for topic upload security updater.",
+ )
return
end
TopicUploadSecurityManager.new(topic).run
diff --git a/app/jobs/regular/update_username.rb b/app/jobs/regular/update_username.rb
index f9660c2358c..3a0ed3194ef 100644
--- a/app/jobs/regular/update_username.rb
+++ b/app/jobs/regular/update_username.rb
@@ -2,8 +2,7 @@
module Jobs
class UpdateUsername < ::Jobs::Base
-
- sidekiq_options queue: 'low'
+ sidekiq_options queue: "low"
def execute(args)
@user_id = args[:user_id]
@@ -14,7 +13,8 @@ module Jobs
@new_username = args[:new_username].unicode_normalize
@avatar_img = PrettyText.avatar_img(args[:avatar_template], "tiny")
- @raw_mention_regex = /
+ @raw_mention_regex =
+ /
(?:
(?
- (user.user_option&.digest_after_minutes || SiteSetting.default_email_digest_frequency.to_i).minutes.ago
+ if user.last_emailed_at &&
+ user.last_emailed_at >
+ (
+ user.user_option&.digest_after_minutes ||
+ SiteSetting.default_email_digest_frequency.to_i
+ ).minutes.ago
+ return
+ end
end
- seen_recently = (user.last_seen_at.present? && user.last_seen_at > SiteSetting.email_time_window_mins.minutes.ago)
+ seen_recently =
+ (
+ user.last_seen_at.present? &&
+ user.last_seen_at > SiteSetting.email_time_window_mins.minutes.ago
+ )
if !args[:force_respect_seen_recently] &&
- (always_email_regular?(user, type) || always_email_private_message?(user, type) || user.staged)
+ (
+ always_email_regular?(user, type) || always_email_private_message?(user, type) ||
+ user.staged
+ )
seen_recently = false
end
email_args = {}
if (post || notification || notification_type || args[:force_respect_seen_recently]) &&
- (seen_recently && !user.suspended?)
-
+ (seen_recently && !user.suspended?)
return skip_message(SkippedEmailLog.reason_types[:user_email_seen_recently])
end
email_args[:post] = post if post
if notification || notification_type
- email_args[:notification_type] ||= notification_type || notification.try(:notification_type)
- email_args[:notification_data_hash] ||= notification_data_hash || notification.try(:data_hash)
+ email_args[:notification_type] ||= notification_type || notification.try(:notification_type)
+ email_args[:notification_data_hash] ||= notification_data_hash ||
+ notification.try(:data_hash)
unless String === email_args[:notification_type]
if Numeric === email_args[:notification_type]
@@ -157,13 +158,12 @@ module Jobs
email_args[:notification_type] = email_args[:notification_type].to_s
end
- if !SiteSetting.disable_mailing_list_mode &&
- user.user_option.mailing_list_mode? &&
- user.user_option.mailing_list_mode_frequency > 0 && # don't catch notifications for users on daily mailing list mode
- (!post.try(:topic).try(:private_message?)) &&
- NOTIFICATIONS_SENT_BY_MAILING_LIST.include?(email_args[:notification_type])
+ if !SiteSetting.disable_mailing_list_mode && user.user_option.mailing_list_mode? &&
+ user.user_option.mailing_list_mode_frequency > 0 && # don't catch notifications for users on daily mailing list mode
+ (!post.try(:topic).try(:private_message?)) &&
+ NOTIFICATIONS_SENT_BY_MAILING_LIST.include?(email_args[:notification_type])
# no need to log a reason when the mail was already sent via the mailing list job
- return [nil, nil]
+ return nil, nil
end
unless always_email_regular?(user, type) || always_email_private_message?(user, type)
@@ -177,7 +177,9 @@ module Jobs
return skip_message(skip_reason_type) if skip_reason_type.present?
# Make sure that mailer exists
- raise Discourse::InvalidParameters.new("type=#{type}") unless UserNotifications.respond_to?(type)
+ unless UserNotifications.respond_to?(type)
+ raise Discourse::InvalidParameters.new("type=#{type}")
+ end
if email_token.present?
email_args[:email_token] = email_token
@@ -185,13 +187,12 @@ module Jobs
if type.to_s == "confirm_new_email"
change_req = EmailChangeRequest.find_by_new_token(email_token)
- if change_req
- email_args[:requested_by_admin] = change_req.requested_by_admin?
- end
+ email_args[:requested_by_admin] = change_req.requested_by_admin? if change_req
end
end
- email_args[:new_email] = args[:new_email] || user.email if type.to_s == "notify_old_email" || type.to_s == "notify_old_email_add"
+ email_args[:new_email] = args[:new_email] || user.email if type.to_s == "notify_old_email" ||
+ type.to_s == "notify_old_email_add"
if args[:client_ip] && args[:user_agent]
email_args[:client_ip] = args[:client_ip]
@@ -202,7 +203,8 @@ module Jobs
return skip_message(SkippedEmailLog.reason_types[:exceeded_emails_limit])
end
- if !EmailLog::CRITICAL_EMAIL_TYPES.include?(type.to_s) && user.user_stat.bounce_score >= SiteSetting.bounce_score_threshold
+ if !EmailLog::CRITICAL_EMAIL_TYPES.include?(type.to_s) &&
+ user.user_stat.bounce_score >= SiteSetting.bounce_score_threshold
return skip_message(SkippedEmailLog.reason_types[:exceeded_bounces_limit])
end
@@ -212,9 +214,10 @@ module Jobs
email_args[:reject_reason] = args[:reject_reason]
- message = EmailLog.unique_email_per_post(post, user) do
- UserNotifications.public_send(type, user, email_args)
- end
+ message =
+ EmailLog.unique_email_per_post(post, user) do
+ UserNotifications.public_send(type, user, email_args)
+ end
# Update the to address if we have a custom one
message.to = to_address if message && to_address.present?
@@ -232,26 +235,24 @@ module Jobs
def skip_email_for_post(post, user)
return false unless post
- if post.topic.blank?
- return SkippedEmailLog.reason_types[:user_email_topic_nil]
- end
+ return SkippedEmailLog.reason_types[:user_email_topic_nil] if post.topic.blank?
- if post.user.blank?
- return SkippedEmailLog.reason_types[:user_email_post_user_deleted]
- end
+ return SkippedEmailLog.reason_types[:user_email_post_user_deleted] if post.user.blank?
- if post.user_deleted?
- return SkippedEmailLog.reason_types[:user_email_post_deleted]
- end
+ return SkippedEmailLog.reason_types[:user_email_post_deleted] if post.user_deleted?
if user.suspended? && (!post.user&.staff? || !post.user&.human?)
return SkippedEmailLog.reason_types[:user_email_user_suspended]
end
- already_read = user.user_option.email_level != UserOption.email_level_types[:always] && PostTiming.exists?(topic_id: post.topic_id, post_number: post.post_number, user_id: user.id)
- if already_read
- SkippedEmailLog.reason_types[:user_email_already_read]
- end
+ already_read =
+ user.user_option.email_level != UserOption.email_level_types[:always] &&
+ PostTiming.exists?(
+ topic_id: post.topic_id,
+ post_number: post.post_number,
+ user_id: user.id,
+ )
+ SkippedEmailLog.reason_types[:user_email_already_read] if already_read
end
def skip(reason_type)
@@ -260,17 +261,18 @@ module Jobs
to_address: @skip_context[:to_address],
user_id: @skip_context[:user_id],
post_id: @skip_context[:post_id],
- reason_type: reason_type
+ reason_type: reason_type,
)
end
def always_email_private_message?(user, type)
- type.to_s == "user_private_message" && user.user_option.email_messages_level == UserOption.email_level_types[:always]
+ type.to_s == "user_private_message" &&
+ user.user_option.email_messages_level == UserOption.email_level_types[:always]
end
def always_email_regular?(user, type)
- type.to_s != "user_private_message" && user.user_option.email_level == UserOption.email_level_types[:always]
+ type.to_s != "user_private_message" &&
+ user.user_option.email_level == UserOption.email_level_types[:always]
end
end
-
end
diff --git a/app/jobs/scheduled/activation_reminder_emails.rb b/app/jobs/scheduled/activation_reminder_emails.rb
index 5bfbf9e9f3a..f3f4470ad90 100644
--- a/app/jobs/scheduled/activation_reminder_emails.rb
+++ b/app/jobs/scheduled/activation_reminder_emails.rb
@@ -5,22 +5,25 @@ module Jobs
every 2.hours
def execute(args)
- User.joins("LEFT JOIN user_custom_fields ON users.id = user_id AND user_custom_fields.name = 'activation_reminder'")
- .where(active: false, staged: false, user_custom_fields: { value: nil })
- .where('users.created_at BETWEEN ? AND ?', 3.days.ago, 2.days.ago)
- .find_each do |user|
-
- user.custom_fields['activation_reminder'] = true
- user.save_custom_fields
-
- email_token = user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:signup])
- ::Jobs.enqueue(
- :user_email,
- type: "activation_reminder",
- user_id: user.id,
- email_token: email_token.token
+ User
+ .joins(
+ "LEFT JOIN user_custom_fields ON users.id = user_id AND user_custom_fields.name = 'activation_reminder'",
)
- end
+ .where(active: false, staged: false, user_custom_fields: { value: nil })
+ .where("users.created_at BETWEEN ? AND ?", 3.days.ago, 2.days.ago)
+ .find_each do |user|
+ user.custom_fields["activation_reminder"] = true
+ user.save_custom_fields
+
+ email_token =
+ user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:signup])
+ ::Jobs.enqueue(
+ :user_email,
+ type: "activation_reminder",
+ user_id: user.id,
+ email_token: email_token.token,
+ )
+ end
end
end
end
diff --git a/app/jobs/scheduled/auto_expire_user_api_keys.rb b/app/jobs/scheduled/auto_expire_user_api_keys.rb
index 4a4e041f7ce..60bd24418d2 100644
--- a/app/jobs/scheduled/auto_expire_user_api_keys.rb
+++ b/app/jobs/scheduled/auto_expire_user_api_keys.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class AutoExpireUserApiKeys < ::Jobs::Scheduled
every 1.day
@@ -9,9 +8,10 @@ module Jobs
if SiteSetting.expire_user_api_keys_days > 0
expire_user_api_keys_days = SiteSetting.expire_user_api_keys_days.days.ago
- UserApiKey.where("last_used_at < ?", expire_user_api_keys_days).update_all(revoked_at: Time.zone.now)
+ UserApiKey.where("last_used_at < ?", expire_user_api_keys_days).update_all(
+ revoked_at: Time.zone.now,
+ )
end
end
end
-
end
diff --git a/app/jobs/scheduled/auto_queue_handler.rb b/app/jobs/scheduled/auto_queue_handler.rb
index 6bf75924c96..66150fb8c97 100644
--- a/app/jobs/scheduled/auto_queue_handler.rb
+++ b/app/jobs/scheduled/auto_queue_handler.rb
@@ -4,7 +4,6 @@
# queue for a long time.
module Jobs
class AutoQueueHandler < ::Jobs::Scheduled
-
every 1.day
def execute(args)
@@ -12,17 +11,16 @@ module Jobs
Reviewable
.pending
- .where('created_at < ?', SiteSetting.auto_handle_queued_age.to_i.days.ago)
+ .where("created_at < ?", SiteSetting.auto_handle_queued_age.to_i.days.ago)
.each do |reviewable|
-
- if reviewable.is_a?(ReviewableFlaggedPost)
- reviewable.perform(Discourse.system_user, :ignore, expired: true)
- elsif reviewable.is_a?(ReviewableQueuedPost)
- reviewable.perform(Discourse.system_user, :reject_post)
- elsif reviewable.is_a?(ReviewableUser)
- reviewable.perform(Discourse.system_user, :delete_user)
+ if reviewable.is_a?(ReviewableFlaggedPost)
+ reviewable.perform(Discourse.system_user, :ignore, expired: true)
+ elsif reviewable.is_a?(ReviewableQueuedPost)
+ reviewable.perform(Discourse.system_user, :reject_post)
+ elsif reviewable.is_a?(ReviewableUser)
+ reviewable.perform(Discourse.system_user, :delete_user)
+ end
end
- end
end
end
end
diff --git a/app/jobs/scheduled/badge_grant.rb b/app/jobs/scheduled/badge_grant.rb
index e9ad67a9b1d..b9bc1ad4e82 100644
--- a/app/jobs/scheduled/badge_grant.rb
+++ b/app/jobs/scheduled/badge_grant.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class BadgeGrant < ::Jobs::Scheduled
def self.run
self.new.execute(nil)
@@ -17,7 +16,10 @@ module Jobs
BadgeGranter.backfill(b)
rescue => ex
# TODO - expose errors in UI
- Discourse.handle_job_exception(ex, error_context({}, code_desc: 'Exception granting badges', extra: { badge_id: b.id }))
+ Discourse.handle_job_exception(
+ ex,
+ error_context({}, code_desc: "Exception granting badges", extra: { badge_id: b.id }),
+ )
end
end
@@ -25,7 +27,5 @@ module Jobs
UserBadge.ensure_consistency! # Badge granter sometimes uses raw SQL, so hooks do not run. Clean up data
UserStat.update_distinct_badge_count
end
-
end
-
end
diff --git a/app/jobs/scheduled/bookmark_reminder_notifications.rb b/app/jobs/scheduled/bookmark_reminder_notifications.rb
index 712a650fc02..5443b247dad 100644
--- a/app/jobs/scheduled/bookmark_reminder_notifications.rb
+++ b/app/jobs/scheduled/bookmark_reminder_notifications.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
# Runs periodically to send out bookmark reminders, capped at 300 at a time.
# Any leftovers will be caught in the next run, because the reminder_at column
# is set to NULL once a reminder has been sent.
@@ -18,10 +17,10 @@ module Jobs
end
def execute(args = nil)
- bookmarks = Bookmark.pending_reminders.includes(:user).order('reminder_at ASC')
- bookmarks.limit(BookmarkReminderNotifications.max_reminder_notifications_per_run).each do |bookmark|
- BookmarkReminderNotificationHandler.new(bookmark).send_notification
- end
+ bookmarks = Bookmark.pending_reminders.includes(:user).order("reminder_at ASC")
+ bookmarks
+ .limit(BookmarkReminderNotifications.max_reminder_notifications_per_run)
+ .each { |bookmark| BookmarkReminderNotificationHandler.new(bookmark).send_notification }
end
end
end
diff --git a/app/jobs/scheduled/category_stats.rb b/app/jobs/scheduled/category_stats.rb
index b1de99224e2..81ff69031fd 100644
--- a/app/jobs/scheduled/category_stats.rb
+++ b/app/jobs/scheduled/category_stats.rb
@@ -1,14 +1,11 @@
# frozen_string_literal: true
module Jobs
-
class CategoryStats < ::Jobs::Scheduled
every 24.hours
def execute(args)
Category.update_stats
end
-
end
-
end
diff --git a/app/jobs/scheduled/check_new_features.rb b/app/jobs/scheduled/check_new_features.rb
index c3f98bf4885..b69410f3516 100644
--- a/app/jobs/scheduled/check_new_features.rb
+++ b/app/jobs/scheduled/check_new_features.rb
@@ -11,10 +11,7 @@ module Jobs
if prev_most_recent
admin_ids.each do |admin_id|
if DiscourseUpdates.get_last_viewed_feature_date(admin_id).blank?
- DiscourseUpdates.bump_last_viewed_feature_date(
- admin_id,
- prev_most_recent["created_at"]
- )
+ DiscourseUpdates.bump_last_viewed_feature_date(admin_id, prev_most_recent["created_at"])
end
end
end
@@ -32,16 +29,15 @@ module Jobs
most_recent_feature_date = Time.zone.parse(new_most_recent["created_at"])
admin_ids.each do |admin_id|
admin_last_viewed_feature_date = DiscourseUpdates.get_last_viewed_feature_date(admin_id)
- if admin_last_viewed_feature_date.blank? || admin_last_viewed_feature_date < most_recent_feature_date
+ if admin_last_viewed_feature_date.blank? ||
+ admin_last_viewed_feature_date < most_recent_feature_date
Notification.consolidate_or_create!(
user_id: admin_id,
notification_type: Notification.types[:new_features],
- data: {}
- )
- DiscourseUpdates.bump_last_viewed_feature_date(
- admin_id,
- new_most_recent["created_at"]
+ data: {
+ },
)
+ DiscourseUpdates.bump_last_viewed_feature_date(admin_id, new_most_recent["created_at"])
end
end
end
diff --git a/app/jobs/scheduled/check_out_of_date_themes.rb b/app/jobs/scheduled/check_out_of_date_themes.rb
index 1003e25a906..35592292c7b 100644
--- a/app/jobs/scheduled/check_out_of_date_themes.rb
+++ b/app/jobs/scheduled/check_out_of_date_themes.rb
@@ -5,9 +5,10 @@ module Jobs
every 1.day
def execute(args)
- target_themes = RemoteTheme
- .joins("JOIN themes ON themes.remote_theme_id = remote_themes.id")
- .where.not(remote_url: "")
+ target_themes =
+ RemoteTheme
+ .joins("JOIN themes ON themes.remote_theme_id = remote_themes.id")
+ .where.not(remote_url: "")
target_themes.each do |remote|
remote.update_remote_version
diff --git a/app/jobs/scheduled/clean_dismissed_topic_users.rb b/app/jobs/scheduled/clean_dismissed_topic_users.rb
index 72109ffbfcc..7b21fb54ea4 100644
--- a/app/jobs/scheduled/clean_dismissed_topic_users.rb
+++ b/app/jobs/scheduled/clean_dismissed_topic_users.rb
@@ -27,12 +27,15 @@ module Jobs
END, users.created_at, :min_date)
AND dtu1.id = dtu2.id
SQL
- sql = DB.sql_fragment(sql,
- now: DateTime.now,
- last_visit: User::NewTopicDuration::LAST_VISIT,
- always: User::NewTopicDuration::ALWAYS,
- default_duration: SiteSetting.default_other_new_topic_duration_minutes,
- min_date: Time.at(SiteSetting.min_new_topics_time).to_datetime)
+ sql =
+ DB.sql_fragment(
+ sql,
+ now: DateTime.now,
+ last_visit: User::NewTopicDuration::LAST_VISIT,
+ always: User::NewTopicDuration::ALWAYS,
+ default_duration: SiteSetting.default_other_new_topic_duration_minutes,
+ min_date: Time.at(SiteSetting.min_new_topics_time).to_datetime,
+ )
DB.exec(sql)
end
diff --git a/app/jobs/scheduled/clean_up_associated_accounts.rb b/app/jobs/scheduled/clean_up_associated_accounts.rb
index ac2ba4802b5..861b0bca1f0 100644
--- a/app/jobs/scheduled/clean_up_associated_accounts.rb
+++ b/app/jobs/scheduled/clean_up_associated_accounts.rb
@@ -1,14 +1,11 @@
# frozen_string_literal: true
module Jobs
-
class CleanUpAssociatedAccounts < ::Jobs::Scheduled
every 1.day
def execute(args)
UserAssociatedAccount.cleanup!
end
-
end
-
end
diff --git a/app/jobs/scheduled/clean_up_crawler_stats.rb b/app/jobs/scheduled/clean_up_crawler_stats.rb
index 09f704bd34d..e333082b174 100644
--- a/app/jobs/scheduled/clean_up_crawler_stats.rb
+++ b/app/jobs/scheduled/clean_up_crawler_stats.rb
@@ -1,12 +1,11 @@
# frozen_string_literal: true
module Jobs
-
class CleanUpCrawlerStats < ::Jobs::Scheduled
every 1.day
def execute(args)
- WebCrawlerRequest.where('date < ?', WebCrawlerRequest.max_record_age.ago).delete_all
+ WebCrawlerRequest.where("date < ?", WebCrawlerRequest.max_record_age.ago).delete_all
# keep count of only the top user agents
DB.exec <<~SQL
@@ -24,5 +23,4 @@ module Jobs
SQL
end
end
-
end
diff --git a/app/jobs/scheduled/clean_up_email_change_requests.rb b/app/jobs/scheduled/clean_up_email_change_requests.rb
index cd572b5e45c..d2e1926a991 100644
--- a/app/jobs/scheduled/clean_up_email_change_requests.rb
+++ b/app/jobs/scheduled/clean_up_email_change_requests.rb
@@ -5,7 +5,7 @@ module Jobs
every 1.day
def execute(args)
- EmailChangeRequest.where('updated_at < ?', 1.month.ago).delete_all
+ EmailChangeRequest.where("updated_at < ?", 1.month.ago).delete_all
end
end
end
diff --git a/app/jobs/scheduled/clean_up_email_logs.rb b/app/jobs/scheduled/clean_up_email_logs.rb
index 9799764e711..9ddc1f0125a 100644
--- a/app/jobs/scheduled/clean_up_email_logs.rb
+++ b/app/jobs/scheduled/clean_up_email_logs.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class CleanUpEmailLogs < ::Jobs::Scheduled
every 1.day
@@ -13,7 +12,5 @@ module Jobs
EmailLog.where("created_at < ?", threshold).delete_all
SkippedEmailLog.where("created_at < ?", threshold).delete_all
end
-
end
-
end
diff --git a/app/jobs/scheduled/clean_up_email_tokens.rb b/app/jobs/scheduled/clean_up_email_tokens.rb
index 0781115fd89..daff838eb8b 100644
--- a/app/jobs/scheduled/clean_up_email_tokens.rb
+++ b/app/jobs/scheduled/clean_up_email_tokens.rb
@@ -5,10 +5,7 @@ module Jobs
every 1.day
def execute(args)
- EmailToken
- .where('NOT confirmed AND expired')
- .where('created_at < ?', 1.month.ago)
- .delete_all
+ EmailToken.where("NOT confirmed AND expired").where("created_at < ?", 1.month.ago).delete_all
end
end
end
diff --git a/app/jobs/scheduled/clean_up_inactive_users.rb b/app/jobs/scheduled/clean_up_inactive_users.rb
index a54e1ee6579..b52ae8d5e21 100644
--- a/app/jobs/scheduled/clean_up_inactive_users.rb
+++ b/app/jobs/scheduled/clean_up_inactive_users.rb
@@ -1,30 +1,32 @@
# frozen_string_literal: true
module Jobs
-
class CleanUpInactiveUsers < ::Jobs::Scheduled
every 1.day
def execute(args)
return if SiteSetting.clean_up_inactive_users_after_days <= 0
- User.joins("LEFT JOIN posts ON posts.user_id = users.id")
- .where(last_posted_at: nil, trust_level: TrustLevel.levels[:newuser], admin: false, moderator: false)
+ User
+ .joins("LEFT JOIN posts ON posts.user_id = users.id")
+ .where(
+ last_posted_at: nil,
+ trust_level: TrustLevel.levels[:newuser],
+ admin: false,
+ moderator: false,
+ )
.where(
"posts.user_id IS NULL AND users.last_seen_at < ?",
- SiteSetting.clean_up_inactive_users_after_days.days.ago
- )
+ SiteSetting.clean_up_inactive_users_after_days.days.ago,
+ )
.limit(1000)
- .pluck(:id).each_slice(50) do |slice|
- destroy(slice)
- end
-
+ .pluck(:id)
+ .each_slice(50) { |slice| destroy(slice) }
end
private
def destroy(ids)
-
destroyer = UserDestroyer.new(Discourse.system_user)
User.transaction do
@@ -32,11 +34,18 @@ module Jobs
begin
user = User.find_by(id: id)
next unless user
- destroyer.destroy(user, transaction: false, context: I18n.t("user.destroy_reasons.inactive_user"))
+ destroyer.destroy(
+ user,
+ transaction: false,
+ context: I18n.t("user.destroy_reasons.inactive_user"),
+ )
rescue => e
- Discourse.handle_job_exception(e,
- message: "Cleaning up inactive users",
- extra: { user_id: id }
+ Discourse.handle_job_exception(
+ e,
+ message: "Cleaning up inactive users",
+ extra: {
+ user_id: id,
+ },
)
raise e
end
diff --git a/app/jobs/scheduled/clean_up_post_reply_keys.rb b/app/jobs/scheduled/clean_up_post_reply_keys.rb
index 748da603f34..a3088101c8f 100644
--- a/app/jobs/scheduled/clean_up_post_reply_keys.rb
+++ b/app/jobs/scheduled/clean_up_post_reply_keys.rb
@@ -9,7 +9,7 @@ module Jobs
PostReplyKey.where(
"created_at < ?",
- SiteSetting.disallow_reply_by_email_after_days.days.ago
+ SiteSetting.disallow_reply_by_email_after_days.days.ago,
).delete_all
end
end
diff --git a/app/jobs/scheduled/clean_up_unmatched_emails.rb b/app/jobs/scheduled/clean_up_unmatched_emails.rb
index 58fb112e17b..abcb85f172a 100644
--- a/app/jobs/scheduled/clean_up_unmatched_emails.rb
+++ b/app/jobs/scheduled/clean_up_unmatched_emails.rb
@@ -1,18 +1,16 @@
# frozen_string_literal: true
module Jobs
-
class CleanUpUnmatchedEmails < ::Jobs::Scheduled
every 1.day
def execute(args)
last_match_threshold = SiteSetting.max_age_unmatched_emails.days.ago
- ScreenedEmail.where(action_type: ScreenedEmail.actions[:block])
+ ScreenedEmail
+ .where(action_type: ScreenedEmail.actions[:block])
.where("last_match_at < ?", last_match_threshold)
.destroy_all
end
-
end
-
end
diff --git a/app/jobs/scheduled/clean_up_unmatched_ips.rb b/app/jobs/scheduled/clean_up_unmatched_ips.rb
index fa16315f2de..fa1c097eef1 100644
--- a/app/jobs/scheduled/clean_up_unmatched_ips.rb
+++ b/app/jobs/scheduled/clean_up_unmatched_ips.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class CleanUpUnmatchedIPs < ::Jobs::Scheduled
every 1.day
@@ -12,11 +11,14 @@ module Jobs
last_match_threshold = SiteSetting.max_age_unmatched_ips.days.ago
# remove old unmatched IP addresses
- ScreenedIpAddress.where(action_type: ScreenedIpAddress.actions[:block])
- .where("last_match_at < ? OR (last_match_at IS NULL AND created_at < ?)", last_match_threshold, last_match_threshold)
+ ScreenedIpAddress
+ .where(action_type: ScreenedIpAddress.actions[:block])
+ .where(
+ "last_match_at < ? OR (last_match_at IS NULL AND created_at < ?)",
+ last_match_threshold,
+ last_match_threshold,
+ )
.destroy_all
end
-
end
-
end
diff --git a/app/jobs/scheduled/clean_up_unsubscribe_keys.rb b/app/jobs/scheduled/clean_up_unsubscribe_keys.rb
index ed8dfb55667..91d22aaf6bf 100644
--- a/app/jobs/scheduled/clean_up_unsubscribe_keys.rb
+++ b/app/jobs/scheduled/clean_up_unsubscribe_keys.rb
@@ -1,14 +1,11 @@
# frozen_string_literal: true
module Jobs
-
class CleanUpUnsubscribeKeys < ::Jobs::Scheduled
every 1.day
def execute(args)
- UnsubscribeKey.where('created_at < ?', 2.months.ago).delete_all
+ UnsubscribeKey.where("created_at < ?", 2.months.ago).delete_all
end
-
end
-
end
diff --git a/app/jobs/scheduled/clean_up_unused_api_keys.rb b/app/jobs/scheduled/clean_up_unused_api_keys.rb
index 4b9e756e631..81266c7050a 100644
--- a/app/jobs/scheduled/clean_up_unused_api_keys.rb
+++ b/app/jobs/scheduled/clean_up_unused_api_keys.rb
@@ -1,14 +1,11 @@
# frozen_string_literal: true
module Jobs
-
class CleanUpUnusedApiKeys < ::Jobs::Scheduled
every 1.day
def execute(args)
ApiKey.revoke_unused_keys!
end
-
end
-
end
diff --git a/app/jobs/scheduled/clean_up_unused_staged_users.rb b/app/jobs/scheduled/clean_up_unused_staged_users.rb
index be2cd173132..301de4efeaf 100644
--- a/app/jobs/scheduled/clean_up_unused_staged_users.rb
+++ b/app/jobs/scheduled/clean_up_unused_staged_users.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class CleanUpUnusedStagedUsers < ::Jobs::Scheduled
every 1.day
@@ -11,23 +10,24 @@ module Jobs
destroyer = UserDestroyer.new(Discourse.system_user)
- User.joins("LEFT JOIN posts ON posts.user_id = users.id")
+ User
+ .joins("LEFT JOIN posts ON posts.user_id = users.id")
.where("posts.user_id IS NULL")
.where(staged: true, admin: false, moderator: false)
.where("users.created_at < ?", clean_up_after_days.days.ago)
.find_each do |user|
-
- begin
- destroyer.destroy(user, context: I18n.t("user.destroy_reasons.unused_staged_user"))
- rescue => e
- Discourse.handle_job_exception(e,
- message: "Cleaning up unused staged user",
- extra: { user_id: user.id }
- )
+ begin
+ destroyer.destroy(user, context: I18n.t("user.destroy_reasons.unused_staged_user"))
+ rescue => e
+ Discourse.handle_job_exception(
+ e,
+ message: "Cleaning up unused staged user",
+ extra: {
+ user_id: user.id,
+ },
+ )
+ end
end
- end
end
-
end
-
end
diff --git a/app/jobs/scheduled/clean_up_uploads.rb b/app/jobs/scheduled/clean_up_uploads.rb
index ecaa5d3876e..4f8c89c11eb 100644
--- a/app/jobs/scheduled/clean_up_uploads.rb
+++ b/app/jobs/scheduled/clean_up_uploads.rb
@@ -10,7 +10,9 @@ module Jobs
# always remove invalid upload records
Upload
.by_users
- .where("retain_hours IS NULL OR created_at < current_timestamp - interval '1 hour' * retain_hours")
+ .where(
+ "retain_hours IS NULL OR created_at < current_timestamp - interval '1 hour' * retain_hours",
+ )
.where("created_at < ?", grace_period.hour.ago)
.where(url: "")
.find_each(&:destroy!)
@@ -21,19 +23,29 @@ module Jobs
return if (Time.zone.now.to_i - c) < (grace_period / 2).hours
end
- base_url = Discourse.store.internal? ? Discourse.store.relative_base_url : Discourse.store.absolute_base_url
+ base_url =
+ (
+ if Discourse.store.internal?
+ Discourse.store.relative_base_url
+ else
+ Discourse.store.absolute_base_url
+ end
+ )
s3_hostname = URI.parse(base_url).hostname
s3_cdn_hostname = URI.parse(SiteSetting.Upload.s3_cdn_url || "").hostname
result = Upload.by_users
Upload.unused_callbacks&.each { |handler| result = handler.call(result) }
- result = result
- .where("uploads.retain_hours IS NULL OR uploads.created_at < current_timestamp - interval '1 hour' * uploads.retain_hours")
- .where("uploads.created_at < ?", grace_period.hour.ago)
- .where("uploads.access_control_post_id IS NULL")
- .joins("LEFT JOIN upload_references ON upload_references.upload_id = uploads.id")
- .where("upload_references.upload_id IS NULL")
- .with_no_non_post_relations
+ result =
+ result
+ .where(
+ "uploads.retain_hours IS NULL OR uploads.created_at < current_timestamp - interval '1 hour' * uploads.retain_hours",
+ )
+ .where("uploads.created_at < ?", grace_period.hour.ago)
+ .where("uploads.access_control_post_id IS NULL")
+ .joins("LEFT JOIN upload_references ON upload_references.upload_id = uploads.id")
+ .where("upload_references.upload_id IS NULL")
+ .with_no_non_post_relations
result.find_each do |upload|
next if Upload.in_use_callbacks&.any? { |callback| callback.call(upload) }
@@ -41,9 +53,30 @@ module Jobs
if upload.sha1.present?
# TODO: Remove this check after UploadReferences records were created
encoded_sha = Base62.encode(upload.sha1.hex)
- next if ReviewableQueuedPost.pending.where("payload->>'raw' LIKE ? OR payload->>'raw' LIKE ?", "%#{upload.sha1}%", "%#{encoded_sha}%").exists?
- next if Draft.where("data LIKE ? OR data LIKE ?", "%#{upload.sha1}%", "%#{encoded_sha}%").exists?
- next if UserProfile.where("bio_raw LIKE ? OR bio_raw LIKE ?", "%#{upload.sha1}%", "%#{encoded_sha}%").exists?
+ if ReviewableQueuedPost
+ .pending
+ .where(
+ "payload->>'raw' LIKE ? OR payload->>'raw' LIKE ?",
+ "%#{upload.sha1}%",
+ "%#{encoded_sha}%",
+ )
+ .exists?
+ next
+ end
+ if Draft.where(
+ "data LIKE ? OR data LIKE ?",
+ "%#{upload.sha1}%",
+ "%#{encoded_sha}%",
+ ).exists?
+ next
+ end
+ if UserProfile.where(
+ "bio_raw LIKE ? OR bio_raw LIKE ?",
+ "%#{upload.sha1}%",
+ "%#{encoded_sha}%",
+ ).exists?
+ next
+ end
upload.destroy
else
@@ -74,6 +107,5 @@ module Jobs
def last_cleanup_key
"LAST_UPLOAD_CLEANUP"
end
-
end
end
diff --git a/app/jobs/scheduled/create_missing_avatars.rb b/app/jobs/scheduled/create_missing_avatars.rb
index 0847b84f2e8..2043bafe0b3 100644
--- a/app/jobs/scheduled/create_missing_avatars.rb
+++ b/app/jobs/scheduled/create_missing_avatars.rb
@@ -6,14 +6,13 @@ module Jobs
def execute(args)
# backfill in batches of 5000 an hour
- UserAvatar.includes(:user)
+ UserAvatar
+ .includes(:user)
.joins(:user)
.where(last_gravatar_download_attempt: nil)
.order("users.last_posted_at DESC")
.limit(5000)
- .each do |u|
- u.user.refresh_avatar
- end
+ .each { |u| u.user.refresh_avatar }
end
end
end
diff --git a/app/jobs/scheduled/create_recent_post_search_indexes.rb b/app/jobs/scheduled/create_recent_post_search_indexes.rb
index 4f0ab41cd9e..95d181024a5 100644
--- a/app/jobs/scheduled/create_recent_post_search_indexes.rb
+++ b/app/jobs/scheduled/create_recent_post_search_indexes.rb
@@ -4,7 +4,7 @@ module Jobs
class CreateRecentPostSearchIndexes < ::Jobs::Scheduled
every 1.day
- REGULAR_POST_SEARCH_DATA_INDEX_NAME = 'idx_recent_regular_post_search_data'
+ REGULAR_POST_SEARCH_DATA_INDEX_NAME = "idx_recent_regular_post_search_data"
def execute(_)
create_recent_regular_post_search_index
@@ -13,7 +13,11 @@ module Jobs
private
def create_recent_regular_post_search_index
- if !PostSearchData.where(private_message: false).offset(SiteSetting.search_enable_recent_regular_posts_offset_size - 1).limit(1).exists?
+ if !PostSearchData
+ .where(private_message: false)
+ .offset(SiteSetting.search_enable_recent_regular_posts_offset_size - 1)
+ .limit(1)
+ .exists?
return
end
@@ -24,22 +28,22 @@ module Jobs
SQL
DB.exec(<<~SQL, post_id: SiteSetting.search_recent_regular_posts_offset_post_id)
- CREATE INDEX #{Rails.env.test? ? '' : 'CONCURRENTLY'} temp_idx_recent_regular_post_search_data
+ CREATE INDEX #{Rails.env.test? ? "" : "CONCURRENTLY"} temp_idx_recent_regular_post_search_data
ON post_search_data USING GIN(search_data)
WHERE NOT private_message AND post_id >= :post_id
SQL
DB.exec(<<~SQL)
- #{Rails.env.test? ? '' : "BEGIN;"}
+ #{Rails.env.test? ? "" : "BEGIN;"}
DROP INDEX IF EXISTS #{REGULAR_POST_SEARCH_DATA_INDEX_NAME};
ALTER INDEX temp_idx_recent_regular_post_search_data RENAME TO #{REGULAR_POST_SEARCH_DATA_INDEX_NAME};
- #{Rails.env.test? ? '' : "COMMIT;"}
+ #{Rails.env.test? ? "" : "COMMIT;"}
SQL
end
def regular_offset_post_id
PostSearchData
- .order('post_id DESC')
+ .order("post_id DESC")
.where(private_message: false)
.offset(SiteSetting.search_recent_posts_size - 1)
.limit(1)
diff --git a/app/jobs/scheduled/dashboard_stats.rb b/app/jobs/scheduled/dashboard_stats.rb
index 2c1bd74fa32..a81d0b5d7b3 100644
--- a/app/jobs/scheduled/dashboard_stats.rb
+++ b/app/jobs/scheduled/dashboard_stats.rb
@@ -8,7 +8,8 @@ module Jobs
if persistent_problems?
# If there have been problems reported on the dashboard for a while,
# send a message to admins no more often than once per week.
- group_message = GroupMessage.new(Group[:admins].name, :dashboard_problems, limit_once_per: 7.days.to_i)
+ group_message =
+ GroupMessage.new(Group[:admins].name, :dashboard_problems, limit_once_per: 7.days.to_i)
Topic.transaction do
group_message.delete_previous!
group_message.create
diff --git a/app/jobs/scheduled/destroy_old_hidden_posts.rb b/app/jobs/scheduled/destroy_old_hidden_posts.rb
index fa282fcbdb1..fc2ed504946 100644
--- a/app/jobs/scheduled/destroy_old_hidden_posts.rb
+++ b/app/jobs/scheduled/destroy_old_hidden_posts.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class DestroyOldHiddenPosts < ::Jobs::Scheduled
every 1.day
@@ -9,7 +8,5 @@ module Jobs
return unless SiteSetting.delete_old_hidden_posts
PostDestroyer.destroy_old_hidden_posts
end
-
end
-
end
diff --git a/app/jobs/scheduled/disable_bootstrap_mode.rb b/app/jobs/scheduled/disable_bootstrap_mode.rb
index 61650b3094c..e9d1db42881 100644
--- a/app/jobs/scheduled/disable_bootstrap_mode.rb
+++ b/app/jobs/scheduled/disable_bootstrap_mode.rb
@@ -8,16 +8,17 @@ module Jobs
return unless SiteSetting.bootstrap_mode_enabled
total_users = User.human_users.count
- if SiteSetting.bootstrap_mode_min_users == 0 || total_users > SiteSetting.bootstrap_mode_min_users
+ if SiteSetting.bootstrap_mode_min_users == 0 ||
+ total_users > SiteSetting.bootstrap_mode_min_users
if SiteSetting.default_trust_level == TrustLevel[1]
- SiteSetting.set_and_log('default_trust_level', TrustLevel[0])
+ SiteSetting.set_and_log("default_trust_level", TrustLevel[0])
end
if SiteSetting.default_email_digest_frequency == 1440
- SiteSetting.set_and_log('default_email_digest_frequency', 10080)
+ SiteSetting.set_and_log("default_email_digest_frequency", 10_080)
end
- SiteSetting.set_and_log('bootstrap_mode_enabled', false)
+ SiteSetting.set_and_log("bootstrap_mode_enabled", false)
end
end
end
diff --git a/app/jobs/scheduled/enqueue_digest_emails.rb b/app/jobs/scheduled/enqueue_digest_emails.rb
index 7d9ad9fa16b..f700c31025f 100644
--- a/app/jobs/scheduled/enqueue_digest_emails.rb
+++ b/app/jobs/scheduled/enqueue_digest_emails.rb
@@ -1,35 +1,45 @@
# frozen_string_literal: true
module Jobs
-
class EnqueueDigestEmails < ::Jobs::Scheduled
every 30.minutes
def execute(args)
- return if SiteSetting.disable_digest_emails? || SiteSetting.private_email? || SiteSetting.disable_emails == 'yes'
+ if SiteSetting.disable_digest_emails? || SiteSetting.private_email? ||
+ SiteSetting.disable_emails == "yes"
+ return
+ end
users = target_user_ids
- users.each do |user_id|
- ::Jobs.enqueue(:user_email, type: "digest", user_id: user_id)
- end
+ users.each { |user_id| ::Jobs.enqueue(:user_email, type: "digest", user_id: user_id) }
end
def target_user_ids
# Users who want to receive digest email within their chosen digest email frequency
- query = User
- .real
- .activated
- .not_suspended
- .where(staged: false)
- .joins(:user_option, :user_stat, :user_emails)
- .where("user_options.email_digests")
- .where("user_stats.bounce_score < ?", SiteSetting.bounce_score_threshold)
- .where("user_emails.primary")
- .where("COALESCE(last_emailed_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)")
- .where("COALESCE(user_stats.digest_attempted_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)")
- .where("COALESCE(last_seen_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)")
- .where("COALESCE(last_seen_at, '2010-01-01') >= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * ?)", SiteSetting.suppress_digest_email_after_days)
- .order("user_stats.digest_attempted_at ASC NULLS FIRST")
+ query =
+ User
+ .real
+ .activated
+ .not_suspended
+ .where(staged: false)
+ .joins(:user_option, :user_stat, :user_emails)
+ .where("user_options.email_digests")
+ .where("user_stats.bounce_score < ?", SiteSetting.bounce_score_threshold)
+ .where("user_emails.primary")
+ .where(
+ "COALESCE(last_emailed_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)",
+ )
+ .where(
+ "COALESCE(user_stats.digest_attempted_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)",
+ )
+ .where(
+ "COALESCE(last_seen_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)",
+ )
+ .where(
+ "COALESCE(last_seen_at, '2010-01-01') >= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * ?)",
+ SiteSetting.suppress_digest_email_after_days,
+ )
+ .order("user_stats.digest_attempted_at ASC NULLS FIRST")
# If the site requires approval, make sure the user is approved
query = query.where("approved OR moderator OR admin") if SiteSetting.must_approve_users?
@@ -38,7 +48,5 @@ module Jobs
query.pluck(:id)
end
-
end
-
end
diff --git a/app/jobs/scheduled/enqueue_onceoffs.rb b/app/jobs/scheduled/enqueue_onceoffs.rb
index 29692c63112..e0b3a4cedf0 100644
--- a/app/jobs/scheduled/enqueue_onceoffs.rb
+++ b/app/jobs/scheduled/enqueue_onceoffs.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class EnqueueOnceoffs < ::Jobs::Scheduled
every 10.minutes
@@ -9,5 +8,4 @@ module Jobs
::Jobs::Onceoff.enqueue_all
end
end
-
end
diff --git a/app/jobs/scheduled/enqueue_suspect_users.rb b/app/jobs/scheduled/enqueue_suspect_users.rb
index d6f568335c7..765728e3f0f 100644
--- a/app/jobs/scheduled/enqueue_suspect_users.rb
+++ b/app/jobs/scheduled/enqueue_suspect_users.rb
@@ -8,51 +8,56 @@ module Jobs
return unless SiteSetting.approve_suspect_users
return if SiteSetting.must_approve_users
- users = User
- .distinct
- .activated
- .human_users
- .where(approved: false)
- .joins(:user_profile, :user_stat)
- .where("users.created_at <= ? AND users.created_at >= ?", 1.day.ago, 6.months.ago)
- .where("LENGTH(COALESCE(user_profiles.bio_raw, user_profiles.website, '')) > 0")
- .where("user_stats.posts_read_count <= 1 OR user_stats.topics_entered <= 1 OR user_stats.time_read < ?", 1.minute.to_i)
- .joins("LEFT OUTER JOIN reviewables r ON r.target_id = users.id AND r.target_type = 'User'")
- .where('r.id IS NULL')
- .joins(
- <<~SQL
+ users =
+ User
+ .distinct
+ .activated
+ .human_users
+ .where(approved: false)
+ .joins(:user_profile, :user_stat)
+ .where("users.created_at <= ? AND users.created_at >= ?", 1.day.ago, 6.months.ago)
+ .where("LENGTH(COALESCE(user_profiles.bio_raw, user_profiles.website, '')) > 0")
+ .where(
+ "user_stats.posts_read_count <= 1 OR user_stats.topics_entered <= 1 OR user_stats.time_read < ?",
+ 1.minute.to_i,
+ )
+ .joins(
+ "LEFT OUTER JOIN reviewables r ON r.target_id = users.id AND r.target_type = 'User'",
+ )
+ .where("r.id IS NULL")
+ .joins(<<~SQL)
LEFT OUTER JOIN (
SELECT user_id
FROM user_custom_fields
WHERE user_custom_fields.name = 'import_id'
) AS ucf ON ucf.user_id = users.id
SQL
- )
- .where('ucf.user_id IS NULL')
- .limit(10)
+ .where("ucf.user_id IS NULL")
+ .limit(10)
users.each do |user|
user_profile = user.user_profile
- reviewable = ReviewableUser.needs_review!(
- target: user,
- created_by: Discourse.system_user,
- reviewable_by_moderator: true,
- payload: {
- username: user.username,
- name: user.name,
- email: user.email,
- bio: user_profile.bio_raw,
- website: user_profile.website,
- }
- )
+ reviewable =
+ ReviewableUser.needs_review!(
+ target: user,
+ created_by: Discourse.system_user,
+ reviewable_by_moderator: true,
+ payload: {
+ username: user.username,
+ name: user.name,
+ email: user.email,
+ bio: user_profile.bio_raw,
+ website: user_profile.website,
+ },
+ )
if reviewable.created_new
reviewable.add_score(
Discourse.system_user,
ReviewableScore.types[:needs_approval],
reason: :suspect_user,
- force_review: true
+ force_review: true,
)
end
end
diff --git a/app/jobs/scheduled/ensure_db_consistency.rb b/app/jobs/scheduled/ensure_db_consistency.rb
index 6ecb928d079..dd38439845e 100644
--- a/app/jobs/scheduled/ensure_db_consistency.rb
+++ b/app/jobs/scheduled/ensure_db_consistency.rb
@@ -23,7 +23,7 @@ module Jobs
User,
UserAvatar,
Category,
- TopicThumbnail
+ TopicThumbnail,
].each do |klass|
klass.ensure_consistency!
measure(klass)
@@ -46,9 +46,7 @@ module Jobs
def format_measure
result = +"EnsureDbConsistency Times\n"
- result << @measure_times.map do |name, duration|
- " #{name}: #{duration}"
- end.join("\n")
+ result << @measure_times.map { |name, duration| " #{name}: #{duration}" }.join("\n")
result
end
@@ -59,11 +57,8 @@ module Jobs
def measure(step = nil)
@measure_now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- if @measure_start
- @measure_times << [step, @measure_now - @measure_start]
- end
+ @measure_times << [step, @measure_now - @measure_start] if @measure_start
@measure_start = @measure_now
end
-
end
end
diff --git a/app/jobs/scheduled/ensure_s3_uploads_existence.rb b/app/jobs/scheduled/ensure_s3_uploads_existence.rb
index 8a8e90643b2..cf71f4253a3 100644
--- a/app/jobs/scheduled/ensure_s3_uploads_existence.rb
+++ b/app/jobs/scheduled/ensure_s3_uploads_existence.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class EnsureS3UploadsExistence < ::Jobs::Scheduled
every 1.day
@@ -11,7 +10,10 @@ module Jobs
super
ensure
if @db_inventories
- @db_inventories.values.each { |f| f.close; f.unlink }
+ @db_inventories.values.each do |f|
+ f.close
+ f.unlink
+ end
end
end
@@ -27,18 +29,20 @@ module Jobs
def execute(args)
return if !executable?
- require 's3_inventory'
+ require "s3_inventory"
if !@db_inventories && Rails.configuration.multisite && GlobalSetting.use_s3?
prepare_for_all_sites
end
- if @db_inventories && preloaded_inventory_file = @db_inventories[RailsMultisite::ConnectionManagement.current_db]
+ if @db_inventories &&
+ preloaded_inventory_file =
+ @db_inventories[RailsMultisite::ConnectionManagement.current_db]
S3Inventory.new(
s3_helper,
:upload,
preloaded_inventory_file: preloaded_inventory_file,
- preloaded_inventory_date: @inventory_date
+ preloaded_inventory_date: @inventory_date,
).backfill_etags_and_list_missing
else
S3Inventory.new(s3_helper, :upload).backfill_etags_and_list_missing
diff --git a/app/jobs/scheduled/fix_user_usernames_and_groups_names_clash.rb b/app/jobs/scheduled/fix_user_usernames_and_groups_names_clash.rb
index d176217d55f..471490be0f9 100644
--- a/app/jobs/scheduled/fix_user_usernames_and_groups_names_clash.rb
+++ b/app/jobs/scheduled/fix_user_usernames_and_groups_names_clash.rb
@@ -5,27 +5,24 @@ module Jobs
every 1.week
def execute(args)
- User.joins("LEFT JOIN groups ON lower(groups.name) = users.username_lower")
+ User
+ .joins("LEFT JOIN groups ON lower(groups.name) = users.username_lower")
.where("groups.id IS NOT NULL")
.find_each do |user|
+ suffix = 1
+ old_username = user.username
- suffix = 1
- old_username = user.username
+ loop do
+ user.username = "#{old_username}#{suffix}"
+ suffix += 1
+ break if user.valid?
+ end
- loop do
- user.username = "#{old_username}#{suffix}"
- suffix += 1
- break if user.valid?
+ new_username = user.username
+ user.username = old_username
+
+ UsernameChanger.new(user, new_username).change(asynchronous: false)
end
-
- new_username = user.username
- user.username = old_username
-
- UsernameChanger.new(
- user,
- new_username
- ).change(asynchronous: false)
- end
end
end
end
diff --git a/app/jobs/scheduled/grant_anniversary_badges.rb b/app/jobs/scheduled/grant_anniversary_badges.rb
index a5246c3243f..c244a2e92ee 100644
--- a/app/jobs/scheduled/grant_anniversary_badges.rb
+++ b/app/jobs/scheduled/grant_anniversary_badges.rb
@@ -35,10 +35,9 @@ module Jobs
HAVING COUNT(p.id) > 0 AND COUNT(ub.id) = 0
SQL
- User.where(id: user_ids).find_each do |user|
- BadgeGranter.grant(badge, user, created_at: end_date)
- end
+ User
+ .where(id: user_ids)
+ .find_each { |user| BadgeGranter.grant(badge, user, created_at: end_date) }
end
-
end
end
diff --git a/app/jobs/scheduled/grant_new_user_of_the_month_badges.rb b/app/jobs/scheduled/grant_new_user_of_the_month_badges.rb
index 3359b934174..ce169794bb0 100644
--- a/app/jobs/scheduled/grant_new_user_of_the_month_badges.rb
+++ b/app/jobs/scheduled/grant_new_user_of_the_month_badges.rb
@@ -13,9 +13,14 @@ module Jobs
previous_month_beginning = 1.month.ago.beginning_of_month
previous_month_end = 1.month.ago.end_of_month
- return if UserBadge.where("badge_id = ? AND granted_at BETWEEN ? AND ?",
- badge.id, previous_month_beginning, Time.zone.now
- ).exists?
+ if UserBadge.where(
+ "badge_id = ? AND granted_at BETWEEN ? AND ?",
+ badge.id,
+ previous_month_beginning,
+ Time.zone.now,
+ ).exists?
+ return
+ end
scores(previous_month_beginning, previous_month_end).each do |user_id, score|
# Don't bother awarding to users who haven't received any likes
@@ -24,9 +29,10 @@ module Jobs
if user.badges.where(id: Badge::NewUserOfTheMonth).blank?
BadgeGranter.grant(badge, user, created_at: previous_month_end)
- SystemMessage.new(user).create('new_user_of_the_month',
+ SystemMessage.new(user).create(
+ "new_user_of_the_month",
month_year: I18n.l(previous_month_beginning, format: :no_day),
- url: "#{Discourse.base_url}/badges"
+ url: "#{Discourse.base_url}/badges",
)
end
end
@@ -65,7 +71,7 @@ module Jobs
LEFT OUTER JOIN topics AS t ON t.id = p.topic_id
WHERE u.active
AND u.id > 0
- AND u.id NOT IN (#{current_owners.join(',')})
+ AND u.id NOT IN (#{current_owners.join(",")})
AND NOT u.staged
AND NOT u.admin
AND NOT u.moderator
@@ -87,10 +93,9 @@ module Jobs
*DB.query_single(
sql,
min_user_created_at: min_user_created_at,
- max_user_created_at: max_user_created_at
+ max_user_created_at: max_user_created_at,
)
]
end
-
end
end
diff --git a/app/jobs/scheduled/heartbeat.rb b/app/jobs/scheduled/heartbeat.rb
index 16ab8b77bbb..04b807ea8e2 100644
--- a/app/jobs/scheduled/heartbeat.rb
+++ b/app/jobs/scheduled/heartbeat.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
# used to ensure at least 1 sidekiq is running correctly
class Heartbeat < ::Jobs::Scheduled
every 3.minute
diff --git a/app/jobs/scheduled/ignored_users_summary.rb b/app/jobs/scheduled/ignored_users_summary.rb
index 59483c2b529..962176a69d3 100644
--- a/app/jobs/scheduled/ignored_users_summary.rb
+++ b/app/jobs/scheduled/ignored_users_summary.rb
@@ -24,7 +24,11 @@ module Jobs
private
def notify_user(user)
- params = SystemMessage.new(user).defaults.merge(ignores_threshold: SiteSetting.ignored_users_count_message_threshold)
+ params =
+ SystemMessage
+ .new(user)
+ .defaults
+ .merge(ignores_threshold: SiteSetting.ignored_users_count_message_threshold)
title = I18n.t("system_messages.ignored_users_summary.subject_template")
raw = I18n.t("system_messages.ignored_users_summary.text_body_template", params)
@@ -35,7 +39,8 @@ module Jobs
subtype: TopicSubtype.system_message,
title: title,
raw: raw,
- skip_validations: true)
+ skip_validations: true,
+ )
IgnoredUser.where(ignored_user_id: user.id).update_all(summarized_at: Time.zone.now)
end
end
diff --git a/app/jobs/scheduled/invalidate_inactive_admins.rb b/app/jobs/scheduled/invalidate_inactive_admins.rb
index bc3e2500a15..3e78dae5a3a 100644
--- a/app/jobs/scheduled/invalidate_inactive_admins.rb
+++ b/app/jobs/scheduled/invalidate_inactive_admins.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class InvalidateInactiveAdmins < ::Jobs::Scheduled
every 1.day
@@ -10,29 +9,38 @@ module Jobs
timestamp = SiteSetting.invalidate_inactive_admin_email_after_days.days.ago
- User.human_users
+ User
+ .human_users
.where(admin: true)
.where(active: true)
- .where('last_seen_at < ?', timestamp)
- .where("NOT EXISTS ( SELECT 1 from api_keys WHERE api_keys.user_id = users.id AND COALESCE(last_used_at, updated_at) > ? )", timestamp)
- .where("NOT EXISTS ( SELECT 1 from posts WHERE posts.user_id = users.id AND created_at > ?)", timestamp)
+ .where("last_seen_at < ?", timestamp)
+ .where(
+ "NOT EXISTS ( SELECT 1 from api_keys WHERE api_keys.user_id = users.id AND COALESCE(last_used_at, updated_at) > ? )",
+ timestamp,
+ )
+ .where(
+ "NOT EXISTS ( SELECT 1 from posts WHERE posts.user_id = users.id AND created_at > ?)",
+ timestamp,
+ )
.each do |user|
+ User.transaction do
+ user.deactivate(Discourse.system_user)
+ user.email_tokens.update_all(confirmed: false, expired: true)
- User.transaction do
- user.deactivate(Discourse.system_user)
- user.email_tokens.update_all(confirmed: false, expired: true)
+ reason =
+ I18n.t(
+ "user.deactivated_by_inactivity",
+ count: SiteSetting.invalidate_inactive_admin_email_after_days,
+ )
+ StaffActionLogger.new(Discourse.system_user).log_user_deactivate(user, reason)
- reason = I18n.t("user.deactivated_by_inactivity", count: SiteSetting.invalidate_inactive_admin_email_after_days)
- StaffActionLogger.new(Discourse.system_user).log_user_deactivate(user, reason)
-
- Discourse.authenticators.each do |authenticator|
- if authenticator.can_revoke? && authenticator.description_for_user(user).present?
- authenticator.revoke(user)
+ Discourse.authenticators.each do |authenticator|
+ if authenticator.can_revoke? && authenticator.description_for_user(user).present?
+ authenticator.revoke(user)
+ end
end
end
end
- end
end
end
-
end
diff --git a/app/jobs/scheduled/migrate_upload_scheme.rb b/app/jobs/scheduled/migrate_upload_scheme.rb
index 601ad3afd87..bccae4d7b8f 100644
--- a/app/jobs/scheduled/migrate_upload_scheme.rb
+++ b/app/jobs/scheduled/migrate_upload_scheme.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class MigrateUploadScheme < ::Jobs::Scheduled
every 10.minutes
sidekiq_options retry: false
@@ -10,51 +9,44 @@ module Jobs
return unless SiteSetting.migrate_to_new_scheme
# clean up failed uploads
- Upload.where("created_at < ?", 1.hour.ago)
+ Upload
+ .where("created_at < ?", 1.hour.ago)
.where("LENGTH(COALESCE(url, '')) = 0")
- .find_each do |upload|
-
- upload.destroy!
- end
+ .find_each { |upload| upload.destroy! }
# migrate uploads to new scheme
problems = Upload.migrate_to_new_scheme(limit: 50)
problems.each do |hash|
upload_id = hash[:upload].id
- Discourse.handle_job_exception(hash[:ex], error_context(args, "Migrating upload id #{upload_id}", upload_id: upload_id))
+ Discourse.handle_job_exception(
+ hash[:ex],
+ error_context(args, "Migrating upload id #{upload_id}", upload_id: upload_id),
+ )
end
# clean up failed optimized images
OptimizedImage
.where("LENGTH(COALESCE(url, '')) = 0")
- .find_each do |optimized_image|
-
- optimized_image.destroy!
- end
+ .find_each { |optimized_image| optimized_image.destroy! }
# Clean up orphan optimized images
OptimizedImage
.joins("LEFT JOIN uploads ON optimized_images.upload_id = uploads.id")
.where("uploads.id IS NULL")
- .find_each do |optimized_image|
-
- optimized_image.destroy!
- end
+ .find_each { |optimized_image| optimized_image.destroy! }
# Clean up optimized images that needs to be regenerated
- OptimizedImage.joins(:upload)
+ OptimizedImage
+ .joins(:upload)
.where("optimized_images.url NOT LIKE '%/optimized/_X/%'")
.where("uploads.url LIKE '%/original/_X/%'")
.limit(50)
.find_each do |optimized_image|
-
- upload = optimized_image.upload
- optimized_image.destroy!
- upload.rebake_posts_on_old_scheme
- end
+ upload = optimized_image.upload
+ optimized_image.destroy!
+ upload.rebake_posts_on_old_scheme
+ end
end
-
end
-
end
diff --git a/app/jobs/scheduled/old_keys_reminder.rb b/app/jobs/scheduled/old_keys_reminder.rb
index de824fa5d0e..cec2108b542 100644
--- a/app/jobs/scheduled/old_keys_reminder.rb
+++ b/app/jobs/scheduled/old_keys_reminder.rb
@@ -17,26 +17,34 @@ module Jobs
raw: body,
archetype: Archetype.private_message,
target_usernames: admins.map(&:username),
- validate: false
+ validate: false,
)
end
private
def old_site_settings_keys
- @old_site_settings_keys ||= SiteSetting.secret_settings.each_with_object([]) do |secret_name, old_keys|
- site_setting = SiteSetting.find_by(name: secret_name)
- next if site_setting&.value.blank?
- next if site_setting.updated_at + OLD_CREDENTIALS_PERIOD > Time.zone.now
- old_keys << site_setting
- end.sort_by { |key| key.updated_at }
+ @old_site_settings_keys ||=
+ SiteSetting
+ .secret_settings
+ .each_with_object([]) do |secret_name, old_keys|
+ site_setting = SiteSetting.find_by(name: secret_name)
+ next if site_setting&.value.blank?
+ next if site_setting.updated_at + OLD_CREDENTIALS_PERIOD > Time.zone.now
+ old_keys << site_setting
+ end
+ .sort_by { |key| key.updated_at }
end
def old_api_keys
- @old_api_keys ||= ApiKey.all.order(created_at: :asc).each_with_object([]) do |api_key, old_keys|
- next if api_key.created_at + OLD_CREDENTIALS_PERIOD > Time.zone.now
- old_keys << api_key
- end
+ @old_api_keys ||=
+ ApiKey
+ .all
+ .order(created_at: :asc)
+ .each_with_object([]) do |api_key, old_keys|
+ next if api_key.created_at + OLD_CREDENTIALS_PERIOD > Time.zone.now
+ old_keys << api_key
+ end
end
def admins
@@ -45,20 +53,24 @@ module Jobs
def message_exists?
message = Topic.private_messages.with_deleted.find_by(title: title)
- message && message.created_at + SiteSetting.send_old_credential_reminder_days.to_i.days > Time.zone.now
+ message &&
+ message.created_at + SiteSetting.send_old_credential_reminder_days.to_i.days > Time.zone.now
end
def title
- I18n.t('old_keys_reminder.title')
+ I18n.t("old_keys_reminder.title")
end
def body
- I18n.t('old_keys_reminder.body', keys: keys_list)
+ I18n.t("old_keys_reminder.body", keys: keys_list)
end
def keys_list
- messages = old_site_settings_keys.map { |key| "#{key.name} - #{key.updated_at.to_date.to_fs(:db)}" }
- old_api_keys.each_with_object(messages) { |key, array| array << "#{[key.description, key.user&.username, key.created_at.to_date.to_fs(:db)].compact.join(" - ")}" }
+ messages =
+ old_site_settings_keys.map { |key| "#{key.name} - #{key.updated_at.to_date.to_fs(:db)}" }
+ old_api_keys.each_with_object(messages) do |key, array|
+ array << "#{[key.description, key.user&.username, key.created_at.to_date.to_fs(:db)].compact.join(" - ")}"
+ end
messages.join("\n")
end
end
diff --git a/app/jobs/scheduled/pending_queued_posts_reminder.rb b/app/jobs/scheduled/pending_queued_posts_reminder.rb
index 22b84fc701b..78f5220adbd 100644
--- a/app/jobs/scheduled/pending_queued_posts_reminder.rb
+++ b/app/jobs/scheduled/pending_queued_posts_reminder.rb
@@ -2,7 +2,6 @@
module Jobs
class PendingQueuedPostsReminder < ::Jobs::Scheduled
-
every 15.minutes
def execute(args)
@@ -16,8 +15,16 @@ module Jobs
target_group_names: Group[:moderators].name,
archetype: Archetype.private_message,
subtype: TopicSubtype.system_message,
- title: I18n.t('system_messages.queued_posts_reminder.subject_template', count: queued_post_ids.size),
- raw: I18n.t('system_messages.queued_posts_reminder.text_body_template', base_url: Discourse.base_url)
+ title:
+ I18n.t(
+ "system_messages.queued_posts_reminder.subject_template",
+ count: queued_post_ids.size,
+ ),
+ raw:
+ I18n.t(
+ "system_messages.queued_posts_reminder.text_body_template",
+ base_url: Discourse.base_url,
+ ),
)
self.last_notified_id = queued_post_ids.max
@@ -27,9 +34,10 @@ module Jobs
end
def should_notify_ids
- ReviewableQueuedPost.pending.where(
- 'created_at < ?', SiteSetting.notify_about_queued_posts_after.to_f.hours.ago
- ).pluck(:id)
+ ReviewableQueuedPost
+ .pending
+ .where("created_at < ?", SiteSetting.notify_about_queued_posts_after.to_f.hours.ago)
+ .pluck(:id)
end
def last_notified_id
diff --git a/app/jobs/scheduled/pending_reviewables_reminder.rb b/app/jobs/scheduled/pending_reviewables_reminder.rb
index 1a94e70b836..deb784934ef 100644
--- a/app/jobs/scheduled/pending_reviewables_reminder.rb
+++ b/app/jobs/scheduled/pending_reviewables_reminder.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class PendingReviewablesReminder < ::Jobs::Scheduled
every 15.minutes
@@ -11,25 +10,30 @@ module Jobs
@sent_reminder = false
if SiteSetting.notify_about_flags_after > 0
- reviewable_ids = Reviewable
- .pending
- .default_visible
- .where('latest_score < ?', SiteSetting.notify_about_flags_after.to_f.hours.ago)
- .order('id DESC')
- .pluck(:id)
+ reviewable_ids =
+ Reviewable
+ .pending
+ .default_visible
+ .where("latest_score < ?", SiteSetting.notify_about_flags_after.to_f.hours.ago)
+ .order("id DESC")
+ .pluck(:id)
if reviewable_ids.size > 0 && self.class.last_notified_id < reviewable_ids[0]
usernames = active_moderator_usernames
- mentions = usernames.size > 0 ? "@#{usernames.join(', @')} " : ""
+ mentions = usernames.size > 0 ? "@#{usernames.join(", @")} " : ""
- message = GroupMessage.new(
- Group[:moderators].name,
- 'reviewables_reminder',
- {
- limit_once_per: false,
- message_params: { mentions: mentions, count: SiteSetting.notify_about_flags_after }
- }
- )
+ message =
+ GroupMessage.new(
+ Group[:moderators].name,
+ "reviewables_reminder",
+ {
+ limit_once_per: false,
+ message_params: {
+ mentions: mentions,
+ count: SiteSetting.notify_about_flags_after,
+ },
+ },
+ )
Topic.transaction do
message.delete_previous!(match_raw: false)
@@ -58,13 +62,7 @@ module Jobs
end
def active_moderator_usernames
- User.where(moderator: true)
- .human_users
- .order('last_seen_at DESC')
- .limit(3)
- .pluck(:username)
+ User.where(moderator: true).human_users.order("last_seen_at DESC").limit(3).pluck(:username)
end
-
end
-
end
diff --git a/app/jobs/scheduled/pending_users_reminder.rb b/app/jobs/scheduled/pending_users_reminder.rb
index 0d8a2d393f9..0ed3fbdc57b 100644
--- a/app/jobs/scheduled/pending_users_reminder.rb
+++ b/app/jobs/scheduled/pending_users_reminder.rb
@@ -1,15 +1,18 @@
# frozen_string_literal: true
module Jobs
-
class PendingUsersReminder < ::Jobs::Scheduled
every 5.minutes
def execute(args)
if SiteSetting.must_approve_users && SiteSetting.pending_users_reminder_delay_minutes >= 0
- query = AdminUserIndexQuery.new(query: 'pending', stats: false).find_users_query # default order is: users.created_at DESC
+ query = AdminUserIndexQuery.new(query: "pending", stats: false).find_users_query # default order is: users.created_at DESC
if SiteSetting.pending_users_reminder_delay_minutes > 0
- query = query.where('users.created_at < ?', SiteSetting.pending_users_reminder_delay_minutes.minutes.ago)
+ query =
+ query.where(
+ "users.created_at < ?",
+ SiteSetting.pending_users_reminder_delay_minutes.minutes.ago,
+ )
end
newest_username = query.limit(1).select(:username).first&.username
@@ -19,17 +22,24 @@ module Jobs
count = query.count
if count > 0
- target_usernames = Group[:moderators].users.map do |user|
- next if user.bot?
+ target_usernames =
+ Group[:moderators]
+ .users
+ .map do |user|
+ next if user.bot?
- unseen_count = user.notifications.joins(:topic)
- .where("notifications.id > ?", user.seen_notification_id)
- .where("notifications.read = false")
- .where("topics.subtype = ?", TopicSubtype.pending_users_reminder)
- .count
+ unseen_count =
+ user
+ .notifications
+ .joins(:topic)
+ .where("notifications.id > ?", user.seen_notification_id)
+ .where("notifications.read = false")
+ .where("topics.subtype = ?", TopicSubtype.pending_users_reminder)
+ .count
- unseen_count == 0 ? user.username : nil
- end.compact
+ unseen_count == 0 ? user.username : nil
+ end
+ .compact
unless target_usernames.empty?
PostCreator.create(
@@ -37,8 +47,14 @@ module Jobs
target_usernames: target_usernames,
archetype: Archetype.private_message,
subtype: TopicSubtype.pending_users_reminder,
- title: I18n.t("system_messages.pending_users_reminder.subject_template", count: count),
- raw: I18n.t("system_messages.pending_users_reminder.text_body_template", count: count, base_url: Discourse.base_url)
+ title:
+ I18n.t("system_messages.pending_users_reminder.subject_template", count: count),
+ raw:
+ I18n.t(
+ "system_messages.pending_users_reminder.text_body_template",
+ count: count,
+ base_url: Discourse.base_url,
+ ),
)
self.previous_newest_username = newest_username
@@ -60,7 +76,5 @@ module Jobs
def previous_newest_username_cache_key
"pending-users-reminder:newest-username"
end
-
end
-
end
diff --git a/app/jobs/scheduled/periodical_updates.rb b/app/jobs/scheduled/periodical_updates.rb
index 5c5da8bac6b..f74adc180c7 100644
--- a/app/jobs/scheduled/periodical_updates.rb
+++ b/app/jobs/scheduled/periodical_updates.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
# This job will run on a regular basis to update statistics and denormalized data.
# If it does not run, the site will not function properly.
class PeriodicalUpdates < ::Jobs::Scheduled
@@ -25,11 +24,15 @@ module Jobs
ScoreCalculator.new.calculate(args)
# Forces rebake of old posts where needed, as long as no system avatars need updating
- if !SiteSetting.automatically_download_gravatars || !UserAvatar.where("last_gravatar_download_attempt IS NULL").limit(1).first
+ if !SiteSetting.automatically_download_gravatars ||
+ !UserAvatar.where("last_gravatar_download_attempt IS NULL").limit(1).first
problems = Post.rebake_old(SiteSetting.rebake_old_posts_count, priority: :ultra_low)
problems.each do |hash|
post_id = hash[:post].id
- Discourse.handle_job_exception(hash[:ex], error_context(args, "Rebaking post id #{post_id}", post_id: post_id))
+ Discourse.handle_job_exception(
+ hash[:ex],
+ error_context(args, "Rebaking post id #{post_id}", post_id: post_id),
+ )
end
end
@@ -37,20 +40,19 @@ module Jobs
problems = UserProfile.rebake_old(250)
problems.each do |hash|
user_id = hash[:profile].user_id
- Discourse.handle_job_exception(hash[:ex], error_context(args, "Rebaking user id #{user_id}", user_id: user_id))
+ Discourse.handle_job_exception(
+ hash[:ex],
+ error_context(args, "Rebaking user id #{user_id}", user_id: user_id),
+ )
end
offset = (SiteSetting.max_new_topics).to_i
- last_new_topic = Topic.order('created_at desc').offset(offset).select(:created_at).first
- if last_new_topic
- SiteSetting.min_new_topics_time = last_new_topic.created_at.to_i
- end
+ last_new_topic = Topic.order("created_at desc").offset(offset).select(:created_at).first
+ SiteSetting.min_new_topics_time = last_new_topic.created_at.to_i if last_new_topic
Category.auto_bump_topic!
nil
end
-
end
-
end
diff --git a/app/jobs/scheduled/poll_mailbox.rb b/app/jobs/scheduled/poll_mailbox.rb
index 19e5a09d654..f4535bc0779 100644
--- a/app/jobs/scheduled/poll_mailbox.rb
+++ b/app/jobs/scheduled/poll_mailbox.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'net/pop'
+require "net/pop"
module Jobs
class PollMailbox < ::Jobs::Scheduled
@@ -43,26 +43,37 @@ module Jobs
process_popmail(mail_string)
p.delete if SiteSetting.pop3_polling_delete_from_server?
rescue => e
- Discourse.handle_job_exception(e, error_context(@args, "Failed to process incoming email."))
+ Discourse.handle_job_exception(
+ e,
+ error_context(@args, "Failed to process incoming email."),
+ )
end
end
rescue Net::OpenTimeout => e
count = Discourse.redis.incr(POLL_MAILBOX_TIMEOUT_ERROR_KEY).to_i
- Discourse.redis.expire(
- POLL_MAILBOX_TIMEOUT_ERROR_KEY,
- SiteSetting.pop3_polling_period_mins.minutes * 3
- ) if count == 1
+ if count == 1
+ Discourse.redis.expire(
+ POLL_MAILBOX_TIMEOUT_ERROR_KEY,
+ SiteSetting.pop3_polling_period_mins.minutes * 3,
+ )
+ end
if count > 3
Discourse.redis.del(POLL_MAILBOX_TIMEOUT_ERROR_KEY)
mark_as_errored!
- add_admin_dashboard_problem_message('dashboard.poll_pop3_timeout')
- Discourse.handle_job_exception(e, error_context(@args, "Connecting to '#{SiteSetting.pop3_polling_host}' for polling emails."))
+ add_admin_dashboard_problem_message("dashboard.poll_pop3_timeout")
+ Discourse.handle_job_exception(
+ e,
+ error_context(
+ @args,
+ "Connecting to '#{SiteSetting.pop3_polling_host}' for polling emails.",
+ ),
+ )
end
rescue Net::POPAuthenticationError => e
mark_as_errored!
- add_admin_dashboard_problem_message('dashboard.poll_pop3_auth_error')
+ add_admin_dashboard_problem_message("dashboard.poll_pop3_auth_error")
Discourse.handle_job_exception(e, error_context(@args, "Signing in to poll incoming emails."))
end
@@ -75,7 +86,7 @@ module Jobs
def mail_too_old?(mail_string)
mail = Mail.new(mail_string)
- date_header = mail.header['Date']
+ date_header = mail.header["Date"]
return false if date_header.blank?
date = Time.parse(date_header.to_s)
@@ -90,9 +101,8 @@ module Jobs
def add_admin_dashboard_problem_message(i18n_key)
AdminDashboardData.add_problem_message(
i18n_key,
- SiteSetting.pop3_polling_period_mins.minutes + 5.minutes
+ SiteSetting.pop3_polling_period_mins.minutes + 5.minutes,
)
end
-
end
end
diff --git a/app/jobs/scheduled/process_user_notification_schedules.rb b/app/jobs/scheduled/process_user_notification_schedules.rb
index 1e793e01f06..1f8bbe4f839 100644
--- a/app/jobs/scheduled/process_user_notification_schedules.rb
+++ b/app/jobs/scheduled/process_user_notification_schedules.rb
@@ -5,13 +5,19 @@ module Jobs
every 1.day
def execute(args)
- UserNotificationSchedule.enabled.includes(:user).each do |schedule|
- begin
- schedule.create_do_not_disturb_timings
- rescue => e
- Discourse.warn_exception(e, message: "Failed to process user_notification_schedule with ID #{schedule.id}")
+ UserNotificationSchedule
+ .enabled
+ .includes(:user)
+ .each do |schedule|
+ begin
+ schedule.create_do_not_disturb_timings
+ rescue => e
+ Discourse.warn_exception(
+ e,
+ message: "Failed to process user_notification_schedule with ID #{schedule.id}",
+ )
+ end
end
- end
end
end
end
diff --git a/app/jobs/scheduled/purge_deleted_uploads.rb b/app/jobs/scheduled/purge_deleted_uploads.rb
index 73c3de50544..ca5376e04f3 100644
--- a/app/jobs/scheduled/purge_deleted_uploads.rb
+++ b/app/jobs/scheduled/purge_deleted_uploads.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class PurgeDeletedUploads < ::Jobs::Scheduled
every 1.day
@@ -9,7 +8,5 @@ module Jobs
grace_period = SiteSetting.purge_deleted_uploads_grace_period_days
Discourse.store.purge_tombstone(grace_period)
end
-
end
-
end
diff --git a/app/jobs/scheduled/reindex_search.rb b/app/jobs/scheduled/reindex_search.rb
index 26215cdc7ae..db54093bad5 100644
--- a/app/jobs/scheduled/reindex_search.rb
+++ b/app/jobs/scheduled/reindex_search.rb
@@ -113,7 +113,11 @@ module Jobs
def load_problem_category_ids(limit)
Category
.joins("LEFT JOIN category_search_data ON category_id = categories.id")
- .where("category_search_data.locale IS NULL OR category_search_data.locale != ? OR category_search_data.version != ?", SiteSetting.default_locale, SearchIndexer::CATEGORY_INDEX_VERSION)
+ .where(
+ "category_search_data.locale IS NULL OR category_search_data.locale != ? OR category_search_data.version != ?",
+ SiteSetting.default_locale,
+ SearchIndexer::CATEGORY_INDEX_VERSION,
+ )
.order("categories.id ASC")
.limit(limit)
.pluck(:id)
@@ -122,7 +126,11 @@ module Jobs
def load_problem_tag_ids(limit)
Tag
.joins("LEFT JOIN tag_search_data ON tag_id = tags.id")
- .where("tag_search_data.locale IS NULL OR tag_search_data.locale != ? OR tag_search_data.version != ?", SiteSetting.default_locale, SearchIndexer::TAG_INDEX_VERSION)
+ .where(
+ "tag_search_data.locale IS NULL OR tag_search_data.locale != ? OR tag_search_data.version != ?",
+ SiteSetting.default_locale,
+ SearchIndexer::TAG_INDEX_VERSION,
+ )
.order("tags.id ASC")
.limit(limit)
.pluck(:id)
@@ -131,7 +139,11 @@ module Jobs
def load_problem_topic_ids(limit)
Topic
.joins("LEFT JOIN topic_search_data ON topic_id = topics.id")
- .where("topic_search_data.locale IS NULL OR topic_search_data.locale != ? OR topic_search_data.version != ?", SiteSetting.default_locale, SearchIndexer::TOPIC_INDEX_VERSION)
+ .where(
+ "topic_search_data.locale IS NULL OR topic_search_data.locale != ? OR topic_search_data.version != ?",
+ SiteSetting.default_locale,
+ SearchIndexer::TOPIC_INDEX_VERSION,
+ )
.order("topics.id DESC")
.limit(limit)
.pluck(:id)
@@ -143,7 +155,11 @@ module Jobs
.joins("LEFT JOIN post_search_data ON post_id = posts.id")
.where("posts.raw != ''")
.where("topics.deleted_at IS NULL")
- .where("post_search_data.locale IS NULL OR post_search_data.locale != ? OR post_search_data.version != ?", SiteSetting.default_locale, SearchIndexer::POST_INDEX_VERSION)
+ .where(
+ "post_search_data.locale IS NULL OR post_search_data.locale != ? OR post_search_data.version != ?",
+ SiteSetting.default_locale,
+ SearchIndexer::POST_INDEX_VERSION,
+ )
.order("posts.id DESC")
.limit(limit)
.pluck(:id)
@@ -152,11 +168,14 @@ module Jobs
def load_problem_user_ids(limit)
User
.joins("LEFT JOIN user_search_data ON user_id = users.id")
- .where("user_search_data.locale IS NULL OR user_search_data.locale != ? OR user_search_data.version != ?", SiteSetting.default_locale, SearchIndexer::USER_INDEX_VERSION)
+ .where(
+ "user_search_data.locale IS NULL OR user_search_data.locale != ? OR user_search_data.version != ?",
+ SiteSetting.default_locale,
+ SearchIndexer::USER_INDEX_VERSION,
+ )
.order("users.id ASC")
.limit(limit)
.pluck(:id)
end
-
end
end
diff --git a/app/jobs/scheduled/reviewable_priorities.rb b/app/jobs/scheduled/reviewable_priorities.rb
index b9c5e4c8b55..55c54ba78c8 100644
--- a/app/jobs/scheduled/reviewable_priorities.rb
+++ b/app/jobs/scheduled/reviewable_priorities.rb
@@ -18,7 +18,9 @@ class Jobs::ReviewablePriorities < ::Jobs::Scheduled
reviewable_count = Reviewable.approved.where("score > ?", min_priority_threshold).count
return if reviewable_count < self.class.min_reviewables
- res = DB.query_single(<<~SQL, target_count: self.class.target_count, min_priority: min_priority_threshold)
+ res =
+ DB.query_single(
+ <<~SQL,
SELECT COALESCE(PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY score), 0.0) AS medium,
COALESCE(PERCENTILE_DISC(0.85) WITHIN GROUP (ORDER BY score), 0.0) AS high
FROM (
@@ -30,15 +32,14 @@ class Jobs::ReviewablePriorities < ::Jobs::Scheduled
HAVING COUNT(*) >= :target_count
) AS x
SQL
+ target_count: self.class.target_count,
+ min_priority: min_priority_threshold,
+ )
return unless res && res.size == 2
medium, high = res
- Reviewable.set_priorities(
- low: min_priority_threshold,
- medium: medium,
- high: high
- )
+ Reviewable.set_priorities(low: min_priority_threshold, medium: medium, high: high)
end
end
diff --git a/app/jobs/scheduled/schedule_backup.rb b/app/jobs/scheduled/schedule_backup.rb
index 703a4515c47..a4e0bcb8939 100644
--- a/app/jobs/scheduled/schedule_backup.rb
+++ b/app/jobs/scheduled/schedule_backup.rb
@@ -30,7 +30,7 @@ module Jobs
Discourse.system_user,
:backup_failed,
target_group_names: Group[:admins].name,
- logs: "#{ex}\n" + ex.backtrace.join("\n")
+ logs: "#{ex}\n" + ex.backtrace.join("\n"),
)
end
end
diff --git a/app/jobs/scheduled/tl3_promotions.rb b/app/jobs/scheduled/tl3_promotions.rb
index af1d6350ff4..9de8f711d43 100644
--- a/app/jobs/scheduled/tl3_promotions.rb
+++ b/app/jobs/scheduled/tl3_promotions.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
class Tl3Promotions < ::Jobs::Scheduled
daily at: 4.hours
@@ -9,40 +8,40 @@ module Jobs
if SiteSetting.default_trust_level < 3
# Demotions
demoted_user_ids = []
- User.real
- .joins("LEFT JOIN (SELECT gu.user_id, MAX(g.grant_trust_level) AS group_granted_trust_level FROM groups g, group_users gu WHERE g.id = gu.group_id GROUP BY gu.user_id) tl ON users.id = tl.user_id")
- .where(
- trust_level: TrustLevel[3],
- manual_locked_trust_level: nil
+ User
+ .real
+ .joins(
+ "LEFT JOIN (SELECT gu.user_id, MAX(g.grant_trust_level) AS group_granted_trust_level FROM groups g, group_users gu WHERE g.id = gu.group_id GROUP BY gu.user_id) tl ON users.id = tl.user_id",
+ )
+ .where(trust_level: TrustLevel[3], manual_locked_trust_level: nil)
+ .where(
+ "group_granted_trust_level IS NULL OR group_granted_trust_level < ?",
+ TrustLevel[3],
)
- .where("group_granted_trust_level IS NULL OR group_granted_trust_level < ?", TrustLevel[3])
.find_each do |u|
- # Don't demote too soon after being promoted
- next if u.on_tl3_grace_period?
+ # Don't demote too soon after being promoted
+ next if u.on_tl3_grace_period?
- if Promotion.tl3_lost?(u)
- demoted_user_ids << u.id
- Promotion.new(u).change_trust_level!(TrustLevel[2])
+ if Promotion.tl3_lost?(u)
+ demoted_user_ids << u.id
+ Promotion.new(u).change_trust_level!(TrustLevel[2])
+ end
end
- end
end
# Promotions
- User.real.not_suspended.where(
- trust_level: TrustLevel[2],
- manual_locked_trust_level: nil
- ).where.not(id: demoted_user_ids)
+ User
+ .real
+ .not_suspended
+ .where(trust_level: TrustLevel[2], manual_locked_trust_level: nil)
+ .where.not(id: demoted_user_ids)
.joins(:user_stat)
.where("user_stats.days_visited >= ?", SiteSetting.tl3_requires_days_visited)
.where("user_stats.topics_entered >= ?", SiteSetting.tl3_requires_topics_viewed_all_time)
.where("user_stats.posts_read_count >= ?", SiteSetting.tl3_requires_posts_read_all_time)
.where("user_stats.likes_given >= ?", SiteSetting.tl3_requires_likes_given)
.where("user_stats.likes_received >= ?", SiteSetting.tl3_requires_likes_received)
- .find_each do |u|
- Promotion.new(u).review_tl2
- end
-
+ .find_each { |u| Promotion.new(u).review_tl2 }
end
end
-
end
diff --git a/app/jobs/scheduled/topic_timer_enqueuer.rb b/app/jobs/scheduled/topic_timer_enqueuer.rb
index 67204c4200c..13322184e66 100644
--- a/app/jobs/scheduled/topic_timer_enqueuer.rb
+++ b/app/jobs/scheduled/topic_timer_enqueuer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
# Runs periodically to look through topic timers that are ready to execute,
# and enqueues their related jobs.
#
@@ -13,13 +12,15 @@ module Jobs
def execute(_args = nil)
TopicTimer.pending_timers.find_each do |timer|
-
# the typed job may not enqueue if it has already
# been scheduled with enqueue_at
begin
timer.enqueue_typed_job
rescue => err
- Discourse.warn_exception(err, message: "Error when attempting to enqueue topic timer job for timer #{timer.id}")
+ Discourse.warn_exception(
+ err,
+ message: "Error when attempting to enqueue topic timer job for timer #{timer.id}",
+ )
end
end
end
diff --git a/app/jobs/scheduled/unsilence_users.rb b/app/jobs/scheduled/unsilence_users.rb
index f6f5f5e0ff4..dbf0a907951 100644
--- a/app/jobs/scheduled/unsilence_users.rb
+++ b/app/jobs/scheduled/unsilence_users.rb
@@ -5,9 +5,9 @@ module Jobs
every 15.minutes
def execute(args)
- User.where("silenced_till IS NOT NULL AND silenced_till < now()").find_each do |user|
- UserSilencer.unsilence(user, Discourse.system_user)
- end
+ User
+ .where("silenced_till IS NOT NULL AND silenced_till < now()")
+ .find_each { |user| UserSilencer.unsilence(user, Discourse.system_user) }
end
end
end
diff --git a/app/jobs/scheduled/update_animated_uploads.rb b/app/jobs/scheduled/update_animated_uploads.rb
index 500e21d7b16..51ea6204a4f 100644
--- a/app/jobs/scheduled/update_animated_uploads.rb
+++ b/app/jobs/scheduled/update_animated_uploads.rb
@@ -12,11 +12,11 @@ module Jobs
.where(animated: nil)
.limit(MAX_PROCESSED_GIF_IMAGES)
.each do |upload|
- uri = Discourse.store.path_for(upload) || upload.url
- upload.animated = FastImage.animated?(uri)
- upload.save(validate: false)
- upload.optimized_images.destroy_all if upload.animated
- end
+ uri = Discourse.store.path_for(upload) || upload.url
+ upload.animated = FastImage.animated?(uri)
+ upload.save(validate: false)
+ upload.optimized_images.destroy_all if upload.animated
+ end
nil
end
diff --git a/app/jobs/scheduled/version_check.rb b/app/jobs/scheduled/version_check.rb
index 37eebf01f9e..6df0e103f82 100644
--- a/app/jobs/scheduled/version_check.rb
+++ b/app/jobs/scheduled/version_check.rb
@@ -5,25 +5,23 @@ module Jobs
every 1.day
def execute(args)
- if SiteSetting.version_checks? && (DiscourseUpdates.updated_at.nil? || DiscourseUpdates.updated_at < (1.minute.ago))
+ if SiteSetting.version_checks? &&
+ (DiscourseUpdates.updated_at.nil? || DiscourseUpdates.updated_at < (1.minute.ago))
begin
prev_missing_versions_count = DiscourseUpdates.missing_versions_count || 0
json = DiscourseHub.discourse_version_check
DiscourseUpdates.last_installed_version = Discourse::VERSION::STRING
- DiscourseUpdates.latest_version = json['latestVersion']
- DiscourseUpdates.critical_updates_available = json['criticalUpdates']
- DiscourseUpdates.missing_versions_count = json['missingVersionsCount']
+ DiscourseUpdates.latest_version = json["latestVersion"]
+ DiscourseUpdates.critical_updates_available = json["criticalUpdates"]
+ DiscourseUpdates.missing_versions_count = json["missingVersionsCount"]
DiscourseUpdates.updated_at = Time.zone.now
- DiscourseUpdates.missing_versions = json['versions']
-
- if SiteSetting.new_version_emails &&
- json['missingVersionsCount'] > (0) &&
- prev_missing_versions_count < (json['missingVersionsCount'].to_i)
+ DiscourseUpdates.missing_versions = json["versions"]
+ if SiteSetting.new_version_emails && json["missingVersionsCount"] > (0) &&
+ prev_missing_versions_count < (json["missingVersionsCount"].to_i)
message = VersionMailer.send_notice
Email::Sender.new(message, :new_version).send
-
end
rescue => e
raise e unless Rails.env.development? # Fail version check silently in development mode
@@ -31,6 +29,5 @@ module Jobs
end
true
end
-
end
end
diff --git a/app/jobs/scheduled/weekly.rb b/app/jobs/scheduled/weekly.rb
index a020fa11f1d..ae023bdc343 100644
--- a/app/jobs/scheduled/weekly.rb
+++ b/app/jobs/scheduled/weekly.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Jobs
-
# This job will run on a regular basis to update statistics and denormalized data.
# If it does not run, the site will not function properly.
class Weekly < ::Jobs::Scheduled
diff --git a/app/mailers/admin_confirmation_mailer.rb b/app/mailers/admin_confirmation_mailer.rb
index 9b6ffa2409c..2cc20258db2 100644
--- a/app/mailers/admin_confirmation_mailer.rb
+++ b/app/mailers/admin_confirmation_mailer.rb
@@ -6,10 +6,10 @@ class AdminConfirmationMailer < ActionMailer::Base
def send_email(to_address, target_email, target_username, token)
build_email(
to_address,
- template: 'admin_confirmation_mailer',
+ template: "admin_confirmation_mailer",
target_email: target_email,
target_username: target_username,
- admin_confirm_url: confirm_admin_url(token: token, host: Discourse.base_url)
+ admin_confirm_url: confirm_admin_url(token: token, host: Discourse.base_url),
)
end
end
diff --git a/app/mailers/download_backup_mailer.rb b/app/mailers/download_backup_mailer.rb
index 62d5e583684..be0b26ffede 100644
--- a/app/mailers/download_backup_mailer.rb
+++ b/app/mailers/download_backup_mailer.rb
@@ -4,6 +4,6 @@ class DownloadBackupMailer < ActionMailer::Base
include Email::BuildEmailHelper
def send_email(to_address, backup_file_path)
- build_email(to_address, template: 'download_backup_mailer', backup_file_path: backup_file_path)
+ build_email(to_address, template: "download_backup_mailer", backup_file_path: backup_file_path)
end
end
diff --git a/app/mailers/group_smtp_mailer.rb b/app/mailers/group_smtp_mailer.rb
index c394439026a..5d0fe11f7ad 100644
--- a/app/mailers/group_smtp_mailer.rb
+++ b/app/mailers/group_smtp_mailer.rb
@@ -4,7 +4,7 @@ class GroupSmtpMailer < ActionMailer::Base
include Email::BuildEmailHelper
def send_mail(from_group, to_address, post, cc_addresses: nil, bcc_addresses: nil)
- raise 'SMTP is disabled' if !SiteSetting.enable_smtp
+ raise "SMTP is disabled" if !SiteSetting.enable_smtp
op_incoming_email = post.topic.first_post.incoming_email
recipient_user = User.find_by_email(to_address, primary: true)
@@ -17,7 +17,7 @@ class GroupSmtpMailer < ActionMailer::Base
password: from_group.email_password,
authentication: GlobalSetting.smtp_authentication,
enable_starttls_auto: from_group.smtp_ssl,
- return_response: true
+ return_response: true,
}
group_name = from_group.name_full_preferred
@@ -37,17 +37,17 @@ class GroupSmtpMailer < ActionMailer::Base
private_reply: post.topic.private_message?,
participants: UserNotifications.participants(post, recipient_user, reveal_staged_email: true),
include_respond_instructions: true,
- template: 'user_notifications.user_posted_pm',
+ template: "user_notifications.user_posted_pm",
use_topic_title_subject: true,
topic_title: op_incoming_email&.subject || post.topic.title,
add_re_to_subject: true,
locale: SiteSetting.default_locale,
delivery_method_options: delivery_options,
from: from_group.smtp_from_address,
- from_alias: I18n.t('email_from_without_site', group_name: group_name),
+ from_alias: I18n.t("email_from_without_site", group_name: group_name),
html_override: html_override(post),
cc: cc_addresses,
- bcc: bcc_addresses
+ bcc: bcc_addresses,
)
end
@@ -55,7 +55,7 @@ class GroupSmtpMailer < ActionMailer::Base
def html_override(post)
UserNotificationRenderer.render(
- template: 'email/notification',
+ template: "email/notification",
format: :html,
locals: {
context_posts: nil,
@@ -63,9 +63,9 @@ class GroupSmtpMailer < ActionMailer::Base
post: post,
in_reply_to_post: nil,
classes: Rtl.new(nil).css_class,
- first_footer_classes: '',
- reply_above_line: true
- }
+ first_footer_classes: "",
+ reply_above_line: true,
+ },
)
end
end
diff --git a/app/mailers/invite_mailer.rb b/app/mailers/invite_mailer.rb
index 6f7fee63468..f11883761ae 100644
--- a/app/mailers/invite_mailer.rb
+++ b/app/mailers/invite_mailer.rb
@@ -3,7 +3,7 @@
class InviteMailer < ActionMailer::Base
include Email::BuildEmailHelper
- layout 'email_template'
+ layout "email_template"
def send_invite(invite, invite_to_topic: false)
# Find the first topic they were invited to
@@ -15,16 +15,20 @@ class InviteMailer < ActionMailer::Base
inviter_name = "#{invite.invited_by.name} (#{invite.invited_by.username})"
end
- sanitized_message = invite.custom_message.present? ?
- ActionView::Base.full_sanitizer.sanitize(invite.custom_message.gsub(/\n+/, " ").strip) : nil
+ sanitized_message =
+ (
+ if invite.custom_message.present?
+ ActionView::Base.full_sanitizer.sanitize(invite.custom_message.gsub(/\n+/, " ").strip)
+ else
+ nil
+ end
+ )
# If they were invited to a topic
if invite_to_topic && first_topic.present?
# get topic excerpt
topic_excerpt = ""
- if first_topic.excerpt
- topic_excerpt = first_topic.excerpt.tr("\n", " ")
- end
+ topic_excerpt = first_topic.excerpt.tr("\n", " ") if first_topic.excerpt
topic_title = first_topic.try(:title)
if SiteSetting.private_email?
@@ -32,35 +36,41 @@ class InviteMailer < ActionMailer::Base
topic_excerpt = ""
end
- build_email(invite.email,
- template: sanitized_message ? 'custom_invite_mailer' : 'invite_mailer',
- inviter_name: inviter_name,
- site_domain_name: Discourse.current_hostname,
- invite_link: invite.link(with_email_token: true),
- topic_title: topic_title,
- topic_excerpt: topic_excerpt,
- site_description: SiteSetting.site_description,
- site_title: SiteSetting.title,
- user_custom_message: sanitized_message)
+ build_email(
+ invite.email,
+ template: sanitized_message ? "custom_invite_mailer" : "invite_mailer",
+ inviter_name: inviter_name,
+ site_domain_name: Discourse.current_hostname,
+ invite_link: invite.link(with_email_token: true),
+ topic_title: topic_title,
+ topic_excerpt: topic_excerpt,
+ site_description: SiteSetting.site_description,
+ site_title: SiteSetting.title,
+ user_custom_message: sanitized_message,
+ )
else
- build_email(invite.email,
- template: sanitized_message ? 'custom_invite_forum_mailer' : 'invite_forum_mailer',
- inviter_name: inviter_name,
- site_domain_name: Discourse.current_hostname,
- invite_link: invite.link(with_email_token: true),
- site_description: SiteSetting.site_description,
- site_title: SiteSetting.title,
- user_custom_message: sanitized_message)
+ build_email(
+ invite.email,
+ template: sanitized_message ? "custom_invite_forum_mailer" : "invite_forum_mailer",
+ inviter_name: inviter_name,
+ site_domain_name: Discourse.current_hostname,
+ invite_link: invite.link(with_email_token: true),
+ site_description: SiteSetting.site_description,
+ site_title: SiteSetting.title,
+ user_custom_message: sanitized_message,
+ )
end
end
def send_password_instructions(user)
if user.present?
- email_token = user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:password_reset])
- build_email(user.email,
- template: 'invite_password_instructions',
- email_token: email_token.token)
+ email_token =
+ user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:password_reset])
+ build_email(
+ user.email,
+ template: "invite_password_instructions",
+ email_token: email_token.token,
+ )
end
end
-
end
diff --git a/app/mailers/rejection_mailer.rb b/app/mailers/rejection_mailer.rb
index ecbf56fbf46..0178a97b2b7 100644
--- a/app/mailers/rejection_mailer.rb
+++ b/app/mailers/rejection_mailer.rb
@@ -1,27 +1,29 @@
# frozen_string_literal: true
-require 'email/message_builder'
+require "email/message_builder"
class RejectionMailer < ActionMailer::Base
include Email::BuildEmailHelper
- DISALLOWED_TEMPLATE_ARGS = [:to,
- :from,
- :base_url,
- :user_preferences_url,
- :include_respond_instructions,
- :html_override,
- :add_unsubscribe_link,
- :respond_instructions,
- :style,
- :body,
- :post_id,
- :topic_id,
- :subject,
- :template,
- :allow_reply_by_email,
- :private_reply,
- :from_alias]
+ DISALLOWED_TEMPLATE_ARGS = %i[
+ to
+ from
+ base_url
+ user_preferences_url
+ include_respond_instructions
+ html_override
+ add_unsubscribe_link
+ respond_instructions
+ style
+ body
+ post_id
+ topic_id
+ subject
+ template
+ allow_reply_by_email
+ private_reply
+ from_alias
+ ]
# Send an email rejection message.
#
@@ -32,10 +34,9 @@ class RejectionMailer < ActionMailer::Base
# BuildEmailHelper. You can see the list in DISALLOWED_TEMPLATE_ARGS.
def send_rejection(template, message_from, template_args)
if template_args.keys.any? { |k| DISALLOWED_TEMPLATE_ARGS.include? k }
- raise ArgumentError.new('Reserved key in template arguments')
+ raise ArgumentError.new("Reserved key in template arguments")
end
build_email(message_from, template_args.merge(template: "system_messages.#{template}"))
end
-
end
diff --git a/app/mailers/subscription_mailer.rb b/app/mailers/subscription_mailer.rb
index c2c40752c84..57d4489ac58 100644
--- a/app/mailers/subscription_mailer.rb
+++ b/app/mailers/subscription_mailer.rb
@@ -9,6 +9,7 @@ class SubscriptionMailer < ActionMailer::Base
template: "unsubscribe_mailer",
site_title: SiteSetting.title,
site_domain_name: Discourse.current_hostname,
- confirm_unsubscribe_link: email_unsubscribe_url(unsubscribe_key, host: Discourse.base_url)
+ confirm_unsubscribe_link:
+ email_unsubscribe_url(unsubscribe_key, host: Discourse.base_url)
end
end
diff --git a/app/mailers/test_mailer.rb b/app/mailers/test_mailer.rb
index 4abd75263a7..4c561e648aa 100644
--- a/app/mailers/test_mailer.rb
+++ b/app/mailers/test_mailer.rb
@@ -4,6 +4,6 @@ class TestMailer < ActionMailer::Base
include Email::BuildEmailHelper
def send_test(to_address, opts = {})
- build_email(to_address, template: 'test_mailer', **opts)
+ build_email(to_address, template: "test_mailer", **opts)
end
end
diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb
index 3aca5a93346..d5580858274 100644
--- a/app/mailers/user_notifications.rb
+++ b/app/mailers/user_notifications.rb
@@ -4,37 +4,38 @@ class UserNotifications < ActionMailer::Base
include UserNotificationsHelper
include ApplicationHelper
helper :application, :email
- default charset: 'UTF-8'
- layout 'email_template'
+ default charset: "UTF-8"
+ layout "email_template"
include Email::BuildEmailHelper
def signup(user, opts = {})
- build_user_email_token_by_template(
- "user_notifications.signup",
- user,
- opts[:email_token]
- )
+ build_user_email_token_by_template("user_notifications.signup", user, opts[:email_token])
end
def activation_reminder(user, opts = {})
build_user_email_token_by_template(
"user_notifications.activation_reminder",
user,
- opts[:email_token]
+ opts[:email_token],
)
end
def signup_after_approval(user, opts = {})
locale = user_locale(user)
- tips = I18n.t('system_messages.usage_tips.text_body_template',
- base_url: Discourse.base_url,
- locale: locale)
+ tips =
+ I18n.t(
+ "system_messages.usage_tips.text_body_template",
+ base_url: Discourse.base_url,
+ locale: locale,
+ )
- build_email(user.email,
- template: 'user_notifications.signup_after_approval',
- locale: locale,
- new_user_tips: tips)
+ build_email(
+ user.email,
+ template: "user_notifications.signup_after_approval",
+ locale: locale,
+ new_user_tips: tips,
+ )
end
def post_approved(user, opts = {})
@@ -43,20 +44,23 @@ class UserNotifications < ActionMailer::Base
return if post_url.nil?
locale = user_locale(user)
- build_email(user.email,
- template: 'user_notifications.post_approved',
+ build_email(
+ user.email,
+ template: "user_notifications.post_approved",
locale: locale,
base_url: Discourse.base_url,
- post_url: post_url
+ post_url: post_url,
)
end
def signup_after_reject(user, opts = {})
locale = user_locale(user)
- build_email(user.email,
- template: 'user_notifications.signup_after_reject',
- locale: locale,
- reject_reason: opts[:reject_reason])
+ build_email(
+ user.email,
+ template: "user_notifications.signup_after_reject",
+ locale: locale,
+ reject_reason: opts[:reject_reason],
+ )
end
def suspicious_login(user, opts = {})
@@ -71,32 +75,36 @@ class UserNotifications < ActionMailer::Base
template: "user_notifications.suspicious_login",
locale: user_locale(user),
client_ip: opts[:client_ip],
- location: location.present? ? location : I18n.t('staff_action_logs.unknown'),
+ location: location.present? ? location : I18n.t("staff_action_logs.unknown"),
browser: I18n.t("user_auth_tokens.browser.#{browser}"),
device: I18n.t("user_auth_tokens.device.#{device}"),
- os: I18n.t("user_auth_tokens.os.#{os}")
+ os: I18n.t("user_auth_tokens.os.#{os}"),
)
end
def notify_old_email(user, opts = {})
- build_email(user.email,
- template: "user_notifications.notify_old_email",
- locale: user_locale(user),
- new_email: opts[:new_email])
+ build_email(
+ user.email,
+ template: "user_notifications.notify_old_email",
+ locale: user_locale(user),
+ new_email: opts[:new_email],
+ )
end
def notify_old_email_add(user, opts = {})
- build_email(user.email,
- template: "user_notifications.notify_old_email_add",
- locale: user_locale(user),
- new_email: opts[:new_email])
+ build_email(
+ user.email,
+ template: "user_notifications.notify_old_email_add",
+ locale: user_locale(user),
+ new_email: opts[:new_email],
+ )
end
def confirm_old_email(user, opts = {})
build_user_email_token_by_template(
"user_notifications.confirm_old_email",
user,
- opts[:email_token]
+ opts[:email_token],
)
end
@@ -104,15 +112,21 @@ class UserNotifications < ActionMailer::Base
build_user_email_token_by_template(
"user_notifications.confirm_old_email_add",
user,
- opts[:email_token]
+ opts[:email_token],
)
end
def confirm_new_email(user, opts = {})
build_user_email_token_by_template(
- opts[:requested_by_admin] ? "user_notifications.confirm_new_email_via_admin" : "user_notifications.confirm_new_email",
+ (
+ if opts[:requested_by_admin]
+ "user_notifications.confirm_new_email_via_admin"
+ else
+ "user_notifications.confirm_new_email"
+ end
+ ),
user,
- opts[:email_token]
+ opts[:email_token],
)
end
@@ -120,31 +134,23 @@ class UserNotifications < ActionMailer::Base
build_user_email_token_by_template(
user.has_password? ? "user_notifications.forgot_password" : "user_notifications.set_password",
user,
- opts[:email_token]
+ opts[:email_token],
)
end
def email_login(user, opts = {})
- build_user_email_token_by_template(
- "user_notifications.email_login",
- user,
- opts[:email_token]
- )
+ build_user_email_token_by_template("user_notifications.email_login", user, opts[:email_token])
end
def admin_login(user, opts = {})
- build_user_email_token_by_template(
- "user_notifications.admin_login",
- user,
- opts[:email_token]
- )
+ build_user_email_token_by_template("user_notifications.admin_login", user, opts[:email_token])
end
def account_created(user, opts = {})
build_user_email_token_by_template(
"user_notifications.account_created",
user,
- opts[:email_token]
+ opts[:email_token],
)
end
@@ -158,7 +164,7 @@ class UserNotifications < ActionMailer::Base
user.email,
template: "user_notifications.account_silenced_forever",
locale: user_locale(user),
- reason: user_history.details
+ reason: user_history.details,
)
else
silenced_till = user.silenced_till.in_time_zone(user.user_option.timezone)
@@ -167,7 +173,7 @@ class UserNotifications < ActionMailer::Base
template: "user_notifications.account_silenced",
locale: user_locale(user),
reason: user_history.details,
- silenced_till: I18n.l(silenced_till, format: :long)
+ silenced_till: I18n.l(silenced_till, format: :long),
)
end
end
@@ -182,7 +188,7 @@ class UserNotifications < ActionMailer::Base
user.email,
template: "user_notifications.account_suspended_forever",
locale: user_locale(user),
- reason: user_history.details
+ reason: user_history.details,
)
else
suspended_till = user.suspended_till.in_time_zone(user.user_option.timezone)
@@ -191,7 +197,7 @@ class UserNotifications < ActionMailer::Base
template: "user_notifications.account_suspended",
locale: user_locale(user),
reason: user_history.details,
- suspended_till: I18n.l(suspended_till, format: :long)
+ suspended_till: I18n.l(suspended_till, format: :long),
)
end
end
@@ -199,18 +205,18 @@ class UserNotifications < ActionMailer::Base
def account_exists(user, opts = {})
build_email(
user.email,
- template: 'user_notifications.account_exists',
+ template: "user_notifications.account_exists",
locale: user_locale(user),
- email: user.email
+ email: user.email,
)
end
def account_second_factor_disabled(user, opts = {})
build_email(
user.email,
- template: 'user_notifications.account_second_factor_disabled',
+ template: "user_notifications.account_second_factor_disabled",
locale: user_locale(user),
- email: user.email
+ email: user.email,
)
end
@@ -221,34 +227,59 @@ class UserNotifications < ActionMailer::Base
min_date = opts[:since] || user.last_emailed_at || user.last_seen_at || 1.month.ago
# Fetch some topics and posts to show
- digest_opts = { limit: SiteSetting.digest_topics + SiteSetting.digest_other_topics, top_order: true }
+ digest_opts = {
+ limit: SiteSetting.digest_topics + SiteSetting.digest_other_topics,
+ top_order: true,
+ }
topics_for_digest = Topic.for_digest(user, min_date, digest_opts).to_a
if topics_for_digest.empty? && !user.user_option.try(:include_tl0_in_digests)
# Find some topics from new users that are at least 24 hours old
- topics_for_digest = Topic.for_digest(user, min_date, digest_opts.merge(include_tl0: true)).where('topics.created_at < ?', 24.hours.ago).to_a
+ topics_for_digest =
+ Topic
+ .for_digest(user, min_date, digest_opts.merge(include_tl0: true))
+ .where("topics.created_at < ?", 24.hours.ago)
+ .to_a
end
@popular_topics = topics_for_digest[0, SiteSetting.digest_topics]
if @popular_topics.present?
- @other_new_for_you = topics_for_digest.size > SiteSetting.digest_topics ? topics_for_digest[SiteSetting.digest_topics..-1] : []
+ @other_new_for_you =
+ (
+ if topics_for_digest.size > SiteSetting.digest_topics
+ topics_for_digest[SiteSetting.digest_topics..-1]
+ else
+ []
+ end
+ )
- @popular_posts = if SiteSetting.digest_posts > 0
- Post.order("posts.score DESC")
- .for_mailing_list(user, min_date)
- .where('posts.post_type = ?', Post.types[:regular])
- .where('posts.deleted_at IS NULL AND posts.hidden = false AND posts.user_deleted = false')
- .where("posts.post_number > ? AND posts.score > ?", 1, ScoreCalculator.default_score_weights[:like_score] * 5.0)
- .where('posts.created_at < ?', (SiteSetting.editing_grace_period || 0).seconds.ago)
- .limit(SiteSetting.digest_posts)
- else
- []
- end
+ @popular_posts =
+ if SiteSetting.digest_posts > 0
+ Post
+ .order("posts.score DESC")
+ .for_mailing_list(user, min_date)
+ .where("posts.post_type = ?", Post.types[:regular])
+ .where(
+ "posts.deleted_at IS NULL AND posts.hidden = false AND posts.user_deleted = false",
+ )
+ .where(
+ "posts.post_number > ? AND posts.score > ?",
+ 1,
+ ScoreCalculator.default_score_weights[:like_score] * 5.0,
+ )
+ .where("posts.created_at < ?", (SiteSetting.editing_grace_period || 0).seconds.ago)
+ .limit(SiteSetting.digest_posts)
+ else
+ []
+ end
@excerpts = {}
@popular_topics.map do |t|
- @excerpts[t.first_post.id] = email_excerpt(t.first_post.cooked, t.first_post) if t.first_post.present?
+ @excerpts[t.first_post.id] = email_excerpt(
+ t.first_post.cooked,
+ t.first_post,
+ ) if t.first_post.present?
end
# Try to find 3 interesting stats for the top of the digest
@@ -258,33 +289,60 @@ class UserNotifications < ActionMailer::Base
# We used topics from new users instead, so count should match
new_topics_count = topics_for_digest.size
end
- @counts = [{ label_key: 'user_notifications.digest.new_topics',
- value: new_topics_count,
- href: "#{Discourse.base_url}/new" }]
+ @counts = [
+ {
+ label_key: "user_notifications.digest.new_topics",
+ value: new_topics_count,
+ href: "#{Discourse.base_url}/new",
+ },
+ ]
# totalling unread notifications (which are low-priority only) and unread
# PMs and bookmark reminder notifications, so the total is both unread low
# and high priority PMs
value = user.unread_notifications + user.unread_high_priority_notifications
- @counts << { label_key: 'user_notifications.digest.unread_notifications', value: value, href: "#{Discourse.base_url}/my/notifications" } if value > 0
+ if value > 0
+ @counts << {
+ label_key: "user_notifications.digest.unread_notifications",
+ value: value,
+ href: "#{Discourse.base_url}/my/notifications",
+ }
+ end
if @counts.size < 3
value = user.unread_notifications_of_type(Notification.types[:liked])
- @counts << { label_key: 'user_notifications.digest.liked_received', value: value, href: "#{Discourse.base_url}/my/notifications" } if value > 0
+ if value > 0
+ @counts << {
+ label_key: "user_notifications.digest.liked_received",
+ value: value,
+ href: "#{Discourse.base_url}/my/notifications",
+ }
+ end
end
if @counts.size < 3 && user.user_option.digest_after_minutes.to_i >= 1440
value = summary_new_users_count(min_date)
- @counts << { label_key: 'user_notifications.digest.new_users', value: value, href: "#{Discourse.base_url}/about" } if value > 0
+ if value > 0
+ @counts << {
+ label_key: "user_notifications.digest.new_users",
+ value: value,
+ href: "#{Discourse.base_url}/about",
+ }
+ end
end
@last_seen_at = short_date(user.last_seen_at || user.created_at)
- @preheader_text = I18n.t('user_notifications.digest.preheader', last_seen_at: @last_seen_at)
+ @preheader_text = I18n.t("user_notifications.digest.preheader", last_seen_at: @last_seen_at)
opts = {
- from_alias: I18n.t('user_notifications.digest.from', site_name: Email.site_title),
- subject: I18n.t('user_notifications.digest.subject_template', email_prefix: @email_prefix, date: short_date(Time.now)),
+ from_alias: I18n.t("user_notifications.digest.from", site_name: Email.site_title),
+ subject:
+ I18n.t(
+ "user_notifications.digest.subject_template",
+ email_prefix: @email_prefix,
+ date: short_date(Time.now),
+ ),
add_unsubscribe_link: true,
unsubscribe_url: "#{Discourse.base_url}/email/unsubscribe/#{@unsubscribe_key}",
}
@@ -351,7 +409,7 @@ class UserNotifications < ActionMailer::Base
opts[:show_group_in_subject] = true if SiteSetting.group_in_subject
# We use the 'user_posted' event when you are emailed a post in a PM.
- opts[:notification_type] = 'posted'
+ opts[:notification_type] = "posted"
notification_email(user, opts)
end
@@ -400,29 +458,33 @@ class UserNotifications < ActionMailer::Base
def email_post_markdown(post, add_posted_by = false)
result = +"#{post.raw}\n\n"
if add_posted_by
- result << "#{I18n.t('user_notifications.posted_by', username: post.username, post_date: post.created_at.strftime("%m/%d/%Y"))}\n\n"
+ result << "#{I18n.t("user_notifications.posted_by", username: post.username, post_date: post.created_at.strftime("%m/%d/%Y"))}\n\n"
end
result
end
def self.get_context_posts(post, topic_user, user)
if (user.user_option.email_previous_replies == UserOption.previous_replies_type[:never]) ||
- SiteSetting.private_email?
+ SiteSetting.private_email?
return []
end
allowed_post_types = [Post.types[:regular]]
allowed_post_types << Post.types[:whisper] if topic_user.try(:user).try(:staff?)
- context_posts = Post.where(topic_id: post.topic_id)
- .where("post_number < ?", post.post_number)
- .where(user_deleted: false)
- .where(hidden: false)
- .where(post_type: allowed_post_types)
- .order('created_at desc')
- .limit(SiteSetting.email_posts_context)
+ context_posts =
+ Post
+ .where(topic_id: post.topic_id)
+ .where("post_number < ?", post.post_number)
+ .where(user_deleted: false)
+ .where(hidden: false)
+ .where(post_type: allowed_post_types)
+ .order("created_at desc")
+ .limit(SiteSetting.email_posts_context)
- if topic_user && topic_user.last_emailed_post_number && user.user_option.email_previous_replies == UserOption.previous_replies_type[:unless_emailed]
+ if topic_user && topic_user.last_emailed_post_number &&
+ user.user_option.email_previous_replies ==
+ UserOption.previous_replies_type[:unless_emailed]
context_posts = context_posts.where("post_number > ?", topic_user.last_emailed_post_number)
end
@@ -435,9 +497,7 @@ class UserNotifications < ActionMailer::Base
post = opts[:post]
unless String === notification_type
- if Numeric === notification_type
- notification_type = Notification.types[notification_type]
- end
+ notification_type = Notification.types[notification_type] if Numeric === notification_type
notification_type = notification_type.to_s
end
@@ -449,13 +509,16 @@ class UserNotifications < ActionMailer::Base
end
allow_reply_by_email = opts[:allow_reply_by_email] unless user.suspended?
- original_username = notification_data[:original_username] || notification_data[:display_username]
+ original_username =
+ notification_data[:original_username] || notification_data[:display_username]
if user.staged && post
- original_subject = IncomingEmail.joins(:post)
- .where("posts.topic_id = ? AND posts.post_number = 1", post.topic_id)
- .pluck(:subject)
- .first
+ original_subject =
+ IncomingEmail
+ .joins(:post)
+ .where("posts.topic_id = ? AND posts.post_number = 1", post.topic_id)
+ .pluck(:subject)
+ .first
end
if original_subject
@@ -472,7 +535,7 @@ class UserNotifications < ActionMailer::Base
title: topic_title,
post: post,
username: original_username,
- from_alias: I18n.t('email_from', user_name: user_name, site_name: Email.site_title),
+ from_alias: I18n.t("email_from", user_name: user_name, site_name: Email.site_title),
allow_reply_by_email: allow_reply_by_email,
use_site_subject: opts[:use_site_subject],
add_re_to_subject: opts[:add_re_to_subject],
@@ -482,7 +545,7 @@ class UserNotifications < ActionMailer::Base
notification_type: notification_type,
use_invite_template: opts[:use_invite_template],
use_topic_title_subject: use_topic_title_subject,
- user: user
+ user: user,
}
if group_id = notification_data[:group_id]
@@ -525,7 +588,8 @@ class UserNotifications < ActionMailer::Base
# subcategory case
if !category.parent_category_id.nil?
- show_category_in_subject = "#{Category.where(id: category.parent_category_id).pluck_first(:name)}/#{show_category_in_subject}"
+ show_category_in_subject =
+ "#{Category.where(id: category.parent_category_id).pluck_first(:name)}/#{show_category_in_subject}"
end
else
show_category_in_subject = nil
@@ -555,7 +619,7 @@ class UserNotifications < ActionMailer::Base
"[#{group.name}] "
end
else
- I18n.t('subject_pm')
+ I18n.t("subject_pm")
end
participants = self.class.participants(post, user)
@@ -573,27 +637,25 @@ class UserNotifications < ActionMailer::Base
context_posts = context_posts.to_a
if context_posts.present?
- context << +"-- \n*#{I18n.t('user_notifications.previous_discussion')}*\n"
- context_posts.each do |cp|
- context << email_post_markdown(cp, true)
- end
+ context << +"-- \n*#{I18n.t("user_notifications.previous_discussion")}*\n"
+ context_posts.each { |cp| context << email_post_markdown(cp, true) }
end
- translation_override_exists = TranslationOverride.where(
- locale: SiteSetting.default_locale,
- translation_key: "#{template}.text_body_template"
- ).exists?
+ translation_override_exists =
+ TranslationOverride.where(
+ locale: SiteSetting.default_locale,
+ translation_key: "#{template}.text_body_template",
+ ).exists?
if opts[:use_invite_template]
invite_template = +"user_notifications.invited"
invite_template << "_group" if group_name
- invite_template <<
- if post.topic.private_message?
- "_to_private_message_body"
- else
- "_to_topic_body"
- end
+ invite_template << if post.topic.private_message?
+ "_to_private_message_body"
+ else
+ "_to_topic_body"
+ end
topic_excerpt = post.excerpt.tr("\n", " ") if post.is_first_post? && post.excerpt
topic_url = post.topic&.url
@@ -603,28 +665,38 @@ class UserNotifications < ActionMailer::Base
topic_url = ""
end
- message = I18n.t(invite_template,
- username: username,
- group_name: group_name,
- topic_title: gsub_emoji_to_unicode(title),
- topic_excerpt: topic_excerpt,
- site_title: SiteSetting.title,
- site_description: SiteSetting.site_description,
- topic_url: topic_url
- )
+ message =
+ I18n.t(
+ invite_template,
+ username: username,
+ group_name: group_name,
+ topic_title: gsub_emoji_to_unicode(title),
+ topic_excerpt: topic_excerpt,
+ site_title: SiteSetting.title,
+ site_description: SiteSetting.site_description,
+ topic_url: topic_url,
+ )
html = PrettyText.cook(message, sanitize: false).html_safe
else
reached_limit = SiteSetting.max_emails_per_day_per_user > 0
- reached_limit &&= (EmailLog.where(user_id: user.id)
- .where('created_at > ?', 1.day.ago)
- .count) >= (SiteSetting.max_emails_per_day_per_user - 1)
+ reached_limit &&=
+ (EmailLog.where(user_id: user.id).where("created_at > ?", 1.day.ago).count) >=
+ (SiteSetting.max_emails_per_day_per_user - 1)
in_reply_to_post = post.reply_to_post if user.user_option.email_in_reply_to
if SiteSetting.private_email?
- message = I18n.t('system_messages.contents_hidden')
+ message = I18n.t("system_messages.contents_hidden")
else
- message = email_post_markdown(post) + (reached_limit ? "\n\n#{I18n.t "user_notifications.reached_limit", count: SiteSetting.max_emails_per_day_per_user}" : "")
+ message =
+ email_post_markdown(post) +
+ (
+ if reached_limit
+ "\n\n#{I18n.t "user_notifications.reached_limit", count: SiteSetting.max_emails_per_day_per_user}"
+ else
+ ""
+ end
+ )
end
first_footer_classes = "highlight"
@@ -633,18 +705,20 @@ class UserNotifications < ActionMailer::Base
end
unless translation_override_exists
- html = UserNotificationRenderer.render(
- template: 'email/notification',
- format: :html,
- locals: { context_posts: context_posts,
- reached_limit: reached_limit,
- post: post,
- in_reply_to_post: in_reply_to_post,
- classes: Rtl.new(user).css_class,
- first_footer_classes: first_footer_classes,
- reply_above_line: false
- }
- )
+ html =
+ UserNotificationRenderer.render(
+ template: "email/notification",
+ format: :html,
+ locals: {
+ context_posts: context_posts,
+ reached_limit: reached_limit,
+ post: post,
+ in_reply_to_post: in_reply_to_post,
+ classes: Rtl.new(user).css_class,
+ first_footer_classes: first_footer_classes,
+ reply_above_line: false,
+ },
+ )
end
end
@@ -676,12 +750,10 @@ class UserNotifications < ActionMailer::Base
site_description: SiteSetting.site_description,
site_title: SiteSetting.title,
site_title_url_encoded: UrlHelper.encode_component(SiteSetting.title),
- locale: locale
+ locale: locale,
}
- unless translation_override_exists
- email_opts[:html_override] = html
- end
+ email_opts[:html_override] = html unless translation_override_exists
# If we have a display name, change the from address
email_opts[:from_alias] = from_alias if from_alias.present?
@@ -701,20 +773,26 @@ class UserNotifications < ActionMailer::Base
break if list.size >= SiteSetting.max_participant_names
end
- recent_posts_query = post.topic.posts
- .select("user_id, MAX(post_number) AS post_number")
- .where(post_type: Post.types[:regular], post_number: ..post.post_number)
- .where.not(user_id: recipient_user.id)
- .group(:user_id)
- .order("post_number DESC")
- .limit(SiteSetting.max_participant_names)
- .to_sql
+ recent_posts_query =
+ post
+ .topic
+ .posts
+ .select("user_id, MAX(post_number) AS post_number")
+ .where(post_type: Post.types[:regular], post_number: ..post.post_number)
+ .where.not(user_id: recipient_user.id)
+ .group(:user_id)
+ .order("post_number DESC")
+ .limit(SiteSetting.max_participant_names)
+ .to_sql
- allowed_users = post.topic.allowed_users
- .joins("LEFT JOIN (#{recent_posts_query}) pu ON topic_allowed_users.user_id = pu.user_id")
- .order("post_number DESC NULLS LAST", :id)
- .where.not(id: recipient_user.id)
- .human_users
+ allowed_users =
+ post
+ .topic
+ .allowed_users
+ .joins("LEFT JOIN (#{recent_posts_query}) pu ON topic_allowed_users.user_id = pu.user_id")
+ .order("post_number DESC NULLS LAST", :id)
+ .where.not(id: recipient_user.id)
+ .human_users
allowed_users.each do |u|
break if list.size >= SiteSetting.max_participant_names
@@ -730,7 +808,11 @@ class UserNotifications < ActionMailer::Base
others_count = allowed_groups.size + allowed_users.size - list.size
if others_count > 0
- I18n.t("user_notifications.more_pm_participants", participants: participants, count: others_count)
+ I18n.t(
+ "user_notifications.more_pm_participants",
+ participants: participants,
+ count: others_count,
+ )
else
participants
end
@@ -739,23 +821,18 @@ class UserNotifications < ActionMailer::Base
private
def build_user_email_token_by_template(template, user, email_token)
- build_email(
- user.email,
- template: template,
- locale: user_locale(user),
- email_token: email_token
- )
+ build_email(user.email, template: template, locale: user_locale(user), email_token: email_token)
end
def build_summary_for(user)
- @site_name = SiteSetting.email_prefix.presence || SiteSetting.title # used by I18n
- @user = user
- @date = short_date(Time.now)
- @base_url = Discourse.base_url
- @email_prefix = SiteSetting.email_prefix.presence || SiteSetting.title
- @header_color = ColorScheme.hex_for_name('header_primary')
- @header_bgcolor = ColorScheme.hex_for_name('header_background')
- @anchor_color = ColorScheme.hex_for_name('tertiary')
+ @site_name = SiteSetting.email_prefix.presence || SiteSetting.title # used by I18n
+ @user = user
+ @date = short_date(Time.now)
+ @base_url = Discourse.base_url
+ @email_prefix = SiteSetting.email_prefix.presence || SiteSetting.title
+ @header_color = ColorScheme.hex_for_name("header_primary")
+ @header_bgcolor = ColorScheme.hex_for_name("header_background")
+ @anchor_color = ColorScheme.hex_for_name("tertiary")
@markdown_linker = MarkdownLinker.new(@base_url)
@disable_email_custom_styles = !SiteSetting.apply_custom_styles_to_digest
end
@@ -765,12 +842,19 @@ class UserNotifications < ActionMailer::Base
end
def summary_new_users_count(min_date)
- min_date_str = min_date.is_a?(String) ? min_date : min_date.strftime('%Y-%m-%d')
+ min_date_str = min_date.is_a?(String) ? min_date : min_date.strftime("%Y-%m-%d")
key = self.class.summary_new_users_count_key(min_date_str)
- ((count = Discourse.redis.get(key)) && count.to_i) || begin
- count = User.real.where(active: true, staged: false).not_suspended.where("created_at > ?", min_date_str).count
- Discourse.redis.setex(key, 1.day, count)
- count
- end
+ ((count = Discourse.redis.get(key)) && count.to_i) ||
+ begin
+ count =
+ User
+ .real
+ .where(active: true, staged: false)
+ .not_suspended
+ .where("created_at > ?", min_date_str)
+ .count
+ Discourse.redis.setex(key, 1.day, count)
+ count
+ end
end
end
diff --git a/app/mailers/version_mailer.rb b/app/mailers/version_mailer.rb
index 0b9445f452b..c38cd29a90b 100644
--- a/app/mailers/version_mailer.rb
+++ b/app/mailers/version_mailer.rb
@@ -6,17 +6,21 @@ class VersionMailer < ActionMailer::Base
def send_notice
if SiteSetting.contact_email.present?
missing_versions = DiscourseUpdates.missing_versions
- if missing_versions.present? && missing_versions.first['notes'].present?
- build_email(SiteSetting.contact_email,
- template: 'new_version_mailer_with_notes',
- notes: missing_versions.first['notes'],
- new_version: DiscourseUpdates.latest_version,
- installed_version: Discourse::VERSION::STRING)
+ if missing_versions.present? && missing_versions.first["notes"].present?
+ build_email(
+ SiteSetting.contact_email,
+ template: "new_version_mailer_with_notes",
+ notes: missing_versions.first["notes"],
+ new_version: DiscourseUpdates.latest_version,
+ installed_version: Discourse::VERSION::STRING,
+ )
else
- build_email(SiteSetting.contact_email,
- template: 'new_version_mailer',
- new_version: DiscourseUpdates.latest_version,
- installed_version: Discourse::VERSION::STRING)
+ build_email(
+ SiteSetting.contact_email,
+ template: "new_version_mailer",
+ new_version: DiscourseUpdates.latest_version,
+ installed_version: Discourse::VERSION::STRING,
+ )
end
end
end
diff --git a/app/models/about.rb b/app/models/about.rb
index 44220472ccc..1901fccc663 100644
--- a/app/models/about.rb
+++ b/app/models/about.rb
@@ -32,11 +32,10 @@ class About
include ActiveModel::Serialization
include StatsCacheable
- attr_accessor :moderators,
- :admins
+ attr_accessor :moderators, :admins
def self.stats_cache_key
- 'about-stats'
+ "about-stats"
end
def self.fetch_stats
@@ -68,38 +67,37 @@ class About
end
def moderators
- @moderators ||= User.where(moderator: true, admin: false)
- .human_users
- .order("last_seen_at DESC")
+ @moderators ||= User.where(moderator: true, admin: false).human_users.order("last_seen_at DESC")
end
def admins
- @admins ||= User.where(admin: true)
- .human_users
- .order("last_seen_at DESC")
+ @admins ||= User.where(admin: true).human_users.order("last_seen_at DESC")
end
def stats
@stats ||= {
topic_count: Topic.listable_topics.count,
- topics_last_day: Topic.listable_topics.where('created_at > ?', 1.days.ago).count,
- topics_7_days: Topic.listable_topics.where('created_at > ?', 7.days.ago).count,
- topics_30_days: Topic.listable_topics.where('created_at > ?', 30.days.ago).count,
+ topics_last_day: Topic.listable_topics.where("created_at > ?", 1.days.ago).count,
+ topics_7_days: Topic.listable_topics.where("created_at > ?", 7.days.ago).count,
+ topics_30_days: Topic.listable_topics.where("created_at > ?", 30.days.ago).count,
post_count: Post.count,
- posts_last_day: Post.where('created_at > ?', 1.days.ago).count,
- posts_7_days: Post.where('created_at > ?', 7.days.ago).count,
- posts_30_days: Post.where('created_at > ?', 30.days.ago).count,
+ posts_last_day: Post.where("created_at > ?", 1.days.ago).count,
+ posts_7_days: Post.where("created_at > ?", 7.days.ago).count,
+ posts_30_days: Post.where("created_at > ?", 30.days.ago).count,
user_count: User.real.count,
- users_last_day: User.real.where('created_at > ?', 1.days.ago).count,
- users_7_days: User.real.where('created_at > ?', 7.days.ago).count,
- users_30_days: User.real.where('created_at > ?', 30.days.ago).count,
- active_users_last_day: User.where('last_seen_at > ?', 1.days.ago).count,
- active_users_7_days: User.where('last_seen_at > ?', 7.days.ago).count,
- active_users_30_days: User.where('last_seen_at > ?', 30.days.ago).count,
+ users_last_day: User.real.where("created_at > ?", 1.days.ago).count,
+ users_7_days: User.real.where("created_at > ?", 7.days.ago).count,
+ users_30_days: User.real.where("created_at > ?", 30.days.ago).count,
+ active_users_last_day: User.where("last_seen_at > ?", 1.days.ago).count,
+ active_users_7_days: User.where("last_seen_at > ?", 7.days.ago).count,
+ active_users_30_days: User.where("last_seen_at > ?", 30.days.ago).count,
like_count: UserAction.where(action_type: UserAction::LIKE).count,
- likes_last_day: UserAction.where(action_type: UserAction::LIKE).where("created_at > ?", 1.days.ago).count,
- likes_7_days: UserAction.where(action_type: UserAction::LIKE).where("created_at > ?", 7.days.ago).count,
- likes_30_days: UserAction.where(action_type: UserAction::LIKE).where("created_at > ?", 30.days.ago).count
+ likes_last_day:
+ UserAction.where(action_type: UserAction::LIKE).where("created_at > ?", 1.days.ago).count,
+ likes_7_days:
+ UserAction.where(action_type: UserAction::LIKE).where("created_at > ?", 7.days.ago).count,
+ likes_30_days:
+ UserAction.where(action_type: UserAction::LIKE).where("created_at > ?", 30.days.ago).count,
}.merge(plugin_stats)
end
@@ -109,17 +107,21 @@ class About
begin
stats = stat_group.call
rescue StandardError => err
- Discourse.warn_exception(err, message: "Unexpected error when collecting #{plugin_stat_group_name} About stats.")
+ Discourse.warn_exception(
+ err,
+ message: "Unexpected error when collecting #{plugin_stat_group_name} About stats.",
+ )
next
end
- if !stats.key?(:last_day) || !stats.key?("7_days") || !stats.key?("30_days") || !stats.key?(:count)
- Rails.logger.warn("Plugin stat group #{plugin_stat_group_name} for About stats does not have all required keys, skipping.")
+ if !stats.key?(:last_day) || !stats.key?("7_days") || !stats.key?("30_days") ||
+ !stats.key?(:count)
+ Rails.logger.warn(
+ "Plugin stat group #{plugin_stat_group_name} for About stats does not have all required keys, skipping.",
+ )
else
final_plugin_stats.merge!(
- stats.transform_keys do |key|
- "#{plugin_stat_group_name}_#{key}".to_sym
- end
+ stats.transform_keys { |key| "#{plugin_stat_group_name}_#{key}".to_sym },
)
end
end
@@ -151,9 +153,7 @@ class About
mods = User.where(id: results.map(&:user_ids).flatten.uniq).index_by(&:id)
- results.map do |row|
- CategoryMods.new(row.category_id, mods.values_at(*row.user_ids))
- end
+ results.map { |row| CategoryMods.new(row.category_id, mods.values_at(*row.user_ids)) }
end
def category_mods_limit
diff --git a/app/models/admin_dashboard_data.rb b/app/models/admin_dashboard_data.rb
index ae6dfa2535e..8c3245a803b 100644
--- a/app/models/admin_dashboard_data.rb
+++ b/app/models/admin_dashboard_data.rb
@@ -3,13 +3,10 @@
class AdminDashboardData
include StatsCacheable
- cattr_reader :problem_syms,
- :problem_blocks,
- :problem_messages,
- :problem_scheduled_check_blocks
+ cattr_reader :problem_syms, :problem_blocks, :problem_messages, :problem_scheduled_check_blocks
class Problem
- VALID_PRIORITIES = ["low", "high"].freeze
+ VALID_PRIORITIES = %w[low high].freeze
attr_reader :message, :priority, :identifier
@@ -114,11 +111,12 @@ class AdminDashboardData
found_problems_json = Discourse.redis.get(SCHEDULED_PROBLEM_STORAGE_KEY)
return [] if found_problems_json.blank?
begin
- JSON.parse(found_problems_json).map do |problem|
- Problem.from_h(problem)
- end
+ JSON.parse(found_problems_json).map { |problem| Problem.from_h(problem) }
rescue JSON::ParserError => err
- Discourse.warn_exception(err, message: "Error parsing found problem JSON in admin dashboard: #{found_problems_json}")
+ Discourse.warn_exception(
+ err,
+ message: "Error parsing found problem JSON in admin dashboard: #{found_problems_json}",
+ )
[]
end
end
@@ -127,16 +125,21 @@ class AdminDashboardData
add_scheduled_problem_check(:group_smtp_credentials) do
problems = GroupEmailCredentialsCheck.run
problems.map do |p|
- problem_message = I18n.t(
- "dashboard.group_email_credentials_warning",
- {
- base_path: Discourse.base_path,
- group_name: p[:group_name],
- group_full_name: p[:group_full_name],
- error: p[:message]
- }
+ problem_message =
+ I18n.t(
+ "dashboard.group_email_credentials_warning",
+ {
+ base_path: Discourse.base_path,
+ group_name: p[:group_name],
+ group_full_name: p[:group_full_name],
+ error: p[:message],
+ },
+ )
+ Problem.new(
+ problem_message,
+ priority: "high",
+ identifier: "group_#{p[:group_id]}_email_credentials",
)
- Problem.new(problem_message, priority: "high", identifier: "group_#{p[:group_id]}_email_credentials")
end
end
end
@@ -149,7 +152,10 @@ class AdminDashboardData
begin
problems = instance_exec(&blk)
rescue StandardError => err
- Discourse.warn_exception(err, message: "A scheduled admin dashboard problem check (#{check_identifier}) errored.")
+ Discourse.warn_exception(
+ err,
+ message: "A scheduled admin dashboard problem check (#{check_identifier}) errored.",
+ )
# we don't want to hold up other checks because this one errored
next
end
@@ -177,26 +183,33 @@ class AdminDashboardData
@@problem_blocks = []
@@problem_scheduled_check_blocks = {}
- @@problem_messages = [
- 'dashboard.bad_favicon_url',
- 'dashboard.poll_pop3_timeout',
- 'dashboard.poll_pop3_auth_error',
+ @@problem_messages = %w[
+ dashboard.bad_favicon_url
+ dashboard.poll_pop3_timeout
+ dashboard.poll_pop3_auth_error
]
- add_problem_check :rails_env_check, :host_names_check, :force_https_check,
- :ram_check, :google_oauth2_config_check,
- :facebook_config_check, :twitter_config_check,
- :github_config_check, :s3_config_check, :s3_cdn_check,
- :image_magick_check, :failing_emails_check,
+ add_problem_check :rails_env_check,
+ :host_names_check,
+ :force_https_check,
+ :ram_check,
+ :google_oauth2_config_check,
+ :facebook_config_check,
+ :twitter_config_check,
+ :github_config_check,
+ :s3_config_check,
+ :s3_cdn_check,
+ :image_magick_check,
+ :failing_emails_check,
:subfolder_ends_in_slash_check,
:email_polling_errored_recently,
- :out_of_date_themes, :unreachable_themes, :watched_words_check
+ :out_of_date_themes,
+ :unreachable_themes,
+ :watched_words_check
register_default_scheduled_problem_checks
- add_problem_check do
- sidekiq_check || queue_size_check
- end
+ add_problem_check { sidekiq_check || queue_size_check }
end
reset_problem_checks
@@ -213,7 +226,7 @@ class AdminDashboardData
end
def self.problems_started_key
- 'dash-problems-started-at'
+ "dash-problems-started-at"
end
def self.set_problems_started
@@ -235,7 +248,11 @@ class AdminDashboardData
end
def self.problem_message_check(i18n_key)
- Discourse.redis.get(problem_message_key(i18n_key)) ? I18n.t(i18n_key, base_path: Discourse.base_path) : nil
+ if Discourse.redis.get(problem_message_key(i18n_key))
+ I18n.t(i18n_key, base_path: Discourse.base_path)
+ else
+ nil
+ end
end
##
@@ -264,97 +281,128 @@ class AdminDashboardData
end
def host_names_check
- I18n.t("dashboard.host_names_warning") if ['localhost', 'production.localhost'].include?(Discourse.current_hostname)
+ if %w[localhost production.localhost].include?(Discourse.current_hostname)
+ I18n.t("dashboard.host_names_warning")
+ end
end
def sidekiq_check
last_job_performed_at = Jobs.last_job_performed_at
- I18n.t('dashboard.sidekiq_warning') if Jobs.queued > 0 && (last_job_performed_at.nil? || last_job_performed_at < 2.minutes.ago)
+ if Jobs.queued > 0 && (last_job_performed_at.nil? || last_job_performed_at < 2.minutes.ago)
+ I18n.t("dashboard.sidekiq_warning")
+ end
end
def queue_size_check
queue_size = Jobs.queued
- I18n.t('dashboard.queue_size_warning', queue_size: queue_size) unless queue_size < 100_000
+ I18n.t("dashboard.queue_size_warning", queue_size: queue_size) unless queue_size < 100_000
end
def ram_check
- I18n.t('dashboard.memory_warning') if MemInfo.new.mem_total && MemInfo.new.mem_total < 950_000
+ I18n.t("dashboard.memory_warning") if MemInfo.new.mem_total && MemInfo.new.mem_total < 950_000
end
def google_oauth2_config_check
- if SiteSetting.enable_google_oauth2_logins && (SiteSetting.google_oauth2_client_id.blank? || SiteSetting.google_oauth2_client_secret.blank?)
- I18n.t('dashboard.google_oauth2_config_warning', base_path: Discourse.base_path)
+ if SiteSetting.enable_google_oauth2_logins &&
+ (
+ SiteSetting.google_oauth2_client_id.blank? ||
+ SiteSetting.google_oauth2_client_secret.blank?
+ )
+ I18n.t("dashboard.google_oauth2_config_warning", base_path: Discourse.base_path)
end
end
def facebook_config_check
- if SiteSetting.enable_facebook_logins && (SiteSetting.facebook_app_id.blank? || SiteSetting.facebook_app_secret.blank?)
- I18n.t('dashboard.facebook_config_warning', base_path: Discourse.base_path)
+ if SiteSetting.enable_facebook_logins &&
+ (SiteSetting.facebook_app_id.blank? || SiteSetting.facebook_app_secret.blank?)
+ I18n.t("dashboard.facebook_config_warning", base_path: Discourse.base_path)
end
end
def twitter_config_check
- if SiteSetting.enable_twitter_logins && (SiteSetting.twitter_consumer_key.blank? || SiteSetting.twitter_consumer_secret.blank?)
- I18n.t('dashboard.twitter_config_warning', base_path: Discourse.base_path)
+ if SiteSetting.enable_twitter_logins &&
+ (SiteSetting.twitter_consumer_key.blank? || SiteSetting.twitter_consumer_secret.blank?)
+ I18n.t("dashboard.twitter_config_warning", base_path: Discourse.base_path)
end
end
def github_config_check
- if SiteSetting.enable_github_logins && (SiteSetting.github_client_id.blank? || SiteSetting.github_client_secret.blank?)
- I18n.t('dashboard.github_config_warning', base_path: Discourse.base_path)
+ if SiteSetting.enable_github_logins &&
+ (SiteSetting.github_client_id.blank? || SiteSetting.github_client_secret.blank?)
+ I18n.t("dashboard.github_config_warning", base_path: Discourse.base_path)
end
end
def s3_config_check
# if set via global setting it is validated during the `use_s3?` call
if !GlobalSetting.use_s3?
- bad_keys = (SiteSetting.s3_access_key_id.blank? || SiteSetting.s3_secret_access_key.blank?) && !SiteSetting.s3_use_iam_profile
+ bad_keys =
+ (SiteSetting.s3_access_key_id.blank? || SiteSetting.s3_secret_access_key.blank?) &&
+ !SiteSetting.s3_use_iam_profile
if SiteSetting.enable_s3_uploads && (bad_keys || SiteSetting.s3_upload_bucket.blank?)
- return I18n.t('dashboard.s3_config_warning', base_path: Discourse.base_path)
+ return I18n.t("dashboard.s3_config_warning", base_path: Discourse.base_path)
end
- if SiteSetting.backup_location == BackupLocationSiteSetting::S3 && (bad_keys || SiteSetting.s3_backup_bucket.blank?)
- return I18n.t('dashboard.s3_backup_config_warning', base_path: Discourse.base_path)
+ if SiteSetting.backup_location == BackupLocationSiteSetting::S3 &&
+ (bad_keys || SiteSetting.s3_backup_bucket.blank?)
+ return I18n.t("dashboard.s3_backup_config_warning", base_path: Discourse.base_path)
end
end
nil
end
def s3_cdn_check
- if (GlobalSetting.use_s3? || SiteSetting.enable_s3_uploads) && SiteSetting.Upload.s3_cdn_url.blank?
- I18n.t('dashboard.s3_cdn_warning')
+ if (GlobalSetting.use_s3? || SiteSetting.enable_s3_uploads) &&
+ SiteSetting.Upload.s3_cdn_url.blank?
+ I18n.t("dashboard.s3_cdn_warning")
end
end
def image_magick_check
- I18n.t('dashboard.image_magick_warning') if SiteSetting.create_thumbnails && !system("command -v convert >/dev/null;")
+ if SiteSetting.create_thumbnails && !system("command -v convert >/dev/null;")
+ I18n.t("dashboard.image_magick_warning")
+ end
end
def failing_emails_check
num_failed_jobs = Jobs.num_email_retry_jobs
- I18n.t('dashboard.failing_emails_warning', num_failed_jobs: num_failed_jobs, base_path: Discourse.base_path) if num_failed_jobs > 0
+ if num_failed_jobs > 0
+ I18n.t(
+ "dashboard.failing_emails_warning",
+ num_failed_jobs: num_failed_jobs,
+ base_path: Discourse.base_path,
+ )
+ end
end
def subfolder_ends_in_slash_check
- I18n.t('dashboard.subfolder_ends_in_slash') if Discourse.base_path =~ /\/$/
+ I18n.t("dashboard.subfolder_ends_in_slash") if Discourse.base_path =~ %r{/$}
end
def email_polling_errored_recently
errors = Jobs::PollMailbox.errors_in_past_24_hours
- I18n.t('dashboard.email_polling_errored_recently', count: errors, base_path: Discourse.base_path) if errors > 0
+ if errors > 0
+ I18n.t(
+ "dashboard.email_polling_errored_recently",
+ count: errors,
+ base_path: Discourse.base_path,
+ )
+ end
end
def missing_mailgun_api_key
return unless SiteSetting.reply_by_email_enabled
- return unless ActionMailer::Base.smtp_settings[:address]['smtp.mailgun.org']
+ return unless ActionMailer::Base.smtp_settings[:address]["smtp.mailgun.org"]
return unless SiteSetting.mailgun_api_key.blank?
- I18n.t('dashboard.missing_mailgun_api_key')
+ I18n.t("dashboard.missing_mailgun_api_key")
end
def force_https_check
return unless @opts[:check_force_https]
- I18n.t('dashboard.force_https_warning', base_path: Discourse.base_path) unless SiteSetting.force_https
+ unless SiteSetting.force_https
+ I18n.t("dashboard.force_https_warning", base_path: Discourse.base_path)
+ end
end
def watched_words_check
@@ -363,7 +411,11 @@ class AdminDashboardData
WordWatcher.word_matcher_regexp_list(action, raise_errors: true)
rescue RegexpError => e
translated_action = I18n.t("admin_js.admin.watched_words.actions.#{action}")
- I18n.t('dashboard.watched_word_regexp_error', base_path: Discourse.base_path, action: translated_action)
+ I18n.t(
+ "dashboard.watched_word_regexp_error",
+ base_path: Discourse.base_path,
+ action: translated_action,
+ )
end
end
nil
@@ -373,22 +425,25 @@ class AdminDashboardData
old_themes = RemoteTheme.out_of_date_themes
return unless old_themes.present?
- themes_html_format(old_themes, 'dashboard.out_of_date_themes')
+ themes_html_format(old_themes, "dashboard.out_of_date_themes")
end
def unreachable_themes
themes = RemoteTheme.unreachable_themes
return unless themes.present?
- themes_html_format(themes, 'dashboard.unreachable_themes')
+ themes_html_format(themes, "dashboard.unreachable_themes")
end
private
def themes_html_format(themes, i18n_key)
- html = themes.map do |name, id|
- "#{CGI.escapeHTML(name)}"
- end.join("\n")
+ html =
+ themes
+ .map do |name, id|
+ "#{CGI.escapeHTML(name)}"
+ end
+ .join("\n")
"#{I18n.t(i18n_key)}"
end
diff --git a/app/models/admin_dashboard_general_data.rb b/app/models/admin_dashboard_general_data.rb
index 06962ac2901..eff6304c545 100644
--- a/app/models/admin_dashboard_general_data.rb
+++ b/app/models/admin_dashboard_general_data.rb
@@ -2,11 +2,13 @@
class AdminDashboardGeneralData < AdminDashboardData
def get_json
- days_since_update = Discourse.last_commit_date ? ((DateTime.now - Discourse.last_commit_date) / 1.day).to_i : nil
+ days_since_update =
+ Discourse.last_commit_date ? ((DateTime.now - Discourse.last_commit_date) / 1.day).to_i : nil
{
updated_at: Time.zone.now.as_json,
discourse_updated_at: Discourse.last_commit_date,
- release_notes_link: "https://meta.discourse.org/c/announcements/67?tags=release-notes&before=#{days_since_update}"
+ release_notes_link:
+ "https://meta.discourse.org/c/announcements/67?tags=release-notes&before=#{days_since_update}",
}
end
diff --git a/app/models/admin_dashboard_index_data.rb b/app/models/admin_dashboard_index_data.rb
index 92da9f0087d..b8f92d2dae0 100644
--- a/app/models/admin_dashboard_index_data.rb
+++ b/app/models/admin_dashboard_index_data.rb
@@ -2,9 +2,7 @@
class AdminDashboardIndexData < AdminDashboardData
def get_json
- {
- updated_at: Time.zone.now.as_json
- }
+ { updated_at: Time.zone.now.as_json }
end
def self.stats_cache_key
diff --git a/app/models/anonymous_user.rb b/app/models/anonymous_user.rb
index 57147625083..b6b42e2eee4 100644
--- a/app/models/anonymous_user.rb
+++ b/app/models/anonymous_user.rb
@@ -2,7 +2,7 @@
class AnonymousUser < ActiveRecord::Base
belongs_to :user
- belongs_to :master_user, class_name: 'User'
+ belongs_to :master_user, class_name: "User"
end
# == Schema Information
diff --git a/app/models/api_key.rb b/app/models/api_key.rb
index 1849f2cd398..dc66d2fb40e 100644
--- a/app/models/api_key.rb
+++ b/app/models/api_key.rb
@@ -1,19 +1,21 @@
# frozen_string_literal: true
class ApiKey < ActiveRecord::Base
- class KeyAccessError < StandardError; end
+ class KeyAccessError < StandardError
+ end
has_many :api_key_scopes
belongs_to :user
- belongs_to :created_by, class_name: 'User'
+ belongs_to :created_by, class_name: "User"
scope :active, -> { where("revoked_at IS NULL") }
scope :revoked, -> { where("revoked_at IS NOT NULL") }
- scope :with_key, ->(key) {
- hashed = self.hash_key(key)
- where(key_hash: hashed)
- }
+ scope :with_key,
+ ->(key) {
+ hashed = self.hash_key(key)
+ where(key_hash: hashed)
+ }
after_initialize :generate_key
@@ -26,7 +28,9 @@ class ApiKey < ActiveRecord::Base
end
def key
- raise KeyAccessError.new "API key is only accessible immediately after creation" unless key_available?
+ unless key_available?
+ raise KeyAccessError.new "API key is only accessible immediately after creation"
+ end
@key
end
@@ -40,10 +44,12 @@ class ApiKey < ActiveRecord::Base
def self.revoke_unused_keys!
return if SiteSetting.revoke_api_keys_days == 0 # Never expire keys
- to_revoke = active.where("GREATEST(last_used_at, created_at, updated_at, :epoch) < :threshold",
- epoch: last_used_epoch,
- threshold: SiteSetting.revoke_api_keys_days.days.ago
- )
+ to_revoke =
+ active.where(
+ "GREATEST(last_used_at, created_at, updated_at, :epoch) < :threshold",
+ epoch: last_used_epoch,
+ threshold: SiteSetting.revoke_api_keys_days.days.ago,
+ )
to_revoke.find_each do |api_key|
ApiKey.transaction do
@@ -53,7 +59,12 @@ class ApiKey < ActiveRecord::Base
api_key,
UserHistory.actions[:api_key_update],
changes: api_key.saved_changes,
- context: I18n.t("staff_action_logs.api_key.automatic_revoked", count: SiteSetting.revoke_api_keys_days))
+ context:
+ I18n.t(
+ "staff_action_logs.api_key.automatic_revoked",
+ count: SiteSetting.revoke_api_keys_days,
+ ),
+ )
end
end
end
@@ -63,7 +74,9 @@ class ApiKey < ActiveRecord::Base
end
def request_allowed?(env)
- return false if allowed_ips.present? && allowed_ips.none? { |ip| ip.include?(Rack::Request.new(env).ip) }
+ if allowed_ips.present? && allowed_ips.none? { |ip| ip.include?(Rack::Request.new(env).ip) }
+ return false
+ end
return true if RouteMatcher.new(methods: :get, actions: "session#scopes").match?(env: env)
api_key_scopes.blank? || api_key_scopes.any? { |s| s.permits?(env) }
diff --git a/app/models/api_key_scope.rb b/app/models/api_key_scope.rb
index 18db82addd7..c0d072d0bca 100644
--- a/app/models/api_key_scope.rb
+++ b/app/models/api_key_scope.rb
@@ -18,26 +18,48 @@ class ApiKeyScope < ActiveRecord::Base
mappings = {
global: {
- read: { methods: %i[get] }
+ read: {
+ methods: %i[get],
+ },
},
topics: {
- write: { actions: %w[posts#create], params: %i[topic_id] },
- update: { actions: %w[topics#update], params: %i[topic_id] },
+ write: {
+ actions: %w[posts#create],
+ params: %i[topic_id],
+ },
+ update: {
+ actions: %w[topics#update],
+ params: %i[topic_id],
+ },
read: {
actions: %w[topics#show topics#feed topics#posts],
- params: %i[topic_id], aliases: { topic_id: :id }
+ params: %i[topic_id],
+ aliases: {
+ topic_id: :id,
+ },
},
read_lists: {
- actions: list_actions, params: %i[category_id],
- aliases: { category_id: :category_slug_path_with_id }
- }
+ actions: list_actions,
+ params: %i[category_id],
+ aliases: {
+ category_id: :category_slug_path_with_id,
+ },
+ },
},
posts: {
- edit: { actions: %w[posts#update], params: %i[id] }
+ edit: {
+ actions: %w[posts#update],
+ params: %i[id],
+ },
},
categories: {
- list: { actions: %w[categories#index] },
- show: { actions: %w[categories#show], params: %i[id] }
+ list: {
+ actions: %w[categories#index],
+ },
+ show: {
+ actions: %w[categories#show],
+ params: %i[id],
+ },
},
uploads: {
create: {
@@ -49,42 +71,95 @@ class ApiKeyScope < ActiveRecord::Base
uploads#batch_presign_multipart_parts
uploads#abort_multipart
uploads#complete_multipart
- ]
- }
+ ],
+ },
},
users: {
- bookmarks: { actions: %w[users#bookmarks], params: %i[username] },
- sync_sso: { actions: %w[admin/users#sync_sso], params: %i[sso sig] },
- show: { actions: %w[users#show], params: %i[username external_id external_provider] },
- check_emails: { actions: %w[users#check_emails], params: %i[username] },
- update: { actions: %w[users#update], params: %i[username] },
- log_out: { actions: %w[admin/users#log_out] },
- anonymize: { actions: %w[admin/users#anonymize] },
- delete: { actions: %w[admin/users#destroy] },
- list: { actions: %w[admin/users#index] },
+ bookmarks: {
+ actions: %w[users#bookmarks],
+ params: %i[username],
+ },
+ sync_sso: {
+ actions: %w[admin/users#sync_sso],
+ params: %i[sso sig],
+ },
+ show: {
+ actions: %w[users#show],
+ params: %i[username external_id external_provider],
+ },
+ check_emails: {
+ actions: %w[users#check_emails],
+ params: %i[username],
+ },
+ update: {
+ actions: %w[users#update],
+ params: %i[username],
+ },
+ log_out: {
+ actions: %w[admin/users#log_out],
+ },
+ anonymize: {
+ actions: %w[admin/users#anonymize],
+ },
+ delete: {
+ actions: %w[admin/users#destroy],
+ },
+ list: {
+ actions: %w[admin/users#index],
+ },
},
user_status: {
- read: { actions: %w[user_status#get] },
- update: { actions: %w[user_status#set user_status#clear] },
+ read: {
+ actions: %w[user_status#get],
+ },
+ update: {
+ actions: %w[user_status#set user_status#clear],
+ },
},
email: {
- receive_emails: { actions: %w[admin/email#handle_mail admin/email#smtp_should_reject] }
+ receive_emails: {
+ actions: %w[admin/email#handle_mail admin/email#smtp_should_reject],
+ },
},
badges: {
- create: { actions: %w[admin/badges#create] },
- show: { actions: %w[badges#show] },
- update: { actions: %w[admin/badges#update] },
- delete: { actions: %w[admin/badges#destroy] },
- list_user_badges: { actions: %w[user_badges#username], params: %i[username] },
- assign_badge_to_user: { actions: %w[user_badges#create], params: %i[username] },
- revoke_badge_from_user: { actions: %w[user_badges#destroy] },
+ create: {
+ actions: %w[admin/badges#create],
+ },
+ show: {
+ actions: %w[badges#show],
+ },
+ update: {
+ actions: %w[admin/badges#update],
+ },
+ delete: {
+ actions: %w[admin/badges#destroy],
+ },
+ list_user_badges: {
+ actions: %w[user_badges#username],
+ params: %i[username],
+ },
+ assign_badge_to_user: {
+ actions: %w[user_badges#create],
+ params: %i[username],
+ },
+ revoke_badge_from_user: {
+ actions: %w[user_badges#destroy],
+ },
},
wordpress: {
- publishing: { actions: %w[site#site posts#create topics#update topics#status topics#show] },
- commenting: { actions: %w[topics#wordpress] },
- discourse_connect: { actions: %w[admin/users#sync_sso admin/users#log_out admin/users#index users#show] },
- utilities: { actions: %w[users#create groups#index] }
- }
+ publishing: {
+ actions: %w[site#site posts#create topics#update topics#status topics#show],
+ },
+ commenting: {
+ actions: %w[topics#wordpress],
+ },
+ discourse_connect: {
+ actions: %w[admin/users#sync_sso admin/users#log_out admin/users#index users#show],
+ },
+ utilities: {
+ actions: %w[users#create groups#index],
+ },
+ },
}
parse_resources!(mappings)
@@ -106,7 +181,10 @@ class ApiKeyScope < ActiveRecord::Base
def parse_resources!(mappings)
mappings.each_value do |resource_actions|
resource_actions.each_value do |action_data|
- action_data[:urls] = find_urls(actions: action_data[:actions], methods: action_data[:methods])
+ action_data[:urls] = find_urls(
+ actions: action_data[:actions],
+ methods: action_data[:methods],
+ )
end
end
end
@@ -128,12 +206,12 @@ class ApiKeyScope < ActiveRecord::Base
set.routes.each do |route|
defaults = route.defaults
action = "#{defaults[:controller].to_s}##{defaults[:action]}"
- path = route.path.spec.to_s.gsub(/\(\.:format\)/, '')
- api_supported_path = (
- path.end_with?('.rss') ||
- !route.path.requirements[:format] ||
- route.path.requirements[:format].match?('json')
- )
+ path = route.path.spec.to_s.gsub(/\(\.:format\)/, "")
+ api_supported_path =
+ (
+ path.end_with?(".rss") || !route.path.requirements[:format] ||
+ route.path.requirements[:format].match?("json")
+ )
excluded_paths = %w[/new-topic /new-message /exception]
if actions.include?(action) && api_supported_path && !excluded_paths.include?(path)
@@ -143,18 +221,16 @@ class ApiKeyScope < ActiveRecord::Base
end
end
- if methods.present?
- methods.each do |method|
- urls << "* (#{method})"
- end
- end
+ methods.each { |method| urls << "* (#{method})" } if methods.present?
urls.to_a
end
end
def permits?(env)
- RouteMatcher.new(**mapping.except(:urls), allowed_param_values: allowed_parameters).match?(env: env)
+ RouteMatcher.new(**mapping.except(:urls), allowed_param_values: allowed_parameters).match?(
+ env: env,
+ )
end
private
diff --git a/app/models/application_request.rb b/app/models/application_request.rb
index 81125566e4a..d422a08c960 100644
--- a/app/models/application_request.rb
+++ b/app/models/application_request.rb
@@ -1,19 +1,20 @@
# frozen_string_literal: true
class ApplicationRequest < ActiveRecord::Base
-
- enum req_type: %i(http_total
- http_2xx
- http_background
- http_3xx
- http_4xx
- http_5xx
- page_view_crawler
- page_view_logged_in
- page_view_anon
- page_view_logged_in_mobile
- page_view_anon_mobile
- api
- user_api)
+ enum req_type: %i[
+ http_total
+ http_2xx
+ http_background
+ http_3xx
+ http_4xx
+ http_5xx
+ page_view_crawler
+ page_view_logged_in
+ page_view_anon
+ page_view_logged_in_mobile
+ page_view_anon_mobile
+ api
+ user_api
+ ]
include CachedCounting
@@ -36,14 +37,12 @@ class ApplicationRequest < ActiveRecord::Base
end
def self.req_id(date, req_type, retries = 0)
-
req_type_id = req_types[req_type]
# a poor man's upsert
id = where(date: date, req_type: req_type_id).pluck_first(:id)
id ||= create!(date: date, req_type: req_type_id, count: 0).id
-
- rescue # primary key violation
+ rescue StandardError # primary key violation
if retries == 0
req_id(date, req_type, 1)
else
@@ -56,9 +55,9 @@ class ApplicationRequest < ActiveRecord::Base
self.req_types.each do |key, i|
query = self.where(req_type: i)
- s["#{key}_total"] = query.sum(:count)
+ s["#{key}_total"] = query.sum(:count)
s["#{key}_30_days"] = query.where("date > ?", 30.days.ago).sum(:count)
- s["#{key}_7_days"] = query.where("date > ?", 7.days.ago).sum(:count)
+ s["#{key}_7_days"] = query.where("date > ?", 7.days.ago).sum(:count)
end
s
diff --git a/app/models/associated_group.rb b/app/models/associated_group.rb
index 9d6e9365dcd..3c8c635094b 100644
--- a/app/models/associated_group.rb
+++ b/app/models/associated_group.rb
@@ -14,9 +14,11 @@ class AssociatedGroup < ActiveRecord::Base
end
def self.cleanup!
- AssociatedGroup.left_joins(:group_associated_groups, :user_associated_groups)
+ AssociatedGroup
+ .left_joins(:group_associated_groups, :user_associated_groups)
.where("group_associated_groups.id IS NULL AND user_associated_groups.id IS NULL")
- .where("last_used < ?", 1.week.ago).delete_all
+ .where("last_used < ?", 1.week.ago)
+ .delete_all
end
end
diff --git a/app/models/auto_track_duration_site_setting.rb b/app/models/auto_track_duration_site_setting.rb
index 9764d0d5256..0aad12e6e41 100644
--- a/app/models/auto_track_duration_site_setting.rb
+++ b/app/models/auto_track_duration_site_setting.rb
@@ -1,28 +1,25 @@
# frozen_string_literal: true
class AutoTrackDurationSiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
- val.to_i.to_s == val.to_s &&
- values.any? { |v| v[:value] == val.to_i }
+ val.to_i.to_s == val.to_s && values.any? { |v| v[:value] == val.to_i }
end
def self.values
@values ||= [
- { name: 'user.auto_track_options.never', value: -1 },
- { name: 'user.auto_track_options.immediately', value: 0 },
- { name: 'user.auto_track_options.after_30_seconds', value: 1000 * 30 },
- { name: 'user.auto_track_options.after_1_minute', value: 1000 * 60 },
- { name: 'user.auto_track_options.after_2_minutes', value: 1000 * 60 * 2 },
- { name: 'user.auto_track_options.after_3_minutes', value: 1000 * 60 * 3 },
- { name: 'user.auto_track_options.after_4_minutes', value: 1000 * 60 * 4 },
- { name: 'user.auto_track_options.after_5_minutes', value: 1000 * 60 * 5 },
- { name: 'user.auto_track_options.after_10_minutes', value: 1000 * 60 * 10 },
+ { name: "user.auto_track_options.never", value: -1 },
+ { name: "user.auto_track_options.immediately", value: 0 },
+ { name: "user.auto_track_options.after_30_seconds", value: 1000 * 30 },
+ { name: "user.auto_track_options.after_1_minute", value: 1000 * 60 },
+ { name: "user.auto_track_options.after_2_minutes", value: 1000 * 60 * 2 },
+ { name: "user.auto_track_options.after_3_minutes", value: 1000 * 60 * 3 },
+ { name: "user.auto_track_options.after_4_minutes", value: 1000 * 60 * 4 },
+ { name: "user.auto_track_options.after_5_minutes", value: 1000 * 60 * 5 },
+ { name: "user.auto_track_options.after_10_minutes", value: 1000 * 60 * 10 },
]
end
def self.translate_names?
true
end
-
end
diff --git a/app/models/backup_file.rb b/app/models/backup_file.rb
index a8a09731a11..46377691047 100644
--- a/app/models/backup_file.rb
+++ b/app/models/backup_file.rb
@@ -3,10 +3,7 @@
class BackupFile
include ActiveModel::SerializerSupport
- attr_reader :filename,
- :size,
- :last_modified,
- :source
+ attr_reader :filename, :size, :last_modified, :source
def initialize(filename:, size:, last_modified:, source: nil)
@filename = filename
diff --git a/app/models/backup_location_site_setting.rb b/app/models/backup_location_site_setting.rb
index 4236ca1de7f..1bdbd2403d6 100644
--- a/app/models/backup_location_site_setting.rb
+++ b/app/models/backup_location_site_setting.rb
@@ -11,7 +11,7 @@ class BackupLocationSiteSetting < EnumSiteSetting
def self.values
@values ||= [
{ name: "admin.backups.location.local", value: LOCAL },
- { name: "admin.backups.location.s3", value: S3 }
+ { name: "admin.backups.location.s3", value: S3 },
]
end
diff --git a/app/models/badge.rb b/app/models/badge.rb
index 2a84344cad8..d8b1ce794da 100644
--- a/app/models/badge.rb
+++ b/app/models/badge.rb
@@ -2,7 +2,7 @@
class Badge < ActiveRecord::Base
# TODO: Drop in July 2021
- self.ignored_columns = %w{image}
+ self.ignored_columns = %w[image]
include GlobalPath
include HasSanitizableFields
@@ -76,10 +76,15 @@ class Badge < ActiveRecord::Base
attr_accessor :has_badge
def self.trigger_hash
- @trigger_hash ||= Badge::Trigger.constants.map do |k|
- name = k.to_s.underscore
- [name, Badge::Trigger.const_get(k)] unless name =~ /deprecated/
- end.compact.to_h
+ @trigger_hash ||=
+ Badge::Trigger
+ .constants
+ .map do |k|
+ name = k.to_s.underscore
+ [name, Badge::Trigger.const_get(k)] unless name =~ /deprecated/
+ end
+ .compact
+ .to_h
end
module Trigger
@@ -105,7 +110,7 @@ class Badge < ActiveRecord::Base
belongs_to :badge_type
belongs_to :badge_grouping
- belongs_to :image_upload, class_name: 'Upload'
+ belongs_to :image_upload, class_name: "Upload"
has_many :user_badges, dependent: :destroy
has_many :upload_references, as: :target, dependent: :destroy
@@ -134,11 +139,7 @@ class Badge < ActiveRecord::Base
# fields that can not be edited on system badges
def self.protected_system_fields
- [
- :name, :badge_type_id, :multiple_grant,
- :target_posts, :show_posts, :query,
- :trigger, :auto_revoke, :listable
- ]
+ %i[name badge_type_id multiple_grant target_posts show_posts query trigger auto_revoke listable]
end
def self.trust_level_badge_ids
@@ -152,7 +153,7 @@ class Badge < ActiveRecord::Base
GreatPost => 50,
NiceTopic => 10,
GoodTopic => 25,
- GreatTopic => 50
+ GreatTopic => 50,
}
end
@@ -219,7 +220,7 @@ class Badge < ActiveRecord::Base
end
def self.i18n_name(name)
- name.downcase.tr(' ', '_')
+ name.downcase.tr(" ", "_")
end
def self.display_name(name)
@@ -231,8 +232,8 @@ class Badge < ActiveRecord::Base
end
def self.find_system_badge_id_from_translation_key(translation_key)
- return unless translation_key.starts_with?('badges.')
- badge_name_klass = translation_key.split('.').second.camelize
+ return unless translation_key.starts_with?("badges.")
+ badge_name_klass = translation_key.split(".").second.camelize
Badge.const_defined?(badge_name_klass) ? "Badge::#{badge_name_klass}".constantize : nil
end
@@ -283,7 +284,12 @@ class Badge < ActiveRecord::Base
def long_description
key = "badges.#{i18n_name}.long_description"
- I18n.t(key, default: self[:long_description] || '', base_uri: Discourse.base_path, max_likes_per_day: SiteSetting.max_likes_per_day)
+ I18n.t(
+ key,
+ default: self[:long_description] || "",
+ base_uri: Discourse.base_path,
+ max_likes_per_day: SiteSetting.max_likes_per_day,
+ )
end
def long_description=(val)
@@ -293,7 +299,12 @@ class Badge < ActiveRecord::Base
def description
key = "badges.#{i18n_name}.description"
- I18n.t(key, default: self[:description] || '', base_uri: Discourse.base_path, max_likes_per_day: SiteSetting.max_likes_per_day)
+ I18n.t(
+ key,
+ default: self[:description] || "",
+ base_uri: Discourse.base_path,
+ max_likes_per_day: SiteSetting.max_likes_per_day,
+ )
end
def description=(val)
@@ -302,7 +313,7 @@ class Badge < ActiveRecord::Base
end
def slug
- Slug.for(self.display_name, '-')
+ Slug.for(self.display_name, "-")
end
def manually_grantable?
@@ -314,9 +325,7 @@ class Badge < ActiveRecord::Base
end
def image_url
- if image_upload_id.present?
- upload_cdn_path(image_upload.url)
- end
+ upload_cdn_path(image_upload.url) if image_upload_id.present?
end
def for_beginners?
@@ -330,9 +339,7 @@ class Badge < ActiveRecord::Base
end
def sanitize_description
- if description_changed?
- self.description = sanitize_field(self.description)
- end
+ self.description = sanitize_field(self.description) if description_changed?
end
end
diff --git a/app/models/badge_grouping.rb b/app/models/badge_grouping.rb
index b95c78f1c4e..c0afcbdbb10 100644
--- a/app/models/badge_grouping.rb
+++ b/app/models/badge_grouping.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class BadgeGrouping < ActiveRecord::Base
-
GettingStarted = 1
Community = 2
Posting = 3
diff --git a/app/models/base_font_setting.rb b/app/models/base_font_setting.rb
index 36c0321876b..d4e3971f0df 100644
--- a/app/models/base_font_setting.rb
+++ b/app/models/base_font_setting.rb
@@ -8,8 +8,6 @@ class BaseFontSetting < EnumSiteSetting
end
def self.values
- @values ||= DiscourseFonts.fonts.map do |font|
- { name: font[:name], value: font[:key] }
- end
+ @values ||= DiscourseFonts.fonts.map { |font| { name: font[:name], value: font[:key] } }
end
end
diff --git a/app/models/bookmark.rb b/app/models/bookmark.rb
index c6947cf0787..3e1a6dab387 100644
--- a/app/models/bookmark.rb
+++ b/app/models/bookmark.rb
@@ -3,7 +3,7 @@
class Bookmark < ActiveRecord::Base
self.ignored_columns = [
"post_id", # TODO (martin) (2022-08-01) remove
- "for_topic" # TODO (martin) (2022-08-01) remove
+ "for_topic", # TODO (martin) (2022-08-01) remove
]
cattr_accessor :registered_bookmarkables
@@ -42,26 +42,24 @@ class Bookmark < ActiveRecord::Base
belongs_to :bookmarkable, polymorphic: true
def self.auto_delete_preferences
- @auto_delete_preferences ||= Enum.new(
- never: 0,
- when_reminder_sent: 1,
- on_owner_reply: 2,
- clear_reminder: 3,
- )
+ @auto_delete_preferences ||=
+ Enum.new(never: 0, when_reminder_sent: 1, on_owner_reply: 2, clear_reminder: 3)
end
def self.select_type(bookmarks_relation, type)
bookmarks_relation.select { |bm| bm.bookmarkable_type == type }
end
- validate :polymorphic_columns_present, on: [:create, :update]
- validate :valid_bookmarkable_type, on: [:create, :update]
+ validate :polymorphic_columns_present, on: %i[create update]
+ validate :valid_bookmarkable_type, on: %i[create update]
validate :unique_per_bookmarkable,
- on: [:create, :update],
- if: Proc.new { |b|
- b.will_save_change_to_bookmarkable_id? || b.will_save_change_to_bookmarkable_type? || b.will_save_change_to_user_id?
- }
+ on: %i[create update],
+ if:
+ Proc.new { |b|
+ b.will_save_change_to_bookmarkable_id? || b.will_save_change_to_bookmarkable_type? ||
+ b.will_save_change_to_user_id?
+ }
validate :ensure_sane_reminder_at_time, if: :will_save_change_to_reminder_at?
validate :bookmark_limit_not_reached
@@ -78,7 +76,13 @@ class Bookmark < ActiveRecord::Base
end
def unique_per_bookmarkable
- return if !Bookmark.exists?(user_id: user_id, bookmarkable_id: bookmarkable_id, bookmarkable_type: bookmarkable_type)
+ if !Bookmark.exists?(
+ user_id: user_id,
+ bookmarkable_id: bookmarkable_id,
+ bookmarkable_type: bookmarkable_type,
+ )
+ return
+ end
self.errors.add(:base, I18n.t("bookmarks.errors.already_bookmarked", type: bookmarkable_type))
end
@@ -102,15 +106,18 @@ class Bookmark < ActiveRecord::Base
I18n.t(
"bookmarks.errors.too_many",
user_bookmarks_url: "#{Discourse.base_url}/my/activity/bookmarks",
- limit: SiteSetting.max_bookmarks_per_user
- )
+ limit: SiteSetting.max_bookmarks_per_user,
+ ),
)
end
def valid_bookmarkable_type
return if Bookmark.valid_bookmarkable_types.include?(self.bookmarkable_type)
- self.errors.add(:base, I18n.t("bookmarks.errors.invalid_bookmarkable", type: self.bookmarkable_type))
+ self.errors.add(
+ :base,
+ I18n.t("bookmarks.errors.invalid_bookmarkable", type: self.bookmarkable_type),
+ )
end
def auto_delete_when_reminder_sent?
@@ -126,54 +133,57 @@ class Bookmark < ActiveRecord::Base
end
def clear_reminder!
- update!(
- reminder_last_sent_at: Time.zone.now,
- reminder_set_at: nil,
- )
+ update!(reminder_last_sent_at: Time.zone.now, reminder_set_at: nil)
end
- scope :with_reminders, -> do
- where("reminder_at IS NOT NULL")
- end
+ scope :with_reminders, -> { where("reminder_at IS NOT NULL") }
- scope :pending_reminders, ->(before_time = Time.now.utc) do
- with_reminders.where("reminder_at <= ?", before_time).where(reminder_last_sent_at: nil)
- end
+ scope :pending_reminders,
+ ->(before_time = Time.now.utc) {
+ with_reminders.where("reminder_at <= ?", before_time).where(reminder_last_sent_at: nil)
+ }
- scope :pending_reminders_for_user, ->(user) do
- pending_reminders.where(user: user)
- end
+ scope :pending_reminders_for_user, ->(user) { pending_reminders.where(user: user) }
- scope :for_user_in_topic, ->(user_id, topic_id) {
- joins("LEFT JOIN posts ON posts.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'")
- .joins("LEFT JOIN topics ON (topics.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Topic') OR
- (topics.id = posts.topic_id)")
- .where(
- "bookmarks.user_id = :user_id AND (topics.id = :topic_id OR posts.topic_id = :topic_id)
+ scope :for_user_in_topic,
+ ->(user_id, topic_id) {
+ joins(
+ "LEFT JOIN posts ON posts.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'",
+ ).joins(
+ "LEFT JOIN topics ON (topics.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Topic') OR
+ (topics.id = posts.topic_id)",
+ ).where(
+ "bookmarks.user_id = :user_id AND (topics.id = :topic_id OR posts.topic_id = :topic_id)
AND posts.deleted_at IS NULL AND topics.deleted_at IS NULL",
- user_id: user_id, topic_id: topic_id
- )
- }
+ user_id: user_id,
+ topic_id: topic_id,
+ )
+ }
def self.count_per_day(opts = nil)
opts ||= {}
- result = where('bookmarks.created_at >= ?', opts[:start_date] || (opts[:since_days_ago] || 30).days.ago)
+ result =
+ where(
+ "bookmarks.created_at >= ?",
+ opts[:start_date] || (opts[:since_days_ago] || 30).days.ago,
+ )
- if opts[:end_date]
- result = result.where('bookmarks.created_at <= ?', opts[:end_date])
- end
+ result = result.where("bookmarks.created_at <= ?", opts[:end_date]) if opts[:end_date]
if opts[:category_id]
- result = result
- .joins("LEFT JOIN posts ON posts.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'")
- .joins("LEFT JOIN topics ON (topics.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Topic') OR (topics.id = posts.topic_id)")
- .where("topics.deleted_at IS NULL AND posts.deleted_at IS NULL")
- .merge(Topic.in_category_and_subcategories(opts[:category_id]))
+ result =
+ result
+ .joins(
+ "LEFT JOIN posts ON posts.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'",
+ )
+ .joins(
+ "LEFT JOIN topics ON (topics.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Topic') OR (topics.id = posts.topic_id)",
+ )
+ .where("topics.deleted_at IS NULL AND posts.deleted_at IS NULL")
+ .merge(Topic.in_category_and_subcategories(opts[:category_id]))
end
- result.group('date(bookmarks.created_at)')
- .order('date(bookmarks.created_at)')
- .count
+ result.group("date(bookmarks.created_at)").order("date(bookmarks.created_at)").count
end
##
diff --git a/app/models/category.rb b/app/models/category.rb
index c68ad7f1c9e..fc721f09405 100644
--- a/app/models/category.rb
+++ b/app/models/category.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
class Category < ActiveRecord::Base
- RESERVED_SLUGS = [
- 'none'
- ]
+ RESERVED_SLUGS = ["none"]
self.ignored_columns = [
:suppress_from_latest, # TODO(2020-11-18): remove
@@ -18,9 +16,9 @@ class Category < ActiveRecord::Base
include AnonCacheInvalidator
include HasDestroyedWebHook
- REQUIRE_TOPIC_APPROVAL = 'require_topic_approval'
- REQUIRE_REPLY_APPROVAL = 'require_reply_approval'
- NUM_AUTO_BUMP_DAILY = 'num_auto_bump_daily'
+ REQUIRE_TOPIC_APPROVAL = "require_topic_approval"
+ REQUIRE_REPLY_APPROVAL = "require_reply_approval"
+ NUM_AUTO_BUMP_DAILY = "num_auto_bump_daily"
register_custom_field_type(REQUIRE_TOPIC_APPROVAL, :boolean)
register_custom_field_type(REQUIRE_REPLY_APPROVAL, :boolean)
@@ -28,9 +26,9 @@ class Category < ActiveRecord::Base
belongs_to :topic
belongs_to :topic_only_relative_url,
- -> { select "id, title, slug" },
- class_name: "Topic",
- foreign_key: "topic_id"
+ -> { select "id, title, slug" },
+ class_name: "Topic",
+ foreign_key: "topic_id"
belongs_to :user
belongs_to :latest_post, class_name: "Post"
@@ -52,10 +50,20 @@ class Category < ActiveRecord::Base
validates :user_id, presence: true
- validates :name, if: Proc.new { |c| c.new_record? || c.will_save_change_to_name? || c.will_save_change_to_parent_category_id? },
- presence: true,
- uniqueness: { scope: :parent_category_id, case_sensitive: false },
- length: { in: 1..50 }
+ validates :name,
+ if:
+ Proc.new { |c|
+ c.new_record? || c.will_save_change_to_name? ||
+ c.will_save_change_to_parent_category_id?
+ },
+ presence: true,
+ uniqueness: {
+ scope: :parent_category_id,
+ case_sensitive: false,
+ },
+ length: {
+ in: 1..50,
+ }
validates :num_featured_topics, numericality: { only_integer: true, greater_than: 0 }
validates :search_priority, inclusion: { in: Searchable::PRIORITIES.values }
@@ -65,7 +73,12 @@ class Category < ActiveRecord::Base
validate :ensure_slug
validate :permissions_compatibility_validator
- validates :auto_close_hours, numericality: { greater_than: 0, less_than_or_equal_to: 87600 }, allow_nil: true
+ validates :auto_close_hours,
+ numericality: {
+ greater_than: 0,
+ less_than_or_equal_to: 87_600,
+ },
+ allow_nil: true
validates :slug, exclusion: { in: RESERVED_SLUGS }
after_create :create_category_definition
@@ -84,7 +97,8 @@ class Category < ActiveRecord::Base
after_save :update_reviewables
after_save do
- if saved_change_to_uploaded_logo_id? || saved_change_to_uploaded_logo_dark_id? || saved_change_to_uploaded_background_id?
+ if saved_change_to_uploaded_logo_id? || saved_change_to_uploaded_logo_dark_id? ||
+ saved_change_to_uploaded_background_id?
upload_ids = [self.uploaded_logo_id, self.uploaded_logo_dark_id, self.uploaded_background_id]
UploadReference.ensure_exist!(upload_ids: upload_ids, target: self)
end
@@ -106,8 +120,8 @@ class Category < ActiveRecord::Base
after_save_commit :index_search
- belongs_to :parent_category, class_name: 'Category'
- has_many :subcategories, class_name: 'Category', foreign_key: 'parent_category_id'
+ belongs_to :parent_category, class_name: "Category"
+ has_many :subcategories, class_name: "Category", foreign_key: "parent_category_id"
has_many :category_tags, dependent: :destroy
has_many :tags, through: :category_tags
@@ -117,65 +131,74 @@ class Category < ActiveRecord::Base
has_many :category_required_tag_groups, -> { order(order: :asc) }, dependent: :destroy
has_many :sidebar_section_links, as: :linkable, dependent: :delete_all
- belongs_to :reviewable_by_group, class_name: 'Group'
+ belongs_to :reviewable_by_group, class_name: "Group"
- scope :latest, -> { order('topic_count DESC') }
+ scope :latest, -> { order("topic_count DESC") }
- scope :secured, -> (guardian = nil) {
- ids = guardian.secure_category_ids if guardian
+ scope :secured,
+ ->(guardian = nil) {
+ ids = guardian.secure_category_ids if guardian
- if ids.present?
- where("NOT categories.read_restricted OR categories.id IN (:cats)", cats: ids).references(:categories)
- else
- where("NOT categories.read_restricted").references(:categories)
- end
- }
+ if ids.present?
+ where(
+ "NOT categories.read_restricted OR categories.id IN (:cats)",
+ cats: ids,
+ ).references(:categories)
+ else
+ where("NOT categories.read_restricted").references(:categories)
+ end
+ }
TOPIC_CREATION_PERMISSIONS ||= [:full]
- POST_CREATION_PERMISSIONS ||= [:create_post, :full]
+ POST_CREATION_PERMISSIONS ||= %i[create_post full]
- scope :topic_create_allowed, -> (guardian) do
+ scope :topic_create_allowed,
+ ->(guardian) {
+ scoped = scoped_to_permissions(guardian, TOPIC_CREATION_PERMISSIONS)
- scoped = scoped_to_permissions(guardian, TOPIC_CREATION_PERMISSIONS)
+ if !SiteSetting.allow_uncategorized_topics && !guardian.is_staff?
+ scoped = scoped.where.not(id: SiteSetting.uncategorized_category_id)
+ end
- if !SiteSetting.allow_uncategorized_topics && !guardian.is_staff?
- scoped = scoped.where.not(id: SiteSetting.uncategorized_category_id)
- end
+ scoped
+ }
- scoped
- end
+ scope :post_create_allowed,
+ ->(guardian) { scoped_to_permissions(guardian, POST_CREATION_PERMISSIONS) }
- scope :post_create_allowed, -> (guardian) { scoped_to_permissions(guardian, POST_CREATION_PERMISSIONS) }
-
- delegate :post_template, to: 'self.class'
+ delegate :post_template, to: "self.class"
# permission is just used by serialization
# we may consider wrapping this in another spot
- attr_accessor :displayable_topics, :permission, :subcategory_ids, :subcategory_list, :notification_level, :has_children
+ attr_accessor :displayable_topics,
+ :permission,
+ :subcategory_ids,
+ :subcategory_list,
+ :notification_level,
+ :has_children
# Allows us to skip creating the category definition topic in tests.
attr_accessor :skip_category_definition
- @topic_id_cache = DistributedCache.new('category_topic_ids')
+ @topic_id_cache = DistributedCache.new("category_topic_ids")
def self.topic_ids
- @topic_id_cache['ids'] || reset_topic_ids_cache
+ @topic_id_cache["ids"] || reset_topic_ids_cache
end
def self.reset_topic_ids_cache
- @topic_id_cache['ids'] = Set.new(Category.pluck(:topic_id).compact)
+ @topic_id_cache["ids"] = Set.new(Category.pluck(:topic_id).compact)
end
def reset_topic_ids_cache
Category.reset_topic_ids_cache
end
- @@subcategory_ids = DistributedCache.new('subcategory_ids')
+ @@subcategory_ids = DistributedCache.new("subcategory_ids")
def self.subcategory_ids(category_id)
- @@subcategory_ids[category_id] ||=
- begin
- sql = <<~SQL
+ @@subcategory_ids[category_id] ||= begin
+ sql = <<~SQL
WITH RECURSIVE subcategories AS (
SELECT :category_id id, 1 depth
UNION
@@ -186,12 +209,12 @@ class Category < ActiveRecord::Base
)
SELECT id FROM subcategories
SQL
- DB.query_single(
- sql,
- category_id: category_id,
- max_category_nesting: SiteSetting.max_category_nesting
- )
- end
+ DB.query_single(
+ sql,
+ category_id: category_id,
+ max_category_nesting: SiteSetting.max_category_nesting,
+ )
+ end
end
def self.clear_subcategory_ids
@@ -217,7 +240,8 @@ class Category < ActiveRecord::Base
end
else
permissions = permission_types.map { |p| CategoryGroup.permission_types[p] }
- where("(:staged AND LENGTH(COALESCE(email_in, '')) > 0 AND email_in_allow_strangers)
+ where(
+ "(:staged AND LENGTH(COALESCE(email_in, '')) > 0 AND email_in_allow_strangers)
OR categories.id NOT IN (SELECT category_id FROM category_groups)
OR categories.id IN (
SELECT category_id
@@ -228,16 +252,21 @@ class Category < ActiveRecord::Base
staged: guardian.is_staged?,
permissions: permissions,
user_id: guardian.user.id,
- everyone: Group::AUTO_GROUPS[:everyone])
+ everyone: Group::AUTO_GROUPS[:everyone],
+ )
end
end
def self.update_stats
- topics_with_post_count = Topic
- .select("topics.category_id, COUNT(*) topic_count, SUM(topics.posts_count) post_count")
- .where("topics.id NOT IN (select cc.topic_id from categories cc WHERE topic_id IS NOT NULL)")
- .group("topics.category_id")
- .visible.to_sql
+ topics_with_post_count =
+ Topic
+ .select("topics.category_id, COUNT(*) topic_count, SUM(topics.posts_count) post_count")
+ .where(
+ "topics.id NOT IN (select cc.topic_id from categories cc WHERE topic_id IS NOT NULL)",
+ )
+ .group("topics.category_id")
+ .visible
+ .to_sql
DB.exec <<~SQL
UPDATE categories c
@@ -265,29 +294,31 @@ class Category < ActiveRecord::Base
Category.all.each do |c|
topics = c.topics.visible
- topics = topics.where(['topics.id <> ?', c.topic_id]) if c.topic_id
- c.topics_year = topics.created_since(1.year.ago).count
+ topics = topics.where(["topics.id <> ?", c.topic_id]) if c.topic_id
+ c.topics_year = topics.created_since(1.year.ago).count
c.topics_month = topics.created_since(1.month.ago).count
- c.topics_week = topics.created_since(1.week.ago).count
- c.topics_day = topics.created_since(1.day.ago).count
+ c.topics_week = topics.created_since(1.week.ago).count
+ c.topics_day = topics.created_since(1.day.ago).count
posts = c.visible_posts
- c.posts_year = posts.created_since(1.year.ago).count
+ c.posts_year = posts.created_since(1.year.ago).count
c.posts_month = posts.created_since(1.month.ago).count
- c.posts_week = posts.created_since(1.week.ago).count
- c.posts_day = posts.created_since(1.day.ago).count
+ c.posts_week = posts.created_since(1.week.ago).count
+ c.posts_day = posts.created_since(1.day.ago).count
c.save if c.changed?
end
end
def visible_posts
- query = Post.joins(:topic)
- .where(['topics.category_id = ?', self.id])
- .where('topics.visible = true')
- .where('posts.deleted_at IS NULL')
- .where('posts.user_deleted = false')
- self.topic_id ? query.where(['topics.id <> ?', self.topic_id]) : query
+ query =
+ Post
+ .joins(:topic)
+ .where(["topics.category_id = ?", self.id])
+ .where("topics.visible = true")
+ .where("posts.deleted_at IS NULL")
+ .where("posts.user_deleted = false")
+ self.topic_id ? query.where(["topics.id <> ?", self.topic_id]) : query
end
# Internal: Generate the text of post prompting to enter category description.
@@ -299,7 +330,13 @@ class Category < ActiveRecord::Base
return if skip_category_definition
Topic.transaction do
- t = Topic.new(title: I18n.t("category.topic_prefix", category: name), user: user, pinned_at: Time.now, category_id: id)
+ t =
+ Topic.new(
+ title: I18n.t("category.topic_prefix", category: name),
+ user: user,
+ pinned_at: Time.now,
+ category_id: id,
+ )
t.skip_callbacks = true
t.ignore_category_auto_close = true
t.delete_topic_timer(TopicTimer.types[:close])
@@ -318,9 +355,7 @@ class Category < ActiveRecord::Base
end
def clear_related_site_settings
- if self.id == SiteSetting.general_category_id
- SiteSetting.general_category_id = -1
- end
+ SiteSetting.general_category_id = -1 if self.id == SiteSetting.general_category_id
end
def topic_url
@@ -345,9 +380,7 @@ class Category < ActiveRecord::Base
return nil unless self.description
@@cache_excerpt ||= LruRedux::ThreadSafeCache.new(1000)
- @@cache_excerpt.getset(self.description) do
- PrettyText.excerpt(description, 300)
- end
+ @@cache_excerpt.getset(self.description) { PrettyText.excerpt(description, 300) }
end
def access_category_via_group
@@ -370,20 +403,20 @@ class Category < ActiveRecord::Base
if slug.present?
# if we don't unescape it first we strip the % from the encoded version
- slug = SiteSetting.slug_generation_method == 'encoded' ? CGI.unescape(self.slug) : self.slug
- self.slug = Slug.for(slug, '', method: :encoded)
+ slug = SiteSetting.slug_generation_method == "encoded" ? CGI.unescape(self.slug) : self.slug
+ self.slug = Slug.for(slug, "", method: :encoded)
if self.slug.blank?
errors.add(:slug, :invalid)
- elsif SiteSetting.slug_generation_method == 'ascii' && !CGI.unescape(self.slug).ascii_only?
+ elsif SiteSetting.slug_generation_method == "ascii" && !CGI.unescape(self.slug).ascii_only?
errors.add(:slug, I18n.t("category.errors.slug_contains_non_ascii_chars"))
elsif duplicate_slug?
errors.add(:slug, I18n.t("category.errors.is_already_in_use"))
end
else
# auto slug
- self.slug = Slug.for(name, '')
- self.slug = '' if duplicate_slug?
+ self.slug = Slug.for(name, "")
+ self.slug = "" if duplicate_slug?
end
# only allow to use category itself id.
@@ -403,30 +436,27 @@ class Category < ActiveRecord::Base
if group_ids.present?
MessageBus.publish(
- '/categories',
+ "/categories",
{ categories: ActiveModel::ArraySerializer.new([self]).as_json },
- group_ids: group_ids
+ group_ids: group_ids,
)
end
else
MessageBus.publish(
- '/categories',
- { categories: ActiveModel::ArraySerializer.new([self]).as_json }
+ "/categories",
+ { categories: ActiveModel::ArraySerializer.new([self]).as_json },
)
end
end
def remove_site_settings
SiteSetting.all_settings.each do |s|
- if s[:type] == 'category' && s[:value].to_i == self.id
- SiteSetting.set(s[:setting], '')
- end
+ SiteSetting.set(s[:setting], "") if s[:type] == "category" && s[:value].to_i == self.id
end
-
end
def publish_category_deletion
- MessageBus.publish('/categories', deleted_categories: [self.id])
+ MessageBus.publish("/categories", deleted_categories: [self.id])
end
# This is used in a validation so has to produce accurate results before the
@@ -492,7 +522,9 @@ class Category < ActiveRecord::Base
errors.add(:base, I18n.t("category.errors.self_parent")) if parent_category_id == id
total_depth = height_of_ancestors + 1 + depth_of_descendants
- errors.add(:base, I18n.t("category.errors.depth")) if total_depth > SiteSetting.max_category_nesting
+ if total_depth > SiteSetting.max_category_nesting
+ errors.add(:base, I18n.t("category.errors.depth"))
+ end
end
end
@@ -500,9 +532,7 @@ class Category < ActiveRecord::Base
# this line bothers me, destroying in AR can not seem to be queued, thinking of extending it
category_groups.destroy_all unless new_record?
ids = Group.where(name: names.split(",")).pluck(:id)
- ids.each do |id|
- category_groups.build(group_id: id)
- end
+ ids.each { |id| category_groups.build(group_id: id) }
end
# will reset permission on a topic to a particular
@@ -527,11 +557,13 @@ class Category < ActiveRecord::Base
def permissions_params
hash = {}
- category_groups.includes(:group).each do |category_group|
- if category_group.group.present?
- hash[category_group.group_name] = category_group.permission_type
+ category_groups
+ .includes(:group)
+ .each do |category_group|
+ if category_group.group.present?
+ hash[category_group.group_name] = category_group.permission_type
+ end
end
- end
hash
end
@@ -551,17 +583,16 @@ class Category < ActiveRecord::Base
everyone = Group::AUTO_GROUPS[:everyone]
full = CategoryGroup.permission_types[:full]
- mapped = permissions.map do |group, permission|
- group_id = Group.group_id_from_param(group)
- permission = CategoryGroup.permission_types[permission] unless permission.is_a?(Integer)
+ mapped =
+ permissions.map do |group, permission|
+ group_id = Group.group_id_from_param(group)
+ permission = CategoryGroup.permission_types[permission] unless permission.is_a?(Integer)
- [group_id, permission]
- end
+ [group_id, permission]
+ end
mapped.each do |group, permission|
- if group == everyone && permission == full
- return [false, []]
- end
+ return false, [] if group == everyone && permission == full
read_restricted = false if group == everyone
end
@@ -587,7 +618,7 @@ class Category < ActiveRecord::Base
def auto_bump_limiter
return nil if num_auto_bump_daily.to_i == 0
- RateLimiter.new(nil, "auto_bump_limit_#{self.id}", 1, 86400 / num_auto_bump_daily.to_i)
+ RateLimiter.new(nil, "auto_bump_limit_#{self.id}", 1, 86_400 / num_auto_bump_daily.to_i)
end
def clear_auto_bump_cache!
@@ -597,10 +628,11 @@ class Category < ActiveRecord::Base
def self.auto_bump_topic!
bumped = false
- auto_bumps = CategoryCustomField
- .where(name: Category::NUM_AUTO_BUMP_DAILY)
- .where('NULLIF(value, \'\')::int > 0')
- .pluck(:category_id)
+ auto_bumps =
+ CategoryCustomField
+ .where(name: Category::NUM_AUTO_BUMP_DAILY)
+ .where('NULLIF(value, \'\')::int > 0')
+ .pluck(:category_id)
if (auto_bumps.length > 0)
auto_bumps.shuffle.each do |category_id|
@@ -625,23 +657,20 @@ class Category < ActiveRecord::Base
relation = Topic
- if filters.length > 0
- filters.each do |filter|
- relation = filter.call(relation)
- end
- end
+ filters.each { |filter| relation = filter.call(relation) } if filters.length > 0
- topic = relation
- .visible
- .listable_topics
- .exclude_scheduled_bump_topics
- .where(category_id: self.id)
- .where('id <> ?', self.topic_id)
- .where('bumped_at < ?', 1.day.ago)
- .where('pinned_at IS NULL AND NOT closed AND NOT archived')
- .order('bumped_at ASC')
- .limit(1)
- .first
+ topic =
+ relation
+ .visible
+ .listable_topics
+ .exclude_scheduled_bump_topics
+ .where(category_id: self.id)
+ .where("id <> ?", self.topic_id)
+ .where("bumped_at < ?", 1.day.ago)
+ .where("pinned_at IS NULL AND NOT closed AND NOT archived")
+ .order("bumped_at ASC")
+ .limit(1)
+ .first
if topic
topic.add_small_action(Discourse.system_user, "autobumped", nil, bump: true)
@@ -650,7 +679,6 @@ class Category < ActiveRecord::Base
else
false
end
-
end
def allowed_tags=(tag_names_arg)
@@ -662,13 +690,20 @@ class Category < ActiveRecord::Base
end
def required_tag_groups=(required_groups)
- map = Array(required_groups).map.with_index { |rg, i| [rg["name"], { min_count: rg["min_count"].to_i, order: i }] }.to_h
+ map =
+ Array(required_groups)
+ .map
+ .with_index { |rg, i| [rg["name"], { min_count: rg["min_count"].to_i, order: i }] }
+ .to_h
tag_groups = TagGroup.where(name: map.keys)
- self.category_required_tag_groups = tag_groups.map do |tag_group|
- attrs = map[tag_group.name]
- CategoryRequiredTagGroup.new(tag_group: tag_group, **attrs)
- end.sort_by(&:order)
+ self.category_required_tag_groups =
+ tag_groups
+ .map do |tag_group|
+ attrs = map[tag_group.name]
+ CategoryRequiredTagGroup.new(tag_group: tag_group, **attrs)
+ end
+ .sort_by(&:order)
end
def downcase_email
@@ -677,17 +712,32 @@ class Category < ActiveRecord::Base
def email_in_validator
return if self.email_in.blank?
- email_in.split("|").each do |email|
-
- escaped = Rack::Utils.escape_html(email)
- if !Email.is_valid?(email)
- self.errors.add(:base, I18n.t('category.errors.invalid_email_in', email: escaped))
- elsif group = Group.find_by_email(email)
- self.errors.add(:base, I18n.t('category.errors.email_already_used_in_group', email: escaped, group_name: Rack::Utils.escape_html(group.name)))
- elsif category = Category.where.not(id: self.id).find_by_email(email)
- self.errors.add(:base, I18n.t('category.errors.email_already_used_in_category', email: escaped, category_name: Rack::Utils.escape_html(category.name)))
+ email_in
+ .split("|")
+ .each do |email|
+ escaped = Rack::Utils.escape_html(email)
+ if !Email.is_valid?(email)
+ self.errors.add(:base, I18n.t("category.errors.invalid_email_in", email: escaped))
+ elsif group = Group.find_by_email(email)
+ self.errors.add(
+ :base,
+ I18n.t(
+ "category.errors.email_already_used_in_group",
+ email: escaped,
+ group_name: Rack::Utils.escape_html(group.name),
+ ),
+ )
+ elsif category = Category.where.not(id: self.id).find_by_email(email)
+ self.errors.add(
+ :base,
+ I18n.t(
+ "category.errors.email_already_used_in_category",
+ email: escaped,
+ category_name: Rack::Utils.escape_html(category.name),
+ ),
+ )
+ end
end
- end
end
def downcase_name
@@ -699,42 +749,45 @@ class Category < ActiveRecord::Base
end
def secure_group_ids
- if self.read_restricted?
- groups.pluck("groups.id")
- end
+ groups.pluck("groups.id") if self.read_restricted?
end
def update_latest
- latest_post_id = Post
- .order("posts.created_at desc")
- .where("NOT hidden")
- .joins("join topics on topics.id = topic_id")
- .where("topics.category_id = :id", id: self.id)
- .limit(1)
- .pluck("posts.id")
- .first
+ latest_post_id =
+ Post
+ .order("posts.created_at desc")
+ .where("NOT hidden")
+ .joins("join topics on topics.id = topic_id")
+ .where("topics.category_id = :id", id: self.id)
+ .limit(1)
+ .pluck("posts.id")
+ .first
- latest_topic_id = Topic
- .order("topics.created_at desc")
- .where("visible")
- .where("topics.category_id = :id", id: self.id)
- .limit(1)
- .pluck("topics.id")
- .first
+ latest_topic_id =
+ Topic
+ .order("topics.created_at desc")
+ .where("visible")
+ .where("topics.category_id = :id", id: self.id)
+ .limit(1)
+ .pluck("topics.id")
+ .first
self.update(latest_topic_id: latest_topic_id, latest_post_id: latest_post_id)
end
def self.query_parent_category(parent_slug)
- encoded_parent_slug = CGI.escape(parent_slug) if SiteSetting.slug_generation_method == 'encoded'
- self.where(slug: (encoded_parent_slug || parent_slug), parent_category_id: nil).pluck_first(:id) ||
- self.where(id: parent_slug.to_i).pluck_first(:id)
+ encoded_parent_slug = CGI.escape(parent_slug) if SiteSetting.slug_generation_method == "encoded"
+ self.where(slug: (encoded_parent_slug || parent_slug), parent_category_id: nil).pluck_first(
+ :id,
+ ) || self.where(id: parent_slug.to_i).pluck_first(:id)
end
def self.query_category(slug_or_id, parent_category_id)
- encoded_slug_or_id = CGI.escape(slug_or_id) if SiteSetting.slug_generation_method == 'encoded'
- self.where(slug: (encoded_slug_or_id || slug_or_id), parent_category_id: parent_category_id).first ||
- self.where(id: slug_or_id.to_i, parent_category_id: parent_category_id).first
+ encoded_slug_or_id = CGI.escape(slug_or_id) if SiteSetting.slug_generation_method == "encoded"
+ self.where(
+ slug: (encoded_slug_or_id || slug_or_id),
+ parent_category_id: parent_category_id,
+ ).first || self.where(id: slug_or_id.to_i, parent_category_id: parent_category_id).first
end
def self.find_by_email(email)
@@ -772,12 +825,16 @@ class Category < ActiveRecord::Base
def url
@@url_cache.defer_get_set(self.id) do
- "#{Discourse.base_path}/c/#{slug_path.join('/')}/#{self.id}"
+ "#{Discourse.base_path}/c/#{slug_path.join("/")}/#{self.id}"
end
end
def url_with_id
- Discourse.deprecate("Category#url_with_id is deprecated. Use `Category#url` instead.", output_in_test: true, drop_from: '2.9.0')
+ Discourse.deprecate(
+ "Category#url_with_id is deprecated. Use `Category#url` instead.",
+ output_in_test: true,
+ drop_from: "2.9.0",
+ )
url
end
@@ -795,7 +852,7 @@ class Category < ActiveRecord::Base
old_slug = saved_changes.transform_values(&:first)["slug"]
url = +"#{Discourse.base_path}/c"
- url << "/#{parent_category.slug_path.join('/')}" if parent_category_id
+ url << "/#{parent_category.slug_path.join("/")}" if parent_category_id
url << "/#{old_slug}/#{id}"
url = Permalink.normalize_url(url)
@@ -807,7 +864,7 @@ class Category < ActiveRecord::Base
end
def delete_category_permalink
- permalink = Permalink.find_by_url("c/#{slug_path.join('/')}")
+ permalink = Permalink.find_by_url("c/#{slug_path.join("/")}")
permalink.destroy if permalink
end
@@ -816,7 +873,8 @@ class Category < ActiveRecord::Base
end
def index_search
- Jobs.enqueue(:index_category_for_search,
+ Jobs.enqueue(
+ :index_category_for_search,
category_id: self.id,
force: saved_change_to_attribute?(:name),
)
@@ -832,9 +890,7 @@ class Category < ActiveRecord::Base
return nil if slug_path.empty?
return nil if slug_path.size > SiteSetting.max_category_nesting
- slug_path.map! do |slug|
- CGI.escape(slug.downcase)
- end
+ slug_path.map! { |slug| CGI.escape(slug.downcase) }
query =
slug_path.inject(nil) do |parent_id, slug|
@@ -871,11 +927,7 @@ class Category < ActiveRecord::Base
subcategory_list_style.end_with?("with_featured_topics")
end
- %i{
- category_created
- category_updated
- category_destroyed
- }.each do |event|
+ %i[category_created category_updated category_destroyed].each do |event|
define_method("trigger_#{event}_event") do
DiscourseEvent.trigger(event, self)
true
@@ -888,10 +940,17 @@ class Category < ActiveRecord::Base
return if parent_category.category_groups.empty?
parent_permissions = parent_category.category_groups.pluck(:group_id, :permission_type)
- child_permissions = @permissions.empty? ? [[Group[:everyone].id, CategoryGroup.permission_types[:full]]] : @permissions
+ child_permissions =
+ (
+ if @permissions.empty?
+ [[Group[:everyone].id, CategoryGroup.permission_types[:full]]]
+ else
+ @permissions
+ end
+ )
check_permissions_compatibility(parent_permissions, child_permissions)
- # when saving parent category
+ # when saving parent category
elsif @permissions && subcategories.present?
return if @permissions.empty?
@@ -903,7 +962,6 @@ class Category < ActiveRecord::Base
end
def self.ensure_consistency!
-
sql = <<~SQL
SELECT t.id FROM topics t
JOIN categories c ON c.topic_id = t.id
@@ -911,9 +969,7 @@ class Category < ActiveRecord::Base
WHERE p.id IS NULL
SQL
- DB.query_single(sql).each do |id|
- Topic.with_deleted.find_by(id: id).destroy!
- end
+ DB.query_single(sql).each { |id| Topic.with_deleted.find_by(id: id).destroy! }
sql = <<~SQL
UPDATE categories c
@@ -928,12 +984,10 @@ class Category < ActiveRecord::Base
DB.exec(sql)
Category
- .joins('LEFT JOIN topics ON categories.topic_id = topics.id AND topics.deleted_at IS NULL')
- .where('categories.id <> ?', SiteSetting.uncategorized_category_id)
+ .joins("LEFT JOIN topics ON categories.topic_id = topics.id AND topics.deleted_at IS NULL")
+ .where("categories.id <> ?", SiteSetting.uncategorized_category_id)
.where(topics: { id: nil })
- .find_each do |category|
- category.create_category_definition
- end
+ .find_each { |category| category.create_category_definition }
end
def slug_path
@@ -947,16 +1001,20 @@ class Category < ActiveRecord::Base
end
def cannot_delete_reason
- return I18n.t('category.cannot_delete.uncategorized') if self.uncategorized?
- return I18n.t('category.cannot_delete.has_subcategories') if self.has_children?
+ return I18n.t("category.cannot_delete.uncategorized") if self.uncategorized?
+ return I18n.t("category.cannot_delete.has_subcategories") if self.has_children?
if self.topic_count != 0
- oldest_topic = self.topics.where.not(id: self.topic_id).order('created_at ASC').limit(1).first
+ oldest_topic = self.topics.where.not(id: self.topic_id).order("created_at ASC").limit(1).first
if oldest_topic
- I18n.t('category.cannot_delete.topic_exists', count: self.topic_count, topic_link: "#{CGI.escapeHTML(oldest_topic.title)}")
+ I18n.t(
+ "category.cannot_delete.topic_exists",
+ count: self.topic_count,
+ topic_link: "#{CGI.escapeHTML(oldest_topic.title)}",
+ )
else
# This is a weird case, probably indicating a bug.
- I18n.t('category.cannot_delete.topic_exists_no_oldest', count: self.topic_count)
+ I18n.t("category.cannot_delete.topic_exists_no_oldest", count: self.topic_count)
end
end
end
@@ -989,8 +1047,7 @@ class Category < ActiveRecord::Base
everyone = Group[:everyone].id
full = CategoryGroup.permission_types[:full]
- result =
- DB.query(<<-SQL, id: id, everyone: everyone, full: full)
+ result = DB.query(<<-SQL, id: id, everyone: everyone, full: full)
SELECT category_groups.group_id, category_groups.permission_type
FROM categories, category_groups
WHERE categories.parent_category_id = :id
diff --git a/app/models/category_featured_topic.rb b/app/models/category_featured_topic.rb
index 0e4a53ef551..1602dc7ad09 100644
--- a/app/models/category_featured_topic.rb
+++ b/app/models/category_featured_topic.rb
@@ -4,38 +4,40 @@ class CategoryFeaturedTopic < ActiveRecord::Base
belongs_to :category
belongs_to :topic
- NEXT_CATEGORY_ID_KEY = 'category-featured-topic:next-category-id'
+ NEXT_CATEGORY_ID_KEY = "category-featured-topic:next-category-id"
DEFAULT_BATCH_SIZE = 100
# Populates the category featured topics.
def self.feature_topics(batched: false, batch_size: nil)
current = {}
- CategoryFeaturedTopic.select(:topic_id, :category_id).order(:rank).each do |f|
- (current[f.category_id] ||= []) << f.topic_id
- end
+ CategoryFeaturedTopic
+ .select(:topic_id, :category_id)
+ .order(:rank)
+ .each { |f| (current[f.category_id] ||= []) << f.topic_id }
batch_size ||= DEFAULT_BATCH_SIZE
next_category_id = batched ? Discourse.redis.get(NEXT_CATEGORY_ID_KEY).to_i : 0
- categories = Category.select(:id, :topic_id, :num_featured_topics)
- .where('id >= ?', next_category_id)
- .order('id ASC')
- .limit(batch_size)
- .to_a
+ categories =
+ Category
+ .select(:id, :topic_id, :num_featured_topics)
+ .where("id >= ?", next_category_id)
+ .order("id ASC")
+ .limit(batch_size)
+ .to_a
if batched
if categories.length == batch_size
- next_id = Category.where('id > ?', categories.last.id).order('id asc').limit(1).pluck(:id)[0]
+ next_id =
+ Category.where("id > ?", categories.last.id).order("id asc").limit(1).pluck(:id)[0]
next_id ? Discourse.redis.setex(NEXT_CATEGORY_ID_KEY, 1.day, next_id) : clear_batch!
else
clear_batch!
end
end
- categories.each do |c|
- CategoryFeaturedTopic.feature_topics_for(c, current[c.id] || [])
- end
+ categories.each { |c| CategoryFeaturedTopic.feature_topics_for(c, current[c.id] || []) }
end
def self.clear_batch!
@@ -49,7 +51,7 @@ class CategoryFeaturedTopic < ActiveRecord::Base
per_page: c.num_featured_topics,
except_topic_ids: [c.topic_id],
visible: true,
- no_definitions: true
+ no_definitions: true,
}
# It may seem a bit odd that we are running 2 queries here, when admin
diff --git a/app/models/category_group.rb b/app/models/category_group.rb
index a4f5b51ef9d..5f0b34cbdcb 100644
--- a/app/models/category_group.rb
+++ b/app/models/category_group.rb
@@ -9,7 +9,6 @@ class CategoryGroup < ActiveRecord::Base
def self.permission_types
@permission_types ||= Enum.new(full: 1, create_post: 2, readonly: 3)
end
-
end
# == Schema Information
diff --git a/app/models/category_list.rb b/app/models/category_list.rb
index 21ebb279c82..38a55042a78 100644
--- a/app/models/category_list.rb
+++ b/app/models/category_list.rb
@@ -6,8 +6,7 @@ class CategoryList
cattr_accessor :preloaded_topic_custom_fields
self.preloaded_topic_custom_fields = Set.new
- attr_accessor :categories,
- :uncategorized
+ attr_accessor :categories, :uncategorized
def initialize(guardian = nil, options = {})
@guardian = guardian || Guardian.new
@@ -28,13 +27,9 @@ class CategoryList
displayable_topics.compact!
if displayable_topics.present?
- Topic.preload_custom_fields(
- displayable_topics,
- preloaded_topic_custom_fields
- )
+ Topic.preload_custom_fields(displayable_topics, preloaded_topic_custom_fields)
end
end
-
end
def preload_key
@@ -46,11 +41,12 @@ class CategoryList
categories.order(:position, :id)
else
allowed_category_ids = categories.pluck(:id) << nil # `nil` is necessary to include categories without any associated topics
- categories.left_outer_joins(:featured_topics)
+ categories
+ .left_outer_joins(:featured_topics)
.where(topics: { category_id: allowed_category_ids })
- .group('categories.id')
+ .group("categories.id")
.order("max(topics.bumped_at) DESC NULLS LAST")
- .order('categories.id ASC')
+ .order("categories.id ASC")
end
end
@@ -60,22 +56,27 @@ class CategoryList
@topics_by_id = {}
@topics_by_category_id = {}
- category_featured_topics = CategoryFeaturedTopic.select([:category_id, :topic_id]).order(:rank)
+ category_featured_topics = CategoryFeaturedTopic.select(%i[category_id topic_id]).order(:rank)
- @all_topics = Topic
- .where(id: category_featured_topics.map(&:topic_id))
- .includes(
+ @all_topics =
+ Topic.where(id: category_featured_topics.map(&:topic_id)).includes(
:shared_draft,
:category,
- { topic_thumbnails: [:optimized_image, :upload] }
+ { topic_thumbnails: %i[optimized_image upload] },
)
- @all_topics = @all_topics.joins(:tags).where(tags: { name: @options[:tag] }) if @options[:tag].present?
+ @all_topics = @all_topics.joins(:tags).where(tags: { name: @options[:tag] }) if @options[
+ :tag
+ ].present?
if @guardian.authenticated?
- @all_topics = @all_topics
- .joins("LEFT JOIN topic_users tu ON topics.id = tu.topic_id AND tu.user_id = #{@guardian.user.id.to_i}")
- .where('COALESCE(tu.notification_level,1) > :muted', muted: TopicUser.notification_levels[:muted])
+ @all_topics =
+ @all_topics.joins(
+ "LEFT JOIN topic_users tu ON topics.id = tu.topic_id AND tu.user_id = #{@guardian.user.id.to_i}",
+ ).where(
+ "COALESCE(tu.notification_level,1) > :muted",
+ muted: TopicUser.notification_levels[:muted],
+ )
end
@all_topics = TopicQuery.remove_muted_tags(@all_topics, @guardian.user).includes(:last_poster)
@@ -94,7 +95,8 @@ class CategoryList
def dismissed_topic?(topic)
if @guardian.current_user
- @dismissed_topic_users_lookup ||= DismissedTopicUser.lookup_for(@guardian.current_user, @all_topics)
+ @dismissed_topic_users_lookup ||=
+ DismissedTopicUser.lookup_for(@guardian.current_user, @all_topics)
@dismissed_topic_users_lookup.include?(topic.id)
else
false
@@ -102,15 +104,20 @@ class CategoryList
end
def find_categories
- @categories = Category.includes(
- :uploaded_background,
- :uploaded_logo,
- :uploaded_logo_dark,
- :topic_only_relative_url,
- subcategories: [:topic_only_relative_url]
- ).secured(@guardian)
+ @categories =
+ Category.includes(
+ :uploaded_background,
+ :uploaded_logo,
+ :uploaded_logo_dark,
+ :topic_only_relative_url,
+ subcategories: [:topic_only_relative_url],
+ ).secured(@guardian)
- @categories = @categories.where("categories.parent_category_id = ?", @options[:parent_category_id].to_i) if @options[:parent_category_id].present?
+ @categories =
+ @categories.where(
+ "categories.parent_category_id = ?",
+ @options[:parent_category_id].to_i,
+ ) if @options[:parent_category_id].present?
@categories = self.class.order_categories(@categories)
@@ -138,9 +145,7 @@ class CategoryList
end
@categories.each do |c|
c.subcategory_ids = subcategory_ids[c.id] || []
- if include_subcategories
- c.subcategory_list = subcategory_list[c.id] || []
- end
+ c.subcategory_list = subcategory_list[c.id] || [] if include_subcategories
end
@categories.delete_if { |c| to_delete.include?(c) }
end
@@ -149,7 +154,9 @@ class CategoryList
categories_with_descendants.each do |category|
category.notification_level = notification_levels[category.id] || default_notification_level
- category.permission = CategoryGroup.permission_types[:full] if allowed_topic_create.include?(category.id)
+ category.permission = CategoryGroup.permission_types[:full] if allowed_topic_create.include?(
+ category.id,
+ )
category.has_children = category.subcategories.present?
end
@@ -193,9 +200,7 @@ class CategoryList
c.displayable_topics.each do |t|
unpinned << t if t.pinned_at && PinnedCheck.unpinned?(t, t.user_data)
end
- unless unpinned.empty?
- c.displayable_topics = (c.displayable_topics - unpinned) + unpinned
- end
+ c.displayable_topics = (c.displayable_topics - unpinned) + unpinned unless unpinned.empty?
end
end
end
@@ -217,9 +222,7 @@ class CategoryList
return @categories_with_children if @categories_with_children && (categories == @categories)
return nil if categories.nil?
- result = categories.flat_map do |c|
- [c, *categories_with_descendants(c.subcategory_list)]
- end
+ result = categories.flat_map { |c| [c, *categories_with_descendants(c.subcategory_list)] }
@categories_with_children = result if categories == @categories
diff --git a/app/models/category_page_style.rb b/app/models/category_page_style.rb
index cf6381d58e6..fe8c5d41978 100644
--- a/app/models/category_page_style.rb
+++ b/app/models/category_page_style.rb
@@ -3,26 +3,39 @@
require "enum_site_setting"
class CategoryPageStyle < EnumSiteSetting
-
def self.valid_value?(val)
values.any? { |v| v[:value].to_s == val.to_s }
end
def self.values
@values ||= [
- { name: 'category_page_style.categories_only', value: 'categories_only' },
- { name: 'category_page_style.categories_with_featured_topics', value: 'categories_with_featured_topics' },
- { name: 'category_page_style.categories_and_latest_topics_created_date', value: 'categories_and_latest_topics_created_date' },
- { name: 'category_page_style.categories_and_latest_topics', value: 'categories_and_latest_topics' },
- { name: 'category_page_style.categories_and_top_topics', value: 'categories_and_top_topics' },
- { name: 'category_page_style.categories_boxes', value: 'categories_boxes' },
- { name: 'category_page_style.categories_boxes_with_topics', value: 'categories_boxes_with_topics' },
- { name: 'category_page_style.subcategories_with_featured_topics', value: 'subcategories_with_featured_topics' },
+ { name: "category_page_style.categories_only", value: "categories_only" },
+ {
+ name: "category_page_style.categories_with_featured_topics",
+ value: "categories_with_featured_topics",
+ },
+ {
+ name: "category_page_style.categories_and_latest_topics_created_date",
+ value: "categories_and_latest_topics_created_date",
+ },
+ {
+ name: "category_page_style.categories_and_latest_topics",
+ value: "categories_and_latest_topics",
+ },
+ { name: "category_page_style.categories_and_top_topics", value: "categories_and_top_topics" },
+ { name: "category_page_style.categories_boxes", value: "categories_boxes" },
+ {
+ name: "category_page_style.categories_boxes_with_topics",
+ value: "categories_boxes_with_topics",
+ },
+ {
+ name: "category_page_style.subcategories_with_featured_topics",
+ value: "subcategories_with_featured_topics",
+ },
]
end
def self.translate_names?
true
end
-
end
diff --git a/app/models/category_required_tag_group.rb b/app/models/category_required_tag_group.rb
index 50d9ef6ab6a..695b838f81f 100644
--- a/app/models/category_required_tag_group.rb
+++ b/app/models/category_required_tag_group.rb
@@ -6,9 +6,7 @@ class CategoryRequiredTagGroup < ActiveRecord::Base
validates :min_count, numericality: { only_integer: true, greater_than: 0 }
- after_commit do
- Site.clear_cache
- end
+ after_commit { Site.clear_cache }
end
# == Schema Information
diff --git a/app/models/category_tag.rb b/app/models/category_tag.rb
index e9cba7c189e..dad98b922ba 100644
--- a/app/models/category_tag.rb
+++ b/app/models/category_tag.rb
@@ -4,9 +4,7 @@ class CategoryTag < ActiveRecord::Base
belongs_to :category
belongs_to :tag
- after_commit do
- Site.clear_cache
- end
+ after_commit { Site.clear_cache }
end
# == Schema Information
diff --git a/app/models/category_tag_group.rb b/app/models/category_tag_group.rb
index ea27bc50c15..6122a00acf6 100644
--- a/app/models/category_tag_group.rb
+++ b/app/models/category_tag_group.rb
@@ -4,9 +4,7 @@ class CategoryTagGroup < ActiveRecord::Base
belongs_to :category
belongs_to :tag_group
- after_commit do
- Site.clear_cache
- end
+ after_commit { Site.clear_cache }
end
# == Schema Information
diff --git a/app/models/category_tag_stat.rb b/app/models/category_tag_stat.rb
index 5f2b1410a1c..478aa069cc2 100644
--- a/app/models/category_tag_stat.rb
+++ b/app/models/category_tag_stat.rb
@@ -6,9 +6,10 @@ class CategoryTagStat < ActiveRecord::Base
def self.topic_moved(topic, from_category_id, to_category_id)
if from_category_id
- self.where(tag_id: topic.tags.map(&:id), category_id: from_category_id)
- .where('topic_count > 0')
- .update_all('topic_count = topic_count - 1')
+ self
+ .where(tag_id: topic.tags.map(&:id), category_id: from_category_id)
+ .where("topic_count > 0")
+ .update_all("topic_count = topic_count - 1")
end
if to_category_id
diff --git a/app/models/category_user.rb b/app/models/category_user.rb
index b07ac73e713..4623567656f 100644
--- a/app/models/category_user.rb
+++ b/app/models/category_user.rb
@@ -23,27 +23,24 @@ class CategoryUser < ActiveRecord::Base
changed = false
# Update pre-existing category users
- if category_ids.present? && CategoryUser
- .where(user_id: user.id, category_id: category_ids)
- .where.not(notification_level: level_num)
- .update_all(notification_level: level_num) > 0
-
+ if category_ids.present? &&
+ CategoryUser
+ .where(user_id: user.id, category_id: category_ids)
+ .where.not(notification_level: level_num)
+ .update_all(notification_level: level_num) > 0
changed = true
end
# Remove extraneous category users
- if CategoryUser.where(user_id: user.id, notification_level: level_num)
- .where.not(category_id: category_ids)
- .delete_all > 0
-
+ if CategoryUser
+ .where(user_id: user.id, notification_level: level_num)
+ .where.not(category_id: category_ids)
+ .delete_all > 0
changed = true
end
if category_ids.present?
- params = {
- user_id: user.id,
- level_num: level_num,
- }
+ params = { user_id: user.id, level_num: level_num }
sql = <<~SQL
INSERT INTO category_users (user_id, category_id, notification_level)
@@ -55,11 +52,8 @@ class CategoryUser < ActiveRecord::Base
# into the query, plus it is a bit of a micro optimisation
category_ids.each do |category_id|
params[:category_id] = category_id
- if DB.exec(sql, params) > 0
- changed = true
- end
+ changed = true if DB.exec(sql, params) > 0
end
-
end
if changed
@@ -91,7 +85,6 @@ class CategoryUser < ActiveRecord::Base
end
def self.auto_track(opts = {})
-
builder = DB.build <<~SQL
UPDATE topic_users tu
SET notification_level = :tracking,
@@ -100,11 +93,13 @@ class CategoryUser < ActiveRecord::Base
/*where*/
SQL
- builder.where("tu.topic_id = t.id AND
+ builder.where(
+ "tu.topic_id = t.id AND
cu.category_id = t.category_id AND
cu.user_id = tu.user_id AND
cu.notification_level = :tracking AND
- tu.notification_level = :regular")
+ tu.notification_level = :regular",
+ )
if category_id = opts[:category_id]
builder.where("t.category_id = :category_id", category_id: category_id)
@@ -121,12 +116,11 @@ class CategoryUser < ActiveRecord::Base
builder.exec(
tracking: notification_levels[:tracking],
regular: notification_levels[:regular],
- auto_track_category: TopicUser.notification_reasons[:auto_track_category]
+ auto_track_category: TopicUser.notification_reasons[:auto_track_category],
)
end
def self.auto_watch(opts = {})
-
builder = DB.build <<~SQL
UPDATE topic_users tu
SET notification_level =
@@ -181,9 +175,8 @@ class CategoryUser < ActiveRecord::Base
watching: notification_levels[:watching],
tracking: notification_levels[:tracking],
regular: notification_levels[:regular],
- auto_watch_category: TopicUser.notification_reasons[:auto_watch_category]
+ auto_watch_category: TopicUser.notification_reasons[:auto_watch_category],
)
-
end
def self.ensure_consistency!
@@ -198,25 +191,30 @@ class CategoryUser < ActiveRecord::Base
end
def self.default_notification_level
- SiteSetting.mute_all_categories_by_default ? notification_levels[:muted] : notification_levels[:regular]
+ if SiteSetting.mute_all_categories_by_default
+ notification_levels[:muted]
+ else
+ notification_levels[:regular]
+ end
end
def self.notification_levels_for(user)
# Anonymous users have all default categories set to regular tracking,
# except for default muted categories which stay muted.
if user.blank?
- notification_levels = [
- SiteSetting.default_categories_watching.split("|"),
- SiteSetting.default_categories_tracking.split("|"),
- SiteSetting.default_categories_watching_first_post.split("|"),
- SiteSetting.default_categories_normal.split("|")
- ].flatten.map do |id|
- [id.to_i, self.notification_levels[:regular]]
- end
+ notification_levels =
+ [
+ SiteSetting.default_categories_watching.split("|"),
+ SiteSetting.default_categories_tracking.split("|"),
+ SiteSetting.default_categories_watching_first_post.split("|"),
+ SiteSetting.default_categories_normal.split("|"),
+ ].flatten.map { |id| [id.to_i, self.notification_levels[:regular]] }
- notification_levels += SiteSetting.default_categories_muted.split("|").map do |id|
- [id.to_i, self.notification_levels[:muted]]
- end
+ notification_levels +=
+ SiteSetting
+ .default_categories_muted
+ .split("|")
+ .map { |id| [id.to_i, self.notification_levels[:muted]] }
else
notification_levels = CategoryUser.where(user: user).pluck(:category_id, :notification_level)
end
@@ -238,22 +236,32 @@ class CategoryUser < ActiveRecord::Base
def self.muted_category_ids_query(user, include_direct: false)
query = Category
query = query.where.not(parent_category_id: nil) if !include_direct
- query = query
- .joins("LEFT JOIN categories categories2 ON categories2.id = categories.parent_category_id")
- .joins("LEFT JOIN category_users ON category_users.category_id = categories.id AND category_users.user_id = #{user.id}")
- .joins("LEFT JOIN category_users category_users2 ON category_users2.category_id = categories2.id AND category_users2.user_id = #{user.id}")
+ query =
+ query
+ .joins("LEFT JOIN categories categories2 ON categories2.id = categories.parent_category_id")
+ .joins(
+ "LEFT JOIN category_users ON category_users.category_id = categories.id AND category_users.user_id = #{user.id}",
+ )
+ .joins(
+ "LEFT JOIN category_users category_users2 ON category_users2.category_id = categories2.id AND category_users2.user_id = #{user.id}",
+ )
- direct_category_muted_sql = "COALESCE(category_users.notification_level, #{CategoryUser.default_notification_level}) = #{CategoryUser.notification_levels[:muted]}"
+ direct_category_muted_sql =
+ "COALESCE(category_users.notification_level, #{CategoryUser.default_notification_level}) = #{CategoryUser.notification_levels[:muted]}"
parent_category_muted_sql =
"(category_users.id IS NULL AND COALESCE(category_users2.notification_level, #{CategoryUser.default_notification_level}) = #{notification_levels[:muted]})"
conditions = [parent_category_muted_sql]
conditions.push(direct_category_muted_sql) if include_direct
if SiteSetting.max_category_nesting === 3
- query = query
- .joins("LEFT JOIN categories categories3 ON categories3.id = categories2.parent_category_id")
- .joins("LEFT JOIN category_users category_users3 ON category_users3.category_id = categories3.id AND category_users3.user_id = #{user.id}")
- grandparent_category_muted_sql = "(category_users.id IS NULL AND category_users2.id IS NULL AND COALESCE(category_users3.notification_level, #{CategoryUser.default_notification_level}) = #{notification_levels[:muted]})"
+ query =
+ query.joins(
+ "LEFT JOIN categories categories3 ON categories3.id = categories2.parent_category_id",
+ ).joins(
+ "LEFT JOIN category_users category_users3 ON category_users3.category_id = categories3.id AND category_users3.user_id = #{user.id}",
+ )
+ grandparent_category_muted_sql =
+ "(category_users.id IS NULL AND category_users2.id IS NULL AND COALESCE(category_users3.notification_level, #{CategoryUser.default_notification_level}) = #{notification_levels[:muted]})"
conditions.push(grandparent_category_muted_sql)
end
diff --git a/app/models/child_theme.rb b/app/models/child_theme.rb
index 7ce4d0dc78b..2f29e6c7b71 100644
--- a/app/models/child_theme.rb
+++ b/app/models/child_theme.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
class ChildTheme < ActiveRecord::Base
- belongs_to :parent_theme, class_name: 'Theme'
- belongs_to :child_theme, class_name: 'Theme'
+ belongs_to :parent_theme, class_name: "Theme"
+ belongs_to :child_theme, class_name: "Theme"
validate :child_validations
@@ -11,7 +11,8 @@ class ChildTheme < ActiveRecord::Base
def child_validations
if Theme.where(
"(component IS true AND id = :parent) OR (component IS false AND id = :child)",
- parent: parent_theme_id, child: child_theme_id
+ parent: parent_theme_id,
+ child: child_theme_id,
).exists?
errors.add(:base, I18n.t("themes.errors.no_multilevels_components"))
end
diff --git a/app/models/color_scheme.rb b/app/models/color_scheme.rb
index bdbef6df9e4..99a1ee75fff 100644
--- a/app/models/color_scheme.rb
+++ b/app/models/color_scheme.rb
@@ -1,173 +1,172 @@
# frozen_string_literal: true
class ColorScheme < ActiveRecord::Base
-
# rubocop:disable Layout/HashAlignment
CUSTOM_SCHEMES = {
- 'Dark': {
- "primary" => 'dddddd',
- "secondary" => '222222',
- "tertiary" => '0f82af',
- "quaternary" => 'c14924',
- "header_background" => '111111',
- "header_primary" => 'dddddd',
- "highlight" => 'a87137',
- "danger" => 'e45735',
- "success" => '1ca551',
- "love" => 'fa6c8d'
+ Dark: {
+ "primary" => "dddddd",
+ "secondary" => "222222",
+ "tertiary" => "0f82af",
+ "quaternary" => "c14924",
+ "header_background" => "111111",
+ "header_primary" => "dddddd",
+ "highlight" => "a87137",
+ "danger" => "e45735",
+ "success" => "1ca551",
+ "love" => "fa6c8d",
},
# By @itsbhanusharma
- 'Neutral': {
- "primary" => '000000',
- "secondary" => 'ffffff',
- "tertiary" => '51839b',
- "quaternary" => 'b85e48',
- "header_background" => '333333',
- "header_primary" => 'f3f3f3',
- "highlight" => 'ecec70',
- "danger" => 'b85e48',
- "success" => '518751',
- "love" => 'fa6c8d'
+ Neutral: {
+ "primary" => "000000",
+ "secondary" => "ffffff",
+ "tertiary" => "51839b",
+ "quaternary" => "b85e48",
+ "header_background" => "333333",
+ "header_primary" => "f3f3f3",
+ "highlight" => "ecec70",
+ "danger" => "b85e48",
+ "success" => "518751",
+ "love" => "fa6c8d",
},
# By @Flower_Child
- 'Grey Amber': {
- "primary" => 'd9d9d9',
- "secondary" => '3d4147',
- "tertiary" => 'fdd459',
- "quaternary" => 'fdd459',
- "header_background" => '36393e',
- "header_primary" => 'd9d9d9',
- "highlight" => 'fdd459',
- "danger" => 'e45735',
- "success" => 'fdd459',
- "love" => 'fdd459'
+ "Grey Amber": {
+ "primary" => "d9d9d9",
+ "secondary" => "3d4147",
+ "tertiary" => "fdd459",
+ "quaternary" => "fdd459",
+ "header_background" => "36393e",
+ "header_primary" => "d9d9d9",
+ "highlight" => "fdd459",
+ "danger" => "e45735",
+ "success" => "fdd459",
+ "love" => "fdd459",
},
# By @rafafotes
- 'Shades of Blue': {
- "primary" => '203243',
- "secondary" => 'eef4f7',
- "tertiary" => '416376',
- "quaternary" => '5e99b9',
- "header_background" => '86bddb',
- "header_primary" => '203243',
- "highlight" => '86bddb',
- "danger" => 'bf3c3c',
- "success" => '70db82',
- "love" => 'fc94cb'
+ "Shades of Blue": {
+ "primary" => "203243",
+ "secondary" => "eef4f7",
+ "tertiary" => "416376",
+ "quaternary" => "5e99b9",
+ "header_background" => "86bddb",
+ "header_primary" => "203243",
+ "highlight" => "86bddb",
+ "danger" => "bf3c3c",
+ "success" => "70db82",
+ "love" => "fc94cb",
},
# By @mikechristopher
- 'Latte': {
- "primary" => 'f2e5d7',
- "secondary" => '262322',
- "tertiary" => 'f7f2ed',
- "quaternary" => 'd7c9aa',
- "header_background" => 'd7c9aa',
- "header_primary" => '262322',
- "highlight" => 'd7c9aa',
- "danger" => 'db9584',
- "success" => '78be78',
- "love" => '8f6201'
+ Latte: {
+ "primary" => "f2e5d7",
+ "secondary" => "262322",
+ "tertiary" => "f7f2ed",
+ "quaternary" => "d7c9aa",
+ "header_background" => "d7c9aa",
+ "header_primary" => "262322",
+ "highlight" => "d7c9aa",
+ "danger" => "db9584",
+ "success" => "78be78",
+ "love" => "8f6201",
},
# By @Flower_Child
- 'Summer': {
- "primary" => '874342',
- "secondary" => 'fffff4',
- "tertiary" => 'fe9896',
- "quaternary" => 'fcc9d0',
- "header_background" => '96ccbf',
- "header_primary" => 'fff1e7',
- "highlight" => 'f3c07f',
- "danger" => 'cfebdc',
- "success" => 'fcb4b5',
- "love" => 'f3c07f'
+ Summer: {
+ "primary" => "874342",
+ "secondary" => "fffff4",
+ "tertiary" => "fe9896",
+ "quaternary" => "fcc9d0",
+ "header_background" => "96ccbf",
+ "header_primary" => "fff1e7",
+ "highlight" => "f3c07f",
+ "danger" => "cfebdc",
+ "success" => "fcb4b5",
+ "love" => "f3c07f",
},
# By @Flower_Child
- 'Dark Rose': {
- "primary" => 'ca9cb2',
- "secondary" => '3a2a37',
- "tertiary" => 'fdd459',
- "quaternary" => '7e566a',
- "header_background" => 'a97189',
- "header_primary" => 'd9b2bb',
- "highlight" => '6c3e63',
- "danger" => '6c3e63',
- "success" => 'd9b2bb',
- "love" => 'd9b2bb'
+ "Dark Rose": {
+ "primary" => "ca9cb2",
+ "secondary" => "3a2a37",
+ "tertiary" => "fdd459",
+ "quaternary" => "7e566a",
+ "header_background" => "a97189",
+ "header_primary" => "d9b2bb",
+ "highlight" => "6c3e63",
+ "danger" => "6c3e63",
+ "success" => "d9b2bb",
+ "love" => "d9b2bb",
},
- "WCAG": {
- "primary" => '000000',
- "primary-medium" => '696969',
- "primary-low-mid" => '909090',
- "secondary" => 'ffffff',
- "tertiary" => '3369FF',
- "quaternary" => '3369FF',
- "header_background" => 'ffffff',
- "header_primary" => '000000',
- "highlight" => '3369FF',
- "highlight-high" => '0036E6',
- "highlight-medium" => 'e0e9ff',
- "highlight-low" => 'e0e9ff',
- "danger" => 'BB1122',
- "success" => '3d854d',
- "love" => '9D256B'
+ WCAG: {
+ "primary" => "000000",
+ "primary-medium" => "696969",
+ "primary-low-mid" => "909090",
+ "secondary" => "ffffff",
+ "tertiary" => "3369FF",
+ "quaternary" => "3369FF",
+ "header_background" => "ffffff",
+ "header_primary" => "000000",
+ "highlight" => "3369FF",
+ "highlight-high" => "0036E6",
+ "highlight-medium" => "e0e9ff",
+ "highlight-low" => "e0e9ff",
+ "danger" => "BB1122",
+ "success" => "3d854d",
+ "love" => "9D256B",
},
"WCAG Dark": {
- "primary" => 'ffffff',
- "primary-medium" => '999999',
- "primary-low-mid" => '888888',
- "secondary" => '0c0c0c',
- "tertiary" => '759AFF',
- "quaternary" => '759AFF',
- "header_background" => '000000',
- "header_primary" => 'ffffff',
- "highlight" => '3369FF',
- "danger" => 'BB1122',
- "success" => '3d854d',
- "love" => '9D256B'
+ "primary" => "ffffff",
+ "primary-medium" => "999999",
+ "primary-low-mid" => "888888",
+ "secondary" => "0c0c0c",
+ "tertiary" => "759AFF",
+ "quaternary" => "759AFF",
+ "header_background" => "000000",
+ "header_primary" => "ffffff",
+ "highlight" => "3369FF",
+ "danger" => "BB1122",
+ "success" => "3d854d",
+ "love" => "9D256B",
},
# By @zenorocha
- "Dracula": {
+ Dracula: {
"primary_very_low" => "373A47",
"primary_low" => "414350",
"primary_low_mid" => "8C8D94",
"primary_medium" => "A3A4AA",
"primary_high" => "CCCCCF",
- "primary" => 'f2f2f2',
- "primary-50" => '3F414E',
- "primary-100" => '535460',
- "primary-200" => '666972',
- "primary-300" => '7A7C84',
- "primary-400" => '8D8F96',
- "primary-500" => 'A2A3A9',
- "primary-600" => 'B6B7BC',
- "primary-700" => 'C7C7C7',
- "primary-800" => 'DEDFE0',
- "primary-900" => 'F5F5F5',
+ "primary" => "f2f2f2",
+ "primary-50" => "3F414E",
+ "primary-100" => "535460",
+ "primary-200" => "666972",
+ "primary-300" => "7A7C84",
+ "primary-400" => "8D8F96",
+ "primary-500" => "A2A3A9",
+ "primary-600" => "B6B7BC",
+ "primary-700" => "C7C7C7",
+ "primary-800" => "DEDFE0",
+ "primary-900" => "F5F5F5",
"secondary_low" => "CCCCCF",
"secondary_medium" => "91939A",
"secondary_high" => "6A6C76",
"secondary_very_high" => "3D404C",
- "secondary" => '2d303e',
+ "secondary" => "2d303e",
"tertiary_low" => "4A4463",
"tertiary_medium" => "6E5D92",
- "tertiary" => 'bd93f9',
+ "tertiary" => "bd93f9",
"tertiary_high" => "9275C1",
"quaternary_low" => "6AA8BA",
- "quaternary" => '8be9fd',
- "header_background" => '373A47',
- "header_primary" => 'f2f2f2',
+ "quaternary" => "8be9fd",
+ "header_background" => "373A47",
+ "header_primary" => "f2f2f2",
"highlight_low" => "686D55",
"highlight_medium" => "52592B",
- "highlight" => '52592B',
+ "highlight" => "52592B",
"highlight_high" => "C0C879",
"danger_low" => "957279",
- "danger" => 'ff5555',
+ "danger" => "ff5555",
"success_low" => "386D50",
"success_medium" => "44B366",
- "success" => '50fa7b',
+ "success" => "50fa7b",
"love_low" => "6C4667",
- "love" => 'ff79c6'
+ "love" => "ff79c6",
},
# By @altercation
"Solarized Light": {
@@ -176,40 +175,40 @@ class ColorScheme < ActiveRecord::Base
"primary_low_mid" => "A4AFA5",
"primary_medium" => "7E918C",
"primary_high" => "4C6869",
- "primary" => '002B36',
- "primary-50" => 'F0EBDA',
- "primary-100" => 'DAD8CA',
- "primary-200" => 'B2B9B3',
- "primary-300" => '839496',
- "primary-400" => '76898C',
- "primary-500" => '697F83',
- "primary-600" => '627A7E',
- "primary-700" => '556F74',
- "primary-800" => '415F66',
- "primary-900" => '21454E',
+ "primary" => "002B36",
+ "primary-50" => "F0EBDA",
+ "primary-100" => "DAD8CA",
+ "primary-200" => "B2B9B3",
+ "primary-300" => "839496",
+ "primary-400" => "76898C",
+ "primary-500" => "697F83",
+ "primary-600" => "627A7E",
+ "primary-700" => "556F74",
+ "primary-800" => "415F66",
+ "primary-900" => "21454E",
"secondary_low" => "325458",
"secondary_medium" => "6C8280",
"secondary_high" => "97A59D",
"secondary_very_high" => "E8E6D3",
- "secondary" => 'FCF6E1',
+ "secondary" => "FCF6E1",
"tertiary_low" => "D6E6DE",
"tertiary_medium" => "7EBFD7",
- "tertiary" => '0088cc',
+ "tertiary" => "0088cc",
"tertiary_high" => "329ED0",
- "quaternary" => 'e45735',
- "header_background" => 'FCF6E1',
- "header_primary" => '002B36',
+ "quaternary" => "e45735",
+ "header_background" => "FCF6E1",
+ "header_primary" => "002B36",
"highlight_low" => "FDF9AD",
"highlight_medium" => "E3D0A3",
- "highlight" => 'F2F481',
+ "highlight" => "F2F481",
"highlight_high" => "BCAA7F",
"danger_low" => "F8D9C2",
- "danger" => 'e45735',
+ "danger" => "e45735",
"success_low" => "CFE5B9",
"success_medium" => "4CB544",
- "success" => '009900',
+ "success" => "009900",
"love_low" => "FCDDD2",
- "love" => 'fa6c8d'
+ "love" => "fa6c8d",
},
# By @altercation
"Solarized Dark": {
@@ -218,65 +217,59 @@ class ColorScheme < ActiveRecord::Base
"primary_low_mid" => "798C88",
"primary_medium" => "97A59D",
"primary_high" => "B5BDB1",
- "primary" => 'FCF6E1',
- "primary-50" => '21454E',
- "primary-100" => '415F66',
- "primary-200" => '556F74',
- "primary-300" => '627A7E',
- "primary-400" => '697F83',
- "primary-500" => '76898C',
- "primary-600" => '839496',
- "primary-700" => 'B2B9B3',
- "primary-800" => 'DAD8CA',
- "primary-900" => 'F0EBDA',
+ "primary" => "FCF6E1",
+ "primary-50" => "21454E",
+ "primary-100" => "415F66",
+ "primary-200" => "556F74",
+ "primary-300" => "627A7E",
+ "primary-400" => "697F83",
+ "primary-500" => "76898C",
+ "primary-600" => "839496",
+ "primary-700" => "B2B9B3",
+ "primary-800" => "DAD8CA",
+ "primary-900" => "F0EBDA",
"secondary_low" => "B5BDB1",
"secondary_medium" => "81938D",
"secondary_high" => "4E6A6B",
"secondary_very_high" => "143B44",
- "secondary" => '002B36',
+ "secondary" => "002B36",
"tertiary_low" => "003E54",
"tertiary_medium" => "00557A",
- "tertiary" => '0088cc',
+ "tertiary" => "0088cc",
"tertiary_high" => "006C9F",
"quaternary_low" => "944835",
- "quaternary" => 'e45735',
- "header_background" => '002B36',
- "header_primary" => 'FCF6E1',
+ "quaternary" => "e45735",
+ "header_background" => "002B36",
+ "header_primary" => "FCF6E1",
"highlight_low" => "4D6B3D",
"highlight_medium" => "464C33",
- "highlight" => 'F2F481',
+ "highlight" => "F2F481",
"highlight_high" => "BFCA47",
"danger_low" => "443836",
"danger_medium" => "944835",
- "danger" => 'e45735',
+ "danger" => "e45735",
"success_low" => "004C26",
"success_medium" => "007313",
- "success" => '009900',
+ "success" => "009900",
"love_low" => "4B3F50",
- "love" => 'fa6c8d',
- }
+ "love" => "fa6c8d",
+ },
}
# rubocop:enable Layout/HashAlignment
- LIGHT_THEME_ID = 'Light'
+ LIGHT_THEME_ID = "Light"
def self.base_color_scheme_colors
base_with_hash = []
- base_colors.each do |name, color|
- base_with_hash << { name: name, hex: "#{color}" }
- end
+ base_colors.each { |name, color| base_with_hash << { name: name, hex: "#{color}" } }
- list = [
- { id: LIGHT_THEME_ID, colors: base_with_hash }
- ]
+ list = [{ id: LIGHT_THEME_ID, colors: base_with_hash }]
CUSTOM_SCHEMES.each do |k, v|
colors = []
- v.each do |name, color|
- colors << { name: name, hex: "#{color}" }
- end
+ v.each { |name, color| colors << { name: name, hex: "#{color}" } }
list.push(id: k.to_s, colors: colors)
end
@@ -290,7 +283,7 @@ class ColorScheme < ActiveRecord::Base
attr_accessor :is_base
attr_accessor :skip_publish
- has_many :color_scheme_colors, -> { order('id ASC') }, dependent: :destroy
+ has_many :color_scheme_colors, -> { order("id ASC") }, dependent: :destroy
alias_method :colors, :color_scheme_colors
@@ -303,7 +296,8 @@ class ColorScheme < ActiveRecord::Base
validates_associated :color_scheme_colors
BASE_COLORS_FILE = "#{Rails.root}/app/assets/stylesheets/common/foundation/colors.scss"
- COLOR_TRANSFORMATION_FILE = "#{Rails.root}/app/assets/stylesheets/common/foundation/color_transformations.scss"
+ COLOR_TRANSFORMATION_FILE =
+ "#{Rails.root}/app/assets/stylesheets/common/foundation/color_transformations.scss"
@mutex = Mutex.new
@@ -312,10 +306,12 @@ class ColorScheme < ActiveRecord::Base
@mutex.synchronize do
return @base_colors if @base_colors
base_colors = {}
- File.readlines(BASE_COLORS_FILE).each do |line|
- matches = /\$([\w]+):\s*#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})(?:[;]|\s)/.match(line.strip)
- base_colors[matches[1]] = matches[2] if matches
- end
+ File
+ .readlines(BASE_COLORS_FILE)
+ .each do |line|
+ matches = /\$([\w]+):\s*#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})(?:[;]|\s)/.match(line.strip)
+ base_colors[matches[1]] = matches[2] if matches
+ end
@base_colors = base_colors
end
@base_colors
@@ -326,10 +322,12 @@ class ColorScheme < ActiveRecord::Base
@mutex.synchronize do
return @transformation_variables if @transformation_variables
transformation_variables = []
- File.readlines(COLOR_TRANSFORMATION_FILE).each do |line|
- matches = /\$([\w\-_]+):.*/.match(line.strip)
- transformation_variables.append(matches[1]) if matches
- end
+ File
+ .readlines(COLOR_TRANSFORMATION_FILE)
+ .each do |line|
+ matches = /\$([\w\-_]+):.*/.match(line.strip)
+ transformation_variables.append(matches[1]) if matches
+ end
@transformation_variables = transformation_variables
end
@transformation_variables
@@ -337,7 +335,11 @@ class ColorScheme < ActiveRecord::Base
def self.base_color_schemes
base_color_scheme_colors.map do |hash|
- scheme = new(name: I18n.t("color_schemes.#{hash[:id].downcase.gsub(' ', '_')}"), base_scheme_id: hash[:id])
+ scheme =
+ new(
+ name: I18n.t("color_schemes.#{hash[:id].downcase.gsub(" ", "_")}"),
+ base_scheme_id: hash[:id],
+ )
scheme.colors = hash[:colors].map { |k| { name: k[:name], hex: k[:hex] } }
scheme.is_base = true
scheme
@@ -346,7 +348,7 @@ class ColorScheme < ActiveRecord::Base
def self.base
return @base_color_scheme if @base_color_scheme
- @base_color_scheme = new(name: I18n.t('color_schemes.base_theme_name'))
+ @base_color_scheme = new(name: I18n.t("color_schemes.base_theme_name"))
@base_color_scheme.colors = base_colors.map { |name, hex| { name: name, hex: hex } }
@base_color_scheme.is_base = true
@base_color_scheme
@@ -363,9 +365,10 @@ class ColorScheme < ActiveRecord::Base
new_color_scheme.base_scheme_id = params[:base_scheme_id]
new_color_scheme.user_selectable = true
- colors = CUSTOM_SCHEMES[params[:base_scheme_id].to_sym]&.map do |name, hex|
- { name: name, hex: hex }
- end if params[:base_scheme_id]
+ colors =
+ CUSTOM_SCHEMES[params[:base_scheme_id].to_sym]&.map do |name, hex|
+ { name: name, hex: hex }
+ end if params[:base_scheme_id]
colors ||= base.colors_hashes
# Override base values
@@ -394,13 +397,17 @@ class ColorScheme < ActiveRecord::Base
def colors=(arr)
@colors_by_name = nil
- arr.each do |c|
- self.color_scheme_colors << ColorSchemeColor.new(name: c[:name], hex: c[:hex])
- end
+ arr.each { |c| self.color_scheme_colors << ColorSchemeColor.new(name: c[:name], hex: c[:hex]) }
end
def colors_by_name
- @colors_by_name ||= self.colors.inject({}) { |sum, c| sum[c.name] = c; sum; }
+ @colors_by_name ||=
+ self
+ .colors
+ .inject({}) do |sum, c|
+ sum[c.name] = c
+ sum
+ end
end
def clear_colors_cache
@@ -408,16 +415,12 @@ class ColorScheme < ActiveRecord::Base
end
def colors_hashes
- color_scheme_colors.map do |c|
- { name: c.name, hex: c.hex }
- end
+ color_scheme_colors.map { |c| { name: c.name, hex: c.hex } }
end
def base_colors
colors = nil
- if base_scheme_id && base_scheme_id != "Light"
- colors = CUSTOM_SCHEMES[base_scheme_id.to_sym]
- end
+ colors = CUSTOM_SCHEMES[base_scheme_id.to_sym] if base_scheme_id && base_scheme_id != "Light"
colors || ColorScheme.base_colors
end
@@ -425,21 +428,15 @@ class ColorScheme < ActiveRecord::Base
resolved = ColorScheme.base_colors.dup
if base_scheme_id && base_scheme_id != "Light"
if scheme = CUSTOM_SCHEMES[base_scheme_id.to_sym]
- scheme.each do |name, value|
- resolved[name] = value
- end
+ scheme.each { |name, value| resolved[name] = value }
end
end
- colors.each do |c|
- resolved[c.name] = c.hex
- end
+ colors.each { |c| resolved[c.name] = c.hex }
resolved
end
def publish_discourse_stylesheet
- if self.id
- self.class.publish_discourse_stylesheets!(self.id)
- end
+ self.class.publish_discourse_stylesheets!(self.id) if self.id
end
def self.publish_discourse_stylesheets!(id = nil)
@@ -458,7 +455,7 @@ class ColorScheme < ActiveRecord::Base
theme_ids,
with_scheme: true,
clear_manager_cache: false,
- all_themes: true
+ all_themes: true,
)
end
end
@@ -469,9 +466,7 @@ class ColorScheme < ActiveRecord::Base
end
def bump_version
- if self.id
- self.version += 1
- end
+ self.version += 1 if self.id
end
def is_dark?
@@ -484,7 +479,7 @@ class ColorScheme < ActiveRecord::Base
end
def is_wcag?
- base_scheme_id&.start_with?('WCAG')
+ base_scheme_id&.start_with?("WCAG")
end
# Equivalent to dc-color-brightness() in variables.scss
diff --git a/app/models/color_scheme_setting.rb b/app/models/color_scheme_setting.rb
index 4003348b0e8..8dc5ce5cc68 100644
--- a/app/models/color_scheme_setting.rb
+++ b/app/models/color_scheme_setting.rb
@@ -1,17 +1,13 @@
# frozen_string_literal: true
class ColorSchemeSetting < EnumSiteSetting
-
def self.valid_value?(val)
val == -1 || ColorScheme.find_by_id(val)
end
def self.values
values = [{ name: I18n.t("site_settings.dark_mode_none"), value: -1 }]
- ColorScheme.all.map do |c|
- values << { name: c.name, value: c.id }
- end
+ ColorScheme.all.map { |c| values << { name: c.name, value: c.id } }
values
end
-
end
diff --git a/app/models/concerns/anon_cache_invalidator.rb b/app/models/concerns/anon_cache_invalidator.rb
index f87cada6c0e..cb468212fac 100644
--- a/app/models/concerns/anon_cache_invalidator.rb
+++ b/app/models/concerns/anon_cache_invalidator.rb
@@ -4,12 +4,8 @@ module AnonCacheInvalidator
extend ActiveSupport::Concern
included do
- after_destroy do
- Site.clear_anon_cache!
- end
+ after_destroy { Site.clear_anon_cache! }
- after_save do
- Site.clear_anon_cache!
- end
+ after_save { Site.clear_anon_cache! }
end
end
diff --git a/app/models/concerns/cached_counting.rb b/app/models/concerns/cached_counting.rb
index f8083cc0788..7598c7be22b 100644
--- a/app/models/concerns/cached_counting.rb
+++ b/app/models/concerns/cached_counting.rb
@@ -53,9 +53,7 @@ module CachedCounting
@last_ensure_thread = now
- if !@thread&.alive?
- @thread = nil
- end
+ @thread = nil if !@thread&.alive?
@thread ||= Thread.new { thread_loop }
end
end
@@ -74,26 +72,20 @@ module CachedCounting
end
iterations += 1
end
-
rescue => ex
if Redis::CommandError === ex && ex.message =~ /READONLY/
# do not warn for Redis readonly mode
elsif PG::ReadOnlySqlTransaction === ex
# do not warn for PG readonly mode
else
- Discourse.warn_exception(
- ex,
- message: 'Unexpected error while processing cached counts'
- )
+ Discourse.warn_exception(ex, message: "Unexpected error while processing cached counts")
end
end
def self.flush
@flush = true
@thread.wakeup
- while @flush
- sleep 0.001
- end
+ sleep 0.001 while @flush
end
COUNTER_REDIS_HASH = "CounterCacheHash"
@@ -122,25 +114,23 @@ module CachedCounting
redis = Discourse.redis.without_namespace
DistributedMutex.synchronize("flush_counters_to_db", redis: redis, validity: 5.minutes) do
if allowed_to_flush_to_db?
- redis.hkeys(COUNTER_REDIS_HASH).each do |key|
+ redis
+ .hkeys(COUNTER_REDIS_HASH)
+ .each do |key|
+ val = LUA_HGET_DEL.eval(redis, [COUNTER_REDIS_HASH, key]).to_i
- val = LUA_HGET_DEL.eval(
- redis,
- [COUNTER_REDIS_HASH, key]
- ).to_i
+ # unlikely (protected by mutex), but protect just in case
+ # could be a race condition in test
+ if val > 0
+ klass_name, db, date, local_key = key.split(",", 4)
+ date = Date.strptime(date, "%Y%m%d")
+ klass = Module.const_get(klass_name)
- # unlikely (protected by mutex), but protect just in case
- # could be a race condition in test
- if val > 0
- klass_name, db, date, local_key = key.split(",", 4)
- date = Date.strptime(date, "%Y%m%d")
- klass = Module.const_get(klass_name)
-
- RailsMultisite::ConnectionManagement.with_connection(db) do
- klass.write_cache!(local_key, val, date)
+ RailsMultisite::ConnectionManagement.with_connection(db) do
+ klass.write_cache!(local_key, val, date)
+ end
end
end
- end
end
end
end
@@ -154,7 +144,12 @@ module CachedCounting
end
def self.allowed_to_flush_to_db?
- Discourse.redis.without_namespace.set(DB_COOLDOWN_KEY, "1", ex: DB_FLUSH_COOLDOWN_SECONDS, nx: true)
+ Discourse.redis.without_namespace.set(
+ DB_COOLDOWN_KEY,
+ "1",
+ ex: DB_FLUSH_COOLDOWN_SECONDS,
+ nx: true,
+ )
end
def self.queue(key, klass)
@@ -176,6 +171,5 @@ module CachedCounting
def write_cache!(key, count, date)
raise NotImplementedError
end
-
end
end
diff --git a/app/models/concerns/category_hashtag.rb b/app/models/concerns/category_hashtag.rb
index db28efe789f..52d4d01b5b5 100644
--- a/app/models/concerns/category_hashtag.rb
+++ b/app/models/concerns/category_hashtag.rb
@@ -55,9 +55,7 @@ module CategoryHashtag
end
end
else
- categories.find do |cat|
- cat.slug.downcase == parent_slug && cat.top_level?
- end
+ categories.find { |cat| cat.slug.downcase == parent_slug && cat.top_level? }
end
end
.compact
diff --git a/app/models/concerns/has_custom_fields.rb b/app/models/concerns/has_custom_fields.rb
index 07ebc880ce9..2b2f64f08a3 100644
--- a/app/models/concerns/has_custom_fields.rb
+++ b/app/models/concerns/has_custom_fields.rb
@@ -4,7 +4,6 @@ module HasCustomFields
extend ActiveSupport::Concern
module Helpers
-
def self.append_field(target, key, value, types)
if target.has_key?(key)
target[key] = [target[key]] if !target[key].is_a? Array
@@ -14,18 +13,14 @@ module HasCustomFields
end
end
- CUSTOM_FIELD_TRUE ||= ['1', 't', 'true', 'T', 'True', 'TRUE'].freeze
+ CUSTOM_FIELD_TRUE ||= %w[1 t true T True TRUE].freeze
def self.get_custom_field_type(types, key)
return unless types
- sorted_types = types.keys.select { |k| k.end_with?("*") }
- .sort_by(&:length)
- .reverse
+ sorted_types = types.keys.select { |k| k.end_with?("*") }.sort_by(&:length).reverse
- sorted_types.each do |t|
- return types[t] if key =~ /^#{t}/i
- end
+ sorted_types.each { |t| return types[t] if key =~ /^#{t}/i }
types[key]
end
@@ -42,9 +37,12 @@ module HasCustomFields
result =
case type
- when :boolean then !!CUSTOM_FIELD_TRUE.include?(value)
- when :integer then value.to_i
- when :json then parse_json_value(value, key)
+ when :boolean
+ !!CUSTOM_FIELD_TRUE.include?(value)
+ when :integer
+ value.to_i
+ when :json
+ parse_json_value(value, key)
else
value
end
@@ -55,7 +53,9 @@ module HasCustomFields
def self.parse_json_value(value, key)
::JSON.parse(value)
rescue JSON::ParserError
- Rails.logger.warn("Value '#{value}' for custom field '#{key}' is not json, it is being ignored.")
+ Rails.logger.warn(
+ "Value '#{value}' for custom field '#{key}' is not json, it is being ignored.",
+ )
{}
end
end
@@ -80,11 +80,13 @@ module HasCustomFields
return result if allowed_fields.blank?
- klass.where(foreign_key => ids, :name => allowed_fields)
- .pluck(foreign_key, :name, :value).each do |cf|
- result[cf[0]] ||= {}
- append_custom_field(result[cf[0]], cf[1], cf[2])
- end
+ klass
+ .where(foreign_key => ids, :name => allowed_fields)
+ .pluck(foreign_key, :name, :value)
+ .each do |cf|
+ result[cf[0]] ||= {}
+ append_custom_field(result[cf[0]], cf[1], cf[2])
+ end
result
end
@@ -108,9 +110,7 @@ module HasCustomFields
map = {}
empty = {}
- fields.each do |field|
- empty[field] = nil
- end
+ fields.each { |field| empty[field] = nil }
objects.each do |obj|
map[obj.id] = obj
@@ -119,20 +119,18 @@ module HasCustomFields
fk = (name.underscore << "_id")
- "#{name}CustomField".constantize
+ "#{name}CustomField"
+ .constantize
.where("#{fk} in (?)", map.keys)
.where("name in (?)", fields)
- .pluck(fk, :name, :value).each do |id, name, value|
+ .pluck(fk, :name, :value)
+ .each do |id, name, value|
+ preloaded = map[id].preloaded_custom_fields
- preloaded = map[id].preloaded_custom_fields
-
- if preloaded[name].nil?
- preloaded.delete(name)
- end
+ preloaded.delete(name) if preloaded[name].nil?
HasCustomFields::Helpers.append_field(preloaded, name, value, @custom_field_types)
- end
-
+ end
end
end
end
@@ -160,7 +158,8 @@ module HasCustomFields
@custom_fields_orig = nil
end
- class NotPreloadedError < StandardError; end
+ class NotPreloadedError < StandardError
+ end
class PreloadedProxy
def initialize(preloaded, klass_with_custom_fields)
@preloaded = preloaded
@@ -172,7 +171,8 @@ module HasCustomFields
@preloaded[key]
else
# for now you can not mix preload an non preload, it better just to fail
- raise NotPreloadedError, "Attempted to access the non preloaded custom field '#{key}' on the '#{@klass_with_custom_fields}' class. This is disallowed to prevent N+1 queries."
+ raise NotPreloadedError,
+ "Attempted to access the non preloaded custom field '#{key}' on the '#{@klass_with_custom_fields}' class. This is disallowed to prevent N+1 queries."
end
end
end
@@ -210,9 +210,7 @@ module HasCustomFields
def upsert_custom_fields(fields)
fields.each do |k, v|
row_count = _custom_fields.where(name: k).update_all(value: v)
- if row_count == 0
- _custom_fields.create!(name: k, value: v)
- end
+ _custom_fields.create!(name: k, value: v) if row_count == 0
custom_fields[k.to_s] = v # We normalize custom_fields as strings
end
@@ -281,8 +279,8 @@ module HasCustomFields
# update the same custom field we should catch the error and perform an update instead.
def create_singular(name, value, field_type = nil)
write_value = value.is_a?(Hash) || field_type == :json ? value.to_json : value
- write_value = 't' if write_value.is_a?(TrueClass)
- write_value = 'f' if write_value.is_a?(FalseClass)
+ write_value = "t" if write_value.is_a?(TrueClass)
+ write_value = "f" if write_value.is_a?(FalseClass)
row_count = DB.exec(<<~SQL, name: name, value: write_value, id: id, now: Time.zone.now)
INSERT INTO #{_custom_fields.table_name} (#{custom_fields_fk}, name, value, created_at, updated_at)
VALUES (:id, :name, :value, :now, :now)
@@ -291,15 +289,15 @@ module HasCustomFields
_custom_fields.where(name: name).update_all(value: write_value) if row_count == 0
end
-protected
+ protected
def refresh_custom_fields_from_db
target = HashWithIndifferentAccess.new
- _custom_fields.order('id asc').pluck(:name, :value).each do |key, value|
- self.class.append_custom_field(target, key, value)
- end
+ _custom_fields
+ .order("id asc")
+ .pluck(:name, :value)
+ .each { |key, value| self.class.append_custom_field(target, key, value) }
@custom_fields_orig = target
@custom_fields = @custom_fields_orig.deep_dup
end
-
end
diff --git a/app/models/concerns/has_destroyed_web_hook.rb b/app/models/concerns/has_destroyed_web_hook.rb
index 0b05f437a1c..85ce31ae6f9 100644
--- a/app/models/concerns/has_destroyed_web_hook.rb
+++ b/app/models/concerns/has_destroyed_web_hook.rb
@@ -3,9 +3,7 @@
module HasDestroyedWebHook
extend ActiveSupport::Concern
- included do
- around_destroy :enqueue_destroyed_web_hook
- end
+ included { around_destroy :enqueue_destroyed_web_hook }
def enqueue_destroyed_web_hook
type = self.class.name.underscore.to_sym
@@ -13,10 +11,7 @@ module HasDestroyedWebHook
if WebHook.active_web_hooks(type).exists?
payload = WebHook.generate_payload(type, self)
yield
- WebHook.enqueue_hooks(type, "#{type}_destroyed".to_sym,
- id: id,
- payload: payload
- )
+ WebHook.enqueue_hooks(type, "#{type}_destroyed".to_sym, id: id, payload: payload)
else
yield
end
diff --git a/app/models/concerns/has_sanitizable_fields.rb b/app/models/concerns/has_sanitizable_fields.rb
index 426c4207479..5897dddd0d4 100644
--- a/app/models/concerns/has_sanitizable_fields.rb
+++ b/app/models/concerns/has_sanitizable_fields.rb
@@ -15,7 +15,7 @@ module HasSanitizableFields
field = CGI.unescape_html(sanitizer.sanitize(field, attributes: allowed_attributes))
# Just replace the characters that our translations use for interpolation.
# Calling CGI.unescape removes characters like '+', which will corrupt the original value.
- field = field.gsub('%7B', '{').gsub('%7D', '}')
+ field = field.gsub("%7B", "{").gsub("%7D", "}")
end
field
diff --git a/app/models/concerns/has_search_data.rb b/app/models/concerns/has_search_data.rb
index e997083019e..1ff9a16358d 100644
--- a/app/models/concerns/has_search_data.rb
+++ b/app/models/concerns/has_search_data.rb
@@ -4,7 +4,7 @@ module HasSearchData
extend ActiveSupport::Concern
included do
- _associated_record_name = self.name.sub('SearchData', '').underscore
+ _associated_record_name = self.name.sub("SearchData", "").underscore
self.primary_key = "#{_associated_record_name}_id"
belongs_to _associated_record_name.to_sym
validates_presence_of :search_data
diff --git a/app/models/concerns/has_url.rb b/app/models/concerns/has_url.rb
index dc6c58cee1d..d11aa69321e 100644
--- a/app/models/concerns/has_url.rb
+++ b/app/models/concerns/has_url.rb
@@ -21,10 +21,11 @@ module HasUrl
def get_from_url(url)
return if url.blank?
- uri = begin
- URI(UrlHelper.unencode(url))
- rescue URI::Error
- end
+ uri =
+ begin
+ URI(UrlHelper.unencode(url))
+ rescue URI::Error
+ end
return if uri&.path.blank?
data = extract_url(uri.path)
@@ -52,10 +53,11 @@ module HasUrl
upload_urls.each do |url|
next if url.blank?
- uri = begin
- URI(UrlHelper.unencode(url))
- rescue URI::Error
- end
+ uri =
+ begin
+ URI(UrlHelper.unencode(url))
+ rescue URI::Error
+ end
next if uri&.path.blank?
urls << uri.path
diff --git a/app/models/concerns/positionable.rb b/app/models/concerns/positionable.rb
index d353e306375..6ee93cdf4c9 100644
--- a/app/models/concerns/positionable.rb
+++ b/app/models/concerns/positionable.rb
@@ -3,14 +3,9 @@
module Positionable
extend ActiveSupport::Concern
- included do
- before_save do
- self.position ||= self.class.count
- end
- end
+ included { before_save { self.position ||= self.class.count } }
def move_to(position_arg)
-
position = [[position_arg, 0].max, self.class.count - 1].min
if self.position.nil? || position > (self.position)
@@ -18,13 +13,15 @@ module Positionable
UPDATE #{self.class.table_name}
SET position = position - 1
WHERE position > :current_position and position <= :new_position",
- current_position: self.position, new_position: position
+ current_position: self.position,
+ new_position: position
elsif position < self.position
DB.exec "
UPDATE #{self.class.table_name}
SET position = position + 1
WHERE position >= :new_position and position < :current_position",
- current_position: self.position, new_position: position
+ current_position: self.position,
+ new_position: position
else
# Not moving to a new position
return
@@ -33,6 +30,8 @@ module Positionable
DB.exec "
UPDATE #{self.class.table_name}
SET position = :position
- WHERE id = :id", id: id, position: position
+ WHERE id = :id",
+ id: id,
+ position: position
end
end
diff --git a/app/models/concerns/reports/bookmarks.rb b/app/models/concerns/reports/bookmarks.rb
index c520855b1d4..3dac869021e 100644
--- a/app/models/concerns/reports/bookmarks.rb
+++ b/app/models/concerns/reports/bookmarks.rb
@@ -5,20 +5,20 @@ module Reports::Bookmarks
class_methods do
def report_bookmarks(report)
- report.icon = 'bookmark'
+ report.icon = "bookmark"
category_filter = report.filters.dig(:category)
- report.add_filter('category', default: category_filter)
+ report.add_filter("category", default: category_filter)
report.data = []
- Bookmark.count_per_day(
- category_id: category_filter,
- start_date: report.start_date,
- end_date: report.end_date
- ).each do |date, count|
- report.data << { x: date, y: count }
- end
- add_counts report, Bookmark, 'bookmarks.created_at'
+ Bookmark
+ .count_per_day(
+ category_id: category_filter,
+ start_date: report.start_date,
+ end_date: report.end_date,
+ )
+ .each { |date, count| report.data << { x: date, y: count } }
+ add_counts report, Bookmark, "bookmarks.created_at"
end
end
end
diff --git a/app/models/concerns/reports/consolidated_api_requests.rb b/app/models/concerns/reports/consolidated_api_requests.rb
index ab25b1f73f1..60184f92dde 100644
--- a/app/models/concerns/reports/consolidated_api_requests.rb
+++ b/app/models/concerns/reports/consolidated_api_requests.rb
@@ -5,29 +5,28 @@ module Reports::ConsolidatedApiRequests
class_methods do
def report_consolidated_api_requests(report)
- filters = %w[
- api
- user_api
- ]
+ filters = %w[api user_api]
report.modes = [:stacked_chart]
- tertiary = ColorScheme.hex_for_name('tertiary') || '0088cc'
- danger = ColorScheme.hex_for_name('danger') || 'e45735'
+ tertiary = ColorScheme.hex_for_name("tertiary") || "0088cc"
+ danger = ColorScheme.hex_for_name("danger") || "e45735"
- requests = filters.map do |filter|
- color = filter == "api" ? report.rgba_color(tertiary) : report.rgba_color(danger)
+ requests =
+ filters.map do |filter|
+ color = filter == "api" ? report.rgba_color(tertiary) : report.rgba_color(danger)
- {
- req: filter,
- label: I18n.t("reports.consolidated_api_requests.xaxis.#{filter}"),
- color: color,
- data: ApplicationRequest.where(req_type: ApplicationRequest.req_types[filter])
- }
- end
+ {
+ req: filter,
+ label: I18n.t("reports.consolidated_api_requests.xaxis.#{filter}"),
+ color: color,
+ data: ApplicationRequest.where(req_type: ApplicationRequest.req_types[filter]),
+ }
+ end
requests.each do |request|
- request[:data] = request[:data].where('date >= ? AND date <= ?', report.start_date, report.end_date)
+ request[:data] = request[:data]
+ .where("date >= ? AND date <= ?", report.start_date, report.end_date)
.order(date: :asc)
.group(:date)
.sum(:count)
diff --git a/app/models/concerns/reports/consolidated_page_views.rb b/app/models/concerns/reports/consolidated_page_views.rb
index 35757d7fbe8..41854f56686 100644
--- a/app/models/concerns/reports/consolidated_page_views.rb
+++ b/app/models/concerns/reports/consolidated_page_views.rb
@@ -5,38 +5,32 @@ module Reports::ConsolidatedPageViews
class_methods do
def report_consolidated_page_views(report)
- filters = %w[
- page_view_logged_in
- page_view_anon
- page_view_crawler
- ]
+ filters = %w[page_view_logged_in page_view_anon page_view_crawler]
report.modes = [:stacked_chart]
- tertiary = ColorScheme.hex_for_name('tertiary') || '0088cc'
- danger = ColorScheme.hex_for_name('danger') || 'e45735'
+ tertiary = ColorScheme.hex_for_name("tertiary") || "0088cc"
+ danger = ColorScheme.hex_for_name("danger") || "e45735"
- requests = filters.map do |filter|
- color = report.rgba_color(tertiary)
+ requests =
+ filters.map do |filter|
+ color = report.rgba_color(tertiary)
- if filter == "page_view_anon"
- color = report.lighten_color(tertiary, 0.25)
+ color = report.lighten_color(tertiary, 0.25) if filter == "page_view_anon"
+
+ color = report.rgba_color(danger, 0.75) if filter == "page_view_crawler"
+
+ {
+ req: filter,
+ label: I18n.t("reports.consolidated_page_views.xaxis.#{filter}"),
+ color: color,
+ data: ApplicationRequest.where(req_type: ApplicationRequest.req_types[filter]),
+ }
end
- if filter == "page_view_crawler"
- color = report.rgba_color(danger, 0.75)
- end
-
- {
- req: filter,
- label: I18n.t("reports.consolidated_page_views.xaxis.#{filter}"),
- color: color,
- data: ApplicationRequest.where(req_type: ApplicationRequest.req_types[filter])
- }
- end
-
requests.each do |request|
- request[:data] = request[:data].where('date >= ? AND date <= ?', report.start_date, report.end_date)
+ request[:data] = request[:data]
+ .where("date >= ? AND date <= ?", report.start_date, report.end_date)
.order(date: :asc)
.group(:date)
.sum(:count)
diff --git a/app/models/concerns/reports/daily_engaged_users.rb b/app/models/concerns/reports/daily_engaged_users.rb
index 9e4dfdbd59e..f2be595c9a2 100644
--- a/app/models/concerns/reports/daily_engaged_users.rb
+++ b/app/models/concerns/reports/daily_engaged_users.rb
@@ -12,27 +12,23 @@ module Reports::DailyEngagedUsers
data = UserAction.count_daily_engaged_users(report.start_date, report.end_date)
if report.facets.include?(:prev30Days)
- prev30DaysData = UserAction.count_daily_engaged_users(report.start_date - 30.days, report.start_date)
+ prev30DaysData =
+ UserAction.count_daily_engaged_users(report.start_date - 30.days, report.start_date)
report.prev30Days = prev30DaysData.sum { |k, v| v }
end
- if report.facets.include?(:total)
- report.total = UserAction.count_daily_engaged_users
- end
+ report.total = UserAction.count_daily_engaged_users if report.facets.include?(:total)
if report.facets.include?(:prev_period)
- prev_data = UserAction.count_daily_engaged_users(report.prev_start_date, report.prev_end_date)
+ prev_data =
+ UserAction.count_daily_engaged_users(report.prev_start_date, report.prev_end_date)
prev = prev_data.sum { |k, v| v }
- if prev > 0
- prev = prev / ((report.end_date - report.start_date) / 1.day)
- end
+ prev = prev / ((report.end_date - report.start_date) / 1.day) if prev > 0
report.prev_period = prev
end
- data.each do |key, value|
- report.data << { x: key, y: value }
- end
+ data.each { |key, value| report.data << { x: key, y: value } }
end
end
end
diff --git a/app/models/concerns/reports/dau_by_mau.rb b/app/models/concerns/reports/dau_by_mau.rb
index 69956c8e578..4d97531fed6 100644
--- a/app/models/concerns/reports/dau_by_mau.rb
+++ b/app/models/concerns/reports/dau_by_mau.rb
@@ -6,16 +6,8 @@ module Reports::DauByMau
class_methods do
def report_dau_by_mau(report)
report.labels = [
- {
- type: :date,
- property: :x,
- title: I18n.t("reports.default.labels.day")
- },
- {
- type: :percent,
- property: :y,
- title: I18n.t("reports.default.labels.percent")
- },
+ { type: :date, property: :x, title: I18n.t("reports.default.labels.day") },
+ { type: :percent, property: :y, title: I18n.t("reports.default.labels.percent") },
]
report.average = true
@@ -25,21 +17,23 @@ module Reports::DauByMau
report.data = []
- compute_dau_by_mau = Proc.new { |data_point|
- if data_point["mau"] == 0
- 0
- else
- ((data_point["dau"].to_f / data_point["mau"].to_f) * 100).ceil(2)
+ compute_dau_by_mau =
+ Proc.new do |data_point|
+ if data_point["mau"] == 0
+ 0
+ else
+ ((data_point["dau"].to_f / data_point["mau"].to_f) * 100).ceil(2)
+ end
end
- }
- dau_avg = Proc.new { |start_date, end_date|
- data_points = UserVisit.count_by_active_users(start_date, end_date)
- if !data_points.empty?
- sum = data_points.sum { |data_point| compute_dau_by_mau.call(data_point) }
- (sum.to_f / data_points.count.to_f).ceil(2)
+ dau_avg =
+ Proc.new do |start_date, end_date|
+ data_points = UserVisit.count_by_active_users(start_date, end_date)
+ if !data_points.empty?
+ sum = data_points.sum { |data_point| compute_dau_by_mau.call(data_point) }
+ (sum.to_f / data_points.count.to_f).ceil(2)
+ end
end
- }
data_points.each do |data_point|
report.data << { x: data_point["date"], y: compute_dau_by_mau.call(data_point) }
diff --git a/app/models/concerns/reports/flags.rb b/app/models/concerns/reports/flags.rb
index 8c8cd8424a5..99c73085fa5 100644
--- a/app/models/concerns/reports/flags.rb
+++ b/app/models/concerns/reports/flags.rb
@@ -7,7 +7,7 @@ module Reports::Flags
def report_flags(report)
category_id, include_subcategories = report.add_category_filter
- report.icon = 'flag'
+ report.icon = "flag"
report.higher_is_better = false
basic_report_about(
@@ -17,20 +17,21 @@ module Reports::Flags
report.start_date,
report.end_date,
category_id,
- include_subcategories
+ include_subcategories,
)
countable = ReviewableFlaggedPost.scores_with_topics
if category_id
if include_subcategories
- countable = countable.where('topics.category_id IN (?)', Category.subcategory_ids(category_id))
+ countable =
+ countable.where("topics.category_id IN (?)", Category.subcategory_ids(category_id))
else
- countable = countable.where('topics.category_id = ?', category_id)
+ countable = countable.where("topics.category_id = ?", category_id)
end
end
- add_counts report, countable, 'reviewable_scores.created_at'
+ add_counts report, countable, "reviewable_scores.created_at"
end
end
end
diff --git a/app/models/concerns/reports/flags_status.rb b/app/models/concerns/reports/flags_status.rb
index 1349f13b0b8..572185ebc53 100644
--- a/app/models/concerns/reports/flags_status.rb
+++ b/app/models/concerns/reports/flags_status.rb
@@ -13,42 +13,42 @@ module Reports::FlagsStatus
properties: {
topic_id: :topic_id,
number: :post_number,
- truncated_raw: :post_type
+ truncated_raw: :post_type,
},
- title: I18n.t("reports.flags_status.labels.flag")
+ title: I18n.t("reports.flags_status.labels.flag"),
},
{
type: :user,
properties: {
username: :staff_username,
id: :staff_id,
- avatar: :staff_avatar_template
+ avatar: :staff_avatar_template,
},
- title: I18n.t("reports.flags_status.labels.assigned")
+ title: I18n.t("reports.flags_status.labels.assigned"),
},
{
type: :user,
properties: {
username: :poster_username,
id: :poster_id,
- avatar: :poster_avatar_template
+ avatar: :poster_avatar_template,
},
- title: I18n.t("reports.flags_status.labels.poster")
+ title: I18n.t("reports.flags_status.labels.poster"),
},
{
type: :user,
properties: {
username: :flagger_username,
id: :flagger_id,
- avatar: :flagger_avatar_template
- },
- title: I18n.t("reports.flags_status.labels.flagger")
+ avatar: :flagger_avatar_template,
+ },
+ title: I18n.t("reports.flags_status.labels.flagger"),
},
{
type: :seconds,
property: :response_time,
- title: I18n.t("reports.flags_status.labels.time_to_resolution")
- }
+ title: I18n.t("reports.flags_status.labels.time_to_resolution"),
+ },
]
report.data = []
@@ -70,7 +70,7 @@ module Reports::FlagsStatus
user_id,
COALESCE(disagreed_at, agreed_at, deferred_at) AS responded_at
FROM post_actions
- WHERE post_action_type_id IN (#{flag_types.values.join(',')})
+ WHERE post_action_type_id IN (#{flag_types.values.join(",")})
AND created_at >= '#{report.start_date}'
AND created_at <= '#{report.end_date}'
ORDER BY created_at DESC
@@ -136,43 +136,54 @@ module Reports::FlagsStatus
ON pd.id = pa.id
SQL
- DB.query(sql).each do |row|
- data = {}
+ DB
+ .query(sql)
+ .each do |row|
+ data = {}
- data[:post_type] = flag_types.key(row.post_action_type_id).to_s
- data[:post_number] = row.post_number
- data[:topic_id] = row.topic_id
+ data[:post_type] = flag_types.key(row.post_action_type_id).to_s
+ data[:post_number] = row.post_number
+ data[:topic_id] = row.topic_id
- if row.staff_id
- data[:staff_username] = row.staff_username
- data[:staff_id] = row.staff_id
- data[:staff_avatar_template] = User.avatar_template(row.staff_username, row.staff_avatar_id)
+ if row.staff_id
+ data[:staff_username] = row.staff_username
+ data[:staff_id] = row.staff_id
+ data[:staff_avatar_template] = User.avatar_template(
+ row.staff_username,
+ row.staff_avatar_id,
+ )
+ end
+
+ if row.poster_id
+ data[:poster_username] = row.poster_username
+ data[:poster_id] = row.poster_id
+ data[:poster_avatar_template] = User.avatar_template(
+ row.poster_username,
+ row.poster_avatar_id,
+ )
+ end
+
+ if row.flagger_id
+ data[:flagger_id] = row.flagger_id
+ data[:flagger_username] = row.flagger_username
+ data[:flagger_avatar_template] = User.avatar_template(
+ row.flagger_username,
+ row.flagger_avatar_id,
+ )
+ end
+
+ if row.agreed_by_id
+ data[:resolution] = I18n.t("reports.flags_status.values.agreed")
+ elsif row.disagreed_by_id
+ data[:resolution] = I18n.t("reports.flags_status.values.disagreed")
+ elsif row.deferred_by_id
+ data[:resolution] = I18n.t("reports.flags_status.values.deferred")
+ else
+ data[:resolution] = I18n.t("reports.flags_status.values.no_action")
+ end
+ data[:response_time] = row.responded_at ? row.responded_at - row.created_at : nil
+ report.data << data
end
-
- if row.poster_id
- data[:poster_username] = row.poster_username
- data[:poster_id] = row.poster_id
- data[:poster_avatar_template] = User.avatar_template(row.poster_username, row.poster_avatar_id)
- end
-
- if row.flagger_id
- data[:flagger_id] = row.flagger_id
- data[:flagger_username] = row.flagger_username
- data[:flagger_avatar_template] = User.avatar_template(row.flagger_username, row.flagger_avatar_id)
- end
-
- if row.agreed_by_id
- data[:resolution] = I18n.t("reports.flags_status.values.agreed")
- elsif row.disagreed_by_id
- data[:resolution] = I18n.t("reports.flags_status.values.disagreed")
- elsif row.deferred_by_id
- data[:resolution] = I18n.t("reports.flags_status.values.deferred")
- else
- data[:resolution] = I18n.t("reports.flags_status.values.no_action")
- end
- data[:response_time] = row.responded_at ? row.responded_at - row.created_at : nil
- report.data << data
- end
end
end
end
diff --git a/app/models/concerns/reports/likes.rb b/app/models/concerns/reports/likes.rb
index 0815a9e79c7..9f5f3375e49 100644
--- a/app/models/concerns/reports/likes.rb
+++ b/app/models/concerns/reports/likes.rb
@@ -5,7 +5,7 @@ module Reports::Likes
class_methods do
def report_likes(report)
- report.icon = 'heart'
+ report.icon = "heart"
post_action_report report, PostActionType.types[:like]
end
diff --git a/app/models/concerns/reports/mobile_visits.rb b/app/models/concerns/reports/mobile_visits.rb
index a5e331891a3..652b12ee468 100644
--- a/app/models/concerns/reports/mobile_visits.rb
+++ b/app/models/concerns/reports/mobile_visits.rb
@@ -7,7 +7,15 @@ module Reports::MobileVisits
def report_mobile_visits(report)
basic_report_about report, UserVisit, :mobile_by_day, report.start_date, report.end_date
report.total = UserVisit.where(mobile: true).count
- report.prev30Days = UserVisit.where(mobile: true).where("visited_at >= ? and visited_at < ?", report.start_date - 30.days, report.start_date).count
+ report.prev30Days =
+ UserVisit
+ .where(mobile: true)
+ .where(
+ "visited_at >= ? and visited_at < ?",
+ report.start_date - 30.days,
+ report.start_date,
+ )
+ .count
end
end
end
diff --git a/app/models/concerns/reports/moderator_warning_private_messages.rb b/app/models/concerns/reports/moderator_warning_private_messages.rb
index ba995594288..16047034d7b 100644
--- a/app/models/concerns/reports/moderator_warning_private_messages.rb
+++ b/app/models/concerns/reports/moderator_warning_private_messages.rb
@@ -5,7 +5,7 @@ module Reports::ModeratorWarningPrivateMessages
class_methods do
def report_moderator_warning_private_messages(report)
- report.icon = 'envelope'
+ report.icon = "envelope"
private_messages_report report, TopicSubtype.moderator_warning
end
end
diff --git a/app/models/concerns/reports/moderators_activity.rb b/app/models/concerns/reports/moderators_activity.rb
index 135e4f09460..b66bf0df74d 100644
--- a/app/models/concerns/reports/moderators_activity.rb
+++ b/app/models/concerns/reports/moderators_activity.rb
@@ -18,33 +18,33 @@ module Reports::ModeratorsActivity
{
property: :flag_count,
type: :number,
- title: I18n.t("reports.moderators_activity.labels.flag_count")
+ title: I18n.t("reports.moderators_activity.labels.flag_count"),
},
{
type: :seconds,
property: :time_read,
- title: I18n.t("reports.moderators_activity.labels.time_read")
+ title: I18n.t("reports.moderators_activity.labels.time_read"),
},
{
property: :topic_count,
type: :number,
- title: I18n.t("reports.moderators_activity.labels.topic_count")
+ title: I18n.t("reports.moderators_activity.labels.topic_count"),
},
{
property: :pm_count,
type: :number,
- title: I18n.t("reports.moderators_activity.labels.pm_count")
+ title: I18n.t("reports.moderators_activity.labels.pm_count"),
},
{
property: :post_count,
type: :number,
- title: I18n.t("reports.moderators_activity.labels.post_count")
+ title: I18n.t("reports.moderators_activity.labels.post_count"),
},
{
property: :revision_count,
type: :number,
- title: I18n.t("reports.moderators_activity.labels.revision_count")
- }
+ title: I18n.t("reports.moderators_activity.labels.revision_count"),
+ },
]
report.modes = [:table]
@@ -75,7 +75,7 @@ module Reports::ModeratorsActivity
SELECT agreed_by_id,
disagreed_by_id
FROM post_actions
- WHERE post_action_type_id IN (#{PostActionType.flag_types_without_custom.values.join(',')})
+ WHERE post_action_type_id IN (#{PostActionType.flag_types_without_custom.values.join(",")})
AND created_at >= '#{report.start_date}'
AND created_at <= '#{report.end_date}'
),
@@ -173,19 +173,21 @@ module Reports::ModeratorsActivity
ORDER BY m.username
SQL
- DB.query(query).each do |row|
- mod = {}
- mod[:username] = row.username
- mod[:user_id] = row.user_id
- mod[:user_avatar_template] = User.avatar_template(row.username, row.uploaded_avatar_id)
- mod[:time_read] = row.time_read
- mod[:flag_count] = row.flag_count
- mod[:revision_count] = row.revision_count
- mod[:topic_count] = row.topic_count
- mod[:post_count] = row.post_count
- mod[:pm_count] = row.pm_count
- report.data << mod
- end
+ DB
+ .query(query)
+ .each do |row|
+ mod = {}
+ mod[:username] = row.username
+ mod[:user_id] = row.user_id
+ mod[:user_avatar_template] = User.avatar_template(row.username, row.uploaded_avatar_id)
+ mod[:time_read] = row.time_read
+ mod[:flag_count] = row.flag_count
+ mod[:revision_count] = row.revision_count
+ mod[:topic_count] = row.topic_count
+ mod[:post_count] = row.post_count
+ mod[:pm_count] = row.pm_count
+ report.data << mod
+ end
end
end
end
diff --git a/app/models/concerns/reports/new_contributors.rb b/app/models/concerns/reports/new_contributors.rb
index c8a8afe2094..89b2fdda173 100644
--- a/app/models/concerns/reports/new_contributors.rb
+++ b/app/models/concerns/reports/new_contributors.rb
@@ -10,23 +10,21 @@ module Reports::NewContributors
data = User.real.count_by_first_post(report.start_date, report.end_date)
if report.facets.include?(:prev30Days)
- prev30DaysData = User.real.count_by_first_post(report.start_date - 30.days, report.start_date)
+ prev30DaysData =
+ User.real.count_by_first_post(report.start_date - 30.days, report.start_date)
report.prev30Days = prev30DaysData.sum { |k, v| v }
end
- if report.facets.include?(:total)
- report.total = User.real.count_by_first_post
- end
+ report.total = User.real.count_by_first_post if report.facets.include?(:total)
if report.facets.include?(:prev_period)
- prev_period_data = User.real.count_by_first_post(report.prev_start_date, report.prev_end_date)
+ prev_period_data =
+ User.real.count_by_first_post(report.prev_start_date, report.prev_end_date)
report.prev_period = prev_period_data.sum { |k, v| v }
# report.prev_data = prev_period_data.map { |k, v| { x: k, y: v } }
end
- data.each do |key, value|
- report.data << { x: key, y: value }
- end
+ data.each { |key, value| report.data << { x: key, y: value } }
end
end
end
diff --git a/app/models/concerns/reports/notify_moderators_private_messages.rb b/app/models/concerns/reports/notify_moderators_private_messages.rb
index 77c2df12d56..e7dcfed2e2b 100644
--- a/app/models/concerns/reports/notify_moderators_private_messages.rb
+++ b/app/models/concerns/reports/notify_moderators_private_messages.rb
@@ -5,7 +5,7 @@ module Reports::NotifyModeratorsPrivateMessages
class_methods do
def report_notify_moderators_private_messages(report)
- report.icon = 'envelope'
+ report.icon = "envelope"
private_messages_report report, TopicSubtype.notify_moderators
end
end
diff --git a/app/models/concerns/reports/notify_user_private_messages.rb b/app/models/concerns/reports/notify_user_private_messages.rb
index aac3dca4ccb..655fa812aff 100644
--- a/app/models/concerns/reports/notify_user_private_messages.rb
+++ b/app/models/concerns/reports/notify_user_private_messages.rb
@@ -5,7 +5,7 @@ module Reports::NotifyUserPrivateMessages
class_methods do
def report_notify_user_private_messages(report)
- report.icon = 'envelope'
+ report.icon = "envelope"
private_messages_report report, TopicSubtype.notify_user
end
end
diff --git a/app/models/concerns/reports/post_edits.rb b/app/models/concerns/reports/post_edits.rb
index 554fea563af..af97ddc19a8 100644
--- a/app/models/concerns/reports/post_edits.rb
+++ b/app/models/concerns/reports/post_edits.rb
@@ -6,7 +6,7 @@ module Reports::PostEdits
class_methods do
def report_post_edits(report)
category_id, include_subcategories = report.add_category_filter
- editor_username = report.filters['editor']
+ editor_username = report.filters["editor"]
report.modes = [:table]
@@ -14,16 +14,16 @@ module Reports::PostEdits
{
type: :date,
property: :created_at,
- title: I18n.t("reports.post_edits.labels.edited_at")
+ title: I18n.t("reports.post_edits.labels.edited_at"),
},
{
type: :post,
properties: {
topic_id: :topic_id,
number: :post_number,
- truncated_raw: :post_raw
+ truncated_raw: :post_raw,
},
- title: I18n.t("reports.post_edits.labels.post")
+ title: I18n.t("reports.post_edits.labels.post"),
},
{
type: :user,
@@ -32,7 +32,7 @@ module Reports::PostEdits
id: :editor_id,
avatar: :editor_avatar_template,
},
- title: I18n.t("reports.post_edits.labels.editor")
+ title: I18n.t("reports.post_edits.labels.editor"),
},
{
type: :user,
@@ -41,12 +41,12 @@ module Reports::PostEdits
id: :author_id,
avatar: :author_avatar_template,
},
- title: I18n.t("reports.post_edits.labels.author")
+ title: I18n.t("reports.post_edits.labels.author"),
},
{
type: :text,
property: :edit_reason,
- title: I18n.t("reports.post_edits.labels.edit_reason")
+ title: I18n.t("reports.post_edits.labels.edit_reason"),
},
]
@@ -105,10 +105,16 @@ module Reports::PostEdits
revision = {}
revision[:editor_id] = r.editor_id
revision[:editor_username] = r.editor_username
- revision[:editor_avatar_template] = User.avatar_template(r.editor_username, r.editor_avatar_id)
+ revision[:editor_avatar_template] = User.avatar_template(
+ r.editor_username,
+ r.editor_avatar_id,
+ )
revision[:author_id] = r.author_id
revision[:author_username] = r.author_username
- revision[:author_avatar_template] = User.avatar_template(r.author_username, r.author_avatar_id)
+ revision[:author_avatar_template] = User.avatar_template(
+ r.author_username,
+ r.author_avatar_id,
+ )
revision[:edit_reason] = r.revision_version == r.post_version ? r.edit_reason : nil
revision[:created_at] = r.created_at
revision[:post_raw] = r.post_raw
diff --git a/app/models/concerns/reports/posts.rb b/app/models/concerns/reports/posts.rb
index 5a692d8f5a3..b2ac5199099 100644
--- a/app/models/concerns/reports/posts.rb
+++ b/app/models/concerns/reports/posts.rb
@@ -5,22 +5,32 @@ module Reports::Posts
class_methods do
def report_posts(report)
- report.modes = [:table, :chart]
+ report.modes = %i[table chart]
category_id, include_subcategories = report.add_category_filter
- basic_report_about report, Post, :public_posts_count_per_day, report.start_date, report.end_date, category_id, include_subcategories
+ basic_report_about report,
+ Post,
+ :public_posts_count_per_day,
+ report.start_date,
+ report.end_date,
+ category_id,
+ include_subcategories
countable = Post.public_posts.where(post_type: Post.types[:regular])
if category_id
if include_subcategories
- countable = countable.joins(:topic).where('topics.category_id IN (?)', Category.subcategory_ids(category_id))
+ countable =
+ countable.joins(:topic).where(
+ "topics.category_id IN (?)",
+ Category.subcategory_ids(category_id),
+ )
else
- countable = countable.joins(:topic).where('topics.category_id = ?', category_id)
+ countable = countable.joins(:topic).where("topics.category_id = ?", category_id)
end
end
- add_counts report, countable, 'posts.created_at'
+ add_counts report, countable, "posts.created_at"
end
end
end
diff --git a/app/models/concerns/reports/profile_views.rb b/app/models/concerns/reports/profile_views.rb
index 4f630a92c87..0fccea83966 100644
--- a/app/models/concerns/reports/profile_views.rb
+++ b/app/models/concerns/reports/profile_views.rb
@@ -6,14 +6,24 @@ module Reports::ProfileViews
class_methods do
def report_profile_views(report)
group_filter = report.filters.dig(:group)
- report.add_filter('group', type: 'group', default: group_filter)
+ report.add_filter("group", type: "group", default: group_filter)
start_date = report.start_date
end_date = report.end_date
- basic_report_about report, UserProfileView, :profile_views_by_day, start_date, end_date, group_filter
+ basic_report_about report,
+ UserProfileView,
+ :profile_views_by_day,
+ start_date,
+ end_date,
+ group_filter
report.total = UserProfile.sum(:views)
- report.prev30Days = UserProfileView.where('viewed_at >= ? AND viewed_at < ?', start_date - 30.days, start_date + 1).count
+ report.prev30Days =
+ UserProfileView.where(
+ "viewed_at >= ? AND viewed_at < ?",
+ start_date - 30.days,
+ start_date + 1,
+ ).count
end
end
end
diff --git a/app/models/concerns/reports/signups.rb b/app/models/concerns/reports/signups.rb
index 380fb0c9bcc..200d229dfe0 100644
--- a/app/models/concerns/reports/signups.rb
+++ b/app/models/concerns/reports/signups.rb
@@ -5,14 +5,19 @@ module Reports::Signups
class_methods do
def report_signups(report)
- report.icon = 'user-plus'
+ report.icon = "user-plus"
group_filter = report.filters.dig(:group)
- report.add_filter('group', type: 'group', default: group_filter)
+ report.add_filter("group", type: "group", default: group_filter)
if group_filter
- basic_report_about report, User.real, :count_by_signup_date, report.start_date, report.end_date, group_filter
- add_counts report, User.real, 'users.created_at'
+ basic_report_about report,
+ User.real,
+ :count_by_signup_date,
+ report.start_date,
+ report.end_date,
+ group_filter
+ add_counts report, User.real, "users.created_at"
else
report_about report, User.real, :count_by_signup_date
end
diff --git a/app/models/concerns/reports/staff_logins.rb b/app/models/concerns/reports/staff_logins.rb
index 1636150baa0..d65c2e2df05 100644
--- a/app/models/concerns/reports/staff_logins.rb
+++ b/app/models/concerns/reports/staff_logins.rb
@@ -17,17 +17,14 @@ module Reports::StaffLogins
id: :user_id,
avatar: :avatar_template,
},
- title: I18n.t("reports.staff_logins.labels.user")
- },
- {
- property: :location,
- title: I18n.t("reports.staff_logins.labels.location")
+ title: I18n.t("reports.staff_logins.labels.user"),
},
+ { property: :location, title: I18n.t("reports.staff_logins.labels.location") },
{
property: :created_at,
type: :precise_date,
- title: I18n.t("reports.staff_logins.labels.login_at")
- }
+ title: I18n.t("reports.staff_logins.labels.login_at"),
+ },
]
sql = <<~SQL
@@ -40,7 +37,7 @@ module Reports::StaffLogins
FROM (
SELECT DISTINCT ON (t.client_ip, t.user_id) t.client_ip, t.user_id, t.created_at
FROM user_auth_token_logs t
- WHERE t.user_id IN (#{User.admins.pluck(:id).join(',')})
+ WHERE t.user_id IN (#{User.admins.pluck(:id).join(",")})
AND t.created_at >= :start_date
AND t.created_at <= :end_date
ORDER BY t.client_ip, t.user_id, t.created_at DESC
@@ -50,16 +47,18 @@ module Reports::StaffLogins
ORDER BY created_at DESC
SQL
- DB.query(sql, start_date: report.start_date, end_date: report.end_date).each do |row|
- data = {}
- data[:avatar_template] = User.avatar_template(row.username, row.uploaded_avatar_id)
- data[:user_id] = row.user_id
- data[:username] = row.username
- data[:location] = DiscourseIpInfo.get(row.client_ip)[:location]
- data[:created_at] = row.created_at
+ DB
+ .query(sql, start_date: report.start_date, end_date: report.end_date)
+ .each do |row|
+ data = {}
+ data[:avatar_template] = User.avatar_template(row.username, row.uploaded_avatar_id)
+ data[:user_id] = row.user_id
+ data[:username] = row.username
+ data[:location] = DiscourseIpInfo.get(row.client_ip)[:location]
+ data[:created_at] = row.created_at
- report.data << data
- end
+ report.data << data
+ end
end
end
end
diff --git a/app/models/concerns/reports/storage_stats.rb b/app/models/concerns/reports/storage_stats.rb
index c95c5371351..1efb79057fa 100644
--- a/app/models/concerns/reports/storage_stats.rb
+++ b/app/models/concerns/reports/storage_stats.rb
@@ -5,18 +5,19 @@ module Reports::StorageStats
class_methods do
def report_storage_stats(report)
- backup_stats = begin
- BackupRestore::BackupStore.create.stats
- rescue BackupRestore::BackupStore::StorageError
- nil
- end
+ backup_stats =
+ begin
+ BackupRestore::BackupStore.create.stats
+ rescue BackupRestore::BackupStore::StorageError
+ nil
+ end
report.data = {
backups: backup_stats,
uploads: {
used_bytes: DiskSpace.uploads_used_bytes,
- free_bytes: DiskSpace.uploads_free_bytes
- }
+ free_bytes: DiskSpace.uploads_free_bytes,
+ },
}
end
end
diff --git a/app/models/concerns/reports/suspicious_logins.rb b/app/models/concerns/reports/suspicious_logins.rb
index 47a726e558e..cd07d427d11 100644
--- a/app/models/concerns/reports/suspicious_logins.rb
+++ b/app/models/concerns/reports/suspicious_logins.rb
@@ -15,32 +15,17 @@ module Reports::SuspiciousLogins
id: :user_id,
avatar: :avatar_template,
},
- title: I18n.t("reports.suspicious_logins.labels.user")
- },
- {
- property: :client_ip,
- title: I18n.t("reports.suspicious_logins.labels.client_ip")
- },
- {
- property: :location,
- title: I18n.t("reports.suspicious_logins.labels.location")
- },
- {
- property: :browser,
- title: I18n.t("reports.suspicious_logins.labels.browser")
- },
- {
- property: :device,
- title: I18n.t("reports.suspicious_logins.labels.device")
- },
- {
- property: :os,
- title: I18n.t("reports.suspicious_logins.labels.os")
+ title: I18n.t("reports.suspicious_logins.labels.user"),
},
+ { property: :client_ip, title: I18n.t("reports.suspicious_logins.labels.client_ip") },
+ { property: :location, title: I18n.t("reports.suspicious_logins.labels.location") },
+ { property: :browser, title: I18n.t("reports.suspicious_logins.labels.browser") },
+ { property: :device, title: I18n.t("reports.suspicious_logins.labels.device") },
+ { property: :os, title: I18n.t("reports.suspicious_logins.labels.os") },
{
type: :date,
property: :login_time,
- title: I18n.t("reports.suspicious_logins.labels.login_time")
+ title: I18n.t("reports.suspicious_logins.labels.login_time"),
},
]
@@ -56,26 +41,28 @@ module Reports::SuspiciousLogins
ORDER BY t.created_at DESC
SQL
- DB.query(sql, start_date: report.start_date, end_date: report.end_date).each do |row|
- data = {}
+ DB
+ .query(sql, start_date: report.start_date, end_date: report.end_date)
+ .each do |row|
+ data = {}
- ipinfo = DiscourseIpInfo.get(row.client_ip)
- browser = BrowserDetection.browser(row.user_agent)
- device = BrowserDetection.device(row.user_agent)
- os = BrowserDetection.os(row.user_agent)
+ ipinfo = DiscourseIpInfo.get(row.client_ip)
+ browser = BrowserDetection.browser(row.user_agent)
+ device = BrowserDetection.device(row.user_agent)
+ os = BrowserDetection.os(row.user_agent)
- data[:username] = row.username
- data[:user_id] = row.user_id
- data[:avatar_template] = User.avatar_template(row.username, row.uploaded_avatar_id)
- data[:client_ip] = row.client_ip.to_s
- data[:location] = ipinfo[:location]
- data[:browser] = I18n.t("user_auth_tokens.browser.#{browser}")
- data[:device] = I18n.t("user_auth_tokens.device.#{device}")
- data[:os] = I18n.t("user_auth_tokens.os.#{os}")
- data[:login_time] = row.login_time
+ data[:username] = row.username
+ data[:user_id] = row.user_id
+ data[:avatar_template] = User.avatar_template(row.username, row.uploaded_avatar_id)
+ data[:client_ip] = row.client_ip.to_s
+ data[:location] = ipinfo[:location]
+ data[:browser] = I18n.t("user_auth_tokens.browser.#{browser}")
+ data[:device] = I18n.t("user_auth_tokens.device.#{device}")
+ data[:os] = I18n.t("user_auth_tokens.os.#{os}")
+ data[:login_time] = row.login_time
- report.data << data
- end
+ report.data << data
+ end
end
end
end
diff --git a/app/models/concerns/reports/system_private_messages.rb b/app/models/concerns/reports/system_private_messages.rb
index 0c046250784..8fd142b0e74 100644
--- a/app/models/concerns/reports/system_private_messages.rb
+++ b/app/models/concerns/reports/system_private_messages.rb
@@ -5,7 +5,7 @@ module Reports::SystemPrivateMessages
class_methods do
def report_system_private_messages(report)
- report.icon = 'envelope'
+ report.icon = "envelope"
private_messages_report report, TopicSubtype.system_message
end
end
diff --git a/app/models/concerns/reports/time_to_first_response.rb b/app/models/concerns/reports/time_to_first_response.rb
index 6217591ab5b..bd710b11eb3 100644
--- a/app/models/concerns/reports/time_to_first_response.rb
+++ b/app/models/concerns/reports/time_to_first_response.rb
@@ -8,16 +8,27 @@ module Reports::TimeToFirstResponse
category_filter = report.filters.dig(:category)
category_id, include_subcategories = report.add_category_filter
- report.icon = 'reply'
+ report.icon = "reply"
report.higher_is_better = false
report.data = []
report.average = true
- Topic.time_to_first_response_per_day(report.start_date, report.end_date, category_id: category_id, include_subcategories: include_subcategories).each do |r|
- report.data << { x: r['date'], y: r['hours'].to_f.round(2) }
- end
+ Topic
+ .time_to_first_response_per_day(
+ report.start_date,
+ report.end_date,
+ category_id: category_id,
+ include_subcategories: include_subcategories,
+ )
+ .each { |r| report.data << { x: r["date"], y: r["hours"].to_f.round(2) } }
- report.prev30Days = Topic.time_to_first_response_total(start_date: report.start_date - 30.days, end_date: report.start_date, category_id: category_id, include_subcategories: include_subcategories)
+ report.prev30Days =
+ Topic.time_to_first_response_total(
+ start_date: report.start_date - 30.days,
+ end_date: report.start_date,
+ category_id: category_id,
+ include_subcategories: include_subcategories,
+ )
end
end
end
diff --git a/app/models/concerns/reports/top_ignored_users.rb b/app/models/concerns/reports/top_ignored_users.rb
index 3b02f081956..3403de992e7 100644
--- a/app/models/concerns/reports/top_ignored_users.rb
+++ b/app/models/concerns/reports/top_ignored_users.rb
@@ -15,22 +15,18 @@ module Reports::TopIgnoredUsers
username: :ignored_username,
avatar: :ignored_user_avatar_template,
},
- title: I18n.t("reports.top_ignored_users.labels.ignored_user")
+ title: I18n.t("reports.top_ignored_users.labels.ignored_user"),
},
{
type: :number,
- properties: [
- :ignores_count,
- ],
- title: I18n.t("reports.top_ignored_users.labels.ignores_count")
+ properties: [:ignores_count],
+ title: I18n.t("reports.top_ignored_users.labels.ignores_count"),
},
{
type: :number,
- properties: [
- :mutes_count,
- ],
- title: I18n.t("reports.top_ignored_users.labels.mutes_count")
- }
+ properties: [:mutes_count],
+ title: I18n.t("reports.top_ignored_users.labels.mutes_count"),
+ },
]
report.data = []
@@ -69,15 +65,18 @@ module Reports::TopIgnoredUsers
ORDER BY total DESC
SQL
- DB.query(sql, limit: report.limit || 250).each do |row|
- report.data << {
- ignored_user_id: row.user_id,
- ignored_username: row.username,
- ignored_user_avatar_template: User.avatar_template(row.username, row.uploaded_avatar_id),
- ignores_count: row.ignores_count,
- mutes_count: row.mutes_count,
- }
- end
+ DB
+ .query(sql, limit: report.limit || 250)
+ .each do |row|
+ report.data << {
+ ignored_user_id: row.user_id,
+ ignored_username: row.username,
+ ignored_user_avatar_template:
+ User.avatar_template(row.username, row.uploaded_avatar_id),
+ ignores_count: row.ignores_count,
+ mutes_count: row.mutes_count,
+ }
+ end
end
end
end
diff --git a/app/models/concerns/reports/top_referred_topics.rb b/app/models/concerns/reports/top_referred_topics.rb
index 348b6537c11..c8cacb79297 100644
--- a/app/models/concerns/reports/top_referred_topics.rb
+++ b/app/models/concerns/reports/top_referred_topics.rb
@@ -14,15 +14,15 @@ module Reports::TopReferredTopics
type: :topic,
properties: {
title: :topic_title,
- id: :topic_id
+ id: :topic_id,
},
- title: I18n.t('reports.top_referred_topics.labels.topic')
+ title: I18n.t("reports.top_referred_topics.labels.topic"),
},
{
property: :num_clicks,
type: :number,
- title: I18n.t('reports.top_referred_topics.labels.num_clicks')
- }
+ title: I18n.t("reports.top_referred_topics.labels.num_clicks"),
+ },
]
options = {
@@ -30,7 +30,7 @@ module Reports::TopReferredTopics
start_date: report.start_date,
limit: report.limit || 8,
category_id: category_id,
- include_subcategories: include_subcategories
+ include_subcategories: include_subcategories,
}
result = nil
result = IncomingLinksReport.find(:top_referred_topics, options)
diff --git a/app/models/concerns/reports/top_referrers.rb b/app/models/concerns/reports/top_referrers.rb
index 3e8483ef535..3454f17632b 100644
--- a/app/models/concerns/reports/top_referrers.rb
+++ b/app/models/concerns/reports/top_referrers.rb
@@ -15,24 +15,24 @@ module Reports::TopReferrers
id: :user_id,
avatar: :user_avatar_template,
},
- title: I18n.t("reports.top_referrers.labels.user")
+ title: I18n.t("reports.top_referrers.labels.user"),
},
{
property: :num_clicks,
type: :number,
- title: I18n.t("reports.top_referrers.labels.num_clicks")
+ title: I18n.t("reports.top_referrers.labels.num_clicks"),
},
{
property: :num_topics,
type: :number,
- title: I18n.t("reports.top_referrers.labels.num_topics")
- }
+ title: I18n.t("reports.top_referrers.labels.num_topics"),
+ },
]
options = {
end_date: report.end_date,
start_date: report.start_date,
- limit: report.limit || 8
+ limit: report.limit || 8,
}
result = IncomingLinksReport.find(:top_referrers, options)
diff --git a/app/models/concerns/reports/top_traffic_sources.rb b/app/models/concerns/reports/top_traffic_sources.rb
index b6602bd1d2b..a1b313f01f9 100644
--- a/app/models/concerns/reports/top_traffic_sources.rb
+++ b/app/models/concerns/reports/top_traffic_sources.rb
@@ -10,20 +10,17 @@ module Reports::TopTrafficSources
report.modes = [:table]
report.labels = [
- {
- property: :domain,
- title: I18n.t('reports.top_traffic_sources.labels.domain')
- },
+ { property: :domain, title: I18n.t("reports.top_traffic_sources.labels.domain") },
{
property: :num_clicks,
type: :number,
- title: I18n.t('reports.top_traffic_sources.labels.num_clicks')
+ title: I18n.t("reports.top_traffic_sources.labels.num_clicks"),
},
{
property: :num_topics,
type: :number,
- title: I18n.t('reports.top_traffic_sources.labels.num_topics')
- }
+ title: I18n.t("reports.top_traffic_sources.labels.num_topics"),
+ },
]
options = {
@@ -31,7 +28,7 @@ module Reports::TopTrafficSources
start_date: report.start_date,
limit: report.limit || 8,
category_id: category_id,
- include_subcategories: include_subcategories
+ include_subcategories: include_subcategories,
}
result = IncomingLinksReport.find(:top_traffic_sources, options)
diff --git a/app/models/concerns/reports/top_uploads.rb b/app/models/concerns/reports/top_uploads.rb
index a3a53ce969c..d5e2955b7d9 100644
--- a/app/models/concerns/reports/top_uploads.rb
+++ b/app/models/concerns/reports/top_uploads.rb
@@ -8,20 +8,18 @@ module Reports::TopUploads
report.modes = [:table]
extension_filter = report.filters.dig(:file_extension)
- report.add_filter('file_extension',
- type: 'list',
- default: extension_filter || 'any',
- choices: (SiteSetting.authorized_extensions.split('|') + Array(extension_filter)).uniq
+ report.add_filter(
+ "file_extension",
+ type: "list",
+ default: extension_filter || "any",
+ choices: (SiteSetting.authorized_extensions.split("|") + Array(extension_filter)).uniq,
)
report.labels = [
{
type: :link,
- properties: [
- :file_url,
- :file_name,
- ],
- title: I18n.t("reports.top_uploads.labels.filename")
+ properties: %i[file_url file_name],
+ title: I18n.t("reports.top_uploads.labels.filename"),
},
{
type: :user,
@@ -30,18 +28,14 @@ module Reports::TopUploads
id: :author_id,
avatar: :author_avatar_template,
},
- title: I18n.t("reports.top_uploads.labels.author")
+ title: I18n.t("reports.top_uploads.labels.author"),
},
{
type: :text,
property: :extension,
- title: I18n.t("reports.top_uploads.labels.extension")
- },
- {
- type: :bytes,
- property: :filesize,
- title: I18n.t("reports.top_uploads.labels.filesize")
+ title: I18n.t("reports.top_uploads.labels.extension"),
},
+ { type: :bytes, property: :filesize, title: I18n.t("reports.top_uploads.labels.filesize") },
]
report.data = []
@@ -64,12 +58,15 @@ module Reports::TopUploads
SQL
builder = DB.build(sql)
- builder.where("up.id > :seeded_id_threshold", seeded_id_threshold: Upload::SEEDED_ID_THRESHOLD)
+ builder.where(
+ "up.id > :seeded_id_threshold",
+ seeded_id_threshold: Upload::SEEDED_ID_THRESHOLD,
+ )
builder.where("up.created_at >= :start_date", start_date: report.start_date)
builder.where("up.created_at < :end_date", end_date: report.end_date)
if extension_filter
- builder.where("up.extension = :extension", extension: extension_filter.sub(/^\./, ''))
+ builder.where("up.extension = :extension", extension: extension_filter.sub(/^\./, ""))
end
builder.query.each do |row|
diff --git a/app/models/concerns/reports/top_users_by_likes_received.rb b/app/models/concerns/reports/top_users_by_likes_received.rb
index 2f1b7c11329..2861cbefc51 100644
--- a/app/models/concerns/reports/top_users_by_likes_received.rb
+++ b/app/models/concerns/reports/top_users_by_likes_received.rb
@@ -5,7 +5,7 @@ module Reports::TopUsersByLikesReceived
class_methods do
def report_top_users_by_likes_received(report)
- report.icon = 'heart'
+ report.icon = "heart"
report.data = []
report.modes = [:table]
@@ -20,12 +20,12 @@ module Reports::TopUsersByLikesReceived
username: :username,
avatar: :user_avatar_template,
},
- title: I18n.t("reports.top_users_by_likes_received.labels.user")
+ title: I18n.t("reports.top_users_by_likes_received.labels.user"),
},
{
type: :number,
property: :qtt_like,
- title: I18n.t("reports.top_users_by_likes_received.labels.qtt_like")
+ title: I18n.t("reports.top_users_by_likes_received.labels.qtt_like"),
},
]
@@ -44,15 +44,16 @@ module Reports::TopUsersByLikesReceived
LIMIT 10
SQL
- DB.query(sql, start_date: report.start_date, end_date: report.end_date).each do |row|
- report.data << {
- user_id: row.user_id,
- username: row.username,
- user_avatar_template: User.avatar_template(row.username, row.uploaded_avatar_id),
- qtt_like: row.qtt_like,
- }
- end
-
+ DB
+ .query(sql, start_date: report.start_date, end_date: report.end_date)
+ .each do |row|
+ report.data << {
+ user_id: row.user_id,
+ username: row.username,
+ user_avatar_template: User.avatar_template(row.username, row.uploaded_avatar_id),
+ qtt_like: row.qtt_like,
+ }
+ end
end
end
end
diff --git a/app/models/concerns/reports/top_users_by_likes_received_from_a_variety_of_people.rb b/app/models/concerns/reports/top_users_by_likes_received_from_a_variety_of_people.rb
index 0bf6a7348c4..a6a42c72181 100644
--- a/app/models/concerns/reports/top_users_by_likes_received_from_a_variety_of_people.rb
+++ b/app/models/concerns/reports/top_users_by_likes_received_from_a_variety_of_people.rb
@@ -5,7 +5,7 @@ module Reports::TopUsersByLikesReceivedFromAVarietyOfPeople
class_methods do
def report_top_users_by_likes_received_from_a_variety_of_people(report)
- report.icon = 'heart'
+ report.icon = "heart"
report.data = []
report.modes = [:table]
@@ -20,12 +20,13 @@ module Reports::TopUsersByLikesReceivedFromAVarietyOfPeople
username: :username,
avatar: :user_avatar_template,
},
- title: I18n.t("reports.top_users_by_likes_received_from_a_variety_of_people.labels.user")
+ title: I18n.t("reports.top_users_by_likes_received_from_a_variety_of_people.labels.user"),
},
{
type: :number,
property: :qtt_like,
- title: I18n.t("reports.top_users_by_likes_received_from_a_variety_of_people.labels.qtt_like")
+ title:
+ I18n.t("reports.top_users_by_likes_received_from_a_variety_of_people.labels.qtt_like"),
},
]
@@ -46,15 +47,16 @@ module Reports::TopUsersByLikesReceivedFromAVarietyOfPeople
LIMIT 10
SQL
- DB.query(sql, start_date: report.start_date, end_date: report.end_date).each do |row|
- report.data << {
- user_id: row.user_id,
- username: row.username,
- user_avatar_template: User.avatar_template(row.username, row.uploaded_avatar_id),
- qtt_like: row.qtt_like,
- }
- end
-
+ DB
+ .query(sql, start_date: report.start_date, end_date: report.end_date)
+ .each do |row|
+ report.data << {
+ user_id: row.user_id,
+ username: row.username,
+ user_avatar_template: User.avatar_template(row.username, row.uploaded_avatar_id),
+ qtt_like: row.qtt_like,
+ }
+ end
end
end
end
diff --git a/app/models/concerns/reports/top_users_by_likes_received_from_inferior_trust_level.rb b/app/models/concerns/reports/top_users_by_likes_received_from_inferior_trust_level.rb
index d0b41d57d63..0daad06783f 100644
--- a/app/models/concerns/reports/top_users_by_likes_received_from_inferior_trust_level.rb
+++ b/app/models/concerns/reports/top_users_by_likes_received_from_inferior_trust_level.rb
@@ -5,7 +5,7 @@ module Reports::TopUsersByLikesReceivedFromInferiorTrustLevel
class_methods do
def report_top_users_by_likes_received_from_inferior_trust_level(report)
- report.icon = 'heart'
+ report.icon = "heart"
report.data = []
report.modes = [:table]
@@ -20,17 +20,22 @@ module Reports::TopUsersByLikesReceivedFromInferiorTrustLevel
username: :username,
avatar: :user_avatar_template,
},
- title: I18n.t("reports.top_users_by_likes_received_from_inferior_trust_level.labels.user")
+ title:
+ I18n.t("reports.top_users_by_likes_received_from_inferior_trust_level.labels.user"),
},
{
type: :number,
property: :trust_level,
- title: I18n.t("reports.top_users_by_likes_received_from_inferior_trust_level.labels.trust_level")
+ title:
+ I18n.t(
+ "reports.top_users_by_likes_received_from_inferior_trust_level.labels.trust_level",
+ ),
},
{
type: :number,
property: :qtt_like,
- title: I18n.t("reports.top_users_by_likes_received_from_inferior_trust_level.labels.qtt_like")
+ title:
+ I18n.t("reports.top_users_by_likes_received_from_inferior_trust_level.labels.qtt_like"),
},
]
@@ -56,16 +61,17 @@ module Reports::TopUsersByLikesReceivedFromInferiorTrustLevel
WHERE rank <= 10
SQL
- DB.query(sql, start_date: report.start_date, end_date: report.end_date).each do |row|
- report.data << {
- user_id: row.user_id,
- username: row.username,
- user_avatar_template: User.avatar_template(row.username, row.uploaded_avatar_id),
- trust_level: row.trust_level,
- qtt_like: row.qtt_like,
- }
- end
-
+ DB
+ .query(sql, start_date: report.start_date, end_date: report.end_date)
+ .each do |row|
+ report.data << {
+ user_id: row.user_id,
+ username: row.username,
+ user_avatar_template: User.avatar_template(row.username, row.uploaded_avatar_id),
+ trust_level: row.trust_level,
+ qtt_like: row.qtt_like,
+ }
+ end
end
end
end
diff --git a/app/models/concerns/reports/topics.rb b/app/models/concerns/reports/topics.rb
index 19c527b3140..19412a6a4da 100644
--- a/app/models/concerns/reports/topics.rb
+++ b/app/models/concerns/reports/topics.rb
@@ -7,12 +7,21 @@ module Reports::Topics
def report_topics(report)
category_id, include_subcategories = report.add_category_filter
- basic_report_about report, Topic, :listable_count_per_day, report.start_date, report.end_date, category_id, include_subcategories
+ basic_report_about report,
+ Topic,
+ :listable_count_per_day,
+ report.start_date,
+ report.end_date,
+ category_id,
+ include_subcategories
countable = Topic.listable_topics
- countable = countable.where(category_id: include_subcategories ? Category.subcategory_ids(category_id) : category_id) if category_id
+ countable =
+ countable.where(
+ category_id: include_subcategories ? Category.subcategory_ids(category_id) : category_id,
+ ) if category_id
- add_counts report, countable, 'topics.created_at'
+ add_counts report, countable, "topics.created_at"
end
end
end
diff --git a/app/models/concerns/reports/topics_with_no_response.rb b/app/models/concerns/reports/topics_with_no_response.rb
index e09c3f08c5b..4cd4b762a27 100644
--- a/app/models/concerns/reports/topics_with_no_response.rb
+++ b/app/models/concerns/reports/topics_with_no_response.rb
@@ -8,13 +8,28 @@ module Reports::TopicsWithNoResponse
category_id, include_subcategories = report.add_category_filter
report.data = []
- Topic.with_no_response_per_day(report.start_date, report.end_date, category_id, include_subcategories).each do |r|
- report.data << { x: r['date'], y: r['count'].to_i }
- end
+ Topic
+ .with_no_response_per_day(
+ report.start_date,
+ report.end_date,
+ category_id,
+ include_subcategories,
+ )
+ .each { |r| report.data << { x: r["date"], y: r["count"].to_i } }
- report.total = Topic.with_no_response_total(category_id: category_id, include_subcategories: include_subcategories)
+ report.total =
+ Topic.with_no_response_total(
+ category_id: category_id,
+ include_subcategories: include_subcategories,
+ )
- report.prev30Days = Topic.with_no_response_total(start_date: report.start_date - 30.days, end_date: report.start_date, category_id: category_id, include_subcategories: include_subcategories)
+ report.prev30Days =
+ Topic.with_no_response_total(
+ start_date: report.start_date - 30.days,
+ end_date: report.start_date,
+ category_id: category_id,
+ include_subcategories: include_subcategories,
+ )
end
end
end
diff --git a/app/models/concerns/reports/trending_search.rb b/app/models/concerns/reports/trending_search.rb
index b30e522744c..8d4f5ff38a3 100644
--- a/app/models/concerns/reports/trending_search.rb
+++ b/app/models/concerns/reports/trending_search.rb
@@ -6,38 +6,28 @@ module Reports::TrendingSearch
class_methods do
def report_trending_search(report)
report.labels = [
- {
- property: :term,
- type: :text,
- title: I18n.t("reports.trending_search.labels.term")
- },
+ { property: :term, type: :text, title: I18n.t("reports.trending_search.labels.term") },
{
property: :searches,
type: :number,
- title: I18n.t("reports.trending_search.labels.searches")
+ title: I18n.t("reports.trending_search.labels.searches"),
},
{
type: :percent,
property: :ctr,
- title: I18n.t("reports.trending_search.labels.click_through")
- }
+ title: I18n.t("reports.trending_search.labels.click_through"),
+ },
]
report.data = []
report.modes = [:table]
- trends = SearchLog.trending_from(report.start_date,
- end_date: report.end_date,
- limit: report.limit
- )
+ trends =
+ SearchLog.trending_from(report.start_date, end_date: report.end_date, limit: report.limit)
trends.each do |trend|
- report.data << {
- term: trend.term,
- searches: trend.searches,
- ctr: trend.ctr
- }
+ report.data << { term: trend.term, searches: trend.searches, ctr: trend.ctr }
end
end
end
diff --git a/app/models/concerns/reports/trust_level_growth.rb b/app/models/concerns/reports/trust_level_growth.rb
index 0071b579ff1..d1f82f06891 100644
--- a/app/models/concerns/reports/trust_level_growth.rb
+++ b/app/models/concerns/reports/trust_level_growth.rb
@@ -7,12 +7,7 @@ module Reports::TrustLevelGrowth
def report_trust_level_growth(report)
report.modes = [:stacked_chart]
- filters = %w[
- tl1_reached
- tl2_reached
- tl3_reached
- tl4_reached
- ]
+ filters = %w[tl1_reached tl2_reached tl3_reached tl4_reached]
sql = <<~SQL
SELECT
@@ -42,41 +37,36 @@ module Reports::TrustLevelGrowth
ORDER BY date(created_at)
SQL
- data = Hash[ filters.collect { |x| [x, []] } ]
+ data = Hash[filters.collect { |x| [x, []] }]
builder = DB.build(sql)
builder.query.each do |row|
filters.each do |filter|
data[filter] << {
x: row.date.strftime("%Y-%m-%d"),
- y: row.instance_variable_get("@#{filter}")
+ y: row.instance_variable_get("@#{filter}"),
}
end
end
- tertiary = ColorScheme.hex_for_name('tertiary') || '0088cc'
- quaternary = ColorScheme.hex_for_name('quaternary') || 'e45735'
+ tertiary = ColorScheme.hex_for_name("tertiary") || "0088cc"
+ quaternary = ColorScheme.hex_for_name("quaternary") || "e45735"
- requests = filters.map do |filter|
- color = report.rgba_color(quaternary)
+ requests =
+ filters.map do |filter|
+ color = report.rgba_color(quaternary)
- if filter == "tl1_reached"
- color = report.lighten_color(tertiary, 0.25)
- end
- if filter == "tl2_reached"
- color = report.rgba_color(tertiary)
- end
- if filter == "tl3_reached"
- color = report.lighten_color(quaternary, 0.25)
- end
+ color = report.lighten_color(tertiary, 0.25) if filter == "tl1_reached"
+ color = report.rgba_color(tertiary) if filter == "tl2_reached"
+ color = report.lighten_color(quaternary, 0.25) if filter == "tl3_reached"
- {
- req: filter,
- label: I18n.t("reports.trust_level_growth.xaxis.#{filter}"),
- color: color,
- data: data[filter]
- }
- end
+ {
+ req: filter,
+ label: I18n.t("reports.trust_level_growth.xaxis.#{filter}"),
+ color: color,
+ data: data[filter],
+ }
+ end
report.data = requests
end
diff --git a/app/models/concerns/reports/user_flagging_ratio.rb b/app/models/concerns/reports/user_flagging_ratio.rb
index 96c2439106b..0147792a8d8 100644
--- a/app/models/concerns/reports/user_flagging_ratio.rb
+++ b/app/models/concerns/reports/user_flagging_ratio.rb
@@ -19,27 +19,27 @@ module Reports::UserFlaggingRatio
id: :user_id,
avatar: :avatar_template,
},
- title: I18n.t("reports.user_flagging_ratio.labels.user")
+ title: I18n.t("reports.user_flagging_ratio.labels.user"),
},
{
type: :number,
property: :disagreed_flags,
- title: I18n.t("reports.user_flagging_ratio.labels.disagreed_flags")
+ title: I18n.t("reports.user_flagging_ratio.labels.disagreed_flags"),
},
{
type: :number,
property: :agreed_flags,
- title: I18n.t("reports.user_flagging_ratio.labels.agreed_flags")
+ title: I18n.t("reports.user_flagging_ratio.labels.agreed_flags"),
},
{
type: :number,
property: :ignored_flags,
- title: I18n.t("reports.user_flagging_ratio.labels.ignored_flags")
+ title: I18n.t("reports.user_flagging_ratio.labels.ignored_flags"),
},
{
type: :number,
property: :score,
- title: I18n.t("reports.user_flagging_ratio.labels.score")
+ title: I18n.t("reports.user_flagging_ratio.labels.score"),
},
]
@@ -74,18 +74,20 @@ module Reports::UserFlaggingRatio
LIMIT 100
SQL
- DB.query(sql, start_date: report.start_date, end_date: report.end_date).each do |row|
- flagger = {}
- flagger[:user_id] = row.id
- flagger[:username] = row.username
- flagger[:avatar_template] = User.avatar_template(row.username, row.avatar_id)
- flagger[:disagreed_flags] = row.disagreed_flags
- flagger[:ignored_flags] = row.ignored_flags
- flagger[:agreed_flags] = row.agreed_flags
- flagger[:score] = row.score
+ DB
+ .query(sql, start_date: report.start_date, end_date: report.end_date)
+ .each do |row|
+ flagger = {}
+ flagger[:user_id] = row.id
+ flagger[:username] = row.username
+ flagger[:avatar_template] = User.avatar_template(row.username, row.avatar_id)
+ flagger[:disagreed_flags] = row.disagreed_flags
+ flagger[:ignored_flags] = row.ignored_flags
+ flagger[:agreed_flags] = row.agreed_flags
+ flagger[:score] = row.score
- report.data << flagger
- end
+ report.data << flagger
+ end
end
end
end
diff --git a/app/models/concerns/reports/user_to_user_private_messages.rb b/app/models/concerns/reports/user_to_user_private_messages.rb
index 7a996400bcc..5d38191545a 100644
--- a/app/models/concerns/reports/user_to_user_private_messages.rb
+++ b/app/models/concerns/reports/user_to_user_private_messages.rb
@@ -5,7 +5,7 @@ module Reports::UserToUserPrivateMessages
class_methods do
def report_user_to_user_private_messages(report)
- report.icon = 'envelope'
+ report.icon = "envelope"
private_messages_report report, TopicSubtype.user_to_user
end
end
diff --git a/app/models/concerns/reports/user_to_user_private_messages_with_replies.rb b/app/models/concerns/reports/user_to_user_private_messages_with_replies.rb
index 42dfc590e40..76c78e6be79 100644
--- a/app/models/concerns/reports/user_to_user_private_messages_with_replies.rb
+++ b/app/models/concerns/reports/user_to_user_private_messages_with_replies.rb
@@ -5,12 +5,17 @@ module Reports::UserToUserPrivateMessagesWithReplies
class_methods do
def report_user_to_user_private_messages_with_replies(report)
- report.icon = 'envelope'
+ report.icon = "envelope"
topic_subtype = TopicSubtype.user_to_user
- subject = Post.where('posts.user_id > 0')
- basic_report_about report, subject, :private_messages_count_per_day, report.start_date, report.end_date, topic_subtype
- subject = Post.private_posts.where('posts.user_id > 0').with_topic_subtype(topic_subtype)
- add_counts report, subject, 'posts.created_at'
+ subject = Post.where("posts.user_id > 0")
+ basic_report_about report,
+ subject,
+ :private_messages_count_per_day,
+ report.start_date,
+ report.end_date,
+ topic_subtype
+ subject = Post.private_posts.where("posts.user_id > 0").with_topic_subtype(topic_subtype)
+ add_counts report, subject, "posts.created_at"
end
end
end
diff --git a/app/models/concerns/reports/users_by_trust_level.rb b/app/models/concerns/reports/users_by_trust_level.rb
index ac2d1b94f1d..f0226a90c8a 100644
--- a/app/models/concerns/reports/users_by_trust_level.rb
+++ b/app/models/concerns/reports/users_by_trust_level.rb
@@ -12,22 +12,20 @@ module Reports::UsersByTrustLevel
report.dates_filtering = false
report.labels = [
- {
- property: :key,
- title: I18n.t("reports.users_by_trust_level.labels.level")
- },
- {
- property: :y,
- type: :number,
- title: I18n.t("reports.default.labels.count")
- }
+ { property: :key, title: I18n.t("reports.users_by_trust_level.labels.level") },
+ { property: :y, type: :number, title: I18n.t("reports.default.labels.count") },
]
- User.real.group('trust_level').count.sort.each do |level, count|
- key = TrustLevel.levels.key(level.to_i)
- url = Proc.new { |k| "/admin/users/list/#{k}" }
- report.data << { url: url.call(key), key: key, x: level.to_i, y: count }
- end
+ User
+ .real
+ .group("trust_level")
+ .count
+ .sort
+ .each do |level, count|
+ key = TrustLevel.levels.key(level.to_i)
+ url = Proc.new { |k| "/admin/users/list/#{k}" }
+ report.data << { url: url.call(key), key: key, x: level.to_i, y: count }
+ end
end
end
end
diff --git a/app/models/concerns/reports/users_by_type.rb b/app/models/concerns/reports/users_by_type.rb
index 33952f3dbb6..5fd407dd3f5 100644
--- a/app/models/concerns/reports/users_by_type.rb
+++ b/app/models/concerns/reports/users_by_type.rb
@@ -12,31 +12,56 @@ module Reports::UsersByType
report.dates_filtering = false
report.labels = [
- {
- property: :x,
- title: I18n.t("reports.users_by_type.labels.type")
- },
- {
- property: :y,
- type: :number,
- title: I18n.t("reports.default.labels.count")
- }
+ { property: :x, title: I18n.t("reports.users_by_type.labels.type") },
+ { property: :y, type: :number, title: I18n.t("reports.default.labels.count") },
]
label = Proc.new { |x| I18n.t("reports.users_by_type.xaxis_labels.#{x}") }
url = Proc.new { |key| "/admin/users/list/#{key}" }
admins = User.real.admins.count
- report.data << { url: url.call("admins"), icon: "shield-alt", key: "admins", x: label.call("admin"), y: admins } if admins > 0
+ if admins > 0
+ report.data << {
+ url: url.call("admins"),
+ icon: "shield-alt",
+ key: "admins",
+ x: label.call("admin"),
+ y: admins,
+ }
+ end
moderators = User.real.moderators.count
- report.data << { url: url.call("moderators"), icon: "shield-alt", key: "moderators", x: label.call("moderator"), y: moderators } if moderators > 0
+ if moderators > 0
+ report.data << {
+ url: url.call("moderators"),
+ icon: "shield-alt",
+ key: "moderators",
+ x: label.call("moderator"),
+ y: moderators,
+ }
+ end
suspended = User.real.suspended.count
- report.data << { url: url.call("suspended"), icon: "ban", key: "suspended", x: label.call("suspended"), y: suspended } if suspended > 0
+ if suspended > 0
+ report.data << {
+ url: url.call("suspended"),
+ icon: "ban",
+ key: "suspended",
+ x: label.call("suspended"),
+ y: suspended,
+ }
+ end
silenced = User.real.silenced.count
- report.data << { url: url.call("silenced"), icon: "ban", key: "silenced", x: label.call("silenced"), y: silenced } if silenced > 0
+ if silenced > 0
+ report.data << {
+ url: url.call("silenced"),
+ icon: "ban",
+ key: "silenced",
+ x: label.call("silenced"),
+ y: silenced,
+ }
+ end
end
end
end
diff --git a/app/models/concerns/reports/visits.rb b/app/models/concerns/reports/visits.rb
index 676cf772021..7878d0a3b7d 100644
--- a/app/models/concerns/reports/visits.rb
+++ b/app/models/concerns/reports/visits.rb
@@ -6,14 +6,24 @@ module Reports::Visits
class_methods do
def report_visits(report)
group_filter = report.filters.dig(:group)
- report.add_filter('group', type: 'group', default: group_filter)
+ report.add_filter("group", type: "group", default: group_filter)
- report.icon = 'user'
+ report.icon = "user"
- basic_report_about report, UserVisit, :by_day, report.start_date, report.end_date, group_filter
- add_counts report, UserVisit, 'visited_at'
+ basic_report_about report,
+ UserVisit,
+ :by_day,
+ report.start_date,
+ report.end_date,
+ group_filter
+ add_counts report, UserVisit, "visited_at"
- report.prev30Days = UserVisit.where('visited_at >= ? and visited_at < ?', report.start_date - 30.days, report.start_date).count
+ report.prev30Days =
+ UserVisit.where(
+ "visited_at >= ? and visited_at < ?",
+ report.start_date - 30.days,
+ report.start_date,
+ ).count
end
end
end
diff --git a/app/models/concerns/reports/web_crawlers.rb b/app/models/concerns/reports/web_crawlers.rb
index 6db61d11a97..cdb731eeab5 100644
--- a/app/models/concerns/reports/web_crawlers.rb
+++ b/app/models/concerns/reports/web_crawlers.rb
@@ -9,22 +9,25 @@ module Reports::WebCrawlers
{
type: :string,
property: :user_agent,
- title: I18n.t('reports.web_crawlers.labels.user_agent')
+ title: I18n.t("reports.web_crawlers.labels.user_agent"),
},
{
property: :count,
type: :number,
- title: I18n.t('reports.web_crawlers.labels.page_views')
- }
+ title: I18n.t("reports.web_crawlers.labels.page_views"),
+ },
]
report.modes = [:table]
- report.data = WebCrawlerRequest.where('date >= ? and date <= ?', report.start_date, report.end_date)
- .limit(200)
- .order('sum_count DESC')
- .group(:user_agent).sum(:count)
- .map { |ua, count| { user_agent: ua, count: count } }
+ report.data =
+ WebCrawlerRequest
+ .where("date >= ? and date <= ?", report.start_date, report.end_date)
+ .limit(200)
+ .order("sum_count DESC")
+ .group(:user_agent)
+ .sum(:count)
+ .map { |ua, count| { user_agent: ua, count: count } }
end
end
end
diff --git a/app/models/concerns/roleable.rb b/app/models/concerns/roleable.rb
index 0400db789db..ebfe7ac6623 100644
--- a/app/models/concerns/roleable.rb
+++ b/app/models/concerns/roleable.rb
@@ -19,37 +19,38 @@ module Roleable
end
def whisperer?
- @whisperer ||= begin
- whispers_allowed_group_ids = SiteSetting.whispers_allowed_group_ids
- return false if whispers_allowed_group_ids.blank?
- return true if admin
- return true if whispers_allowed_group_ids.include?(primary_group_id)
- group_users&.exists?(group_id: whispers_allowed_group_ids)
- end
+ @whisperer ||=
+ begin
+ whispers_allowed_group_ids = SiteSetting.whispers_allowed_group_ids
+ return false if whispers_allowed_group_ids.blank?
+ return true if admin
+ return true if whispers_allowed_group_ids.include?(primary_group_id)
+ group_users&.exists?(group_id: whispers_allowed_group_ids)
+ end
end
def grant_moderation!
return if moderator
- set_permission('moderator', true)
+ set_permission("moderator", true)
auto_approve_user
enqueue_staff_welcome_message(:moderator)
set_default_notification_levels(:moderators)
end
def revoke_moderation!
- set_permission('moderator', false)
+ set_permission("moderator", false)
end
def grant_admin!
return if admin
- set_permission('admin', true)
+ set_permission("admin", true)
auto_approve_user
enqueue_staff_welcome_message(:admin)
set_default_notification_levels(:admins)
end
def revoke_admin!
- set_permission('admin', false)
+ set_permission("admin", false)
end
def save_and_refresh_staff_groups!
diff --git a/app/models/concerns/searchable.rb b/app/models/concerns/searchable.rb
index ed01ecff8e9..84ba85843b9 100644
--- a/app/models/concerns/searchable.rb
+++ b/app/models/concerns/searchable.rb
@@ -3,16 +3,7 @@
module Searchable
extend ActiveSupport::Concern
- PRIORITIES = Enum.new(
- ignore: 1,
- very_low: 2,
- low: 3,
- normal: 0,
- high: 4,
- very_high: 5
- )
+ PRIORITIES = Enum.new(ignore: 1, very_low: 2, low: 3, normal: 0, high: 4, very_high: 5)
- included do
- has_one "#{self.name.underscore}_search_data".to_sym, dependent: :destroy
- end
+ included { has_one "#{self.name.underscore}_search_data".to_sym, dependent: :destroy }
end
diff --git a/app/models/concerns/second_factor_manager.rb b/app/models/concerns/second_factor_manager.rb
index e21957e75ff..dc74d541e08 100644
--- a/app/models/concerns/second_factor_manager.rb
+++ b/app/models/concerns/second_factor_manager.rb
@@ -5,24 +5,27 @@ module SecondFactorManager
extend ActiveSupport::Concern
- SecondFactorAuthenticationResult = Struct.new(
- :ok,
- :error,
- :reason,
- :backup_enabled,
- :security_key_enabled,
- :totp_enabled,
- :multiple_second_factor_methods,
- :used_2fa_method,
- )
+ SecondFactorAuthenticationResult =
+ Struct.new(
+ :ok,
+ :error,
+ :reason,
+ :backup_enabled,
+ :security_key_enabled,
+ :totp_enabled,
+ :multiple_second_factor_methods,
+ :used_2fa_method,
+ )
def create_totp(opts = {})
require_rotp
- UserSecondFactor.create!({
- user_id: self.id,
- method: UserSecondFactor.methods[:totp],
- data: ROTP::Base32.random
- }.merge(opts))
+ UserSecondFactor.create!(
+ {
+ user_id: self.id,
+ method: UserSecondFactor.methods[:totp],
+ data: ROTP::Base32.random,
+ }.merge(opts),
+ )
end
def get_totp_object(data)
@@ -38,19 +41,18 @@ module SecondFactorManager
totps = self&.user_second_factors.totps
authenticated = false
totps.each do |totp|
-
last_used = 0
- if totp.last_used
- last_used = totp.last_used.to_i
- end
+ last_used = totp.last_used.to_i if totp.last_used
- authenticated = !token.blank? && totp.totp_object.verify(
- token,
- drift_ahead: TOTP_ALLOWED_DRIFT_SECONDS,
- drift_behind: TOTP_ALLOWED_DRIFT_SECONDS,
- after: last_used
- )
+ authenticated =
+ !token.blank? &&
+ totp.totp_object.verify(
+ token,
+ drift_ahead: TOTP_ALLOWED_DRIFT_SECONDS,
+ drift_behind: TOTP_ALLOWED_DRIFT_SECONDS,
+ after: last_used,
+ )
if authenticated
totp.update!(last_used: DateTime.now)
@@ -61,21 +63,21 @@ module SecondFactorManager
end
def totp_enabled?
- !SiteSetting.enable_discourse_connect &&
- SiteSetting.enable_local_logins &&
+ !SiteSetting.enable_discourse_connect && SiteSetting.enable_local_logins &&
self&.user_second_factors.totps.exists?
end
def backup_codes_enabled?
- !SiteSetting.enable_discourse_connect &&
- SiteSetting.enable_local_logins &&
+ !SiteSetting.enable_discourse_connect && SiteSetting.enable_local_logins &&
self&.user_second_factors.backup_codes.exists?
end
def security_keys_enabled?
- !SiteSetting.enable_discourse_connect &&
- SiteSetting.enable_local_logins &&
- self&.security_keys.where(factor_type: UserSecurityKey.factor_types[:second_factor], enabled: true).exists?
+ !SiteSetting.enable_discourse_connect && SiteSetting.enable_local_logins &&
+ self
+ &.security_keys
+ .where(factor_type: UserSecurityKey.factor_types[:second_factor], enabled: true)
+ .exists?
end
def has_any_second_factor_methods_enabled?
@@ -166,35 +168,35 @@ module SecondFactorManager
security_key_credential,
challenge: Webauthn.challenge(self, secure_session),
rp_id: Webauthn.rp_id(self, secure_session),
- origin: Discourse.base_url
+ origin: Discourse.base_url,
).authenticate_security_key
end
def invalid_totp_or_backup_code_result
invalid_second_factor_authentication_result(
I18n.t("login.invalid_second_factor_code"),
- "invalid_second_factor"
+ "invalid_second_factor",
)
end
def invalid_security_key_result(error_message = nil)
invalid_second_factor_authentication_result(
error_message || I18n.t("login.invalid_security_key"),
- "invalid_security_key"
+ "invalid_security_key",
)
end
def invalid_second_factor_method_result
invalid_second_factor_authentication_result(
I18n.t("login.invalid_second_factor_method"),
- "invalid_second_factor_method"
+ "invalid_second_factor_method",
)
end
def not_enabled_second_factor_method_result
invalid_second_factor_authentication_result(
I18n.t("login.not_enabled_second_factor_method"),
- "not_enabled_second_factor_method"
+ "not_enabled_second_factor_method",
)
end
@@ -206,22 +208,19 @@ module SecondFactorManager
backup_codes_enabled?,
security_keys_enabled?,
totp_enabled?,
- has_multiple_second_factor_methods?
+ has_multiple_second_factor_methods?,
)
end
def generate_backup_codes
codes = []
- 10.times do
- codes << SecureRandom.hex(16)
- end
+ 10.times { codes << SecureRandom.hex(16) }
- codes_json = codes.map do |code|
- salt = SecureRandom.hex(16)
- { salt: salt,
- code_hash: hash_backup_code(code, salt)
- }
- end
+ codes_json =
+ codes.map do |code|
+ salt = SecureRandom.hex(16)
+ { salt: salt, code_hash: hash_backup_code(code, salt) }
+ end
if self.user_second_factors.backup_codes.empty?
create_backup_codes(codes_json)
@@ -239,7 +238,7 @@ module SecondFactorManager
user_id: self.id,
data: code.to_json,
enabled: true,
- method: UserSecondFactor.methods[:backup_codes]
+ method: UserSecondFactor.methods[:backup_codes],
)
end
end
@@ -264,10 +263,15 @@ module SecondFactorManager
end
def hash_backup_code(code, salt)
- Pbkdf2.hash_password(code, salt, Rails.configuration.pbkdf2_iterations, Rails.configuration.pbkdf2_algorithm)
+ Pbkdf2.hash_password(
+ code,
+ salt,
+ Rails.configuration.pbkdf2_iterations,
+ Rails.configuration.pbkdf2_algorithm,
+ )
end
def require_rotp
- require 'rotp' if !defined? ROTP
+ require "rotp" if !defined?(ROTP)
end
end
diff --git a/app/models/concerns/stats_cacheable.rb b/app/models/concerns/stats_cacheable.rb
index 31d4908097c..027c02f83fe 100644
--- a/app/models/concerns/stats_cacheable.rb
+++ b/app/models/concerns/stats_cacheable.rb
@@ -5,11 +5,11 @@ module StatsCacheable
module ClassMethods
def stats_cache_key
- raise 'Stats cache key has not been set.'
+ raise "Stats cache key has not been set."
end
def fetch_stats
- raise 'Not implemented.'
+ raise "Not implemented."
end
# Could be configurable, multisite need to support it.
diff --git a/app/models/concerns/topic_tracking_state_publishable.rb b/app/models/concerns/topic_tracking_state_publishable.rb
index 77dd75a841a..079bda6dbe0 100644
--- a/app/models/concerns/topic_tracking_state_publishable.rb
+++ b/app/models/concerns/topic_tracking_state_publishable.rb
@@ -4,17 +4,19 @@ module TopicTrackingStatePublishable
extend ActiveSupport::Concern
class_methods do
- def publish_read_message(message_type:,
- channel_name:,
- topic_id:,
- user:,
- last_read_post_number:,
- notification_level: nil)
-
- highest_post_number = DB.query_single(
- "SELECT #{user.whisperer? ? "highest_staff_post_number" : "highest_post_number"} FROM topics WHERE id = ?",
- topic_id
- ).first
+ def publish_read_message(
+ message_type:,
+ channel_name:,
+ topic_id:,
+ user:,
+ last_read_post_number:,
+ notification_level: nil
+ )
+ highest_post_number =
+ DB.query_single(
+ "SELECT #{user.whisperer? ? "highest_staff_post_number" : "highest_post_number"} FROM topics WHERE id = ?",
+ topic_id,
+ ).first
message = {
message_type: message_type,
@@ -22,8 +24,8 @@ module TopicTrackingStatePublishable
payload: {
last_read_post_number: last_read_post_number,
notification_level: notification_level,
- highest_post_number: highest_post_number
- }
+ highest_post_number: highest_post_number,
+ },
}.as_json
MessageBus.publish(channel_name, message, user_ids: [user.id])
diff --git a/app/models/concerns/trashable.rb b/app/models/concerns/trashable.rb
index 2a7e51fa81a..cdd52c08425 100644
--- a/app/models/concerns/trashable.rb
+++ b/app/models/concerns/trashable.rb
@@ -7,7 +7,7 @@ module Trashable
default_scope { where(deleted_at: nil) }
scope :with_deleted, -> { unscope(where: :deleted_at) }
- belongs_to :deleted_by, class_name: 'User'
+ belongs_to :deleted_by, class_name: "User"
end
def trashed?
@@ -33,5 +33,4 @@ module Trashable
def trash_update(deleted_at, deleted_by_id)
self.update_columns(deleted_at: deleted_at, deleted_by_id: deleted_by_id)
end
-
end
diff --git a/app/models/developer.rb b/app/models/developer.rb
index a789dd6dd66..ee25a849c92 100644
--- a/app/models/developer.rb
+++ b/app/models/developer.rb
@@ -6,7 +6,7 @@ class Developer < ActiveRecord::Base
after_save :rebuild_cache
after_destroy :rebuild_cache
- @id_cache = DistributedCache.new('developer_ids')
+ @id_cache = DistributedCache.new("developer_ids")
def self.user_ids
@id_cache["ids"] || rebuild_cache
diff --git a/app/models/digest_email_site_setting.rb b/app/models/digest_email_site_setting.rb
index 23cc4e28ecb..08055b53098 100644
--- a/app/models/digest_email_site_setting.rb
+++ b/app/models/digest_email_site_setting.rb
@@ -1,26 +1,23 @@
# frozen_string_literal: true
class DigestEmailSiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
- val.to_i.to_s == val.to_s &&
- values.any? { |v| v[:value] == val.to_i }
+ val.to_i.to_s == val.to_s && values.any? { |v| v[:value] == val.to_i }
end
def self.values
@values ||= [
- { name: 'never', value: 0 },
- { name: 'every_30_minutes', value: 30 },
- { name: 'every_hour', value: 60 },
- { name: 'daily', value: 1440 },
- { name: 'weekly', value: 10080 },
- { name: 'every_month', value: 43200 },
- { name: 'every_six_months', value: 259200 }
+ { name: "never", value: 0 },
+ { name: "every_30_minutes", value: 30 },
+ { name: "every_hour", value: 60 },
+ { name: "daily", value: 1440 },
+ { name: "weekly", value: 10_080 },
+ { name: "every_month", value: 43_200 },
+ { name: "every_six_months", value: 259_200 },
]
end
def self.translate_names?
true
end
-
end
diff --git a/app/models/directory_column.rb b/app/models/directory_column.rb
index 3a290432c2f..73a0762a1e8 100644
--- a/app/models/directory_column.rb
+++ b/app/models/directory_column.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class DirectoryColumn < ActiveRecord::Base
-
# TODO(2021-06-18): Remove automatic column
self.ignored_columns = ["automatic"]
self.inheritance_column = nil
@@ -9,17 +8,23 @@ class DirectoryColumn < ActiveRecord::Base
enum type: { automatic: 0, user_field: 1, plugin: 2 }, _scopes: false
def self.automatic_column_names
- @automatic_column_names ||= [:likes_received,
- :likes_given,
- :topics_entered,
- :topic_count,
- :post_count,
- :posts_read,
- :days_visited]
+ @automatic_column_names ||= %i[
+ likes_received
+ likes_given
+ topics_entered
+ topic_count
+ post_count
+ posts_read
+ days_visited
+ ]
end
def self.active_column_names
- DirectoryColumn.where(type: [:automatic, :plugin]).where(enabled: true).pluck(:name).map(&:to_sym)
+ DirectoryColumn
+ .where(type: %i[automatic plugin])
+ .where(enabled: true)
+ .pluck(:name)
+ .map(&:to_sym)
end
@@plugin_directory_columns = []
@@ -35,14 +40,15 @@ class DirectoryColumn < ActiveRecord::Base
end
def self.find_or_create_plugin_directory_column(attrs)
- directory_column = find_or_create_by(
- name: attrs[:column_name],
- icon: attrs[:icon],
- type: DirectoryColumn.types[:plugin]
- ) do |column|
- column.position = DirectoryColumn.maximum("position") + 1
- column.enabled = false
- end
+ directory_column =
+ find_or_create_by(
+ name: attrs[:column_name],
+ icon: attrs[:icon],
+ type: DirectoryColumn.types[:plugin],
+ ) do |column|
+ column.position = DirectoryColumn.maximum("position") + 1
+ column.enabled = false
+ end
unless @@plugin_directory_columns.include?(directory_column.name)
@@plugin_directory_columns << directory_column.name
diff --git a/app/models/directory_item.rb b/app/models/directory_item.rb
index 817697a434a..0dce2080868 100644
--- a/app/models/directory_item.rb
+++ b/app/models/directory_item.rb
@@ -7,12 +7,7 @@ class DirectoryItem < ActiveRecord::Base
@@plugin_queries = []
def self.period_types
- @types ||= Enum.new(all: 1,
- yearly: 2,
- monthly: 3,
- weekly: 4,
- daily: 5,
- quarterly: 6)
+ @types ||= Enum.new(all: 1, yearly: 2, monthly: 3, weekly: 4, daily: 5, quarterly: 6)
end
def self.refresh!
@@ -43,36 +38,49 @@ class DirectoryItem < ActiveRecord::Base
since =
case period_type
- when :daily then 1.day.ago
- when :weekly then 1.week.ago
- when :monthly then 1.month.ago
- when :quarterly then 3.months.ago
- when :yearly then 1.year.ago
- else 1000.years.ago
+ when :daily
+ 1.day.ago
+ when :weekly
+ 1.week.ago
+ when :monthly
+ 1.month.ago
+ when :quarterly
+ 3.months.ago
+ when :yearly
+ 1.year.ago
+ else
+ 1000.years.ago
end
ActiveRecord::Base.transaction do
# Delete records that belonged to users who have been deleted
- DB.exec("DELETE FROM directory_items
+ DB.exec(
+ "DELETE FROM directory_items
USING directory_items di
LEFT JOIN users u ON (u.id = user_id AND u.active AND u.silenced_till IS NULL AND u.id > 0)
WHERE di.id = directory_items.id AND
u.id IS NULL AND
- di.period_type = :period_type", period_type: period_types[period_type])
+ di.period_type = :period_type",
+ period_type: period_types[period_type],
+ )
# Create new records for users who don't have one yet
- column_names = DirectoryColumn.automatic_column_names + DirectoryColumn.plugin_directory_columns
- DB.exec("INSERT INTO directory_items(period_type, user_id, #{column_names.map(&:to_s).join(", ")})
+ column_names =
+ DirectoryColumn.automatic_column_names + DirectoryColumn.plugin_directory_columns
+ DB.exec(
+ "INSERT INTO directory_items(period_type, user_id, #{column_names.map(&:to_s).join(", ")})
SELECT
:period_type,
u.id,
- #{Array.new(column_names.count) { |_| 0 }.join(", ") }
+ #{Array.new(column_names.count) { |_| 0 }.join(", ")}
FROM users u
LEFT JOIN directory_items di ON di.user_id = u.id AND di.period_type = :period_type
WHERE di.id IS NULL AND u.id > 0 AND u.silenced_till IS NULL AND u.active
- #{SiteSetting.must_approve_users ? 'AND u.approved' : ''}
- ", period_type: period_types[period_type])
+ #{SiteSetting.must_approve_users ? "AND u.approved" : ""}
+ ",
+ period_type: period_types[period_type],
+ )
# Calculate new values and update records
#
@@ -88,10 +96,11 @@ class DirectoryItem < ActiveRecord::Base
was_liked_type: UserAction::WAS_LIKED,
new_topic_type: UserAction::NEW_TOPIC,
reply_type: UserAction::REPLY,
- regular_post_type: Post.types[:regular]
+ regular_post_type: Post.types[:regular],
}
- DB.exec("WITH x AS (SELECT
+ DB.exec(
+ "WITH x AS (SELECT
u.id user_id,
SUM(CASE WHEN p.id IS NOT NULL AND t.id IS NOT NULL AND ua.action_type = :was_liked_type THEN 1 ELSE 0 END) likes_received,
SUM(CASE WHEN p.id IS NOT NULL AND t.id IS NOT NULL AND ua.action_type = :like_type THEN 1 ELSE 0 END) likes_given,
@@ -131,15 +140,12 @@ class DirectoryItem < ActiveRecord::Base
di.post_count <> x.post_count )
",
- query_args
- )
+ query_args,
+ )
- @@plugin_queries.each do |plugin_query|
- DB.exec(plugin_query, query_args)
- end
+ @@plugin_queries.each { |plugin_query| DB.exec(plugin_query, query_args) }
- if period_type == :all
- DB.exec <<~SQL
+ DB.exec <<~SQL if period_type == :all
UPDATE user_stats s
SET likes_given = d.likes_given,
likes_received = d.likes_received,
@@ -155,7 +161,6 @@ class DirectoryItem < ActiveRecord::Base
s.post_count <> d.post_count
)
SQL
- end
end
end
end
diff --git a/app/models/discourse_connect.rb b/app/models/discourse_connect.rb
index ede77372f82..850784173f4 100644
--- a/app/models/discourse_connect.rb
+++ b/app/models/discourse_connect.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
class DiscourseConnect < DiscourseConnectBase
-
- class BlankExternalId < StandardError; end
- class BannedExternalId < StandardError; end
+ class BlankExternalId < StandardError
+ end
+ class BannedExternalId < StandardError
+ end
def self.sso_url
SiteSetting.discourse_connect_url
@@ -34,7 +35,11 @@ class DiscourseConnect < DiscourseConnectBase
if SiteSetting.discourse_connect_csrf_protection
@secure_session.set(nonce_key, return_path, expires: DiscourseConnectBase.nonce_expiry_time)
else
- Discourse.cache.write(nonce_key, return_path, expires_in: DiscourseConnectBase.nonce_expiry_time)
+ Discourse.cache.write(
+ nonce_key,
+ return_path,
+ expires_in: DiscourseConnectBase.nonce_expiry_time,
+ )
end
end
end
@@ -73,7 +78,11 @@ class DiscourseConnect < DiscourseConnectBase
Discourse.cache.delete nonce_key
end
- Discourse.cache.write(used_nonce_key, return_path, expires_in: DiscourseConnectBase.used_nonce_expiry_time)
+ Discourse.cache.write(
+ used_nonce_key,
+ return_path,
+ expires_in: DiscourseConnectBase.used_nonce_expiry_time,
+ )
end
end
@@ -85,20 +94,15 @@ class DiscourseConnect < DiscourseConnectBase
"USED_SSO_NONCE_#{nonce}"
end
- BANNED_EXTERNAL_IDS = %w{none nil blank null}
+ BANNED_EXTERNAL_IDS = %w[none nil blank null]
def lookup_or_create_user(ip_address = nil)
-
# we don't want to ban 0 from being an external id
external_id = self.external_id.to_s
- if external_id.blank?
- raise BlankExternalId
- end
+ raise BlankExternalId if external_id.blank?
- if BANNED_EXTERNAL_IDS.include?(external_id.downcase)
- raise BannedExternalId, external_id
- end
+ raise BannedExternalId, external_id if BANNED_EXTERNAL_IDS.include?(external_id.downcase)
# we protect here to ensure there is no situation where the same external id
# concurrently attempts to create or update sso records
@@ -130,13 +134,11 @@ class DiscourseConnect < DiscourseConnectBase
if sso_record && (user = sso_record.user) && !user.active && !require_activation
user.active = true
user.save!
- user.enqueue_welcome_message('welcome_user') unless suppress_welcome_message
+ user.enqueue_welcome_message("welcome_user") unless suppress_welcome_message
user.set_automatic_groups
end
- custom_fields.each do |k, v|
- user.custom_fields[k] = v
- end
+ custom_fields.each { |k, v| user.custom_fields[k] = v }
user.ip_address = ip_address
@@ -149,9 +151,7 @@ class DiscourseConnect < DiscourseConnectBase
user.user_avatar.save! if user.user_avatar
user.save!
- if @email_changed && user.active
- user.set_automatic_groups
- end
+ user.set_automatic_groups if @email_changed && user.active
# The user might require approval
user.create_reviewable
@@ -177,9 +177,7 @@ class DiscourseConnect < DiscourseConnectBase
sso_record.save!
- if sso_record.user
- apply_group_rules(sso_record.user)
- end
+ apply_group_rules(sso_record.user) if sso_record.user
sso_record && sso_record.user
end
@@ -188,7 +186,7 @@ class DiscourseConnect < DiscourseConnectBase
names = (groups || "").split(",").map(&:downcase)
current_groups = user.groups.where(automatic: false)
- desired_groups = Group.where('LOWER(NAME) in (?) AND NOT automatic', names)
+ desired_groups = Group.where("LOWER(NAME) in (?) AND NOT automatic", names)
to_be_added = desired_groups
if current_groups.present?
@@ -218,7 +216,7 @@ class DiscourseConnect < DiscourseConnectBase
if add_groups
split = add_groups.split(",").map(&:downcase)
if split.length > 0
- to_be_added = Group.where('LOWER(name) in (?) AND NOT automatic', split)
+ to_be_added = Group.where("LOWER(name) in (?) AND NOT automatic", split)
if already_member = GroupUser.where(user_id: user.id).pluck(:group_id).presence
to_be_added = to_be_added.where("id NOT IN (?)", already_member)
end
@@ -229,10 +227,11 @@ class DiscourseConnect < DiscourseConnectBase
if remove_groups
split = remove_groups.split(",").map(&:downcase)
if split.length > 0
- to_be_removed = Group
- .joins(:group_users)
- .where(automatic: false, group_users: { user_id: user.id })
- .where("LOWER(name) IN (?)", split)
+ to_be_removed =
+ Group
+ .joins(:group_users)
+ .where(automatic: false, group_users: { user_id: user.id })
+ .where("LOWER(name) IN (?)", split)
end
end
@@ -255,7 +254,7 @@ class DiscourseConnect < DiscourseConnectBase
primary_email: UserEmail.new(email: email, primary: true),
name: resolve_name,
username: resolve_username,
- ip_address: ip_address
+ ip_address: ip_address,
}
if SiteSetting.allow_user_locale && locale && LocaleSiteSetting.valid_value?(locale)
@@ -271,7 +270,9 @@ class DiscourseConnect < DiscourseConnectBase
user.save!
if SiteSetting.verbose_discourse_connect_logging
- Rails.logger.warn("Verbose SSO log: New User (user_id: #{user.id}) Params: #{user_params} User Params: #{user.attributes} User Errors: #{user.errors.full_messages} Email: #{user.primary_email.attributes} Email Error: #{user.primary_email.errors.full_messages}")
+ Rails.logger.warn(
+ "Verbose SSO log: New User (user_id: #{user.id}) Params: #{user_params} User Params: #{user.attributes} User Errors: #{user.errors.full_messages} Email: #{user.primary_email.attributes} Email Error: #{user.primary_email.errors.full_messages}",
+ )
end
end
@@ -281,26 +282,29 @@ class DiscourseConnect < DiscourseConnectBase
sso_record.external_id = external_id
else
if avatar_url.present?
- Jobs.enqueue(:download_avatar_from_url,
+ Jobs.enqueue(
+ :download_avatar_from_url,
url: avatar_url,
user_id: user.id,
- override_gravatar: SiteSetting.discourse_connect_overrides_avatar
+ override_gravatar: SiteSetting.discourse_connect_overrides_avatar,
)
end
if profile_background_url.present?
- Jobs.enqueue(:download_profile_background_from_url,
+ Jobs.enqueue(
+ :download_profile_background_from_url,
url: profile_background_url,
user_id: user.id,
- is_card_background: false
+ is_card_background: false,
)
end
if card_background_url.present?
- Jobs.enqueue(:download_profile_background_from_url,
+ Jobs.enqueue(
+ :download_profile_background_from_url,
url: card_background_url,
user_id: user.id,
- is_card_background: true
+ is_card_background: true,
)
end
@@ -312,7 +316,7 @@ class DiscourseConnect < DiscourseConnectBase
external_name: name,
external_avatar_url: avatar_url,
external_profile_background_url: profile_background_url,
- external_card_background_url: card_background_url
+ external_card_background_url: card_background_url,
)
end
end
@@ -338,44 +342,58 @@ class DiscourseConnect < DiscourseConnectBase
user.name = name || User.suggest_name(username.blank? ? email : username)
end
- if locale_force_update && SiteSetting.allow_user_locale && locale && LocaleSiteSetting.valid_value?(locale)
+ if locale_force_update && SiteSetting.allow_user_locale && locale &&
+ LocaleSiteSetting.valid_value?(locale)
user.locale = locale
end
avatar_missing = user.uploaded_avatar_id.nil? || !Upload.exists?(user.uploaded_avatar_id)
- if (avatar_missing || avatar_force_update || SiteSetting.discourse_connect_overrides_avatar) && avatar_url.present?
+ if (avatar_missing || avatar_force_update || SiteSetting.discourse_connect_overrides_avatar) &&
+ avatar_url.present?
avatar_changed = sso_record.external_avatar_url != avatar_url
if avatar_force_update || avatar_changed || avatar_missing
- Jobs.enqueue(:download_avatar_from_url, url: avatar_url, user_id: user.id, override_gravatar: SiteSetting.discourse_connect_overrides_avatar)
+ Jobs.enqueue(
+ :download_avatar_from_url,
+ url: avatar_url,
+ user_id: user.id,
+ override_gravatar: SiteSetting.discourse_connect_overrides_avatar,
+ )
end
end
if profile_background_url.present?
- profile_background_missing = user.user_profile.profile_background_upload.blank? || Upload.get_from_url(user.user_profile.profile_background_upload.url).blank?
+ profile_background_missing =
+ user.user_profile.profile_background_upload.blank? ||
+ Upload.get_from_url(user.user_profile.profile_background_upload.url).blank?
if profile_background_missing || SiteSetting.discourse_connect_overrides_profile_background
- profile_background_changed = sso_record.external_profile_background_url != profile_background_url
+ profile_background_changed =
+ sso_record.external_profile_background_url != profile_background_url
if profile_background_changed || profile_background_missing
- Jobs.enqueue(:download_profile_background_from_url,
- url: profile_background_url,
- user_id: user.id,
- is_card_background: false
+ Jobs.enqueue(
+ :download_profile_background_from_url,
+ url: profile_background_url,
+ user_id: user.id,
+ is_card_background: false,
)
end
end
end
if card_background_url.present?
- card_background_missing = user.user_profile.card_background_upload.blank? || Upload.get_from_url(user.user_profile.card_background_upload.url).blank?
+ card_background_missing =
+ user.user_profile.card_background_upload.blank? ||
+ Upload.get_from_url(user.user_profile.card_background_upload.url).blank?
if card_background_missing || SiteSetting.discourse_connect_overrides_card_background
card_background_changed = sso_record.external_card_background_url != card_background_url
if card_background_changed || card_background_missing
- Jobs.enqueue(:download_profile_background_from_url,
- url: card_background_url,
- user_id: user.id,
- is_card_background: true
+ Jobs.enqueue(
+ :download_profile_background_from_url,
+ url: card_background_url,
+ user_id: user.id,
+ is_card_background: true,
)
end
end
diff --git a/app/models/do_not_disturb_timing.rb b/app/models/do_not_disturb_timing.rb
index 62d7d65cbda..56bbb6524e6 100644
--- a/app/models/do_not_disturb_timing.rb
+++ b/app/models/do_not_disturb_timing.rb
@@ -6,9 +6,7 @@ class DoNotDisturbTiming < ActiveRecord::Base
validate :ends_at_greater_than_starts_at
def ends_at_greater_than_starts_at
- if starts_at > ends_at
- errors.add(:ends_at, :invalid)
- end
+ errors.add(:ends_at, :invalid) if starts_at > ends_at
end
end
diff --git a/app/models/draft.rb b/app/models/draft.rb
index ced0d4df5b4..a9dff7f2774 100644
--- a/app/models/draft.rb
+++ b/app/models/draft.rb
@@ -1,21 +1,23 @@
# frozen_string_literal: true
class Draft < ActiveRecord::Base
- NEW_TOPIC ||= 'new_topic'
- NEW_PRIVATE_MESSAGE ||= 'new_private_message'
- EXISTING_TOPIC ||= 'topic_'
+ NEW_TOPIC ||= "new_topic"
+ NEW_PRIVATE_MESSAGE ||= "new_private_message"
+ EXISTING_TOPIC ||= "topic_"
belongs_to :user
- after_commit :update_draft_count, on: [:create, :destroy]
+ after_commit :update_draft_count, on: %i[create destroy]
- class OutOfSequence < StandardError; end
+ class OutOfSequence < StandardError
+ end
def self.set(user, key, sequence, data, owner = nil, force_save: false)
return 0 if !User.human_user_id?(user.id)
force_save = force_save.to_s == "true"
- if SiteSetting.backup_drafts_to_pm_length > 0 && SiteSetting.backup_drafts_to_pm_length < data.length
+ if SiteSetting.backup_drafts_to_pm_length > 0 &&
+ SiteSetting.backup_drafts_to_pm_length < data.length
backup_draft(user, key, sequence, data)
end
@@ -44,21 +46,16 @@ class Draft < ActiveRecord::Base
current_sequence ||= 0
if draft_id
- if !force_save && (current_sequence != sequence)
- raise Draft::OutOfSequence
- end
+ raise Draft::OutOfSequence if !force_save && (current_sequence != sequence)
sequence = current_sequence if force_save
sequence += 1
# we need to keep upping our sequence on every save
# if we do not do that there are bad race conditions
- DraftSequence.upsert({
- sequence: sequence,
- draft_key: key,
- user_id: user.id,
- },
- unique_by: [:user_id, :draft_key]
+ DraftSequence.upsert(
+ { sequence: sequence, draft_key: key, user_id: user.id },
+ unique_by: %i[user_id draft_key],
)
DB.exec(<<~SQL, id: draft_id, sequence: sequence, data: data, owner: owner || current_owner)
@@ -70,17 +67,10 @@ class Draft < ActiveRecord::Base
, updated_at = CURRENT_TIMESTAMP
WHERE id = :id
SQL
-
elsif sequence != current_sequence
raise Draft::OutOfSequence
else
- opts = {
- user_id: user.id,
- draft_key: key,
- data: data,
- sequence: sequence,
- owner: owner
- }
+ opts = { user_id: user.id, draft_key: key, data: data, sequence: sequence, owner: owner }
draft_id = DB.query_single(<<~SQL, opts).first
INSERT INTO drafts (user_id, draft_key, data, sequence, owner, created_at, updated_at)
@@ -101,8 +91,8 @@ class Draft < ActiveRecord::Base
UploadReference.ensure_exist!(
upload_ids: Upload.extract_upload_ids(data),
- target_type: 'Draft',
- target_id: draft_id
+ target_type: "Draft",
+ target_id: draft_id,
)
sequence
@@ -111,11 +101,7 @@ class Draft < ActiveRecord::Base
def self.get(user, key, sequence)
return if !user || !user.id || !User.human_user_id?(user.id)
- opts = {
- user_id: user.id,
- draft_key: key,
- sequence: sequence
- }
+ opts = { user_id: user.id, draft_key: key, sequence: sequence }
current_sequence, data, draft_sequence = DB.query_single(<<~SQL, opts)
WITH draft AS (
@@ -136,9 +122,7 @@ class Draft < ActiveRecord::Base
current_sequence ||= 0
- if sequence != current_sequence
- raise Draft::OutOfSequence
- end
+ raise Draft::OutOfSequence if sequence != current_sequence
data if current_sequence == draft_sequence
end
@@ -155,9 +139,7 @@ class Draft < ActiveRecord::Base
current_sequence = DraftSequence.current(user, key)
# bad caller is a reason to complain
- if sequence != current_sequence
- raise Draft::OutOfSequence
- end
+ raise Draft::OutOfSequence if sequence != current_sequence
# corrupt data is not a reason not to leave data
Draft.where(user_id: user.id, draft_key: key).destroy_all
@@ -176,9 +158,7 @@ class Draft < ActiveRecord::Base
end
def topic_id
- if draft_key.starts_with?(EXISTING_TOPIC)
- draft_key.gsub(EXISTING_TOPIC, "").to_i
- end
+ draft_key.gsub(EXISTING_TOPIC, "").to_i if draft_key.starts_with?(EXISTING_TOPIC)
end
def topic_preloaded?
@@ -186,7 +166,9 @@ class Draft < ActiveRecord::Base
end
def topic
- topic_preloaded? ? @topic : @topic = Draft.allowed_draft_topics_for_user(user).find_by(id: topic_id)
+ topic_preloaded? ?
+ @topic :
+ @topic = Draft.allowed_draft_topics_for_user(user).find_by(id: topic_id)
end
def preload_topic(topic)
@@ -240,10 +222,7 @@ class Draft < ActiveRecord::Base
offset = (opts[:offset] || 0).to_i
limit = (opts[:limit] || 30).to_i
- stream = Draft.where(user_id: user_id)
- .order(updated_at: :desc)
- .offset(offset)
- .limit(limit)
+ stream = Draft.where(user_id: user_id).order(updated_at: :desc).offset(offset).limit(limit)
# Preload posts and topics to avoid N+1 queries
Draft.preload_data(stream, opts[:user])
@@ -276,13 +255,9 @@ class Draft < ActiveRecord::Base
post_id = BackupDraftPost.where(user_id: user.id, key: key).pluck_first(:post_id)
post = Post.where(id: post_id).first if post_id
- if post_id && !post
- BackupDraftPost.where(user_id: user.id, key: key).delete_all
- end
+ BackupDraftPost.where(user_id: user.id, key: key).delete_all if post_id && !post
- indented_reply = reply.split("\n").map! do |l|
- " #{l}"
- end
+ indented_reply = reply.split("\n").map! { |l| " #{l}" }
draft_body = <<~MD
#{indented_reply.join("\n")}
@@ -297,13 +272,14 @@ class Draft < ActiveRecord::Base
if !post
topic = ensure_draft_topic!(user)
Post.transaction do
- post = PostCreator.new(
- user,
- raw: draft_body,
- skip_jobs: true,
- skip_validations: true,
- topic_id: topic.id,
- ).create
+ post =
+ PostCreator.new(
+ user,
+ raw: draft_body,
+ skip_jobs: true,
+ skip_validations: true,
+ topic_id: topic.id,
+ ).create
BackupDraftPost.create!(user_id: user.id, key: key, post_id: post.id)
end
elsif post.last_version_at > 5.minutes.ago
@@ -311,18 +287,19 @@ class Draft < ActiveRecord::Base
post.update_columns(
raw: draft_body,
cooked: PrettyText.cook(draft_body),
- updated_at: Time.zone.now
+ updated_at: Time.zone.now,
)
else
revisor = PostRevisor.new(post, post.topic)
- revisor.revise!(user, { raw: draft_body },
+ revisor.revise!(
+ user,
+ { raw: draft_body },
bypass_bump: true,
skip_validations: true,
skip_staff_log: true,
- bypass_rate_limiter: true
+ bypass_rate_limiter: true,
)
end
-
rescue => e
Discourse.warn_exception(e, message: "Failed to backup draft")
end
@@ -331,28 +308,26 @@ class Draft < ActiveRecord::Base
topic_id = BackupDraftTopic.where(user_id: user.id).pluck_first(:topic_id)
topic = Topic.find_by(id: topic_id) if topic_id
- if topic_id && !topic
- BackupDraftTopic.where(user_id: user.id).delete_all
- end
+ BackupDraftTopic.where(user_id: user.id).delete_all if topic_id && !topic
if !topic
Topic.transaction do
- creator = PostCreator.new(
- user,
- title: I18n.t("draft_backup.pm_title"),
- archetype: Archetype.private_message,
- raw: I18n.t("draft_backup.pm_body"),
- skip_jobs: true,
- skip_validations: true,
- target_usernames: user.username
- )
+ creator =
+ PostCreator.new(
+ user,
+ title: I18n.t("draft_backup.pm_title"),
+ archetype: Archetype.private_message,
+ raw: I18n.t("draft_backup.pm_body"),
+ skip_jobs: true,
+ skip_validations: true,
+ target_usernames: user.username,
+ )
topic = creator.create.topic
BackupDraftTopic.create!(topic_id: topic.id, user_id: user.id)
end
end
topic
-
end
def update_draft_count
diff --git a/app/models/draft_sequence.rb b/app/models/draft_sequence.rb
index cfe1a27befb..3570df5aa35 100644
--- a/app/models/draft_sequence.rb
+++ b/app/models/draft_sequence.rb
@@ -9,8 +9,7 @@ class DraftSequence < ActiveRecord::Base
return 0 if !User.human_user_id?(user_id)
- sequence =
- DB.query_single(<<~SQL, user_id: user_id, draft_key: key).first
+ sequence = DB.query_single(<<~SQL, user_id: user_id, draft_key: key).first
INSERT INTO draft_sequences (user_id, draft_key, sequence)
VALUES (:user_id, :draft_key, 1)
ON CONFLICT (user_id, draft_key) DO
@@ -21,7 +20,12 @@ class DraftSequence < ActiveRecord::Base
RETURNING sequence
SQL
- DB.exec("DELETE FROM drafts WHERE user_id = :user_id AND draft_key = :draft_key AND sequence < :sequence", draft_key: key, user_id: user_id, sequence: sequence)
+ DB.exec(
+ "DELETE FROM drafts WHERE user_id = :user_id AND draft_key = :draft_key AND sequence < :sequence",
+ draft_key: key,
+ user_id: user_id,
+ sequence: sequence,
+ )
UserStat.update_draft_count(user_id)
@@ -37,7 +41,12 @@ class DraftSequence < ActiveRecord::Base
return 0 if !User.human_user_id?(user_id)
# perf critical path
- r, _ = DB.query_single('select sequence from draft_sequences where user_id = ? and draft_key = ?', user_id, key)
+ r, _ =
+ DB.query_single(
+ "select sequence from draft_sequences where user_id = ? and draft_key = ?",
+ user_id,
+ key,
+ )
r.to_i
end
end
diff --git a/app/models/email_change_request.rb b/app/models/email_change_request.rb
index 44ac085c2da..e0e175e0336 100644
--- a/app/models/email_change_request.rb
+++ b/app/models/email_change_request.rb
@@ -2,8 +2,8 @@
class EmailChangeRequest < ActiveRecord::Base
belongs_to :user
- belongs_to :old_email_token, class_name: 'EmailToken', dependent: :destroy
- belongs_to :new_email_token, class_name: 'EmailToken', dependent: :destroy
+ belongs_to :old_email_token, class_name: "EmailToken", dependent: :destroy
+ belongs_to :new_email_token, class_name: "EmailToken", dependent: :destroy
belongs_to :requested_by, class_name: "User", foreign_key: :requested_by_user_id
validates :new_email, presence: true, format: { with: EmailAddressValidator.email_regex }
@@ -14,7 +14,9 @@ class EmailChangeRequest < ActiveRecord::Base
def self.find_by_new_token(token)
EmailChangeRequest
- .joins("INNER JOIN email_tokens ON email_tokens.id = email_change_requests.new_email_token_id")
+ .joins(
+ "INNER JOIN email_tokens ON email_tokens.id = email_change_requests.new_email_token_id",
+ )
.where("email_tokens.token_hash = ?", EmailToken.hash_token(token))
.last
end
diff --git a/app/models/email_level_site_setting.rb b/app/models/email_level_site_setting.rb
index 9f805dd2536..9d5131e50cf 100644
--- a/app/models/email_level_site_setting.rb
+++ b/app/models/email_level_site_setting.rb
@@ -1,22 +1,19 @@
# frozen_string_literal: true
class EmailLevelSiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
- val.to_i.to_s == val.to_s &&
- values.any? { |v| v[:value] == val.to_i }
+ val.to_i.to_s == val.to_s && values.any? { |v| v[:value] == val.to_i }
end
def self.values
@values ||= [
- { name: 'user.email_level.always', value: 0 },
- { name: 'user.email_level.only_when_away', value: 1 },
- { name: 'user.email_level.never', value: 2 },
+ { name: "user.email_level.always", value: 0 },
+ { name: "user.email_level.only_when_away", value: 1 },
+ { name: "user.email_level.never", value: 2 },
]
end
def self.translate_names?
true
end
-
end
diff --git a/app/models/email_log.rb b/app/models/email_log.rb
index b5ab6d6402d..c3dc39e0363 100644
--- a/app/models/email_log.rb
+++ b/app/models/email_log.rb
@@ -1,32 +1,32 @@
# frozen_string_literal: true
class EmailLog < ActiveRecord::Base
- CRITICAL_EMAIL_TYPES ||= Set.new %w{
- account_created
- admin_login
- confirm_new_email
- confirm_old_email
- confirm_old_email_add
- forgot_password
- notify_old_email
- notify_old_email_add
- signup
- signup_after_approval
- }
+ CRITICAL_EMAIL_TYPES ||=
+ Set.new %w[
+ account_created
+ admin_login
+ confirm_new_email
+ confirm_old_email
+ confirm_old_email_add
+ forgot_password
+ notify_old_email
+ notify_old_email_add
+ signup
+ signup_after_approval
+ ]
# cf. https://www.iana.org/assignments/smtp-enhanced-status-codes/smtp-enhanced-status-codes.xhtml
SMTP_ERROR_CODE_REGEXP = Regexp.new(/\d\.\d\.\d+|\d{3}/).freeze
belongs_to :user
belongs_to :post
- belongs_to :smtp_group, class_name: 'Group'
+ belongs_to :smtp_group, class_name: "Group"
validates :email_type, :to_address, presence: true
scope :bounced, -> { where(bounced: true) }
- scope :addressed_to_user, ->(user) do
- where(<<~SQL, user_id: user.id)
+ scope :addressed_to_user, ->(user) { where(<<~SQL, user_id: user.id) }
EXISTS(
SELECT 1
FROM user_emails
@@ -35,7 +35,6 @@ class EmailLog < ActiveRecord::Base
email_logs.cc_addresses ILIKE '%' || user_emails.email || '%')
)
SQL
- end
before_save do
if self.bounce_error_code.present?
@@ -66,11 +65,11 @@ class EmailLog < ActiveRecord::Base
end
def self.reached_max_emails?(user, email_type = nil)
- return false if SiteSetting.max_emails_per_day_per_user == 0 || CRITICAL_EMAIL_TYPES.include?(email_type)
+ if SiteSetting.max_emails_per_day_per_user == 0 || CRITICAL_EMAIL_TYPES.include?(email_type)
+ return false
+ end
- count = where('created_at > ?', 1.day.ago)
- .where(user_id: user.id)
- .count
+ count = where("created_at > ?", 1.day.ago).where(user_id: user.id).count
count >= SiteSetting.max_emails_per_day_per_user
end
@@ -87,15 +86,11 @@ class EmailLog < ActiveRecord::Base
end
def self.last_sent_email_address
- self.where(email_type: "signup")
- .order(created_at: :desc)
- .limit(1)
- .pluck(:to_address)
- .first
+ self.where(email_type: "signup").order(created_at: :desc).limit(1).pluck(:to_address).first
end
def bounce_key
- super&.delete('-')
+ super&.delete("-")
end
def cc_users
diff --git a/app/models/email_style.rb b/app/models/email_style.rb
index 9aeb483f01b..88b4b7692ad 100644
--- a/app/models/email_style.rb
+++ b/app/models/email_style.rb
@@ -6,7 +6,7 @@ class EmailStyle
attr_accessor :html, :css, :default_html, :default_css
def id
- 'email-style'
+ "email-style"
end
def html
@@ -30,12 +30,11 @@ class EmailStyle
end
def self.default_template
- @_default_template ||= File.read(
- File.join(Rails.root, 'app', 'views', 'email', 'default_template.html')
- )
+ @_default_template ||=
+ File.read(File.join(Rails.root, "app", "views", "email", "default_template.html"))
end
def self.default_css
- ''
+ ""
end
end
diff --git a/app/models/email_token.rb b/app/models/email_token.rb
index 8cd7dbdd03a..7a04e7c2296 100644
--- a/app/models/email_token.rb
+++ b/app/models/email_token.rb
@@ -1,14 +1,21 @@
# frozen_string_literal: true
class EmailToken < ActiveRecord::Base
- class TokenAccessError < StandardError; end
+ class TokenAccessError < StandardError
+ end
belongs_to :user
validates :user_id, :email, :token_hash, presence: true
scope :unconfirmed, -> { where(confirmed: false) }
- scope :active, -> { where(expired: false).where('created_at >= ?', SiteSetting.email_token_valid_hours.hours.ago) }
+ scope :active,
+ -> {
+ where(expired: false).where(
+ "created_at >= ?",
+ SiteSetting.email_token_valid_hours.hours.ago,
+ )
+ }
after_initialize do
if self.token_hash.blank?
@@ -25,9 +32,7 @@ class EmailToken < ActiveRecord::Base
.update_all(expired: true)
end
- before_validation do
- self.email = self.email.downcase if self.email
- end
+ before_validation { self.email = self.email.downcase if self.email }
before_save do
if self.scope.blank?
@@ -36,15 +41,10 @@ class EmailToken < ActiveRecord::Base
end
# TODO(2022-01-01): Remove
- self.ignored_columns = %w{token}
+ self.ignored_columns = %w[token]
def self.scopes
- @scopes ||= Enum.new(
- signup: 1,
- password_reset: 2,
- email_login: 3,
- email_update: 4,
- )
+ @scopes ||= Enum.new(signup: 1, password_reset: 2, email_login: 3, email_update: 4)
end
def token
@@ -64,7 +64,7 @@ class EmailToken < ActiveRecord::Base
user.send_welcome_message = !user.active?
user.email = email_token.email
user.active = true
- user.custom_fields.delete('activation_reminder')
+ user.custom_fields.delete("activation_reminder")
user.save!
user.create_reviewable if !skip_reviewable
user.set_automatic_groups
@@ -80,9 +80,7 @@ class EmailToken < ActiveRecord::Base
def self.confirmable(token, scope: nil)
return nil if token.blank?
- relation = unconfirmed.active
- .includes(:user)
- .where(token_hash: hash_token(token))
+ relation = unconfirmed.active.includes(:user).where(token_hash: hash_token(token))
# TODO(2022-01-01): All email tokens should have scopes by now
if !scope
@@ -98,7 +96,7 @@ class EmailToken < ActiveRecord::Base
type: "signup",
user_id: email_token.user_id,
email_token: email_token.token,
- to_address: to_address
+ to_address: to_address,
)
end
diff --git a/app/models/embeddable_host.rb b/app/models/embeddable_host.rb
index f638ff235ab..b9c63aff5b3 100644
--- a/app/models/embeddable_host.rb
+++ b/app/models/embeddable_host.rb
@@ -6,8 +6,8 @@ class EmbeddableHost < ActiveRecord::Base
after_destroy :reset_embedding_settings
before_validation do
- self.host.sub!(/^https?:\/\//, '')
- self.host.sub!(/\/.*$/, '')
+ self.host.sub!(%r{^https?://}, "")
+ self.host.sub!(%r{/.*$}, "")
end
# TODO(2021-07-23): Remove
@@ -15,10 +15,11 @@ class EmbeddableHost < ActiveRecord::Base
def self.record_for_url(uri)
if uri.is_a?(String)
- uri = begin
- URI(UrlHelper.normalized_encode(uri))
- rescue URI::Error, Addressable::URI::InvalidURIError
- end
+ uri =
+ begin
+ URI(UrlHelper.normalized_encode(uri))
+ rescue URI::Error, Addressable::URI::InvalidURIError
+ end
end
return false unless uri.present?
@@ -26,9 +27,7 @@ class EmbeddableHost < ActiveRecord::Base
host = uri.host
return false unless host.present?
- if uri.port.present? && uri.port != 80 && uri.port != 443
- host << ":#{uri.port}"
- end
+ host << ":#{uri.port}" if uri.port.present? && uri.port != 80 && uri.port != 443
path = uri.path
path << "?" << uri.query if uri.query.present?
@@ -49,10 +48,11 @@ class EmbeddableHost < ActiveRecord::Base
# Work around IFRAME reload on WebKit where the referer will be set to the Forum URL
return true if url&.starts_with?(Discourse.base_url) && EmbeddableHost.exists?
- uri = begin
- URI(UrlHelper.normalized_encode(url))
- rescue URI::Error
- end
+ uri =
+ begin
+ URI(UrlHelper.normalized_encode(url))
+ rescue URI::Error
+ end
uri.present? && record_for_url(uri).present?
end
@@ -67,9 +67,9 @@ class EmbeddableHost < ActiveRecord::Base
def host_must_be_valid
if host !~ /\A[a-z0-9]+([\-\.]+{1}[a-z0-9]+)*\.[a-z]{2,24}(:[0-9]{1,5})?(\/.*)?\Z/i &&
- host !~ /\A(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(:[0-9]{1,5})?(\/.*)?\Z/ &&
- host !~ /\A([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.)?localhost(\:[0-9]{1,5})?(\/.*)?\Z/i
- errors.add(:host, I18n.t('errors.messages.invalid'))
+ host !~ /\A(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(:[0-9]{1,5})?(\/.*)?\Z/ &&
+ host !~ /\A([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.)?localhost(\:[0-9]{1,5})?(\/.*)?\Z/i
+ errors.add(:host, I18n.t("errors.messages.invalid"))
end
end
end
diff --git a/app/models/embedding.rb b/app/models/embedding.rb
index 909ba1c2727..cf6585130e8 100644
--- a/app/models/embedding.rb
+++ b/app/models/embedding.rb
@@ -1,19 +1,21 @@
# frozen_string_literal: true
-require 'has_errors'
+require "has_errors"
class Embedding < OpenStruct
include HasErrors
def self.settings
- %i(embed_by_username
- embed_post_limit
- embed_title_scrubber
- embed_truncate
- embed_unlisted
- allowed_embed_selectors
- blocked_embed_selectors
- allowed_embed_classnames)
+ %i[
+ embed_by_username
+ embed_post_limit
+ embed_title_scrubber
+ embed_truncate
+ embed_unlisted
+ allowed_embed_selectors
+ blocked_embed_selectors
+ allowed_embed_classnames
+ ]
end
def base_url
@@ -21,9 +23,7 @@ class Embedding < OpenStruct
end
def save
- Embedding.settings.each do |s|
- SiteSetting.set(s, public_send(s))
- end
+ Embedding.settings.each { |s| SiteSetting.set(s, public_send(s)) }
true
rescue Discourse::InvalidParameters => p
errors.add :base, p.to_s
@@ -35,7 +35,7 @@ class Embedding < OpenStruct
end
def self.find
- embedding_args = { id: 'default' }
+ embedding_args = { id: "default" }
Embedding.settings.each { |s| embedding_args[s] = SiteSetting.get(s) }
Embedding.new(embedding_args)
end
diff --git a/app/models/emoji.rb b/app/models/emoji.rb
index 750be812834..94b85eb154d 100644
--- a/app/models/emoji.rb
+++ b/app/models/emoji.rb
@@ -4,7 +4,7 @@ class Emoji
# update this to clear the cache
EMOJI_VERSION = "12"
- FITZPATRICK_SCALE ||= [ "1f3fb", "1f3fc", "1f3fd", "1f3fe", "1f3ff" ]
+ FITZPATRICK_SCALE ||= %w[1f3fb 1f3fc 1f3fd 1f3fe 1f3ff]
DEFAULT_GROUP ||= "default"
@@ -29,11 +29,11 @@ class Emoji
end
def self.aliases
- db['aliases']
+ db["aliases"]
end
def self.search_aliases
- db['searchAliases']
+ db["searchAliases"]
end
def self.translations
@@ -45,11 +45,11 @@ class Emoji
end
def self.tonable_emojis
- db['tonableEmojis']
+ db["tonableEmojis"]
end
def self.custom?(name)
- name = name.delete_prefix(':').delete_suffix(':')
+ name = name.delete_prefix(":").delete_suffix(":")
Emoji.custom.detect { |e| e.name == name }.present?
end
@@ -58,29 +58,28 @@ class Emoji
end
def self.[](name)
- name = name.delete_prefix(':').delete_suffix(':')
+ name = name.delete_prefix(":").delete_suffix(":")
is_toned = name.match?(/.+:t[1-6]/)
normalized_name = name.gsub(/(.+):t[1-6]/, '\1')
found_emoji = nil
[[global_emoji_cache, :standard], [site_emoji_cache, :custom]].each do |cache, list_key|
- cache_postfix, found_emoji = cache.defer_get_set(normalized_name) do
- emoji = Emoji.public_send(list_key).detect do |e|
- e.name == normalized_name &&
- (!is_toned || (is_toned && e.tonable))
+ cache_postfix, found_emoji =
+ cache.defer_get_set(normalized_name) do
+ emoji =
+ Emoji
+ .public_send(list_key)
+ .detect { |e| e.name == normalized_name && (!is_toned || (is_toned && e.tonable)) }
+ [self.cache_postfix, emoji]
end
- [self.cache_postfix, emoji]
- end
if found_emoji && (cache_postfix != self.cache_postfix)
cache.delete(normalized_name)
redo
end
- if found_emoji
- break
- end
+ break if found_emoji
end
found_emoji
@@ -89,7 +88,7 @@ class Emoji
def self.create_from_db_item(emoji)
name = emoji["name"]
return unless group = groups[name]
- filename = emoji['filename'] || name
+ filename = emoji["filename"] || name
Emoji.new.tap do |e|
e.name = name
@@ -101,7 +100,7 @@ class Emoji
end
def self.url_for(name)
- name = name.delete_prefix(':').delete_suffix(':').gsub(/(.+):t([1-6])/, '\1/\2')
+ name = name.delete_prefix(":").delete_suffix(":").gsub(/(.+):t([1-6])/, '\1/\2')
if SiteSetting.external_emoji_url.blank?
"#{Discourse.base_path}/images/emoji/#{SiteSetting.emoji_set}/#{name}.png?v=#{EMOJI_VERSION}"
else
@@ -118,7 +117,7 @@ class Emoji
end
def self.clear_cache
- %w{custom standard translations all}.each do |key|
+ %w[custom standard translations all].each do |key|
Discourse.cache.delete(cache_key("#{key}_emojis"))
end
global_emoji_cache.clear
@@ -130,17 +129,16 @@ class Emoji
end
def self.groups
- @groups ||= begin
- groups = {}
+ @groups ||=
+ begin
+ groups = {}
- File.open(groups_file, "r:UTF-8") { |f| JSON.parse(f.read) }.each do |group|
- group["icons"].each do |icon|
- groups[icon["name"]] = group["name"]
- end
+ File
+ .open(groups_file, "r:UTF-8") { |f| JSON.parse(f.read) }
+ .each { |group| group["icons"].each { |icon| groups[icon["name"]] = group["name"] } }
+
+ groups
end
-
- groups
- end
end
def self.db_file
@@ -152,27 +150,30 @@ class Emoji
end
def self.load_standard
- db['emojis'].map { |e| Emoji.create_from_db_item(e) }.compact
+ db["emojis"].map { |e| Emoji.create_from_db_item(e) }.compact
end
def self.load_custom
result = []
if !GlobalSetting.skip_db?
- CustomEmoji.includes(:upload).order(:name).each do |emoji|
- result << Emoji.new.tap do |e|
- e.name = emoji.name
- e.url = emoji.upload&.url
- e.group = emoji.group || DEFAULT_GROUP
+ CustomEmoji
+ .includes(:upload)
+ .order(:name)
+ .each do |emoji|
+ result << Emoji.new.tap do |e|
+ e.name = emoji.name
+ e.url = emoji.upload&.url
+ e.group = emoji.group || DEFAULT_GROUP
+ end
end
- end
end
Plugin::CustomEmoji.emojis.each do |group, emojis|
emojis.each do |name, url|
result << Emoji.new.tap do |e|
e.name = name
- url = (Discourse.base_path + url) if url[/^\/[^\/]/]
+ url = (Discourse.base_path + url) if url[%r{^/[^/]}]
e.url = url
e.group = group || DEFAULT_GROUP
end
@@ -196,47 +197,45 @@ class Emoji
end
def self.replacement_code(code)
- code
- .split('-')
- .map!(&:hex)
- .pack("U*")
+ code.split("-").map!(&:hex).pack("U*")
end
def self.unicode_replacements
- @unicode_replacements ||= begin
- replacements = {}
- is_tonable_emojis = Emoji.tonable_emojis
- fitzpatrick_scales = FITZPATRICK_SCALE.map { |scale| scale.to_i(16) }
+ @unicode_replacements ||=
+ begin
+ replacements = {}
+ is_tonable_emojis = Emoji.tonable_emojis
+ fitzpatrick_scales = FITZPATRICK_SCALE.map { |scale| scale.to_i(16) }
- db['emojis'].each do |e|
- name = e['name']
+ db["emojis"].each do |e|
+ name = e["name"]
- # special cased as we prefer to keep these as symbols
- next if name == 'registered'
- next if name == 'copyright'
- next if name == 'tm'
- next if name == 'left_right_arrow'
+ # special cased as we prefer to keep these as symbols
+ next if name == "registered"
+ next if name == "copyright"
+ next if name == "tm"
+ next if name == "left_right_arrow"
- code = replacement_code(e['code'])
- next unless code
+ code = replacement_code(e["code"])
+ next unless code
- replacements[code] = name
- if is_tonable_emojis.include?(name)
- fitzpatrick_scales.each_with_index do |scale, index|
- toned_code = code.codepoints.insert(1, scale).pack("U*")
- replacements[toned_code] = "#{name}:t#{index + 2}"
+ replacements[code] = name
+ if is_tonable_emojis.include?(name)
+ fitzpatrick_scales.each_with_index do |scale, index|
+ toned_code = code.codepoints.insert(1, scale).pack("U*")
+ replacements[toned_code] = "#{name}:t#{index + 2}"
+ end
end
end
+
+ replacements["\u{2639}"] = "frowning"
+ replacements["\u{263B}"] = "slight_smile"
+ replacements["\u{2661}"] = "heart"
+ replacements["\u{2665}"] = "heart"
+ replacements["\u{263A}"] = "relaxed"
+
+ replacements
end
-
- replacements["\u{2639}"] = 'frowning'
- replacements["\u{263B}"] = 'slight_smile'
- replacements["\u{2661}"] = 'heart'
- replacements["\u{2665}"] = 'heart'
- replacements["\u{263A}"] = 'relaxed'
-
- replacements
- end
end
def self.unicode_unescape(string)
@@ -244,40 +243,37 @@ class Emoji
end
def self.gsub_emoji_to_unicode(str)
- if str
- str.gsub(/:([\w\-+]*(?::t\d)?):/) { |name| Emoji.lookup_unicode($1) || name }
- end
+ str.gsub(/:([\w\-+]*(?::t\d)?):/) { |name| Emoji.lookup_unicode($1) || name } if str
end
def self.lookup_unicode(name)
- @reverse_map ||= begin
- map = {}
- is_tonable_emojis = Emoji.tonable_emojis
+ @reverse_map ||=
+ begin
+ map = {}
+ is_tonable_emojis = Emoji.tonable_emojis
- db['emojis'].each do |e|
- next if e['name'] == 'tm'
+ db["emojis"].each do |e|
+ next if e["name"] == "tm"
- code = replacement_code(e['code'])
- next unless code
+ code = replacement_code(e["code"])
+ next unless code
- map[e['name']] = code
- if is_tonable_emojis.include?(e['name'])
- FITZPATRICK_SCALE.each_with_index do |scale, index|
- toned_code = (code.codepoints.insert(1, scale.to_i(16))).pack("U*")
- map["#{e['name']}:t#{index + 2}"] = toned_code
+ map[e["name"]] = code
+ if is_tonable_emojis.include?(e["name"])
+ FITZPATRICK_SCALE.each_with_index do |scale, index|
+ toned_code = (code.codepoints.insert(1, scale.to_i(16))).pack("U*")
+ map["#{e["name"]}:t#{index + 2}"] = toned_code
+ end
end
end
- end
- Emoji.aliases.each do |key, alias_names|
- next unless alias_code = map[key]
- alias_names.each do |alias_name|
- map[alias_name] = alias_code
+ Emoji.aliases.each do |key, alias_names|
+ next unless alias_code = map[key]
+ alias_names.each { |alias_name| map[alias_name] = alias_code }
end
- end
- map
- end
+ map
+ end
@reverse_map[name]
end
@@ -288,17 +284,18 @@ class Emoji
def self.codes_to_img(str)
return if str.blank?
- str = str.gsub(/:([\w\-+]*(?::t\d)?):/) do |name|
- code = $1
+ str =
+ str.gsub(/:([\w\-+]*(?::t\d)?):/) do |name|
+ code = $1
- if code && Emoji.custom?(code)
- emoji = Emoji[code]
- ""
- elsif code && Emoji.exists?(code)
- ""
- else
- name
+ if code && Emoji.custom?(code)
+ emoji = Emoji[code]
+ ""
+ elsif code && Emoji.exists?(code)
+ ""
+ else
+ name
+ end
end
- end
end
end
diff --git a/app/models/emoji_set_site_setting.rb b/app/models/emoji_set_site_setting.rb
index 0fe47723900..172b249deec 100644
--- a/app/models/emoji_set_site_setting.rb
+++ b/app/models/emoji_set_site_setting.rb
@@ -1,26 +1,24 @@
# frozen_string_literal: true
-require 'enum_site_setting'
+require "enum_site_setting"
class EmojiSetSiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
values.any? { |v| v[:value] == val.to_s }
end
def self.values
@values ||= [
- { name: 'emoji_set.apple_international', value: 'apple' },
- { name: 'emoji_set.google', value: 'google' },
- { name: 'emoji_set.twitter', value: 'twitter' },
- { name: 'emoji_set.win10', value: 'win10' },
- { name: 'emoji_set.google_classic', value: 'google_classic' },
- { name: 'emoji_set.facebook_messenger', value: 'facebook_messenger' },
+ { name: "emoji_set.apple_international", value: "apple" },
+ { name: "emoji_set.google", value: "google" },
+ { name: "emoji_set.twitter", value: "twitter" },
+ { name: "emoji_set.win10", value: "win10" },
+ { name: "emoji_set.google_classic", value: "google_classic" },
+ { name: "emoji_set.facebook_messenger", value: "facebook_messenger" },
]
end
def self.translate_names?
true
end
-
end
diff --git a/app/models/external_upload_stub.rb b/app/models/external_upload_stub.rb
index 00fe2479423..99ed046b97e 100644
--- a/app/models/external_upload_stub.rb
+++ b/app/models/external_upload_stub.rb
@@ -7,27 +7,32 @@ class ExternalUploadStub < ActiveRecord::Base
UPLOADED_EXPIRY_HOURS = 24
FAILED_EXPIRY_HOURS = 48
- belongs_to :created_by, class_name: 'User'
+ belongs_to :created_by, class_name: "User"
- validates :filesize, numericality: {
- allow_nil: false, only_integer: true, greater_than_or_equal_to: 1
- }
+ validates :filesize,
+ numericality: {
+ allow_nil: false,
+ only_integer: true,
+ greater_than_or_equal_to: 1,
+ }
- scope :expired_created, -> {
- where(
- "status = ? AND created_at <= ?",
- ExternalUploadStub.statuses[:created],
- CREATED_EXPIRY_HOURS.hours.ago
- )
- }
+ scope :expired_created,
+ -> {
+ where(
+ "status = ? AND created_at <= ?",
+ ExternalUploadStub.statuses[:created],
+ CREATED_EXPIRY_HOURS.hours.ago,
+ )
+ }
- scope :expired_uploaded, -> {
- where(
- "status = ? AND created_at <= ?",
- ExternalUploadStub.statuses[:uploaded],
- UPLOADED_EXPIRY_HOURS.hours.ago
- )
- }
+ scope :expired_uploaded,
+ -> {
+ where(
+ "status = ? AND created_at <= ?",
+ ExternalUploadStub.statuses[:uploaded],
+ UPLOADED_EXPIRY_HOURS.hours.ago,
+ )
+ }
before_create do
self.unique_identifier = SecureRandom.uuid
@@ -35,11 +40,7 @@ class ExternalUploadStub < ActiveRecord::Base
end
def self.statuses
- @statuses ||= Enum.new(
- created: 1,
- uploaded: 2,
- failed: 3,
- )
+ @statuses ||= Enum.new(created: 1, uploaded: 2, failed: 3)
end
# TODO (martin): Lifecycle rule would be best to clean stuff up in the external
diff --git a/app/models/given_daily_like.rb b/app/models/given_daily_like.rb
index e5483ce3600..5b2096d867d 100644
--- a/app/models/given_daily_like.rb
+++ b/app/models/given_daily_like.rb
@@ -12,14 +12,15 @@ class GivenDailyLike < ActiveRecord::Base
given_date = Date.today
# upsert would be nice here
- rows = find_for(user_id, given_date).update_all('likes_given = likes_given + 1')
+ rows = find_for(user_id, given_date).update_all("likes_given = likes_given + 1")
if rows == 0
create(user_id: user_id, given_date: given_date, likes_given: 1)
else
- find_for(user_id, given_date)
- .where('limit_reached = false AND likes_given >= :limit', limit: SiteSetting.max_likes_per_day)
- .update_all(limit_reached: true)
+ find_for(user_id, given_date).where(
+ "limit_reached = false AND likes_given >= :limit",
+ limit: SiteSetting.max_likes_per_day,
+ ).update_all(limit_reached: true)
end
end
@@ -28,10 +29,11 @@ class GivenDailyLike < ActiveRecord::Base
given_date = Date.today
- find_for(user_id, given_date).update_all('likes_given = likes_given - 1')
- find_for(user_id, given_date)
- .where('limit_reached = true AND likes_given < :limit', limit: SiteSetting.max_likes_per_day)
- .update_all(limit_reached: false)
+ find_for(user_id, given_date).update_all("likes_given = likes_given - 1")
+ find_for(user_id, given_date).where(
+ "limit_reached = true AND likes_given < :limit",
+ limit: SiteSetting.max_likes_per_day,
+ ).update_all(limit_reached: false)
end
end
diff --git a/app/models/global_setting.rb b/app/models/global_setting.rb
index ff1ac7a5066..efd83403a06 100644
--- a/app/models/global_setting.rb
+++ b/app/models/global_setting.rb
@@ -1,17 +1,14 @@
# frozen_string_literal: true
class GlobalSetting
-
def self.register(key, default)
- define_singleton_method(key) do
- provider.lookup(key, default)
- end
+ define_singleton_method(key) { provider.lookup(key, default) }
end
VALID_SECRET_KEY ||= /^[0-9a-f]{128}$/
# this is named SECRET_TOKEN as opposed to SECRET_KEY_BASE
# for legacy reasons
- REDIS_SECRET_KEY ||= 'SECRET_TOKEN'
+ REDIS_SECRET_KEY ||= "SECRET_TOKEN"
REDIS_VALIDATE_SECONDS ||= 30
@@ -23,58 +20,59 @@ class GlobalSetting
# - generate a token on the fly if needed and cache in redis
# - enforce rules about token format falling back to redis if needed
def self.safe_secret_key_base
-
- if @safe_secret_key_base && @token_in_redis && (@token_last_validated + REDIS_VALIDATE_SECONDS) < Time.now
+ if @safe_secret_key_base && @token_in_redis &&
+ (@token_last_validated + REDIS_VALIDATE_SECONDS) < Time.now
@token_last_validated = Time.now
token = Discourse.redis.without_namespace.get(REDIS_SECRET_KEY)
- if token.nil?
- Discourse.redis.without_namespace.set(REDIS_SECRET_KEY, @safe_secret_key_base)
- end
+ Discourse.redis.without_namespace.set(REDIS_SECRET_KEY, @safe_secret_key_base) if token.nil?
end
- @safe_secret_key_base ||= begin
- token = secret_key_base
- if token.blank? || token !~ VALID_SECRET_KEY
+ @safe_secret_key_base ||=
+ begin
+ token = secret_key_base
+ if token.blank? || token !~ VALID_SECRET_KEY
+ @token_in_redis = true
+ @token_last_validated = Time.now
- @token_in_redis = true
- @token_last_validated = Time.now
-
- token = Discourse.redis.without_namespace.get(REDIS_SECRET_KEY)
- unless token && token =~ VALID_SECRET_KEY
- token = SecureRandom.hex(64)
- Discourse.redis.without_namespace.set(REDIS_SECRET_KEY, token)
+ token = Discourse.redis.without_namespace.get(REDIS_SECRET_KEY)
+ unless token && token =~ VALID_SECRET_KEY
+ token = SecureRandom.hex(64)
+ Discourse.redis.without_namespace.set(REDIS_SECRET_KEY, token)
+ end
end
+ if !secret_key_base.blank? && token != secret_key_base
+ STDERR.puts "WARNING: DISCOURSE_SECRET_KEY_BASE is invalid, it was re-generated"
+ end
+ token
end
- if !secret_key_base.blank? && token != secret_key_base
- STDERR.puts "WARNING: DISCOURSE_SECRET_KEY_BASE is invalid, it was re-generated"
- end
- token
- end
rescue Redis::CommandError => e
@safe_secret_key_base = SecureRandom.hex(64) if e.message =~ /READONLY/
end
def self.load_defaults
- default_provider = FileProvider.from(File.expand_path('../../../config/discourse_defaults.conf', __FILE__))
- default_provider.keys.concat(@provider.keys).uniq.each do |key|
- default = default_provider.lookup(key, nil)
+ default_provider =
+ FileProvider.from(File.expand_path("../../../config/discourse_defaults.conf", __FILE__))
+ default_provider
+ .keys
+ .concat(@provider.keys)
+ .uniq
+ .each do |key|
+ default = default_provider.lookup(key, nil)
- instance_variable_set("@#{key}_cache", nil)
+ instance_variable_set("@#{key}_cache", nil)
- define_singleton_method(key) do
- val = instance_variable_get("@#{key}_cache")
- unless val.nil?
- val == :missing ? nil : val
- else
- val = provider.lookup(key, default)
- if val.nil?
- val = :missing
+ define_singleton_method(key) do
+ val = instance_variable_get("@#{key}_cache")
+ unless val.nil?
+ val == :missing ? nil : val
+ else
+ val = provider.lookup(key, default)
+ val = :missing if val.nil?
+ instance_variable_set("@#{key}_cache", val)
+ val == :missing ? nil : val
end
- instance_variable_set("@#{key}_cache", val)
- val == :missing ? nil : val
end
end
- end
end
def self.skip_db=(v)
@@ -94,13 +92,17 @@ class GlobalSetting
end
def self.use_s3?
- (@use_s3 ||=
- begin
- s3_bucket &&
- s3_region && (
- s3_use_iam_profile || (s3_access_key_id && s3_secret_access_key)
- ) ? :true : :false
- end) == :true
+ (
+ @use_s3 ||=
+ begin
+ if s3_bucket && s3_region &&
+ (s3_use_iam_profile || (s3_access_key_id && s3_secret_access_key))
+ :true
+ else
+ :false
+ end
+ end
+ ) == :true
end
def self.s3_bucket_name
@@ -122,7 +124,7 @@ class GlobalSetting
def self.database_config
hash = { "adapter" => "postgresql" }
- %w{
+ %w[
pool
connect_timeout
timeout
@@ -135,13 +137,13 @@ class GlobalSetting
password
replica_host
replica_port
- }.each do |s|
+ ].each do |s|
if val = self.public_send("db_#{s}")
hash[s] = val
end
end
- hostnames = [ hostname ]
+ hostnames = [hostname]
hostnames << backup_hostname if backup_hostname.present?
hostnames << URI.parse(cdn_url).host if cdn_url.present?
@@ -154,11 +156,11 @@ class GlobalSetting
hash["reaping_frequency"] = connection_reaper_interval if connection_reaper_interval.present?
hash["advisory_locks"] = !!self.db_advisory_locks
- db_variables = provider.keys.filter { |k| k.to_s.starts_with? 'db_variables_' }
+ db_variables = provider.keys.filter { |k| k.to_s.starts_with? "db_variables_" }
if db_variables.length > 0
hash["variables"] = {}
db_variables.each do |k|
- hash["variables"][k.slice(('db_variables_'.length)..)] = self.public_send(k)
+ hash["variables"][k.slice(("db_variables_".length)..)] = self.public_send(k)
end
end
@@ -183,12 +185,16 @@ class GlobalSetting
def self.get_message_bus_redis_replica_host
return message_bus_redis_replica_host if message_bus_redis_replica_host.present?
- message_bus_redis_slave_host if respond_to?(:message_bus_redis_slave_host) && message_bus_redis_slave_host.present?
+ if respond_to?(:message_bus_redis_slave_host) && message_bus_redis_slave_host.present?
+ message_bus_redis_slave_host
+ end
end
def self.get_message_bus_redis_replica_port
return message_bus_redis_replica_port if message_bus_redis_replica_port.present?
- message_bus_redis_slave_port if respond_to?(:message_bus_redis_slave_port) && message_bus_redis_slave_port.present?
+ if respond_to?(:message_bus_redis_slave_port) && message_bus_redis_slave_port.present?
+ message_bus_redis_slave_port
+ end
end
def self.redis_config
@@ -239,11 +245,7 @@ class GlobalSetting
end
def self.add_default(name, default)
- unless self.respond_to? name
- define_singleton_method(name) do
- default
- end
- end
+ define_singleton_method(name) { default } unless self.respond_to? name
end
class BaseProvider
@@ -259,7 +261,7 @@ class GlobalSetting
current
else
default.present? ? default : nil
- end
+ end,
)
end
end
@@ -267,9 +269,7 @@ class GlobalSetting
class FileProvider < BaseProvider
attr_reader :data
def self.from(file)
- if File.exist?(file)
- parse(file)
- end
+ parse(file) if File.exist?(file)
end
def initialize(file)
@@ -278,11 +278,15 @@ class GlobalSetting
end
def read
- ERB.new(File.read(@file)).result().split("\n").each do |line|
- if line =~ /^\s*([a-z_]+[a-z0-9_]*)\s*=\s*(\"([^\"]*)\"|\'([^\']*)\'|[^#]*)/
- @data[$1.strip.to_sym] = ($4 || $3 || $2).strip
+ ERB
+ .new(File.read(@file))
+ .result()
+ .split("\n")
+ .each do |line|
+ if line =~ /^\s*([a-z_]+[a-z0-9_]*)\s*=\s*(\"([^\"]*)\"|\'([^\']*)\'|[^#]*)/
+ @data[$1.strip.to_sym] = ($4 || $3 || $2).strip
+ end
end
- end
end
def lookup(key, default)
@@ -306,7 +310,7 @@ class GlobalSetting
class EnvProvider < BaseProvider
def lookup(key, default)
var = ENV["DISCOURSE_" + key.to_s.upcase]
- resolve(var , var.nil? ? default : nil)
+ resolve(var, var.nil? ? default : nil)
end
def keys
@@ -316,7 +320,6 @@ class GlobalSetting
class BlankProvider < BaseProvider
def lookup(key, default)
-
if key == :redis_port
return ENV["DISCOURSE_REDIS_PORT"] if ENV["DISCOURSE_REDIS_PORT"]
end
@@ -337,8 +340,8 @@ class GlobalSetting
@provider = BlankProvider.new
else
@provider =
- FileProvider.from(File.expand_path('../../../config/discourse.conf', __FILE__)) ||
- EnvProvider.new
+ FileProvider.from(File.expand_path("../../../config/discourse.conf", __FILE__)) ||
+ EnvProvider.new
end
end
diff --git a/app/models/group.rb b/app/models/group.rb
index b4dbd85eabb..c31436815a9 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -1,12 +1,10 @@
# frozen_string_literal: true
-require 'net/imap'
+require "net/imap"
class Group < ActiveRecord::Base
# TODO(2021-05-26): remove
- self.ignored_columns = %w{
- flair_url
- }
+ self.ignored_columns = %w[flair_url]
include HasCustomFields
include AnonCacheInvalidator
@@ -28,17 +26,20 @@ class Group < ActiveRecord::Base
has_many :users, through: :group_users
has_many :requesters, through: :group_requests, source: :user
has_many :group_histories, dependent: :destroy
- has_many :category_reviews, class_name: 'Category', foreign_key: :reviewable_by_group_id, dependent: :nullify
+ has_many :category_reviews,
+ class_name: "Category",
+ foreign_key: :reviewable_by_group_id,
+ dependent: :nullify
has_many :reviewables, foreign_key: :reviewable_by_group_id, dependent: :nullify
has_many :group_category_notification_defaults, dependent: :destroy
has_many :group_tag_notification_defaults, dependent: :destroy
has_many :associated_groups, through: :group_associated_groups, dependent: :destroy
- belongs_to :flair_upload, class_name: 'Upload'
+ belongs_to :flair_upload, class_name: "Upload"
has_many :upload_references, as: :target, dependent: :destroy
- belongs_to :smtp_updated_by, class_name: 'User'
- belongs_to :imap_updated_by, class_name: 'User'
+ belongs_to :smtp_updated_by, class_name: "User"
+ belongs_to :imap_updated_by, class_name: "User"
has_and_belongs_to_many :web_hooks
@@ -50,7 +51,7 @@ class Group < ActiveRecord::Base
after_save :update_title
after_save :enqueue_update_mentions_job,
- if: Proc.new { |g| g.name_before_last_save && g.saved_change_to_name? }
+ if: Proc.new { |g| g.name_before_last_save && g.saved_change_to_name? }
after_save do
if saved_change_to_flair_upload_id?
@@ -61,11 +62,11 @@ class Group < ActiveRecord::Base
after_save :expire_cache
after_destroy :expire_cache
- after_commit :automatic_group_membership, on: [:create, :update]
+ after_commit :automatic_group_membership, on: %i[create update]
after_commit :trigger_group_created_event, on: :create
after_commit :trigger_group_updated_event, on: :update
after_commit :trigger_group_destroyed_event, on: :destroy
- after_commit :set_default_notifications, on: [:create, :update]
+ after_commit :set_default_notifications, on: %i[create update]
def expire_cache
ApplicationSerializer.expire_cache_fragment!("group_names")
@@ -97,31 +98,31 @@ class Group < ActiveRecord::Base
trust_level_1: 11,
trust_level_2: 12,
trust_level_3: 13,
- trust_level_4: 14
+ trust_level_4: 14,
}
AUTO_GROUP_IDS = Hash[*AUTO_GROUPS.to_a.flatten.reverse]
- STAFF_GROUPS = [:admins, :moderators, :staff]
+ STAFF_GROUPS = %i[admins moderators staff]
AUTO_GROUPS_ADD = "add"
AUTO_GROUPS_REMOVE = "remove"
- IMAP_SETTING_ATTRIBUTES = [
- "imap_server",
- "imap_port",
- "imap_ssl",
- "imap_mailbox_name",
- "email_username",
- "email_password"
+ IMAP_SETTING_ATTRIBUTES = %w[
+ imap_server
+ imap_port
+ imap_ssl
+ imap_mailbox_name
+ email_username
+ email_password
]
- SMTP_SETTING_ATTRIBUTES = [
- "imap_server",
- "imap_port",
- "imap_ssl",
- "email_username",
- "email_password",
- "email_from_alias"
+ SMTP_SETTING_ATTRIBUTES = %w[
+ imap_server
+ imap_port
+ imap_ssl
+ email_username
+ email_password
+ email_from_alias
]
ALIAS_LEVELS = {
@@ -130,45 +131,38 @@ class Group < ActiveRecord::Base
mods_and_admins: 2,
members_mods_and_admins: 3,
owners_mods_and_admins: 4,
- everyone: 99
+ everyone: 99,
}
VALID_DOMAIN_REGEX = /\A[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,24}(:[0-9]{1,5})?(\/.*)?\Z/i
def self.visibility_levels
- @visibility_levels = Enum.new(
- public: 0,
- logged_on_users: 1,
- members: 2,
- staff: 3,
- owners: 4
- )
+ @visibility_levels = Enum.new(public: 0, logged_on_users: 1, members: 2, staff: 3, owners: 4)
end
validates :mentionable_level, inclusion: { in: ALIAS_LEVELS.values }
validates :messageable_level, inclusion: { in: ALIAS_LEVELS.values }
- scope :with_imap_configured, -> { where(imap_enabled: true).where.not(imap_mailbox_name: '') }
+ scope :with_imap_configured, -> { where(imap_enabled: true).where.not(imap_mailbox_name: "") }
scope :with_smtp_configured, -> { where(smtp_enabled: true) }
- scope :visible_groups, Proc.new { |user, order, opts|
- groups = self
- groups = groups.order(order) if order
- groups = groups.order("groups.name ASC") unless order&.include?("name")
+ scope :visible_groups,
+ Proc.new { |user, order, opts|
+ groups = self
+ groups = groups.order(order) if order
+ groups = groups.order("groups.name ASC") unless order&.include?("name")
- if !opts || !opts[:include_everyone]
- groups = groups.where("groups.id > 0")
- end
+ groups = groups.where("groups.id > 0") if !opts || !opts[:include_everyone]
- if !user&.admin
- is_staff = !!user&.staff?
+ if !user&.admin
+ is_staff = !!user&.staff?
- if user.blank?
- sql = "groups.visibility_level = :public"
- elsif is_staff
- sql = "groups.visibility_level IN (:public, :logged_on_users, :members, :staff)"
- else
- sql = <<~SQL
+ if user.blank?
+ sql = "groups.visibility_level = :public"
+ elsif is_staff
+ sql = "groups.visibility_level IN (:public, :logged_on_users, :members, :staff)"
+ else
+ sql = <<~SQL
groups.id IN (
SELECT id
FROM groups
@@ -189,31 +183,31 @@ class Group < ActiveRecord::Base
WHERE g.visibility_level IN (:staff, :owners)
)
SQL
- end
+ end
- params = Group.visibility_levels.to_h.merge(user_id: user&.id, is_staff: is_staff)
- groups = groups.where(sql, params)
- end
+ params = Group.visibility_levels.to_h.merge(user_id: user&.id, is_staff: is_staff)
+ groups = groups.where(sql, params)
+ end
- groups
- }
+ groups
+ }
- scope :members_visible_groups, Proc.new { |user, order, opts|
- groups = self.order(order || "name ASC")
+ scope :members_visible_groups,
+ Proc.new { |user, order, opts|
+ groups = self.order(order || "name ASC")
- if !opts || !opts[:include_everyone]
- groups = groups.where("groups.id > 0")
- end
+ groups = groups.where("groups.id > 0") if !opts || !opts[:include_everyone]
- if !user&.admin
- is_staff = !!user&.staff?
+ if !user&.admin
+ is_staff = !!user&.staff?
- if user.blank?
- sql = "groups.members_visibility_level = :public"
- elsif is_staff
- sql = "groups.members_visibility_level IN (:public, :logged_on_users, :members, :staff)"
- else
- sql = <<~SQL
+ if user.blank?
+ sql = "groups.members_visibility_level = :public"
+ elsif is_staff
+ sql =
+ "groups.members_visibility_level IN (:public, :logged_on_users, :members, :staff)"
+ else
+ sql = <<~SQL
groups.id IN (
SELECT id
FROM groups
@@ -234,32 +228,39 @@ class Group < ActiveRecord::Base
WHERE g.members_visibility_level IN (:staff, :owners)
)
SQL
- end
+ end
- params = Group.visibility_levels.to_h.merge(user_id: user&.id, is_staff: is_staff)
- groups = groups.where(sql, params)
- end
+ params = Group.visibility_levels.to_h.merge(user_id: user&.id, is_staff: is_staff)
+ groups = groups.where(sql, params)
+ end
- groups
- }
+ groups
+ }
- scope :mentionable, lambda { |user, include_public: true|
- where(self.mentionable_sql_clause(include_public: include_public),
- levels: alias_levels(user),
- user_id: user&.id
- )
- }
+ scope :mentionable,
+ lambda { |user, include_public: true|
+ where(
+ self.mentionable_sql_clause(include_public: include_public),
+ levels: alias_levels(user),
+ user_id: user&.id,
+ )
+ }
- scope :messageable, lambda { |user|
- where("messageable_level in (:levels) OR
+ scope :messageable,
+ lambda { |user|
+ where(
+ "messageable_level in (:levels) OR
(
messageable_level = #{ALIAS_LEVELS[:members_mods_and_admins]} AND id in (
SELECT group_id FROM group_users WHERE user_id = :user_id)
) OR (
messageable_level = #{ALIAS_LEVELS[:owners_mods_and_admins]} AND id in (
SELECT group_id FROM group_users WHERE user_id = :user_id AND owner IS TRUE)
- )", levels: alias_levels(user), user_id: user && user.id)
- }
+ )",
+ levels: alias_levels(user),
+ user_id: user && user.id,
+ )
+ }
def self.mentionable_sql_clause(include_public: true)
clause = +<<~SQL
@@ -275,9 +276,7 @@ class Group < ActiveRecord::Base
)
SQL
- if include_public
- clause << "OR visibility_level = #{Group.visibility_levels[:public]}"
- end
+ clause << "OR visibility_level = #{Group.visibility_levels[:public]}" if include_public
clause
end
@@ -330,8 +329,18 @@ class Group < ActiveRecord::Base
self.smtp_updated_by_id = user.id
end
- self.smtp_enabled = [self.smtp_port, self.smtp_server, self.email_password, self.email_username].all?(&:present?)
- self.imap_enabled = [self.imap_port, self.imap_server, self.email_password, self.email_username].all?(&:present?)
+ self.smtp_enabled = [
+ self.smtp_port,
+ self.smtp_server,
+ self.email_password,
+ self.email_username,
+ ].all?(&:present?)
+ self.imap_enabled = [
+ self.imap_port,
+ self.imap_server,
+ self.email_password,
+ self.email_username,
+ ].all?(&:present?)
self.save
end
@@ -339,71 +348,96 @@ class Group < ActiveRecord::Base
def incoming_email_validator
return if self.automatic || self.incoming_email.blank?
- incoming_email.split("|").each do |email|
- escaped = Rack::Utils.escape_html(email)
- if !Email.is_valid?(email)
- self.errors.add(:base, I18n.t('groups.errors.invalid_incoming_email', email: escaped))
- elsif group = Group.where.not(id: self.id).find_by_email(email)
- self.errors.add(:base, I18n.t('groups.errors.email_already_used_in_group', email: escaped, group_name: Rack::Utils.escape_html(group.name)))
- elsif category = Category.find_by_email(email)
- self.errors.add(:base, I18n.t('groups.errors.email_already_used_in_category', email: escaped, category_name: Rack::Utils.escape_html(category.name)))
+ incoming_email
+ .split("|")
+ .each do |email|
+ escaped = Rack::Utils.escape_html(email)
+ if !Email.is_valid?(email)
+ self.errors.add(:base, I18n.t("groups.errors.invalid_incoming_email", email: escaped))
+ elsif group = Group.where.not(id: self.id).find_by_email(email)
+ self.errors.add(
+ :base,
+ I18n.t(
+ "groups.errors.email_already_used_in_group",
+ email: escaped,
+ group_name: Rack::Utils.escape_html(group.name),
+ ),
+ )
+ elsif category = Category.find_by_email(email)
+ self.errors.add(
+ :base,
+ I18n.t(
+ "groups.errors.email_already_used_in_category",
+ email: escaped,
+ category_name: Rack::Utils.escape_html(category.name),
+ ),
+ )
+ end
end
- end
end
def posts_for(guardian, opts = nil)
opts ||= {}
- result = Post.joins(:topic, user: :groups, topic: :category)
- .preload(:topic, user: :groups, topic: :category)
- .references(:posts, :topics, :category)
- .where(groups: { id: id })
- .where('topics.archetype <> ?', Archetype.private_message)
- .where('topics.visible')
- .where(post_type: [Post.types[:regular], Post.types[:moderator_action]])
+ result =
+ Post
+ .joins(:topic, user: :groups, topic: :category)
+ .preload(:topic, user: :groups, topic: :category)
+ .references(:posts, :topics, :category)
+ .where(groups: { id: id })
+ .where("topics.archetype <> ?", Archetype.private_message)
+ .where("topics.visible")
+ .where(post_type: [Post.types[:regular], Post.types[:moderator_action]])
if opts[:category_id].present?
- result = result.where('topics.category_id = ?', opts[:category_id].to_i)
+ result = result.where("topics.category_id = ?", opts[:category_id].to_i)
end
result = guardian.filter_allowed_categories(result)
- result = result.where('posts.id < ?', opts[:before_post_id].to_i) if opts[:before_post_id]
- result.order('posts.created_at desc')
+ result = result.where("posts.id < ?", opts[:before_post_id].to_i) if opts[:before_post_id]
+ result.order("posts.created_at desc")
end
def messages_for(guardian, opts = nil)
opts ||= {}
- result = Post.includes(:user, :topic, topic: :category)
- .references(:posts, :topics, :category)
- .where('topics.archetype = ?', Archetype.private_message)
- .where(post_type: Post.types[:regular])
- .where('topics.id IN (SELECT topic_id FROM topic_allowed_groups WHERE group_id = ?)', self.id)
+ result =
+ Post
+ .includes(:user, :topic, topic: :category)
+ .references(:posts, :topics, :category)
+ .where("topics.archetype = ?", Archetype.private_message)
+ .where(post_type: Post.types[:regular])
+ .where(
+ "topics.id IN (SELECT topic_id FROM topic_allowed_groups WHERE group_id = ?)",
+ self.id,
+ )
if opts[:category_id].present?
- result = result.where('topics.category_id = ?', opts[:category_id].to_i)
+ result = result.where("topics.category_id = ?", opts[:category_id].to_i)
end
result = guardian.filter_allowed_categories(result)
- result = result.where('posts.id < ?', opts[:before_post_id].to_i) if opts[:before_post_id]
- result.order('posts.created_at desc')
+ result = result.where("posts.id < ?", opts[:before_post_id].to_i) if opts[:before_post_id]
+ result.order("posts.created_at desc")
end
def mentioned_posts_for(guardian, opts = nil)
opts ||= {}
- result = Post.joins(:group_mentions)
- .includes(:user, :topic, topic: :category)
- .references(:posts, :topics, :category)
- .where('topics.archetype <> ?', Archetype.private_message)
- .where(post_type: Post.types[:regular])
- .where('group_mentions.group_id = ?', self.id)
+ result =
+ Post
+ .joins(:group_mentions)
+ .includes(:user, :topic, topic: :category)
+ .references(:posts, :topics, :category)
+ .where("topics.archetype <> ?", Archetype.private_message)
+ .where(post_type: Post.types[:regular])
+ .where("group_mentions.group_id = ?", self.id)
if opts[:category_id].present?
- result = result.where('topics.category_id = ?', opts[:category_id].to_i)
+ result = result.where("topics.category_id = ?", opts[:category_id].to_i)
end
result = guardian.filter_allowed_categories(result)
- result = result.where('posts.id < ?', opts[:before_post_id].to_i) if opts[:before_post_id]
- result.order('posts.created_at desc')
+ result = result.where("posts.id < ?", opts[:before_post_id].to_i) if opts[:before_post_id]
+ result.order("posts.created_at desc")
end
def self.trust_group_ids
@@ -411,22 +445,29 @@ class Group < ActiveRecord::Base
end
def set_message_default_notification_levels!(topic, ignore_existing: false)
- group_users.pluck(:user_id, :notification_level).each do |user_id, notification_level|
- next if user_id == -1
- next if user_id == topic.user_id
- next if ignore_existing && TopicUser.where(user_id: user_id, topic_id: topic.id).exists?
+ group_users
+ .pluck(:user_id, :notification_level)
+ .each do |user_id, notification_level|
+ next if user_id == -1
+ next if user_id == topic.user_id
+ next if ignore_existing && TopicUser.where(user_id: user_id, topic_id: topic.id).exists?
- action =
- case notification_level
- when TopicUser.notification_levels[:tracking] then "track!"
- when TopicUser.notification_levels[:regular] then "regular!"
- when TopicUser.notification_levels[:muted] then "mute!"
- when TopicUser.notification_levels[:watching] then "watch!"
- else "track!"
- end
+ action =
+ case notification_level
+ when TopicUser.notification_levels[:tracking]
+ "track!"
+ when TopicUser.notification_levels[:regular]
+ "regular!"
+ when TopicUser.notification_levels[:muted]
+ "mute!"
+ when TopicUser.notification_levels[:watching]
+ "watch!"
+ else
+ "track!"
+ end
- topic.notifier.public_send(action, user_id)
- end
+ topic.notifier.public_send(action, user_id)
+ end
end
def self.set_category_and_tag_default_notification_levels!(user, group_name)
@@ -455,9 +496,7 @@ class Group < ActiveRecord::Base
localized_name = I18n.t("groups.default_names.#{name}", locale: SiteSetting.default_locale)
validator = UsernameValidator.new(localized_name)
- if validator.valid_format? && !User.username_exists?(localized_name)
- group.name = localized_name
- end
+ group.name = localized_name if validator.valid_format? && !User.username_exists?(localized_name)
# the everyone group is special, it can include non-users so there is no
# way to have the membership in a table
@@ -470,7 +509,9 @@ class Group < ActiveRecord::Base
group.update!(messageable_level: ALIAS_LEVELS[:everyone])
end
- group.update!(visibility_level: Group.visibility_levels[:logged_on_users]) if group.visibility_level == Group.visibility_levels[:public]
+ if group.visibility_level == Group.visibility_levels[:public]
+ group.update!(visibility_level: Group.visibility_levels[:logged_on_users])
+ end
# Remove people from groups they don't belong in.
remove_subquery =
@@ -496,7 +537,9 @@ class Group < ActiveRecord::Base
if removed_user_ids.present?
Jobs.enqueue(
:publish_group_membership_updates,
- user_ids: removed_user_ids, group_id: group.id, type: AUTO_GROUPS_REMOVE
+ user_ids: removed_user_ids,
+ group_id: group.id,
+ type: AUTO_GROUPS_REMOVE,
)
end
@@ -529,7 +572,9 @@ class Group < ActiveRecord::Base
if added_user_ids.present?
Jobs.enqueue(
:publish_group_membership_updates,
- user_ids: added_user_ids, group_id: group.id, type: AUTO_GROUPS_ADD
+ user_ids: added_user_ids,
+ group_id: group.id,
+ type: AUTO_GROUPS_ADD,
)
end
@@ -554,7 +599,7 @@ class Group < ActiveRecord::Base
end
def self.reset_groups_user_count!(only_group_ids: [])
- where_sql = ''
+ where_sql = ""
if only_group_ids.present?
where_sql = "WHERE group_id IN (#{only_group_ids.map(&:to_i).join(",")})"
@@ -596,9 +641,7 @@ class Group < ActiveRecord::Base
end
def self.ensure_automatic_groups!
- AUTO_GROUPS.each_key do |name|
- refresh_automatic_group!(name) unless lookup_group(name)
- end
+ AUTO_GROUPS.each_key { |name| refresh_automatic_group!(name) unless lookup_group(name) }
end
def self.[](name)
@@ -608,18 +651,18 @@ class Group < ActiveRecord::Base
def self.search_groups(name, groups: nil, custom_scope: {}, sort: :none)
groups ||= Group
- relation = groups.where(
- "name ILIKE :term_like OR full_name ILIKE :term_like", term_like: "%#{name}%"
- )
+ relation =
+ groups.where("name ILIKE :term_like OR full_name ILIKE :term_like", term_like: "%#{name}%")
if sort == :auto
prefix = "#{name.gsub("_", "\\_")}%"
- relation = relation.reorder(
- DB.sql_fragment(
- "CASE WHEN name ILIKE :like OR full_name ILIKE :like THEN 0 ELSE 1 END ASC, name ASC",
- like: prefix
+ relation =
+ relation.reorder(
+ DB.sql_fragment(
+ "CASE WHEN name ILIKE :like OR full_name ILIKE :like THEN 0 ELSE 1 END ASC, name ASC",
+ like: prefix,
+ ),
)
- )
end
relation
@@ -652,9 +695,7 @@ class Group < ActiveRecord::Base
end
def self.desired_trust_level_groups(trust_level)
- trust_group_ids.keep_if do |id|
- id == AUTO_GROUPS[:trust_level_0] || (trust_level + 10) >= id
- end
+ trust_group_ids.keep_if { |id| id == AUTO_GROUPS[:trust_level_0] || (trust_level + 10) >= id }
end
def self.user_trust_level_change!(user_id, trust_level)
@@ -696,21 +737,21 @@ class Group < ActiveRecord::Base
additions = expected - current
deletions = current - expected
- map = Hash[*User.where(username: additions + deletions)
- .select('id,username')
- .map { |u| [u.username, u.id] }.flatten]
+ map =
+ Hash[
+ *User
+ .where(username: additions + deletions)
+ .select("id,username")
+ .map { |u| [u.username, u.id] }
+ .flatten
+ ]
deletions = Set.new(deletions.map { |d| map[d] })
@deletions = []
- group_users.each do |gu|
- @deletions << gu if deletions.include?(gu.user_id)
- end
-
- additions.each do |a|
- group_users.build(user_id: map[a])
- end
+ group_users.each { |gu| @deletions << gu if deletions.include?(gu.user_id) }
+ additions.each { |a| group_users.build(user_id: map[a]) }
end
def usernames
@@ -728,14 +769,16 @@ class Group < ActiveRecord::Base
Notification.create!(
notification_type: Notification.types[:membership_request_accepted],
user_id: user.id,
- data: { group_id: id, group_name: name }.to_json
+ data: { group_id: id, group_name: name }.to_json,
)
end
if self.categories.count < PUBLISH_CATEGORIES_LIMIT
- MessageBus.publish('/categories', {
- categories: ActiveModel::ArraySerializer.new(self.categories).as_json
- }, user_ids: [user.id])
+ MessageBus.publish(
+ "/categories",
+ { categories: ActiveModel::ArraySerializer.new(self.categories).as_json },
+ user_ids: [user.id],
+ )
else
Discourse.request_refresh!(user_ids: [user.id])
end
@@ -750,13 +793,18 @@ class Group < ActiveRecord::Base
return false if group_user.blank?
has_webhooks = WebHook.active_web_hooks(:group_user)
- payload = WebHook.generate_payload(:group_user, group_user, WebHookGroupUserSerializer) if has_webhooks
+ payload =
+ WebHook.generate_payload(:group_user, group_user, WebHookGroupUserSerializer) if has_webhooks
group_user.destroy
trigger_user_removed_event(user)
- WebHook.enqueue_hooks(:group_user, :user_removed_from_group,
- id: group_user.id,
- payload: payload
- ) if has_webhooks
+ if has_webhooks
+ WebHook.enqueue_hooks(
+ :group_user,
+ :user_removed_from_group,
+ id: group_user.id,
+ payload: payload,
+ )
+ end
true
end
@@ -781,7 +829,7 @@ class Group < ActiveRecord::Base
"email_username = :email OR
string_to_array(incoming_email, '|') @> ARRAY[:email] OR
email_from_alias = :email",
- email: Email.downcase(email)
+ email: Email.downcase(email),
).first
end
@@ -810,17 +858,11 @@ class Group < ActiveRecord::Base
user_attributes = {}
- if self.primary_group?
- user_attributes[:primary_group_id] = self.id
- end
+ user_attributes[:primary_group_id] = self.id if self.primary_group?
- if self.title.present?
- user_attributes[:title] = self.title
- end
+ user_attributes[:title] = self.title if self.title.present?
- if user_attributes.present?
- User.where(id: user_ids).update_all(user_attributes)
- end
+ User.where(id: user_ids).update_all(user_attributes) if user_attributes.present?
# update group user count
DB.exec <<~SQL
@@ -834,10 +876,7 @@ class Group < ActiveRecord::Base
end
if self.grant_trust_level.present?
- Jobs.enqueue(:bulk_grant_trust_level,
- user_ids: user_ids,
- trust_level: self.grant_trust_level
- )
+ Jobs.enqueue(:bulk_grant_trust_level, user_ids: user_ids, trust_level: self.grant_trust_level)
end
self
@@ -862,20 +901,17 @@ class Group < ActiveRecord::Base
end
def self.member_of(groups, user)
- groups
- .joins("LEFT JOIN group_users gu ON gu.group_id = groups.id ")
- .where("gu.user_id = ?", user.id)
+ groups.joins("LEFT JOIN group_users gu ON gu.group_id = groups.id ").where(
+ "gu.user_id = ?",
+ user.id,
+ )
end
def self.owner_of(groups, user)
self.member_of(groups, user).where("gu.owner")
end
- %i{
- group_created
- group_updated
- group_destroyed
- }.each do |event|
+ %i[group_created group_updated group_destroyed].each do |event|
define_method("trigger_#{event}_event") do
DiscourseEvent.trigger(event, self)
true
@@ -894,7 +930,7 @@ class Group < ActiveRecord::Base
nil
end
- [:muted, :regular, :tracking, :watching, :watching_first_post].each do |level|
+ %i[muted regular tracking watching watching_first_post].each do |level|
define_method("#{level}_category_ids=") do |category_ids|
@category_notifications ||= {}
@category_notifications[level] = category_ids
@@ -923,26 +959,28 @@ class Group < ActiveRecord::Base
def imap_mailboxes
return [] if !self.imap_enabled || !SiteSetting.enable_imap
- Discourse.cache.fetch("group_imap_mailboxes_#{self.id}", expires_in: 30.minutes) do
- Rails.logger.info("[IMAP] Refreshing mailboxes list for group #{self.name}")
- mailboxes = []
+ Discourse
+ .cache
+ .fetch("group_imap_mailboxes_#{self.id}", expires_in: 30.minutes) do
+ Rails.logger.info("[IMAP] Refreshing mailboxes list for group #{self.name}")
+ mailboxes = []
- begin
- imap_provider = Imap::Providers::Detector.init_with_detected_provider(
- self.imap_config
- )
- imap_provider.connect!
- mailboxes = imap_provider.filter_mailboxes(imap_provider.list_mailboxes_with_attributes)
- imap_provider.disconnect!
+ begin
+ imap_provider = Imap::Providers::Detector.init_with_detected_provider(self.imap_config)
+ imap_provider.connect!
+ mailboxes = imap_provider.filter_mailboxes(imap_provider.list_mailboxes_with_attributes)
+ imap_provider.disconnect!
- update_columns(imap_last_error: nil)
- rescue => ex
- Rails.logger.warn("[IMAP] Mailbox refresh failed for group #{self.name} with error: #{ex}")
- update_columns(imap_last_error: ex.message)
+ update_columns(imap_last_error: nil)
+ rescue => ex
+ Rails.logger.warn(
+ "[IMAP] Mailbox refresh failed for group #{self.name} with error: #{ex}",
+ )
+ update_columns(imap_last_error: ex.message)
+ end
+
+ mailboxes
end
-
- mailboxes
- end
end
def imap_config
@@ -951,16 +989,16 @@ class Group < ActiveRecord::Base
port: self.imap_port,
ssl: self.imap_ssl,
username: self.email_username,
- password: self.email_password
+ password: self.email_password,
}
end
def email_username_domain
- email_username.split('@').last
+ email_username.split("@").last
end
def email_username_user
- email_username.split('@').first
+ email_username.split("@").first
end
def email_username_regex
@@ -976,7 +1014,7 @@ class Group < ActiveRecord::Base
user,
owner ? :user_added_to_group_as_owner : :user_added_to_group_as_member,
group_name: name_full_preferred,
- group_path: "/g/#{self.name}"
+ group_path: "/g/#{self.name}",
)
end
@@ -1005,21 +1043,25 @@ class Group < ActiveRecord::Base
self.name = stripped
end
- UsernameValidator.perform_validation(self, 'name') || begin
- normalized_name = User.normalize_username(self.name)
+ UsernameValidator.perform_validation(self, "name") ||
+ begin
+ normalized_name = User.normalize_username(self.name)
- if self.will_save_change_to_name? && User.normalize_username(self.name_was) != normalized_name && User.username_exists?(self.name)
- errors.add(:name, I18n.t("activerecord.errors.messages.taken"))
+ if self.will_save_change_to_name? &&
+ User.normalize_username(self.name_was) != normalized_name &&
+ User.username_exists?(self.name)
+ errors.add(:name, I18n.t("activerecord.errors.messages.taken"))
+ end
end
- end
end
def automatic_membership_email_domains_format_validator
return if self.automatic_membership_email_domains.blank?
- domains = Group.get_valid_email_domains(self.automatic_membership_email_domains) do |domain|
- self.errors.add :base, (I18n.t('groups.errors.invalid_domain', domain: domain))
- end
+ domains =
+ Group.get_valid_email_domains(self.automatic_membership_email_domains) do |domain|
+ self.errors.add :base, (I18n.t("groups.errors.invalid_domain", domain: domain))
+ end
self.automatic_membership_email_domains = domains.join("|")
end
@@ -1029,7 +1071,11 @@ class Group < ActiveRecord::Base
if @deletions
@deletions.each do |gu|
gu.destroy
- User.where('id = ? AND primary_group_id = ?', gu.user_id, gu.group_id).update_all 'primary_group_id = NULL'
+ User.where(
+ "id = ? AND primary_group_id = ?",
+ gu.user_id,
+ gu.group_id,
+ ).update_all "primary_group_id = NULL"
end
end
@deletions = nil
@@ -1067,7 +1113,7 @@ class Group < ActiveRecord::Base
/*where*/
SQL
- [:primary_group_id, :flair_group_id].each do |column|
+ %i[primary_group_id flair_group_id].each do |column|
builder = DB.build(sql)
builder.where(<<~SQL, id: id)
id IN (
@@ -1091,10 +1137,19 @@ class Group < ActiveRecord::Base
end
def self.automatic_membership_users(domains, group_id = nil)
- pattern = "@(#{domains.gsub('.', '\.')})$"
+ pattern = "@(#{domains.gsub(".", '\.')})$"
- users = User.joins(:user_emails).where("user_emails.email ~* ?", pattern).activated.where(staged: false)
- users = users.where("users.id NOT IN (SELECT user_id FROM group_users WHERE group_users.group_id = ?)", group_id) if group_id.present?
+ users =
+ User
+ .joins(:user_emails)
+ .where("user_emails.email ~* ?", pattern)
+ .activated
+ .where(staged: false)
+ users =
+ users.where(
+ "users.id NOT IN (SELECT user_id FROM group_users WHERE group_users.group_id = ?)",
+ group_id,
+ ) if group_id.present?
users
end
@@ -1102,16 +1157,18 @@ class Group < ActiveRecord::Base
def self.get_valid_email_domains(value)
valid_domains = []
- value.split("|").each do |domain|
- domain.sub!(/^https?:\/\//, '')
- domain.sub!(/\/.*$/, '')
+ value
+ .split("|")
+ .each do |domain|
+ domain.sub!(%r{^https?://}, "")
+ domain.sub!(%r{/.*$}, "")
- if domain =~ Group::VALID_DOMAIN_REGEX
- valid_domains << domain
- else
- yield domain if block_given?
+ if domain =~ Group::VALID_DOMAIN_REGEX
+ valid_domains << domain
+ else
+ yield domain if block_given?
+ end
end
- end
valid_domains
end
@@ -1120,10 +1177,10 @@ class Group < ActiveRecord::Base
def validate_grant_trust_level
unless TrustLevel.valid?(self.grant_trust_level)
- self.errors.add(:base, I18n.t(
- 'groups.errors.grant_trust_level_not_valid',
- trust_level: self.grant_trust_level
- ))
+ self.errors.add(
+ :base,
+ I18n.t("groups.errors.grant_trust_level_not_valid", trust_level: self.grant_trust_level),
+ )
end
end
@@ -1137,15 +1194,14 @@ class Group < ActiveRecord::Base
self.group_users.any?(&:owner)
end
- if !valid
- self.errors.add(:base, I18n.t('groups.errors.cant_allow_membership_requests'))
- end
+ self.errors.add(:base, I18n.t("groups.errors.cant_allow_membership_requests")) if !valid
end
def enqueue_update_mentions_job
- Jobs.enqueue(:update_group_mentions,
+ Jobs.enqueue(
+ :update_group_mentions,
previous_name: self.name_before_last_save,
- group_id: self.id
+ group_id: self.id,
)
end
end
diff --git a/app/models/group_archived_message.rb b/app/models/group_archived_message.rb
index 72d71af025c..30d9feb5ce7 100644
--- a/app/models/group_archived_message.rb
+++ b/app/models/group_archived_message.rb
@@ -15,7 +15,7 @@ class GroupArchivedMessage < ActiveRecord::Base
:group_pm_update_summary,
group_id: group_id,
topic_id: topic_id,
- acting_user_id: opts[:acting_user_id]
+ acting_user_id: opts[:acting_user_id],
)
end
@@ -31,20 +31,19 @@ class GroupArchivedMessage < ActiveRecord::Base
:group_pm_update_summary,
group_id: group_id,
topic_id: topic_id,
- acting_user_id: opts[:acting_user_id]
+ acting_user_id: opts[:acting_user_id],
)
end
def self.trigger(event, group_id, topic_id)
group = Group.find_by(id: group_id)
topic = Topic.find_by(id: topic_id)
- if group && topic
- DiscourseEvent.trigger(event, group: group, topic: topic)
- end
+ DiscourseEvent.trigger(event, group: group, topic: topic) if group && topic
end
def self.set_imap_sync(topic_id)
- IncomingEmail.joins(:post)
+ IncomingEmail
+ .joins(:post)
.where.not(imap_uid: nil)
.where(topic_id: topic_id, posts: { post_number: 1 })
.update_all(imap_sync: true)
@@ -55,7 +54,7 @@ class GroupArchivedMessage < ActiveRecord::Base
PrivateMessageTopicTrackingState.publish_group_archived(
topic: topic,
group_id: group_id,
- acting_user_id: acting_user_id
+ acting_user_id: acting_user_id,
)
end
private_class_method :publish_topic_tracking_state
diff --git a/app/models/group_associated_group.rb b/app/models/group_associated_group.rb
index be71f09eb08..4e9f963fbd1 100644
--- a/app/models/group_associated_group.rb
+++ b/app/models/group_associated_group.rb
@@ -3,22 +3,22 @@ class GroupAssociatedGroup < ActiveRecord::Base
belongs_to :group
belongs_to :associated_group
- after_commit :add_associated_users, on: [:create, :update]
+ after_commit :add_associated_users, on: %i[create update]
before_destroy :remove_associated_users
def add_associated_users
with_mutex do
associated_group.users.in_batches do |users|
- users.each do |user|
- group.add_automatically(user, subject: associated_group.label)
- end
+ users.each { |user| group.add_automatically(user, subject: associated_group.label) }
end
end
end
def remove_associated_users
with_mutex do
- User.where("NOT EXISTS(
+ User
+ .where(
+ "NOT EXISTS(
SELECT 1
FROM user_associated_groups uag
JOIN group_associated_groups gag
@@ -26,11 +26,13 @@ class GroupAssociatedGroup < ActiveRecord::Base
WHERE uag.user_id = users.id
AND gag.id != :gag_id
AND gag.group_id = :group_id
- )", gag_id: id, group_id: group_id).in_batches do |users|
- users.each do |user|
- group.remove_automatically(user, subject: associated_group.label)
+ )",
+ gag_id: id,
+ group_id: group_id,
+ )
+ .in_batches do |users|
+ users.each { |user| group.remove_automatically(user, subject: associated_group.label) }
end
- end
end
end
diff --git a/app/models/group_category_notification_default.rb b/app/models/group_category_notification_default.rb
index 858ef422b51..b75183ef1fd 100644
--- a/app/models/group_category_notification_default.rb
+++ b/app/models/group_category_notification_default.rb
@@ -19,28 +19,24 @@ class GroupCategoryNotificationDefault < ActiveRecord::Base
changed = false
# Update pre-existing
- if category_ids.present? && GroupCategoryNotificationDefault
- .where(group_id: group.id, category_id: category_ids)
- .where.not(notification_level: level_num)
- .update_all(notification_level: level_num) > 0
-
+ if category_ids.present? &&
+ GroupCategoryNotificationDefault
+ .where(group_id: group.id, category_id: category_ids)
+ .where.not(notification_level: level_num)
+ .update_all(notification_level: level_num) > 0
changed = true
end
# Remove extraneous category users
if GroupCategoryNotificationDefault
- .where(group_id: group.id, notification_level: level_num)
- .where.not(category_id: category_ids)
- .delete_all > 0
-
+ .where(group_id: group.id, notification_level: level_num)
+ .where.not(category_id: category_ids)
+ .delete_all > 0
changed = true
end
if category_ids.present?
- params = {
- group_id: group.id,
- level_num: level_num,
- }
+ params = { group_id: group.id, level_num: level_num }
sql = <<~SQL
INSERT INTO group_category_notification_defaults (group_id, category_id, notification_level)
@@ -52,9 +48,7 @@ class GroupCategoryNotificationDefault < ActiveRecord::Base
# into the query, plus it is a bit of a micro optimisation
category_ids.each do |category_id|
params[:category_id] = category_id
- if DB.exec(sql, params) > 0
- changed = true
- end
+ changed = true if DB.exec(sql, params) > 0
end
end
diff --git a/app/models/group_history.rb b/app/models/group_history.rb
index 83583824a6c..9f58072e581 100644
--- a/app/models/group_history.rb
+++ b/app/models/group_history.rb
@@ -2,43 +2,43 @@
class GroupHistory < ActiveRecord::Base
belongs_to :group
- belongs_to :acting_user, class_name: 'User'
- belongs_to :target_user, class_name: 'User'
+ belongs_to :acting_user, class_name: "User"
+ belongs_to :target_user, class_name: "User"
validates :acting_user_id, presence: true
validates :group_id, presence: true
validates :action, presence: true
def self.actions
- @actions ||= Enum.new(
- change_group_setting: 1,
- add_user_to_group: 2,
- remove_user_from_group: 3,
- make_user_group_owner: 4,
- remove_user_as_group_owner: 5
- )
+ @actions ||=
+ Enum.new(
+ change_group_setting: 1,
+ add_user_to_group: 2,
+ remove_user_from_group: 3,
+ make_user_group_owner: 4,
+ remove_user_as_group_owner: 5,
+ )
end
def self.filters
- [
- :acting_user,
- :target_user,
- :action,
- :subject
- ]
+ %i[acting_user target_user action subject]
end
def self.with_filters(group, params = {})
- records = self.includes(:acting_user, :target_user)
- .where(group_id: group.id)
- .order('group_histories.created_at DESC')
+ records =
+ self
+ .includes(:acting_user, :target_user)
+ .where(group_id: group.id)
+ .order("group_histories.created_at DESC")
if !params.blank?
params = params.slice(*filters)
- records = records.where(action: self.actions[params[:action].to_sym]) unless params[:action].blank?
+ records = records.where(action: self.actions[params[:action].to_sym]) unless params[
+ :action
+ ].blank?
records = records.where(subject: params[:subject]) unless params[:subject].blank?
- [:acting_user, :target_user].each do |filter|
+ %i[acting_user target_user].each do |filter|
unless params[filter].blank?
id = User.where(username_lower: params[filter]).pluck(:id)
records = records.where("#{filter}_id" => id)
diff --git a/app/models/group_tag_notification_default.rb b/app/models/group_tag_notification_default.rb
index a72d554b5be..312dd2bd68e 100644
--- a/app/models/group_tag_notification_default.rb
+++ b/app/models/group_tag_notification_default.rb
@@ -21,15 +21,16 @@ class GroupTagNotificationDefault < ActiveRecord::Base
tag_ids = tag_names.empty? ? [] : Tag.where_name(tag_names).pluck(:id)
- Tag.where_name(tag_names).joins(:target_tag).each do |tag|
- tag_ids[tag_ids.index(tag.id)] = tag.target_tag_id
- end
+ Tag
+ .where_name(tag_names)
+ .joins(:target_tag)
+ .each { |tag| tag_ids[tag_ids.index(tag.id)] = tag.target_tag_id }
tag_ids.uniq!
remove = (old_ids - tag_ids)
if remove.present?
- records.where('tag_id in (?)', remove).destroy_all
+ records.where("tag_id in (?)", remove).destroy_all
changed = true
end
diff --git a/app/models/group_user.rb b/app/models/group_user.rb
index 1c5df59922e..cfd27f01f39 100644
--- a/app/models/group_user.rb
+++ b/app/models/group_user.rb
@@ -29,7 +29,8 @@ class GroupUser < ActiveRecord::Base
def self.update_first_unread_pm(last_seen, limit: 10_000)
whisperers_group_ids = SiteSetting.whispers_allowed_group_ids
- DB.exec(<<~SQL, archetype: Archetype.private_message, last_seen: last_seen, limit: limit, now: 10.minutes.ago, whisperers_group_ids: whisperers_group_ids)
+ DB.exec(
+ <<~SQL,
UPDATE group_users gu
SET first_unread_pm_at = Y.min_date
FROM (
@@ -56,7 +57,7 @@ class GroupUser < ActiveRecord::Base
WHERE t.deleted_at IS NULL
AND t.archetype = :archetype
AND tu.last_read_post_number < CASE
- WHEN u.admin OR u.moderator #{whisperers_group_ids.present? ? 'OR gu2.group_id IN (:whisperers_group_ids)' : ''}
+ WHEN u.admin OR u.moderator #{whisperers_group_ids.present? ? "OR gu2.group_id IN (:whisperers_group_ids)" : ""}
THEN t.highest_staff_post_number
ELSE t.highest_post_number
END
@@ -75,6 +76,12 @@ class GroupUser < ActiveRecord::Base
) Y
WHERE gu.user_id = Y.user_id AND gu.group_id = Y.group_id
SQL
+ archetype: Archetype.private_message,
+ last_seen: last_seen,
+ limit: limit,
+ now: 10.minutes.ago,
+ whisperers_group_ids: whisperers_group_ids,
+ )
end
protected
@@ -105,10 +112,12 @@ class GroupUser < ActiveRecord::Base
def update_title
if group.title.present?
- DB.exec("
+ DB.exec(
+ "
UPDATE users SET title = :title
WHERE (title IS NULL OR title = '') AND id = :id",
- id: user_id, title: group.title
+ id: user_id,
+ title: group.title,
)
end
end
@@ -131,28 +140,34 @@ class GroupUser < ActiveRecord::Base
end
def self.set_category_notifications(group, user)
- group_levels = group.group_category_notification_defaults.each_with_object({}) do |r, h|
- h[r.notification_level] ||= []
- h[r.notification_level] << r.category_id
- end
+ group_levels =
+ group
+ .group_category_notification_defaults
+ .each_with_object({}) do |r, h|
+ h[r.notification_level] ||= []
+ h[r.notification_level] << r.category_id
+ end
return if group_levels.empty?
- user_levels = CategoryUser.where(user_id: user.id).each_with_object({}) do |r, h|
- h[r.notification_level] ||= []
- h[r.notification_level] << r.category_id
- end
+ user_levels =
+ CategoryUser
+ .where(user_id: user.id)
+ .each_with_object({}) do |r, h|
+ h[r.notification_level] ||= []
+ h[r.notification_level] << r.category_id
+ end
higher_level_category_ids = user_levels.values.flatten
- [:muted, :regular, :tracking, :watching_first_post, :watching].each do |level|
+ %i[muted regular tracking watching_first_post watching].each do |level|
level_num = NotificationLevels.all[level]
higher_level_category_ids -= (user_levels[level_num] || [])
if group_category_ids = group_levels[level_num]
CategoryUser.batch_set(
user,
level,
- group_category_ids + (user_levels[level_num] || []) - higher_level_category_ids
+ group_category_ids + (user_levels[level_num] || []) - higher_level_category_ids,
)
end
end
@@ -163,28 +178,34 @@ class GroupUser < ActiveRecord::Base
end
def self.set_tag_notifications(group, user)
- group_levels = group.group_tag_notification_defaults.each_with_object({}) do |r, h|
- h[r.notification_level] ||= []
- h[r.notification_level] << r.tag_id
- end
+ group_levels =
+ group
+ .group_tag_notification_defaults
+ .each_with_object({}) do |r, h|
+ h[r.notification_level] ||= []
+ h[r.notification_level] << r.tag_id
+ end
return if group_levels.empty?
- user_levels = TagUser.where(user_id: user.id).each_with_object({}) do |r, h|
- h[r.notification_level] ||= []
- h[r.notification_level] << r.tag_id
- end
+ user_levels =
+ TagUser
+ .where(user_id: user.id)
+ .each_with_object({}) do |r, h|
+ h[r.notification_level] ||= []
+ h[r.notification_level] << r.tag_id
+ end
higher_level_tag_ids = user_levels.values.flatten
- [:muted, :regular, :tracking, :watching_first_post, :watching].each do |level|
+ %i[muted regular tracking watching_first_post watching].each do |level|
level_num = NotificationLevels.all[level]
higher_level_tag_ids -= (user_levels[level_num] || [])
if group_tag_ids = group_levels[level_num]
TagUser.batch_set(
user,
level,
- group_tag_ids + (user_levels[level_num] || []) - higher_level_tag_ids
+ group_tag_ids + (user_levels[level_num] || []) - higher_level_tag_ids,
)
end
end
diff --git a/app/models/imap_sync_log.rb b/app/models/imap_sync_log.rb
index e1073dcd16a..28f216c4cb2 100644
--- a/app/models/imap_sync_log.rb
+++ b/app/models/imap_sync_log.rb
@@ -12,14 +12,18 @@ class ImapSyncLog < ActiveRecord::Base
def self.log(message, level, group_id = nil, db = true)
now = Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")
- new_log = if db
- create(message: message, level: ImapSyncLog.levels[level], group_id: group_id)
- end
+ new_log = (create(message: message, level: ImapSyncLog.levels[level], group_id: group_id) if db)
if ENV["DEBUG_IMAP"]
- Rails.logger.send(:warn, "#{level[0].upcase}, [#{now}] [IMAP] (group_id #{group_id}) #{message}")
+ Rails.logger.send(
+ :warn,
+ "#{level[0].upcase}, [#{now}] [IMAP] (group_id #{group_id}) #{message}",
+ )
else
- Rails.logger.send(level, "#{level[0].upcase}, [#{now}] [IMAP] (group_id #{group_id}) #{message}")
+ Rails.logger.send(
+ level,
+ "#{level[0].upcase}, [#{now}] [IMAP] (group_id #{group_id}) #{message}",
+ )
end
new_log
diff --git a/app/models/incoming_domain.rb b/app/models/incoming_domain.rb
index e9ef69ffaac..94d56cecd9f 100644
--- a/app/models/incoming_domain.rb
+++ b/app/models/incoming_domain.rb
@@ -25,9 +25,7 @@ class IncomingDomain < ActiveRecord::Base
def to_url
url = +"http#{https ? "s" : ""}://#{name}"
- if https && port != 443 || !https && port != 80
- url << ":#{port}"
- end
+ url << ":#{port}" if https && port != 443 || !https && port != 80
url
end
diff --git a/app/models/incoming_email.rb b/app/models/incoming_email.rb
index b33ae191a8a..f565bbce67c 100644
--- a/app/models/incoming_email.rb
+++ b/app/models/incoming_email.rb
@@ -4,22 +4,19 @@ class IncomingEmail < ActiveRecord::Base
belongs_to :user
belongs_to :topic
belongs_to :post
- belongs_to :group, foreign_key: :imap_group_id, class_name: 'Group'
+ belongs_to :group, foreign_key: :imap_group_id, class_name: "Group"
validates :created_via, presence: true
- scope :errored, -> { where("NOT is_bounce AND error IS NOT NULL") }
+ scope :errored, -> { where("NOT is_bounce AND error IS NOT NULL") }
- scope :addressed_to, -> (email) do
- where(<<~SQL, email: "%#{email}%")
+ scope :addressed_to, ->(email) { where(<<~SQL, email: "%#{email}%") }
incoming_emails.from_address = :email OR
incoming_emails.to_addresses ILIKE :email OR
incoming_emails.cc_addresses ILIKE :email
SQL
- end
- scope :addressed_to_user, ->(user) do
- where(<<~SQL, user_id: user.id)
+ scope :addressed_to_user, ->(user) { where(<<~SQL, user_id: user.id) }
EXISTS(
SELECT 1
FROM user_emails
@@ -29,18 +26,11 @@ class IncomingEmail < ActiveRecord::Base
incoming_emails.cc_addresses ILIKE '%' || user_emails.email || '%')
)
SQL
- end
scope :without_raw, -> { select(self.column_names - ["raw"]) }
def self.created_via_types
- @types ||= Enum.new(
- unknown: 0,
- handle_mail: 1,
- pop3_poll: 2,
- imap: 3,
- group_smtp: 4
- )
+ @types ||= Enum.new(unknown: 0, handle_mail: 1, pop3_poll: 2, imap: 3, group_smtp: 4)
end
def as_mail_message
@@ -64,23 +54,17 @@ class IncomingEmail < ActiveRecord::Base
end
def to_addresses=(to)
- if to&.is_a?(Array)
- to = to.map(&:downcase).join(";")
- end
+ to = to.map(&:downcase).join(";") if to&.is_a?(Array)
super(to)
end
def cc_addresses=(cc)
- if cc&.is_a?(Array)
- cc = cc.map(&:downcase).join(";")
- end
+ cc = cc.map(&:downcase).join(";") if cc&.is_a?(Array)
super(cc)
end
def from_address=(from)
- if from&.is_a?(Array)
- from = from.first
- end
+ from = from.first if from&.is_a?(Array)
super(from)
end
end
diff --git a/app/models/incoming_link.rb b/app/models/incoming_link.rb
index 4e51a668231..acb7d0b3955 100644
--- a/app/models/incoming_link.rb
+++ b/app/models/incoming_link.rb
@@ -35,35 +35,32 @@ class IncomingLink < ActiveRecord::Base
end
if host != opts[:host] && (user_id || referer)
-
post_id = opts[:post_id]
- post_id ||= Post.where(topic_id: opts[:topic_id],
- post_number: opts[:post_number] || 1)
- .pluck_first(:id)
+ post_id ||=
+ Post.where(topic_id: opts[:topic_id], post_number: opts[:post_number] || 1).pluck_first(:id)
cid = current_user ? (current_user.id) : (nil)
ip_address = nil if cid
unless cid && cid == user_id
-
- create(referer: referer,
- user_id: user_id,
- post_id: post_id,
- current_user_id: cid,
- ip_address: ip_address) if post_id
-
+ if post_id
+ create(
+ referer: referer,
+ user_id: user_id,
+ post_id: post_id,
+ current_user_id: cid,
+ ip_address: ip_address,
+ )
+ end
end
end
-
end
def referer=(referer)
self.incoming_referer_id = nil
# will set incoming_referer_id
- unless referer.present?
- return
- end
+ return unless referer.present?
parsed = URI.parse(referer)
@@ -73,7 +70,6 @@ class IncomingLink < ActiveRecord::Base
referer_record = IncomingReferer.add!(path: parsed.path, incoming_domain: domain) if domain
self.incoming_referer_id = referer_record.id if referer_record
end
-
rescue URI::Error
# ignore
end
@@ -85,19 +81,23 @@ class IncomingLink < ActiveRecord::Base
end
def domain
- if incoming_referer
- incoming_referer.incoming_domain.name
- end
+ incoming_referer.incoming_domain.name if incoming_referer
end
# Internal: Update appropriate link counts.
def update_link_counts
- DB.exec("UPDATE topics
+ DB.exec(
+ "UPDATE topics
SET incoming_link_count = incoming_link_count + 1
- WHERE id = (SELECT topic_id FROM posts where id = ?)", post_id)
- DB.exec("UPDATE posts
+ WHERE id = (SELECT topic_id FROM posts where id = ?)",
+ post_id,
+ )
+ DB.exec(
+ "UPDATE posts
SET incoming_link_count = incoming_link_count + 1
- WHERE id = ?", post_id)
+ WHERE id = ?",
+ post_id,
+ )
end
protected
@@ -106,7 +106,7 @@ class IncomingLink < ActiveRecord::Base
return true unless referer
if (referer.length < 3 || referer.length > 100) || (domain.length < 1 || domain.length > 100)
# internal, no need to localize
- errors.add(:referer, 'referer is invalid')
+ errors.add(:referer, "referer is invalid")
false
else
true
diff --git a/app/models/incoming_links_report.rb b/app/models/incoming_links_report.rb
index e17f893a939..3c17ff38100 100644
--- a/app/models/incoming_links_report.rb
+++ b/app/models/incoming_links_report.rb
@@ -1,8 +1,14 @@
# frozen_string_literal: true
class IncomingLinksReport
-
- attr_accessor :type, :data, :y_titles, :start_date, :end_date, :limit, :category_id, :include_subcategories
+ attr_accessor :type,
+ :data,
+ :y_titles,
+ :start_date,
+ :end_date,
+ :limit,
+ :category_id,
+ :include_subcategories
def initialize(type)
@type = type
@@ -20,7 +26,7 @@ class IncomingLinksReport
ytitles: self.y_titles,
data: self.data,
start_date: start_date,
- end_date: end_date
+ end_date: end_date,
}
end
@@ -46,18 +52,31 @@ class IncomingLinksReport
report.y_titles[:num_clicks] = I18n.t("reports.#{report.type}.num_clicks")
report.y_titles[:num_topics] = I18n.t("reports.#{report.type}.num_topics")
- num_clicks = link_count_per_user(start_date: report.start_date, end_date: report.end_date, category_id: report.category_id, include_subcategories: report.include_subcategories)
- num_topics = topic_count_per_user(start_date: report.start_date, end_date: report.end_date, category_id: report.category_id, include_subcategories: report.include_subcategories)
- user_id_lookup = User
- .where(username: num_clicks.keys)
- .select(:id, :username, :uploaded_avatar_id)
- .inject({}) { |sum, v|
- sum[v.username] = {
- id: v.id,
- user_avatar_template: User.avatar_template(v.username, v.uploaded_avatar_id)
- }
- sum
- }
+ num_clicks =
+ link_count_per_user(
+ start_date: report.start_date,
+ end_date: report.end_date,
+ category_id: report.category_id,
+ include_subcategories: report.include_subcategories,
+ )
+ num_topics =
+ topic_count_per_user(
+ start_date: report.start_date,
+ end_date: report.end_date,
+ category_id: report.category_id,
+ include_subcategories: report.include_subcategories,
+ )
+ user_id_lookup =
+ User
+ .where(username: num_clicks.keys)
+ .select(:id, :username, :uploaded_avatar_id)
+ .inject({}) do |sum, v|
+ sum[v.username] = {
+ id: v.id,
+ user_avatar_template: User.avatar_template(v.username, v.uploaded_avatar_id),
+ }
+ sum
+ end
report.data = []
num_clicks.each_key do |username|
@@ -66,7 +85,7 @@ class IncomingLinksReport
user_id: user_id_lookup[username][:id],
user_avatar_template: user_id_lookup[username][:user_avatar_template],
num_clicks: num_clicks[username],
- num_topics: num_topics[username]
+ num_topics: num_topics[username],
}
end
report.data = report.data.sort_by { |x| x[:num_clicks] }.reverse[0, 10]
@@ -74,17 +93,31 @@ class IncomingLinksReport
def self.per_user(start_date:, end_date:, category_id:, include_subcategories:)
public_incoming_links(category_id: category_id, include_subcategories: include_subcategories)
- .where('incoming_links.created_at > ? AND incoming_links.created_at < ? AND incoming_links.user_id IS NOT NULL', start_date, end_date)
+ .where(
+ "incoming_links.created_at > ? AND incoming_links.created_at < ? AND incoming_links.user_id IS NOT NULL",
+ start_date,
+ end_date,
+ )
.joins(:user)
- .group('users.username')
+ .group("users.username")
end
def self.link_count_per_user(start_date:, end_date:, category_id:, include_subcategories:)
- per_user(start_date: start_date, end_date: end_date, category_id: category_id, include_subcategories: include_subcategories).count
+ per_user(
+ start_date: start_date,
+ end_date: end_date,
+ category_id: category_id,
+ include_subcategories: include_subcategories,
+ ).count
end
def self.topic_count_per_user(start_date:, end_date:, category_id:, include_subcategories:)
- per_user(start_date: start_date, end_date: end_date, category_id: category_id, include_subcategories: include_subcategories).joins(:post).count("DISTINCT posts.topic_id")
+ per_user(
+ start_date: start_date,
+ end_date: end_date,
+ category_id: category_id,
+ include_subcategories: include_subcategories,
+ ).joins(:post).count("DISTINCT posts.topic_id")
end
# Return top 10 domains that brought traffic to the site within the last 30 days
@@ -93,30 +126,58 @@ class IncomingLinksReport
report.y_titles[:num_topics] = I18n.t("reports.#{report.type}.num_topics")
report.y_titles[:num_users] = I18n.t("reports.#{report.type}.num_users")
- num_clicks = link_count_per_domain(start_date: report.start_date, end_date: report.end_date, category_id: report.category_id, include_subcategories: report.include_subcategories)
- num_topics = topic_count_per_domain(num_clicks.keys, category_id: report.category_id, include_subcategories: report.include_subcategories)
+ num_clicks =
+ link_count_per_domain(
+ start_date: report.start_date,
+ end_date: report.end_date,
+ category_id: report.category_id,
+ include_subcategories: report.include_subcategories,
+ )
+ num_topics =
+ topic_count_per_domain(
+ num_clicks.keys,
+ category_id: report.category_id,
+ include_subcategories: report.include_subcategories,
+ )
report.data = []
num_clicks.each_key do |domain|
- report.data << { domain: domain, num_clicks: num_clicks[domain], num_topics: num_topics[domain] }
+ report.data << {
+ domain: domain,
+ num_clicks: num_clicks[domain],
+ num_topics: num_topics[domain],
+ }
end
report.data = report.data.sort_by { |x| x[:num_clicks] }.reverse[0, 10]
end
- def self.link_count_per_domain(limit: 10, start_date:, end_date:, category_id:, include_subcategories:)
+ def self.link_count_per_domain(
+ limit: 10,
+ start_date:,
+ end_date:,
+ category_id:,
+ include_subcategories:
+ )
public_incoming_links(category_id: category_id, include_subcategories: include_subcategories)
- .where('incoming_links.created_at > ? AND incoming_links.created_at < ?', start_date, end_date)
+ .where(
+ "incoming_links.created_at > ? AND incoming_links.created_at < ?",
+ start_date,
+ end_date,
+ )
.joins(incoming_referer: :incoming_domain)
- .group('incoming_domains.name')
- .order('count_all DESC')
+ .group("incoming_domains.name")
+ .order("count_all DESC")
.limit(limit)
.count
end
def self.per_domain(domains, options = {})
- public_incoming_links(category_id: options[:category_id], include_subcategories: options[:include_subcategories])
+ public_incoming_links(
+ category_id: options[:category_id],
+ include_subcategories: options[:include_subcategories],
+ )
.joins(incoming_referer: :incoming_domain)
- .where('incoming_links.created_at > ? AND incoming_domains.name IN (?)', 30.days.ago, domains)
- .group('incoming_domains.name')
+ .where("incoming_links.created_at > ? AND incoming_domains.name IN (?)", 30.days.ago, domains)
+ .group("incoming_domains.name")
end
def self.topic_count_per_domain(domains, options = {})
@@ -126,17 +187,38 @@ class IncomingLinksReport
def self.report_top_referred_topics(report)
report.y_titles[:num_clicks] = I18n.t("reports.#{report.type}.labels.num_clicks")
- num_clicks = link_count_per_topic(start_date: report.start_date, end_date: report.end_date, category_id: report.category_id, include_subcategories: report.include_subcategories)
+ num_clicks =
+ link_count_per_topic(
+ start_date: report.start_date,
+ end_date: report.end_date,
+ category_id: report.category_id,
+ include_subcategories: report.include_subcategories,
+ )
num_clicks = num_clicks.to_a.sort_by { |x| x[1] }.last(report.limit || 10).reverse
report.data = []
- topics = Topic.select('id, slug, title').where('id in (?)', num_clicks.map { |z| z[0] })
+ topics = Topic.select("id, slug, title").where("id in (?)", num_clicks.map { |z| z[0] })
if report.category_id
- topics = topics.where(category_id: report.include_subcategories ? Category.subcategory_ids(report.category_id) : report.category_id)
+ topics =
+ topics.where(
+ category_id:
+ (
+ if report.include_subcategories
+ Category.subcategory_ids(report.category_id)
+ else
+ report.category_id
+ end
+ ),
+ )
end
num_clicks.each do |topic_id, num_clicks_element|
topic = topics.find { |t| t.id == topic_id }
if topic
- report.data << { topic_id: topic_id, topic_title: topic.title, topic_url: topic.relative_url, num_clicks: num_clicks_element }
+ report.data << {
+ topic_id: topic_id,
+ topic_title: topic.title,
+ topic_url: topic.relative_url,
+ num_clicks: num_clicks_element,
+ }
end
end
report.data
@@ -144,15 +226,17 @@ class IncomingLinksReport
def self.link_count_per_topic(start_date:, end_date:, category_id:, include_subcategories:)
public_incoming_links(category_id: category_id, include_subcategories: include_subcategories)
- .where('incoming_links.created_at > ? AND incoming_links.created_at < ? AND topic_id IS NOT NULL', start_date, end_date)
- .group('topic_id')
+ .where(
+ "incoming_links.created_at > ? AND incoming_links.created_at < ? AND topic_id IS NOT NULL",
+ start_date,
+ end_date,
+ )
+ .group("topic_id")
.count
end
def self.public_incoming_links(category_id: nil, include_subcategories: nil)
- links = IncomingLink
- .joins(post: :topic)
- .where("topics.archetype = ?", Archetype.default)
+ links = IncomingLink.joins(post: :topic).where("topics.archetype = ?", Archetype.default)
if category_id
if include_subcategories
diff --git a/app/models/invite.rb b/app/models/invite.rb
index 2712760ab1c..dae62e32317 100644
--- a/app/models/invite.rb
+++ b/app/models/invite.rb
@@ -1,25 +1,26 @@
# frozen_string_literal: true
class Invite < ActiveRecord::Base
- class UserExists < StandardError; end
- class RedemptionFailed < StandardError; end
- class ValidationFailed < StandardError; end
+ class UserExists < StandardError
+ end
+ class RedemptionFailed < StandardError
+ end
+ class ValidationFailed < StandardError
+ end
include RateLimiter::OnCreateRecord
include Trashable
# TODO(2021-05-22): remove
- self.ignored_columns = %w{
- user_id
- redeemed_at
- }
+ self.ignored_columns = %w[user_id redeemed_at]
BULK_INVITE_EMAIL_LIMIT = 200
- DOMAIN_REGEX = /\A(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)+([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/
+ DOMAIN_REGEX =
+ /\A(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)+([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/
rate_limit :limit_invites_per_day
- belongs_to :invited_by, class_name: 'User'
+ belongs_to :invited_by, class_name: "User"
has_many :invited_users
has_many :users, through: :invited_users
@@ -42,19 +43,16 @@ class Invite < ActiveRecord::Base
end
before_save do
- if will_save_change_to_email?
- self.email_token = email.present? ? SecureRandom.hex : nil
- end
+ self.email_token = email.present? ? SecureRandom.hex : nil if will_save_change_to_email?
end
- before_validation do
- self.email = Email.downcase(email) unless email.nil?
- end
+ before_validation { self.email = Email.downcase(email) unless email.nil? }
attribute :email_already_exists
def self.emailed_status_types
- @emailed_status_types ||= Enum.new(not_required: 0, pending: 1, bulk_pending: 2, sending: 3, sent: 4)
+ @emailed_status_types ||=
+ Enum.new(not_required: 0, pending: 1, bulk_pending: 2, sending: 3, sent: 4)
end
def user_doesnt_already_exist
@@ -69,9 +67,7 @@ class Invite < ActiveRecord::Base
end
def email_xor_domain
- if email.present? && domain.present?
- errors.add(:base, I18n.t('invite.email_xor_domain'))
- end
+ errors.add(:base, I18n.t("invite.email_xor_domain")) if email.present? && domain.present?
end
# Even if a domain is specified on the invite, it still counts as
@@ -107,7 +103,7 @@ class Invite < ActiveRecord::Base
end
def domain_matches?(email)
- _, domain = email.split('@')
+ _, domain = email.split("@")
self.domain == domain
end
@@ -124,8 +120,11 @@ class Invite < ActiveRecord::Base
end
def link(with_email_token: false)
- with_email_token ? "#{Discourse.base_url}/invites/#{invite_key}?t=#{email_token}"
- : "#{Discourse.base_url}/invites/#{invite_key}"
+ if with_email_token
+ "#{Discourse.base_url}/invites/#{invite_key}?t=#{email_token}"
+ else
+ "#{Discourse.base_url}/invites/#{invite_key}"
+ end
end
def link_valid?
@@ -140,11 +139,12 @@ class Invite < ActiveRecord::Base
raise UserExists.new(new.user_exists_error_msg(email)) if find_user_by_email(email)
if email.present?
- invite = Invite
- .with_deleted
- .where(email: email, invited_by_id: invited_by.id)
- .order('created_at DESC')
- .first
+ invite =
+ Invite
+ .with_deleted
+ .where(email: email, invited_by_id: invited_by.id)
+ .order("created_at DESC")
+ .first
if invite && (invite.expired? || invite.deleted_at)
invite.destroy
@@ -154,25 +154,27 @@ class Invite < ActiveRecord::Base
RateLimiter.new(invited_by, "reinvites-per-day-#{email_digest}", 3, 1.day.to_i).performed!
end
- emailed_status = if opts[:skip_email] || invite&.emailed_status == emailed_status_types[:not_required]
- emailed_status_types[:not_required]
- elsif opts[:emailed_status].present?
- opts[:emailed_status]
- elsif email.present?
- emailed_status_types[:pending]
- else
- emailed_status_types[:not_required]
- end
+ emailed_status =
+ if opts[:skip_email] || invite&.emailed_status == emailed_status_types[:not_required]
+ emailed_status_types[:not_required]
+ elsif opts[:emailed_status].present?
+ opts[:emailed_status]
+ elsif email.present?
+ emailed_status_types[:pending]
+ else
+ emailed_status_types[:not_required]
+ end
if invite
invite.update_columns(
created_at: Time.zone.now,
updated_at: Time.zone.now,
expires_at: opts[:expires_at] || SiteSetting.invite_expiry_days.days.from_now,
- emailed_status: emailed_status
+ emailed_status: emailed_status,
)
else
- create_args = opts.slice(:email, :domain, :moderator, :custom_message, :max_redemptions_allowed)
+ create_args =
+ opts.slice(:email, :domain, :moderator, :custom_message, :max_redemptions_allowed)
create_args[:invited_by] = invited_by
create_args[:email] = email
create_args[:emailed_status] = emailed_status
@@ -182,15 +184,11 @@ class Invite < ActiveRecord::Base
end
topic_id = opts[:topic]&.id || opts[:topic_id]
- if topic_id.present?
- invite.topic_invites.find_or_create_by!(topic_id: topic_id)
- end
+ invite.topic_invites.find_or_create_by!(topic_id: topic_id) if topic_id.present?
group_ids = opts[:group_ids]
if group_ids.present?
- group_ids.each do |group_id|
- invite.invited_groups.find_or_create_by!(group_id: group_id)
- end
+ group_ids.each { |group_id| invite.invited_groups.find_or_create_by!(group_id: group_id) }
end
if emailed_status == emailed_status_types[:pending]
@@ -224,7 +222,7 @@ class Invite < ActiveRecord::Base
ip_address: ip_address,
session: session,
email_token: email_token,
- redeeming_user: redeeming_user
+ redeeming_user: redeeming_user,
).redeem
end
@@ -241,35 +239,37 @@ class Invite < ActiveRecord::Base
end
def self.pending(inviter)
- Invite.distinct
+ Invite
+ .distinct
.joins("LEFT JOIN invited_users ON invites.id = invited_users.invite_id")
.joins("LEFT JOIN users ON invited_users.user_id = users.id")
.where(invited_by_id: inviter.id)
- .where('redemption_count < max_redemptions_allowed')
- .where('expires_at > ?', Time.zone.now)
- .order('invites.updated_at DESC')
+ .where("redemption_count < max_redemptions_allowed")
+ .where("expires_at > ?", Time.zone.now)
+ .order("invites.updated_at DESC")
end
def self.expired(inviter)
- Invite.distinct
+ Invite
+ .distinct
.joins("LEFT JOIN invited_users ON invites.id = invited_users.invite_id")
.joins("LEFT JOIN users ON invited_users.user_id = users.id")
.where(invited_by_id: inviter.id)
- .where('redemption_count < max_redemptions_allowed')
- .where('expires_at < ?', Time.zone.now)
- .order('invites.expires_at ASC')
+ .where("redemption_count < max_redemptions_allowed")
+ .where("expires_at < ?", Time.zone.now)
+ .order("invites.expires_at ASC")
end
def self.redeemed_users(inviter)
InvitedUser
.joins("LEFT JOIN invites ON invites.id = invited_users.invite_id")
.includes(user: :user_stat)
- .where('invited_users.user_id IS NOT NULL')
- .where('invites.invited_by_id = ?', inviter.id)
- .order('invited_users.redeemed_at DESC')
- .references('invite')
- .references('user')
- .references('user_stat')
+ .where("invited_users.user_id IS NOT NULL")
+ .where("invites.invited_by_id = ?", inviter.id)
+ .order("invited_users.redeemed_at DESC")
+ .references("invite")
+ .references("user")
+ .references("user_stat")
end
def self.invalidate_for_email(email)
@@ -280,7 +280,11 @@ class Invite < ActiveRecord::Base
end
def resend_invite
- self.update_columns(updated_at: Time.zone.now, invalidated_at: nil, expires_at: SiteSetting.invite_expiry_days.days.from_now)
+ self.update_columns(
+ updated_at: Time.zone.now,
+ invalidated_at: nil,
+ expires_at: SiteSetting.invite_expiry_days.days.from_now,
+ )
Jobs.enqueue(:invite_email, invite_id: self.id)
end
@@ -289,27 +293,48 @@ class Invite < ActiveRecord::Base
end
def self.base_directory
- File.join(Rails.root, "public", "uploads", "csv", RailsMultisite::ConnectionManagement.current_db)
+ File.join(
+ Rails.root,
+ "public",
+ "uploads",
+ "csv",
+ RailsMultisite::ConnectionManagement.current_db,
+ )
end
def ensure_max_redemptions_allowed
if self.max_redemptions_allowed.nil?
self.max_redemptions_allowed = 1
else
- limit = invited_by&.staff? ? SiteSetting.invite_link_max_redemptions_limit
- : SiteSetting.invite_link_max_redemptions_limit_users
+ limit =
+ (
+ if invited_by&.staff?
+ SiteSetting.invite_link_max_redemptions_limit
+ else
+ SiteSetting.invite_link_max_redemptions_limit_users
+ end
+ )
if self.email.present? && self.max_redemptions_allowed != 1
errors.add(:max_redemptions_allowed, I18n.t("invite.max_redemptions_allowed_one"))
elsif !self.max_redemptions_allowed.between?(1, limit)
- errors.add(:max_redemptions_allowed, I18n.t("invite_link.max_redemptions_limit", max_limit: limit))
+ errors.add(
+ :max_redemptions_allowed,
+ I18n.t("invite_link.max_redemptions_limit", max_limit: limit),
+ )
end
end
end
def valid_redemption_count
if self.redemption_count > self.max_redemptions_allowed
- errors.add(:redemption_count, I18n.t("invite.redemption_count_less_than_max", max_redemptions_allowed: self.max_redemptions_allowed))
+ errors.add(
+ :redemption_count,
+ I18n.t(
+ "invite.redemption_count_less_than_max",
+ max_redemptions_allowed: self.max_redemptions_allowed,
+ ),
+ )
end
end
@@ -319,7 +344,7 @@ class Invite < ActiveRecord::Base
self.domain.downcase!
if self.domain !~ Invite::DOMAIN_REGEX
- self.errors.add(:base, I18n.t('invite.domain_not_allowed'))
+ self.errors.add(:base, I18n.t("invite.domain_not_allowed"))
end
end
diff --git a/app/models/invite_redeemer.rb b/app/models/invite_redeemer.rb
index 6a7ae4b22a0..3fa9ac7313f 100644
--- a/app/models/invite_redeemer.rb
+++ b/app/models/invite_redeemer.rb
@@ -15,15 +15,15 @@
# (email IS NULL) on the Invite model.
class InviteRedeemer
attr_reader :invite,
- :email,
- :username,
- :name,
- :password,
- :user_custom_fields,
- :ip_address,
- :session,
- :email_token,
- :redeeming_user
+ :email,
+ :username,
+ :name,
+ :password,
+ :user_custom_fields,
+ :ip_address,
+ :session,
+ :email_token,
+ :redeeming_user
def initialize(
invite:,
@@ -35,7 +35,8 @@ class InviteRedeemer
ip_address: nil,
session: nil,
email_token: nil,
- redeeming_user: nil)
+ redeeming_user: nil
+ )
@invite = invite
@username = username
@name = name
@@ -81,8 +82,19 @@ class InviteRedeemer
# This will _never_ be called if there is a redeeming_user being passed
# in to InviteRedeemer -- see invited_user below.
- def self.create_user_from_invite(email:, invite:, username: nil, name: nil, password: nil, user_custom_fields: nil, ip_address: nil, session: nil, email_token: nil)
- if username && UsernameValidator.new(username).valid_format? && User.username_available?(username, email)
+ def self.create_user_from_invite(
+ email:,
+ invite:,
+ username: nil,
+ name: nil,
+ password: nil,
+ user_custom_fields: nil,
+ ip_address: nil,
+ session: nil,
+ email_token: nil
+ )
+ if username && UsernameValidator.new(username).valid_format? &&
+ User.username_available?(username, email)
available_username = username
else
available_username = UserNameSuggester.suggest(email)
@@ -99,12 +111,11 @@ class InviteRedeemer
active: false,
trust_level: SiteSetting.default_invitee_trust_level,
ip_address: ip_address,
- registration_ip_address: ip_address
+ registration_ip_address: ip_address,
}
if (!SiteSetting.must_approve_users && SiteSetting.invite_only) ||
- (SiteSetting.must_approve_users? && EmailValidator.can_auto_approve_user?(user.email))
-
+ (SiteSetting.must_approve_users? && EmailValidator.can_auto_approve_user?(user.email))
ReviewableUser.set_approved_fields!(user, Discourse.system_user)
end
@@ -115,7 +126,9 @@ class InviteRedeemer
user_fields.each do |f|
field_val = field_params[f.id.to_s]
- fields["#{User::USER_FIELD_PREFIX}#{f.id}"] = field_val[0...UserField.max_length] unless field_val.blank?
+ fields["#{User::USER_FIELD_PREFIX}#{f.id}"] = field_val[
+ 0...UserField.max_length
+ ] unless field_val.blank?
end
user.custom_fields = fields
end
@@ -143,9 +156,7 @@ class InviteRedeemer
authenticator.finish
if invite.emailed_status != Invite.emailed_status_types[:not_required] &&
- email == invite.email &&
- invite.email_token.present? &&
- email_token == invite.email_token
+ email == invite.email && invite.email_token.present? && email_token == invite.email_token
user.activate
end
@@ -159,9 +170,7 @@ class InviteRedeemer
return false if email.blank?
# Invite scoped to email has already been redeemed by anyone.
- if invite.is_email_invite? && InvitedUser.exists?(invite_id: invite.id)
- return false
- end
+ return false if invite.is_email_invite? && InvitedUser.exists?(invite_id: invite.id)
# The email will be present for either an invite link (where the user provides
# us the email manually) or for an invite scoped to an email, where we
@@ -171,17 +180,18 @@ class InviteRedeemer
email_to_check = redeeming_user&.email || email
if invite.email.present? && !invite.email_matches?(email_to_check)
- raise ActiveRecord::RecordNotSaved.new(I18n.t('invite.not_matching_email'))
+ raise ActiveRecord::RecordNotSaved.new(I18n.t("invite.not_matching_email"))
end
if invite.domain.present? && !invite.domain_matches?(email_to_check)
- raise ActiveRecord::RecordNotSaved.new(I18n.t('invite.domain_not_allowed'))
+ raise ActiveRecord::RecordNotSaved.new(I18n.t("invite.domain_not_allowed"))
end
# Anon user is trying to redeem an invitation, if an existing user already
# redeemed it then we cannot redeem now.
redeeming_user ||= User.where(admin: false, staged: false).find_by_email(email)
- if redeeming_user.present? && InvitedUser.exists?(user_id: redeeming_user.id, invite_id: invite.id)
+ if redeeming_user.present? &&
+ InvitedUser.exists?(user_id: redeeming_user.id, invite_id: invite.id)
return false
end
@@ -205,17 +215,18 @@ class InviteRedeemer
# If there was no logged in user then we must attempt to create
# one based on the provided params.
- invited_user ||= InviteRedeemer.create_user_from_invite(
- email: email,
- invite: invite,
- username: username,
- name: name,
- password: password,
- user_custom_fields: user_custom_fields,
- ip_address: ip_address,
- session: session,
- email_token: email_token
- )
+ invited_user ||=
+ InviteRedeemer.create_user_from_invite(
+ email: email,
+ invite: invite,
+ username: username,
+ name: name,
+ password: password,
+ user_custom_fields: user_custom_fields,
+ ip_address: ip_address,
+ session: session,
+ email_token: email_token,
+ )
invited_user.send_welcome_message = false
@invited_user = invited_user
@invited_user
@@ -243,11 +254,13 @@ class InviteRedeemer
# Should not happen because of ensure_email_is_present!, but better to cover bases.
return if email.blank?
- topic_ids = TopicInvite.joins(:invite)
- .joins(:topic)
- .where("topics.archetype = ?", Archetype::private_message)
- .where("invites.email = ?", email)
- .pluck(:topic_id)
+ topic_ids =
+ TopicInvite
+ .joins(:invite)
+ .joins(:topic)
+ .where("topics.archetype = ?", Archetype.private_message)
+ .where("invites.email = ?", email)
+ .pluck(:topic_id)
topic_ids.each do |id|
if !TopicAllowedUser.exists?(user_id: invited_user.id, topic_id: id)
TopicAllowedUser.create!(user_id: invited_user.id, topic_id: id)
@@ -277,7 +290,7 @@ class InviteRedeemer
return if invite.invited_by.blank?
invite.invited_by.notifications.create!(
notification_type: Notification.types[:invitee_accepted],
- data: { display_username: invited_user.username }.to_json
+ data: { display_username: invited_user.username }.to_json,
)
end
@@ -286,10 +299,10 @@ class InviteRedeemer
return if email.blank?
Invite
- .where('invites.max_redemptions_allowed = 1')
+ .where("invites.max_redemptions_allowed = 1")
.joins("LEFT JOIN invited_users ON invites.id = invited_users.invite_id")
- .where('invited_users.user_id IS NULL')
- .where('invites.email = ? AND invites.id != ?', email, invite.id)
+ .where("invited_users.user_id IS NULL")
+ .where("invites.email = ? AND invites.id != ?", email, invite.id)
.delete_all
end
end
diff --git a/app/models/like_notification_frequency_site_setting.rb b/app/models/like_notification_frequency_site_setting.rb
index 19d7043627d..5d8622e7b53 100644
--- a/app/models/like_notification_frequency_site_setting.rb
+++ b/app/models/like_notification_frequency_site_setting.rb
@@ -1,23 +1,20 @@
# frozen_string_literal: true
class LikeNotificationFrequencySiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
- val.to_i.to_s == val.to_s &&
- values.any? { |v| v[:value] == val.to_i }
+ val.to_i.to_s == val.to_s && values.any? { |v| v[:value] == val.to_i }
end
def self.values
@values ||= [
- { name: 'user.like_notification_frequency.always', value: 0 },
- { name: 'user.like_notification_frequency.first_time_and_daily', value: 1 },
- { name: 'user.like_notification_frequency.first_time', value: 2 },
- { name: 'user.like_notification_frequency.never', value: 3 },
+ { name: "user.like_notification_frequency.always", value: 0 },
+ { name: "user.like_notification_frequency.first_time_and_daily", value: 1 },
+ { name: "user.like_notification_frequency.first_time", value: 2 },
+ { name: "user.like_notification_frequency.never", value: 3 },
]
end
def self.translate_names?
true
end
-
end
diff --git a/app/models/locale_site_setting.rb b/app/models/locale_site_setting.rb
index 68431871648..8d48568d675 100644
--- a/app/models/locale_site_setting.rb
+++ b/app/models/locale_site_setting.rb
@@ -1,19 +1,16 @@
# frozen_string_literal: true
class LocaleSiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
supported_locales.include?(val)
end
def self.values
- @values ||= supported_locales.map do |locale|
- lang = language_names[locale] || language_names[locale.split("_")[0]]
- {
- name: lang ? lang['nativeName'] : locale,
- value: locale
- }
- end
+ @values ||=
+ supported_locales.map do |locale|
+ lang = language_names[locale] || language_names[locale.split("_")[0]]
+ { name: lang ? lang["nativeName"] : locale, value: locale }
+ end
end
@lock = Mutex.new
@@ -22,42 +19,41 @@ class LocaleSiteSetting < EnumSiteSetting
return @language_names if @language_names
@lock.synchronize do
- @language_names ||= begin
- names = YAML.safe_load(File.read(File.join(Rails.root, 'config', 'locales', 'names.yml')))
+ @language_names ||=
+ begin
+ names = YAML.safe_load(File.read(File.join(Rails.root, "config", "locales", "names.yml")))
- DiscoursePluginRegistry.locales.each do |locale, options|
- if !names.key?(locale) && options[:name] && options[:nativeName]
- names[locale] = { "name" => options[:name], "nativeName" => options[:nativeName] }
+ DiscoursePluginRegistry.locales.each do |locale, options|
+ if !names.key?(locale) && options[:name] && options[:nativeName]
+ names[locale] = { "name" => options[:name], "nativeName" => options[:nativeName] }
+ end
end
- end
- names
- end
+ names
+ end
end
end
def self.supported_locales
@lock.synchronize do
- @supported_locales ||= begin
- locales = Dir.glob(
- File.join(Rails.root, 'config', 'locales', 'client.*.yml')
- ).map { |x| x.split('.')[-2] }
+ @supported_locales ||=
+ begin
+ locales =
+ Dir
+ .glob(File.join(Rails.root, "config", "locales", "client.*.yml"))
+ .map { |x| x.split(".")[-2] }
- locales += DiscoursePluginRegistry.locales.keys
- locales.uniq.sort
- end
+ locales += DiscoursePluginRegistry.locales.keys
+ locales.uniq.sort
+ end
end
end
def self.reset!
- @lock.synchronize do
- @values = @language_names = @supported_locales = nil
- end
+ @lock.synchronize { @values = @language_names = @supported_locales = nil }
end
- FALLBACKS ||= {
- en_GB: :en
- }
+ FALLBACKS ||= { en_GB: :en }
def self.fallback_locale(locale)
fallback_locale = FALLBACKS[locale.to_sym]
diff --git a/app/models/mailing_list_mode_site_setting.rb b/app/models/mailing_list_mode_site_setting.rb
index 2192a6fbf7d..859b780dd39 100644
--- a/app/models/mailing_list_mode_site_setting.rb
+++ b/app/models/mailing_list_mode_site_setting.rb
@@ -2,14 +2,13 @@
class MailingListModeSiteSetting < EnumSiteSetting
def self.valid_value?(val)
- val.to_i.to_s == val.to_s &&
- values.any? { |v| v[:value] == val.to_i }
+ val.to_i.to_s == val.to_s && values.any? { |v| v[:value] == val.to_i }
end
def self.values
@values ||= [
- { name: 'user.mailing_list_mode.individual', value: 1 },
- { name: 'user.mailing_list_mode.individual_no_echo', value: 2 }
+ { name: "user.mailing_list_mode.individual", value: 1 },
+ { name: "user.mailing_list_mode.individual_no_echo", value: 2 },
]
end
diff --git a/app/models/muted_user.rb b/app/models/muted_user.rb
index 4be90200cd3..dd0a544c63d 100644
--- a/app/models/muted_user.rb
+++ b/app/models/muted_user.rb
@@ -2,7 +2,7 @@
class MutedUser < ActiveRecord::Base
belongs_to :user
- belongs_to :muted_user, class_name: 'User'
+ belongs_to :muted_user, class_name: "User"
end
# == Schema Information
diff --git a/app/models/navigation_menu_site_setting.rb b/app/models/navigation_menu_site_setting.rb
index d71cac2fdd2..bc7b38540de 100644
--- a/app/models/navigation_menu_site_setting.rb
+++ b/app/models/navigation_menu_site_setting.rb
@@ -13,7 +13,7 @@ class NavigationMenuSiteSetting < EnumSiteSetting
@values ||= [
{ name: "admin.navigation_menu.sidebar", value: SIDEBAR },
{ name: "admin.navigation_menu.header_dropdown", value: HEADER_DROPDOWN },
- { name: "admin.navigation_menu.legacy", value: LEGACY }
+ { name: "admin.navigation_menu.legacy", value: LEGACY },
]
end
diff --git a/app/models/new_topic_duration_site_setting.rb b/app/models/new_topic_duration_site_setting.rb
index 3ed58210ae8..e1f5b1fdae6 100644
--- a/app/models/new_topic_duration_site_setting.rb
+++ b/app/models/new_topic_duration_site_setting.rb
@@ -1,25 +1,22 @@
# frozen_string_literal: true
class NewTopicDurationSiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
- val.to_i.to_s == val.to_s &&
- values.any? { |v| v[:value] == val.to_i }
+ val.to_i.to_s == val.to_s && values.any? { |v| v[:value] == val.to_i }
end
def self.values
@values ||= [
- { name: 'user.new_topic_duration.not_viewed', value: -1 },
- { name: 'user.new_topic_duration.after_1_day', value: 60 * 24 },
- { name: 'user.new_topic_duration.after_2_days', value: 60 * 24 * 2 },
- { name: 'user.new_topic_duration.after_1_week', value: 60 * 24 * 7 },
- { name: 'user.new_topic_duration.after_2_weeks', value: 60 * 24 * 7 * 2 },
- { name: 'user.new_topic_duration.last_here', value: -2 },
+ { name: "user.new_topic_duration.not_viewed", value: -1 },
+ { name: "user.new_topic_duration.after_1_day", value: 60 * 24 },
+ { name: "user.new_topic_duration.after_2_days", value: 60 * 24 * 2 },
+ { name: "user.new_topic_duration.after_1_week", value: 60 * 24 * 7 },
+ { name: "user.new_topic_duration.after_2_weeks", value: 60 * 24 * 7 * 2 },
+ { name: "user.new_topic_duration.last_here", value: -2 },
]
end
def self.translate_names?
true
end
-
end
diff --git a/app/models/notification.rb b/app/models/notification.rb
index c4843a70e6f..f8aeab2b73d 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -12,48 +12,58 @@ class Notification < ActiveRecord::Base
validates_presence_of :notification_type
scope :unread, lambda { where(read: false) }
- scope :recent, lambda { |n = nil| n ||= 10; order('notifications.created_at desc').limit(n) }
- scope :visible , lambda { joins('LEFT JOIN topics ON notifications.topic_id = topics.id')
- .where('topics.id IS NULL OR topics.deleted_at IS NULL') }
- scope :unread_type, ->(user, type, limit = 30) do
- unread_types(user, [type], limit)
- end
- scope :unread_types, ->(user, types, limit = 30) do
- where(user_id: user.id, read: false, notification_type: types)
- .visible
- .includes(:topic)
- .limit(limit)
- end
- scope :prioritized, ->(deprioritized_types = []) do
- scope = order("notifications.high_priority AND NOT notifications.read DESC")
- if deprioritized_types.present?
- scope = scope.order(DB.sql_fragment("NOT notifications.read AND notifications.notification_type NOT IN (?) DESC", deprioritized_types))
- else
- scope = scope.order("NOT notifications.read DESC")
- end
- scope.order("notifications.created_at DESC")
- end
- scope :for_user_menu, ->(user_id, limit: 30) do
- where(user_id: user_id)
- .visible
- .prioritized
- .includes(:topic)
- .limit(limit)
- end
+ scope :recent,
+ lambda { |n = nil|
+ n ||= 10
+ order("notifications.created_at desc").limit(n)
+ }
+ scope :visible,
+ lambda {
+ joins("LEFT JOIN topics ON notifications.topic_id = topics.id").where(
+ "topics.id IS NULL OR topics.deleted_at IS NULL",
+ )
+ }
+ scope :unread_type, ->(user, type, limit = 30) { unread_types(user, [type], limit) }
+ scope :unread_types,
+ ->(user, types, limit = 30) {
+ where(user_id: user.id, read: false, notification_type: types)
+ .visible
+ .includes(:topic)
+ .limit(limit)
+ }
+ scope :prioritized,
+ ->(deprioritized_types = []) {
+ scope = order("notifications.high_priority AND NOT notifications.read DESC")
+ if deprioritized_types.present?
+ scope =
+ scope.order(
+ DB.sql_fragment(
+ "NOT notifications.read AND notifications.notification_type NOT IN (?) DESC",
+ deprioritized_types,
+ ),
+ )
+ else
+ scope = scope.order("NOT notifications.read DESC")
+ end
+ scope.order("notifications.created_at DESC")
+ }
+ scope :for_user_menu,
+ ->(user_id, limit: 30) {
+ where(user_id: user_id).visible.prioritized.includes(:topic).limit(limit)
+ }
attr_accessor :skip_send_email
- after_commit :refresh_notification_count, on: [:create, :update, :destroy]
+ after_commit :refresh_notification_count, on: %i[create update destroy]
after_commit :send_email, on: :create
- after_commit(on: :create) do
- DiscourseEvent.trigger(:notification_created, self)
- end
+ after_commit(on: :create) { DiscourseEvent.trigger(:notification_created, self) }
before_create do
# if we have manually set the notification to high_priority on create then
# make sure that is respected
- self.high_priority = self.high_priority || Notification.high_priority_types.include?(self.notification_type)
+ self.high_priority =
+ self.high_priority || Notification.high_priority_types.include?(self.notification_type)
end
def self.consolidate_or_create!(notification_params)
@@ -103,54 +113,53 @@ class Notification < ActiveRecord::Base
end
def self.types
- @types ||= Enum.new(mentioned: 1,
- replied: 2,
- quoted: 3,
- edited: 4,
- liked: 5,
- private_message: 6,
- invited_to_private_message: 7,
- invitee_accepted: 8,
- posted: 9,
- moved_post: 10,
- linked: 11,
- granted_badge: 12,
- invited_to_topic: 13,
- custom: 14,
- group_mentioned: 15,
- group_message_summary: 16,
- watching_first_post: 17,
- topic_reminder: 18,
- liked_consolidated: 19,
- post_approved: 20,
- code_review_commit_approved: 21,
- membership_request_accepted: 22,
- membership_request_consolidated: 23,
- bookmark_reminder: 24,
- reaction: 25,
- votes_released: 26,
- event_reminder: 27,
- event_invitation: 28,
- chat_mention: 29,
- chat_message: 30,
- chat_invitation: 31,
- chat_group_mention: 32, # March 2022 - This is obsolete, as all chat_mentions use `chat_mention` type
- chat_quoted: 33,
- assigned: 34,
- question_answer_user_commented: 35, # Used by https://github.com/discourse/discourse-question-answer
- watching_category_or_tag: 36,
- new_features: 37,
- following: 800, # Used by https://github.com/discourse/discourse-follow
- following_created_topic: 801, # Used by https://github.com/discourse/discourse-follow
- following_replied: 802, # Used by https://github.com/discourse/discourse-follow
- )
+ @types ||=
+ Enum.new(
+ mentioned: 1,
+ replied: 2,
+ quoted: 3,
+ edited: 4,
+ liked: 5,
+ private_message: 6,
+ invited_to_private_message: 7,
+ invitee_accepted: 8,
+ posted: 9,
+ moved_post: 10,
+ linked: 11,
+ granted_badge: 12,
+ invited_to_topic: 13,
+ custom: 14,
+ group_mentioned: 15,
+ group_message_summary: 16,
+ watching_first_post: 17,
+ topic_reminder: 18,
+ liked_consolidated: 19,
+ post_approved: 20,
+ code_review_commit_approved: 21,
+ membership_request_accepted: 22,
+ membership_request_consolidated: 23,
+ bookmark_reminder: 24,
+ reaction: 25,
+ votes_released: 26,
+ event_reminder: 27,
+ event_invitation: 28,
+ chat_mention: 29,
+ chat_message: 30,
+ chat_invitation: 31,
+ chat_group_mention: 32, # March 2022 - This is obsolete, as all chat_mentions use `chat_mention` type
+ chat_quoted: 33,
+ assigned: 34,
+ question_answer_user_commented: 35, # Used by https://github.com/discourse/discourse-question-answer
+ watching_category_or_tag: 36,
+ new_features: 37,
+ following: 800, # Used by https://github.com/discourse/discourse-follow
+ following_created_topic: 801, # Used by https://github.com/discourse/discourse-follow
+ following_replied: 802, # Used by https://github.com/discourse/discourse-follow
+ )
end
def self.high_priority_types
- @high_priority_types ||= [
- types[:private_message],
- types[:bookmark_reminder]
- ]
+ @high_priority_types ||= [types[:private_message], types[:bookmark_reminder]]
end
def self.normal_priority_types
@@ -158,24 +167,16 @@ class Notification < ActiveRecord::Base
end
def self.mark_posts_read(user, topic_id, post_numbers)
- Notification
- .where(
- user_id: user.id,
- topic_id: topic_id,
- post_number: post_numbers,
- read: false
- )
- .update_all(read: true)
+ Notification.where(
+ user_id: user.id,
+ topic_id: topic_id,
+ post_number: post_numbers,
+ read: false,
+ ).update_all(read: true)
end
def self.read(user, notification_ids)
- Notification
- .where(
- id: notification_ids,
- user_id: user.id,
- read: false
- )
- .update_all(read: true)
+ Notification.where(id: notification_ids, user_id: user.id, read: false).update_all(read: true)
end
def self.read_types(user, types = nil)
@@ -185,15 +186,19 @@ class Notification < ActiveRecord::Base
end
def self.interesting_after(min_date)
- result = where("created_at > ?", min_date)
- .includes(:topic)
- .visible
- .unread
- .limit(20)
- .order("CASE WHEN notification_type = #{Notification.types[:replied]} THEN 1
+ result =
+ where("created_at > ?", min_date)
+ .includes(:topic)
+ .visible
+ .unread
+ .limit(20)
+ .order(
+ "CASE WHEN notification_type = #{Notification.types[:replied]} THEN 1
WHEN notification_type = #{Notification.types[:mentioned]} THEN 2
ELSE 3
- END, created_at DESC").to_a
+ END, created_at DESC",
+ )
+ .to_a
# Remove any duplicates by type and topic
if result.present?
@@ -222,14 +227,15 @@ class Notification < ActiveRecord::Base
# Be wary of calling this frequently. O(n) JSON parsing can suck.
def data_hash
- @data_hash ||= begin
- return {} if data.blank?
+ @data_hash ||=
+ begin
+ return {} if data.blank?
- parsed = JSON.parse(data)
- return {} if parsed.blank?
+ parsed = JSON.parse(data)
+ return {} if parsed.blank?
- parsed.with_indifferent_access
- end
+ parsed.with_indifferent_access
+ end
end
def url
@@ -245,26 +251,27 @@ class Notification < ActiveRecord::Base
[
Notification.types[:liked],
Notification.types[:liked_consolidated],
- Notification.types[:reaction]
+ Notification.types[:reaction],
]
end
def self.prioritized_list(user, count: 30, types: [])
return [] if !user&.user_option
- notifications = user.notifications
- .includes(:topic)
- .visible
- .prioritized(types.present? ? [] : like_types)
- .limit(count)
+ notifications =
+ user
+ .notifications
+ .includes(:topic)
+ .visible
+ .prioritized(types.present? ? [] : like_types)
+ .limit(count)
if types.present?
notifications = notifications.where(notification_type: types)
- elsif user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:never]
+ elsif user.user_option.like_notification_frequency ==
+ UserOption.like_notification_frequency_type[:never]
like_types.each do |notification_type|
- notifications = notifications.where(
- 'notification_type <> ?', notification_type
- )
+ notifications = notifications.where("notification_type <> ?", notification_type)
end
end
notifications.to_a
@@ -275,20 +282,16 @@ class Notification < ActiveRecord::Base
return unless user && user.user_option
count ||= 10
- notifications = user.notifications
- .visible
- .recent(count)
- .includes(:topic)
+ notifications = user.notifications.visible.recent(count).includes(:topic)
notifications = notifications.where(notification_type: types) if types.present?
- if user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:never]
+ if user.user_option.like_notification_frequency ==
+ UserOption.like_notification_frequency_type[:never]
[
Notification.types[:liked],
- Notification.types[:liked_consolidated]
+ Notification.types[:liked_consolidated],
].each do |notification_type|
- notifications = notifications.where(
- 'notification_type <> ?', notification_type
- )
+ notifications = notifications.where("notification_type <> ?", notification_type)
end
end
@@ -313,27 +316,30 @@ class Notification < ActiveRecord::Base
ids = builder.query_single
if ids.length > 0
- notifications += user
- .notifications
- .order('notifications.created_at DESC')
- .where(id: ids)
- .joins(:topic)
- .limit(count)
+ notifications +=
+ user
+ .notifications
+ .order("notifications.created_at DESC")
+ .where(id: ids)
+ .joins(:topic)
+ .limit(count)
end
- notifications.uniq(&:id).sort do |x, y|
- if x.unread_high_priority? && !y.unread_high_priority?
- -1
- elsif y.unread_high_priority? && !x.unread_high_priority?
- 1
- else
- y.created_at <=> x.created_at
+ notifications
+ .uniq(&:id)
+ .sort do |x, y|
+ if x.unread_high_priority? && !y.unread_high_priority?
+ -1
+ elsif y.unread_high_priority? && !x.unread_high_priority?
+ 1
+ else
+ y.created_at <=> x.created_at
+ end
end
- end.take(count)
+ .take(count)
else
[]
end
-
end
def unread_high_priority?
@@ -347,19 +353,18 @@ class Notification < ActiveRecord::Base
protected
def refresh_notification_count
- if user_id
- User.find_by(id: user_id)&.publish_notifications_state
- end
+ User.find_by(id: user_id)&.publish_notifications_state if user_id
end
def send_email
return if skip_send_email
- user.do_not_disturb? ?
- ShelvedNotification.create(notification_id: self.id) :
+ if user.do_not_disturb?
+ ShelvedNotification.create(notification_id: self.id)
+ else
NotificationEmailer.process_notification(self)
+ end
end
-
end
# == Schema Information
diff --git a/app/models/notification_level_when_replying_site_setting.rb b/app/models/notification_level_when_replying_site_setting.rb
index c71927815fe..e12b97b6351 100644
--- a/app/models/notification_level_when_replying_site_setting.rb
+++ b/app/models/notification_level_when_replying_site_setting.rb
@@ -1,10 +1,8 @@
# frozen_string_literal: true
class NotificationLevelWhenReplyingSiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
- val.to_i.to_s == val.to_s &&
- values.any? { |v| v[:value] == val.to_i }
+ val.to_i.to_s == val.to_s && values.any? { |v| v[:value] == val.to_i }
end
def self.notification_levels
@@ -13,14 +11,13 @@ class NotificationLevelWhenReplyingSiteSetting < EnumSiteSetting
def self.values
@values ||= [
- { name: 'topic.notifications.watching.title', value: notification_levels[:watching] },
- { name: 'topic.notifications.tracking.title', value: notification_levels[:tracking] },
- { name: 'topic.notifications.regular.title', value: notification_levels[:regular] }
+ { name: "topic.notifications.watching.title", value: notification_levels[:watching] },
+ { name: "topic.notifications.tracking.title", value: notification_levels[:tracking] },
+ { name: "topic.notifications.regular.title", value: notification_levels[:regular] },
]
end
def self.translate_names?
true
end
-
end
diff --git a/app/models/oauth2_user_info.rb b/app/models/oauth2_user_info.rb
index bf758ee9118..34a9e62f564 100644
--- a/app/models/oauth2_user_info.rb
+++ b/app/models/oauth2_user_info.rb
@@ -4,7 +4,11 @@ class Oauth2UserInfo < ActiveRecord::Base
belongs_to :user
before_save do
- Discourse.deprecate("Oauth2UserInfo is deprecated. Use `ManagedAuthenticator` and `UserAssociatedAccount` instead. For more information, see https://meta.discourse.org/t/106695", drop_from: '2.9.0', output_in_test: true)
+ Discourse.deprecate(
+ "Oauth2UserInfo is deprecated. Use `ManagedAuthenticator` and `UserAssociatedAccount` instead. For more information, see https://meta.discourse.org/t/106695",
+ drop_from: "2.9.0",
+ output_in_test: true,
+ )
end
end
diff --git a/app/models/optimized_image.rb b/app/models/optimized_image.rb
index 901e762328f..dbfa6d10c66 100644
--- a/app/models/optimized_image.rb
+++ b/app/models/optimized_image.rb
@@ -6,7 +6,7 @@ class OptimizedImage < ActiveRecord::Base
# BUMP UP if optimized image algorithm changes
VERSION = 2
- URL_REGEX ||= /(\/optimized\/\dX[\/\.\w]*\/([a-zA-Z0-9]+)[\.\w]*)/
+ URL_REGEX ||= %r{(/optimized/\dX[/\.\w]*/([a-zA-Z0-9]+)[\.\w]*)}
def self.lock(upload_id, width, height)
@hostname ||= Discourse.os_hostname
@@ -15,14 +15,10 @@ class OptimizedImage < ActiveRecord::Base
#
# we can not afford this blocking in Sidekiq cause it can lead to starvation
if Sidekiq.server?
- DistributedMutex.synchronize("optimized_image_#{upload_id}_#{width}_#{height}") do
- yield
- end
+ DistributedMutex.synchronize("optimized_image_#{upload_id}_#{width}_#{height}") { yield }
else
DistributedMutex.synchronize("optimized_image_host_#{@hostname}") do
- DistributedMutex.synchronize("optimized_image_#{upload_id}_#{width}_#{height}") do
- yield
- end
+ DistributedMutex.synchronize("optimized_image_#{upload_id}_#{width}_#{height}") { yield }
end
end
end
@@ -32,9 +28,7 @@ class OptimizedImage < ActiveRecord::Base
return if upload.try(:sha1).blank?
# no extension so try to guess it
- if (!upload.extension)
- upload.fix_image_extension
- end
+ upload.fix_image_extension if (!upload.extension)
if !upload.extension.match?(IM_DECODERS) && upload.extension != "svg"
if !opts[:raise_on_error]
@@ -61,7 +55,12 @@ class OptimizedImage < ActiveRecord::Base
if original_path.blank?
# download is protected with a DistributedMutex
- external_copy = Discourse.store.download(upload) rescue nil
+ external_copy =
+ begin
+ Discourse.store.download(upload)
+ rescue StandardError
+ nil
+ end
original_path = external_copy.try(:path)
end
@@ -78,14 +77,13 @@ class OptimizedImage < ActiveRecord::Base
# create a temp file with the same extension as the original
extension = ".#{opts[:format] || upload.extension}"
- if extension.length == 1
- return nil
- end
+ return nil if extension.length == 1
temp_file = Tempfile.new(["discourse-thumbnail", extension])
temp_path = temp_file.path
- target_quality = upload.target_image_quality(original_path, SiteSetting.image_preview_jpg_quality)
+ target_quality =
+ upload.target_image_quality(original_path, SiteSetting.image_preview_jpg_quality)
opts = opts.merge(quality: target_quality) if target_quality
if upload.extension == "svg"
@@ -98,25 +96,29 @@ class OptimizedImage < ActiveRecord::Base
end
if resized
- thumbnail = OptimizedImage.create!(
- upload_id: upload.id,
- sha1: Upload.generate_digest(temp_path),
- extension: extension,
- width: width,
- height: height,
- url: "",
- filesize: File.size(temp_path),
- version: VERSION
- )
+ thumbnail =
+ OptimizedImage.create!(
+ upload_id: upload.id,
+ sha1: Upload.generate_digest(temp_path),
+ extension: extension,
+ width: width,
+ height: height,
+ url: "",
+ filesize: File.size(temp_path),
+ version: VERSION,
+ )
# store the optimized image and update its url
File.open(temp_path) do |file|
- url = Discourse.store.store_optimized_image(file, thumbnail, nil, secure: upload.secure?)
+ url =
+ Discourse.store.store_optimized_image(file, thumbnail, nil, secure: upload.secure?)
if url.present?
thumbnail.url = url
thumbnail.save
else
- Rails.logger.error("Failed to store optimized image of size #{width}x#{height} from url: #{upload.url}\nTemp image path: #{temp_path}")
+ Rails.logger.error(
+ "Failed to store optimized image of size #{width}x#{height} from url: #{upload.url}\nTemp image path: #{temp_path}",
+ )
end
end
end
@@ -126,9 +128,7 @@ class OptimizedImage < ActiveRecord::Base
end
# make sure we remove the cached copy from external stores
- if Discourse.store.external?
- external_copy&.close
- end
+ external_copy&.close if Discourse.store.external?
thumbnail
end
@@ -142,7 +142,7 @@ class OptimizedImage < ActiveRecord::Base
end
def local?
- !(url =~ /^(https?:)?\/\//)
+ !(url =~ %r{^(https?:)?//})
end
def calculate_filesize
@@ -162,9 +162,7 @@ class OptimizedImage < ActiveRecord::Base
size = calculate_filesize
write_attribute(:filesize, size)
- if !new_record?
- update_columns(filesize: size)
- end
+ update_columns(filesize: size) if !new_record?
size
end
end
@@ -173,14 +171,12 @@ class OptimizedImage < ActiveRecord::Base
# this matches instructions which call #to_s
path = path.to_s
return false if path != File.expand_path(path)
- return false if path !~ /\A[\w\-\.\/]+\z/m
+ return false if path !~ %r{\A[\w\-\./]+\z}m
true
end
def self.ensure_safe_paths!(*paths)
- paths.each do |path|
- raise Discourse::InvalidAccess unless safe_path?(path)
- end
+ paths.each { |path| raise Discourse::InvalidAccess unless safe_path?(path) }
end
IM_DECODERS ||= /\A(jpe?g|png|ico|gif|webp)\z/i
@@ -215,29 +211,35 @@ class OptimizedImage < ActiveRecord::Base
from = prepend_decoder!(from, to, opts)
to = prepend_decoder!(to, to, opts)
- instructions = ['convert', "#{from}[0]"]
+ instructions = ["convert", "#{from}[0]"]
- if opts[:colors]
- instructions << "-colors" << opts[:colors].to_s
- end
+ instructions << "-colors" << opts[:colors].to_s if opts[:colors]
- if opts[:quality]
- instructions << "-quality" << opts[:quality].to_s
- end
+ instructions << "-quality" << opts[:quality].to_s if opts[:quality]
# NOTE: ORDER is important!
- instructions.concat(%W{
- -auto-orient
- -gravity center
- -background transparent
- -#{thumbnail_or_resize} #{dimensions}^
- -extent #{dimensions}
- -interpolate catrom
- -unsharp 2x0.5+0.7+0
- -interlace none
- -profile #{File.join(Rails.root, 'vendor', 'data', 'RT_sRGB.icm')}
- #{to}
- })
+ instructions.concat(
+ %W[
+ -auto-orient
+ -gravity
+ center
+ -background
+ transparent
+ -#{thumbnail_or_resize}
+ #{dimensions}^
+ -extent
+ #{dimensions}
+ -interpolate
+ catrom
+ -unsharp
+ 2x0.5+0.7+0
+ -interlace
+ none
+ -profile
+ #{File.join(Rails.root, "vendor", "data", "RT_sRGB.icm")}
+ #{to}
+ ],
+ )
end
def self.crop_instructions(from, to, dimensions, opts = {})
@@ -250,18 +252,23 @@ class OptimizedImage < ActiveRecord::Base
convert
#{from}[0]
-auto-orient
- -gravity north
- -background transparent
- -#{thumbnail_or_resize} #{dimensions}^
- -crop #{dimensions}+0+0
- -unsharp 2x0.5+0.7+0
- -interlace none
- -profile #{File.join(Rails.root, 'vendor', 'data', 'RT_sRGB.icm')}
+ -gravity
+ north
+ -background
+ transparent
+ -#{thumbnail_or_resize}
+ #{dimensions}^
+ -crop
+ #{dimensions}+0+0
+ -unsharp
+ 2x0.5+0.7+0
+ -interlace
+ none
+ -profile
+ #{File.join(Rails.root, "vendor", "data", "RT_sRGB.icm")}
}
- if opts[:quality]
- instructions << "-quality" << opts[:quality].to_s
- end
+ instructions << "-quality" << opts[:quality].to_s if opts[:quality]
instructions << to
end
@@ -276,11 +283,16 @@ class OptimizedImage < ActiveRecord::Base
convert
#{from}[0]
-auto-orient
- -gravity center
- -background transparent
- -interlace none
- -resize #{dimensions}
- -profile #{File.join(Rails.root, 'vendor', 'data', 'RT_sRGB.icm')}
+ -gravity
+ center
+ -background
+ transparent
+ -interlace
+ none
+ -resize
+ #{dimensions}
+ -profile
+ #{File.join(Rails.root, "vendor", "data", "RT_sRGB.icm")}
#{to}
}
end
@@ -308,7 +320,13 @@ class OptimizedImage < ActiveRecord::Base
MAX_CONVERT_SECONDS = 20
def self.convert_with(instructions, to, opts = {})
- Discourse::Utils.execute_command("nice", "-n", "10", *instructions, timeout: MAX_CONVERT_SECONDS)
+ Discourse::Utils.execute_command(
+ "nice",
+ "-n",
+ "10",
+ *instructions,
+ timeout: MAX_CONVERT_SECONDS,
+ )
allow_pngquant = to.downcase.ends_with?(".png") && File.size(to) < MAX_PNGQUANT_SIZE
FileHelper.optimize_image!(to, allow_pngquant: allow_pngquant)
diff --git a/app/models/permalink.rb b/app/models/permalink.rb
index 11ea908d9f6..028313fcae2 100644
--- a/app/models/permalink.rb
+++ b/app/models/permalink.rb
@@ -15,15 +15,11 @@ class Permalink < ActiveRecord::Base
def initialize(source)
@source = source
- if source.present?
- @rules = source.split("|").map do |rule|
- parse_rule(rule)
- end.compact
- end
+ @rules = source.split("|").map { |rule| parse_rule(rule) }.compact if source.present?
end
def parse_rule(rule)
- return unless rule =~ /\/.*\//
+ return unless rule =~ %r{/.*/}
escaping = false
regex = +""
@@ -41,32 +37,27 @@ class Permalink < ActiveRecord::Base
end
end
- if regex.length > 1
- [Regexp.new(regex[1..-1]), sub[1..-1] || ""]
- end
-
+ [Regexp.new(regex[1..-1]), sub[1..-1] || ""] if regex.length > 1
end
def normalize(url)
return url unless @rules
- @rules.each do |(regex, sub)|
- url = url.sub(regex, sub)
- end
+ @rules.each { |(regex, sub)| url = url.sub(regex, sub) }
url
end
-
end
def self.normalize_url(url)
if url
url = url.strip
- url = url[1..-1] if url[0, 1] == '/'
+ url = url[1..-1] if url[0, 1] == "/"
end
normalizations = SiteSetting.permalink_normalizations
- @normalizer = Normalizer.new(normalizations) unless @normalizer && @normalizer.source == normalizations
+ @normalizer = Normalizer.new(normalizations) unless @normalizer &&
+ @normalizer.source == normalizations
@normalizer.normalize(url)
end
@@ -88,11 +79,10 @@ class Permalink < ActiveRecord::Base
end
def self.filter_by(url = nil)
- permalinks = Permalink
- .includes(:topic, :post, :category, :tag)
- .order('permalinks.created_at desc')
+ permalinks =
+ Permalink.includes(:topic, :post, :category, :tag).order("permalinks.created_at desc")
- permalinks.where!('url ILIKE :url OR external_url ILIKE :url', url: "%#{url}%") if url.present?
+ permalinks.where!("url ILIKE :url OR external_url ILIKE :url", url: "%#{url}%") if url.present?
permalinks.limit!(100)
permalinks.to_a
end
diff --git a/app/models/plugin_store.rb b/app/models/plugin_store.rb
index ed8dd6dc000..15504cc857b 100644
--- a/app/models/plugin_store.rb
+++ b/app/models/plugin_store.rb
@@ -31,7 +31,7 @@ class PluginStore
end
def self.get_all(plugin_name, keys)
- rows = PluginStoreRow.where('plugin_name = ? AND key IN (?)', plugin_name, keys).to_a
+ rows = PluginStoreRow.where("plugin_name = ? AND key IN (?)", plugin_name, keys).to_a
Hash[rows.map { |row| [row.key, cast_value(row.type_name, row.value)] }]
end
@@ -72,10 +72,14 @@ class PluginStore
def self.cast_value(type, value)
case type
- when "Integer", "Fixnum" then value.to_i
- when "TrueClass", "FalseClass" then value == "true"
- when "JSON" then map_json(::JSON.parse(value))
- else value
+ when "Integer", "Fixnum"
+ value.to_i
+ when "TrueClass", "FalseClass"
+ value == "true"
+ when "JSON"
+ map_json(::JSON.parse(value))
+ else
+ value
end
end
end
diff --git a/app/models/post.rb b/app/models/post.rb
index 7d1f5514145..7aa9155264a 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'archetype'
-require 'digest/sha1'
+require "archetype"
+require "digest/sha1"
class Post < ActiveRecord::Base
include RateLimiter::OnCreateRecord
@@ -12,7 +12,7 @@ class Post < ActiveRecord::Base
self.ignored_columns = [
"avg_time", # TODO(2021-01-04): remove
- "image_url" # TODO(2021-06-01): remove
+ "image_url", # TODO(2021-06-01): remove
]
cattr_accessor :plugin_permitted_create_params, :plugin_permitted_update_params
@@ -54,7 +54,7 @@ class Post < ActiveRecord::Base
has_many :post_details
has_many :post_revisions
- has_many :revisions, -> { order(:number) }, foreign_key: :post_id, class_name: 'PostRevision'
+ has_many :revisions, -> { order(:number) }, foreign_key: :post_id, class_name: "PostRevision"
has_many :user_actions, foreign_key: :target_post_id
@@ -67,11 +67,17 @@ class Post < ActiveRecord::Base
after_commit :index_search
# We can pass several creating options to a post via attributes
- attr_accessor :image_sizes, :quoted_post_numbers, :no_bump, :invalidate_oneboxes, :cooking_options, :skip_unique_check, :skip_validation
+ attr_accessor :image_sizes,
+ :quoted_post_numbers,
+ :no_bump,
+ :invalidate_oneboxes,
+ :cooking_options,
+ :skip_unique_check,
+ :skip_validation
- MISSING_UPLOADS ||= "missing uploads"
+ MISSING_UPLOADS ||= "missing uploads"
MISSING_UPLOADS_IGNORED ||= "missing uploads ignored"
- NOTICE ||= "notice"
+ NOTICE ||= "notice"
SHORT_POST_CHARS ||= 1200
@@ -80,46 +86,56 @@ class Post < ActiveRecord::Base
register_custom_field_type(NOTICE, :json)
- scope :private_posts_for_user, ->(user) do
- where(
- "topics.id IN (#{Topic::PRIVATE_MESSAGES_SQL_USER})
+ scope :private_posts_for_user,
+ ->(user) {
+ where(
+ "topics.id IN (#{Topic::PRIVATE_MESSAGES_SQL_USER})
OR topics.id IN (#{Topic::PRIVATE_MESSAGES_SQL_GROUP})",
- user_id: user.id
- )
- end
+ user_id: user.id,
+ )
+ }
- scope :by_newest, -> { order('created_at DESC, id DESC') }
- scope :by_post_number, -> { order('post_number ASC') }
+ scope :by_newest, -> { order("created_at DESC, id DESC") }
+ scope :by_post_number, -> { order("post_number ASC") }
scope :with_user, -> { includes(:user) }
- scope :created_since, -> (time_ago) { where('posts.created_at > ?', time_ago) }
- scope :public_posts, -> { joins(:topic).where('topics.archetype <> ?', Archetype.private_message) }
- scope :private_posts, -> { joins(:topic).where('topics.archetype = ?', Archetype.private_message) }
- scope :with_topic_subtype, ->(subtype) { joins(:topic).where('topics.subtype = ?', subtype) }
- scope :visible, -> { joins(:topic).where('topics.visible = true').where(hidden: false) }
- scope :secured, -> (guardian) { where('posts.post_type IN (?)', Topic.visible_post_types(guardian&.user)) }
+ scope :created_since, ->(time_ago) { where("posts.created_at > ?", time_ago) }
+ scope :public_posts,
+ -> { joins(:topic).where("topics.archetype <> ?", Archetype.private_message) }
+ scope :private_posts,
+ -> { joins(:topic).where("topics.archetype = ?", Archetype.private_message) }
+ scope :with_topic_subtype, ->(subtype) { joins(:topic).where("topics.subtype = ?", subtype) }
+ scope :visible, -> { joins(:topic).where("topics.visible = true").where(hidden: false) }
+ scope :secured,
+ ->(guardian) { where("posts.post_type IN (?)", Topic.visible_post_types(guardian&.user)) }
- scope :for_mailing_list, ->(user, since) {
- q = created_since(since)
- .joins("INNER JOIN (#{Topic.for_digest(user, Time.at(0)).select(:id).to_sql}) AS digest_topics ON digest_topics.id = posts.topic_id") # we want all topics with new content, regardless when they were created
- .order('posts.created_at ASC')
+ scope :for_mailing_list,
+ ->(user, since) {
+ q =
+ created_since(since).joins(
+ "INNER JOIN (#{Topic.for_digest(user, Time.at(0)).select(:id).to_sql}) AS digest_topics ON digest_topics.id = posts.topic_id",
+ ) # we want all topics with new content, regardless when they were created
+ .order("posts.created_at ASC")
- q = q.where.not(post_type: Post.types[:whisper]) unless user.staff?
- q
- }
+ q = q.where.not(post_type: Post.types[:whisper]) unless user.staff?
+ q
+ }
- scope :raw_match, -> (pattern, type = 'string') {
- type = type&.downcase
+ scope :raw_match,
+ ->(pattern, type = "string") {
+ type = type&.downcase
- case type
- when 'string'
- where('raw ILIKE ?', "%#{pattern}%")
- when 'regex'
- where('raw ~* ?', "(?n)#{pattern}")
- end
- }
+ case type
+ when "string"
+ where("raw ILIKE ?", "%#{pattern}%")
+ when "regex"
+ where("raw ~* ?", "(?n)#{pattern}")
+ end
+ }
- scope :have_uploads, -> {
- where("
+ scope :have_uploads,
+ -> {
+ where(
+ "
(
posts.cooked LIKE '% 1
- RateLimiter.new(user, "first-day-replies-per-day", SiteSetting.max_replies_in_first_day, 1.day.to_i)
+ RateLimiter.new(
+ user,
+ "first-day-replies-per-day",
+ SiteSetting.max_replies_in_first_day,
+ 1.day.to_i,
+ )
end
end
@@ -207,7 +225,7 @@ class Post < ActiveRecord::Base
user_id: user_id,
last_editor_id: last_editor_id,
type: type,
- version: version
+ version: version,
}.merge(opts)
publish_message!("/topic/#{topic_id}", message)
@@ -220,14 +238,10 @@ class Post < ActiveRecord::Base
if Topic.visible_post_types.include?(post_type)
opts.merge!(topic.secure_audience_publish_messages)
else
- opts[:user_ids] = User.human_users
- .where("admin OR moderator OR id = ?", user_id)
- .pluck(:id)
+ opts[:user_ids] = User.human_users.where("admin OR moderator OR id = ?", user_id).pluck(:id)
end
- if opts[:user_ids] != [] && opts[:group_ids] != []
- MessageBus.publish(channel, message, opts)
- end
+ MessageBus.publish(channel, message, opts) if opts[:user_ids] != [] && opts[:group_ids] != []
end
def trash!(trashed_by = nil)
@@ -241,9 +255,7 @@ class Post < ActiveRecord::Base
recover_public_post_actions
TopicLink.extract_from(self)
QuotedPost.extract_from(self)
- if topic && topic.category_id && topic.category
- topic.category.update_latest
- end
+ topic.category.update_latest if topic && topic.category_id && topic.category
end
# The key we use in redis to ensure unique posts
@@ -268,7 +280,7 @@ class Post < ActiveRecord::Base
end
def self.allowed_image_classes
- @allowed_image_classes ||= ['avatar', 'favicon', 'thumbnail', 'emoji', 'ytp-thumbnail-image']
+ @allowed_image_classes ||= %w[avatar favicon thumbnail emoji ytp-thumbnail-image]
end
def post_analyzer
@@ -276,17 +288,15 @@ class Post < ActiveRecord::Base
@post_analyzers[raw_hash] ||= PostAnalyzer.new(raw, topic_id)
end
- %w{raw_mentions
+ %w[
+ raw_mentions
linked_hosts
embedded_media_count
attachment_count
link_count
raw_links
- has_oneboxes?}.each do |attr|
- define_method(attr) do
- post_analyzer.public_send(attr)
- end
- end
+ has_oneboxes?
+ ].each { |attr| define_method(attr) { post_analyzer.public_send(attr) } }
def add_nofollow?
return false if user&.staff?
@@ -318,11 +328,16 @@ class Post < ActiveRecord::Base
each_upload_url do |url|
uri = URI.parse(url)
if FileHelper.is_supported_media?(File.basename(uri.path))
- raw = raw.sub(
- url, Rails.application.routes.url_for(
- controller: "uploads", action: "show_secure", path: uri.path[1..-1], host: Discourse.current_hostname
+ raw =
+ raw.sub(
+ url,
+ Rails.application.routes.url_for(
+ controller: "uploads",
+ action: "show_secure",
+ path: uri.path[1..-1],
+ host: Discourse.current_hostname,
+ ),
)
- )
end
end
end
@@ -358,43 +373,46 @@ class Post < ActiveRecord::Base
end
def allowed_spam_hosts
- hosts = SiteSetting
- .allowed_spam_host_domains
- .split('|')
- .map { |h| h.strip }
- .reject { |h| !h.include?('.') }
+ hosts =
+ SiteSetting
+ .allowed_spam_host_domains
+ .split("|")
+ .map { |h| h.strip }
+ .reject { |h| !h.include?(".") }
hosts << GlobalSetting.hostname
hosts << RailsMultisite::ConnectionManagement.current_hostname
-
end
def total_hosts_usage
hosts = linked_hosts.clone
allowlisted = allowed_spam_hosts
- hosts.reject! do |h|
- allowlisted.any? do |w|
- h.end_with?(w)
- end
- end
+ hosts.reject! { |h| allowlisted.any? { |w| h.end_with?(w) } }
return hosts if hosts.length == 0
- TopicLink.where(domain: hosts.keys, user_id: acting_user.id)
+ TopicLink
+ .where(domain: hosts.keys, user_id: acting_user.id)
.group(:domain, :post_id)
.count
.each_key do |tuple|
- domain = tuple[0]
- hosts[domain] = (hosts[domain] || 0) + 1
- end
+ domain = tuple[0]
+ hosts[domain] = (hosts[domain] || 0) + 1
+ end
hosts
end
# Prevent new users from posting the same hosts too many times.
def has_host_spam?
- return false if acting_user.present? && (acting_user.staged? || acting_user.mature_staged? || acting_user.has_trust_level?(TrustLevel[1]))
+ if acting_user.present? &&
+ (
+ acting_user.staged? || acting_user.mature_staged? ||
+ acting_user.has_trust_level?(TrustLevel[1])
+ )
+ return false
+ end
return false if topic&.private_message?
total_hosts_usage.values.any? { |count| count >= SiteSetting.newuser_spam_host_threshold }
@@ -409,15 +427,15 @@ class Post < ActiveRecord::Base
end
def self.reverse_order
- order('sort_order desc, post_number desc')
+ order("sort_order desc, post_number desc")
end
def self.summary(topic_id)
topic_id = topic_id.to_i
# percent rank has tons of ties
- where(topic_id: topic_id)
- .where([
+ where(topic_id: topic_id).where(
+ [
"id = ANY(
(
SELECT posts.id
@@ -435,8 +453,9 @@ class Post < ActiveRecord::Base
)
)",
SiteSetting.summary_percent_filter.to_f / 100.0,
- SiteSetting.summary_max_results
- ])
+ SiteSetting.summary_max_results,
+ ],
+ )
end
def delete_post_notices
@@ -445,7 +464,8 @@ class Post < ActiveRecord::Base
end
def recover_public_post_actions
- PostAction.publics
+ PostAction
+ .publics
.with_deleted
.where(post_id: self.id, id: self.custom_fields["deleted_public_actions"])
.find_each do |post_action|
@@ -463,10 +483,10 @@ class Post < ActiveRecord::Base
# We only filter quotes when there is exactly 1
return cooked unless (quote_count == 1)
- parent_raw = parent_post.raw.sub(/\[quote.+\/quote\]/m, '')
+ parent_raw = parent_post.raw.sub(%r{\[quote.+/quote\]}m, "")
if raw[parent_raw] || (parent_raw.size < SHORT_POST_CHARS)
- return cooked.sub(/\/m, '')
+ return cooked.sub(%r{\}m, "")
end
cooked
@@ -478,12 +498,22 @@ class Post < ActiveRecord::Base
def reply_to_post
return if reply_to_post_number.blank?
- @reply_to_post ||= Post.find_by("topic_id = :topic_id AND post_number = :post_number", topic_id: topic_id, post_number: reply_to_post_number)
+ @reply_to_post ||=
+ Post.find_by(
+ "topic_id = :topic_id AND post_number = :post_number",
+ topic_id: topic_id,
+ post_number: reply_to_post_number,
+ )
end
def reply_notification_target
return if reply_to_post_number.blank?
- Post.find_by("topic_id = :topic_id AND post_number = :post_number AND user_id <> :user_id", topic_id: topic_id, post_number: reply_to_post_number, user_id: user_id).try(:user)
+ Post.find_by(
+ "topic_id = :topic_id AND post_number = :post_number AND user_id <> :user_id",
+ topic_id: topic_id,
+ post_number: reply_to_post_number,
+ user_id: user_id,
+ ).try(:user)
end
def self.excerpt(cooked, maxlength = nil, options = {})
@@ -497,13 +527,17 @@ class Post < ActiveRecord::Base
end
def excerpt_for_topic
- Post.excerpt(cooked, SiteSetting.topic_excerpt_maxlength, strip_links: true, strip_images: true, post: self)
+ Post.excerpt(
+ cooked,
+ SiteSetting.topic_excerpt_maxlength,
+ strip_links: true,
+ strip_images: true,
+ post: self,
+ )
end
def is_first_post?
- post_number.blank? ?
- topic.try(:highest_post_number) == 0 :
- post_number == 1
+ post_number.blank? ? topic.try(:highest_post_number) == 0 : post_number == 1
end
def is_category_description?
@@ -515,7 +549,10 @@ class Post < ActiveRecord::Base
end
def is_flagged?
- post_actions.where(post_action_type_id: PostActionType.flag_types_without_custom.values, deleted_at: nil).count != 0
+ post_actions.where(
+ post_action_type_id: PostActionType.flag_types_without_custom.values,
+ deleted_at: nil,
+ ).count != 0
end
def reviewable_flag
@@ -524,16 +561,21 @@ class Post < ActiveRecord::Base
def with_secure_uploads?
return false if !SiteSetting.secure_uploads?
- SiteSetting.login_required? || \
+ SiteSetting.login_required? ||
(topic.present? && (topic.private_message? || topic.category&.read_restricted))
end
def hide!(post_action_type_id, reason = nil, custom_message: nil)
return if hidden?
- reason ||= hidden_at ?
- Post.hidden_reasons[:flag_threshold_reached_again] :
- Post.hidden_reasons[:flag_threshold_reached]
+ reason ||=
+ (
+ if hidden_at
+ Post.hidden_reasons[:flag_threshold_reached_again]
+ else
+ Post.hidden_reasons[:flag_threshold_reached]
+ end
+ )
hiding_again = hidden_at.present?
@@ -547,7 +589,7 @@ class Post < ActiveRecord::Base
Topic.where(
"id = :topic_id AND NOT EXISTS(SELECT 1 FROM POSTS WHERE topic_id = :topic_id AND NOT hidden)",
- topic_id: topic_id
+ topic_id: topic_id,
).update_all(visible: false)
UserStatCountUpdater.decrement!(self)
@@ -558,24 +600,23 @@ class Post < ActiveRecord::Base
options = {
url: url,
edit_delay: SiteSetting.cooldown_minutes_after_hiding_posts,
- flag_reason: I18n.t(
- "flag_reasons.#{PostActionType.types[post_action_type_id]}",
- locale: SiteSetting.default_locale,
- base_path: Discourse.base_path
- )
+ flag_reason:
+ I18n.t(
+ "flag_reasons.#{PostActionType.types[post_action_type_id]}",
+ locale: SiteSetting.default_locale,
+ base_path: Discourse.base_path,
+ ),
}
message = custom_message
- if message.nil?
- message = hiding_again ? :post_hidden_again : :post_hidden
- end
+ message = hiding_again ? :post_hidden_again : :post_hidden if message.nil?
Jobs.enqueue_in(
5.seconds,
:send_system_message,
user_id: user.id,
message_type: message.to_s,
- message_options: options
+ message_options: options,
)
end
end
@@ -610,9 +651,7 @@ class Post < ActiveRecord::Base
page = ""
- if topic_view.page > 1
- page = "?page=#{topic_view.page}"
- end
+ page = "?page=#{topic_view.page}" if topic_view.page > 1
"#{topic.url}#{page}#post_#{post_number}"
end
@@ -636,11 +675,11 @@ class Post < ActiveRecord::Base
ids = post_ids.map { |u| u }
if ids.length > 0
urls = {}
- Topic.joins(:posts).where('posts.id' => ids).
- select(['posts.id as post_id', 'post_number', 'topics.slug', 'topics.title', 'topics.id']).
- each do |t|
- urls[t.post_id.to_i] = url(t.slug, t.id, t.post_number)
- end
+ Topic
+ .joins(:posts)
+ .where("posts.id" => ids)
+ .select(["posts.id as post_id", "post_number", "topics.slug", "topics.title", "topics.id"])
+ .each { |t| urls[t.post_id.to_i] = url(t.slug, t.id, t.post_number) }
urls
else
{}
@@ -652,47 +691,50 @@ class Post < ActiveRecord::Base
end
def self.rebake_old(limit, priority: :normal, rate_limiter: true)
-
- limiter = RateLimiter.new(
- nil,
- "global_periodical_rebake_limit",
- GlobalSetting.max_old_rebakes_per_15_minutes,
- 900,
- global: true
- )
+ limiter =
+ RateLimiter.new(
+ nil,
+ "global_periodical_rebake_limit",
+ GlobalSetting.max_old_rebakes_per_15_minutes,
+ 900,
+ global: true,
+ )
problems = []
- Post.where('baked_version IS NULL OR baked_version < ?', BAKED_VERSION)
- .order('id desc')
- .limit(limit).pluck(:id).each do |id|
- begin
-
- break if !limiter.can_perform?
-
- post = Post.find(id)
- post.rebake!(priority: priority)
-
+ Post
+ .where("baked_version IS NULL OR baked_version < ?", BAKED_VERSION)
+ .order("id desc")
+ .limit(limit)
+ .pluck(:id)
+ .each do |id|
begin
- limiter.performed! if rate_limiter
- rescue RateLimiter::LimitExceeded
- break
+ break if !limiter.can_perform?
+
+ post = Post.find(id)
+ post.rebake!(priority: priority)
+
+ begin
+ limiter.performed! if rate_limiter
+ rescue RateLimiter::LimitExceeded
+ break
+ end
+ rescue => e
+ problems << { post: post, ex: e }
+
+ attempts = post.custom_fields["rebake_attempts"].to_i
+
+ if attempts > 3
+ post.update_columns(baked_version: BAKED_VERSION)
+ Discourse.warn_exception(
+ e,
+ message: "Can not rebake post# #{post.id} after 3 attempts, giving up",
+ )
+ else
+ post.custom_fields["rebake_attempts"] = attempts + 1
+ post.save_custom_fields
+ end
end
-
- rescue => e
- problems << { post: post, ex: e }
-
- attempts = post.custom_fields["rebake_attempts"].to_i
-
- if attempts > 3
- post.update_columns(baked_version: BAKED_VERSION)
- Discourse.warn_exception(e, message: "Can not rebake post# #{post.id} after 3 attempts, giving up")
- else
- post.custom_fields["rebake_attempts"] = attempts + 1
- post.save_custom_fields
- end
-
end
- end
problems
end
@@ -700,15 +742,9 @@ class Post < ActiveRecord::Base
new_cooked = cook(raw, topic_id: topic_id, invalidate_oneboxes: invalidate_oneboxes)
old_cooked = cooked
- update_columns(
- cooked: new_cooked,
- baked_at: Time.zone.now,
- baked_version: BAKED_VERSION
- )
+ update_columns(cooked: new_cooked, baked_at: Time.zone.now, baked_version: BAKED_VERSION)
- if is_first_post?
- topic&.update_excerpt(excerpt_for_topic)
- end
+ topic&.update_excerpt(excerpt_for_topic) if is_first_post?
if invalidate_broken_images
post_hotlinked_media.download_failed.destroy_all
@@ -730,31 +766,29 @@ class Post < ActiveRecord::Base
def set_owner(new_user, actor, skip_revision = false)
return if user_id == new_user.id
- edit_reason = I18n.t('change_owner.post_revision_text', locale: SiteSetting.default_locale)
+ edit_reason = I18n.t("change_owner.post_revision_text", locale: SiteSetting.default_locale)
revise(
actor,
{ raw: self.raw, user_id: new_user.id, edit_reason: edit_reason },
- bypass_bump: true, skip_revision: skip_revision, skip_validations: true
+ bypass_bump: true,
+ skip_revision: skip_revision,
+ skip_validations: true,
)
- if post_number == topic.highest_post_number
- topic.update_columns(last_post_user_id: new_user.id)
- end
+ topic.update_columns(last_post_user_id: new_user.id) if post_number == topic.highest_post_number
end
- before_create do
- PostCreator.before_create_tasks(self)
- end
+ before_create { PostCreator.before_create_tasks(self) }
def self.estimate_posts_per_day
val = Discourse.redis.get("estimated_posts_per_day")
return val.to_i if val
- posts_per_day = Topic.listable_topics.secured.joins(:posts).merge(Post.created_since(30.days.ago)).count / 30
+ posts_per_day =
+ Topic.listable_topics.secured.joins(:posts).merge(Post.created_since(30.days.ago)).count / 30
Discourse.redis.setex("estimated_posts_per_day", 1.day.to_i, posts_per_day.to_s)
posts_per_day
-
end
before_save do
@@ -778,13 +812,15 @@ class Post < ActiveRecord::Base
temp_collector = []
# Create relationships for the quotes
- raw.scan(/\[quote=\"([^"]+)"\]/).each do |quote|
- args = parse_quote_into_arguments(quote)
- # If the topic attribute is present, ensure it's the same topic
- if !(args[:topic].present? && topic_id != args[:topic]) && args[:post] != post_number
- temp_collector << args[:post]
+ raw
+ .scan(/\[quote=\"([^"]+)"\]/)
+ .each do |quote|
+ args = parse_quote_into_arguments(quote)
+ # If the topic attribute is present, ensure it's the same topic
+ if !(args[:topic].present? && topic_id != args[:topic]) && args[:post] != post_number
+ temp_collector << args[:post]
+ end
end
- end
temp_collector.uniq!
self.quoted_post_numbers = temp_collector
@@ -803,7 +839,12 @@ class Post < ActiveRecord::Base
end
# Enqueue post processing for this post
- def trigger_post_process(bypass_bump: false, priority: :normal, new_post: false, skip_pull_hotlinked_images: false)
+ def trigger_post_process(
+ bypass_bump: false,
+ priority: :normal,
+ new_post: false,
+ skip_pull_hotlinked_images: false
+ )
args = {
bypass_bump: bypass_bump,
cooking_options: self.cooking_options,
@@ -820,30 +861,36 @@ class Post < ActiveRecord::Base
DiscourseEvent.trigger(:after_trigger_post_process, self)
end
- def self.public_posts_count_per_day(start_date, end_date, category_id = nil, include_subcategories = false)
- result = public_posts
- .where('posts.created_at >= ? AND posts.created_at <= ?', start_date, end_date)
- .where(post_type: Post.types[:regular])
+ def self.public_posts_count_per_day(
+ start_date,
+ end_date,
+ category_id = nil,
+ include_subcategories = false
+ )
+ result =
+ public_posts.where(
+ "posts.created_at >= ? AND posts.created_at <= ?",
+ start_date,
+ end_date,
+ ).where(post_type: Post.types[:regular])
if category_id
if include_subcategories
- result = result.where('topics.category_id IN (?)', Category.subcategory_ids(category_id))
+ result = result.where("topics.category_id IN (?)", Category.subcategory_ids(category_id))
else
- result = result.where('topics.category_id = ?', category_id)
+ result = result.where("topics.category_id = ?", category_id)
end
end
- result
- .group('date(posts.created_at)')
- .order('date(posts.created_at)')
- .count
+ result.group("date(posts.created_at)").order("date(posts.created_at)").count
end
def self.private_messages_count_per_day(start_date, end_date, topic_subtype)
- private_posts.with_topic_subtype(topic_subtype)
- .where('posts.created_at >= ? AND posts.created_at <= ?', start_date, end_date)
- .group('date(posts.created_at)')
- .order('date(posts.created_at)')
+ private_posts
+ .with_topic_subtype(topic_subtype)
+ .where("posts.created_at >= ? AND posts.created_at <= ?", start_date, end_date)
+ .group("date(posts.created_at)")
+ .order("date(posts.created_at)")
.count
end
@@ -962,28 +1009,26 @@ class Post < ActiveRecord::Base
upload_ids << upload.id if upload.present?
end
- upload_references = upload_ids.map do |upload_id|
- {
- target_id: self.id,
- target_type: self.class.name,
- upload_id: upload_id,
- created_at: Time.zone.now,
- updated_at: Time.zone.now
- }
- end
+ upload_references =
+ upload_ids.map do |upload_id|
+ {
+ target_id: self.id,
+ target_type: self.class.name,
+ upload_id: upload_id,
+ created_at: Time.zone.now,
+ updated_at: Time.zone.now,
+ }
+ end
UploadReference.transaction do
UploadReference.where(target: self).delete_all
UploadReference.insert_all(upload_references) if upload_references.size > 0
if SiteSetting.secure_uploads?
- Upload.where(
- id: upload_ids, access_control_post_id: nil
- ).where(
- 'id NOT IN (SELECT upload_id FROM custom_emojis)'
- ).update_all(
- access_control_post_id: self.id
- )
+ Upload
+ .where(id: upload_ids, access_control_post_id: nil)
+ .where("id NOT IN (SELECT upload_id FROM custom_emojis)")
+ .update_all(access_control_post_id: self.id)
end
end
end
@@ -997,25 +1042,30 @@ class Post < ActiveRecord::Base
def each_upload_url(fragments: nil, include_local_upload: true)
current_db = RailsMultisite::ConnectionManagement.current_db
upload_patterns = [
- /\/uploads\/#{current_db}\//,
- /\/original\//,
- /\/optimized\//,
- /\/uploads\/short-url\/[a-zA-Z0-9]+(\.[a-z0-9]+)?/
+ %r{/uploads/#{current_db}/},
+ %r{/original/},
+ %r{/optimized/},
+ %r{/uploads/short-url/[a-zA-Z0-9]+(\.[a-z0-9]+)?},
]
- fragments ||= Nokogiri::HTML5::fragment(self.cooked)
+ fragments ||= Nokogiri::HTML5.fragment(self.cooked)
selectors = fragments.css("a/@href", "img/@src", "source/@src", "track/@src", "video/@poster")
- links = selectors.map do |media|
- src = media.value
- next if src.blank?
+ links =
+ selectors
+ .map do |media|
+ src = media.value
+ next if src.blank?
- if src.end_with?("/images/transparent.png") && (parent = media.parent)["data-orig-src"].present?
- parent["data-orig-src"]
- else
- src
- end
- end.compact.uniq
+ if src.end_with?("/images/transparent.png") &&
+ (parent = media.parent)["data-orig-src"].present?
+ parent["data-orig-src"]
+ else
+ src
+ end
+ end
+ .compact
+ .uniq
links.each do |src|
src = src.split("?")[0]
@@ -1034,13 +1084,19 @@ class Post < ActiveRecord::Base
next if Rails.configuration.multisite && src.exclude?(current_db)
src = "#{SiteSetting.force_https ? "https" : "http"}:#{src}" if src.start_with?("//")
- next unless Discourse.store.has_been_uploaded?(src) || Upload.secure_uploads_url?(src) || (include_local_upload && src =~ /\A\/[^\/]/i)
-
- path = begin
- URI(UrlHelper.unencode(GlobalSetting.cdn_url ? src.sub(GlobalSetting.cdn_url, "") : src))&.path
- rescue URI::Error
+ unless Discourse.store.has_been_uploaded?(src) || Upload.secure_uploads_url?(src) ||
+ (include_local_upload && src =~ %r{\A/[^/]}i)
+ next
end
+ path =
+ begin
+ URI(
+ UrlHelper.unencode(GlobalSetting.cdn_url ? src.sub(GlobalSetting.cdn_url, "") : src),
+ )&.path
+ rescue URI::Error
+ end
+
next if path.blank?
sha1 =
@@ -1061,20 +1117,24 @@ class Post < ActiveRecord::Base
DistributedMutex.synchronize("find_missing_uploads", validity: 30.minutes) do
PostCustomField.where(name: Post::MISSING_UPLOADS).delete_all
- query = Post
- .have_uploads
- .joins(:topic)
- .joins("LEFT JOIN post_custom_fields ON posts.id = post_custom_fields.post_id AND post_custom_fields.name = '#{Post::MISSING_UPLOADS_IGNORED}'")
- .where("post_custom_fields.id IS NULL")
- .select(:id, :cooked)
+ query =
+ Post
+ .have_uploads
+ .joins(:topic)
+ .joins(
+ "LEFT JOIN post_custom_fields ON posts.id = post_custom_fields.post_id AND post_custom_fields.name = '#{Post::MISSING_UPLOADS_IGNORED}'",
+ )
+ .where("post_custom_fields.id IS NULL")
+ .select(:id, :cooked)
query.find_in_batches do |posts|
ids = posts.pluck(:id)
- sha1s = Upload
- .joins(:upload_references)
- .where(upload_references: { target_type: "Post" })
- .where("upload_references.target_id BETWEEN ? AND ?", ids.min, ids.max)
- .pluck(:sha1)
+ sha1s =
+ Upload
+ .joins(:upload_references)
+ .where(upload_references: { target_type: "Post" })
+ .where("upload_references.target_id BETWEEN ? AND ?", ids.min, ids.max)
+ .pluck(:sha1)
posts.each do |post|
post.each_upload_url do |src, path, sha1|
@@ -1099,14 +1159,19 @@ class Post < ActiveRecord::Base
end
end
- missing_post_uploads = missing_post_uploads.reject do |post_id, uploads|
- if uploads.present?
- PostCustomField.create!(post_id: post_id, name: Post::MISSING_UPLOADS, value: uploads.to_json)
- count += uploads.count
- end
+ missing_post_uploads =
+ missing_post_uploads.reject do |post_id, uploads|
+ if uploads.present?
+ PostCustomField.create!(
+ post_id: post_id,
+ name: Post::MISSING_UPLOADS,
+ value: uploads.to_json,
+ )
+ count += uploads.count
+ end
- uploads.empty?
- end
+ uploads.empty?
+ end
end
{ uploads: missing_uploads, post_uploads: missing_post_uploads, count: count }
@@ -1123,8 +1188,11 @@ class Post < ActiveRecord::Base
def cannot_permanently_delete_reason(user)
if self.deleted_by_id == user&.id && self.deleted_at >= Post::PERMANENT_DELETE_TIMER.ago
- time_left = RateLimiter.time_left(Post::PERMANENT_DELETE_TIMER.to_i - Time.zone.now.to_i + self.deleted_at.to_i)
- I18n.t('post.cannot_permanently_delete.wait_or_different_admin', time_left: time_left)
+ time_left =
+ RateLimiter.time_left(
+ Post::PERMANENT_DELETE_TIMER.to_i - Time.zone.now.to_i + self.deleted_at.to_i,
+ )
+ I18n.t("post.cannot_permanently_delete.wait_or_different_admin", time_left: time_left)
end
end
@@ -1137,9 +1205,7 @@ class Post < ActiveRecord::Base
def parse_quote_into_arguments(quote)
return {} unless quote.present?
args = HashWithIndifferentAccess.new
- quote.first.scan(/([a-z]+)\:(\d+)/).each do |arg|
- args[arg[0]] = arg[1].to_i
- end
+ quote.first.scan(/([a-z]+)\:(\d+)/).each { |arg| args[arg[0]] = arg[1].to_i }
args
end
@@ -1154,7 +1220,7 @@ class Post < ActiveRecord::Base
post_reply = post.post_replies.new(reply_post_id: id)
if post_reply.save
if Topic.visible_post_types.include?(self.post_type)
- Post.where(id: post.id).update_all ['reply_count = reply_count + 1']
+ Post.where(id: post.id).update_all ["reply_count = reply_count + 1"]
end
end
end
diff --git a/app/models/post_action.rb b/app/models/post_action.rb
index e2fa99e45ff..a02c8908cf6 100644
--- a/app/models/post_action.rb
+++ b/app/models/post_action.rb
@@ -7,8 +7,8 @@ class PostAction < ActiveRecord::Base
belongs_to :post
belongs_to :user
belongs_to :post_action_type
- belongs_to :related_post, class_name: 'Post'
- belongs_to :target_user, class_name: 'User'
+ belongs_to :related_post, class_name: "Post"
+ belongs_to :target_user, class_name: "User"
rate_limit :post_action_rate_limiter
@@ -55,9 +55,9 @@ class PostAction < ActiveRecord::Base
ORDER BY p.topic_id, p.post_number
SQL
- builder.query(user_id: user.id, post_action_type_id: post_action_type_id, topic_ids: topic_ids).each do |row|
- (map[row.topic_id] ||= []) << row.post_number
- end
+ builder
+ .query(user_id: user.id, post_action_type_id: post_action_type_id, topic_ids: topic_ids)
+ .each { |row| (map[row.topic_id] ||= []) << row.post_number }
map
end
@@ -65,18 +65,24 @@ class PostAction < ActiveRecord::Base
def self.count_per_day_for_type(post_action_type, opts = nil)
opts ||= {}
result = unscoped.where(post_action_type_id: post_action_type)
- result = result.where('post_actions.created_at >= ?', opts[:start_date] || (opts[:since_days_ago] || 30).days.ago)
- result = result.where('post_actions.created_at <= ?', opts[:end_date]) if opts[:end_date]
+ result =
+ result.where(
+ "post_actions.created_at >= ?",
+ opts[:start_date] || (opts[:since_days_ago] || 30).days.ago,
+ )
+ result = result.where("post_actions.created_at <= ?", opts[:end_date]) if opts[:end_date]
if opts[:category_id]
if opts[:include_subcategories]
- result = result.joins(post: :topic).where('topics.category_id IN (?)', Category.subcategory_ids(opts[:category_id]))
+ result =
+ result.joins(post: :topic).where(
+ "topics.category_id IN (?)",
+ Category.subcategory_ids(opts[:category_id]),
+ )
else
- result = result.joins(post: :topic).where('topics.category_id = ?', opts[:category_id])
+ result = result.joins(post: :topic).where("topics.category_id = ?", opts[:category_id])
end
end
- result.group('date(post_actions.created_at)')
- .order('date(post_actions.created_at)')
- .count
+ result.group("date(post_actions.created_at)").order("date(post_actions.created_at)").count
end
def add_moderator_post_if_needed(moderator, disposition, delete_post = false)
@@ -95,7 +101,13 @@ class PostAction < ActiveRecord::Base
end
def staff_already_replied?(topic)
- topic.posts.where("user_id IN (SELECT id FROM users WHERE moderator OR admin) OR (post_type != :regular_post_type)", regular_post_type: Post.types[:regular]).exists?
+ topic
+ .posts
+ .where(
+ "user_id IN (SELECT id FROM users WHERE moderator OR admin) OR (post_type != :regular_post_type)",
+ regular_post_type: Post.types[:regular],
+ )
+ .exists?
end
def self.limit_action!(user, post, post_action_type_id)
@@ -106,21 +118,17 @@ class PostAction < ActiveRecord::Base
Discourse.deprecate(
"PostAction.act is deprecated. Use `PostActionCreator` instead.",
output_in_test: true,
- drop_from: '2.9.0',
+ drop_from: "2.9.0",
)
- result = PostActionCreator.new(
- created_by,
- post,
- post_action_type_id,
- message: opts[:message]
- ).perform
+ result =
+ PostActionCreator.new(created_by, post, post_action_type_id, message: opts[:message]).perform
result.success? ? result.post_action : nil
end
def self.copy(original_post, target_post)
- cols_to_copy = (column_names - %w{id post_id}).join(', ')
+ cols_to_copy = (column_names - %w[id post_id]).join(", ")
DB.exec <<~SQL
INSERT INTO post_actions(post_id, #{cols_to_copy})
@@ -136,7 +144,7 @@ class PostAction < ActiveRecord::Base
Discourse.deprecate(
"PostAction.remove_act is deprecated. Use `PostActionDestroyer` instead.",
output_in_test: true,
- drop_from: '2.9.0',
+ drop_from: "2.9.0",
)
PostActionDestroyer.new(user, post, post_action_type_id).perform
@@ -160,7 +168,7 @@ class PostAction < ActiveRecord::Base
def is_private_message?
post_action_type_id == PostActionType.types[:notify_user] ||
- post_action_type_id == PostActionType.types[:notify_moderators]
+ post_action_type_id == PostActionType.types[:notify_moderators]
end
# A custom rate limiter for this model
@@ -169,12 +177,13 @@ class PostAction < ActiveRecord::Base
return @rate_limiter if @rate_limiter.present?
- %w(like flag).each do |type|
+ %w[like flag].each do |type|
if public_send("is_#{type}?")
limit = SiteSetting.get("max_#{type}s_per_day")
if (is_flag? || is_like?) && user && user.trust_level >= 2
- multiplier = SiteSetting.get("tl#{user.trust_level}_additional_#{type}s_per_day_multiplier").to_f
+ multiplier =
+ SiteSetting.get("tl#{user.trust_level}_additional_#{type}s_per_day_multiplier").to_f
multiplier = 1.0 if multiplier < 1.0
limit = (limit * multiplier).to_i
@@ -189,13 +198,15 @@ class PostAction < ActiveRecord::Base
def ensure_unique_actions
post_action_type_ids = is_flag? ? PostActionType.notify_flag_types.values : post_action_type_id
- acted = PostAction.where(user_id: user_id)
- .where(post_id: post_id)
- .where(post_action_type_id: post_action_type_ids)
- .where(deleted_at: nil)
- .where(disagreed_at: nil)
- .where(targets_topic: targets_topic)
- .exists?
+ acted =
+ PostAction
+ .where(user_id: user_id)
+ .where(post_id: post_id)
+ .where(post_action_type_id: post_action_type_ids)
+ .where(deleted_at: nil)
+ .where(disagreed_at: nil)
+ .where(targets_topic: targets_topic)
+ .exists?
errors.add(:post_action_type_id) if acted
end
@@ -207,18 +218,24 @@ class PostAction < ActiveRecord::Base
def update_counters
# Update denormalized counts
column = "#{post_action_type_key}_count"
- count = PostAction.where(post_id: post_id)
- .where(post_action_type_id: post_action_type_id)
- .count
+ count = PostAction.where(post_id: post_id).where(post_action_type_id: post_action_type_id).count
# We probably want to refactor this method to something cleaner.
case post_action_type_key
when :like
# 'like_score' is weighted higher for staff accounts
- score = PostAction.joins(:user)
- .where(post_id: post_id)
- .sum("CASE WHEN users.moderator OR users.admin THEN #{SiteSetting.staff_like_weight} ELSE 1 END")
- Post.where(id: post_id).update_all ["like_count = :count, like_score = :score", count: count, score: score]
+ score =
+ PostAction
+ .joins(:user)
+ .where(post_id: post_id)
+ .sum(
+ "CASE WHEN users.moderator OR users.admin THEN #{SiteSetting.staff_like_weight} ELSE 1 END",
+ )
+ Post.where(id: post_id).update_all [
+ "like_count = :count, like_score = :score",
+ count: count,
+ score: score,
+ ]
else
if ActiveRecord::Base.connection.column_exists?(:posts, column)
Post.where(id: post_id).update_all ["#{column} = ?", count]
@@ -229,15 +246,14 @@ class PostAction < ActiveRecord::Base
# topic_user
if post_action_type_key == :like
- TopicUser.update_post_action_cache(user_id: user_id,
- topic_id: topic_id,
- post_action_type: post_action_type_key)
- end
-
- if column == "like_count"
- Topic.find_by(id: topic_id)&.update_action_counts
+ TopicUser.update_post_action_cache(
+ user_id: user_id,
+ topic_id: topic_id,
+ post_action_type: post_action_type_key,
+ )
end
+ Topic.find_by(id: topic_id)&.update_action_counts if column == "like_count"
end
end
diff --git a/app/models/post_action_type.rb b/app/models/post_action_type.rb
index a209a79b6b0..db785c307fe 100644
--- a/app/models/post_action_type.rb
+++ b/app/models/post_action_type.rb
@@ -24,16 +24,14 @@ class PostActionType < ActiveRecord::Base
end
def ordered
- order('position asc')
+ order("position asc")
end
def types
unless @types
# NOTE: Previously bookmark was type 1 but that has been superseded
# by the separate Bookmark model and functionality
- @types = Enum.new(
- like: 2
- )
+ @types = Enum.new(like: 2)
@types.merge!(flag_settings.flag_types)
end
@@ -85,39 +83,22 @@ class PostActionType < ActiveRecord::Base
def initialize_flag_settings
@flag_settings = FlagSettings.new
- @flag_settings.add(
- 3,
- :off_topic,
- notify_type: true,
- auto_action_type: true,
- )
+ @flag_settings.add(3, :off_topic, notify_type: true, auto_action_type: true)
@flag_settings.add(
4,
:inappropriate,
topic_type: true,
notify_type: true,
auto_action_type: true,
- )
- @flag_settings.add(
- 8,
- :spam,
- topic_type: true,
- notify_type: true,
- auto_action_type: true,
- )
- @flag_settings.add(
- 6,
- :notify_user,
- topic_type: false,
- notify_type: false,
- custom_type: true
)
+ @flag_settings.add(8, :spam, topic_type: true, notify_type: true, auto_action_type: true)
+ @flag_settings.add(6, :notify_user, topic_type: false, notify_type: false, custom_type: true)
@flag_settings.add(
7,
:notify_moderators,
topic_type: true,
notify_type: true,
- custom_type: true
+ custom_type: true,
)
end
end
diff --git a/app/models/post_analyzer.rb b/app/models/post_analyzer.rb
index bbd5bdd7f3e..2d2622c2070 100644
--- a/app/models/post_analyzer.rb
+++ b/app/models/post_analyzer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class PostAnalyzer
-
def initialize(raw, topic_id)
@raw = raw
@topic_id = topic_id
@@ -32,19 +31,20 @@ class PostAnalyzer
end
limit = SiteSetting.max_oneboxes_per_post
- result = Oneboxer.apply(cooked, extra_paths: ".inline-onebox-loading") do |url, element|
- if opts[:invalidate_oneboxes]
- Oneboxer.invalidate(url)
- InlineOneboxer.invalidate(url)
+ result =
+ Oneboxer.apply(cooked, extra_paths: ".inline-onebox-loading") do |url, element|
+ if opts[:invalidate_oneboxes]
+ Oneboxer.invalidate(url)
+ InlineOneboxer.invalidate(url)
+ end
+ next if element["class"] != Oneboxer::ONEBOX_CSS_CLASS
+ next if limit <= 0
+ limit -= 1
+ @onebox_urls << url
+ onebox = Oneboxer.cached_onebox(url)
+ @found_oneboxes = true if onebox.present?
+ onebox
end
- next if element["class"] != Oneboxer::ONEBOX_CSS_CLASS
- next if limit <= 0
- limit -= 1
- @onebox_urls << url
- onebox = Oneboxer.cached_onebox(url)
- @found_oneboxes = true if onebox.present?
- onebox
- end
if result.changed?
PrettyText.sanitize_hotlinked_media(result.doc)
@@ -59,19 +59,26 @@ class PostAnalyzer
return 0 unless @raw.present?
# TODO - do we need to look for tags other than img, video and audio?
- cooked_stripped.css("img", "video", "audio").reject do |t|
- if dom_class = t["class"]
- (Post.allowed_image_classes & dom_class.split).count > 0
+ cooked_stripped
+ .css("img", "video", "audio")
+ .reject do |t|
+ if dom_class = t["class"]
+ (Post.allowed_image_classes & dom_class.split).count > 0
+ end
end
- end.count
+ .count
end
# How many attachments are present in the post
def attachment_count
return 0 unless @raw.present?
- attachments = cooked_stripped.css("a.attachment[href^=\"#{Discourse.store.absolute_base_url}\"]")
- attachments += cooked_stripped.css("a.attachment[href^=\"#{Discourse.store.relative_base_url}\"]") if Discourse.store.internal?
+ attachments =
+ cooked_stripped.css("a.attachment[href^=\"#{Discourse.store.absolute_base_url}\"]")
+ attachments +=
+ cooked_stripped.css(
+ "a.attachment[href^=\"#{Discourse.store.relative_base_url}\"]",
+ ) if Discourse.store.internal?
attachments.count
end
@@ -116,15 +123,17 @@ class PostAnalyzer
return @raw_links if @raw_links.present?
@raw_links = []
- cooked_stripped.css("a").each do |l|
- # Don't include @mentions in the link count
- next if link_is_a_mention?(l)
- # Don't include heading anchor in the link count
- next if link_is_an_anchor?(l)
- # Don't include hashtags in the link count
- next if link_is_a_hashtag?(l)
- @raw_links << l['href'].to_s
- end
+ cooked_stripped
+ .css("a")
+ .each do |l|
+ # Don't include @mentions in the link count
+ next if link_is_a_mention?(l)
+ # Don't include heading anchor in the link count
+ next if link_is_an_anchor?(l)
+ # Don't include hashtags in the link count
+ next if link_is_a_hashtag?(l)
+ @raw_links << l["href"].to_s
+ end
@raw_links
end
@@ -135,27 +144,37 @@ class PostAnalyzer
end
def cooked_stripped
- @cooked_stripped ||= begin
- doc = Nokogiri::HTML5.fragment(cook(@raw, topic_id: @topic_id))
- doc.css("pre .mention, aside.quote > .title, aside.quote .mention, aside.quote .mention-group, .onebox, .elided").remove
- doc
- end
+ @cooked_stripped ||=
+ begin
+ doc = Nokogiri::HTML5.fragment(cook(@raw, topic_id: @topic_id))
+ doc.css(
+ "pre .mention, aside.quote > .title, aside.quote .mention, aside.quote .mention-group, .onebox, .elided",
+ ).remove
+ doc
+ end
end
private
def link_is_a_mention?(l)
- href = l['href'].to_s
- l['class'].to_s['mention'] && (href.start_with?("#{Discourse.base_path}/u/") || href.start_with?("#{Discourse.base_path}/users/"))
+ href = l["href"].to_s
+ l["class"].to_s["mention"] &&
+ (
+ href.start_with?("#{Discourse.base_path}/u/") ||
+ href.start_with?("#{Discourse.base_path}/users/")
+ )
end
def link_is_an_anchor?(l)
- l['class'].to_s['anchor'] && l['href'].to_s.start_with?('#')
+ l["class"].to_s["anchor"] && l["href"].to_s.start_with?("#")
end
def link_is_a_hashtag?(l)
- href = l['href'].to_s
- l['class'].to_s['hashtag'] && (href.start_with?("#{Discourse.base_path}/c/") || href.start_with?("#{Discourse.base_path}/tag/"))
+ href = l["href"].to_s
+ l["class"].to_s["hashtag"] &&
+ (
+ href.start_with?("#{Discourse.base_path}/c/") ||
+ href.start_with?("#{Discourse.base_path}/tag/")
+ )
end
-
end
diff --git a/app/models/post_detail.rb b/app/models/post_detail.rb
index 56fbed2ac5f..c28d501d8ec 100644
--- a/app/models/post_detail.rb
+++ b/app/models/post_detail.rb
@@ -3,7 +3,7 @@
class PostDetail < ActiveRecord::Base
belongs_to :post
- validates_presence_of :key, :value
+ validates_presence_of :key, :value
validates_uniqueness_of :key, scope: :post_id
end
diff --git a/app/models/post_hotlinked_media.rb b/app/models/post_hotlinked_media.rb
index fc8e5814dfb..de7d6aca7a5 100644
--- a/app/models/post_hotlinked_media.rb
+++ b/app/models/post_hotlinked_media.rb
@@ -4,11 +4,11 @@ class PostHotlinkedMedia < ActiveRecord::Base
belongs_to :post
belongs_to :upload
enum status: {
- downloaded: "downloaded",
- too_large: "too_large",
- download_failed: "download_failed",
- upload_create_failed: "upload_create_failed"
- }
+ downloaded: "downloaded",
+ too_large: "too_large",
+ download_failed: "download_failed",
+ upload_create_failed: "upload_create_failed",
+ }
def self.normalize_src(src)
uri = Addressable::URI.heuristic_parse(src)
diff --git a/app/models/post_mover.rb b/app/models/post_mover.rb
index f8e77c7cd6d..ac6e90471ae 100644
--- a/app/models/post_mover.rb
+++ b/app/models/post_mover.rb
@@ -19,13 +19,11 @@ class PostMover
topic = Topic.find_by_id(id)
if topic.archetype != @original_topic.archetype &&
- [@original_topic.archetype, topic.archetype].include?(Archetype.private_message)
+ [@original_topic.archetype, topic.archetype].include?(Archetype.private_message)
raise Discourse::InvalidParameters
end
- Topic.transaction do
- move_posts_to topic
- end
+ Topic.transaction { move_posts_to topic }
add_allowed_users(participants) if participants.present? && @move_to_pm
enqueue_jobs(topic)
topic
@@ -38,20 +36,22 @@ class PostMover
raise Discourse::InvalidParameters unless post
archetype = @move_to_pm ? Archetype.private_message : Archetype.default
- topic = Topic.transaction do
- new_topic = Topic.create!(
- user: post.user,
- title: title,
- category_id: category_id,
- created_at: post.created_at,
- archetype: archetype
- )
- DiscourseTagging.tag_topic_by_names(new_topic, Guardian.new(user), tags)
- move_posts_to new_topic
- watch_new_topic
- update_topic_excerpt new_topic
- new_topic
- end
+ topic =
+ Topic.transaction do
+ new_topic =
+ Topic.create!(
+ user: post.user,
+ title: title,
+ category_id: category_id,
+ created_at: post.created_at,
+ archetype: archetype,
+ )
+ DiscourseTagging.tag_topic_by_names(new_topic, Guardian.new(user), tags)
+ move_posts_to new_topic
+ watch_new_topic
+ update_topic_excerpt new_topic
+ new_topic
+ end
enqueue_jobs(topic)
topic
end
@@ -73,9 +73,15 @@ class PostMover
# we should only exclude whispers with action_code: 'split_topic'
# because we use such whispers as a small-action posts when moving posts to the secret message
# (in this case we don't want everyone to see that posts were moved, that's why we use whispers)
- original_topic_posts_count = @original_topic.posts
- .where("post_type = ? or (post_type = ? and action_code != 'split_topic')", Post.types[:regular], Post.types[:whisper])
- .count
+ original_topic_posts_count =
+ @original_topic
+ .posts
+ .where(
+ "post_type = ? or (post_type = ? and action_code != 'split_topic')",
+ Post.types[:regular],
+ Post.types[:whisper],
+ )
+ .count
moving_all_posts = original_topic_posts_count == posts.length
create_temp_table
@@ -87,9 +93,7 @@ class PostMover
update_upload_security_status
update_bookmarks
- if moving_all_posts
- close_topic_and_schedule_deletion
- end
+ close_topic_and_schedule_deletion if moving_all_posts
destination_topic.reload
destination_topic
@@ -152,19 +156,20 @@ class PostMover
end
def create_first_post(post)
- @post_creator = PostCreator.new(
- post.user,
- raw: post.raw,
- topic_id: destination_topic.id,
- acting_user: user,
- cook_method: post.cook_method,
- via_email: post.via_email,
- raw_email: post.raw_email,
- skip_validations: true,
- created_at: post.created_at,
- guardian: Guardian.new(user),
- skip_jobs: true
- )
+ @post_creator =
+ PostCreator.new(
+ post.user,
+ raw: post.raw,
+ topic_id: destination_topic.id,
+ acting_user: user,
+ cook_method: post.cook_method,
+ via_email: post.via_email,
+ raw_email: post.raw_email,
+ skip_validations: true,
+ created_at: post.created_at,
+ guardian: Guardian.new(user),
+ skip_jobs: true,
+ )
new_post = @post_creator.create!
move_email_logs(post, new_post)
@@ -192,12 +197,10 @@ class PostMover
reply_to_post_number: @move_map[post.reply_to_post_number],
topic_id: destination_topic.id,
sort_order: @move_map[post.post_number],
- baked_version: nil
+ baked_version: nil,
}
- unless @move_map[post.reply_to_post_number]
- update[:reply_to_user_id] = nil
- end
+ update[:reply_to_user_id] = nil unless @move_map[post.reply_to_post_number]
post.attributes = update
post.save(validate: false)
@@ -217,7 +220,7 @@ class PostMover
old_post_number: post.post_number,
new_topic_id: destination_topic.id,
new_post_number: @move_map[post.post_number],
- new_topic_title: destination_topic.title
+ new_topic_title: destination_topic.title,
}
end
@@ -241,9 +244,7 @@ class PostMover
end
def move_email_logs(old_post, new_post)
- EmailLog
- .where(post_id: old_post.id)
- .update_all(post_id: new_post.id)
+ EmailLog.where(post_id: old_post.id).update_all(post_id: new_post.id)
end
def move_notifications
@@ -349,7 +350,7 @@ class PostMover
old_topic_id: original_topic.id,
new_topic_id: destination_topic.id,
old_highest_post_number: destination_topic.highest_post_number,
- old_highest_staff_post_number: destination_topic.highest_staff_post_number
+ old_highest_staff_post_number: destination_topic.highest_staff_post_number,
}
DB.exec(<<~SQL, params)
@@ -423,7 +424,10 @@ class PostMover
def update_statistics
destination_topic.update_statistics
original_topic.update_statistics
- TopicUser.update_post_action_cache(topic_id: [original_topic.id, destination_topic.id], post_id: @post_ids)
+ TopicUser.update_post_action_cache(
+ topic_id: [original_topic.id, destination_topic.id],
+ post_id: @post_ids,
+ )
end
def update_user_actions
@@ -434,35 +438,42 @@ class PostMover
move_type_str = PostMover.move_types[@move_type].to_s
move_type_str.sub!("topic", "message") if @move_to_pm
- message = I18n.with_locale(SiteSetting.default_locale) do
- I18n.t(
- "move_posts.#{move_type_str}_moderator_post",
- count: posts.length,
- topic_link: posts.first.is_first_post? ?
- "[#{destination_topic.title}](#{destination_topic.relative_url})" :
- "[#{destination_topic.title}](#{posts.first.url})"
- )
- end
+ message =
+ I18n.with_locale(SiteSetting.default_locale) do
+ I18n.t(
+ "move_posts.#{move_type_str}_moderator_post",
+ count: posts.length,
+ topic_link:
+ (
+ if posts.first.is_first_post?
+ "[#{destination_topic.title}](#{destination_topic.relative_url})"
+ else
+ "[#{destination_topic.title}](#{posts.first.url})"
+ end
+ ),
+ )
+ end
post_type = @move_to_pm ? Post.types[:whisper] : Post.types[:small_action]
original_topic.add_moderator_post(
- user, message,
+ user,
+ message,
post_type: post_type,
action_code: "split_topic",
- post_number: @first_post_number_moved
+ post_number: @first_post_number_moved,
)
end
def posts
- @posts ||= begin
- Post.where(topic: @original_topic, id: post_ids)
- .where.not(post_type: Post.types[:small_action])
- .where.not(raw: '')
- .order(:created_at).tap do |posts|
-
- raise Discourse::InvalidParameters.new(:post_ids) if posts.empty?
+ @posts ||=
+ begin
+ Post
+ .where(topic: @original_topic, id: post_ids)
+ .where.not(post_type: Post.types[:small_action])
+ .where.not(raw: "")
+ .order(:created_at)
+ .tap { |posts| raise Discourse::InvalidParameters.new(:post_ids) if posts.empty? }
end
- end
end
def update_last_post_stats
@@ -478,9 +489,7 @@ class PostMover
end
def update_upload_security_status
- DB.after_commit do
- Jobs.enqueue(:update_topic_upload_security, topic_id: @destination_topic.id)
- end
+ DB.after_commit { Jobs.enqueue(:update_topic_upload_security, topic_id: @destination_topic.id) }
end
def update_bookmarks
@@ -493,9 +502,18 @@ class PostMover
def watch_new_topic
if @destination_topic.archetype == Archetype.private_message
if @original_topic.archetype == Archetype.private_message
- notification_levels = TopicUser.where(topic_id: @original_topic.id, user_id: posts.pluck(:user_id)).pluck(:user_id, :notification_level).to_h
+ notification_levels =
+ TopicUser
+ .where(topic_id: @original_topic.id, user_id: posts.pluck(:user_id))
+ .pluck(:user_id, :notification_level)
+ .to_h
else
- notification_levels = posts.pluck(:user_id).uniq.map { |user_id| [user_id, TopicUser.notification_levels[:watching]] }.to_h
+ notification_levels =
+ posts
+ .pluck(:user_id)
+ .uniq
+ .map { |user_id| [user_id, TopicUser.notification_levels[:watching]] }
+ .to_h
end
else
notification_levels = [[@destination_topic.user_id, TopicUser.notification_levels[:watching]]]
@@ -506,7 +524,10 @@ class PostMover
user_id,
@destination_topic.id,
notification_level: notification_level,
- notifications_reason_id: TopicUser.notification_reasons[destination_topic.user_id == user_id ? :created_topic : :created_post]
+ notifications_reason_id:
+ TopicUser.notification_reasons[
+ destination_topic.user_id == user_id ? :created_topic : :created_post
+ ],
)
end
end
@@ -514,37 +535,34 @@ class PostMover
def add_allowed_users(usernames)
return unless usernames.present?
- names = usernames.split(',').flatten
- User.where(username: names).find_each do |user|
- destination_topic.topic_allowed_users.build(user_id: user.id) unless destination_topic.topic_allowed_users.where(user_id: user.id).exists?
- end
+ names = usernames.split(",").flatten
+ User
+ .where(username: names)
+ .find_each do |user|
+ unless destination_topic.topic_allowed_users.where(user_id: user.id).exists?
+ destination_topic.topic_allowed_users.build(user_id: user.id)
+ end
+ end
destination_topic.save!
end
def enqueue_jobs(topic)
@post_creator.enqueue_jobs if @post_creator
- Jobs.enqueue(
- :notify_moved_posts,
- post_ids: post_ids,
- moved_by_id: user.id
- )
+ Jobs.enqueue(:notify_moved_posts, post_ids: post_ids, moved_by_id: user.id)
- Jobs.enqueue(
- :delete_inaccessible_notifications,
- topic_id: topic.id
- )
+ Jobs.enqueue(:delete_inaccessible_notifications, topic_id: topic.id)
end
def close_topic_and_schedule_deletion
- @original_topic.update_status('closed', true, @user)
+ @original_topic.update_status("closed", true, @user)
days_to_deleting = SiteSetting.delete_merged_stub_topics_after_days
if days_to_deleting > 0
@original_topic.set_or_create_timer(
TopicTimer.types[:delete],
days_to_deleting * 24,
- by_user: @user
+ by_user: @user,
)
end
end
diff --git a/app/models/post_reply.rb b/app/models/post_reply.rb
index 1cedb847a94..d2cce1de360 100644
--- a/app/models/post_reply.rb
+++ b/app/models/post_reply.rb
@@ -2,7 +2,7 @@
class PostReply < ActiveRecord::Base
belongs_to :post
- belongs_to :reply, foreign_key: :reply_post_id, class_name: 'Post'
+ belongs_to :reply, foreign_key: :reply_post_id, class_name: "Post"
validates_uniqueness_of :reply_post_id, scope: :post_id
validate :ensure_same_topic
@@ -11,10 +11,7 @@ class PostReply < ActiveRecord::Base
def ensure_same_topic
if post.topic_id != reply.topic_id
- self.errors.add(
- :base,
- I18n.t("activerecord.errors.models.post_reply.base.different_topic")
- )
+ self.errors.add(:base, I18n.t("activerecord.errors.models.post_reply.base.different_topic"))
end
end
end
diff --git a/app/models/post_reply_key.rb b/app/models/post_reply_key.rb
index 83686df18ba..1084996ec81 100644
--- a/app/models/post_reply_key.rb
+++ b/app/models/post_reply_key.rb
@@ -11,7 +11,7 @@ class PostReplyKey < ActiveRecord::Base
validates :reply_key, presence: true
def reply_key
- super&.delete('-')
+ super&.delete("-")
end
def self.generate_reply_key
diff --git a/app/models/post_revision.rb b/app/models/post_revision.rb
index 9d9d48c3195..91554852383 100644
--- a/app/models/post_revision.rb
+++ b/app/models/post_revision.rb
@@ -39,7 +39,6 @@ class PostRevision < ActiveRecord::Base
def create_notification
PostActionNotifier.after_create_post_revision(self)
end
-
end
# == Schema Information
diff --git a/app/models/post_timing.rb b/app/models/post_timing.rb
index 9efb3e59f2a..1a3863672f5 100644
--- a/app/models/post_timing.rb
+++ b/app/models/post_timing.rb
@@ -10,7 +10,8 @@ class PostTiming < ActiveRecord::Base
def self.pretend_read(topic_id, actual_read_post_number, pretend_read_post_number)
# This is done in SQL cause the logic is quite tricky and we want to do this in one db hit
#
- DB.exec("INSERT INTO post_timings(topic_id, user_id, post_number, msecs)
+ DB.exec(
+ "INSERT INTO post_timings(topic_id, user_id, post_number, msecs)
SELECT :topic_id, user_id, :pretend_read_post_number, 1
FROM post_timings pt
WHERE topic_id = :topic_id AND
@@ -22,27 +23,32 @@ class PostTiming < ActiveRecord::Base
pt1.user_id = pt.user_id
)
",
- pretend_read_post_number: pretend_read_post_number,
- topic_id: topic_id,
- actual_read_post_number: actual_read_post_number
- )
+ pretend_read_post_number: pretend_read_post_number,
+ topic_id: topic_id,
+ actual_read_post_number: actual_read_post_number,
+ )
TopicUser.ensure_consistency!(topic_id)
end
def self.record_new_timing(args)
- row_count = DB.exec("INSERT INTO post_timings (topic_id, user_id, post_number, msecs)
+ row_count =
+ DB.exec(
+ "INSERT INTO post_timings (topic_id, user_id, post_number, msecs)
SELECT :topic_id, :user_id, :post_number, :msecs
ON CONFLICT DO NOTHING",
- args)
+ args,
+ )
# concurrency is hard, we are not running serialized so this can possibly
# still happen, if it happens we just don't care, its an invalid record anyway
return if row_count == 0
- Post.where(['topic_id = :topic_id and post_number = :post_number', args]).update_all 'reads = reads + 1'
+ Post.where(
+ ["topic_id = :topic_id and post_number = :post_number", args],
+ ).update_all "reads = reads + 1"
return if Topic.exists?(id: args[:topic_id], archetype: Archetype.private_message)
- UserStat.where(user_id: args[:user_id]).update_all 'posts_read_count = posts_read_count + 1'
+ UserStat.where(user_id: args[:user_id]).update_all "posts_read_count = posts_read_count + 1"
end
# Increases a timer if a row exists, otherwise create it
@@ -65,13 +71,16 @@ class PostTiming < ActiveRecord::Base
last_read = post_number - 1
PostTiming.transaction do
- PostTiming.where("topic_id = ? AND user_id = ? AND post_number > ?", topic.id, user.id, last_read).delete_all
- if last_read < 1
- last_read = nil
- end
+ PostTiming.where(
+ "topic_id = ? AND user_id = ? AND post_number > ?",
+ topic.id,
+ user.id,
+ last_read,
+ ).delete_all
+ last_read = nil if last_read < 1
TopicUser.where(user_id: user.id, topic_id: topic.id).update_all(
- last_read_post_number: last_read
+ last_read_post_number: last_read,
)
topic.posts.find_by(post_number: post_number).decrement!(:reads)
@@ -86,28 +95,23 @@ class PostTiming < ActiveRecord::Base
def self.destroy_for(user_id, topic_ids)
PostTiming.transaction do
- PostTiming
- .where('user_id = ? and topic_id in (?)', user_id, topic_ids)
- .delete_all
+ PostTiming.where("user_id = ? and topic_id in (?)", user_id, topic_ids).delete_all
- TopicUser
- .where('user_id = ? and topic_id in (?)', user_id, topic_ids)
- .delete_all
+ TopicUser.where("user_id = ? and topic_id in (?)", user_id, topic_ids).delete_all
- Post.where(topic_id: topic_ids).update_all('reads = reads - 1')
+ Post.where(topic_id: topic_ids).update_all("reads = reads - 1")
date = Topic.listable_topics.where(id: topic_ids).minimum(:updated_at)
- if date
- set_minimum_first_unread!(user_id: user_id, date: date)
- end
+ set_minimum_first_unread!(user_id: user_id, date: date) if date
end
end
def self.set_minimum_first_unread_pm!(topic:, user_id:, date:)
if topic.topic_allowed_users.exists?(user_id: user_id)
- UserStat.where("first_unread_pm_at > ? AND user_id = ?", date, user_id)
- .update_all(first_unread_pm_at: date)
+ UserStat.where("first_unread_pm_at > ? AND user_id = ?", date, user_id).update_all(
+ first_unread_pm_at: date,
+ )
else
DB.exec(<<~SQL, date: date, user_id: user_id, topic_id: topic.id)
UPDATE group_users gu
@@ -155,12 +159,10 @@ class PostTiming < ActiveRecord::Base
end
timings.each_with_index do |(post_number, time), index|
-
join_table << "SELECT #{topic_id.to_i} topic_id, #{post_number.to_i} post_number,
#{current_user.id.to_i} user_id, #{time.to_i} msecs, #{index} idx"
- highest_seen = post_number.to_i > highest_seen ?
- post_number.to_i : highest_seen
+ highest_seen = post_number.to_i > highest_seen ? post_number.to_i : highest_seen
end
if join_table.length > 0
@@ -188,10 +190,12 @@ SQL
timings.each_with_index do |(post_number, time), index|
unless existing.include?(index)
- PostTiming.record_new_timing(topic_id: topic_id,
- post_number: post_number,
- user_id: current_user.id,
- msecs: time)
+ PostTiming.record_new_timing(
+ topic_id: topic_id,
+ post_number: post_number,
+ user_id: current_user.id,
+ msecs: time,
+ )
end
end
end
@@ -203,7 +207,14 @@ SQL
topic_time = max_time_per_post if topic_time > max_time_per_post
- TopicUser.update_last_read(current_user, topic_id, highest_seen, new_posts_read, topic_time, opts)
+ TopicUser.update_last_read(
+ current_user,
+ topic_id,
+ highest_seen,
+ new_posts_read,
+ topic_time,
+ opts,
+ )
TopicGroup.update_last_read(current_user, topic_id, highest_seen)
if total_changed > 0
diff --git a/app/models/previous_replies_site_setting.rb b/app/models/previous_replies_site_setting.rb
index 59b7c2d246e..ff1ed64b9a0 100644
--- a/app/models/previous_replies_site_setting.rb
+++ b/app/models/previous_replies_site_setting.rb
@@ -1,22 +1,19 @@
# frozen_string_literal: true
class PreviousRepliesSiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
- val.to_i.to_s == val.to_s &&
- values.any? { |v| v[:value] == val.to_i }
+ val.to_i.to_s == val.to_s && values.any? { |v| v[:value] == val.to_i }
end
def self.values
@values ||= [
- { name: 'user.email_previous_replies.always', value: 0 },
- { name: 'user.email_previous_replies.unless_emailed', value: 1 },
- { name: 'user.email_previous_replies.never', value: 2 },
+ { name: "user.email_previous_replies.always", value: 0 },
+ { name: "user.email_previous_replies.unless_emailed", value: 1 },
+ { name: "user.email_previous_replies.never", value: 2 },
]
end
def self.translate_names?
true
end
-
end
diff --git a/app/models/private_message_topic_tracking_state.rb b/app/models/private_message_topic_tracking_state.rb
index cd03054c6f1..48db452375d 100644
--- a/app/models/private_message_topic_tracking_state.rb
+++ b/app/models/private_message_topic_tracking_state.rb
@@ -30,8 +30,8 @@ class PrivateMessageTopicTrackingState
sql + "\n\n LIMIT :max_topics",
{
max_topics: TopicTrackingState::MAX_TOPICS,
- min_new_topic_date: Time.at(SiteSetting.min_new_topics_time).to_datetime
- }
+ min_new_topic_date: Time.at(SiteSetting.min_new_topics_time).to_datetime,
+ },
)
end
@@ -41,9 +41,7 @@ class PrivateMessageTopicTrackingState
sql << report_raw_sql(user, skip_new: true)
end
- def self.report_raw_sql(user, skip_unread: false,
- skip_new: false)
-
+ def self.report_raw_sql(user, skip_unread: false, skip_new: false)
unread =
if skip_unread
"1=0"
@@ -101,9 +99,7 @@ class PrivateMessageTopicTrackingState
topic = post.topic
return unless topic.private_message?
- scope = TopicUser
- .tracking(post.topic_id)
- .includes(user: [:user_stat, :user_option])
+ scope = TopicUser.tracking(post.topic_id).includes(user: %i[user_stat user_option])
allowed_group_ids = topic.allowed_groups.pluck(:id)
@@ -115,9 +111,11 @@ class PrivateMessageTopicTrackingState
end
if group_ids.present?
- scope = scope
- .joins("INNER JOIN group_users gu ON gu.user_id = topic_users.user_id")
- .where("gu.group_id IN (?)", group_ids)
+ scope =
+ scope.joins("INNER JOIN group_users gu ON gu.user_id = topic_users.user_id").where(
+ "gu.group_id IN (?)",
+ group_ids,
+ )
end
# Note: At some point we may want to make the same peformance optimisation
@@ -127,31 +125,27 @@ class PrivateMessageTopicTrackingState
#
# cf. f6c852bf8e7f4dea519425ba87a114f22f52a8f4
scope
- .select([:user_id, :last_read_post_number, :notification_level])
+ .select(%i[user_id last_read_post_number notification_level])
.each do |tu|
+ if tu.last_read_post_number.nil? &&
+ topic.created_at < tu.user.user_option.treat_as_new_topic_start_date
+ next
+ end
- if tu.last_read_post_number.nil? &&
- topic.created_at < tu.user.user_option.treat_as_new_topic_start_date
-
- next
- end
-
- message = {
- topic_id: post.topic_id,
- message_type: UNREAD_MESSAGE_TYPE,
- payload: {
- last_read_post_number: tu.last_read_post_number,
- highest_post_number: post.post_number,
- notification_level: tu.notification_level,
- group_ids: allowed_group_ids,
- created_by_user_id: post.user_id
+ message = {
+ topic_id: post.topic_id,
+ message_type: UNREAD_MESSAGE_TYPE,
+ payload: {
+ last_read_post_number: tu.last_read_post_number,
+ highest_post_number: post.post_number,
+ notification_level: tu.notification_level,
+ group_ids: allowed_group_ids,
+ created_by_user_id: post.user_id,
+ },
}
- }
- MessageBus.publish(self.user_channel(tu.user_id), message.as_json,
- user_ids: [tu.user_id]
- )
- end
+ MessageBus.publish(self.user_channel(tu.user_id), message.as_json, user_ids: [tu.user_id])
+ end
end
def self.publish_new(topic)
@@ -165,16 +159,22 @@ class PrivateMessageTopicTrackingState
highest_post_number: 1,
group_ids: topic.allowed_groups.pluck(:id),
created_by_user_id: topic.user_id,
- }
+ },
}.as_json
- topic.allowed_users.pluck(:id).each do |user_id|
- MessageBus.publish(self.user_channel(user_id), message, user_ids: [user_id])
- end
+ topic
+ .allowed_users
+ .pluck(:id)
+ .each do |user_id|
+ MessageBus.publish(self.user_channel(user_id), message, user_ids: [user_id])
+ end
- topic.allowed_groups.pluck(:id).each do |group_id|
- MessageBus.publish(self.group_channel(group_id), message, group_ids: [group_id])
- end
+ topic
+ .allowed_groups
+ .pluck(:id)
+ .each do |group_id|
+ MessageBus.publish(self.group_channel(group_id), message, group_ids: [group_id])
+ end
end
def self.publish_group_archived(topic:, group_id:, acting_user_id: nil)
@@ -185,15 +185,11 @@ class PrivateMessageTopicTrackingState
topic_id: topic.id,
payload: {
group_ids: [group_id],
- acting_user_id: acting_user_id
- }
+ acting_user_id: acting_user_id,
+ },
}.as_json
- MessageBus.publish(
- self.group_channel(group_id),
- message,
- group_ids: [group_id]
- )
+ MessageBus.publish(self.group_channel(group_id), message, group_ids: [group_id])
end
def self.publish_read(topic_id, last_read_post_number, user, notification_level = nil)
@@ -203,7 +199,7 @@ class PrivateMessageTopicTrackingState
topic_id: topic_id,
user: user,
last_read_post_number: last_read_post_number,
- notification_level: notification_level
+ notification_level: notification_level,
)
end
diff --git a/app/models/published_page.rb b/app/models/published_page.rb
index 8345ae05bb6..937ba59310e 100644
--- a/app/models/published_page.rb
+++ b/app/models/published_page.rb
@@ -10,7 +10,7 @@ class PublishedPage < ActiveRecord::Base
def slug_format
if slug !~ /^[a-zA-Z\-\_0-9]+$/
errors.add(:slug, I18n.t("publish_page.slug_errors.invalid"))
- elsif ["check-slug", "by-topic"].include?(slug)
+ elsif %w[check-slug by-topic].include?(slug)
errors.add(:slug, I18n.t("publish_page.slug_errors.unavailable"))
end
end
@@ -26,16 +26,17 @@ class PublishedPage < ActiveRecord::Base
def self.publish!(publisher, topic, slug, options = {})
pp = nil
- results = transaction do
- pp = find_or_initialize_by(topic: topic)
- pp.slug = slug.strip
- pp.public = options[:public] || false
+ results =
+ transaction do
+ pp = find_or_initialize_by(topic: topic)
+ pp.slug = slug.strip
+ pp.public = options[:public] || false
- if pp.save
- StaffActionLogger.new(publisher).log_published_page(topic.id, slug)
- [true, pp]
+ if pp.save
+ StaffActionLogger.new(publisher).log_published_page(topic.id, slug)
+ [true, pp]
+ end
end
- end
results || [false, pp]
end
diff --git a/app/models/quoted_post.rb b/app/models/quoted_post.rb
index 9a6a96e9ebf..54d68c9a926 100644
--- a/app/models/quoted_post.rb
+++ b/app/models/quoted_post.rb
@@ -2,36 +2,36 @@
class QuotedPost < ActiveRecord::Base
belongs_to :post
- belongs_to :quoted_post, class_name: 'Post'
+ belongs_to :quoted_post, class_name: "Post"
# NOTE we already have a path that does this for topic links,
# however topic links exclude quotes and links within a topic
# we are double parsing this fragment, this may be worth optimising later
def self.extract_from(post)
-
doc = Nokogiri::HTML5.fragment(post.cooked)
uniq = {}
- doc.css("aside.quote[data-topic]").each do |a|
- topic_id = a['data-topic'].to_i
- post_number = a['data-post'].to_i
+ doc
+ .css("aside.quote[data-topic]")
+ .each do |a|
+ topic_id = a["data-topic"].to_i
+ post_number = a["data-post"].to_i
- next if topic_id == 0 || post_number == 0
- next if uniq[[topic_id, post_number]]
- next if post.topic_id == topic_id && post.post_number == post_number
+ next if topic_id == 0 || post_number == 0
+ next if uniq[[topic_id, post_number]]
+ next if post.topic_id == topic_id && post.post_number == post_number
- uniq[[topic_id, post_number]] = true
- end
+ uniq[[topic_id, post_number]] = true
+ end
if uniq.length == 0
DB.exec("DELETE FROM quoted_posts WHERE post_id = :post_id", post_id: post.id)
else
-
args = {
post_id: post.id,
topic_ids: uniq.keys.map(&:first),
- post_numbers: uniq.keys.map(&:second)
+ post_numbers: uniq.keys.map(&:second),
}
DB.exec(<<~SQL, args)
@@ -67,14 +67,14 @@ class QuotedPost < ActiveRecord::Base
reply_quoted = false
if post.reply_to_post_number
- reply_post_id = Post.where(topic_id: post.topic_id, post_number: post.reply_to_post_number).pluck_first(:id)
- reply_quoted = reply_post_id.present? && QuotedPost.where(post_id: post.id, quoted_post_id: reply_post_id).count > 0
- end
-
- if reply_quoted != post.reply_quoted
- post.update_columns(reply_quoted: reply_quoted)
+ reply_post_id =
+ Post.where(topic_id: post.topic_id, post_number: post.reply_to_post_number).pluck_first(:id)
+ reply_quoted =
+ reply_post_id.present? &&
+ QuotedPost.where(post_id: post.id, quoted_post_id: reply_post_id).count > 0
end
+ post.update_columns(reply_quoted: reply_quoted) if reply_quoted != post.reply_quoted
end
end
diff --git a/app/models/remote_theme.rb b/app/models/remote_theme.rb
index 2c7f4e1ed13..baed6456548 100644
--- a/app/models/remote_theme.rb
+++ b/app/models/remote_theme.rb
@@ -1,28 +1,35 @@
# frozen_string_literal: true
class RemoteTheme < ActiveRecord::Base
- METADATA_PROPERTIES = %i{
- license_url
- about_url
- authors
- theme_version
- minimum_discourse_version
- maximum_discourse_version
- }
+ METADATA_PROPERTIES = %i[
+ license_url
+ about_url
+ authors
+ theme_version
+ minimum_discourse_version
+ maximum_discourse_version
+ ]
- class ImportError < StandardError; end
+ class ImportError < StandardError
+ end
- ALLOWED_FIELDS = %w{scss embedded_scss head_tag header after_header body_tag footer}
+ ALLOWED_FIELDS = %w[scss embedded_scss head_tag header after_header body_tag footer]
- GITHUB_REGEXP = /^https?:\/\/github\.com\//
- GITHUB_SSH_REGEXP = /^ssh:\/\/git@github\.com:/
+ GITHUB_REGEXP = %r{^https?://github\.com/}
+ GITHUB_SSH_REGEXP = %r{^ssh://git@github\.com:}
has_one :theme, autosave: false
- scope :joined_remotes, -> {
- joins("JOIN themes ON themes.remote_theme_id = remote_themes.id").where.not(remote_url: "")
- }
+ scope :joined_remotes,
+ -> {
+ joins("JOIN themes ON themes.remote_theme_id = remote_themes.id").where.not(
+ remote_url: "",
+ )
+ }
- validates_format_of :minimum_discourse_version, :maximum_discourse_version, with: Discourse::VERSION_REGEXP, allow_nil: true
+ validates_format_of :minimum_discourse_version,
+ :maximum_discourse_version,
+ with: Discourse::VERSION_REGEXP,
+ allow_nil: true
def self.extract_theme_info(importer)
json = JSON.parse(importer["about.json"])
@@ -32,7 +39,14 @@ class RemoteTheme < ActiveRecord::Base
raise ImportError.new I18n.t("themes.import_error.about_json")
end
- def self.update_zipped_theme(filename, original_filename, match_theme: false, user: Discourse.system_user, theme_id: nil, update_components: nil)
+ def self.update_zipped_theme(
+ filename,
+ original_filename,
+ match_theme: false,
+ user: Discourse.system_user,
+ theme_id: nil,
+ update_components: nil
+ )
importer = ThemeStore::ZipImporter.new(filename, original_filename)
importer.import!
@@ -60,10 +74,18 @@ class RemoteTheme < ActiveRecord::Base
child_components = child_components.map { |url| ThemeStore::GitImporter.new(url.strip).url }
if update_components == "sync"
- ChildTheme.joins(child_theme: :remote_theme).where("remote_themes.remote_url NOT IN (?)", child_components).delete_all
+ ChildTheme
+ .joins(child_theme: :remote_theme)
+ .where("remote_themes.remote_url NOT IN (?)", child_components)
+ .delete_all
end
- child_components -= theme.child_themes.joins(:remote_theme).where("remote_themes.remote_url IN (?)", child_components).pluck("remote_themes.remote_url")
+ child_components -=
+ theme
+ .child_themes
+ .joins(:remote_theme)
+ .where("remote_themes.remote_url IN (?)", child_components)
+ .pluck("remote_themes.remote_url")
theme.child_components = child_components
theme.update_child_components
end
@@ -106,7 +128,9 @@ class RemoteTheme < ActiveRecord::Base
end
def self.out_of_date_themes
- self.joined_remotes.where("commits_behind > 0 OR remote_version <> local_version")
+ self
+ .joined_remotes
+ .where("commits_behind > 0 OR remote_version <> local_version")
.where(themes: { enabled: true })
.pluck("themes.name", "themes.id")
end
@@ -164,13 +188,28 @@ class RemoteTheme < ActiveRecord::Base
if path = importer.real_path(relative_path)
new_path = "#{File.dirname(path)}/#{SecureRandom.hex}#{File.extname(path)}"
File.rename(path, new_path) # OptimizedImage has strict file name restrictions, so rename temporarily
- upload = UploadCreator.new(File.open(new_path), File.basename(relative_path), for_theme: true).create_for(theme.user_id)
+ upload =
+ UploadCreator.new(
+ File.open(new_path),
+ File.basename(relative_path),
+ for_theme: true,
+ ).create_for(theme.user_id)
if !upload.errors.empty?
- raise ImportError, I18n.t("themes.import_error.upload", name: name, errors: upload.errors.full_messages.join(","))
+ raise ImportError,
+ I18n.t(
+ "themes.import_error.upload",
+ name: name,
+ errors: upload.errors.full_messages.join(","),
+ )
end
- updated_fields << theme.set_field(target: :common, name: name, type: :theme_upload_var, upload_id: upload.id)
+ updated_fields << theme.set_field(
+ target: :common,
+ name: name,
+ type: :theme_upload_var,
+ upload_id: upload.id,
+ )
end
end
@@ -185,14 +224,25 @@ class RemoteTheme < ActiveRecord::Base
self.public_send(:"#{property}=", theme_info[property.to_s])
end
if !self.valid?
- raise ImportError, I18n.t("themes.import_error.about_json_values", errors: self.errors.full_messages.join(","))
+ raise ImportError,
+ I18n.t(
+ "themes.import_error.about_json_values",
+ errors: self.errors.full_messages.join(","),
+ )
end
ThemeModifierSet.modifiers.keys.each do |modifier_name|
- theme.theme_modifier_set.public_send(:"#{modifier_name}=", theme_info.dig("modifiers", modifier_name.to_s))
+ theme.theme_modifier_set.public_send(
+ :"#{modifier_name}=",
+ theme_info.dig("modifiers", modifier_name.to_s),
+ )
end
if !theme.theme_modifier_set.valid?
- raise ImportError, I18n.t("themes.import_error.modifier_values", errors: theme.theme_modifier_set.errors.full_messages.join(","))
+ raise ImportError,
+ I18n.t(
+ "themes.import_error.modifier_values",
+ errors: theme.theme_modifier_set.errors.full_messages.join(","),
+ )
end
importer.all_files.each do |filename|
@@ -230,9 +280,7 @@ class RemoteTheme < ActiveRecord::Base
return unless hex
override = hex.downcase
- if override !~ /\A[0-9a-f]{6}\z/
- override = nil
- end
+ override = nil if override !~ /\A[0-9a-f]{6}\z/
override
end
@@ -247,8 +295,9 @@ class RemoteTheme < ActiveRecord::Base
# Update main colors
ColorScheme.base.colors_hashes.each do |color|
override = normalize_override(colors[color[:name]])
- color_scheme_color = scheme.color_scheme_colors.to_a.find { |c| c.name == color[:name] } ||
- scheme.color_scheme_colors.build(name: color[:name])
+ color_scheme_color =
+ scheme.color_scheme_colors.to_a.find { |c| c.name == color[:name] } ||
+ scheme.color_scheme_colors.build(name: color[:name])
color_scheme_color.hex = override || color[:hex]
theme.notify_color_change(color_scheme_color) if color_scheme_color.hex_changed?
end
@@ -275,9 +324,7 @@ class RemoteTheme < ActiveRecord::Base
# we may have stuff pointed at the incorrect scheme?
end
- if theme.new_record?
- theme.color_scheme = ordered_schemes.first
- end
+ theme.color_scheme = ordered_schemes.first if theme.new_record?
end
def github_diff_link
diff --git a/app/models/remove_muted_tags_from_latest_site_setting.rb b/app/models/remove_muted_tags_from_latest_site_setting.rb
index 9ca328e328f..fb07d94b7a9 100644
--- a/app/models/remove_muted_tags_from_latest_site_setting.rb
+++ b/app/models/remove_muted_tags_from_latest_site_setting.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class RemoveMutedTagsFromLatestSiteSetting < EnumSiteSetting
-
ALWAYS ||= "always"
ONLY_MUTED ||= "only_muted"
NEVER ||= "never"
@@ -14,7 +13,7 @@ class RemoveMutedTagsFromLatestSiteSetting < EnumSiteSetting
@values ||= [
{ name: "admin.tags.remove_muted_tags_from_latest.always", value: ALWAYS },
{ name: "admin.tags.remove_muted_tags_from_latest.only_muted", value: ONLY_MUTED },
- { name: "admin.tags.remove_muted_tags_from_latest.never", value: NEVER }
+ { name: "admin.tags.remove_muted_tags_from_latest.never", value: NEVER },
]
end
diff --git a/app/models/report.rb b/app/models/report.rb
index fa893edfcb4..cd9b7623ac1 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -5,7 +5,16 @@ class Report
# and you want to ensure cache is reset
SCHEMA_VERSION = 4
- FILTERS = [:name, :start_date, :end_date, :category, :group, :trust_level, :file_extension, :include_subcategories]
+ FILTERS = %i[
+ name
+ start_date
+ end_date
+ category
+ group
+ trust_level
+ file_extension
+ include_subcategories
+ ]
include Reports::PostEdits
include Reports::TopTrafficSources
@@ -51,11 +60,30 @@ class Report
include Reports::TopUsersByLikesReceivedFromInferiorTrustLevel
include Reports::TopUsersByLikesReceivedFromAVarietyOfPeople
- attr_accessor :type, :data, :total, :prev30Days, :start_date,
- :end_date, :labels, :prev_period, :facets, :limit, :average,
- :percent, :higher_is_better, :icon, :modes, :prev_data,
- :prev_start_date, :prev_end_date, :dates_filtering, :error,
- :primary_color, :secondary_color, :filters, :available_filters
+ attr_accessor :type,
+ :data,
+ :total,
+ :prev30Days,
+ :start_date,
+ :end_date,
+ :labels,
+ :prev_period,
+ :facets,
+ :limit,
+ :average,
+ :percent,
+ :higher_is_better,
+ :icon,
+ :modes,
+ :prev_data,
+ :prev_start_date,
+ :prev_end_date,
+ :dates_filtering,
+ :error,
+ :primary_color,
+ :secondary_color,
+ :filters,
+ :available_filters
def self.default_days
30
@@ -63,16 +91,8 @@ class Report
def self.default_labels
[
- {
- type: :date,
- property: :x,
- title: I18n.t("reports.default.labels.day")
- },
- {
- type: :number,
- property: :y,
- title: I18n.t("reports.default.labels.count")
- },
+ { type: :date, property: :x, title: I18n.t("reports.default.labels.day") },
+ { type: :number, property: :y, title: I18n.t("reports.default.labels.count") },
]
end
@@ -84,13 +104,13 @@ class Report
@average = false
@percent = false
@higher_is_better = true
- @modes = [:table, :chart]
+ @modes = %i[table chart]
@prev_data = nil
@dates_filtering = true
@available_filters = {}
@filters = {}
- tertiary = ColorScheme.hex_for_name('tertiary') || '0088cc'
+ tertiary = ColorScheme.hex_for_name("tertiary") || "0088cc"
@primary_color = rgba_color(tertiary)
@secondary_color = rgba_color(tertiary, 0.1)
end
@@ -105,13 +125,16 @@ class Report
report.limit,
report.filters.blank? ? nil : MultiJson.dump(report.filters),
SCHEMA_VERSION,
- ].compact.map(&:to_s).join(':')
+ ].compact.map(&:to_s).join(":")
end
def add_filter(name, options = {})
if options[:type].blank?
options[:type] = name
- Discourse.deprecate("#{name} filter should define a `:type` option. Temporarily setting type to #{name}.", drop_from: '2.9.0')
+ Discourse.deprecate(
+ "#{name} filter should define a `:type` option. Temporarily setting type to #{name}.",
+ drop_from: "2.9.0",
+ )
end
available_filters[name] = options
@@ -123,12 +146,12 @@ class Report
def add_category_filter
category_id = filters[:category].to_i if filters[:category].present?
- add_filter('category', type: 'category', default: category_id)
+ add_filter("category", type: "category", default: category_id)
return if category_id.blank?
include_subcategories = filters[:include_subcategories]
include_subcategories = !!ActiveRecord::Type::Boolean.new.cast(include_subcategories)
- add_filter('include_subcategories', type: 'bool', default: include_subcategories)
+ add_filter("include_subcategories", type: "bool", default: include_subcategories)
[category_id, include_subcategories]
end
@@ -136,12 +159,10 @@ class Report
def self.clear_cache(type = nil)
pattern = type ? "reports:#{type}:*" : "reports:*"
- Discourse.cache.keys(pattern).each do |key|
- Discourse.cache.redis.del(key)
- end
+ Discourse.cache.keys(pattern).each { |key| Discourse.cache.redis.del(key) }
end
- def self.wrap_slow_query(timeout = 20000)
+ def self.wrap_slow_query(timeout = 20_000)
ActiveRecord::Base.connection.transaction do
# Allows only read only transactions
DB.exec "SET TRANSACTION READ ONLY"
@@ -195,8 +216,12 @@ class Report
json[:prev30Days] = self.prev30Days if self.prev30Days
json[:limit] = self.limit if self.limit
- if type == 'page_view_crawler_reqs'
- json[:related_report] = Report.find('web_crawlers', start_date: start_date, end_date: end_date)&.as_json
+ if type == "page_view_crawler_reqs"
+ json[:related_report] = Report.find(
+ "web_crawlers",
+ start_date: start_date,
+ end_date: end_date,
+ )&.as_json
end
end
end
@@ -212,7 +237,7 @@ class Report
report = Report.new(type)
report.start_date = opts[:start_date] if opts[:start_date]
report.end_date = opts[:end_date] if opts[:end_date]
- report.facets = opts[:facets] || [:total, :prev30Days]
+ report.facets = opts[:facets] || %i[total prev30Days]
report.limit = opts[:limit] if opts[:limit]
report.average = opts[:average] if opts[:average]
report.percent = opts[:percent] if opts[:percent]
@@ -268,7 +293,9 @@ class Report
# given reports can be added by plugins we don’t want dashboard failures
# on report computation, however we do want to log which report is provoking
# an error
- Rails.logger.error("Error while computing report `#{report.type}`: #{e.message}\n#{e.backtrace.join("\n")}")
+ Rails.logger.error(
+ "Error while computing report `#{report.type}`: #{e.message}\n#{e.backtrace.join("\n")}",
+ )
end
report
@@ -277,32 +304,35 @@ class Report
def self.req_report(report, filter = nil)
data =
if filter == :page_view_total
- ApplicationRequest.where(req_type: [
- ApplicationRequest.req_types.reject { |k, v| k =~ /mobile/ }.map { |k, v| v if k =~ /page_view/ }.compact
- ].flatten)
+ ApplicationRequest.where(
+ req_type: [
+ ApplicationRequest
+ .req_types
+ .reject { |k, v| k =~ /mobile/ }
+ .map { |k, v| v if k =~ /page_view/ }
+ .compact,
+ ].flatten,
+ )
else
ApplicationRequest.where(req_type: ApplicationRequest.req_types[filter])
end
- if filter == :page_view_total
- report.icon = 'file'
- end
+ report.icon = "file" if filter == :page_view_total
report.data = []
- data.where('date >= ? AND date <= ?', report.start_date, report.end_date)
+ data
+ .where("date >= ? AND date <= ?", report.start_date, report.end_date)
.order(date: :asc)
.group(:date)
.sum(:count)
- .each do |date, count|
- report.data << { x: date, y: count }
- end
+ .each { |date, count| report.data << { x: date, y: count } }
report.total = data.sum(:count)
- report.prev30Days = data.where(
- 'date >= ? AND date < ?',
- (report.start_date - 31.days), report.start_date
- ).sum(:count)
+ report.prev30Days =
+ data.where("date >= ? AND date < ?", (report.start_date - 31.days), report.start_date).sum(
+ :count,
+ )
end
def self.report_about(report, subject_class, report_method = :count_per_day)
@@ -313,9 +343,9 @@ class Report
def self.basic_report_about(report, subject_class, report_method, *args)
report.data = []
- subject_class.public_send(report_method, *args).each do |date, count|
- report.data << { x: date, y: count }
- end
+ subject_class
+ .public_send(report_method, *args)
+ .each { |date, count| report.data << { x: date, y: count } }
end
def self.add_prev_data(report, subject_class, report_method, *args)
@@ -325,25 +355,27 @@ class Report
end
end
- def self.add_counts(report, subject_class, query_column = 'created_at')
+ def self.add_counts(report, subject_class, query_column = "created_at")
if report.facets.include?(:prev_period)
- prev_data = subject_class
- .where("#{query_column} >= ? and #{query_column} < ?",
+ prev_data =
+ subject_class.where(
+ "#{query_column} >= ? and #{query_column} < ?",
report.prev_start_date,
- report.prev_end_date)
+ report.prev_end_date,
+ )
report.prev_period = prev_data.count
end
- if report.facets.include?(:total)
- report.total = subject_class.count
- end
+ report.total = subject_class.count if report.facets.include?(:total)
if report.facets.include?(:prev30Days)
- report.prev30Days = subject_class
- .where("#{query_column} >= ? and #{query_column} < ?",
+ report.prev30Days =
+ subject_class.where(
+ "#{query_column} >= ? and #{query_column} < ?",
report.start_date - 30.days,
- report.start_date).count
+ report.start_date,
+ ).count
end
end
@@ -351,28 +383,43 @@ class Report
category_id, include_subcategories = report.add_category_filter
report.data = []
- PostAction.count_per_day_for_type(post_action_type, category_id: category_id, include_subcategories: include_subcategories, start_date: report.start_date, end_date: report.end_date).each do |date, count|
- report.data << { x: date, y: count }
- end
+ PostAction
+ .count_per_day_for_type(
+ post_action_type,
+ category_id: category_id,
+ include_subcategories: include_subcategories,
+ start_date: report.start_date,
+ end_date: report.end_date,
+ )
+ .each { |date, count| report.data << { x: date, y: count } }
countable = PostAction.unscoped.where(post_action_type_id: post_action_type)
if category_id
if include_subcategories
- countable = countable.joins(post: :topic).where('topics.category_id IN (?)', Category.subcategory_ids(category_id))
+ countable =
+ countable.joins(post: :topic).where(
+ "topics.category_id IN (?)",
+ Category.subcategory_ids(category_id),
+ )
else
- countable = countable.joins(post: :topic).where('topics.category_id = ?', category_id)
+ countable = countable.joins(post: :topic).where("topics.category_id = ?", category_id)
end
end
- add_counts report, countable, 'post_actions.created_at'
+ add_counts report, countable, "post_actions.created_at"
end
def self.private_messages_report(report, topic_subtype)
- report.icon = 'envelope'
- subject = Topic.where('topics.user_id > 0')
- basic_report_about report, subject, :private_message_topics_count_per_day, report.start_date, report.end_date, topic_subtype
- subject = Topic.private_messages.where('topics.user_id > 0').with_subtype(topic_subtype)
- add_counts report, subject, 'topics.created_at'
+ report.icon = "envelope"
+ subject = Topic.where("topics.user_id > 0")
+ basic_report_about report,
+ subject,
+ :private_message_topics_count_per_day,
+ report.start_date,
+ report.end_date,
+ topic_subtype
+ subject = Topic.private_messages.where("topics.user_id > 0").with_subtype(topic_subtype)
+ add_counts report, subject, "topics.created_at"
end
def lighten_color(hex, amount)
@@ -386,31 +433,27 @@ class Report
def rgba_color(hex, opacity = 1)
rgbs = hex_to_rgbs(adjust_hex(hex))
- "rgba(#{rgbs.join(',')},#{opacity})"
+ "rgba(#{rgbs.join(",")},#{opacity})"
end
private
def adjust_hex(hex)
- hex = hex.gsub('#', '')
+ hex = hex.gsub("#", "")
if hex.size == 3
chars = hex.scan(/\w/)
hex = chars.zip(chars).flatten.join
end
- if hex.size < 3
- hex = hex.ljust(6, hex.last)
- end
+ hex = hex.ljust(6, hex.last) if hex.size < 3
hex
end
def hex_to_rgbs(hex_color)
- hex_color = hex_color.gsub('#', '')
+ hex_color = hex_color.gsub("#", "")
rgbs = hex_color.scan(/../)
- rgbs
- .map! { |color| color.hex }
- .map! { |rgb| rgb.to_i }
+ rgbs.map! { |color| color.hex }.map! { |rgb| rgb.to_i }
end
end
diff --git a/app/models/reviewable.rb b/app/models/reviewable.rb
index 1d010d0cf61..8f389cb6700 100644
--- a/app/models/reviewable.rb
+++ b/app/models/reviewable.rb
@@ -4,10 +4,11 @@ class Reviewable < ActiveRecord::Base
TYPE_TO_BASIC_SERIALIZER = {
ReviewableFlaggedPost: BasicReviewableFlaggedPostSerializer,
ReviewableQueuedPost: BasicReviewableQueuedPostSerializer,
- ReviewableUser: BasicReviewableUserSerializer
+ ReviewableUser: BasicReviewableUserSerializer,
}
- class UpdateConflict < StandardError; end
+ class UpdateConflict < StandardError
+ end
class InvalidAction < StandardError
def initialize(action_id, klass)
@@ -20,9 +21,9 @@ class Reviewable < ActiveRecord::Base
attr_accessor :created_new
validates_presence_of :type, :status, :created_by_id
belongs_to :target, polymorphic: true
- belongs_to :created_by, class_name: 'User'
- belongs_to :target_created_by, class_name: 'User'
- belongs_to :reviewable_by_group, class_name: 'Group'
+ belongs_to :created_by, class_name: "User"
+ belongs_to :target_created_by, class_name: "User"
+ belongs_to :reviewable_by_group, class_name: "Group"
# Optional, for filtering
belongs_to :topic
@@ -31,34 +32,15 @@ class Reviewable < ActiveRecord::Base
has_many :reviewable_histories, dependent: :destroy
has_many :reviewable_scores, -> { order(created_at: :desc) }, dependent: :destroy
- enum :status, {
- pending: 0,
- approved: 1,
- rejected: 2,
- ignored: 3,
- deleted: 4
- }
- enum :priority, {
- low: 0,
- medium: 5,
- high: 10
- }, scopes: false, suffix: true
- enum :sensitivity, {
- disabled: 0,
- low: 9,
- medium: 6,
- high: 3
- }, scopes: false, suffix: true
+ enum :status, { pending: 0, approved: 1, rejected: 2, ignored: 3, deleted: 4 }
+ enum :priority, { low: 0, medium: 5, high: 10 }, scopes: false, suffix: true
+ enum :sensitivity, { disabled: 0, low: 9, medium: 6, high: 3 }, scopes: false, suffix: true
- after_create do
- log_history(:created, created_by)
- end
+ after_create { log_history(:created, created_by) }
- after_commit(on: :create) do
- DiscourseEvent.trigger(:reviewable_created, self)
- end
+ after_commit(on: :create) { DiscourseEvent.trigger(:reviewable_created, self) }
- after_commit(on: [:create, :update]) do
+ after_commit(on: %i[create update]) do
Jobs.enqueue(:notify_reviewable, reviewable_id: self.id) if pending?
end
@@ -119,14 +101,15 @@ class Reviewable < ActiveRecord::Base
reviewable_by_moderator: false,
potential_spam: true
)
- reviewable = new(
- target: target,
- topic: topic,
- created_by: created_by,
- reviewable_by_moderator: reviewable_by_moderator,
- payload: payload,
- potential_spam: potential_spam
- )
+ reviewable =
+ new(
+ target: target,
+ topic: topic,
+ created_by: created_by,
+ reviewable_by_moderator: reviewable_by_moderator,
+ payload: payload,
+ potential_spam: potential_spam,
+ )
reviewable.created_new!
if target.blank? || !Reviewable.where(target: target, type: reviewable.type).exists?
@@ -147,7 +130,7 @@ class Reviewable < ActiveRecord::Base
status: statuses[:pending],
id: target.id,
type: target.class.name,
- potential_spam: potential_spam == true ? true : nil
+ potential_spam: potential_spam == true ? true : nil,
}
row = DB.query_single(<<~SQL, update_args)
@@ -187,22 +170,22 @@ class Reviewable < ActiveRecord::Base
meta_topic_id: nil,
force_review: false
)
-
type_bonus = PostActionType.where(id: reviewable_score_type).pluck(:score_bonus)[0] || 0
take_action_bonus = take_action ? 5.0 : 0.0
user_accuracy_bonus = ReviewableScore.user_accuracy_bonus(user)
sub_total = ReviewableScore.calculate_score(user, type_bonus, take_action_bonus)
- rs = reviewable_scores.new(
- user: user,
- status: :pending,
- reviewable_score_type: reviewable_score_type,
- score: sub_total,
- user_accuracy_bonus: user_accuracy_bonus,
- meta_topic_id: meta_topic_id,
- take_action_bonus: take_action_bonus,
- created_at: created_at || Time.zone.now
- )
+ rs =
+ reviewable_scores.new(
+ user: user,
+ status: :pending,
+ reviewable_score_type: reviewable_score_type,
+ score: sub_total,
+ user_accuracy_bonus: user_accuracy_bonus,
+ meta_topic_id: meta_topic_id,
+ take_action_bonus: take_action_bonus,
+ created_at: created_at || Time.zone.now,
+ )
rs.reason = reason.to_s if reason
rs.save!
@@ -217,7 +200,7 @@ class Reviewable < ActiveRecord::Base
def self.set_priorities(values)
values.each do |k, v|
id = priorities[k]
- PluginStore.set('reviewables', "priority_#{id}", v) unless id.nil?
+ PluginStore.set("reviewables", "priority_#{id}", v) unless id.nil?
end
end
@@ -225,10 +208,8 @@ class Reviewable < ActiveRecord::Base
return Float::MAX if sensitivity == 0
ratio = sensitivity / sensitivities[:low].to_f
- high = (
- PluginStore.get('reviewables', "priority_#{priorities[:high]}") ||
- typical_sensitivity
- ).to_f
+ high =
+ (PluginStore.get("reviewables", "priority_#{priorities[:high]}") || typical_sensitivity).to_f
# We want this to be hard to reach
((high.to_f * ratio) * scale).truncate(2)
@@ -257,7 +238,7 @@ class Reviewable < ActiveRecord::Base
priority ||= SiteSetting.reviewable_default_visibility
id = priorities[priority]
return 0.0 if id.nil?
- PluginStore.get('reviewables', "priority_#{id}").to_f
+ PluginStore.get("reviewables", "priority_#{id}").to_f
end
def history
@@ -269,14 +250,15 @@ class Reviewable < ActiveRecord::Base
reviewable_history_type: reviewable_history_type,
status: status,
created_by: performed_by,
- edited: edited
+ edited: edited,
)
end
def apply_review_group
- return unless SiteSetting.enable_category_group_moderation? &&
- category.present? &&
- category.reviewable_by_group_id
+ unless SiteSetting.enable_category_group_moderation? && category.present? &&
+ category.reviewable_by_group_id
+ return
+ end
self.reviewable_by_group_id = category.reviewable_by_group_id
end
@@ -284,16 +266,14 @@ class Reviewable < ActiveRecord::Base
def actions_for(guardian, args = nil)
args ||= {}
- Actions.new(self, guardian).tap do |actions|
- build_actions(actions, guardian, args)
- end
+ Actions.new(self, guardian).tap { |actions| build_actions(actions, guardian, args) }
end
def editable_for(guardian, args = nil)
args ||= {}
- EditableFields.new(self, guardian, args).tap do |fields|
- build_editable_fields(fields, guardian, args)
- end
+ EditableFields
+ .new(self, guardian, args)
+ .tap { |fields| build_editable_fields(fields, guardian, args) }
end
# subclasses must implement "build_actions" to list the actions they're capable of
@@ -316,7 +296,7 @@ class Reviewable < ActiveRecord::Base
Reviewable.transaction do
increment_version!(version)
changes_json = changes.as_json
- changes_json.delete('version')
+ changes_json.delete("version")
result = save
log_history(:edited, performed_by, edited: changes_json) if result
@@ -331,7 +311,7 @@ class Reviewable < ActiveRecord::Base
args ||= {}
# Support this action or any aliases
aliases = self.class.action_aliases
- valid = [ action_id, aliases.to_a.select { |k, v| v == action_id }.map(&:first) ].flatten
+ valid = [action_id, aliases.to_a.select { |k, v| v == action_id }.map(&:first)].flatten
# Ensure the user has access to the action
actions = actions_for(Guardian.new(performed_by), args)
@@ -353,16 +333,14 @@ class Reviewable < ActiveRecord::Base
recalculate_score if result.recalculate_score
end
- if result && result.after_commit
- result.after_commit.call
- end
+ result.after_commit.call if result && result.after_commit
if update_count || result.remove_reviewable_ids.present?
Jobs.enqueue(
:notify_reviewable,
reviewable_id: self.id,
performing_username: performed_by.username,
- updated_reviewable_ids: result.remove_reviewable_ids
+ updated_reviewable_ids: result.remove_reviewable_ids,
)
end
@@ -380,7 +358,7 @@ class Reviewable < ActiveRecord::Base
reviewable_scores.pending.update_all(
status: score_status,
reviewed_by_id: performed_by.id,
- reviewed_at: Time.zone.now
+ reviewed_at: Time.zone.now,
)
end
@@ -391,40 +369,45 @@ class Reviewable < ActiveRecord::Base
Discourse.deprecate(
"Reviewable#post_options is deprecated. Please use #payload instead.",
output_in_test: true,
- drop_from: '2.9.0',
+ drop_from: "2.9.0",
)
end
def self.bulk_perform_targets(performed_by, action, type, target_ids, args = nil)
args ||= {}
- viewable_by(performed_by).where(type: type, target_id: target_ids).each do |r|
- r.perform(performed_by, action, args)
- end
+ viewable_by(performed_by)
+ .where(type: type, target_id: target_ids)
+ .each { |r| r.perform(performed_by, action, args) }
end
def self.viewable_by(user, order: nil, preload: true)
return none unless user.present?
- result = self.order(order || 'reviewables.score desc, reviewables.created_at desc')
+ result = self.order(order || "reviewables.score desc, reviewables.created_at desc")
if preload
- result = result.includes(
- { created_by: :user_stat },
- :topic,
- :target,
- :target_created_by,
- :reviewable_histories
- ).includes(reviewable_scores: { user: :user_stat, meta_topic: :posts })
+ result =
+ result.includes(
+ { created_by: :user_stat },
+ :topic,
+ :target,
+ :target_created_by,
+ :reviewable_histories,
+ ).includes(reviewable_scores: { user: :user_stat, meta_topic: :posts })
end
return result if user.admin?
- group_ids = SiteSetting.enable_category_group_moderation? ? user.group_users.pluck(:group_id) : []
+ group_ids =
+ SiteSetting.enable_category_group_moderation? ? user.group_users.pluck(:group_id) : []
result.where(
- '(reviewables.reviewable_by_moderator AND :staff) OR (reviewables.reviewable_by_group_id IN (:group_ids))',
+ "(reviewables.reviewable_by_moderator AND :staff) OR (reviewables.reviewable_by_group_id IN (:group_ids))",
staff: user.staff?,
- group_ids: group_ids
- ).where("reviewables.category_id IS NULL OR reviewables.category_id IN (?)", Guardian.new(user).allowed_category_ids)
+ group_ids: group_ids,
+ ).where(
+ "reviewables.category_id IS NULL OR reviewables.category_id IN (?)",
+ Guardian.new(user).allowed_category_ids,
+ )
end
def self.pending_count(user)
@@ -454,16 +437,17 @@ class Reviewable < ActiveRecord::Base
preload: true,
include_claimed_by_others: true
)
- order = case sort_order
- when 'score_asc'
- 'reviewables.score ASC, reviewables.created_at DESC'
- when 'created_at'
- 'reviewables.created_at DESC, reviewables.score DESC'
- when 'created_at_asc'
- 'reviewables.created_at ASC, reviewables.score DESC'
- else
- 'reviewables.score DESC, reviewables.created_at DESC'
- end
+ order =
+ case sort_order
+ when "score_asc"
+ "reviewables.score ASC, reviewables.created_at DESC"
+ when "created_at"
+ "reviewables.created_at DESC, reviewables.score DESC"
+ when "created_at_asc"
+ "reviewables.created_at ASC, reviewables.score DESC"
+ else
+ "reviewables.score DESC, reviewables.created_at DESC"
+ end
if username.present?
user_id = User.find_by_username(username)&.id
@@ -475,9 +459,9 @@ class Reviewable < ActiveRecord::Base
result = by_status(result, status)
result = result.where(id: ids) if ids
- result = result.where('reviewables.type = ?', type) if type
- result = result.where('reviewables.category_id = ?', category_id) if category_id
- result = result.where('reviewables.topic_id = ?', topic_id) if topic_id
+ result = result.where("reviewables.type = ?", type) if type
+ result = result.where("reviewables.category_id = ?", category_id) if category_id
+ result = result.where("reviewables.topic_id = ?", topic_id) if topic_id
result = result.where("reviewables.created_at >= ?", from_date) if from_date
result = result.where("reviewables.created_at <= ?", to_date) if to_date
@@ -485,7 +469,7 @@ class Reviewable < ActiveRecord::Base
reviewed_by_id = User.find_by_username(reviewed_by)&.id
return none if reviewed_by_id.nil?
- result = result.joins(<<~SQL
+ result = result.joins(<<~SQL)
INNER JOIN(
SELECT reviewable_id
FROM reviewable_histories
@@ -493,7 +477,6 @@ class Reviewable < ActiveRecord::Base
status <> #{statuses[:pending]} AND created_by_id = #{reviewed_by_id}
) AS rh ON rh.reviewable_id = reviewables.id
SQL
- )
end
min_score = min_score_for_priority(priority)
@@ -505,28 +488,31 @@ class Reviewable < ActiveRecord::Base
end
if !custom_filters.empty?
- result = custom_filters.reduce(result) do |memo, filter|
- key = filter.first
- filter_query = filter.last
+ result =
+ custom_filters.reduce(result) do |memo, filter|
+ key = filter.first
+ filter_query = filter.last
- next(memo) unless additional_filters[key]
- filter_query.call(result, additional_filters[key])
- end
+ next(memo) unless additional_filters[key]
+ filter_query.call(result, additional_filters[key])
+ end
end
# If a reviewable doesn't have a target, allow us to filter on who created that reviewable.
if user_id
- result = result.where(
- "(reviewables.target_created_by_id IS NULL AND reviewables.created_by_id = :user_id)
+ result =
+ result.where(
+ "(reviewables.target_created_by_id IS NULL AND reviewables.created_by_id = :user_id)
OR (reviewables.target_created_by_id = :user_id)",
- user_id: user_id
- )
+ user_id: user_id,
+ )
end
if !include_claimed_by_others
- result = result
- .joins("LEFT JOIN reviewable_claimed_topics rct ON reviewables.topic_id = rct.topic_id")
- .where("rct.user_id IS NULL OR rct.user_id = ?", user.id)
+ result =
+ result.joins(
+ "LEFT JOIN reviewable_claimed_topics rct ON reviewables.topic_id = rct.topic_id",
+ ).where("rct.user_id IS NULL OR rct.user_id = ?", user.id)
end
result = result.limit(limit) if limit
result = result.offset(offset) if offset
@@ -536,10 +522,7 @@ class Reviewable < ActiveRecord::Base
def self.unseen_list_for(user, preload: true, limit: nil)
results = list_for(user, preload: preload, limit: limit, include_claimed_by_others: false)
if user.last_seen_reviewable_id
- results = results.where(
- "reviewables.id > ?",
- user.last_seen_reviewable_id
- )
+ results = results.where("reviewables.id > ?", user.last_seen_reviewable_id)
end
results
end
@@ -584,7 +567,8 @@ class Reviewable < ActiveRecord::Base
end
def self.count_by_date(start_date, end_date, category_id = nil, include_subcategories = false)
- query = scores_with_topics.where('reviewable_scores.created_at BETWEEN ? AND ?', start_date, end_date)
+ query =
+ scores_with_topics.where("reviewable_scores.created_at BETWEEN ? AND ?", start_date, end_date)
if category_id
if include_subcategories
@@ -596,7 +580,7 @@ class Reviewable < ActiveRecord::Base
query
.group("date(reviewable_scores.created_at)")
- .order('date(reviewable_scores.created_at)')
+ .order("date(reviewable_scores.created_at)")
.count
end
@@ -634,12 +618,13 @@ class Reviewable < ActiveRecord::Base
RETURNING score
SQL
- result = DB.query(
- sql,
- id: self.id,
- pending: ReviewableScore.statuses[:pending],
- agreed: ReviewableScore.statuses[:agreed]
- )
+ result =
+ DB.query(
+ sql,
+ id: self.id,
+ pending: ReviewableScore.statuses[:pending],
+ agreed: ReviewableScore.statuses[:agreed],
+ )
# Update topic score
sql = <<~SQL
@@ -657,7 +642,7 @@ class Reviewable < ActiveRecord::Base
sql,
topic_id: topic_id,
pending: self.class.statuses[:pending],
- approved: self.class.statuses[:approved]
+ approved: self.class.statuses[:approved],
)
self.score = result[0].score
@@ -668,44 +653,47 @@ class Reviewable < ActiveRecord::Base
end
def delete_user_actions(actions, require_reject_reason: false)
- reject = actions.add_bundle(
- 'reject_user',
- icon: 'user-times',
- label: 'reviewables.actions.reject_user.title'
- )
+ reject =
+ actions.add_bundle(
+ "reject_user",
+ icon: "user-times",
+ label: "reviewables.actions.reject_user.title",
+ )
actions.add(:delete_user, bundle: reject) do |a|
- a.icon = 'user-times'
+ a.icon = "user-times"
a.label = "reviewables.actions.reject_user.delete.title"
a.require_reject_reason = require_reject_reason
a.description = "reviewables.actions.reject_user.delete.description"
end
actions.add(:delete_user_block, bundle: reject) do |a|
- a.icon = 'ban'
+ a.icon = "ban"
a.label = "reviewables.actions.reject_user.block.title"
a.require_reject_reason = require_reject_reason
a.description = "reviewables.actions.reject_user.block.description"
end
end
-protected
+ protected
def increment_version!(version = nil)
version_result = nil
if version
- version_result = DB.query_single(
- "UPDATE reviewables SET version = version + 1 WHERE id = :id AND version = :version RETURNING version",
- version: version,
- id: self.id
- )
+ version_result =
+ DB.query_single(
+ "UPDATE reviewables SET version = version + 1 WHERE id = :id AND version = :version RETURNING version",
+ version: version,
+ id: self.id,
+ )
else
# We didn't supply a version to update safely, so just increase it
- version_result = DB.query_single(
- "UPDATE reviewables SET version = version + 1 WHERE id = :id RETURNING version",
- id: self.id
- )
+ version_result =
+ DB.query_single(
+ "UPDATE reviewables SET version = version + 1 WHERE id = :id RETURNING version",
+ id: self.id,
+ )
end
if version_result && version_result[0]
@@ -725,10 +713,10 @@ protected
end
end
-private
+ private
def update_flag_stats(status:, user_ids:)
- return unless [:agreed, :disagreed, :ignored].include?(status)
+ return unless %i[agreed disagreed ignored].include?(status)
# Don't count self-flags
user_ids -= [post&.user_id]
@@ -741,7 +729,8 @@ private
RETURNING user_id, flags_agreed + flags_disagreed + flags_ignored AS total
SQL
- user_ids = result.select { |r| r.total > Jobs::TruncateUserFlagStats.truncate_to }.map(&:user_id)
+ user_ids =
+ result.select { |r| r.total > Jobs::TruncateUserFlagStats.truncate_to }.map(&:user_id)
return if user_ids.blank?
Jobs.enqueue(:truncate_user_flag_stats, user_ids: user_ids)
diff --git a/app/models/reviewable_claimed_topic.rb b/app/models/reviewable_claimed_topic.rb
index dc54c4abf14..a4b81864c70 100644
--- a/app/models/reviewable_claimed_topic.rb
+++ b/app/models/reviewable_claimed_topic.rb
@@ -7,10 +7,11 @@ class ReviewableClaimedTopic < ActiveRecord::Base
def self.claimed_hash(topic_ids)
result = {}
- if SiteSetting.reviewable_claiming != 'disabled'
- ReviewableClaimedTopic.where(topic_id: topic_ids).includes(:user).each do |rct|
- result[rct.topic_id] = rct.user
- end
+ if SiteSetting.reviewable_claiming != "disabled"
+ ReviewableClaimedTopic
+ .where(topic_id: topic_ids)
+ .includes(:user)
+ .each { |rct| result[rct.topic_id] = rct.user }
end
result
end
diff --git a/app/models/reviewable_flagged_post.rb b/app/models/reviewable_flagged_post.rb
index 44011bf6fbf..8015cd6e127 100644
--- a/app/models/reviewable_flagged_post.rb
+++ b/app/models/reviewable_flagged_post.rb
@@ -1,16 +1,16 @@
# frozen_string_literal: true
class ReviewableFlaggedPost < Reviewable
- scope :pending_and_default_visible, -> {
- pending.default_visible
- }
+ scope :pending_and_default_visible, -> { pending.default_visible }
# Penalties are handled by the modal after the action is performed
def self.action_aliases
- { agree_and_keep_hidden: :agree_and_keep,
+ {
+ agree_and_keep_hidden: :agree_and_keep,
agree_and_silence: :agree_and_keep,
agree_and_suspend: :agree_and_keep,
- disagree_and_restore: :disagree }
+ disagree_and_restore: :disagree,
+ }
end
def self.counts_for(posts)
@@ -43,68 +43,84 @@ class ReviewableFlaggedPost < Reviewable
return unless pending?
return if post.blank?
- agree = actions.add_bundle("#{id}-agree", icon: 'thumbs-up', label: 'reviewables.actions.agree.title')
+ agree =
+ actions.add_bundle("#{id}-agree", icon: "thumbs-up", label: "reviewables.actions.agree.title")
if !post.user_deleted? && !post.hidden?
- build_action(actions, :agree_and_hide, icon: 'far-eye-slash', bundle: agree)
+ build_action(actions, :agree_and_hide, icon: "far-eye-slash", bundle: agree)
end
if post.hidden?
- build_action(actions, :agree_and_keep_hidden, icon: 'thumbs-up', bundle: agree)
+ build_action(actions, :agree_and_keep_hidden, icon: "thumbs-up", bundle: agree)
else
- build_action(actions, :agree_and_keep, icon: 'thumbs-up', bundle: agree)
+ build_action(actions, :agree_and_keep, icon: "thumbs-up", bundle: agree)
end
if guardian.can_suspend?(target_created_by)
- build_action(actions, :agree_and_suspend, icon: 'ban', bundle: agree, client_action: 'suspend')
- build_action(actions, :agree_and_silence, icon: 'microphone-slash', bundle: agree, client_action: 'silence')
+ build_action(
+ actions,
+ :agree_and_suspend,
+ icon: "ban",
+ bundle: agree,
+ client_action: "suspend",
+ )
+ build_action(
+ actions,
+ :agree_and_silence,
+ icon: "microphone-slash",
+ bundle: agree,
+ client_action: "silence",
+ )
end
- if post.user_deleted?
- build_action(actions, :agree_and_restore, icon: 'far-eye', bundle: agree)
- end
+ build_action(actions, :agree_and_restore, icon: "far-eye", bundle: agree) if post.user_deleted?
if post.hidden?
- build_action(actions, :disagree_and_restore, icon: 'thumbs-down')
+ build_action(actions, :disagree_and_restore, icon: "thumbs-down")
else
- build_action(actions, :disagree, icon: 'thumbs-down')
+ build_action(actions, :disagree, icon: "thumbs-down")
end
- build_action(actions, :ignore, icon: 'external-link-alt')
+ build_action(actions, :ignore, icon: "external-link-alt")
- if potential_spam? && guardian.can_delete_user?(target_created_by)
- delete_user_actions(actions)
- end
+ delete_user_actions(actions) if potential_spam? && guardian.can_delete_user?(target_created_by)
if guardian.can_delete_post_or_topic?(post)
- delete = actions.add_bundle("#{id}-delete", icon: "far-trash-alt", label: "reviewables.actions.delete.title")
- build_action(actions, :delete_and_ignore, icon: 'external-link-alt', bundle: delete)
+ delete =
+ actions.add_bundle(
+ "#{id}-delete",
+ icon: "far-trash-alt",
+ label: "reviewables.actions.delete.title",
+ )
+ build_action(actions, :delete_and_ignore, icon: "external-link-alt", bundle: delete)
if post.reply_count > 0
build_action(
actions,
:delete_and_ignore_replies,
- icon: 'external-link-alt',
+ icon: "external-link-alt",
confirm: true,
- bundle: delete
+ bundle: delete,
)
end
- build_action(actions, :delete_and_agree, icon: 'thumbs-up', bundle: delete)
+ build_action(actions, :delete_and_agree, icon: "thumbs-up", bundle: delete)
if post.reply_count > 0
build_action(
actions,
:delete_and_agree_replies,
- icon: 'external-link-alt',
+ icon: "external-link-alt",
bundle: delete,
- confirm: true
+ confirm: true,
)
end
end
end
def perform_ignore(performed_by, args)
- actions = PostAction.active
- .where(post_id: target_id)
- .where(post_action_type_id: PostActionType.notify_flag_type_ids)
+ actions =
+ PostAction
+ .active
+ .where(post_id: target_id)
+ .where(post_action_type_id: PostActionType.notify_flag_type_ids)
actions.each do |action|
action.deferred_at = Time.zone.now
@@ -142,9 +158,7 @@ class ReviewableFlaggedPost < Reviewable
def perform_delete_user_block(performed_by, args)
delete_options = delete_opts
- if Rails.env.production?
- delete_options.merge!(block_email: true, block_ip: true)
- end
+ delete_options.merge!(block_email: true, block_ip: true) if Rails.env.production?
UserDestroyer.new(performed_by).destroy(post.user, delete_options)
@@ -152,15 +166,11 @@ class ReviewableFlaggedPost < Reviewable
end
def perform_agree_and_hide(performed_by, args)
- agree(performed_by, args) do |pa|
- post.hide!(pa.post_action_type_id)
- end
+ agree(performed_by, args) { |pa| post.hide!(pa.post_action_type_id) }
end
def perform_agree_and_restore(performed_by, args)
- agree(performed_by, args) do
- PostDestroyer.new(performed_by, post).recover
- end
+ agree(performed_by, args) { PostDestroyer.new(performed_by, post).recover }
end
def perform_disagree(performed_by, args)
@@ -172,7 +182,8 @@ class ReviewableFlaggedPost < Reviewable
PostActionType.notify_flag_type_ids
end
- actions = PostAction.active.where(post_id: target_id).where(post_action_type_id: action_type_ids)
+ actions =
+ PostAction.active.where(post_id: target_id).where(post_action_type_id: action_type_ids)
actions.each do |action|
action.disagreed_at = Time.zone.now
@@ -234,12 +245,14 @@ class ReviewableFlaggedPost < Reviewable
result
end
-protected
+ protected
def agree(performed_by, args)
- actions = PostAction.active
- .where(post_id: target_id)
- .where(post_action_type_id: PostActionType.notify_flag_types.values)
+ actions =
+ PostAction
+ .active
+ .where(post_id: target_id)
+ .where(post_action_type_id: PostActionType.notify_flag_types.values)
trigger_spam = false
actions.each do |action|
@@ -270,7 +283,15 @@ protected
end
end
- def build_action(actions, id, icon:, button_class: nil, bundle: nil, client_action: nil, confirm: false)
+ def build_action(
+ actions,
+ id,
+ icon:,
+ button_class: nil,
+ bundle: nil,
+ client_action: nil,
+ confirm: false
+ )
actions.add(id, bundle: bundle) do |action|
prefix = "reviewables.actions.#{id}"
action.icon = icon
@@ -284,15 +305,14 @@ protected
def unassign_topic(performed_by, post)
topic = post.topic
- return unless topic && performed_by && SiteSetting.reviewable_claiming != 'disabled'
+ return unless topic && performed_by && SiteSetting.reviewable_claiming != "disabled"
ReviewableClaimedTopic.where(topic_id: topic.id).delete_all
- topic.reviewables.find_each do |reviewable|
- reviewable.log_history(:unclaimed, performed_by)
- end
+ topic.reviewables.find_each { |reviewable| reviewable.log_history(:unclaimed, performed_by) }
user_ids = User.staff.pluck(:id)
- if SiteSetting.enable_category_group_moderation? && group_id = topic.category&.reviewable_by_group_id.presence
+ if SiteSetting.enable_category_group_moderation? &&
+ group_id = topic.category&.reviewable_by_group_id.presence
user_ids.concat(GroupUser.where(group_id: group_id).pluck(:user_id))
user_ids.uniq!
end
@@ -302,7 +322,7 @@ protected
MessageBus.publish("/reviewable_claimed", data, user_ids: user_ids)
end
-private
+ private
def delete_opts
{
@@ -310,7 +330,7 @@ private
prepare_for_destroy: true,
block_urls: true,
delete_as_spammer: true,
- context: "review"
+ context: "review",
}
end
@@ -327,8 +347,8 @@ private
message_type: "flags_disagreed",
message_options: {
flagged_post_raw_content: post.raw,
- url: post.url
- }
+ url: post.url,
+ },
)
end
end
diff --git a/app/models/reviewable_history.rb b/app/models/reviewable_history.rb
index c01d41a9357..b5df88cb421 100644
--- a/app/models/reviewable_history.rb
+++ b/app/models/reviewable_history.rb
@@ -2,24 +2,12 @@
class ReviewableHistory < ActiveRecord::Base
belongs_to :reviewable
- belongs_to :created_by, class_name: 'User'
+ belongs_to :created_by, class_name: "User"
- enum status: {
- pending: 0,
- approved: 1,
- rejected: 2,
- ignored: 3,
- deleted: 4
- }
+ enum status: { pending: 0, approved: 1, rejected: 2, ignored: 3, deleted: 4 }
alias_attribute :type, :reviewable_history_type
- enum type: {
- created: 0,
- transitioned: 1,
- edited: 2,
- claimed: 3,
- unclaimed: 4
- }
+ enum type: { created: 0, transitioned: 1, edited: 2, claimed: 3, unclaimed: 4 }
end
# == Schema Information
diff --git a/app/models/reviewable_post.rb b/app/models/reviewable_post.rb
index 983a96c0549..f9fb8afb37c 100644
--- a/app/models/reviewable_post.rb
+++ b/app/models/reviewable_post.rb
@@ -9,7 +9,10 @@ class ReviewablePost < Reviewable
return unless SiteSetting.review_every_post
return if post.post_type != Post.types[:regular] || post.topic.private_message?
return if Reviewable.pending.where(target: post).exists?
- return if created_or_edited_by.bot? || created_or_edited_by.staff? || created_or_edited_by.has_trust_level?(TrustLevel[4])
+ if created_or_edited_by.bot? || created_or_edited_by.staff? ||
+ created_or_edited_by.has_trust_level?(TrustLevel[4])
+ return
+ end
system_user = Discourse.system_user
needs_review!(
@@ -17,13 +20,9 @@ class ReviewablePost < Reviewable
topic: post.topic,
created_by: system_user,
reviewable_by_moderator: true,
- potential_spam: false
+ potential_spam: false,
).tap do |reviewable|
- reviewable.add_score(
- system_user,
- ReviewableScore.types[:needs_approval],
- force_review: true
- )
+ reviewable.add_score(system_user, ReviewableScore.types[:needs_approval], force_review: true)
end
end
@@ -31,26 +30,41 @@ class ReviewablePost < Reviewable
return unless pending?
if post.trashed? && guardian.can_recover_post?(post)
- build_action(actions, :approve_and_restore, icon: 'check')
+ build_action(actions, :approve_and_restore, icon: "check")
elsif post.hidden?
- build_action(actions, :approve_and_unhide, icon: 'check')
+ build_action(actions, :approve_and_unhide, icon: "check")
else
- build_action(actions, :approve, icon: 'check')
+ build_action(actions, :approve, icon: "check")
end
- reject = actions.add_bundle(
- "#{id}-reject", icon: 'times', label: 'reviewables.actions.reject.bundle_title'
- )
+ reject =
+ actions.add_bundle(
+ "#{id}-reject",
+ icon: "times",
+ label: "reviewables.actions.reject.bundle_title",
+ )
if post.trashed?
- build_action(actions, :reject_and_keep_deleted, icon: 'trash-alt', bundle: reject)
+ build_action(actions, :reject_and_keep_deleted, icon: "trash-alt", bundle: reject)
elsif guardian.can_delete_post_or_topic?(post)
- build_action(actions, :reject_and_delete, icon: 'trash-alt', bundle: reject)
+ build_action(actions, :reject_and_delete, icon: "trash-alt", bundle: reject)
end
if guardian.can_suspend?(target_created_by)
- build_action(actions, :reject_and_suspend, icon: 'ban', bundle: reject, client_action: 'suspend')
- build_action(actions, :reject_and_silence, icon: 'microphone-slash', bundle: reject, client_action: 'silence')
+ build_action(
+ actions,
+ :reject_and_suspend,
+ icon: "ban",
+ bundle: reject,
+ client_action: "suspend",
+ )
+ build_action(
+ actions,
+ :reject_and_silence,
+ icon: "microphone-slash",
+ bundle: reject,
+ client_action: "silence",
+ )
end
end
@@ -90,7 +104,15 @@ class ReviewablePost < Reviewable
@post ||= (target || Post.with_deleted.find_by(id: target_id))
end
- def build_action(actions, id, icon:, button_class: nil, bundle: nil, client_action: nil, confirm: false)
+ def build_action(
+ actions,
+ id,
+ icon:,
+ button_class: nil,
+ bundle: nil,
+ client_action: nil,
+ confirm: false
+ )
actions.add(id, bundle: bundle) do |action|
prefix = "reviewables.actions.#{id}"
action.icon = icon
@@ -103,7 +125,7 @@ class ReviewablePost < Reviewable
end
def successful_transition(to_state, recalculate_score: true)
- create_result(:success, to_state) do |result|
+ create_result(:success, to_state) do |result|
result.recalculate_score = recalculate_score
result.update_flag_stats = { status: to_state, user_ids: [created_by_id] }
end
diff --git a/app/models/reviewable_priority_setting.rb b/app/models/reviewable_priority_setting.rb
index 42afd497758..04547837a45 100644
--- a/app/models/reviewable_priority_setting.rb
+++ b/app/models/reviewable_priority_setting.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ReviewablePrioritySetting < EnumSiteSetting
-
def self.valid_value?(val)
values.any? { |v| v[:value].to_s == val.to_s }
end
@@ -15,5 +14,4 @@ class ReviewablePrioritySetting < EnumSiteSetting
def self.translate_names?
false
end
-
end
diff --git a/app/models/reviewable_queued_post.rb b/app/models/reviewable_queued_post.rb
index 928b841060c..ecf6297cdcd 100644
--- a/app/models/reviewable_queued_post.rb
+++ b/app/models/reviewable_queued_post.rb
@@ -1,15 +1,15 @@
# frozen_string_literal: true
class ReviewableQueuedPost < Reviewable
-
after_create do
# Backwards compatibility, new code should listen for `reviewable_created`
DiscourseEvent.trigger(:queued_post_created, self)
end
after_save do
- if saved_change_to_payload? && self.status == Reviewable.statuses[:pending] && self.payload&.[]('raw').present?
- upload_ids = Upload.extract_upload_ids(self.payload['raw'])
+ if saved_change_to_payload? && self.status == Reviewable.statuses[:pending] &&
+ self.payload&.[]("raw").present?
+ upload_ids = Upload.extract_upload_ids(self.payload["raw"])
UploadReference.ensure_exist!(upload_ids: upload_ids, target: self)
end
end
@@ -17,18 +17,16 @@ class ReviewableQueuedPost < Reviewable
after_commit :compute_user_stats, only: %i[create update]
def build_actions(actions, guardian, args)
-
unless approved?
-
if topic&.closed?
actions.add(:approve_post_closed) do |a|
- a.icon = 'check'
+ a.icon = "check"
a.label = "reviewables.actions.approve_post.title"
a.confirm_message = "reviewables.actions.approve_post.confirm_closed"
end
else
actions.add(:approve_post) do |a|
- a.icon = 'check'
+ a.icon = "check"
a.label = "reviewables.actions.approve_post.title"
end
end
@@ -36,32 +34,28 @@ class ReviewableQueuedPost < Reviewable
unless rejected?
actions.add(:reject_post) do |a|
- a.icon = 'times'
+ a.icon = "times"
a.label = "reviewables.actions.reject_post.title"
end
end
- if pending? && guardian.can_delete_user?(created_by)
- delete_user_actions(actions)
- end
+ delete_user_actions(actions) if pending? && guardian.can_delete_user?(created_by)
actions.add(:delete) if guardian.can_delete?(self)
end
def build_editable_fields(fields, guardian, args)
-
# We can edit category / title if it's a new topic
if topic_id.blank?
-
# Only staff can edit category for now, since in theory a category group reviewer could
# post in a category they don't have access to.
- fields.add('category_id', :category) if guardian.is_staff?
+ fields.add("category_id", :category) if guardian.is_staff?
- fields.add('payload.title', :text)
- fields.add('payload.tags', :tags)
+ fields.add("payload.title", :text)
+ fields.add("payload.tags", :tags)
end
- fields.add('payload.raw', :editor)
+ fields.add("payload.raw", :editor)
end
def create_options
@@ -74,12 +68,13 @@ class ReviewableQueuedPost < Reviewable
def perform_approve_post(performed_by, args)
created_post = nil
- opts = create_options.merge(
- skip_validations: true,
- skip_jobs: true,
- skip_events: true,
- skip_guardian: true
- )
+ opts =
+ create_options.merge(
+ skip_validations: true,
+ skip_jobs: true,
+ skip_events: true,
+ skip_guardian: true,
+ )
opts.merge!(guardian: Guardian.new(performed_by)) if performed_by.staff?
creator = PostCreator.new(created_by, opts)
@@ -90,9 +85,7 @@ class ReviewableQueuedPost < Reviewable
end
self.target = created_post
- if topic_id.nil?
- self.topic_id = created_post.topic_id
- end
+ self.topic_id = created_post.topic_id if topic_id.nil?
save
UserSilencer.unsilence(created_by, performed_by) if created_by.silenced?
@@ -107,17 +100,17 @@ class ReviewableQueuedPost < Reviewable
user_id: created_by.id,
data: { post_url: created_post.url }.to_json,
topic_id: created_post.topic_id,
- post_number: created_post.post_number
+ post_number: created_post.post_number,
)
create_result(:success, :approved) do |result|
result.created_post = created_post
# Do sidekiq work outside of the transaction
- result.after_commit = -> {
+ result.after_commit = -> do
creator.enqueue_jobs
creator.trigger_after_events
- }
+ end
end
end
@@ -145,9 +138,7 @@ class ReviewableQueuedPost < Reviewable
def perform_delete_user_block(performed_by, args)
delete_options = delete_opts
- if Rails.env.production?
- delete_options.merge!(block_email: true, block_ip: true)
- end
+ delete_options.merge!(block_email: true, block_ip: true) if Rails.env.production?
delete_user(performed_by, delete_options)
end
@@ -162,10 +153,10 @@ class ReviewableQueuedPost < Reviewable
def delete_opts
{
- context: I18n.t('reviewables.actions.delete_user.reason'),
+ context: I18n.t("reviewables.actions.delete_user.reason"),
delete_posts: true,
block_urls: true,
- delete_as_spammer: true
+ delete_as_spammer: true,
}
end
@@ -175,8 +166,7 @@ class ReviewableQueuedPost < Reviewable
end
def status_changed_from_or_to_pending?
- saved_change_to_id?(from: nil) && pending? ||
- saved_change_to_status?(from: "pending")
+ saved_change_to_id?(from: nil) && pending? || saved_change_to_status?(from: "pending")
end
end
diff --git a/app/models/reviewable_score.rb b/app/models/reviewable_score.rb
index 2d650b41317..774a5385333 100644
--- a/app/models/reviewable_score.rb
+++ b/app/models/reviewable_score.rb
@@ -3,22 +3,15 @@
class ReviewableScore < ActiveRecord::Base
belongs_to :reviewable
belongs_to :user
- belongs_to :reviewed_by, class_name: 'User'
- belongs_to :meta_topic, class_name: 'Topic'
+ belongs_to :reviewed_by, class_name: "User"
+ belongs_to :meta_topic, class_name: "Topic"
- enum status: {
- pending: 0,
- agreed: 1,
- disagreed: 2,
- ignored: 3
- }
+ enum status: { pending: 0, agreed: 1, disagreed: 2, ignored: 3 }
# To keep things simple the types correspond to `PostActionType` for backwards
# compatibility, but we can add extra reasons for scores.
def self.types
- @types ||= PostActionType.flag_types.merge(
- needs_approval: 9
- )
+ @types ||= PostActionType.flag_types.merge(needs_approval: 9)
end
# When extending post action flags, we need to call this method in order to
@@ -31,17 +24,11 @@ class ReviewableScore < ActiveRecord::Base
def self.add_new_types(type_names)
next_id = types.values.max + 1
- type_names.each_with_index do |name, idx|
- @types[name] = next_id + idx
- end
+ type_names.each_with_index { |name, idx| @types[name] = next_id + idx }
end
def self.score_transitions
- {
- approved: statuses[:agreed],
- rejected: statuses[:disagreed],
- ignored: statuses[:ignored]
- }
+ { approved: statuses[:agreed], rejected: statuses[:disagreed], ignored: statuses[:ignored] }
end
def score_type
@@ -88,22 +75,21 @@ class ReviewableScore < ActiveRecord::Base
bottom = positive_accuracy ? accuracy_axis : 0.0
top = positive_accuracy ? 1.0 : accuracy_axis
- absolute_distance = positive_accuracy ?
- percent_correct - bottom :
- top - percent_correct
+ absolute_distance = positive_accuracy ? percent_correct - bottom : top - percent_correct
axis_distance_multiplier = 1.0 / (top - bottom)
positivity_multiplier = positive_accuracy ? 1.0 : -1.0
- (absolute_distance * axis_distance_multiplier * positivity_multiplier * (Math.log(total, 4) * 5.0))
- .round(2)
+ (
+ absolute_distance * axis_distance_multiplier * positivity_multiplier *
+ (Math.log(total, 4) * 5.0)
+ ).round(2)
end
def reviewable_conversation
return if meta_topic.blank?
Reviewable::Conversation.new(meta_topic)
end
-
end
# == Schema Information
diff --git a/app/models/reviewable_sensitivity_setting.rb b/app/models/reviewable_sensitivity_setting.rb
index c6fa405c3d6..5eb60bed4ef 100644
--- a/app/models/reviewable_sensitivity_setting.rb
+++ b/app/models/reviewable_sensitivity_setting.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ReviewableSensitivitySetting < EnumSiteSetting
-
def self.valid_value?(val)
values.any? { |v| v[:value].to_s == val.to_s }
end
@@ -15,5 +14,4 @@ class ReviewableSensitivitySetting < EnumSiteSetting
def self.translate_names?
false
end
-
end
diff --git a/app/models/reviewable_user.rb b/app/models/reviewable_user.rb
index c885c8718c6..d7d2d8da098 100644
--- a/app/models/reviewable_user.rb
+++ b/app/models/reviewable_user.rb
@@ -1,12 +1,8 @@
# frozen_string_literal: true
class ReviewableUser < Reviewable
-
def self.create_for(user)
- create(
- created_by_id: Discourse.system_user.id,
- target: user
- )
+ create(created_by_id: Discourse.system_user.id, target: user)
end
def build_actions(actions, guardian, args)
@@ -14,7 +10,7 @@ class ReviewableUser < Reviewable
if guardian.can_approve?(target)
actions.add(:approve_user) do |a|
- a.icon = 'user-plus'
+ a.icon = "user-plus"
a.label = "reviewables.actions.approve_user.title"
end
end
@@ -29,11 +25,7 @@ class ReviewableUser < Reviewable
DiscourseEvent.trigger(:user_approved, target)
if args[:send_email] != false && SiteSetting.must_approve_users?
- Jobs.enqueue(
- :critical_user_email,
- type: "signup_after_approval",
- user_id: target.id
- )
+ Jobs.enqueue(:critical_user_email, type: "signup_after_approval", user_id: target.id)
end
StaffActionLogger.new(performed_by).log_user_approve(target)
@@ -52,11 +44,9 @@ class ReviewableUser < Reviewable
if args[:send_email] && SiteSetting.must_approve_users?
# Execute job instead of enqueue because user has to exists to send email
- Jobs::CriticalUserEmail.new.execute({
- type: :signup_after_reject,
- user_id: target.id,
- reject_reason: self.reject_reason
- })
+ Jobs::CriticalUserEmail.new.execute(
+ { type: :signup_after_reject, user_id: target.id, reject_reason: self.reject_reason },
+ )
end
delete_args = {}
@@ -95,7 +85,7 @@ class ReviewableUser < Reviewable
end
def is_a_suspect_user?
- reviewable_scores.any? { |rs| rs.reason == 'suspect_user' }
+ reviewable_scores.any? { |rs| rs.reason == "suspect_user" }
end
end
diff --git a/app/models/s3_region_site_setting.rb b/app/models/s3_region_site_setting.rb
index bf7d36740e7..e7b0c2756cd 100644
--- a/app/models/s3_region_site_setting.rb
+++ b/app/models/s3_region_site_setting.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class S3RegionSiteSetting < EnumSiteSetting
-
def self.valid_value?(val)
valid_values.include? val
end
@@ -11,29 +10,29 @@ class S3RegionSiteSetting < EnumSiteSetting
end
def self.valid_values
- [
- 'ap-northeast-1',
- 'ap-northeast-2',
- 'ap-east-1',
- 'ap-south-1',
- 'ap-southeast-1',
- 'ap-southeast-2',
- 'ca-central-1',
- 'cn-north-1',
- 'cn-northwest-1',
- 'eu-central-1',
- 'eu-north-1',
- 'eu-south-1',
- 'eu-west-1',
- 'eu-west-2',
- 'eu-west-3',
- 'sa-east-1',
- 'us-east-1',
- 'us-east-2',
- 'us-gov-east-1',
- 'us-gov-west-1',
- 'us-west-1',
- 'us-west-2',
+ %w[
+ ap-northeast-1
+ ap-northeast-2
+ ap-east-1
+ ap-south-1
+ ap-southeast-1
+ ap-southeast-2
+ ca-central-1
+ cn-north-1
+ cn-northwest-1
+ eu-central-1
+ eu-north-1
+ eu-south-1
+ eu-west-1
+ eu-west-2
+ eu-west-3
+ sa-east-1
+ us-east-1
+ us-east-2
+ us-gov-east-1
+ us-gov-west-1
+ us-west-1
+ us-west-2
]
end
diff --git a/app/models/screened_email.rb b/app/models/screened_email.rb
index 3f8a604d9b1..d86fa0a0c58 100644
--- a/app/models/screened_email.rb
+++ b/app/models/screened_email.rb
@@ -5,7 +5,6 @@
# (or some other form) matches a ScreenedEmail record, an action can be
# performed based on the action_type.
class ScreenedEmail < ActiveRecord::Base
-
include ScreeningModel
default_action :block
@@ -19,11 +18,9 @@ class ScreenedEmail < ActiveRecord::Base
end
def self.canonical(email)
- name, domain = email.split('@', 2)
- name = name.gsub(/\+.*/, '')
- if ['gmail.com', 'googlemail.com'].include?(domain.downcase)
- name = name.gsub('.', '')
- end
+ name, domain = email.split("@", 2)
+ name = name.gsub(/\+.*/, "")
+ name = name.gsub(".", "") if %w[gmail.com googlemail.com].include?(domain.downcase)
"#{name}@#{domain}".downcase
end
@@ -33,18 +30,21 @@ class ScreenedEmail < ActiveRecord::Base
end
def self.should_block?(email)
-
email = canonical(email)
screened_emails = ScreenedEmail.order(created_at: :desc).limit(100)
distances = {}
- screened_emails.each { |se| distances[se.email] = levenshtein(se.email.downcase, email.downcase) }
+ screened_emails.each do |se|
+ distances[se.email] = levenshtein(se.email.downcase, email.downcase)
+ end
max_distance = SiteSetting.levenshtein_distance_spammer_emails
- screened_email = screened_emails.select { |se| distances[se.email] <= max_distance }
- .sort { |se| distances[se.email] }
- .first
+ screened_email =
+ screened_emails
+ .select { |se| distances[se.email] <= max_distance }
+ .sort { |se| distances[se.email] }
+ .first
screened_email.record_match! if screened_email
@@ -53,26 +53,19 @@ class ScreenedEmail < ActiveRecord::Base
def self.levenshtein(first, second)
matrix = [(0..first.length).to_a]
- (1..second.length).each do |j|
- matrix << [j] + [0] * (first.length)
- end
+ (1..second.length).each { |j| matrix << [j] + [0] * (first.length) }
(1..second.length).each do |i|
(1..first.length).each do |j|
if first[j - 1] == second[i - 1]
matrix[i][j] = matrix[i - 1][j - 1]
else
- matrix[i][j] = [
- matrix[i - 1][j],
- matrix[i][j - 1],
- matrix[i - 1][j - 1],
- ].min + 1
+ matrix[i][j] = [matrix[i - 1][j], matrix[i][j - 1], matrix[i - 1][j - 1]].min + 1
end
end
end
matrix.last.last
end
-
end
# == Schema Information
diff --git a/app/models/screened_ip_address.rb b/app/models/screened_ip_address.rb
index 13bf4a90922..ed6cc3d800b 100644
--- a/app/models/screened_ip_address.rb
+++ b/app/models/screened_ip_address.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'screening_model'
+require "screening_model"
# A ScreenedIpAddress record represents an IP address or subnet that is being watched,
# and possibly blocked from creating accounts.
class ScreenedIpAddress < ActiveRecord::Base
-
include ScreeningModel
default_action :block
@@ -25,7 +24,8 @@ class ScreenedIpAddress < ActiveRecord::Base
]
def self.watch(ip_address, opts = {})
- match_for_ip_address(ip_address) || create(opts.slice(:action_type).merge(ip_address: ip_address))
+ match_for_ip_address(ip_address) ||
+ create(opts.slice(:action_type).merge(ip_address: ip_address))
end
def check_for_match
@@ -60,8 +60,8 @@ class ScreenedIpAddress < ActiveRecord::Base
write_attribute(:ip_address, v)
- # this gets even messier, Ruby 1.9.2 raised a different exception to Ruby 2.0.0
- # handle both exceptions
+ # this gets even messier, Ruby 1.9.2 raised a different exception to Ruby 2.0.0
+ # handle both exceptions
rescue ArgumentError, IPAddr::InvalidAddressError
self.errors.add(:ip_address, :invalid)
end
@@ -79,7 +79,7 @@ class ScreenedIpAddress < ActiveRecord::Base
# http://www.postgresql.org/docs/9.1/static/datatype-net-types.html
# http://www.postgresql.org/docs/9.1/static/functions-net.html
ip_address = IPAddr === ip_address ? ip_address.to_cidr_s : ip_address.to_s
- order('masklen(ip_address) DESC').find_by("? <<= ip_address", ip_address)
+ order("masklen(ip_address) DESC").find_by("? <<= ip_address", ip_address)
end
def self.should_block?(ip_address)
@@ -134,31 +134,33 @@ class ScreenedIpAddress < ActiveRecord::Base
def self.roll_up(current_user = Discourse.system_user)
ROLLED_UP_BLOCKS.each do |family, from_masklen, to_masklen|
- ScreenedIpAddress.subnets(family, from_masklen, to_masklen).map do |subnet|
- next if ScreenedIpAddress.where("? <<= ip_address", subnet).exists?
+ ScreenedIpAddress
+ .subnets(family, from_masklen, to_masklen)
+ .map do |subnet|
+ next if ScreenedIpAddress.where("? <<= ip_address", subnet).exists?
- old_ips = ScreenedIpAddress
- .where(action_type: ScreenedIpAddress.actions[:block])
- .where("ip_address << ?", subnet)
- .where("family(ip_address) = ?", family)
- .where("masklen(ip_address) IN (?)", from_masklen)
+ old_ips =
+ ScreenedIpAddress
+ .where(action_type: ScreenedIpAddress.actions[:block])
+ .where("ip_address << ?", subnet)
+ .where("family(ip_address) = ?", family)
+ .where("masklen(ip_address) IN (?)", from_masklen)
- sum_match_count, max_last_match_at, min_created_at =
- old_ips.pluck_first('SUM(match_count), MAX(last_match_at), MIN(created_at)')
+ sum_match_count, max_last_match_at, min_created_at =
+ old_ips.pluck_first("SUM(match_count), MAX(last_match_at), MIN(created_at)")
- ScreenedIpAddress.create!(
- ip_address: subnet,
- match_count: sum_match_count,
- last_match_at: max_last_match_at,
- created_at: min_created_at,
- )
+ ScreenedIpAddress.create!(
+ ip_address: subnet,
+ match_count: sum_match_count,
+ last_match_at: max_last_match_at,
+ created_at: min_created_at,
+ )
- StaffActionLogger.new(current_user).log_roll_up(subnet, old_ips.map(&:ip_address))
- old_ips.delete_all
- end
+ StaffActionLogger.new(current_user).log_roll_up(subnet, old_ips.map(&:ip_address))
+ old_ips.delete_all
+ end
end
end
-
end
# == Schema Information
diff --git a/app/models/screened_url.rb b/app/models/screened_url.rb
index 0140dd2b47c..0e827cf522d 100644
--- a/app/models/screened_url.rb
+++ b/app/models/screened_url.rb
@@ -6,7 +6,6 @@
# For now, nothing is done. We're just collecting the data and will decide
# what to do with it later.
class ScreenedUrl < ActiveRecord::Base
-
include ScreeningModel
default_action :do_nothing
@@ -18,7 +17,7 @@ class ScreenedUrl < ActiveRecord::Base
def normalize
self.url = ScreenedUrl.normalize_url(self.url) if self.url
- self.domain = self.domain.downcase.sub(/^www\./, '') if self.domain
+ self.domain = self.domain.downcase.sub(/^www\./, "") if self.domain
end
def self.watch(url, domain, opts = {})
@@ -30,9 +29,9 @@ class ScreenedUrl < ActiveRecord::Base
end
def self.normalize_url(url)
- normalized = url.gsub(/http(s?):\/\//i, '')
- normalized.gsub!(/(\/)+$/, '') # trim trailing slashes
- normalized.gsub!(/^([^\/]+)(?:\/)?/) { |m| m.downcase } # downcase the domain part of the url
+ normalized = url.gsub(%r{http(s?)://}i, "")
+ normalized.gsub!(%r{(/)+$}, "") # trim trailing slashes
+ normalized.gsub!(%r{^([^/]+)(?:/)?}) { |m| m.downcase } # downcase the domain part of the url
normalized
end
end
diff --git a/app/models/search_log.rb b/app/models/search_log.rb
index ecaa2db6e79..8d4e1d7e7e6 100644
--- a/app/models/search_log.rb
+++ b/app/models/search_log.rb
@@ -14,19 +14,11 @@ class SearchLog < ActiveRecord::Base
end
def self.search_types
- @search_types ||= Enum.new(
- header: 1,
- full_page: 2
- )
+ @search_types ||= Enum.new(header: 1, full_page: 2)
end
def self.search_result_types
- @search_result_types ||= Enum.new(
- topic: 1,
- user: 2,
- category: 3,
- tag: 4
- )
+ @search_result_types ||= Enum.new(topic: 1, user: 2, category: 3, tag: 4)
end
def self.redis_key(ip_address:, user_id: nil)
@@ -39,13 +31,10 @@ class SearchLog < ActiveRecord::Base
# for testing
def self.clear_debounce_cache!
- Discourse.redis.keys("__SEARCH__LOG_*").each do |k|
- Discourse.redis.del(k)
- end
+ Discourse.redis.keys("__SEARCH__LOG_*").each { |k| Discourse.redis.del(k) }
end
def self.log(term:, search_type:, ip_address:, user_id: nil)
-
return [:error] if term.blank?
search_type = search_types[search_type]
@@ -60,22 +49,15 @@ class SearchLog < ActiveRecord::Base
id, old_term = existing.split(",", 2)
if term.start_with?(old_term)
- where(id: id.to_i).update_all(
- created_at: Time.zone.now,
- term: term
- )
+ where(id: id.to_i).update_all(created_at: Time.zone.now, term: term)
result = [:updated, id.to_i]
end
end
if !result
- log = self.create!(
- term: term,
- search_type: search_type,
- ip_address: ip_address,
- user_id: user_id
- )
+ log =
+ self.create!(term: term, search_type: search_type, ip_address: ip_address, user_id: user_id)
result = [:created, log.id]
end
@@ -88,21 +70,21 @@ class SearchLog < ActiveRecord::Base
def self.term_details(term, period = :weekly, search_type = :all)
details = []
- result = SearchLog.select("COUNT(*) AS count, created_at::date AS date")
- .where(
- 'lower(term) = ? AND created_at > ?',
- term.downcase, start_of(period)
+ result =
+ SearchLog.select("COUNT(*) AS count, created_at::date AS date").where(
+ "lower(term) = ? AND created_at > ?",
+ term.downcase,
+ start_of(period),
)
- result = result.where('search_type = ?', search_types[search_type]) if search_type == :header || search_type == :full_page
- result = result.where('search_result_id IS NOT NULL') if search_type == :click_through_only
+ result = result.where("search_type = ?", search_types[search_type]) if search_type == :header ||
+ search_type == :full_page
+ result = result.where("search_result_id IS NOT NULL") if search_type == :click_through_only
result
.order("date")
.group("date")
- .each do |record|
- details << { x: Date.parse(record['date'].to_s), y: record['count'] }
- end
+ .each { |record| details << { x: Date.parse(record["date"].to_s), y: record["count"] } }
{
type: "search_log_term",
@@ -110,7 +92,7 @@ class SearchLog < ActiveRecord::Base
start_date: start_of(period),
end_date: Time.zone.now,
data: details,
- period: period.to_s
+ period: period.to_s,
}
end
@@ -132,39 +114,40 @@ class SearchLog < ActiveRecord::Base
END) AS click_through
SQL
- result = SearchLog.select(select_sql)
- .where('created_at > ?', start_date)
+ result = SearchLog.select(select_sql).where("created_at > ?", start_date)
- if end_date
- result = result.where('created_at < ?', end_date)
- end
+ result = result.where("created_at < ?", end_date) if end_date
- unless search_type == :all
- result = result.where('search_type = ?', search_types[search_type])
- end
+ result = result.where("search_type = ?", search_types[search_type]) unless search_type == :all
- result.group('lower(term)')
- .order('searches DESC, click_through DESC, term ASC')
- .limit(limit)
+ result.group("lower(term)").order("searches DESC, click_through DESC, term ASC").limit(limit)
end
def self.clean_up
- search_id = SearchLog.order(:id).offset(SiteSetting.search_query_log_max_size).limit(1).pluck(:id)
- if search_id.present?
- SearchLog.where('id < ?', search_id[0]).delete_all
- end
- SearchLog.where('created_at < TIMESTAMP ?', SiteSetting.search_query_log_max_retention_days.days.ago).delete_all
+ search_id =
+ SearchLog.order(:id).offset(SiteSetting.search_query_log_max_size).limit(1).pluck(:id)
+ SearchLog.where("id < ?", search_id[0]).delete_all if search_id.present?
+ SearchLog.where(
+ "created_at < TIMESTAMP ?",
+ SiteSetting.search_query_log_max_retention_days.days.ago,
+ ).delete_all
end
def self.start_of(period)
period =
case period
- when :yearly then 1.year.ago
- when :monthly then 1.month.ago
- when :quarterly then 3.months.ago
- when :weekly then 1.week.ago
- when :daily then Time.zone.now
- else 1000.years.ago
+ when :yearly
+ 1.year.ago
+ when :monthly
+ 1.month.ago
+ when :quarterly
+ 3.months.ago
+ when :weekly
+ 1.week.ago
+ when :daily
+ Time.zone.now
+ else
+ 1000.years.ago
end
period&.to_date
diff --git a/app/models/sidebar_section_link.rb b/app/models/sidebar_section_link.rb
index 0b6f7bfebea..b6b23a73571 100644
--- a/app/models/sidebar_section_link.rb
+++ b/app/models/sidebar_section_link.rb
@@ -4,16 +4,20 @@ class SidebarSectionLink < ActiveRecord::Base
belongs_to :user
belongs_to :linkable, polymorphic: true
- validates :user_id, presence: true, uniqueness: { scope: [:linkable_type, :linkable_id] }
+ validates :user_id, presence: true, uniqueness: { scope: %i[linkable_type linkable_id] }
validates :linkable_id, presence: true
validates :linkable_type, presence: true
validate :ensure_supported_linkable_type, if: :will_save_change_to_linkable_type?
- SUPPORTED_LINKABLE_TYPES = %w{Category Tag}
+ SUPPORTED_LINKABLE_TYPES = %w[Category Tag]
private def ensure_supported_linkable_type
- if (!SUPPORTED_LINKABLE_TYPES.include?(self.linkable_type)) || (self.linkable_type == 'Tag' && !SiteSetting.tagging_enabled)
- self.errors.add(:linkable_type, I18n.t("activerecord.errors.models.sidebar_section_link.attributes.linkable_type.invalid"))
+ if (!SUPPORTED_LINKABLE_TYPES.include?(self.linkable_type)) ||
+ (self.linkable_type == "Tag" && !SiteSetting.tagging_enabled)
+ self.errors.add(
+ :linkable_type,
+ I18n.t("activerecord.errors.models.sidebar_section_link.attributes.linkable_type.invalid"),
+ )
end
end
end
diff --git a/app/models/site.rb b/app/models/site.rb
index 2899a932cbe..5d3b4565bc2 100644
--- a/app/models/site.rb
+++ b/app/models/site.rb
@@ -67,84 +67,90 @@ class Site
#
# Do note that any new association added to the eager loading needs a
# corresponding ActiveRecord callback to clear the categories cache.
- Discourse.cache.fetch(categories_cache_key, expires_in: 30.minutes) do
- categories = Category
- .includes(:uploaded_logo, :uploaded_logo_dark, :uploaded_background, :tags, :tag_groups, category_required_tag_groups: :tag_group)
- .joins('LEFT JOIN topics t on t.id = categories.topic_id')
- .select('categories.*, t.slug topic_slug')
- .order(:position)
- .to_a
+ Discourse
+ .cache
+ .fetch(categories_cache_key, expires_in: 30.minutes) do
+ categories =
+ Category
+ .includes(
+ :uploaded_logo,
+ :uploaded_logo_dark,
+ :uploaded_background,
+ :tags,
+ :tag_groups,
+ category_required_tag_groups: :tag_group,
+ )
+ .joins("LEFT JOIN topics t on t.id = categories.topic_id")
+ .select("categories.*, t.slug topic_slug")
+ .order(:position)
+ .to_a
- if preloaded_category_custom_fields.present?
- Category.preload_custom_fields(
+ if preloaded_category_custom_fields.present?
+ Category.preload_custom_fields(categories, preloaded_category_custom_fields)
+ end
+
+ ActiveModel::ArraySerializer.new(
categories,
- preloaded_category_custom_fields
- )
+ each_serializer: SiteCategorySerializer,
+ ).as_json
end
-
- ActiveModel::ArraySerializer.new(
- categories,
- each_serializer: SiteCategorySerializer
- ).as_json
- end
end
def categories
- @categories ||= begin
- categories = []
+ @categories ||=
+ begin
+ categories = []
- self.class.all_categories_cache.each do |category|
- if @guardian.can_see_serialized_category?(category_id: category[:id], read_restricted: category[:read_restricted])
- categories << category
+ self.class.all_categories_cache.each do |category|
+ if @guardian.can_see_serialized_category?(
+ category_id: category[:id],
+ read_restricted: category[:read_restricted],
+ )
+ categories << category
+ end
end
- end
- with_children = Set.new
- categories.each do |c|
- if c[:parent_category_id]
- with_children << c[:parent_category_id]
+ with_children = Set.new
+ categories.each { |c| with_children << c[:parent_category_id] if c[:parent_category_id] }
+
+ allowed_topic_create = nil
+ unless @guardian.is_admin?
+ allowed_topic_create_ids =
+ @guardian.anonymous? ? [] : Category.topic_create_allowed(@guardian).pluck(:id)
+ allowed_topic_create = Set.new(allowed_topic_create_ids)
end
+
+ by_id = {}
+
+ notification_levels = CategoryUser.notification_levels_for(@guardian.user)
+ default_notification_level = CategoryUser.default_notification_level
+
+ categories.each do |category|
+ category[:notification_level] = notification_levels[category[:id]] ||
+ default_notification_level
+ category[:permission] = CategoryGroup.permission_types[
+ :full
+ ] if allowed_topic_create&.include?(category[:id]) || @guardian.is_admin?
+ category[:has_children] = with_children.include?(category[:id])
+
+ category[:can_edit] = @guardian.can_edit_serialized_category?(
+ category_id: category[:id],
+ read_restricted: category[:read_restricted],
+ )
+
+ by_id[category[:id]] = category
+ end
+
+ categories.reject! { |c| c[:parent_category_id] && !by_id[c[:parent_category_id]] }
+
+ self.class.categories_callbacks.each { |callback| callback.call(categories, @guardian) }
+
+ categories
end
-
- allowed_topic_create = nil
- unless @guardian.is_admin?
- allowed_topic_create_ids =
- @guardian.anonymous? ? [] : Category.topic_create_allowed(@guardian).pluck(:id)
- allowed_topic_create = Set.new(allowed_topic_create_ids)
- end
-
- by_id = {}
-
- notification_levels = CategoryUser.notification_levels_for(@guardian.user)
- default_notification_level = CategoryUser.default_notification_level
-
- categories.each do |category|
- category[:notification_level] = notification_levels[category[:id]] || default_notification_level
- category[:permission] = CategoryGroup.permission_types[:full] if allowed_topic_create&.include?(category[:id]) || @guardian.is_admin?
- category[:has_children] = with_children.include?(category[:id])
-
- category[:can_edit] = @guardian.can_edit_serialized_category?(
- category_id: category[:id],
- read_restricted: category[:read_restricted]
- )
-
- by_id[category[:id]] = category
- end
-
- categories.reject! { |c| c[:parent_category_id] && !by_id[c[:parent_category_id]] }
-
- self.class.categories_callbacks.each do |callback|
- callback.call(categories, @guardian)
- end
-
- categories
- end
end
def groups
- Group
- .visible_groups(@guardian.user, "name ASC", include_everyone: true)
- .includes(:flair_upload)
+ Group.visible_groups(@guardian.user, "name ASC", include_everyone: true).includes(:flair_upload)
end
def archetypes
@@ -157,24 +163,31 @@ class Site
def self.json_for(guardian)
if guardian.anonymous? && SiteSetting.login_required
- return {
- periods: TopTopic.periods.map(&:to_s),
- filters: Discourse.filters.map(&:to_s),
- user_fields: UserField.includes(:user_field_options).order(:position).all.map do |userfield|
- UserFieldSerializer.new(userfield, root: false, scope: guardian)
- end,
- auth_providers: Discourse.enabled_auth_providers.map do |provider|
- AuthProviderSerializer.new(provider, root: false, scope: guardian)
- end
- }.to_json
+ return(
+ {
+ periods: TopTopic.periods.map(&:to_s),
+ filters: Discourse.filters.map(&:to_s),
+ user_fields:
+ UserField
+ .includes(:user_field_options)
+ .order(:position)
+ .all
+ .map { |userfield| UserFieldSerializer.new(userfield, root: false, scope: guardian) },
+ auth_providers:
+ Discourse.enabled_auth_providers.map do |provider|
+ AuthProviderSerializer.new(provider, root: false, scope: guardian)
+ end,
+ }.to_json
+ )
end
seq = nil
if guardian.anonymous?
- seq = MessageBus.last_id('/site_json')
+ seq = MessageBus.last_id("/site_json")
- cached_json, cached_seq, cached_version = Discourse.redis.mget('site_json', 'site_json_seq', 'site_json_version')
+ cached_json, cached_seq, cached_version =
+ Discourse.redis.mget("site_json", "site_json_seq", "site_json_version")
if cached_json && seq == cached_seq.to_i && Discourse.git_version == cached_version
return cached_json
@@ -186,21 +199,21 @@ class Site
if guardian.anonymous?
Discourse.redis.multi do |transaction|
- transaction.setex 'site_json', 1800, json
- transaction.set 'site_json_seq', seq
- transaction.set 'site_json_version', Discourse.git_version
+ transaction.setex "site_json", 1800, json
+ transaction.set "site_json_seq", seq
+ transaction.set "site_json_version", Discourse.git_version
end
end
json
end
- SITE_JSON_CHANNEL = '/site_json'
+ SITE_JSON_CHANNEL = "/site_json"
def self.clear_anon_cache!
# publishing forces the sequence up
# the cache is validated based on the sequence
- MessageBus.publish(SITE_JSON_CHANNEL, '')
+ MessageBus.publish(SITE_JSON_CHANNEL, "")
end
def self.welcome_topic_banner_cache_key(user_id)
@@ -208,12 +221,14 @@ class Site
end
def self.welcome_topic_exists_and_is_not_edited?
- Post.joins(:topic)
+ Post
+ .joins(:topic)
.where(
"topics.id = :topic_id AND topics.deleted_at IS NULL AND posts.post_number = 1 AND posts.version = 1 AND posts.created_at > :created_at",
topic_id: SiteSetting.welcome_topic_id,
- created_at: 1.month.ago
- ).exists?
+ created_at: 1.month.ago,
+ )
+ .exists?
end
def self.show_welcome_topic_banner?(guardian)
@@ -223,11 +238,12 @@ class Site
show_welcome_topic_banner = Discourse.cache.read(welcome_topic_banner_cache_key(user_id))
return show_welcome_topic_banner unless show_welcome_topic_banner.nil?
- show_welcome_topic_banner = if (user_id == User.first_login_admin_id)
- welcome_topic_exists_and_is_not_edited?
- else
- false
- end
+ show_welcome_topic_banner =
+ if (user_id == User.first_login_admin_id)
+ welcome_topic_exists_and_is_not_edited?
+ else
+ false
+ end
Discourse.cache.write(welcome_topic_banner_cache_key(user_id), show_welcome_topic_banner)
show_welcome_topic_banner
diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb
index dfd2ae8bf33..01af33da64c 100644
--- a/app/models/site_setting.rb
+++ b/app/models/site_setting.rb
@@ -14,19 +14,21 @@ class SiteSetting < ActiveRecord::Base
if self.data_type == SiteSettings::TypeSupervisor.types[:upload]
UploadReference.ensure_exist!(upload_ids: [self.value], target: self)
elsif self.data_type == SiteSettings::TypeSupervisor.types[:uploaded_image_list]
- upload_ids = self.value.split('|').compact.uniq
+ upload_ids = self.value.split("|").compact.uniq
UploadReference.ensure_exist!(upload_ids: upload_ids, target: self)
end
end
end
def self.load_settings(file, plugin: nil)
- SiteSettings::YamlLoader.new(file).load do |category, name, default, opts|
- setting(name, default, opts.merge(category: category, plugin: plugin))
- end
+ SiteSettings::YamlLoader
+ .new(file)
+ .load do |category, name, default, opts|
+ setting(name, default, opts.merge(category: category, plugin: plugin))
+ end
end
- load_settings(File.join(Rails.root, 'config', 'site_settings.yml'))
+ load_settings(File.join(Rails.root, "config", "site_settings.yml"))
if GlobalSetting.load_plugins?
Dir[File.join(Rails.root, "plugins", "*", "config", "settings.yml")].each do |file|
@@ -62,7 +64,7 @@ class SiteSetting < ActiveRecord::Base
end
def self.top_menu_items
- top_menu.split('|').map { |menu_item| TopMenuItem.new(menu_item) }
+ top_menu.split("|").map { |menu_item| TopMenuItem.new(menu_item) }
end
def self.homepage
@@ -74,7 +76,8 @@ class SiteSetting < ActiveRecord::Base
end
def self.anonymous_homepage
- top_menu_items.map { |item| item.name }
+ top_menu_items
+ .map { |item| item.name }
.select { |item| anonymous_menu_items.include?(item) }
.first
end
@@ -98,7 +101,10 @@ class SiteSetting < ActiveRecord::Base
end
def self.queue_jobs=(val)
- Discourse.deprecate("queue_jobs is deprecated. Please use Jobs.run_immediately! instead", drop_from: '2.9.0')
+ Discourse.deprecate(
+ "queue_jobs is deprecated. Please use Jobs.run_immediately! instead",
+ drop_from: "2.9.0",
+ )
val ? Jobs.run_later! : Jobs.run_immediately!
end
@@ -159,12 +165,19 @@ class SiteSetting < ActiveRecord::Base
def self.s3_base_url
path = self.s3_upload_bucket.split("/", 2)[1]
- "#{self.absolute_base_url}#{path ? '/' + path : ''}"
+ "#{self.absolute_base_url}#{path ? "/" + path : ""}"
end
def self.absolute_base_url
- url_basename = SiteSetting.s3_endpoint.split('/')[-1]
- bucket = SiteSetting.enable_s3_uploads ? Discourse.store.s3_bucket_name : GlobalSetting.s3_bucket_name
+ url_basename = SiteSetting.s3_endpoint.split("/")[-1]
+ bucket =
+ (
+ if SiteSetting.enable_s3_uploads
+ Discourse.store.s3_bucket_name
+ else
+ GlobalSetting.s3_bucket_name
+ end
+ )
# cf. http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
if SiteSetting.s3_endpoint.blank? || SiteSetting.s3_endpoint.end_with?("amazonaws.com")
@@ -196,7 +209,7 @@ class SiteSetting < ActiveRecord::Base
end
client_settings << :require_invite_code
- %i{
+ %i[
site_logo_url
site_logo_small_url
site_mobile_logo_url
@@ -204,9 +217,9 @@ class SiteSetting < ActiveRecord::Base
site_logo_dark_url
site_logo_small_dark_url
site_mobile_logo_dark_url
- }.each { |client_setting| client_settings << client_setting }
+ ].each { |client_setting| client_settings << client_setting }
- %i{
+ %i[
logo
logo_small
digest_logo
@@ -221,14 +234,14 @@ class SiteSetting < ActiveRecord::Base
twitter_summary_large_image
opengraph_image
push_notifications_icon
- }.each do |setting_name|
+ ].each do |setting_name|
define_singleton_method("site_#{setting_name}_url") do
if SiteIconManager.respond_to?("#{setting_name}_url")
return SiteIconManager.public_send("#{setting_name}_url")
end
upload = self.public_send(setting_name)
- upload ? full_cdn_url(upload.url) : ''
+ upload ? full_cdn_url(upload.url) : ""
end
end
@@ -242,34 +255,42 @@ class SiteSetting < ActiveRecord::Base
end
ALLOWLIST_DEPRECATED_SITE_SETTINGS = {
- 'email_domains_blacklist': 'blocked_email_domains',
- 'email_domains_whitelist': 'allowed_email_domains',
- 'unicode_username_character_whitelist': 'allowed_unicode_username_characters',
- 'user_website_domains_whitelist': 'allowed_user_website_domains',
- 'whitelisted_link_domains': 'allowed_link_domains',
- 'embed_whitelist_selector': 'allowed_embed_selectors',
- 'auto_generated_whitelist': 'auto_generated_allowlist',
- 'attachment_content_type_blacklist': 'blocked_attachment_content_types',
- 'attachment_filename_blacklist': 'blocked_attachment_filenames',
- 'use_admin_ip_whitelist': 'use_admin_ip_allowlist',
- 'blacklist_ip_blocks': 'blocked_ip_blocks',
- 'whitelist_internal_hosts': 'allowed_internal_hosts',
- 'whitelisted_crawler_user_agents': 'allowed_crawler_user_agents',
- 'blacklisted_crawler_user_agents': 'blocked_crawler_user_agents',
- 'onebox_domains_blacklist': 'blocked_onebox_domains',
- 'inline_onebox_domains_whitelist': 'allowed_inline_onebox_domains',
- 'white_listed_spam_host_domains': 'allowed_spam_host_domains',
- 'embed_blacklist_selector': 'blocked_embed_selectors',
- 'embed_classname_whitelist': 'allowed_embed_classnames',
+ email_domains_blacklist: "blocked_email_domains",
+ email_domains_whitelist: "allowed_email_domains",
+ unicode_username_character_whitelist: "allowed_unicode_username_characters",
+ user_website_domains_whitelist: "allowed_user_website_domains",
+ whitelisted_link_domains: "allowed_link_domains",
+ embed_whitelist_selector: "allowed_embed_selectors",
+ auto_generated_whitelist: "auto_generated_allowlist",
+ attachment_content_type_blacklist: "blocked_attachment_content_types",
+ attachment_filename_blacklist: "blocked_attachment_filenames",
+ use_admin_ip_whitelist: "use_admin_ip_allowlist",
+ blacklist_ip_blocks: "blocked_ip_blocks",
+ whitelist_internal_hosts: "allowed_internal_hosts",
+ whitelisted_crawler_user_agents: "allowed_crawler_user_agents",
+ blacklisted_crawler_user_agents: "blocked_crawler_user_agents",
+ onebox_domains_blacklist: "blocked_onebox_domains",
+ inline_onebox_domains_whitelist: "allowed_inline_onebox_domains",
+ white_listed_spam_host_domains: "allowed_spam_host_domains",
+ embed_blacklist_selector: "blocked_embed_selectors",
+ embed_classname_whitelist: "allowed_embed_classnames",
}
ALLOWLIST_DEPRECATED_SITE_SETTINGS.each_pair do |old_method, new_method|
self.define_singleton_method(old_method) do
- Discourse.deprecate("#{old_method.to_s} is deprecated, use the #{new_method.to_s}.", drop_from: "2.6", raise_error: true)
+ Discourse.deprecate(
+ "#{old_method.to_s} is deprecated, use the #{new_method.to_s}.",
+ drop_from: "2.6",
+ raise_error: true,
+ )
send(new_method)
end
self.define_singleton_method("#{old_method}=") do |args|
- Discourse.deprecate("#{old_method.to_s} is deprecated, use the #{new_method.to_s}.", drop_from: "2.6", raise_error: true)
+ Discourse.deprecate(
+ "#{old_method.to_s} is deprecated, use the #{new_method.to_s}.",
+ drop_from: "2.6",
+ raise_error: true,
+ )
send("#{new_method}=", args)
end
end
diff --git a/app/models/sitemap.rb b/app/models/sitemap.rb
index a6ead4692ea..a0ca9a6df26 100644
--- a/app/models/sitemap.rb
+++ b/app/models/sitemap.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
class Sitemap < ActiveRecord::Base
- RECENT_SITEMAP_NAME = 'recent'
- NEWS_SITEMAP_NAME = 'news'
+ RECENT_SITEMAP_NAME = "recent"
+ NEWS_SITEMAP_NAME = "news"
class << self
def regenerate_sitemaps
@@ -26,10 +26,7 @@ class Sitemap < ActiveRecord::Base
def touch(name)
find_or_initialize_by(name: name).tap do |sitemap|
- sitemap.update!(
- last_posted_at: sitemap.last_posted_topic || 3.days.ago,
- enabled: true
- )
+ sitemap.update!(last_posted_at: sitemap.last_posted_topic || 3.days.ago, enabled: true)
end
end
end
@@ -55,15 +52,13 @@ class Sitemap < ActiveRecord::Base
private
def sitemap_topics
- indexable_topics = Topic
- .where(visible: true)
- .joins(:category)
- .where(categories: { read_restricted: false })
+ indexable_topics =
+ Topic.where(visible: true).joins(:category).where(categories: { read_restricted: false })
if name == RECENT_SITEMAP_NAME
- indexable_topics.where('bumped_at > ?', 3.days.ago).order(bumped_at: :desc)
+ indexable_topics.where("bumped_at > ?", 3.days.ago).order(bumped_at: :desc)
elsif name == NEWS_SITEMAP_NAME
- indexable_topics.where('bumped_at > ?', 72.hours.ago).order(bumped_at: :desc)
+ indexable_topics.where("bumped_at > ?", 72.hours.ago).order(bumped_at: :desc)
else
offset = (name.to_i - 1) * max_page_size
diff --git a/app/models/skipped_email_log.rb b/app/models/skipped_email_log.rb
index 2af1b2dd12f..eb28a0749fe 100644
--- a/app/models/skipped_email_log.rb
+++ b/app/models/skipped_email_log.rb
@@ -14,37 +14,38 @@ class SkippedEmailLog < ActiveRecord::Base
validate :ensure_valid_reason_type
def self.reason_types
- @types ||= Enum.new(
- custom: 1,
- exceeded_emails_limit: 2,
- exceeded_bounces_limit: 3,
- mailing_list_no_echo_mode: 4,
- user_email_no_user: 5,
- user_email_post_not_found: 6,
- user_email_anonymous_user: 7,
- user_email_user_suspended_not_pm: 8,
- user_email_seen_recently: 9,
- user_email_notification_already_read: 10,
- user_email_topic_nil: 11,
- user_email_post_user_deleted: 12,
- user_email_post_deleted: 13,
- user_email_user_suspended: 14,
- user_email_already_read: 15,
- sender_message_blank: 16,
- sender_message_to_blank: 17,
- sender_text_part_body_blank: 18,
- sender_body_blank: 19,
- sender_post_deleted: 20,
- sender_message_to_invalid: 21,
- user_email_access_denied: 22,
- sender_topic_deleted: 23,
- user_email_no_email: 24,
- group_smtp_post_deleted: 25,
- group_smtp_topic_deleted: 26,
- group_smtp_disabled_for_group: 27,
- # you need to add the reason in server.en.yml below the "skipped_email_log" key
- # when you add a new enum value
- )
+ @types ||=
+ Enum.new(
+ custom: 1,
+ exceeded_emails_limit: 2,
+ exceeded_bounces_limit: 3,
+ mailing_list_no_echo_mode: 4,
+ user_email_no_user: 5,
+ user_email_post_not_found: 6,
+ user_email_anonymous_user: 7,
+ user_email_user_suspended_not_pm: 8,
+ user_email_seen_recently: 9,
+ user_email_notification_already_read: 10,
+ user_email_topic_nil: 11,
+ user_email_post_user_deleted: 12,
+ user_email_post_deleted: 13,
+ user_email_user_suspended: 14,
+ user_email_already_read: 15,
+ sender_message_blank: 16,
+ sender_message_to_blank: 17,
+ sender_text_part_body_blank: 18,
+ sender_body_blank: 19,
+ sender_post_deleted: 20,
+ sender_message_to_invalid: 21,
+ user_email_access_denied: 22,
+ sender_topic_deleted: 23,
+ user_email_no_email: 24,
+ group_smtp_post_deleted: 25,
+ group_smtp_topic_deleted: 26,
+ group_smtp_disabled_for_group: 27,
+ # you need to add the reason in server.en.yml below the "skipped_email_log" key
+ # when you add a new enum value
+ )
end
def reason
@@ -56,7 +57,7 @@ class SkippedEmailLog < ActiveRecord::Base
I18n.t(
"skipped_email_log.#{SkippedEmailLog.reason_types[type]}",
user_id: self.user_id,
- post_id: self.post_id
+ post_id: self.post_id,
)
end
end
@@ -68,9 +69,7 @@ class SkippedEmailLog < ActiveRecord::Base
end
def ensure_valid_reason_type
- unless self.class.reason_types[self.reason_type]
- self.errors.add(:reason_type, :invalid)
- end
+ self.errors.add(:reason_type, :invalid) unless self.class.reason_types[self.reason_type]
end
end
diff --git a/app/models/slug_setting.rb b/app/models/slug_setting.rb
index 65460f83900..bd8912996d5 100644
--- a/app/models/slug_setting.rb
+++ b/app/models/slug_setting.rb
@@ -1,17 +1,13 @@
# frozen_string_literal: true
class SlugSetting < EnumSiteSetting
-
- VALUES = %w(ascii encoded none)
+ VALUES = %w[ascii encoded none]
def self.valid_value?(val)
VALUES.include?(val)
end
def self.values
- VALUES.map do |l|
- { name: l, value: l }
- end
+ VALUES.map { |l| { name: l, value: l } }
end
-
end
diff --git a/app/models/stylesheet_cache.rb b/app/models/stylesheet_cache.rb
index 819f9ab3662..df2c493e15d 100644
--- a/app/models/stylesheet_cache.rb
+++ b/app/models/stylesheet_cache.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class StylesheetCache < ActiveRecord::Base
- self.table_name = 'stylesheet_cache'
+ self.table_name = "stylesheet_cache"
MAX_TO_KEEP = 50
CLEANUP_AFTER_DAYS = 150
@@ -12,21 +12,14 @@ class StylesheetCache < ActiveRecord::Base
return false if where(target: target, digest: digest).exists?
- if Rails.env.development?
- ActiveRecord::Base.logger = nil
- end
+ ActiveRecord::Base.logger = nil if Rails.env.development?
success = create(target: target, digest: digest, content: content, source_map: source_map)
count = StylesheetCache.count
if count > max_to_keep
-
- remove_lower = StylesheetCache
- .where(target: target)
- .limit(max_to_keep)
- .order('id desc')
- .pluck(:id)
- .last
+ remove_lower =
+ StylesheetCache.where(target: target).limit(max_to_keep).order("id desc").pluck(:id).last
DB.exec(<<~SQL, id: remove_lower, target: target)
DELETE FROM stylesheet_cache
@@ -38,15 +31,12 @@ class StylesheetCache < ActiveRecord::Base
rescue ActiveRecord::RecordNotUnique, ActiveRecord::ReadOnlyError
false
ensure
- if Rails.env.development? && old_logger
- ActiveRecord::Base.logger = old_logger
- end
+ ActiveRecord::Base.logger = old_logger if Rails.env.development? && old_logger
end
def self.clean_up
- StylesheetCache.where('created_at < ?', CLEANUP_AFTER_DAYS.days.ago).delete_all
+ StylesheetCache.where("created_at < ?", CLEANUP_AFTER_DAYS.days.ago).delete_all
end
-
end
# == Schema Information
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 6311dd3dc2f..64b932d02ed 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -5,29 +5,30 @@ class Tag < ActiveRecord::Base
include HasDestroyedWebHook
RESERVED_TAGS = [
- 'none',
- 'constructor' # prevents issues with javascript's constructor of objects
+ "none",
+ "constructor", # prevents issues with javascript's constructor of objects
]
- validates :name,
- presence: true,
- uniqueness: { case_sensitive: false }
+ validates :name, presence: true, uniqueness: { case_sensitive: false }
- validate :target_tag_validator, if: Proc.new { |t| t.new_record? || t.will_save_change_to_target_tag_id? }
+ validate :target_tag_validator,
+ if: Proc.new { |t| t.new_record? || t.will_save_change_to_target_tag_id? }
validate :name_validator
validates :description, length: { maximum: 280 }
- scope :where_name, ->(name) do
- name = Array(name).map(&:downcase)
- where("lower(tags.name) IN (?)", name)
- end
+ scope :where_name,
+ ->(name) {
+ name = Array(name).map(&:downcase)
+ where("lower(tags.name) IN (?)", name)
+ }
# tags that have never been used and don't belong to a tag group
- scope :unused, -> do
- where(topic_count: 0, pm_topic_count: 0)
- .joins("LEFT JOIN tag_group_memberships tgm ON tags.id = tgm.tag_id")
- .where("tgm.tag_id IS NULL")
- end
+ scope :unused,
+ -> {
+ where(topic_count: 0, pm_topic_count: 0).joins(
+ "LEFT JOIN tag_group_memberships tgm ON tags.id = tgm.tag_id",
+ ).where("tgm.tag_id IS NULL")
+ }
scope :base_tags, -> { where(target_tag_id: nil) }
@@ -93,7 +94,7 @@ class Tag < ActiveRecord::Base
end
def self.find_by_name(name)
- self.find_by('lower(name) = ?', name.downcase)
+ self.find_by("lower(name) = ?", name.downcase)
end
def self.top_tags(limit_arg: nil, category: nil, guardian: nil)
@@ -102,19 +103,24 @@ class Tag < ActiveRecord::Base
limit = limit_arg || (SiteSetting.max_tags_in_filter_list + 1)
scope_category_ids = (guardian || Guardian.new).allowed_category_ids
- if category
- scope_category_ids &= ([category.id] + category.subcategories.pluck(:id))
- end
+ scope_category_ids &= ([category.id] + category.subcategories.pluck(:id)) if category
return [] if scope_category_ids.empty?
- filter_sql = guardian&.is_staff? ? '' : " AND tags.id IN (#{DiscourseTagging.visible_tags(guardian).select(:id).to_sql})"
+ filter_sql =
+ (
+ if guardian&.is_staff?
+ ""
+ else
+ " AND tags.id IN (#{DiscourseTagging.visible_tags(guardian).select(:id).to_sql})"
+ end
+ )
tag_names_with_counts = DB.query <<~SQL
SELECT tags.name as tag_name, SUM(stats.topic_count) AS sum_topic_count
FROM category_tag_stats stats
JOIN tags ON stats.tag_id = tags.id AND stats.topic_count > 0
- WHERE stats.category_id in (#{scope_category_ids.join(',')})
+ WHERE stats.category_id in (#{scope_category_ids.join(",")})
#{filter_sql}
GROUP BY tags.name
ORDER BY sum_topic_count DESC, tag_name ASC
@@ -181,16 +187,16 @@ class Tag < ActiveRecord::Base
def update_synonym_associations
if target_tag_id && saved_change_to_target_tag_id?
- target_tag.tag_groups.each { |tag_group| tag_group.tags << self unless tag_group.tags.include?(self) }
- target_tag.categories.each { |category| category.tags << self unless category.tags.include?(self) }
+ target_tag.tag_groups.each do |tag_group|
+ tag_group.tags << self unless tag_group.tags.include?(self)
+ end
+ target_tag.categories.each do |category|
+ category.tags << self unless category.tags.include?(self)
+ end
end
end
- %i{
- tag_created
- tag_updated
- tag_destroyed
- }.each do |event|
+ %i[tag_created tag_updated tag_destroyed].each do |event|
define_method("trigger_#{event}_event") do
DiscourseEvent.trigger(event, self)
true
@@ -200,9 +206,7 @@ class Tag < ActiveRecord::Base
private
def name_validator
- if name.present? && RESERVED_TAGS.include?(self.name.strip.downcase)
- errors.add(:name, :invalid)
- end
+ errors.add(:name, :invalid) if name.present? && RESERVED_TAGS.include?(self.name.strip.downcase)
end
end
diff --git a/app/models/tag_group.rb b/app/models/tag_group.rb
index c80c65f95c7..54ee33bc1cc 100644
--- a/app/models/tag_group.rb
+++ b/app/models/tag_group.rb
@@ -10,7 +10,7 @@ class TagGroup < ActiveRecord::Base
has_many :categories, through: :category_tag_groups
has_many :tag_group_permissions, dependent: :destroy
- belongs_to :parent_tag, class_name: 'Tag'
+ belongs_to :parent_tag, class_name: "Tag"
before_create :init_permissions
before_save :apply_permissions
@@ -28,7 +28,11 @@ class TagGroup < ActiveRecord::Base
if tag_names_arg.empty?
self.parent_tag = nil
else
- if tag_name = DiscourseTagging.tags_for_saving(tag_names_arg, Guardian.new(Discourse.system_user)).first
+ if tag_name =
+ DiscourseTagging.tags_for_saving(
+ tag_names_arg,
+ Guardian.new(Discourse.system_user),
+ ).first
self.parent_tag = Tag.find_by_name(tag_name) || Tag.create(name: tag_name)
end
end
@@ -40,11 +44,7 @@ class TagGroup < ActiveRecord::Base
# TODO: long term we can cache this if TONs of tag groups exist
def self.find_id_by_slug(slug)
- self.pluck(:id, :name).each do |id, name|
- if Slug.for(name) == slug
- return id
- end
- end
+ self.pluck(:id, :name).each { |id, name| return id if Slug.for(name) == slug }
nil
end
@@ -60,7 +60,7 @@ class TagGroup < ActiveRecord::Base
unless tag_group_permissions.present? || @permissions
tag_group_permissions.build(
group_id: Group::AUTO_GROUPS[:everyone],
- permission_type: TagGroupPermission.permission_types[:full]
+ permission_type: TagGroupPermission.permission_types[:full],
)
end
end
@@ -98,7 +98,11 @@ class TagGroup < ActiveRecord::Base
AND id IN (SELECT tag_group_id FROM tag_group_permissions WHERE group_id IN (?))
SQL
- TagGroup.where(filter_sql, guardian.allowed_category_ids, DiscourseTagging.permitted_group_ids(guardian))
+ TagGroup.where(
+ filter_sql,
+ guardian.allowed_category_ids,
+ DiscourseTagging.permitted_group_ids(guardian),
+ )
end
end
end
diff --git a/app/models/tag_user.rb b/app/models/tag_user.rb
index d9437ec9f4a..21a01e5c925 100644
--- a/app/models/tag_user.rb
+++ b/app/models/tag_user.rb
@@ -4,20 +4,27 @@ class TagUser < ActiveRecord::Base
belongs_to :tag
belongs_to :user
- scope :notification_level_visible, -> (notification_levels = TagUser.notification_levels.values) {
- select("tag_users.*")
- .distinct
- .joins("LEFT OUTER JOIN tag_group_memberships ON tag_users.tag_id = tag_group_memberships.tag_id")
- .joins("LEFT OUTER JOIN tag_group_permissions ON tag_group_memberships.tag_group_id = tag_group_permissions.tag_group_id")
- .joins("LEFT OUTER JOIN group_users on group_users.user_id = tag_users.user_id")
- .where("(tag_group_permissions.group_id IS NULL
+ scope :notification_level_visible,
+ ->(notification_levels = TagUser.notification_levels.values) {
+ select("tag_users.*")
+ .distinct
+ .joins(
+ "LEFT OUTER JOIN tag_group_memberships ON tag_users.tag_id = tag_group_memberships.tag_id",
+ )
+ .joins(
+ "LEFT OUTER JOIN tag_group_permissions ON tag_group_memberships.tag_group_id = tag_group_permissions.tag_group_id",
+ )
+ .joins("LEFT OUTER JOIN group_users on group_users.user_id = tag_users.user_id")
+ .where(
+ "(tag_group_permissions.group_id IS NULL
OR tag_group_permissions.group_id IN (:everyone_group_id, group_users.group_id)
OR group_users.group_id = :staff_group_id)
AND tag_users.notification_level IN (:notification_levels)",
- staff_group_id: Group::AUTO_GROUPS[:staff],
- everyone_group_id: Group::AUTO_GROUPS[:everyone],
- notification_levels: notification_levels)
- }
+ staff_group_id: Group::AUTO_GROUPS[:staff],
+ everyone_group_id: Group::AUTO_GROUPS[:everyone],
+ notification_levels: notification_levels,
+ )
+ }
def self.notification_levels
NotificationLevels.all
@@ -34,46 +41,48 @@ class TagUser < ActiveRecord::Base
records = TagUser.where(user: user, notification_level: notification_levels[level])
old_ids = records.pluck(:tag_id)
- tag_ids = if tags.empty?
- []
- elsif tags.first&.is_a?(String)
- Tag.where_name(tags).pluck(:id)
- else
- tags
- end
+ tag_ids =
+ if tags.empty?
+ []
+ elsif tags.first&.is_a?(String)
+ Tag.where_name(tags).pluck(:id)
+ else
+ tags
+ end
- Tag.where(id: tag_ids).joins(:target_tag).each do |tag|
- tag_ids[tag_ids.index(tag.id)] = tag.target_tag_id
- end
+ Tag
+ .where(id: tag_ids)
+ .joins(:target_tag)
+ .each { |tag| tag_ids[tag_ids.index(tag.id)] = tag.target_tag_id }
tag_ids.uniq!
if tag_ids.present? &&
- TagUser.where(user_id: user.id, tag_id: tag_ids)
- .where
- .not(notification_level: notification_levels[level])
- .update_all(notification_level: notification_levels[level]) > 0
-
+ TagUser
+ .where(user_id: user.id, tag_id: tag_ids)
+ .where.not(notification_level: notification_levels[level])
+ .update_all(notification_level: notification_levels[level]) > 0
changed = true
end
remove = (old_ids - tag_ids)
if remove.present?
- records.where('tag_id in (?)', remove).destroy_all
+ records.where("tag_id in (?)", remove).destroy_all
changed = true
end
now = Time.zone.now
- new_records_attrs = (tag_ids - old_ids).map do |tag_id|
- {
- user_id: user.id,
- tag_id: tag_id,
- notification_level: notification_levels[level],
- created_at: now,
- updated_at: now
- }
- end
+ new_records_attrs =
+ (tag_ids - old_ids).map do |tag_id|
+ {
+ user_id: user.id,
+ tag_id: tag_id,
+ notification_level: notification_levels[level],
+ created_at: now,
+ updated_at: now,
+ }
+ end
unless new_records_attrs.empty?
result = TagUser.insert_all(new_records_attrs)
@@ -96,9 +105,7 @@ class TagUser < ActiveRecord::Base
tag = Tag.find_by_id(tag_id)
end
- if tag.synonym?
- tag_id = tag.target_tag_id
- end
+ tag_id = tag.target_tag_id if tag.synonym?
user_id = user_id.id if user_id.is_a?(::User)
@@ -168,11 +175,12 @@ class TagUser < ActiveRecord::Base
builder.where("tu.user_id = :user_id", user_id: user_id)
end
- builder.exec(watching: notification_levels[:watching],
- tracking: notification_levels[:tracking],
- regular: notification_levels[:regular],
- auto_watch_tag: TopicUser.notification_reasons[:auto_watch_tag])
-
+ builder.exec(
+ watching: notification_levels[:watching],
+ tracking: notification_levels[:tracking],
+ regular: notification_levels[:regular],
+ auto_watch_tag: TopicUser.notification_reasons[:auto_watch_tag],
+ )
end
def self.auto_track(opts)
@@ -202,36 +210,40 @@ class TagUser < ActiveRecord::Base
builder.where("tu.user_id = :user_id", user_id: user_id)
end
- builder.exec(tracking: notification_levels[:tracking],
- regular: notification_levels[:regular],
- auto_track_tag: TopicUser.notification_reasons[:auto_track_tag])
+ builder.exec(
+ tracking: notification_levels[:tracking],
+ regular: notification_levels[:regular],
+ auto_track_tag: TopicUser.notification_reasons[:auto_track_tag],
+ )
end
def self.notification_levels_for(user)
# Anonymous users have all default tags set to regular tracking,
# except for default muted tags which stay muted.
if user.blank?
- notification_levels = [
- SiteSetting.default_tags_watching_first_post.split("|"),
- SiteSetting.default_tags_watching.split("|"),
- SiteSetting.default_tags_tracking.split("|")
- ].flatten.map do |name|
- [name, self.notification_levels[:regular]]
- end
+ notification_levels =
+ [
+ SiteSetting.default_tags_watching_first_post.split("|"),
+ SiteSetting.default_tags_watching.split("|"),
+ SiteSetting.default_tags_tracking.split("|"),
+ ].flatten.map { |name| [name, self.notification_levels[:regular]] }
- notification_levels += SiteSetting.default_tags_muted.split("|").map do |name|
- [name, self.notification_levels[:muted]]
- end
+ notification_levels +=
+ SiteSetting
+ .default_tags_muted
+ .split("|")
+ .map { |name| [name, self.notification_levels[:muted]] }
else
- notification_levels = TagUser
- .notification_level_visible
- .where(user: user)
- .joins(:tag).pluck("tags.name", :notification_level)
+ notification_levels =
+ TagUser
+ .notification_level_visible
+ .where(user: user)
+ .joins(:tag)
+ .pluck("tags.name", :notification_level)
end
Hash[*notification_levels.flatten]
end
-
end
# == Schema Information
diff --git a/app/models/theme.rb b/app/models/theme.rb
index e14fa527edc..23701642e55 100644
--- a/app/models/theme.rb
+++ b/app/models/theme.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'csv'
-require 'json_schemer'
+require "csv"
+require "json_schemer"
class Theme < ActiveRecord::Base
include GlobalPath
@@ -17,44 +17,67 @@ class Theme < ActiveRecord::Base
has_many :theme_fields, dependent: :destroy
has_many :theme_settings, dependent: :destroy
has_many :theme_translation_overrides, dependent: :destroy
- has_many :child_theme_relation, class_name: 'ChildTheme', foreign_key: 'parent_theme_id', dependent: :destroy
- has_many :parent_theme_relation, class_name: 'ChildTheme', foreign_key: 'child_theme_id', dependent: :destroy
+ has_many :child_theme_relation,
+ class_name: "ChildTheme",
+ foreign_key: "parent_theme_id",
+ dependent: :destroy
+ has_many :parent_theme_relation,
+ class_name: "ChildTheme",
+ foreign_key: "child_theme_id",
+ dependent: :destroy
has_many :child_themes, -> { order(:name) }, through: :child_theme_relation, source: :child_theme
- has_many :parent_themes, -> { order(:name) }, through: :parent_theme_relation, source: :parent_theme
+ has_many :parent_themes,
+ -> { order(:name) },
+ through: :parent_theme_relation,
+ source: :parent_theme
has_many :color_schemes
belongs_to :remote_theme, dependent: :destroy
has_one :theme_modifier_set, dependent: :destroy
- has_one :settings_field, -> { where(target_id: Theme.targets[:settings], name: "yaml") }, class_name: 'ThemeField'
+ has_one :settings_field,
+ -> { where(target_id: Theme.targets[:settings], name: "yaml") },
+ class_name: "ThemeField"
has_one :javascript_cache, dependent: :destroy
- has_many :locale_fields, -> { filter_locale_fields(I18n.fallbacks[I18n.locale]) }, class_name: 'ThemeField'
- has_many :upload_fields, -> { where(type_id: ThemeField.types[:theme_upload_var]).preload(:upload) }, class_name: 'ThemeField'
- has_many :extra_scss_fields, -> { where(target_id: Theme.targets[:extra_scss]) }, class_name: 'ThemeField'
- has_many :yaml_theme_fields, -> { where("name = 'yaml' AND type_id = ?", ThemeField.types[:yaml]) }, class_name: 'ThemeField'
- has_many :var_theme_fields, -> { where("type_id IN (?)", ThemeField.theme_var_type_ids) }, class_name: 'ThemeField'
- has_many :builder_theme_fields, -> { where("name IN (?)", ThemeField.scss_fields) }, class_name: 'ThemeField'
+ has_many :locale_fields,
+ -> { filter_locale_fields(I18n.fallbacks[I18n.locale]) },
+ class_name: "ThemeField"
+ has_many :upload_fields,
+ -> { where(type_id: ThemeField.types[:theme_upload_var]).preload(:upload) },
+ class_name: "ThemeField"
+ has_many :extra_scss_fields,
+ -> { where(target_id: Theme.targets[:extra_scss]) },
+ class_name: "ThemeField"
+ has_many :yaml_theme_fields,
+ -> { where("name = 'yaml' AND type_id = ?", ThemeField.types[:yaml]) },
+ class_name: "ThemeField"
+ has_many :var_theme_fields,
+ -> { where("type_id IN (?)", ThemeField.theme_var_type_ids) },
+ class_name: "ThemeField"
+ has_many :builder_theme_fields,
+ -> { where("name IN (?)", ThemeField.scss_fields) },
+ class_name: "ThemeField"
validate :component_validations
after_create :update_child_components
- scope :user_selectable, ->() {
- where('user_selectable OR id = ?', SiteSetting.default_theme_id)
- }
+ scope :user_selectable, -> { where("user_selectable OR id = ?", SiteSetting.default_theme_id) }
- scope :include_relations, -> {
- includes(:child_themes,
- :parent_themes,
- :remote_theme,
- :theme_settings,
- :settings_field,
- :locale_fields,
- :user,
- :color_scheme,
- :theme_translation_overrides,
- theme_fields: :upload
- )
- }
+ scope :include_relations,
+ -> {
+ includes(
+ :child_themes,
+ :parent_themes,
+ :remote_theme,
+ :theme_settings,
+ :settings_field,
+ :locale_fields,
+ :user,
+ :color_scheme,
+ :theme_translation_overrides,
+ theme_fields: :upload,
+ )
+ }
def notify_color_change(color, scheme: nil)
scheme ||= color.color_scheme
@@ -78,11 +101,11 @@ class Theme < ActiveRecord::Base
theme_modifier_set.save!
- if saved_change_to_name?
- theme_fields.select(&:basic_html_field?).each(&:invalidate_baked!)
- end
+ theme_fields.select(&:basic_html_field?).each(&:invalidate_baked!) if saved_change_to_name?
- Theme.expire_site_cache! if saved_change_to_color_scheme_id? || saved_change_to_user_selectable? || saved_change_to_name?
+ if saved_change_to_color_scheme_id? || saved_change_to_user_selectable? || saved_change_to_name?
+ Theme.expire_site_cache!
+ end
notify_with_scheme = saved_change_to_color_scheme_id?
reload
@@ -115,11 +138,12 @@ class Theme < ActiveRecord::Base
end
def update_javascript_cache!
- all_extra_js = theme_fields
- .where(target_id: Theme.targets[:extra_js])
- .order(:name, :id)
- .pluck(:name, :value)
- .to_h
+ all_extra_js =
+ theme_fields
+ .where(target_id: Theme.targets[:extra_js])
+ .order(:name, :id)
+ .pluck(:name, :value)
+ .to_h
if all_extra_js.present?
js_compiler = ThemeJavascriptCompiler.new(id, name)
@@ -135,9 +159,7 @@ class Theme < ActiveRecord::Base
after_destroy do
remove_from_cache!
- if SiteSetting.default_theme_id == self.id
- Theme.clear_default!
- end
+ Theme.clear_default! if SiteSetting.default_theme_id == self.id
if self.id
ColorScheme
@@ -145,9 +167,7 @@ class Theme < ActiveRecord::Base
.where("id NOT IN (SELECT color_scheme_id FROM themes where color_scheme_id IS NOT NULL)")
.destroy_all
- ColorScheme
- .where(theme_id: self.id)
- .update_all(theme_id: nil)
+ ColorScheme.where(theme_id: self.id).update_all(theme_id: nil)
end
Theme.expire_site_cache!
@@ -162,7 +182,7 @@ class Theme < ActiveRecord::Base
GlobalSetting.s3_cdn_url,
GlobalSetting.s3_endpoint,
GlobalSetting.s3_bucket,
- Discourse.current_hostname
+ Discourse.current_hostname,
]
Digest::SHA1.hexdigest(dependencies.join)
end
@@ -199,10 +219,7 @@ class Theme < ActiveRecord::Base
get_set_cache "allowed_remote_theme_ids" do
urls = GlobalSetting.allowed_theme_repos.split(",").map(&:strip)
- Theme
- .joins(:remote_theme)
- .where('remote_themes.remote_url in (?)', urls)
- .pluck(:id)
+ Theme.joins(:remote_theme).where("remote_themes.remote_url in (?)", urls).pluck(:id)
end
end
@@ -239,10 +256,12 @@ class Theme < ActiveRecord::Base
[id]
end
- disabled_ids = Theme.where(id: all_ids)
- .includes(:remote_theme)
- .select { |t| !t.supported? || !t.enabled? }
- .map(&:id)
+ disabled_ids =
+ Theme
+ .where(id: all_ids)
+ .includes(:remote_theme)
+ .select { |t| !t.supported? || !t.enabled? }
+ .map(&:id)
all_ids - disabled_ids
end
@@ -250,9 +269,7 @@ class Theme < ActiveRecord::Base
def set_default!
if component
- raise Discourse::InvalidParameters.new(
- I18n.t("themes.errors.component_no_default")
- )
+ raise Discourse::InvalidParameters.new(I18n.t("themes.errors.component_no_default"))
end
SiteSetting.default_theme_id = id
Theme.expire_site_cache!
@@ -335,22 +352,35 @@ class Theme < ActiveRecord::Base
end
def self.clear_cache!
- DB.after_commit do
- @cache.clear
- end
+ DB.after_commit { @cache.clear }
end
def self.targets
- @targets ||= Enum.new(common: 0, desktop: 1, mobile: 2, settings: 3, translations: 4, extra_scss: 5, extra_js: 6, tests_js: 7)
+ @targets ||=
+ Enum.new(
+ common: 0,
+ desktop: 1,
+ mobile: 2,
+ settings: 3,
+ translations: 4,
+ extra_scss: 5,
+ extra_js: 6,
+ tests_js: 7,
+ )
end
def self.lookup_target(target_id)
self.targets.invert[target_id]
end
- def self.notify_theme_change(theme_ids, with_scheme: false, clear_manager_cache: true, all_themes: false)
+ def self.notify_theme_change(
+ theme_ids,
+ with_scheme: false,
+ clear_manager_cache: true,
+ all_themes: false
+ )
Stylesheet::Manager.clear_theme_cache!
- targets = [:mobile_theme, :desktop_theme]
+ targets = %i[mobile_theme desktop_theme]
if with_scheme
targets.prepend(:desktop, :mobile, :admin)
@@ -364,7 +394,7 @@ class Theme < ActiveRecord::Base
message = refresh_message_for_targets(targets, theme_ids).flatten
end
- MessageBus.publish('/file-change', message)
+ MessageBus.publish("/file-change", message)
end
def notify_theme_change(with_scheme: false)
@@ -386,20 +416,22 @@ class Theme < ActiveRecord::Base
def self.resolve_baked_field(theme_ids, target, name)
if target == :extra_js
- require_rebake = ThemeField.where(theme_id: theme_ids, target_id: Theme.targets[:extra_js]).
- where("compiler_version <> ?", Theme.compiler_version)
+ require_rebake =
+ ThemeField.where(theme_id: theme_ids, target_id: Theme.targets[:extra_js]).where(
+ "compiler_version <> ?",
+ Theme.compiler_version,
+ )
require_rebake.each { |tf| tf.ensure_baked! }
- require_rebake.map(&:theme_id).uniq.each do |theme_id|
- Theme.find(theme_id).update_javascript_cache!
- end
+ require_rebake
+ .map(&:theme_id)
+ .uniq
+ .each { |theme_id| Theme.find(theme_id).update_javascript_cache! }
caches = JavascriptCache.where(theme_id: theme_ids)
caches = caches.sort_by { |cache| theme_ids.index(cache.theme_id) }
- return caches.map do |c|
- <<~HTML.html_safe
+ return caches.map { |c| <<~HTML.html_safe }.join("\n")
HTML
- end.join("\n")
end
list_baked_fields(theme_ids, target, name).map { |f| f.value_baked || f.value }.join("\n")
end
@@ -413,8 +445,10 @@ class Theme < ActiveRecord::Base
else
target = :mobile if target == :mobile_theme
target = :desktop if target == :desktop_theme
- fields = ThemeField.find_by_theme_ids(theme_ids)
- .where(target_id: [Theme.targets[target], Theme.targets[:common]])
+ fields =
+ ThemeField.find_by_theme_ids(theme_ids).where(
+ target_id: [Theme.targets[target], Theme.targets[:common]],
+ )
fields = fields.where(name: name.to_s) unless name.nil?
fields = fields.order(:target_id)
end
@@ -455,12 +489,14 @@ class Theme < ActiveRecord::Base
target_id = Theme.targets[target.to_sym]
raise "Unknown target #{target} passed to set field" unless target_id
- type_id ||= type ? ThemeField.types[type.to_sym] : ThemeField.guess_type(name: name, target: target)
+ type_id ||=
+ type ? ThemeField.types[type.to_sym] : ThemeField.guess_type(name: name, target: target)
raise "Unknown type #{type} passed to set field" unless type_id
value ||= ""
- field = theme_fields.find { |f| f.name == name && f.target_id == target_id && f.type_id == type_id }
+ field =
+ theme_fields.find { |f| f.name == name && f.target_id == target_id && f.type_id == type_id }
if field
if value.blank? && !upload_id
theme_fields.delete field.destroy
@@ -473,16 +509,25 @@ class Theme < ActiveRecord::Base
end
field
else
- theme_fields.build(target_id: target_id, value: value, name: name, type_id: type_id, upload_id: upload_id) if value.present? || upload_id.present?
+ if value.present? || upload_id.present?
+ theme_fields.build(
+ target_id: target_id,
+ value: value,
+ name: name,
+ type_id: type_id,
+ upload_id: upload_id,
+ )
+ end
end
end
def add_relative_theme!(kind, theme)
- new_relation = if kind == :child
- child_theme_relation.new(child_theme_id: theme.id)
- else
- parent_theme_relation.new(parent_theme_id: theme.id)
- end
+ new_relation =
+ if kind == :child
+ child_theme_relation.new(child_theme_id: theme.id)
+ else
+ parent_theme_relation.new(parent_theme_id: theme.id)
+ end
if new_relation.save
child_themes.reload
parent_themes.reload
@@ -500,13 +545,20 @@ class Theme < ActiveRecord::Base
def translations(internal: false)
fallbacks = I18n.fallbacks[I18n.locale]
begin
- data = locale_fields.first&.translation_data(with_overrides: false, internal: internal, fallback_fields: locale_fields)
+ data =
+ locale_fields.first&.translation_data(
+ with_overrides: false,
+ internal: internal,
+ fallback_fields: locale_fields,
+ )
return {} if data.nil?
best_translations = {}
- fallbacks.reverse.each do |locale|
- best_translations.deep_merge! data[locale] if data[locale]
- end
- ThemeTranslationManager.list_from_hash(theme: self, hash: best_translations, locale: I18n.locale)
+ fallbacks.reverse.each { |locale| best_translations.deep_merge! data[locale] if data[locale] }
+ ThemeTranslationManager.list_from_hash(
+ theme: self,
+ hash: best_translations,
+ locale: I18n.locale,
+ )
rescue ThemeTranslationParser::InvalidYaml
{}
end
@@ -517,9 +569,11 @@ class Theme < ActiveRecord::Base
return [] unless field && field.error.nil?
settings = []
- ThemeSettingsParser.new(field).load do |name, default, type, opts|
- settings << ThemeSettingsManager.create(name, default, type, self, opts)
- end
+ ThemeSettingsParser
+ .new(field)
+ .load do |name, default, type, opts|
+ settings << ThemeSettingsManager.create(name, default, type, self, opts)
+ end
settings
end
@@ -532,15 +586,13 @@ class Theme < ActiveRecord::Base
def cached_default_settings
Theme.get_set_cache "default_settings_for_theme_#{self.id}" do
settings_hash = {}
- self.settings.each do |setting|
- settings_hash[setting.name] = setting.default
- end
+ self.settings.each { |setting| settings_hash[setting.name] = setting.default }
theme_uploads = build_theme_uploads_hash
- settings_hash['theme_uploads'] = theme_uploads if theme_uploads.present?
+ settings_hash["theme_uploads"] = theme_uploads if theme_uploads.present?
theme_uploads_local = build_local_theme_uploads_hash
- settings_hash['theme_uploads_local'] = theme_uploads_local if theme_uploads_local.present?
+ settings_hash["theme_uploads_local"] = theme_uploads_local if theme_uploads_local.present?
settings_hash
end
@@ -548,15 +600,13 @@ class Theme < ActiveRecord::Base
def build_settings_hash
hash = {}
- self.settings.each do |setting|
- hash[setting.name] = setting.value
- end
+ self.settings.each { |setting| hash[setting.name] = setting.value }
theme_uploads = build_theme_uploads_hash
- hash['theme_uploads'] = theme_uploads if theme_uploads.present?
+ hash["theme_uploads"] = theme_uploads if theme_uploads.present?
theme_uploads_local = build_local_theme_uploads_hash
- hash['theme_uploads_local'] = theme_uploads_local if theme_uploads_local.present?
+ hash["theme_uploads_local"] = theme_uploads_local if theme_uploads_local.present?
hash
end
@@ -564,9 +614,7 @@ class Theme < ActiveRecord::Base
def build_theme_uploads_hash
hash = {}
upload_fields.each do |field|
- if field.upload&.url
- hash[field.name] = Discourse.store.cdn_url(field.upload.url)
- end
+ hash[field.name] = Discourse.store.cdn_url(field.upload.url) if field.upload&.url
end
hash
end
@@ -574,9 +622,7 @@ class Theme < ActiveRecord::Base
def build_local_theme_uploads_hash
hash = {}
upload_fields.each do |field|
- if field.javascript_cache
- hash[field.name] = field.javascript_cache.local_url
- end
+ hash[field.name] = field.javascript_cache.local_url if field.javascript_cache
end
hash
end
@@ -587,9 +633,7 @@ class Theme < ActiveRecord::Base
target_setting.value = new_value
- if target_setting.requests_refresh?
- self.theme_setting_requests_refresh = true
- end
+ self.theme_setting_requests_refresh = true if target_setting.requests_refresh?
end
def update_translation(translation_key, new_value)
@@ -603,9 +647,7 @@ class Theme < ActiveRecord::Base
theme_translation_overrides.each do |override|
cursor = hash
path = [override.locale] + override.translation_key.split(".")
- path[0..-2].each do |key|
- cursor = (cursor[key] ||= {})
- end
+ path[0..-2].each { |key| cursor = (cursor[key] ||= {}) }
cursor[path[-1]] = override.value
end
hash
@@ -622,9 +664,9 @@ class Theme < ActiveRecord::Base
end
meta[:assets] = {}.tap do |hash|
- theme_fields.where(type_id: ThemeField.types[:theme_upload_var]).each do |field|
- hash[field.name] = field.file_path
- end
+ theme_fields
+ .where(type_id: ThemeField.types[:theme_upload_var])
+ .each { |field| hash[field.name] = field.file_path }
end
meta[:color_schemes] = {}.tap do |hash|
@@ -632,7 +674,9 @@ class Theme < ActiveRecord::Base
# The selected color scheme may not belong to the theme, so include it anyway
schemes = [self.color_scheme] + schemes if self.color_scheme
schemes.uniq.each do |scheme|
- hash[scheme.name] = {}.tap { |colors| scheme.colors.each { |color| colors[color.name] = color.hex } }
+ hash[scheme.name] = {}.tap do |colors|
+ scheme.colors.each { |color| colors[color.name] = color.hex }
+ end
end
end
@@ -643,8 +687,9 @@ class Theme < ActiveRecord::Base
end
end
- meta[:learn_more] = "https://meta.discourse.org/t/beginners-guide-to-using-discourse-themes/91966"
-
+ meta[
+ :learn_more
+ ] = "https://meta.discourse.org/t/beginners-guide-to-using-discourse-themes/91966"
end
end
@@ -659,9 +704,9 @@ class Theme < ActiveRecord::Base
def with_scss_load_paths
return yield([]) if self.extra_scss_fields.empty?
- ThemeStore::ZipExporter.new(self).with_export_dir(extra_scss_only: true) do |dir|
- yield ["#{dir}/stylesheets"]
- end
+ ThemeStore::ZipExporter
+ .new(self)
+ .with_export_dir(extra_scss_only: true) { |dir| yield ["#{dir}/stylesheets"] }
end
def scss_variables
@@ -696,12 +741,15 @@ class Theme < ActiveRecord::Base
setting_row = ThemeSetting.where(theme_id: self.id, name: setting.name.to_s).first
if setting_row && setting_row.data_type != setting.type
- if (setting_row.data_type == ThemeSetting.types[:list] &&
- setting.type == ThemeSetting.types[:string] &&
- setting.json_schema.present?)
+ if (
+ setting_row.data_type == ThemeSetting.types[:list] &&
+ setting.type == ThemeSetting.types[:string] && setting.json_schema.present?
+ )
convert_list_to_json_schema(setting_row, setting)
else
- Rails.logger.warn("Theme setting type has changed but cannot be converted. \n\n #{setting.inspect}")
+ Rails.logger.warn(
+ "Theme setting type has changed but cannot be converted. \n\n #{setting.inspect}",
+ )
end
end
end
@@ -713,10 +761,10 @@ class Theme < ActiveRecord::Base
keys = schema["items"]["properties"].keys
return if !keys
- current_values = CSV.parse(setting_row.value, **{ col_sep: '|' }).flatten
+ current_values = CSV.parse(setting_row.value, **{ col_sep: "|" }).flatten
new_values = []
current_values.each do |item|
- parts = CSV.parse(item, **{ col_sep: ',' }).flatten
+ parts = CSV.parse(item, **{ col_sep: "," }).flatten
props = parts.map.with_index { |p, idx| [keys[idx], p] }.to_h
new_values << props
end
@@ -730,13 +778,14 @@ class Theme < ActiveRecord::Base
end
def baked_js_tests_with_digest
- tests_tree = theme_fields
- .where(target_id: Theme.targets[:tests_js])
- .order(name: :asc)
- .pluck(:name, :value)
- .to_h
+ tests_tree =
+ theme_fields
+ .where(target_id: Theme.targets[:tests_js])
+ .order(name: :asc)
+ .pluck(:name, :value)
+ .to_h
- return [nil, nil] if tests_tree.blank?
+ return nil, nil if tests_tree.blank?
compiler = ThemeJavascriptCompiler.new(id, name)
compiler.append_tree(tests_tree, for_tests: true)
@@ -748,7 +797,8 @@ class Theme < ActiveRecord::Base
content = compiler.content
if compiler.source_map
- content += "\n//# sourceMappingURL=data:application/json;base64,#{Base64.strict_encode64(compiler.source_map)}\n"
+ content +=
+ "\n//# sourceMappingURL=data:application/json;base64,#{Base64.strict_encode64(compiler.source_map)}\n"
end
[content, Digest::SHA1.hexdigest(content)]
@@ -765,7 +815,11 @@ class Theme < ActiveRecord::Base
def find_disable_action_log
if component? && !enabled?
- @disable_log ||= UserHistory.where(context: id.to_s, action: UserHistory.actions[:disable_theme_component]).order("created_at DESC").first
+ @disable_log ||=
+ UserHistory
+ .where(context: id.to_s, action: UserHistory.actions[:disable_theme_component])
+ .order("created_at DESC")
+ .first
end
end
end
diff --git a/app/models/theme_field.rb b/app/models/theme_field.rb
index 4c45b08b60d..780789c42bf 100644
--- a/app/models/theme_field.rb
+++ b/app/models/theme_field.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ThemeField < ActiveRecord::Base
-
belongs_to :upload
has_one :javascript_cache, dependent: :destroy
has_one :upload_reference, as: :target, dependent: :destroy
@@ -12,45 +11,50 @@ class ThemeField < ActiveRecord::Base
end
end
- scope :find_by_theme_ids, ->(theme_ids) {
- return none unless theme_ids.present?
+ scope :find_by_theme_ids,
+ ->(theme_ids) {
+ return none unless theme_ids.present?
- where(theme_id: theme_ids)
- .joins(
- "JOIN (
+ where(theme_id: theme_ids).joins(
+ "JOIN (
SELECT #{theme_ids.map.with_index { |id, idx| "#{id.to_i} AS theme_id, #{idx} AS theme_sort_column" }.join(" UNION ALL SELECT ")}
- ) as X ON X.theme_id = theme_fields.theme_id")
- .order("theme_sort_column")
- }
+ ) as X ON X.theme_id = theme_fields.theme_id",
+ ).order("theme_sort_column")
+ }
- scope :filter_locale_fields, ->(locale_codes) {
- return none unless locale_codes.present?
+ scope :filter_locale_fields,
+ ->(locale_codes) {
+ return none unless locale_codes.present?
- where(target_id: Theme.targets[:translations], name: locale_codes)
- .joins(DB.sql_fragment(
- "JOIN (
+ where(target_id: Theme.targets[:translations], name: locale_codes).joins(
+ DB.sql_fragment(
+ "JOIN (
SELECT * FROM (VALUES #{locale_codes.map { "(?)" }.join(",")}) as Y (locale_code, locale_sort_column)
) as Y ON Y.locale_code = theme_fields.name",
- *locale_codes.map.with_index { |code, index| [code, index] }
- ))
- .order("Y.locale_sort_column")
- }
+ *locale_codes.map.with_index { |code, index| [code, index] },
+ ),
+ ).order("Y.locale_sort_column")
+ }
- scope :find_first_locale_fields, ->(theme_ids, locale_codes) {
- find_by_theme_ids(theme_ids)
- .filter_locale_fields(locale_codes)
- .reorder("X.theme_sort_column", "Y.locale_sort_column")
- .select("DISTINCT ON (X.theme_sort_column) *")
- }
+ scope :find_first_locale_fields,
+ ->(theme_ids, locale_codes) {
+ find_by_theme_ids(theme_ids)
+ .filter_locale_fields(locale_codes)
+ .reorder("X.theme_sort_column", "Y.locale_sort_column")
+ .select("DISTINCT ON (X.theme_sort_column) *")
+ }
def self.types
- @types ||= Enum.new(html: 0,
- scss: 1,
- theme_upload_var: 2,
- theme_color_var: 3, # No longer used
- theme_var: 4, # No longer used
- yaml: 5,
- js: 6)
+ @types ||=
+ Enum.new(
+ html: 0,
+ scss: 1,
+ theme_upload_var: 2,
+ theme_color_var: 3, # No longer used
+ theme_var: 4, # No longer used
+ yaml: 5,
+ js: 6,
+ )
end
def self.theme_var_type_ids
@@ -68,8 +72,11 @@ class ThemeField < ActiveRecord::Base
end
end
- validates :name, format: { with: /\A[a-z_][a-z0-9_-]*\z/i },
- if: Proc.new { |field| ThemeField.theme_var_type_ids.include?(field.type_id) }
+ validates :name,
+ format: {
+ with: /\A[a-z_][a-z0-9_-]*\z/i,
+ },
+ if: Proc.new { |field| ThemeField.theme_var_type_ids.include?(field.type_id) }
belongs_to :theme
@@ -83,36 +90,38 @@ class ThemeField < ActiveRecord::Base
doc = Nokogiri::HTML5.fragment(html)
- doc.css('script[type="text/x-handlebars"]').each do |node|
- name = node["name"] || node["data-template-name"] || "broken"
- is_raw = name =~ /\.(raw|hbr)$/
- hbs_template = node.inner_html
+ doc
+ .css('script[type="text/x-handlebars"]')
+ .each do |node|
+ name = node["name"] || node["data-template-name"] || "broken"
+ is_raw = name =~ /\.(raw|hbr)$/
+ hbs_template = node.inner_html
- begin
- if is_raw
- js_compiler.append_raw_template(name, hbs_template)
- else
- js_compiler.append_ember_template("discourse/templates/#{name}", hbs_template)
+ begin
+ if is_raw
+ js_compiler.append_raw_template(name, hbs_template)
+ else
+ js_compiler.append_ember_template("discourse/templates/#{name}", hbs_template)
+ end
+ rescue ThemeJavascriptCompiler::CompileError => ex
+ js_compiler.append_js_error("discourse/templates/#{name}", ex.message)
+ errors << ex.message
end
- rescue ThemeJavascriptCompiler::CompileError => ex
- js_compiler.append_js_error("discourse/templates/#{name}", ex.message)
- errors << ex.message
+
+ node.remove
end
- node.remove
- end
+ doc
+ .css('script[type="text/discourse-plugin"]')
+ .each_with_index do |node, index|
+ version = node["version"]
+ next if version.blank?
- doc.css('script[type="text/discourse-plugin"]').each_with_index do |node, index|
- version = node['version']
- next if version.blank?
-
- initializer_name = "theme-field" +
- "-#{self.id}" +
- "-#{Theme.targets[self.target_id]}" +
- "-#{ThemeField.types[self.type_id]}" +
- "-script-#{index + 1}"
- begin
- js = <<~JS
+ initializer_name =
+ "theme-field" + "-#{self.id}" + "-#{Theme.targets[self.target_id]}" +
+ "-#{ThemeField.types[self.type_id]}" + "-script-#{index + 1}"
+ begin
+ js = <<~JS
import { withPluginApi } from "discourse/lib/plugin-api";
export default {
@@ -127,43 +136,60 @@ class ThemeField < ActiveRecord::Base
};
JS
- js_compiler.append_module(js, "discourse/initializers/#{initializer_name}", include_variables: true)
- rescue ThemeJavascriptCompiler::CompileError => ex
- js_compiler.append_js_error("discourse/initializers/#{initializer_name}", ex.message)
- errors << ex.message
+ js_compiler.append_module(
+ js,
+ "discourse/initializers/#{initializer_name}",
+ include_variables: true,
+ )
+ rescue ThemeJavascriptCompiler::CompileError => ex
+ js_compiler.append_js_error("discourse/initializers/#{initializer_name}", ex.message)
+ errors << ex.message
+ end
+
+ node.remove
end
- node.remove
- end
-
- doc.css('script').each_with_index do |node, index|
- next unless inline_javascript?(node)
- js_compiler.append_raw_script("_html/#{Theme.targets[self.target_id]}/#{name}_#{index + 1}.js", node.inner_html)
- node.remove
- end
+ doc
+ .css("script")
+ .each_with_index do |node, index|
+ next unless inline_javascript?(node)
+ js_compiler.append_raw_script(
+ "_html/#{Theme.targets[self.target_id]}/#{name}_#{index + 1}.js",
+ node.inner_html,
+ )
+ node.remove
+ end
settings_hash = theme.build_settings_hash
- js_compiler.prepend_settings(settings_hash) if js_compiler.has_content? && settings_hash.present?
+ if js_compiler.has_content? && settings_hash.present?
+ js_compiler.prepend_settings(settings_hash)
+ end
javascript_cache.content = js_compiler.content
javascript_cache.source_map = js_compiler.source_map
javascript_cache.save!
- if javascript_cache.content.present?
- doc.add_child(
- <<~HTML.html_safe
+ doc.add_child(<<~HTML.html_safe) if javascript_cache.content.present?
HTML
- )
- end
[doc.to_s, errors&.join("\n")]
end
def validate_svg_sprite_xml
- upload = Upload.find(self.upload_id) rescue nil
+ upload =
+ begin
+ Upload.find(self.upload_id)
+ rescue StandardError
+ nil
+ end
if Discourse.store.external?
- external_copy = Discourse.store.download(upload) rescue nil
+ external_copy =
+ begin
+ Discourse.store.download(upload)
+ rescue StandardError
+ nil
+ end
path = external_copy.try(:path)
else
path = Discourse.store.path_for(upload)
@@ -173,9 +199,7 @@ class ThemeField < ActiveRecord::Base
begin
content = File.read(path)
- Nokogiri::XML(content) do |config|
- config.options = Nokogiri::XML::ParseOptions::NOBLANKS
- end
+ Nokogiri.XML(content) { |config| config.options = Nokogiri::XML::ParseOptions::NOBLANKS }
rescue => e
error = "Error with #{self.name}: #{e.inspect}"
end
@@ -190,16 +214,17 @@ class ThemeField < ActiveRecord::Base
def translation_data(with_overrides: true, internal: false, fallback_fields: nil)
fallback_fields ||= theme.theme_fields.filter_locale_fields(I18n.fallbacks[name])
- fallback_data = fallback_fields.each_with_index.map do |field, index|
- begin
- field.raw_translation_data(internal: internal)
- rescue ThemeTranslationParser::InvalidYaml
- # If this is the locale with the error, raise it.
- # If not, let the other theme_field raise the error when it processes itself
- raise if field.id == id
- {}
+ fallback_data =
+ fallback_fields.each_with_index.map do |field, index|
+ begin
+ field.raw_translation_data(internal: internal)
+ rescue ThemeTranslationParser::InvalidYaml
+ # If this is the locale with the error, raise it.
+ # If not, let the other theme_field raise the error when it processes itself
+ raise if field.id == id
+ {}
+ end
end
- end
# TODO: Deduplicate the fallback data in the same way as JSLocaleHelper#load_translations_merged
# this would reduce the size of the payload, without affecting functionality
@@ -239,7 +264,11 @@ class ThemeField < ActiveRecord::Base
};
JS
- js_compiler.append_module(js, "discourse/pre-initializers/theme-#{theme_id}-translations", include_variables: false)
+ js_compiler.append_module(
+ js,
+ "discourse/pre-initializers/theme-#{theme_id}-translations",
+ include_variables: false,
+ )
rescue ThemeTranslationParser::InvalidYaml => e
errors << e.message
end
@@ -248,13 +277,10 @@ class ThemeField < ActiveRecord::Base
javascript_cache.source_map = js_compiler.source_map
javascript_cache.save!
doc = ""
- if javascript_cache.content.present?
- doc =
- <<~HTML.html_safe
+ doc = <<~HTML.html_safe if javascript_cache.content.present?
HTML
- end
[doc, errors&.join("\n")]
end
@@ -263,32 +289,32 @@ class ThemeField < ActiveRecord::Base
errors = []
begin
- ThemeSettingsParser.new(self).load do |name, default, type, opts|
- setting = ThemeSetting.new(name: name, data_type: type, theme: theme)
- translation_key = "themes.settings_errors"
+ ThemeSettingsParser
+ .new(self)
+ .load do |name, default, type, opts|
+ setting = ThemeSetting.new(name: name, data_type: type, theme: theme)
+ translation_key = "themes.settings_errors"
- if setting.invalid?
- setting.errors.details.each_pair do |attribute, _errors|
- _errors.each do |hash|
- errors << I18n.t("#{translation_key}.#{attribute}_#{hash[:error]}", name: name)
+ if setting.invalid?
+ setting.errors.details.each_pair do |attribute, _errors|
+ _errors.each do |hash|
+ errors << I18n.t("#{translation_key}.#{attribute}_#{hash[:error]}", name: name)
+ end
end
end
- end
- if default.nil?
- errors << I18n.t("#{translation_key}.default_value_missing", name: name)
- end
+ errors << I18n.t("#{translation_key}.default_value_missing", name: name) if default.nil?
- if (min = opts[:min]) && (max = opts[:max])
- unless ThemeSetting.value_in_range?(default, (min..max), type)
- errors << I18n.t("#{translation_key}.default_out_range", name: name)
+ if (min = opts[:min]) && (max = opts[:max])
+ unless ThemeSetting.value_in_range?(default, (min..max), type)
+ errors << I18n.t("#{translation_key}.default_out_range", name: name)
+ end
+ end
+
+ unless ThemeSetting.acceptable_value_for_type?(default, type)
+ errors << I18n.t("#{translation_key}.default_not_match_type", name: name)
end
end
-
- unless ThemeSetting.acceptable_value_for_type?(default, type)
- errors << I18n.t("#{translation_key}.default_not_match_type", name: name)
- end
- end
rescue ThemeSettingsParser::InvalidYaml => e
errors << e.message
end
@@ -311,15 +337,15 @@ class ThemeField < ActiveRecord::Base
end
def self.html_fields
- @html_fields ||= %w(body_tag head_tag header footer after_header)
+ @html_fields ||= %w[body_tag head_tag header footer after_header]
end
def self.scss_fields
- @scss_fields ||= %w(scss embedded_scss color_definitions)
+ @scss_fields ||= %w[scss embedded_scss color_definitions]
end
def self.basic_targets
- @basic_targets ||= %w(common desktop mobile)
+ @basic_targets ||= %w[common desktop mobile]
end
def basic_html_field?
@@ -353,7 +379,8 @@ class ThemeField < ActiveRecord::Base
end
def svg_sprite_field?
- ThemeField.theme_var_type_ids.include?(self.type_id) && self.name == SvgSprite.theme_sprite_variable_name
+ ThemeField.theme_var_type_ids.include?(self.type_id) &&
+ self.name == SvgSprite.theme_sprite_variable_name
end
def ensure_baked!
@@ -361,7 +388,8 @@ class ThemeField < ActiveRecord::Base
return unless needs_baking
if basic_html_field? || translation_field?
- self.value_baked, self.error = translation_field? ? process_translation : process_html(self.value)
+ self.value_baked, self.error =
+ translation_field? ? process_translation : process_html(self.value)
self.error = nil unless self.error.present?
self.compiler_version = Theme.compiler_version
DB.after_commit { CSP::Extension.clear_theme_extensions_cache! }
@@ -385,13 +413,13 @@ class ThemeField < ActiveRecord::Base
self.compiler_version = Theme.compiler_version
end
- if self.will_save_change_to_value_baked? ||
- self.will_save_change_to_compiler_version? ||
- self.will_save_change_to_error?
-
- self.update_columns(value_baked: value_baked,
- compiler_version: compiler_version,
- error: error)
+ if self.will_save_change_to_value_baked? || self.will_save_change_to_compiler_version? ||
+ self.will_save_change_to_error?
+ self.update_columns(
+ value_baked: value_baked,
+ compiler_version: compiler_version,
+ error: error,
+ )
end
end
@@ -399,23 +427,25 @@ class ThemeField < ActiveRecord::Base
prepended_scss ||= Stylesheet::Importer.new({}).prepended_scss
self.theme.with_scss_load_paths do |load_paths|
- Stylesheet::Compiler.compile("#{prepended_scss} #{self.theme.scss_variables.to_s} #{self.value}",
+ Stylesheet::Compiler.compile(
+ "#{prepended_scss} #{self.theme.scss_variables.to_s} #{self.value}",
"#{Theme.targets[self.target_id]}.scss",
theme: self.theme,
- load_paths: load_paths
+ load_paths: load_paths,
)
end
end
def compiled_css(prepended_scss)
- css, _source_map = begin
- compile_scss(prepended_scss)
- rescue SassC::SyntaxError => e
- # We don't want to raise a blocking error here
- # admin theme editor or discourse_theme CLI will show it nonetheless
- Rails.logger.error "SCSS compilation error: #{e.message}"
- ["", nil]
- end
+ css, _source_map =
+ begin
+ compile_scss(prepended_scss)
+ rescue SassC::SyntaxError => e
+ # We don't want to raise a blocking error here
+ # admin theme editor or discourse_theme CLI will show it nonetheless
+ Rails.logger.error "SCSS compilation error: #{e.message}"
+ ["", nil]
+ end
css
end
@@ -450,7 +480,7 @@ class ThemeField < ActiveRecord::Base
end
class ThemeFileMatcher
- OPTIONS = %i{name type target}
+ OPTIONS = %i[name type target]
# regex: used to match file names to fields (import).
# can contain named capture groups for name/type/target
# canonical: a lambda which converts name/type/target
@@ -480,55 +510,100 @@ class ThemeField < ActiveRecord::Base
end
def filename_from_opts(opts)
- is_match = OPTIONS.all? do |option|
- plural = :"#{option}s"
- next true if @allowed_values[plural] == nil # Allows any value
- next true if @allowed_values[plural].include?(opts[option]) # Value is allowed
- end
+ is_match =
+ OPTIONS.all? do |option|
+ plural = :"#{option}s"
+ next true if @allowed_values[plural] == nil # Allows any value
+ next true if @allowed_values[plural].include?(opts[option]) # Value is allowed
+ end
is_match ? @canonical.call(opts) : nil
end
end
FILE_MATCHERS = [
- ThemeFileMatcher.new(regex: /^(?(?:mobile|desktop|common))\/(?(?:head_tag|header|after_header|body_tag|footer))\.html$/,
- targets: [:mobile, :desktop, :common], names: ["head_tag", "header", "after_header", "body_tag", "footer"], types: :html,
- canonical: -> (h) { "#{h[:target]}/#{h[:name]}.html" }),
- ThemeFileMatcher.new(regex: /^(?(?:mobile|desktop|common))\/(?:\k)\.scss$/,
- targets: [:mobile, :desktop, :common], names: "scss", types: :scss,
- canonical: -> (h) { "#{h[:target]}/#{h[:target]}.scss" }),
- ThemeFileMatcher.new(regex: /^common\/embedded\.scss$/,
- targets: :common, names: "embedded_scss", types: :scss,
- canonical: -> (h) { "common/embedded.scss" }),
- ThemeFileMatcher.new(regex: /^common\/color_definitions\.scss$/,
- targets: :common, names: "color_definitions", types: :scss,
- canonical: -> (h) { "common/color_definitions.scss" }),
- ThemeFileMatcher.new(regex: /^(?:scss|stylesheets)\/(?.+)\.scss$/,
- targets: :extra_scss, names: nil, types: :scss,
- canonical: -> (h) { "stylesheets/#{h[:name]}.scss" }),
- ThemeFileMatcher.new(regex: /^javascripts\/(?.+)$/,
- targets: :extra_js, names: nil, types: :js,
- canonical: -> (h) { "javascripts/#{h[:name]}" }),
- ThemeFileMatcher.new(regex: /^test\/(?.+)$/,
- targets: :tests_js, names: nil, types: :js,
- canonical: -> (h) { "test/#{h[:name]}" }),
- ThemeFileMatcher.new(regex: /^settings\.ya?ml$/,
- names: "yaml", types: :yaml, targets: :settings,
- canonical: -> (h) { "settings.yml" }),
- ThemeFileMatcher.new(regex: /^locales\/(?(?:#{I18n.available_locales.join("|")}))\.yml$/,
- names: I18n.available_locales.map(&:to_s), types: :yaml, targets: :translations,
- canonical: -> (h) { "locales/#{h[:name]}.yml" }),
- ThemeFileMatcher.new(regex: /(?!)/, # Never match uploads by filename, they must be named in about.json
- names: nil, types: :theme_upload_var, targets: :common,
- canonical: -> (h) { "assets/#{h[:name]}#{File.extname(h[:filename])}" }),
+ ThemeFileMatcher.new(
+ regex:
+ %r{^(?(?:mobile|desktop|common))/(?(?:head_tag|header|after_header|body_tag|footer))\.html$},
+ targets: %i[mobile desktop common],
+ names: %w[head_tag header after_header body_tag footer],
+ types: :html,
+ canonical: ->(h) { "#{h[:target]}/#{h[:name]}.html" },
+ ),
+ ThemeFileMatcher.new(
+ regex: %r{^(?(?:mobile|desktop|common))/(?:\k)\.scss$},
+ targets: %i[mobile desktop common],
+ names: "scss",
+ types: :scss,
+ canonical: ->(h) { "#{h[:target]}/#{h[:target]}.scss" },
+ ),
+ ThemeFileMatcher.new(
+ regex: %r{^common/embedded\.scss$},
+ targets: :common,
+ names: "embedded_scss",
+ types: :scss,
+ canonical: ->(h) { "common/embedded.scss" },
+ ),
+ ThemeFileMatcher.new(
+ regex: %r{^common/color_definitions\.scss$},
+ targets: :common,
+ names: "color_definitions",
+ types: :scss,
+ canonical: ->(h) { "common/color_definitions.scss" },
+ ),
+ ThemeFileMatcher.new(
+ regex: %r{^(?:scss|stylesheets)/(?.+)\.scss$},
+ targets: :extra_scss,
+ names: nil,
+ types: :scss,
+ canonical: ->(h) { "stylesheets/#{h[:name]}.scss" },
+ ),
+ ThemeFileMatcher.new(
+ regex: %r{^javascripts/(?.+)$},
+ targets: :extra_js,
+ names: nil,
+ types: :js,
+ canonical: ->(h) { "javascripts/#{h[:name]}" },
+ ),
+ ThemeFileMatcher.new(
+ regex: %r{^test/(?.+)$},
+ targets: :tests_js,
+ names: nil,
+ types: :js,
+ canonical: ->(h) { "test/#{h[:name]}" },
+ ),
+ ThemeFileMatcher.new(
+ regex: /^settings\.ya?ml$/,
+ names: "yaml",
+ types: :yaml,
+ targets: :settings,
+ canonical: ->(h) { "settings.yml" },
+ ),
+ ThemeFileMatcher.new(
+ regex: %r{^locales/(?(?:#{I18n.available_locales.join("|")}))\.yml$},
+ names: I18n.available_locales.map(&:to_s),
+ types: :yaml,
+ targets: :translations,
+ canonical: ->(h) { "locales/#{h[:name]}.yml" },
+ ),
+ ThemeFileMatcher.new(
+ regex: /(?!)/, # Never match uploads by filename, they must be named in about.json
+ names: nil,
+ types: :theme_upload_var,
+ targets: :common,
+ canonical: ->(h) { "assets/#{h[:name]}#{File.extname(h[:filename])}" },
+ ),
]
# For now just work for standard fields
def file_path
FILE_MATCHERS.each do |matcher|
- if filename = matcher.filename_from_opts(target: target_name.to_sym,
- name: name,
- type: ThemeField.types[type_id],
- filename: upload&.original_filename)
+ if filename =
+ matcher.filename_from_opts(
+ target: target_name.to_sym,
+ name: name,
+ type: ThemeField.types[type_id],
+ filename: upload&.original_filename,
+ )
return filename
end
end
@@ -546,11 +621,19 @@ class ThemeField < ActiveRecord::Base
def dependent_fields
if extra_scss_field?
- return theme.theme_fields.where(target_id: ThemeField.basic_targets.map { |t| Theme.targets[t.to_sym] },
- name: ThemeField.scss_fields)
+ return(
+ theme.theme_fields.where(
+ target_id: ThemeField.basic_targets.map { |t| Theme.targets[t.to_sym] },
+ name: ThemeField.scss_fields,
+ )
+ )
elsif settings_field?
- return theme.theme_fields.where(target_id: ThemeField.basic_targets.map { |t| Theme.targets[t.to_sym] },
- name: ThemeField.scss_fields + ThemeField.html_fields)
+ return(
+ theme.theme_fields.where(
+ target_id: ThemeField.basic_targets.map { |t| Theme.targets[t.to_sym] },
+ name: ThemeField.scss_fields + ThemeField.html_fields,
+ )
+ )
end
ThemeField.none
end
@@ -561,7 +644,8 @@ class ThemeField < ActiveRecord::Base
end
before_save do
- if (will_save_change_to_value? || will_save_change_to_upload_id?) && !will_save_change_to_value_baked?
+ if (will_save_change_to_value? || will_save_change_to_upload_id?) &&
+ !will_save_change_to_value_baked?
self.value_baked = nil
end
if upload && upload.extension == "js"
@@ -572,29 +656,19 @@ class ThemeField < ActiveRecord::Base
end
end
- after_save do
- dependent_fields.each(&:invalidate_baked!)
- end
+ after_save { dependent_fields.each(&:invalidate_baked!) }
- after_destroy do
- if svg_sprite_field?
- DB.after_commit { SvgSprite.expire_cache }
- end
- end
+ after_destroy { DB.after_commit { SvgSprite.expire_cache } if svg_sprite_field? }
private
- JAVASCRIPT_TYPES = %w(
- text/javascript
- application/javascript
- application/ecmascript
- )
+ JAVASCRIPT_TYPES = %w[text/javascript application/javascript application/ecmascript]
def inline_javascript?(node)
- if node['src'].present?
+ if node["src"].present?
false
- elsif node['type'].present?
- JAVASCRIPT_TYPES.include?(node['type'].downcase)
+ elsif node["type"].present?
+ JAVASCRIPT_TYPES.include?(node["type"].downcase)
else
true
end
diff --git a/app/models/theme_modifier_set.rb b/app/models/theme_modifier_set.rb
index 781ea42f51f..1d1c8e59f2b 100644
--- a/app/models/theme_modifier_set.rb
+++ b/app/models/theme_modifier_set.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class ThemeModifierSet < ActiveRecord::Base
- class ThemeModifierSetError < StandardError; end
+ class ThemeModifierSetError < StandardError
+ end
belongs_to :theme
@@ -26,12 +27,8 @@ class ThemeModifierSet < ActiveRecord::Base
end
after_save do
- if saved_change_to_svg_icons?
- SvgSprite.expire_cache
- end
- if saved_change_to_csp_extensions?
- CSP::Extension.clear_theme_extensions_cache!
- end
+ SvgSprite.expire_cache if saved_change_to_svg_icons?
+ CSP::Extension.clear_theme_extensions_cache! if saved_change_to_csp_extensions?
end
# Given the ids of multiple active themes / theme components, this function
@@ -39,7 +36,11 @@ class ThemeModifierSet < ActiveRecord::Base
def self.resolve_modifier_for_themes(theme_ids, modifier_name)
return nil if !(config = self.modifiers[modifier_name])
- all_values = self.where(theme_id: theme_ids).where.not(modifier_name => nil).map { |s| s.public_send(modifier_name) }
+ all_values =
+ self
+ .where(theme_id: theme_ids)
+ .where.not(modifier_name => nil)
+ .map { |s| s.public_send(modifier_name) }
case config[:type]
when :boolean
all_values.any?
@@ -55,17 +56,21 @@ class ThemeModifierSet < ActiveRecord::Base
return if array.nil?
- array.map do |dimension|
- parts = dimension.split("x")
- next if parts.length != 2
- [parts[0].to_i, parts[1].to_i]
- end.filter(&:present?)
+ array
+ .map do |dimension|
+ parts = dimension.split("x")
+ next if parts.length != 2
+ [parts[0].to_i, parts[1].to_i]
+ end
+ .filter(&:present?)
end
def topic_thumbnail_sizes=(val)
return write_attribute(:topic_thumbnail_sizes, val) if val.nil?
return write_attribute(:topic_thumbnail_sizes, val) if !val.is_a?(Array)
- return write_attribute(:topic_thumbnail_sizes, val) if !val.all? { |v| v.is_a?(Array) && v.length == 2 }
+ if !val.all? { |v| v.is_a?(Array) && v.length == 2 }
+ return write_attribute(:topic_thumbnail_sizes, val)
+ end
super(val.map { |dim| "#{dim[0]}x#{dim[1]}" })
end
@@ -77,7 +82,7 @@ class ThemeModifierSet < ActiveRecord::Base
def self.load_modifiers
hash = {}
columns_hash.each do |column_name, info|
- next if ["id", "theme_id"].include?(column_name)
+ next if %w[id theme_id].include?(column_name)
type = nil
if info.type == :string && info.array?
@@ -85,7 +90,9 @@ class ThemeModifierSet < ActiveRecord::Base
elsif info.type == :boolean && !info.array?
type = :boolean
else
- raise ThemeModifierSetError "Invalid theme modifier column type" if ![:boolean, :string].include?(info.type)
+ if !%i[boolean string].include?(info.type)
+ raise ThemeModifierSetError "Invalid theme modifier column type"
+ end
end
hash[column_name.to_sym] = { type: type }
diff --git a/app/models/top_menu_item.rb b/app/models/top_menu_item.rb
index fad4c9b1ad1..8334f73104f 100644
--- a/app/models/top_menu_item.rb
+++ b/app/models/top_menu_item.rb
@@ -26,7 +26,7 @@
# item.specific_category # => "hardware"
class TopMenuItem
def initialize(value)
- parts = value.split(',')
+ parts = value.split(",")
@name = parts[0]
@filter = initialize_filter(parts[1])
end
@@ -38,18 +38,18 @@ class TopMenuItem
end
def has_specific_category?
- name.split('/')[0] == 'category'
+ name.split("/")[0] == "category"
end
def specific_category
- name.split('/')[1]
+ name.split("/")[1]
end
private
def initialize_filter(value)
if value
- if value.start_with?('-')
+ if value.start_with?("-")
value[1..-1] # all but the leading -
else
Rails.logger.warn "WARNING: found top_menu_item with invalid filter, ignoring '#{value}'..."
diff --git a/app/models/top_topic.rb b/app/models/top_topic.rb
index 3f09fda10e7..975adc8ec72 100644
--- a/app/models/top_topic.rb
+++ b/app/models/top_topic.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class TopTopic < ActiveRecord::Base
-
belongs_to :topic
# The top topics we want to refresh often
@@ -16,13 +15,9 @@ class TopTopic < ActiveRecord::Base
# We don't have to refresh these as often
def self.refresh_older!
- older_periods = periods - [:daily, :all]
+ older_periods = periods - %i[daily all]
- transaction do
- older_periods.each do |period|
- update_counts_and_compute_scores_for(period)
- end
- end
+ transaction { older_periods.each { |period| update_counts_and_compute_scores_for(period) } }
compute_top_score_for(:all)
end
@@ -33,16 +28,11 @@ class TopTopic < ActiveRecord::Base
end
def self.periods
- @@periods ||= [:all, :yearly, :quarterly, :monthly, :weekly, :daily].freeze
+ @@periods ||= %i[all yearly quarterly monthly weekly daily].freeze
end
def self.sorted_periods
- ascending_periods ||= Enum.new(daily: 1,
- weekly: 2,
- monthly: 3,
- quarterly: 4,
- yearly: 5,
- all: 6)
+ ascending_periods ||= Enum.new(daily: 1, weekly: 2, monthly: 3, quarterly: 4, yearly: 5, all: 6)
end
def self.score_column_for_period(period)
@@ -52,25 +42,26 @@ class TopTopic < ActiveRecord::Base
def self.validate_period(period)
if period.blank? || !periods.include?(period.to_sym)
- raise Discourse::InvalidParameters.new("Invalid period. Valid periods are #{periods.join(", ")}")
+ raise Discourse::InvalidParameters.new(
+ "Invalid period. Valid periods are #{periods.join(", ")}",
+ )
end
end
private
def self.sort_orders
- @@sort_orders ||= [:posts, :views, :likes, :op_likes].freeze
+ @@sort_orders ||= %i[posts views likes op_likes].freeze
end
def self.update_counts_and_compute_scores_for(period)
- sort_orders.each do |sort|
- TopTopic.public_send("update_#{sort}_count_for", period)
- end
+ sort_orders.each { |sort| TopTopic.public_send("update_#{sort}_count_for", period) }
compute_top_score_for(period)
end
def self.remove_invisible_topics
- DB.exec("WITH category_definition_topic_ids AS (
+ DB.exec(
+ "WITH category_definition_topic_ids AS (
SELECT COALESCE(topic_id, 0) AS id FROM categories
), invisible_topic_ids AS (
SELECT id
@@ -83,11 +74,13 @@ class TopTopic < ActiveRecord::Base
)
DELETE FROM top_topics
WHERE topic_id IN (SELECT id FROM invisible_topic_ids)",
- private_message: Archetype::private_message)
+ private_message: Archetype.private_message,
+ )
end
def self.add_new_visible_topics
- DB.exec("WITH category_definition_topic_ids AS (
+ DB.exec(
+ "WITH category_definition_topic_ids AS (
SELECT COALESCE(topic_id, 0) AS id FROM categories
), visible_topics AS (
SELECT t.id
@@ -102,11 +95,13 @@ class TopTopic < ActiveRecord::Base
)
INSERT INTO top_topics (topic_id)
SELECT id FROM visible_topics",
- private_message: Archetype::private_message)
+ private_message: Archetype.private_message,
+ )
end
def self.update_posts_count_for(period)
- sql = "SELECT topic_id, GREATEST(COUNT(*), 1) AS count
+ sql =
+ "SELECT topic_id, GREATEST(COUNT(*), 1) AS count
FROM posts
WHERE created_at >= :from
AND deleted_at IS NULL
@@ -119,7 +114,8 @@ class TopTopic < ActiveRecord::Base
end
def self.update_views_count_for(period)
- sql = "SELECT topic_id, COUNT(*) AS count
+ sql =
+ "SELECT topic_id, COUNT(*) AS count
FROM topic_views
WHERE viewed_at >= :from
GROUP BY topic_id"
@@ -128,7 +124,8 @@ class TopTopic < ActiveRecord::Base
end
def self.update_likes_count_for(period)
- sql = "SELECT topic_id, SUM(like_count) AS count
+ sql =
+ "SELECT topic_id, SUM(like_count) AS count
FROM posts
WHERE created_at >= :from
AND deleted_at IS NULL
@@ -140,7 +137,8 @@ class TopTopic < ActiveRecord::Base
end
def self.update_op_likes_count_for(period)
- sql = "SELECT topic_id, like_count AS count
+ sql =
+ "SELECT topic_id, like_count AS count
FROM posts
WHERE created_at >= :from
AND post_number = 1
@@ -152,18 +150,19 @@ class TopTopic < ActiveRecord::Base
end
def self.compute_top_score_for(period)
-
log_views_multiplier = SiteSetting.top_topics_formula_log_views_multiplier.to_f
log_views_multiplier = 2 if log_views_multiplier == 0
first_post_likes_multiplier = SiteSetting.top_topics_formula_first_post_likes_multiplier.to_f
first_post_likes_multiplier = 0.5 if first_post_likes_multiplier == 0
- least_likes_per_post_multiplier = SiteSetting.top_topics_formula_least_likes_per_post_multiplier.to_f
+ least_likes_per_post_multiplier =
+ SiteSetting.top_topics_formula_least_likes_per_post_multiplier.to_f
least_likes_per_post_multiplier = 3 if least_likes_per_post_multiplier == 0
if period == :all
- top_topics = "(
+ top_topics =
+ "(
SELECT t.like_count all_likes_count,
t.id topic_id,
t.posts_count all_posts_count,
@@ -213,22 +212,29 @@ class TopTopic < ActiveRecord::Base
def self.start_of(period)
case period
- when :yearly then 1.year.ago
- when :monthly then 1.month.ago
- when :quarterly then 3.months.ago
- when :weekly then 1.week.ago
- when :daily then 1.day.ago
+ when :yearly
+ 1.year.ago
+ when :monthly
+ 1.month.ago
+ when :quarterly
+ 3.months.ago
+ when :weekly
+ 1.week.ago
+ when :daily
+ 1.day.ago
end
end
def self.update_top_topics(period, sort, inner_join)
- DB.exec("UPDATE top_topics
+ DB.exec(
+ "UPDATE top_topics
SET #{period}_#{sort}_count = c.count
FROM top_topics tt
INNER JOIN (#{inner_join}) c ON tt.topic_id = c.topic_id
WHERE tt.topic_id = top_topics.topic_id
AND tt.#{period}_#{sort}_count <> c.count",
- from: start_of(period))
+ from: start_of(period),
+ )
end
end
diff --git a/app/models/topic.rb b/app/models/topic.rb
index 8c407873e16..b15bbc519f6 100644
--- a/app/models/topic.rb
+++ b/app/models/topic.rb
@@ -1,8 +1,10 @@
# frozen_string_literal: true
class Topic < ActiveRecord::Base
- class UserExists < StandardError; end
- class NotAllowed < StandardError; end
+ class UserExists < StandardError
+ end
+ class NotAllowed < StandardError
+ end
include RateLimiter::OnCreateRecord
include HasCustomFields
include Trashable
@@ -14,7 +16,7 @@ class Topic < ActiveRecord::Base
self.ignored_columns = [
"avg_time", # TODO(2021-01-04): remove
- "image_url" # TODO(2021-06-01): remove
+ "image_url", # TODO(2021-06-01): remove
]
def_delegator :featured_users, :user_ids, :featured_user_ids
@@ -37,7 +39,7 @@ class Topic < ActiveRecord::Base
end
def self.thumbnail_sizes
- [ self.share_thumbnail_size ] + DiscoursePluginRegistry.topic_thumbnail_sizes
+ [self.share_thumbnail_size] + DiscoursePluginRegistry.topic_thumbnail_sizes
end
def thumbnail_job_redis_key(sizes)
@@ -49,7 +51,9 @@ class Topic < ActiveRecord::Base
return nil unless original.read_attribute(:width) && original.read_attribute(:height)
thumbnail_sizes = Topic.thumbnail_sizes + extra_sizes
- topic_thumbnails.filter { |record| thumbnail_sizes.include?([record.max_width, record.max_height]) }
+ topic_thumbnails.filter do |record|
+ thumbnail_sizes.include?([record.max_width, record.max_height])
+ end
end
def thumbnail_info(enqueue_if_missing: false, extra_sizes: [])
@@ -59,12 +63,12 @@ class Topic < ActiveRecord::Base
infos = []
infos << { # Always add original
- max_width: nil,
- max_height: nil,
- width: original.width,
- height: original.height,
- url: original.url
- }
+ max_width: nil,
+ max_height: nil,
+ width: original.width,
+ height: original.height,
+ url: original.url,
+ }
records = filtered_topic_thumbnails(extra_sizes: extra_sizes)
@@ -76,15 +80,14 @@ class Topic < ActiveRecord::Base
max_height: record.max_height,
width: record.optimized_image&.width,
height: record.optimized_image&.height,
- url: record.optimized_image&.url
+ url: record.optimized_image&.url,
}
end
thumbnail_sizes = Topic.thumbnail_sizes + extra_sizes
- if SiteSetting.create_thumbnails &&
- enqueue_if_missing &&
- records.length < thumbnail_sizes.length &&
- Discourse.redis.set(thumbnail_job_redis_key(extra_sizes), 1, nx: true, ex: 1.minute)
+ if SiteSetting.create_thumbnails && enqueue_if_missing &&
+ records.length < thumbnail_sizes.length &&
+ Discourse.redis.set(thumbnail_job_redis_key(extra_sizes), 1, nx: true, ex: 1.minute)
Jobs.enqueue(:generate_topic_thumbnails, { topic_id: id, extra_sizes: extra_sizes })
end
@@ -106,19 +109,17 @@ class Topic < ActiveRecord::Base
end
def image_url(enqueue_if_missing: false)
- thumbnail = topic_thumbnails.detect do |record|
- record.max_width == Topic.share_thumbnail_size[0] &&
- record.max_height == Topic.share_thumbnail_size[1]
- end
+ thumbnail =
+ topic_thumbnails.detect do |record|
+ record.max_width == Topic.share_thumbnail_size[0] &&
+ record.max_height == Topic.share_thumbnail_size[1]
+ end
- if thumbnail.nil? &&
- image_upload &&
- SiteSetting.create_thumbnails &&
- image_upload.filesize < SiteSetting.max_image_size_kb.kilobytes &&
- image_upload.read_attribute(:width) &&
- image_upload.read_attribute(:height) &&
- enqueue_if_missing &&
- Discourse.redis.set(thumbnail_job_redis_key([]), 1, nx: true, ex: 1.minute)
+ if thumbnail.nil? && image_upload && SiteSetting.create_thumbnails &&
+ image_upload.filesize < SiteSetting.max_image_size_kb.kilobytes &&
+ image_upload.read_attribute(:width) && image_upload.read_attribute(:height) &&
+ enqueue_if_missing &&
+ Discourse.redis.set(thumbnail_job_redis_key([]), 1, nx: true, ex: 1.minute)
Jobs.enqueue(:generate_topic_thumbnails, { topic_id: id })
end
@@ -169,34 +170,42 @@ class Topic < ActiveRecord::Base
rate_limit :limit_topics_per_day
rate_limit :limit_private_messages_per_day
- validates :title, if: Proc.new { |t| t.new_record? || t.title_changed? },
- presence: true,
- topic_title_length: true,
- censored_words: true,
- watched_words: true,
- quality_title: { unless: :private_message? },
- max_emojis: true,
- unique_among: { unless: Proc.new { |t| (SiteSetting.allow_duplicate_topic_titles? || t.private_message?) },
- message: :has_already_been_used,
- allow_blank: true,
- case_sensitive: false,
- collection: Proc.new { |t|
- SiteSetting.allow_duplicate_topic_titles_category? ?
- Topic.listable_topics.where("category_id = ?", t.category_id) :
- Topic.listable_topics
- }
- }
+ validates :title,
+ if: Proc.new { |t| t.new_record? || t.title_changed? },
+ presence: true,
+ topic_title_length: true,
+ censored_words: true,
+ watched_words: true,
+ quality_title: {
+ unless: :private_message?,
+ },
+ max_emojis: true,
+ unique_among: {
+ unless:
+ Proc.new { |t| (SiteSetting.allow_duplicate_topic_titles? || t.private_message?) },
+ message: :has_already_been_used,
+ allow_blank: true,
+ case_sensitive: false,
+ collection:
+ Proc.new { |t|
+ if SiteSetting.allow_duplicate_topic_titles_category?
+ Topic.listable_topics.where("category_id = ?", t.category_id)
+ else
+ Topic.listable_topics
+ end
+ },
+ }
validates :category_id,
presence: true,
exclusion: {
- in: Proc.new { [SiteSetting.uncategorized_category_id] }
+ in: Proc.new { [SiteSetting.uncategorized_category_id] },
},
- if: Proc.new { |t|
- (t.new_record? || t.category_id_changed?) &&
- !SiteSetting.allow_uncategorized_topics &&
- (t.archetype.nil? || t.regular?)
- }
+ if:
+ Proc.new { |t|
+ (t.new_record? || t.category_id_changed?) &&
+ !SiteSetting.allow_uncategorized_topics && (t.archetype.nil? || t.regular?)
+ }
validates :featured_link, allow_nil: true, url: true
validate if: :featured_link do
@@ -205,10 +214,22 @@ class Topic < ActiveRecord::Base
end
end
- validates :external_id, allow_nil: true, uniqueness: { case_sensitive: false }, length: { maximum: EXTERNAL_ID_MAX_LENGTH }, format: { with: /\A[\w-]+\z/ }
+ validates :external_id,
+ allow_nil: true,
+ uniqueness: {
+ case_sensitive: false,
+ },
+ length: {
+ maximum: EXTERNAL_ID_MAX_LENGTH,
+ },
+ format: {
+ with: /\A[\w-]+\z/,
+ }
before_validation do
- self.title = TextCleaner.clean_title(TextSentinel.title_sentinel(title).text) if errors[:title].empty?
+ self.title = TextCleaner.clean_title(TextSentinel.title_sentinel(title).text) if errors[
+ :title
+ ].empty?
self.featured_link = self.featured_link.strip.presence if self.featured_link
end
@@ -241,11 +262,11 @@ class Topic < ActiveRecord::Base
has_one :published_page
belongs_to :user
- belongs_to :last_poster, class_name: 'User', foreign_key: :last_post_user_id
- belongs_to :featured_user1, class_name: 'User', foreign_key: :featured_user1_id
- belongs_to :featured_user2, class_name: 'User', foreign_key: :featured_user2_id
- belongs_to :featured_user3, class_name: 'User', foreign_key: :featured_user3_id
- belongs_to :featured_user4, class_name: 'User', foreign_key: :featured_user4_id
+ belongs_to :last_poster, class_name: "User", foreign_key: :last_post_user_id
+ belongs_to :featured_user1, class_name: "User", foreign_key: :featured_user1_id
+ belongs_to :featured_user2, class_name: "User", foreign_key: :featured_user2_id
+ belongs_to :featured_user3, class_name: "User", foreign_key: :featured_user3_id
+ belongs_to :featured_user4, class_name: "User", foreign_key: :featured_user4_id
has_many :topic_users
has_many :dismissed_topic_users
@@ -257,12 +278,12 @@ class Topic < ActiveRecord::Base
has_many :user_profiles
has_one :user_warning
- has_one :first_post, -> { where post_number: 1 }, class_name: 'Post'
+ has_one :first_post, -> { where post_number: 1 }, class_name: "Post"
has_one :topic_search_data
has_one :topic_embed, dependent: :destroy
has_one :linked_topic, dependent: :destroy
- belongs_to :image_upload, class_name: 'Upload'
+ belongs_to :image_upload, class_name: "Upload"
has_many :topic_thumbnails, through: :image_upload
# When we want to temporarily attach some data to a forum topic (usually before serialization)
@@ -270,7 +291,7 @@ class Topic < ActiveRecord::Base
attr_accessor :category_user_data
attr_accessor :dismissed
- attr_accessor :posters # TODO: can replace with posters_summary once we remove old list code
+ attr_accessor :posters # TODO: can replace with posters_summary once we remove old list code
attr_accessor :participants
attr_accessor :topic_list
attr_accessor :meta_data
@@ -278,7 +299,7 @@ class Topic < ActiveRecord::Base
attr_accessor :import_mode # set to true to optimize creation and save for imports
# The regular order
- scope :topic_list_order, -> { order('topics.bumped_at desc') }
+ scope :topic_list_order, -> { order("topics.bumped_at desc") }
# Return private message topics
scope :private_messages, -> { where(archetype: Archetype.private_message) }
@@ -295,50 +316,57 @@ class Topic < ActiveRecord::Base
JOIN group_users gu ON gu.user_id = :user_id AND gu.group_id = tg.group_id
SQL
- scope :private_messages_for_user, ->(user) do
- private_messages.where(
- "topics.id IN (#{PRIVATE_MESSAGES_SQL_USER})
+ scope :private_messages_for_user,
+ ->(user) {
+ private_messages.where(
+ "topics.id IN (#{PRIVATE_MESSAGES_SQL_USER})
OR topics.id IN (#{PRIVATE_MESSAGES_SQL_GROUP})",
- user_id: user.id
- )
- end
+ user_id: user.id,
+ )
+ }
- scope :listable_topics, -> { where('topics.archetype <> ?', Archetype.private_message) }
+ scope :listable_topics, -> { where("topics.archetype <> ?", Archetype.private_message) }
- scope :by_newest, -> { order('topics.created_at desc, topics.id desc') }
+ scope :by_newest, -> { order("topics.created_at desc, topics.id desc") }
scope :visible, -> { where(visible: true) }
- scope :created_since, lambda { |time_ago| where('topics.created_at > ?', time_ago) }
+ scope :created_since, lambda { |time_ago| where("topics.created_at > ?", time_ago) }
scope :exclude_scheduled_bump_topics, -> { where.not(id: TopicTimer.scheduled_bump_topics) }
- scope :secured, lambda { |guardian = nil|
- ids = guardian.secure_category_ids if guardian
+ scope :secured,
+ lambda { |guardian = nil|
+ ids = guardian.secure_category_ids if guardian
- # Query conditions
- condition = if ids.present?
- ["NOT read_restricted OR id IN (:cats)", cats: ids]
- else
- ["NOT read_restricted"]
- end
+ # Query conditions
+ condition =
+ if ids.present?
+ ["NOT read_restricted OR id IN (:cats)", cats: ids]
+ else
+ ["NOT read_restricted"]
+ end
- where("topics.category_id IS NULL OR topics.category_id IN (SELECT id FROM categories WHERE #{condition[0]})", condition[1])
- }
+ where(
+ "topics.category_id IS NULL OR topics.category_id IN (SELECT id FROM categories WHERE #{condition[0]})",
+ condition[1],
+ )
+ }
- scope :in_category_and_subcategories, lambda { |category_id|
- where("topics.category_id IN (?)", Category.subcategory_ids(category_id.to_i)) if category_id
- }
+ scope :in_category_and_subcategories,
+ lambda { |category_id|
+ if category_id
+ where("topics.category_id IN (?)", Category.subcategory_ids(category_id.to_i))
+ end
+ }
- scope :with_subtype, ->(subtype) { where('topics.subtype = ?', subtype) }
+ scope :with_subtype, ->(subtype) { where("topics.subtype = ?", subtype) }
attr_accessor :ignore_category_auto_close
attr_accessor :skip_callbacks
attr_accessor :advance_draft
- before_create do
- initialize_default_values
- end
+ before_create { initialize_default_values }
after_create do
unless skip_callbacks
@@ -348,13 +376,9 @@ class Topic < ActiveRecord::Base
end
before_save do
- unless skip_callbacks
- ensure_topic_has_a_category
- end
+ ensure_topic_has_a_category unless skip_callbacks
- if title_changed?
- write_attribute(:fancy_title, Topic.fancy_title(title))
- end
+ write_attribute(:fancy_title, Topic.fancy_title(title)) if title_changed?
if category_id_changed? || new_record?
inherit_auto_close_from_category
@@ -369,7 +393,8 @@ class Topic < ActiveRecord::Base
ApplicationController.banner_json_cache.clear
end
- if tags_changed || saved_change_to_attribute?(:category_id) || saved_change_to_attribute?(:title)
+ if tags_changed || saved_change_to_attribute?(:category_id) ||
+ saved_change_to_attribute?(:title)
SearchIndexer.queue_post_reindex(self.id)
if tags_changed
@@ -418,11 +443,11 @@ class Topic < ActiveRecord::Base
end
def self.top_viewed(max = 10)
- Topic.listable_topics.visible.secured.order('views desc').limit(max)
+ Topic.listable_topics.visible.secured.order("views desc").limit(max)
end
def self.recent(max = 10)
- Topic.listable_topics.visible.secured.order('created_at desc').limit(max)
+ Topic.listable_topics.visible.secured.order("created_at desc").limit(max)
end
def self.count_exceeds_minimum?
@@ -430,7 +455,11 @@ class Topic < ActiveRecord::Base
end
def best_post
- posts.where(post_type: Post.types[:regular], user_deleted: false).order('score desc nulls last').limit(1).first
+ posts
+ .where(post_type: Post.types[:regular], user_deleted: false)
+ .order("score desc nulls last")
+ .limit(1)
+ .first
end
def self.has_flag_scope
@@ -447,8 +476,11 @@ class Topic < ActiveRecord::Base
# all users (in groups or directly targeted) that are going to get the pm
def all_allowed_users
- moderators_sql = " UNION #{User.moderators.to_sql}" if private_message? && (has_flags? || is_official_warning?)
- User.from("(#{allowed_users.to_sql} UNION #{allowed_group_users.to_sql}#{moderators_sql}) as users")
+ moderators_sql = " UNION #{User.moderators.to_sql}" if private_message? &&
+ (has_flags? || is_official_warning?)
+ User.from(
+ "(#{allowed_users.to_sql} UNION #{allowed_group_users.to_sql}#{moderators_sql}) as users",
+ )
end
# Additional rate limits on topics: per day and private messages per day
@@ -482,7 +514,11 @@ class Topic < ActiveRecord::Base
if !new_record? && !Discourse.readonly_mode?
# make sure data is set in table, this also allows us to change algorithm
# by simply nulling this column
- DB.exec("UPDATE topics SET fancy_title = :fancy_title where id = :id", id: self.id, fancy_title: fancy_title)
+ DB.exec(
+ "UPDATE topics SET fancy_title = :fancy_title where id = :id",
+ id: self.id,
+ fancy_title: fancy_title,
+ )
end
end
@@ -494,25 +530,34 @@ class Topic < ActiveRecord::Base
opts = opts || {}
period = ListController.best_period_for(since)
- topics = Topic
- .visible
- .secured(Guardian.new(user))
- .joins("LEFT OUTER JOIN topic_users ON topic_users.topic_id = topics.id AND topic_users.user_id = #{user.id.to_i}")
- .joins("LEFT OUTER JOIN category_users ON category_users.category_id = topics.category_id AND category_users.user_id = #{user.id.to_i}")
- .joins("LEFT OUTER JOIN users ON users.id = topics.user_id")
- .where(closed: false, archived: false)
- .where("COALESCE(topic_users.notification_level, 1) <> ?", TopicUser.notification_levels[:muted])
- .created_since(since)
- .where('topics.created_at < ?', (SiteSetting.editing_grace_period || 0).seconds.ago)
- .listable_topics
- .includes(:category)
+ topics =
+ Topic
+ .visible
+ .secured(Guardian.new(user))
+ .joins(
+ "LEFT OUTER JOIN topic_users ON topic_users.topic_id = topics.id AND topic_users.user_id = #{user.id.to_i}",
+ )
+ .joins(
+ "LEFT OUTER JOIN category_users ON category_users.category_id = topics.category_id AND category_users.user_id = #{user.id.to_i}",
+ )
+ .joins("LEFT OUTER JOIN users ON users.id = topics.user_id")
+ .where(closed: false, archived: false)
+ .where(
+ "COALESCE(topic_users.notification_level, 1) <> ?",
+ TopicUser.notification_levels[:muted],
+ )
+ .created_since(since)
+ .where("topics.created_at < ?", (SiteSetting.editing_grace_period || 0).seconds.ago)
+ .listable_topics
+ .includes(:category)
unless opts[:include_tl0] || user.user_option.try(:include_tl0_in_digests)
topics = topics.where("COALESCE(users.trust_level, 0) > 0")
end
if !!opts[:top_order]
- topics = topics.joins("LEFT OUTER JOIN top_topics ON top_topics.topic_id = topics.id").order(<<~SQL)
+ topics =
+ topics.joins("LEFT OUTER JOIN top_topics ON top_topics.topic_id = topics.id").order(<<~SQL)
COALESCE(topic_users.notification_level, 1) DESC,
COALESCE(category_users.notification_level, 1) DESC,
COALESCE(top_topics.#{TopTopic.score_column_for_period(period)}, 0) DESC,
@@ -520,27 +565,34 @@ class Topic < ActiveRecord::Base
SQL
end
- if opts[:limit]
- topics = topics.limit(opts[:limit])
- end
+ topics = topics.limit(opts[:limit]) if opts[:limit]
# Remove category topics
category_topic_ids = Category.pluck(:topic_id).compact!
- if category_topic_ids.present?
- topics = topics.where("topics.id NOT IN (?)", category_topic_ids)
- end
+ topics = topics.where("topics.id NOT IN (?)", category_topic_ids) if category_topic_ids.present?
# Remove muted and shared draft categories
- remove_category_ids = CategoryUser.where(user_id: user.id, notification_level: CategoryUser.notification_levels[:muted]).pluck(:category_id)
+ remove_category_ids =
+ CategoryUser.where(
+ user_id: user.id,
+ notification_level: CategoryUser.notification_levels[:muted],
+ ).pluck(:category_id)
if SiteSetting.digest_suppress_categories.present?
- topics = topics.where("topics.category_id NOT IN (?)", SiteSetting.digest_suppress_categories.split("|").map(&:to_i))
- end
- if SiteSetting.shared_drafts_enabled?
- remove_category_ids << SiteSetting.shared_drafts_category
+ topics =
+ topics.where(
+ "topics.category_id NOT IN (?)",
+ SiteSetting.digest_suppress_categories.split("|").map(&:to_i),
+ )
end
+ remove_category_ids << SiteSetting.shared_drafts_category if SiteSetting.shared_drafts_enabled?
if remove_category_ids.present?
remove_category_ids.uniq!
- topics = topics.where("topic_users.notification_level != ? OR topics.category_id NOT IN (?)", TopicUser.notification_levels[:muted], remove_category_ids)
+ topics =
+ topics.where(
+ "topic_users.notification_level != ? OR topics.category_id NOT IN (?)",
+ TopicUser.notification_levels[:muted],
+ remove_category_ids,
+ )
end
# Remove muted tags
@@ -548,9 +600,12 @@ class Topic < ActiveRecord::Base
unless muted_tag_ids.empty?
# If multiple tags per topic, include topics with tags that aren't muted,
# and don't forget untagged topics.
- topics = topics.where(
- "EXISTS ( SELECT 1 FROM topic_tags WHERE topic_tags.topic_id = topics.id AND tag_id NOT IN (?) )
- OR NOT EXISTS (SELECT 1 FROM topic_tags WHERE topic_tags.topic_id = topics.id)", muted_tag_ids)
+ topics =
+ topics.where(
+ "EXISTS ( SELECT 1 FROM topic_tags WHERE topic_tags.topic_id = topics.id AND tag_id NOT IN (?) )
+ OR NOT EXISTS (SELECT 1 FROM topic_tags WHERE topic_tags.topic_id = topics.id)",
+ muted_tag_ids,
+ )
end
topics
@@ -585,10 +640,23 @@ class Topic < ActiveRecord::Base
((Time.zone.now - created_at) / 1.minute).round
end
- def self.listable_count_per_day(start_date, end_date, category_id = nil, include_subcategories = false)
- result = listable_topics.where("topics.created_at >= ? AND topics.created_at <= ?", start_date, end_date)
- result = result.group('date(topics.created_at)').order('date(topics.created_at)')
- result = result.where(category_id: include_subcategories ? Category.subcategory_ids(category_id) : category_id) if category_id
+ def self.listable_count_per_day(
+ start_date,
+ end_date,
+ category_id = nil,
+ include_subcategories = false
+ )
+ result =
+ listable_topics.where(
+ "topics.created_at >= ? AND topics.created_at <= ?",
+ start_date,
+ end_date,
+ )
+ result = result.group("date(topics.created_at)").order("date(topics.created_at)")
+ result =
+ result.where(
+ category_id: include_subcategories ? Category.subcategory_ids(category_id) : category_id,
+ ) if category_id
result.count
end
@@ -613,20 +681,16 @@ class Topic < ActiveRecord::Base
return [] if search_data.blank?
- tsquery = Search.set_tsquery_weight_filter(search_data, 'A')
+ tsquery = Search.set_tsquery_weight_filter(search_data, "A")
if raw.present?
- cooked = SearchIndexer::HtmlScrubber.scrub(
- PrettyText.cook(raw[0...MAX_SIMILAR_BODY_LENGTH].strip)
- )
+ cooked =
+ SearchIndexer::HtmlScrubber.scrub(PrettyText.cook(raw[0...MAX_SIMILAR_BODY_LENGTH].strip))
prepared_data = cooked.present? && Search.prepare_data(cooked)
if prepared_data.present?
- raw_tsquery = Search.set_tsquery_weight_filter(
- prepared_data,
- 'B'
- )
+ raw_tsquery = Search.set_tsquery_weight_filter(prepared_data, "B")
tsquery = "#{tsquery} & #{raw_tsquery}"
end
@@ -636,46 +700,62 @@ class Topic < ActiveRecord::Base
guardian = Guardian.new(user)
- excluded_category_ids_sql = Category.secured(guardian).where(search_priority: Searchable::PRIORITIES[:ignore]).select(:id).to_sql
+ excluded_category_ids_sql =
+ Category
+ .secured(guardian)
+ .where(search_priority: Searchable::PRIORITIES[:ignore])
+ .select(:id)
+ .to_sql
- if user
- excluded_category_ids_sql = <<~SQL
+ excluded_category_ids_sql = <<~SQL if user
#{excluded_category_ids_sql}
UNION
#{CategoryUser.muted_category_ids_query(user, include_direct: true).select("categories.id").to_sql}
SQL
- end
- candidates = Topic
- .visible
- .listable_topics
- .secured(guardian)
- .joins("JOIN topic_search_data s ON topics.id = s.topic_id")
- .joins("LEFT JOIN categories c ON topics.id = c.topic_id")
- .where("search_data @@ #{tsquery}")
- .where("c.topic_id IS NULL")
- .where("topics.category_id NOT IN (#{excluded_category_ids_sql})")
- .order("ts_rank(search_data, #{tsquery}) DESC")
- .limit(SiteSetting.max_similar_results * 3)
+ candidates =
+ Topic
+ .visible
+ .listable_topics
+ .secured(guardian)
+ .joins("JOIN topic_search_data s ON topics.id = s.topic_id")
+ .joins("LEFT JOIN categories c ON topics.id = c.topic_id")
+ .where("search_data @@ #{tsquery}")
+ .where("c.topic_id IS NULL")
+ .where("topics.category_id NOT IN (#{excluded_category_ids_sql})")
+ .order("ts_rank(search_data, #{tsquery}) DESC")
+ .limit(SiteSetting.max_similar_results * 3)
candidate_ids = candidates.pluck(:id)
return [] if candidate_ids.blank?
- similars = Topic
- .joins("JOIN posts AS p ON p.topic_id = topics.id AND p.post_number = 1")
- .where("topics.id IN (?)", candidate_ids)
- .order("similarity DESC")
- .limit(SiteSetting.max_similar_results)
+ similars =
+ Topic
+ .joins("JOIN posts AS p ON p.topic_id = topics.id AND p.post_number = 1")
+ .where("topics.id IN (?)", candidate_ids)
+ .order("similarity DESC")
+ .limit(SiteSetting.max_similar_results)
if raw.present?
- similars
- .select(DB.sql_fragment("topics.*, similarity(topics.title, :title) + similarity(p.raw, :raw) AS similarity, p.cooked AS blurb", title: title, raw: raw))
- .where("similarity(topics.title, :title) + similarity(p.raw, :raw) > 0.2", title: title, raw: raw)
+ similars.select(
+ DB.sql_fragment(
+ "topics.*, similarity(topics.title, :title) + similarity(p.raw, :raw) AS similarity, p.cooked AS blurb",
+ title: title,
+ raw: raw,
+ ),
+ ).where(
+ "similarity(topics.title, :title) + similarity(p.raw, :raw) > 0.2",
+ title: title,
+ raw: raw,
+ )
else
- similars
- .select(DB.sql_fragment("topics.*, similarity(topics.title, :title) AS similarity, p.cooked AS blurb", title: title))
- .where("similarity(topics.title, :title) > 0.2", title: title)
+ similars.select(
+ DB.sql_fragment(
+ "topics.*, similarity(topics.title, :title) AS similarity, p.cooked AS blurb",
+ title: title,
+ ),
+ ).where("similarity(topics.title, :title) > 0.2", title: title)
end
end
@@ -683,30 +763,34 @@ class Topic < ActiveRecord::Base
TopicStatusUpdater.new(self, user).update!(status, enabled, opts)
DiscourseEvent.trigger(:topic_status_updated, self, status, enabled)
- if status == 'closed'
+ if status == "closed"
StaffActionLogger.new(user).log_topic_closed(self, closed: enabled)
- elsif status == 'archived'
+ elsif status == "archived"
StaffActionLogger.new(user).log_topic_archived(self, archived: enabled)
end
if enabled && private_message? && status.to_s["closed"]
group_ids = user.groups.pluck(:id)
if group_ids.present?
- allowed_group_ids = self.allowed_groups
- .where('topic_allowed_groups.group_id IN (?)', group_ids).pluck(:id)
- allowed_group_ids.each do |id|
- GroupArchivedMessage.archive!(id, self)
- end
+ allowed_group_ids =
+ self.allowed_groups.where("topic_allowed_groups.group_id IN (?)", group_ids).pluck(:id)
+ allowed_group_ids.each { |id| GroupArchivedMessage.archive!(id, self) }
end
end
end
# Atomically creates the next post number
def self.next_post_number(topic_id, opts = {})
- highest = DB.query_single("SELECT coalesce(max(post_number),0) AS max FROM posts WHERE topic_id = ?", topic_id).first.to_i
+ highest =
+ DB
+ .query_single(
+ "SELECT coalesce(max(post_number),0) AS max FROM posts WHERE topic_id = ?",
+ topic_id,
+ )
+ .first
+ .to_i
if opts[:whisper]
-
result = DB.query_single(<<~SQL, highest, topic_id)
UPDATE topics
SET highest_staff_post_number = ? + 1
@@ -715,11 +799,9 @@ class Topic < ActiveRecord::Base
SQL
result.first.to_i
-
else
-
reply_sql = opts[:reply] ? ", reply_count = reply_count + 1" : ""
- posts_sql = opts[:post] ? ", posts_count = posts_count + 1" : ""
+ posts_sql = opts[:post] ? ", posts_count = posts_count + 1" : ""
result = DB.query_single(<<~SQL, highest: highest, topic_id: topic_id)
UPDATE topics
@@ -814,7 +896,8 @@ class Topic < ActiveRecord::Base
archetype = Topic.where(id: topic_id).pluck_first(:archetype)
# ignore small_action replies for private messages
- post_type = archetype == Archetype.private_message ? " AND post_type <> #{Post.types[:small_action]}" : ''
+ post_type =
+ archetype == Archetype.private_message ? " AND post_type <> #{Post.types[:small_action]}" : ""
result = DB.query_single(<<~SQL, topic_id: topic_id)
UPDATE topics
@@ -875,7 +958,10 @@ class Topic < ActiveRecord::Base
def changed_to_category(new_category)
return true if new_category.blank? || Category.exists?(topic_id: id)
- return false if new_category.id == SiteSetting.uncategorized_category_id && !SiteSetting.allow_uncategorized_topics
+ if new_category.id == SiteSetting.uncategorized_category_id &&
+ !SiteSetting.allow_uncategorized_topics
+ return false
+ end
Topic.transaction do
old_category = category
@@ -884,9 +970,7 @@ class Topic < ActiveRecord::Base
self.update_attribute(:category_id, new_category.id)
if old_category
- Category
- .where(id: old_category.id)
- .update_all("topic_count = topic_count - 1")
+ Category.where(id: old_category.id).update_all("topic_count = topic_count - 1")
end
# when a topic changes category we may have to start watching it
@@ -897,7 +981,11 @@ class Topic < ActiveRecord::Base
if !SiteSetting.disable_category_edit_notifications && (post = self.ordered_posts.first)
notified_user_ids = [post.user_id, post.last_editor_id].uniq
DB.after_commit do
- Jobs.enqueue(:notify_category_change, post_id: post.id, notified_user_ids: notified_user_ids)
+ Jobs.enqueue(
+ :notify_category_change,
+ post_id: post.id,
+ notified_user_ids: notified_user_ids,
+ )
end
end
@@ -905,16 +993,16 @@ class Topic < ActiveRecord::Base
# linked to posts secure/not secure depending on whether the
# category is private. this is only done if the category
# has actually changed to avoid noise.
- DB.after_commit do
- Jobs.enqueue(:update_topic_upload_security, topic_id: self.id)
- end
+ DB.after_commit { Jobs.enqueue(:update_topic_upload_security, topic_id: self.id) }
end
Category.where(id: new_category.id).update_all("topic_count = topic_count + 1")
if Topic.update_featured_topics != false
CategoryFeaturedTopic.feature_topics_for(old_category) unless @import_mode
- CategoryFeaturedTopic.feature_topics_for(new_category) unless @import_mode || old_category.try(:id) == new_category.id
+ unless @import_mode || old_category.try(:id) == new_category.id
+ CategoryFeaturedTopic.feature_topics_for(new_category)
+ end
end
end
@@ -924,11 +1012,12 @@ class Topic < ActiveRecord::Base
def add_small_action(user, action_code, who = nil, opts = {})
custom_fields = {}
custom_fields["action_code_who"] = who if who.present?
- opts = opts.merge(
- post_type: Post.types[:small_action],
- action_code: action_code,
- custom_fields: custom_fields
- )
+ opts =
+ opts.merge(
+ post_type: Post.types[:small_action],
+ action_code: action_code,
+ custom_fields: custom_fields,
+ )
add_moderator_post(user, nil, opts)
end
@@ -936,22 +1025,27 @@ class Topic < ActiveRecord::Base
def add_moderator_post(user, text, opts = nil)
opts ||= {}
new_post = nil
- creator = PostCreator.new(user,
- raw: text,
- post_type: opts[:post_type] || Post.types[:moderator_action],
- action_code: opts[:action_code],
- no_bump: opts[:bump].blank?,
- topic_id: self.id,
- silent: opts[:silent],
- skip_validations: true,
- custom_fields: opts[:custom_fields],
- import_mode: opts[:import_mode])
+ creator =
+ PostCreator.new(
+ user,
+ raw: text,
+ post_type: opts[:post_type] || Post.types[:moderator_action],
+ action_code: opts[:action_code],
+ no_bump: opts[:bump].blank?,
+ topic_id: self.id,
+ silent: opts[:silent],
+ skip_validations: true,
+ custom_fields: opts[:custom_fields],
+ import_mode: opts[:import_mode],
+ )
if (new_post = creator.create) && new_post.present?
increment!(:moderator_posts_count) if new_post.persisted?
# If we are moving posts, we want to insert the moderator post where the previous posts were
# in the stream, not at the end.
- new_post.update!(post_number: opts[:post_number], sort_order: opts[:post_number]) if opts[:post_number].present?
+ if opts[:post_number].present?
+ new_post.update!(post_number: opts[:post_number], sort_order: opts[:post_number])
+ end
# Grab any links that are present
TopicLink.extract_from(new_post)
@@ -1016,14 +1110,16 @@ class Topic < ActiveRecord::Base
def reached_recipients_limit?
return false unless private_message?
- topic_allowed_users.count + topic_allowed_groups.count >= SiteSetting.max_allowed_message_recipients
+ topic_allowed_users.count + topic_allowed_groups.count >=
+ SiteSetting.max_allowed_message_recipients
end
def invite_group(user, group)
TopicAllowedGroup.create!(topic_id: self.id, group_id: group.id)
self.allowed_groups.reload
- last_post = self.posts.order('post_number desc').where('not hidden AND posts.deleted_at IS NULL').first
+ last_post =
+ self.posts.order("post_number desc").where("not hidden AND posts.deleted_at IS NULL").first
if last_post
Jobs.enqueue(:post_alert, post_id: last_post.id)
add_small_action(user, "invited_group", group.name)
@@ -1045,12 +1141,14 @@ class Topic < ActiveRecord::Base
topic_allowed_users.user_id != :op_user_id
)
SQL
- User.where([
- allowed_user_where_clause,
- { group_id: group.id, topic_id: self.id, op_user_id: self.user_id }
- ]).find_each do |allowed_user|
- remove_allowed_user(Discourse.system_user, allowed_user)
- end
+ User
+ .where(
+ [
+ allowed_user_where_clause,
+ { group_id: group.id, topic_id: self.id, op_user_id: self.user_id },
+ ],
+ )
+ .find_each { |allowed_user| remove_allowed_user(Discourse.system_user, allowed_user) }
true
end
@@ -1068,11 +1166,11 @@ class Topic < ActiveRecord::Base
raise NotAllowed.new(I18n.t("not_accepting_pms", username: target_user.username))
end
- if TopicUser
- .where(topic: self,
- user: target_user,
- notification_level: TopicUser.notification_levels[:muted])
- .exists?
+ if TopicUser.where(
+ topic: self,
+ user: target_user,
+ notification_level: TopicUser.notification_levels[:muted],
+ ).exists?
raise NotAllowed.new(I18n.t("topic_invite.muted_topic"))
end
@@ -1080,7 +1178,10 @@ class Topic < ActiveRecord::Base
raise NotAllowed.new(I18n.t("topic_invite.receiver_does_not_allow_pm"))
end
- if UserCommScreener.new(acting_user: target_user, target_user_ids: invited_by.id).disallowing_pms_from_actor?(invited_by.id)
+ if UserCommScreener.new(
+ acting_user: target_user,
+ target_user_ids: invited_by.id,
+ ).disallowing_pms_from_actor?(invited_by.id)
raise NotAllowed.new(I18n.t("topic_invite.sender_does_not_allow_pm"))
end
@@ -1090,12 +1191,13 @@ class Topic < ActiveRecord::Base
!!invite_to_topic(invited_by, target_user, group_ids, guardian)
end
elsif username_or_email =~ /^.+@.+$/ && guardian.can_invite_via_email?(self)
- !!Invite.generate(invited_by,
+ !!Invite.generate(
+ invited_by,
email: username_or_email,
topic: self,
group_ids: group_ids,
custom_message: custom_message,
- invite_to_topic: true
+ invite_to_topic: true,
)
end
end
@@ -1106,7 +1208,9 @@ class Topic < ActiveRecord::Base
def grant_permission_to_user(lower_email)
user = User.find_by_email(lower_email)
- topic_allowed_users.create!(user_id: user.id) unless topic_allowed_users.exists?(user_id: user.id)
+ unless topic_allowed_users.exists?(user_id: user.id)
+ topic_allowed_users.create!(user_id: user.id)
+ end
end
def max_post_number
@@ -1114,15 +1218,18 @@ class Topic < ActiveRecord::Base
end
def move_posts(moved_by, post_ids, opts)
- post_mover = PostMover.new(self, moved_by, post_ids, move_to_pm: opts[:archetype].present? && opts[:archetype] == "private_message")
+ post_mover =
+ PostMover.new(
+ self,
+ moved_by,
+ post_ids,
+ move_to_pm: opts[:archetype].present? && opts[:archetype] == "private_message",
+ )
if opts[:destination_topic_id]
topic = post_mover.to_topic(opts[:destination_topic_id], participants: opts[:participants])
- DiscourseEvent.trigger(:topic_merged,
- post_mover.original_topic,
- post_mover.destination_topic
- )
+ DiscourseEvent.trigger(:topic_merged, post_mover.original_topic, post_mover.destination_topic)
topic
elsif opts[:title]
@@ -1142,10 +1249,7 @@ class Topic < ActiveRecord::Base
def update_action_counts
update_column(
:like_count,
- Post
- .where.not(post_type: Post.types[:whisper])
- .where(topic_id: id)
- .sum(:like_count)
+ Post.where.not(post_type: Post.types[:whisper]).where(topic_id: id).sum(:like_count),
)
end
@@ -1159,26 +1263,26 @@ class Topic < ActiveRecord::Base
def make_banner!(user, bannered_until = nil)
if bannered_until
- bannered_until = begin
- Time.parse(bannered_until)
- rescue ArgumentError
- raise Discourse::InvalidParameters.new(:bannered_until)
- end
+ bannered_until =
+ begin
+ Time.parse(bannered_until)
+ rescue ArgumentError
+ raise Discourse::InvalidParameters.new(:bannered_until)
+ end
end
# only one banner at the same time
previous_banner = Topic.where(archetype: Archetype.banner).first
previous_banner.remove_banner!(user) if previous_banner.present?
- UserProfile.where("dismissed_banner_key IS NOT NULL")
- .update_all(dismissed_banner_key: nil)
+ UserProfile.where("dismissed_banner_key IS NOT NULL").update_all(dismissed_banner_key: nil)
self.archetype = Archetype.banner
self.bannered_until = bannered_until
self.add_small_action(user, "banner.enabled")
self.save
- MessageBus.publish('/site/banner', banner)
+ MessageBus.publish("/site/banner", banner)
Jobs.cancel_scheduled_job(:remove_banner, topic_id: self.id)
Jobs.enqueue_at(bannered_until, :remove_banner, topic_id: self.id) if bannered_until
@@ -1190,7 +1294,7 @@ class Topic < ActiveRecord::Base
self.add_small_action(user, "banner.disabled")
self.save
- MessageBus.publish('/site/banner', nil)
+ MessageBus.publish("/site/banner", nil)
Jobs.cancel_scheduled_job(:remove_banner, topic_id: self.id)
end
@@ -1198,24 +1302,18 @@ class Topic < ActiveRecord::Base
def banner
post = self.ordered_posts.first
- {
- html: post.cooked,
- key: self.id,
- url: self.url
- }
+ { html: post.cooked, key: self.id, url: self.url }
end
cattr_accessor :slug_computed_callbacks
self.slug_computed_callbacks = []
def slug_for_topic(title)
- return '' unless title.present?
+ return "" unless title.present?
slug = Slug.for(title)
# this is a hook for plugins that need to modify the generated slug
- self.class.slug_computed_callbacks.each do |callback|
- slug = callback.call(self, slug, title)
- end
+ self.class.slug_computed_callbacks.each { |callback| slug = callback.call(self, slug, title) }
slug
end
@@ -1223,7 +1321,7 @@ class Topic < ActiveRecord::Base
# Even if the slug column in the database is null, topic.slug will return something:
def slug
unless slug = read_attribute(:slug)
- return '' unless title.present?
+ return "" unless title.present?
slug = slug_for_topic(title)
if new_record?
write_attribute(:slug, slug)
@@ -1295,17 +1393,18 @@ class Topic < ActiveRecord::Base
def update_pinned(status, global = false, pinned_until = nil)
if pinned_until
- pinned_until = begin
- Time.parse(pinned_until)
- rescue ArgumentError
- raise Discourse::InvalidParameters.new(:pinned_until)
- end
+ pinned_until =
+ begin
+ Time.parse(pinned_until)
+ rescue ArgumentError
+ raise Discourse::InvalidParameters.new(:pinned_until)
+ end
end
update_columns(
pinned_at: status ? Time.zone.now : nil,
pinned_globally: global,
- pinned_until: pinned_until
+ pinned_until: pinned_until,
)
Jobs.cancel_scheduled_job(:unpin_topic, topic_id: self.id)
@@ -1321,17 +1420,19 @@ class Topic < ActiveRecord::Base
end
def muted?(user)
- if user && user.id
- notifier.muted?(user.id)
- end
+ notifier.muted?(user.id) if user && user.id
end
def self.ensure_consistency!
# unpin topics that might have been missed
- Topic.where('pinned_until < ?', Time.now).update_all(pinned_at: nil, pinned_globally: false, pinned_until: nil)
- Topic.where('bannered_until < ?', Time.now).find_each do |topic|
- topic.remove_banner!(Discourse.system_user)
- end
+ Topic.where("pinned_until < ?", Time.now).update_all(
+ pinned_at: nil,
+ pinned_globally: false,
+ pinned_until: nil,
+ )
+ Topic
+ .where("bannered_until < ?", Time.now)
+ .find_each { |topic| topic.remove_banner!(Discourse.system_user) }
end
def inherit_slow_mode_from_category
@@ -1343,11 +1444,8 @@ class Topic < ActiveRecord::Base
def inherit_auto_close_from_category(timer_type: :close)
auto_close_hours = self.category&.auto_close_hours
- if self.open? &&
- !@ignore_category_auto_close &&
- auto_close_hours.present? &&
- public_topic_timer&.execute_at.blank?
-
+ if self.open? && !@ignore_category_auto_close && auto_close_hours.present? &&
+ public_topic_timer&.execute_at.blank?
based_on_last_post = self.category.auto_close_based_on_last_post
duration_minutes = based_on_last_post ? auto_close_hours * 60 : nil
@@ -1374,7 +1472,7 @@ class Topic < ActiveRecord::Base
auto_close_time,
by_user: Discourse.system_user,
based_on_last_post: based_on_last_post,
- duration_minutes: duration_minutes
+ duration_minutes: duration_minutes,
)
end
end
@@ -1407,8 +1505,18 @@ class Topic < ActiveRecord::Base
# * duration_minutes: The duration of the timer in minutes, which is used if the timer is based
# on the last post or if the timer type is delete_replies.
# * silent: Affects whether the close topic timer status change will be silent or not.
- def set_or_create_timer(status_type, time, by_user: nil, based_on_last_post: false, category_id: SiteSetting.uncategorized_category_id, duration_minutes: nil, silent: nil)
- return delete_topic_timer(status_type, by_user: by_user) if time.blank? && duration_minutes.blank?
+ def set_or_create_timer(
+ status_type,
+ time,
+ by_user: nil,
+ based_on_last_post: false,
+ category_id: SiteSetting.uncategorized_category_id,
+ duration_minutes: nil,
+ silent: nil
+ )
+ if time.blank? && duration_minutes.blank?
+ return delete_topic_timer(status_type, by_user: by_user)
+ end
duration_minutes = duration_minutes ? duration_minutes.to_i : 0
public_topic_timer = !!TopicTimer.public_types[status_type]
@@ -1427,21 +1535,30 @@ class Topic < ActiveRecord::Base
if topic_timer.based_on_last_post
if duration_minutes > 0
- last_post_created_at = self.ordered_posts.last.present? ? self.ordered_posts.last.created_at : time_now
+ last_post_created_at =
+ self.ordered_posts.last.present? ? self.ordered_posts.last.created_at : time_now
topic_timer.duration_minutes = duration_minutes
topic_timer.execute_at = last_post_created_at + duration_minutes.minutes
topic_timer.created_at = last_post_created_at
end
elsif topic_timer.status_type == TopicTimer.types[:delete_replies]
if duration_minutes > 0
- first_reply_created_at = (self.ordered_posts.where("post_number > 1").minimum(:created_at) || time_now)
+ first_reply_created_at =
+ (self.ordered_posts.where("post_number > 1").minimum(:created_at) || time_now)
topic_timer.duration_minutes = duration_minutes
topic_timer.execute_at = first_reply_created_at + duration_minutes.minutes
topic_timer.created_at = first_reply_created_at
end
else
utc = Time.find_zone("UTC")
- is_float = (Float(time) rescue nil)
+ is_float =
+ (
+ begin
+ Float(time)
+ rescue StandardError
+ nil
+ end
+ )
if is_float
num_hours = time.to_f
@@ -1458,7 +1575,14 @@ class Topic < ActiveRecord::Base
if by_user&.staff? || by_user&.trust_level == TrustLevel[4]
topic_timer.user = by_user
else
- topic_timer.user ||= (self.user.staff? || self.user.trust_level == TrustLevel[4] ? self.user : Discourse.system_user)
+ topic_timer.user ||=
+ (
+ if self.user.staff? || self.user.trust_level == TrustLevel[4]
+ self.user
+ else
+ Discourse.system_user
+ end
+ )
end
if self.persisted?
@@ -1490,9 +1614,8 @@ class Topic < ActiveRecord::Base
end
def secure_group_ids
- @secure_group_ids ||= if self.category && self.category.read_restricted?
- self.category.secure_group_ids
- end
+ @secure_group_ids ||=
+ (self.category.secure_group_ids if self.category && self.category.read_restricted?)
end
def has_topic_embed?
@@ -1584,7 +1707,10 @@ class Topic < ActiveRecord::Base
end
def self.time_to_first_response_per_day(start_date, end_date, opts = {})
- time_to_first_response(TIME_TO_FIRST_RESPONSE_SQL, opts.merge(start_date: start_date, end_date: end_date))
+ time_to_first_response(
+ TIME_TO_FIRST_RESPONSE_SQL,
+ opts.merge(start_date: start_date, end_date: end_date),
+ )
end
def self.time_to_first_response_total(opts = nil)
@@ -1606,7 +1732,12 @@ class Topic < ActiveRecord::Base
ORDER BY tt.created_at
SQL
- def self.with_no_response_per_day(start_date, end_date, category_id = nil, include_subcategories = nil)
+ def self.with_no_response_per_day(
+ start_date,
+ end_date,
+ category_id = nil,
+ include_subcategories = nil
+ )
builder = DB.build(WITH_NO_RESPONSE_SQL)
builder.where("t.created_at >= :start_date", start_date: start_date) if start_date
builder.where("t.created_at < :end_date", end_date: end_date) if end_date
@@ -1662,9 +1793,7 @@ class Topic < ActiveRecord::Base
def update_excerpt(excerpt)
update_column(:excerpt, excerpt)
- if archetype == "banner"
- ApplicationController.banner_json_cache.clear
- end
+ ApplicationController.banner_json_cache.clear if archetype == "banner"
end
def pm_with_non_human_user?
@@ -1692,9 +1821,9 @@ class Topic < ActiveRecord::Base
def self.private_message_topics_count_per_day(start_date, end_date, topic_subtype)
private_messages
.with_subtype(topic_subtype)
- .where('topics.created_at >= ? AND topics.created_at <= ?', start_date, end_date)
- .group('date(topics.created_at)')
- .order('date(topics.created_at)')
+ .where("topics.created_at >= ? AND topics.created_at <= ?", start_date, end_date)
+ .group("date(topics.created_at)")
+ .order("date(topics.created_at)")
.count
end
@@ -1703,11 +1832,12 @@ class Topic < ActiveRecord::Base
end
def reset_bumped_at
- post = ordered_posts.where(
- user_deleted: false,
- hidden: false,
- post_type: Post.types[:regular]
- ).last || first_post
+ post =
+ ordered_posts.where(
+ user_deleted: false,
+ hidden: false,
+ post_type: Post.types[:regular],
+ ).last || first_post
self.bumped_at = post.created_at
self.save(validate: false)
@@ -1716,21 +1846,26 @@ class Topic < ActiveRecord::Base
def auto_close_threshold_reached?
return if user&.staff?
- scores = ReviewableScore.pending
- .joins(:reviewable)
- .where('reviewable_scores.score >= ?', Reviewable.min_score_for_priority)
- .where('reviewables.topic_id = ?', self.id)
- .pluck('COUNT(DISTINCT reviewable_scores.user_id), COALESCE(SUM(reviewable_scores.score), 0.0)')
- .first
+ scores =
+ ReviewableScore
+ .pending
+ .joins(:reviewable)
+ .where("reviewable_scores.score >= ?", Reviewable.min_score_for_priority)
+ .where("reviewables.topic_id = ?", self.id)
+ .pluck(
+ "COUNT(DISTINCT reviewable_scores.user_id), COALESCE(SUM(reviewable_scores.score), 0.0)",
+ )
+ .first
- scores[0] >= SiteSetting.num_flaggers_to_close_topic && scores[1] >= Reviewable.score_to_auto_close_topic
+ scores[0] >= SiteSetting.num_flaggers_to_close_topic &&
+ scores[1] >= Reviewable.score_to_auto_close_topic
end
def update_category_topic_count_by(num)
if category_id.present?
Category
- .where('id = ?', category_id)
- .where('topic_id != ? OR topic_id IS NULL', self.id)
+ .where("id = ?", category_id)
+ .where("topic_id != ? OR topic_id IS NULL", self.id)
.update_all("topic_count = topic_count + #{num.to_i}")
end
end
@@ -1749,40 +1884,46 @@ class Topic < ActiveRecord::Base
# TODO(martin) Look at improving this N1, it will just get slower the
# more replies/incoming emails there are for the topic.
- self.incoming_email.where("created_at <= ?", received_before).each do |incoming_email|
- to_addresses = incoming_email.to_addresses_split
- cc_addresses = incoming_email.cc_addresses_split
- combined_addresses = [to_addresses, cc_addresses].flatten
+ self
+ .incoming_email
+ .where("created_at <= ?", received_before)
+ .each do |incoming_email|
+ to_addresses = incoming_email.to_addresses_split
+ cc_addresses = incoming_email.cc_addresses_split
+ combined_addresses = [to_addresses, cc_addresses].flatten
- # We only care about the emails addressed to the group or CC'd to the
- # group if the group is present. If combined addresses is empty we do
- # not need to do this check, and instead can proceed on to adding the
- # from address.
- #
- # Will not include test1@gmail.com if the only IncomingEmail
- # is:
- #
- # from: test1@gmail.com
- # to: test+support@discoursemail.com
- #
- # Because we don't care about the from addresses and also the to address
- # is not the email_username, which will be something like test1@gmail.com.
- if group.present? && combined_addresses.any?
- next if combined_addresses.none? { |address| address =~ group.email_username_regex }
+ # We only care about the emails addressed to the group or CC'd to the
+ # group if the group is present. If combined addresses is empty we do
+ # not need to do this check, and instead can proceed on to adding the
+ # from address.
+ #
+ # Will not include test1@gmail.com if the only IncomingEmail
+ # is:
+ #
+ # from: test1@gmail.com
+ # to: test+support@discoursemail.com
+ #
+ # Because we don't care about the from addresses and also the to address
+ # is not the email_username, which will be something like test1@gmail.com.
+ if group.present? && combined_addresses.any?
+ next if combined_addresses.none? { |address| address =~ group.email_username_regex }
+ end
+
+ email_addresses.add(incoming_email.from_address)
+ email_addresses.merge(combined_addresses)
end
- email_addresses.add(incoming_email.from_address)
- email_addresses.merge(combined_addresses)
- end
-
- email_addresses.subtract([nil, ''])
+ email_addresses.subtract([nil, ""])
email_addresses.delete(group.email_username) if group.present?
email_addresses.to_a
end
def create_invite_notification!(target_user, notification_type, invited_by, post_number: 1)
- if UserCommScreener.new(acting_user: invited_by, target_user_ids: target_user.id).ignoring_or_muting_actor?(target_user.id)
+ if UserCommScreener.new(
+ acting_user: invited_by,
+ target_user_ids: target_user.id,
+ ).ignoring_or_muting_actor?(target_user.id)
raise NotAllowed.new(I18n.t("not_accepting_pms", username: target_user.username))
end
@@ -1794,8 +1935,8 @@ class Topic < ActiveRecord::Base
topic_title: self.title,
display_username: invited_by.username,
original_user_id: user.id,
- original_username: user.username
- }.to_json
+ original_username: user.username,
+ }.to_json,
)
end
@@ -1804,28 +1945,35 @@ class Topic < ActiveRecord::Base
invited_by,
"topic-invitations-per-day",
SiteSetting.max_topic_invitations_per_day,
- 1.day.to_i
+ 1.day.to_i,
).performed!
RateLimiter.new(
invited_by,
"topic-invitations-per-minute",
SiteSetting.max_topic_invitations_per_minute,
- 1.day.to_i
+ 1.day.to_i,
).performed!
end
def cannot_permanently_delete_reason(user)
- all_posts_count = Post.with_deleted
- .where(topic_id: self.id)
- .where(post_type: [Post.types[:regular], Post.types[:moderator_action], Post.types[:whisper]])
- .count
+ all_posts_count =
+ Post
+ .with_deleted
+ .where(topic_id: self.id)
+ .where(
+ post_type: [Post.types[:regular], Post.types[:moderator_action], Post.types[:whisper]],
+ )
+ .count
if posts_count > 0 || all_posts_count > 1
- I18n.t('post.cannot_permanently_delete.many_posts')
+ I18n.t("post.cannot_permanently_delete.many_posts")
elsif self.deleted_by_id == user&.id && self.deleted_at >= Post::PERMANENT_DELETE_TIMER.ago
- time_left = RateLimiter.time_left(Post::PERMANENT_DELETE_TIMER.to_i - Time.zone.now.to_i + self.deleted_at.to_i)
- I18n.t('post.cannot_permanently_delete.wait_or_different_admin', time_left: time_left)
+ time_left =
+ RateLimiter.time_left(
+ Post::PERMANENT_DELETE_TIMER.to_i - Time.zone.now.to_i + self.deleted_at.to_i,
+ )
+ I18n.t("post.cannot_permanently_delete.wait_or_different_admin", time_left: time_left)
end
end
@@ -1855,9 +2003,11 @@ class Topic < ActiveRecord::Base
when :liked, :unliked
stats = { like_count: topic.like_count }
when :created, :destroyed, :deleted, :recovered
- stats = { posts_count: topic.posts_count,
- last_posted_at: topic.last_posted_at.as_json,
- last_poster: BasicUserSerializer.new(topic.last_poster, root: false).as_json }
+ stats = {
+ posts_count: topic.posts_count,
+ last_posted_at: topic.last_posted_at.as_json,
+ last_poster: BasicUserSerializer.new(topic.last_poster, root: false).as_json,
+ }
else
stats = nil
end
@@ -1866,11 +2016,7 @@ class Topic < ActiveRecord::Base
secure_audience = topic.secure_audience_publish_messages
if secure_audience[:user_ids] != [] && secure_audience[:group_ids] != []
- message = stats.merge({
- id: topic_id,
- updated_at: Time.now,
- type: :stats,
- })
+ message = stats.merge({ id: topic_id, updated_at: Time.now, type: :stats })
MessageBus.publish("/topic/#{topic_id}", message, opts.merge(secure_audience))
end
end
@@ -1880,15 +2026,15 @@ class Topic < ActiveRecord::Base
def invite_to_private_message(invited_by, target_user, guardian)
if !guardian.can_send_private_message?(target_user)
- raise UserExists.new(I18n.t(
- "activerecord.errors.models.topic.attributes.base.cant_send_pm"
- ))
+ raise UserExists.new(I18n.t("activerecord.errors.models.topic.attributes.base.cant_send_pm"))
end
rate_limit_topic_invitation(invited_by)
Topic.transaction do
- topic_allowed_users.create!(user_id: target_user.id) unless topic_allowed_users.exists?(user_id: target_user.id)
+ unless topic_allowed_users.exists?(user_id: target_user.id)
+ topic_allowed_users.create!(user_id: target_user.id)
+ end
user_in_allowed_group = (user.group_ids & topic_allowed_groups.map(&:group_id)).present?
add_small_action(invited_by, "invited_user", target_user.username) if !user_in_allowed_group
@@ -1896,7 +2042,7 @@ class Topic < ActiveRecord::Base
create_invite_notification!(
target_user,
Notification.types[:invited_to_private_message],
- invited_by
+ invited_by,
)
end
end
@@ -1908,24 +2054,18 @@ class Topic < ActiveRecord::Base
if group_ids.present?
(
self.category.groups.where(id: group_ids).where(automatic: false) -
- target_user.groups.where(automatic: false)
+ target_user.groups.where(automatic: false)
).each do |group|
if guardian.can_edit_group?(group)
group.add(target_user)
- GroupActionLogger
- .new(invited_by, group)
- .log_add_user_to_group(target_user)
+ GroupActionLogger.new(invited_by, group).log_add_user_to_group(target_user)
end
end
end
if Guardian.new(target_user).can_see_topic?(self)
- create_invite_notification!(
- target_user,
- Notification.types[:invited_to_topic],
- invited_by
- )
+ create_invite_notification!(target_user, Notification.types[:invited_to_topic], invited_by)
end
end
end
diff --git a/app/models/topic_converter.rb b/app/models/topic_converter.rb
index 47c8b4a3c72..8eab3a31d0c 100644
--- a/app/models/topic_converter.rb
+++ b/app/models/topic_converter.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class TopicConverter
-
attr_reader :topic
def initialize(topic, user)
@@ -17,16 +16,17 @@ class TopicConverter
elsif SiteSetting.allow_uncategorized_topics
SiteSetting.uncategorized_category_id
else
- Category.where(read_restricted: false)
+ Category
+ .where(read_restricted: false)
.where.not(id: SiteSetting.uncategorized_category_id)
- .order('id asc')
+ .order("id asc")
.pluck_first(:id)
end
PostRevisor.new(@topic.first_post, @topic).revise!(
@user,
category_id: category_id,
- archetype: Archetype.default
+ archetype: Archetype.default,
)
update_user_stats
@@ -45,7 +45,7 @@ class TopicConverter
PostRevisor.new(@topic.first_post, @topic).revise!(
@user,
category_id: nil,
- archetype: Archetype.private_message
+ archetype: Archetype.private_message,
)
add_allowed_users
@@ -63,9 +63,12 @@ class TopicConverter
private
def posters
- @posters ||= @topic.posts
- .where.not(post_type: [Post.types[:small_action], Post.types[:whisper]])
- .distinct.pluck(:user_id)
+ @posters ||=
+ @topic
+ .posts
+ .where.not(post_type: [Post.types[:small_action], Post.types[:whisper]])
+ .distinct
+ .pluck(:user_id)
end
def increment_users_post_count
@@ -134,8 +137,6 @@ class TopicConverter
end
def update_post_uploads_secure_status
- DB.after_commit do
- Jobs.enqueue(:update_topic_upload_security, topic_id: @topic.id)
- end
+ DB.after_commit { Jobs.enqueue(:update_topic_upload_security, topic_id: @topic.id) }
end
end
diff --git a/app/models/topic_embed.rb b/app/models/topic_embed.rb
index 6b0e3662f84..3b9545bf815 100644
--- a/app/models/topic_embed.rb
+++ b/app/models/topic_embed.rb
@@ -9,7 +9,13 @@ class TopicEmbed < ActiveRecord::Base
validates_uniqueness_of :embed_url
before_validation(on: :create) do
- unless (topic_embed = TopicEmbed.with_deleted.where('deleted_at IS NOT NULL AND embed_url = ?', embed_url).first).nil?
+ unless (
+ topic_embed =
+ TopicEmbed
+ .with_deleted
+ .where("deleted_at IS NOT NULL AND embed_url = ?", embed_url)
+ .first
+ ).nil?
topic_embed.destroy!
end
end
@@ -19,23 +25,21 @@ class TopicEmbed < ActiveRecord::Base
end
def self.normalize_url(url)
- url.downcase.sub(/\/$/, '').sub(/\-+/, '-').strip
+ url.downcase.sub(%r{/$}, "").sub(/\-+/, "-").strip
end
def self.imported_from_html(url)
I18n.with_locale(SiteSetting.default_locale) do
- "\n
\n#{I18n.t('embed.imported_from', link: "#{url}")}\n"
+ "\n
\n#{I18n.t("embed.imported_from", link: "#{url}")}\n"
end
end
# Import an article from a source (RSS/Atom/Other)
def self.import(user, url, title, contents, category_id: nil, cook_method: nil, tags: nil)
- return unless url =~ /^https?\:\/\//
+ return unless url =~ %r{^https?\://}
- if SiteSetting.embed_truncate && cook_method.nil?
- contents = first_paragraph_from(contents)
- end
- contents ||= ''
+ contents = first_paragraph_from(contents) if SiteSetting.embed_truncate && cook_method.nil?
+ contents ||= ""
contents = contents.dup << imported_from_html(url)
url = normalize_url(url)
@@ -49,11 +53,12 @@ class TopicEmbed < ActiveRecord::Base
Topic.transaction do
eh = EmbeddableHost.record_for_url(url)
- cook_method ||= if SiteSetting.embed_support_markdown
- Post.cook_methods[:regular]
- else
- Post.cook_methods[:raw_html]
- end
+ cook_method ||=
+ if SiteSetting.embed_support_markdown
+ Post.cook_methods[:regular]
+ else
+ Post.cook_methods[:raw_html]
+ end
create_args = {
title: title,
@@ -63,17 +68,17 @@ class TopicEmbed < ActiveRecord::Base
category: category_id || eh.try(:category_id),
tags: SiteSetting.tagging_enabled ? tags : nil,
}
- if SiteSetting.embed_unlisted?
- create_args[:visible] = false
- end
+ create_args[:visible] = false if SiteSetting.embed_unlisted?
creator = PostCreator.new(user, create_args)
post = creator.create
if post.present?
- TopicEmbed.create!(topic_id: post.topic_id,
- embed_url: url,
- content_sha1: content_sha1,
- post_id: post.id)
+ TopicEmbed.create!(
+ topic_id: post.topic_id,
+ embed_url: url,
+ content_sha1: content_sha1,
+ post_id: post.id,
+ )
end
end
else
@@ -87,7 +92,7 @@ class TopicEmbed < ActiveRecord::Base
post_ids: [post.id],
topic_id: post.topic_id,
new_owner: user,
- acting_user: Discourse.system_user
+ acting_user: Discourse.system_user,
).change_owner!
# make sure the post returned has the right author
@@ -108,16 +113,11 @@ class TopicEmbed < ActiveRecord::Base
end
def self.find_remote(url)
- require 'ruby-readability'
+ require "ruby-readability"
url = UrlHelper.normalized_encode(url)
original_uri = URI.parse(url)
- fd = FinalDestination.new(
- url,
- validate_uri: true,
- max_redirects: 5,
- follow_canonical: true,
- )
+ fd = FinalDestination.new(url, validate_uri: true, max_redirects: 5, follow_canonical: true)
uri = fd.resolve
return if uri.blank?
@@ -125,12 +125,17 @@ class TopicEmbed < ActiveRecord::Base
opts = {
tags: %w[div p code pre h1 h2 h3 b em i strong a img ul li ol blockquote],
attributes: %w[href src class],
- remove_empty_nodes: false
+ remove_empty_nodes: false,
}
- opts[:whitelist] = SiteSetting.allowed_embed_selectors if SiteSetting.allowed_embed_selectors.present?
- opts[:blacklist] = SiteSetting.blocked_embed_selectors if SiteSetting.blocked_embed_selectors.present?
- allowed_embed_classnames = SiteSetting.allowed_embed_classnames if SiteSetting.allowed_embed_classnames.present?
+ opts[
+ :whitelist
+ ] = SiteSetting.allowed_embed_selectors if SiteSetting.allowed_embed_selectors.present?
+ opts[
+ :blacklist
+ ] = SiteSetting.blocked_embed_selectors if SiteSetting.blocked_embed_selectors.present?
+ allowed_embed_classnames =
+ SiteSetting.allowed_embed_classnames if SiteSetting.allowed_embed_classnames.present?
response = FetchResponse.new
begin
@@ -139,7 +144,7 @@ class TopicEmbed < ActiveRecord::Base
return
end
- raw_doc = Nokogiri::HTML5(html)
+ raw_doc = Nokogiri.HTML5(html)
auth_element = raw_doc.at('meta[@name="author"]')
if auth_element.present?
response.author = User.where(username_lower: auth_element[:content].strip).first
@@ -147,39 +152,51 @@ class TopicEmbed < ActiveRecord::Base
read_doc = Readability::Document.new(html, opts)
- title = +(raw_doc.title || '')
+ title = +(raw_doc.title || "")
title.strip!
if SiteSetting.embed_title_scrubber.present?
- title.sub!(Regexp.new(SiteSetting.embed_title_scrubber), '')
+ title.sub!(Regexp.new(SiteSetting.embed_title_scrubber), "")
title.strip!
end
response.title = title
- doc = Nokogiri::HTML5(read_doc.content)
+ doc = Nokogiri.HTML5(read_doc.content)
- tags = { 'img' => 'src', 'script' => 'src', 'a' => 'href' }
- doc.search(tags.keys.join(',')).each do |node|
- url_param = tags[node.name]
- src = node[url_param]
- unless (src.nil? || src.empty?)
- begin
- # convert URL to absolute form
- node[url_param] = URI.join(url, UrlHelper.normalized_encode(src)).to_s
- rescue URI::Error, Addressable::URI::InvalidURIError
- # If there is a mistyped URL, just do nothing
+ tags = { "img" => "src", "script" => "src", "a" => "href" }
+ doc
+ .search(tags.keys.join(","))
+ .each do |node|
+ url_param = tags[node.name]
+ src = node[url_param]
+ unless (src.nil? || src.empty?)
+ begin
+ # convert URL to absolute form
+ node[url_param] = URI.join(url, UrlHelper.normalized_encode(src)).to_s
+ rescue URI::Error, Addressable::URI::InvalidURIError
+ # If there is a mistyped URL, just do nothing
+ end
end
+ # only allow classes in the allowlist
+ allowed_classes =
+ if allowed_embed_classnames.blank?
+ []
+ else
+ allowed_embed_classnames.split(/[ ,]+/i)
+ end
+ doc
+ .search('[class]:not([class=""])')
+ .each do |classnode|
+ classes =
+ classnode[:class]
+ .split(" ")
+ .select { |classname| allowed_classes.include?(classname) }
+ if classes.length === 0
+ classnode.delete("class")
+ else
+ classnode[:class] = classes.join(" ")
+ end
+ end
end
- # only allow classes in the allowlist
- allowed_classes = if allowed_embed_classnames.blank? then [] else allowed_embed_classnames.split(/[ ,]+/i) end
- doc.search('[class]:not([class=""])').each do |classnode|
- classes = classnode[:class].split(' ').select { |classname| allowed_classes.include?(classname) }
- if classes.length === 0
- classnode.delete('class')
- else
- classnode[:class] = classes.join(' ')
- end
- end
- end
response.body = doc.to_html
response
@@ -208,59 +225,69 @@ class TopicEmbed < ActiveRecord::Base
prefix += ":#{uri.port}" if uri.port != 80 && uri.port != 443
fragment = Nokogiri::HTML5.fragment("#{contents}
")
- fragment.css('a').each do |a|
- if a['href'].present?
- begin
- a['href'] = URI.join(prefix, a['href']).to_s
- rescue URI::InvalidURIError
- # NOOP, URL is malformed
+ fragment
+ .css("a")
+ .each do |a|
+ if a["href"].present?
+ begin
+ a["href"] = URI.join(prefix, a["href"]).to_s
+ rescue URI::InvalidURIError
+ # NOOP, URL is malformed
+ end
end
end
- end
- fragment.css('img').each do |a|
- if a['src'].present?
- begin
- a['src'] = URI.join(prefix, a['src']).to_s
- rescue URI::InvalidURIError
- # NOOP, URL is malformed
+ fragment
+ .css("img")
+ .each do |a|
+ if a["src"].present?
+ begin
+ a["src"] = URI.join(prefix, a["src"]).to_s
+ rescue URI::InvalidURIError
+ # NOOP, URL is malformed
+ end
end
end
- end
- fragment.at('div').inner_html
+ fragment.at("div").inner_html
end
def self.topic_id_for_embed(embed_url)
- embed_url = normalize_url(embed_url).sub(/^https?\:\/\//, '')
- TopicEmbed.where("embed_url ~* ?", "^https?://#{Regexp.escape(embed_url)}$").pluck_first(:topic_id)
+ embed_url = normalize_url(embed_url).sub(%r{^https?\://}, "")
+ TopicEmbed.where("embed_url ~* ?", "^https?://#{Regexp.escape(embed_url)}$").pluck_first(
+ :topic_id,
+ )
end
def self.first_paragraph_from(html)
- doc = Nokogiri::HTML5(html)
+ doc = Nokogiri.HTML5(html)
result = +""
- doc.css('p').each do |p|
- if p.text.present?
- result << p.to_s
- return result if result.size >= 100
+ doc
+ .css("p")
+ .each do |p|
+ if p.text.present?
+ result << p.to_s
+ return result if result.size >= 100
+ end
end
- end
return result unless result.blank?
# If there is no first paragraph, return the first div (onebox)
- doc.css('div').first.to_s
+ doc.css("div").first.to_s
end
def self.expanded_for(post)
- Discourse.cache.fetch("embed-topic:#{post.topic_id}", expires_in: 10.minutes) do
- url = TopicEmbed.where(topic_id: post.topic_id).pluck_first(:embed_url)
- response = TopicEmbed.find_remote(url)
+ Discourse
+ .cache
+ .fetch("embed-topic:#{post.topic_id}", expires_in: 10.minutes) do
+ url = TopicEmbed.where(topic_id: post.topic_id).pluck_first(:embed_url)
+ response = TopicEmbed.find_remote(url)
- body = response.body
- body << TopicEmbed.imported_from_html(url)
- body
- end
+ body = response.body
+ body << TopicEmbed.imported_from_html(url)
+ body
+ end
end
end
diff --git a/app/models/topic_featured_users.rb b/app/models/topic_featured_users.rb
index 3cd3c7fda31..5383ae6655f 100644
--- a/app/models/topic_featured_users.rb
+++ b/app/models/topic_featured_users.rb
@@ -18,14 +18,15 @@ class TopicFeaturedUsers
end
def user_ids
- [topic.featured_user1_id,
- topic.featured_user2_id,
- topic.featured_user3_id,
- topic.featured_user4_id].uniq.compact
+ [
+ topic.featured_user1_id,
+ topic.featured_user2_id,
+ topic.featured_user3_id,
+ topic.featured_user4_id,
+ ].uniq.compact
end
def self.ensure_consistency!(topic_id = nil)
-
filter = "#{"AND t.id = #{topic_id.to_i}" if topic_id}"
filter2 = "#{"AND tt.id = #{topic_id.to_i}" if topic_id}"
@@ -87,7 +88,11 @@ SQL
private
def update_participant_count
- count = topic.posts.where('NOT hidden AND post_type in (?)', Topic.visible_post_types).count('distinct user_id')
+ count =
+ topic
+ .posts
+ .where("NOT hidden AND post_type in (?)", Topic.visible_post_types)
+ .count("distinct user_id")
topic.update_columns(participant_count: count)
end
end
diff --git a/app/models/topic_group.rb b/app/models/topic_group.rb
index 7f3c4060f34..f9e0f65fb01 100644
--- a/app/models/topic_group.rb
+++ b/app/models/topic_group.rb
@@ -31,10 +31,14 @@ class TopicGroup < ActiveRecord::Base
tg.group_id
SQL
- updated_groups = DB.query(
- update_query,
- user_id: user.id, topic_id: topic_id, post_number: post_number, now: DateTime.now
- )
+ updated_groups =
+ DB.query(
+ update_query,
+ user_id: user.id,
+ topic_id: topic_id,
+ post_number: post_number,
+ now: DateTime.now,
+ )
end
def self.create_topic_group(user, topic_id, post_number, updated_group_ids)
@@ -47,7 +51,8 @@ class TopicGroup < ActiveRecord::Base
AND tag.topic_id = :topic_id
SQL
- query += 'AND NOT(tag.group_id IN (:already_updated_groups))' unless updated_group_ids.length.zero?
+ query +=
+ "AND NOT(tag.group_id IN (:already_updated_groups))" unless updated_group_ids.length.zero?
query += <<~SQL
ON CONFLICT(topic_id, group_id)
@@ -56,7 +61,11 @@ class TopicGroup < ActiveRecord::Base
DB.exec(
query,
- user_id: user.id, topic_id: topic_id, post_number: post_number, now: DateTime.now, already_updated_groups: updated_group_ids
+ user_id: user.id,
+ topic_id: topic_id,
+ post_number: post_number,
+ now: DateTime.now,
+ already_updated_groups: updated_group_ids,
)
end
end
diff --git a/app/models/topic_link.rb b/app/models/topic_link.rb
index 690779cb06e..03bc3587b45 100644
--- a/app/models/topic_link.rb
+++ b/app/models/topic_link.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'uri'
+require "uri"
class TopicLink < ActiveRecord::Base
-
def self.max_domain_length
100
end
@@ -15,14 +14,14 @@ class TopicLink < ActiveRecord::Base
belongs_to :topic
belongs_to :user
belongs_to :post
- belongs_to :link_topic, class_name: 'Topic'
- belongs_to :link_post, class_name: 'Post'
+ belongs_to :link_topic, class_name: "Topic"
+ belongs_to :link_post, class_name: "Post"
validates_presence_of :url
validates_length_of :url, maximum: 500
- validates_uniqueness_of :url, scope: [:topic_id, :post_id]
+ validates_uniqueness_of :url, scope: %i[topic_id post_id]
has_many :topic_link_clicks, dependent: :destroy
@@ -36,7 +35,6 @@ class TopicLink < ActiveRecord::Base
end
def self.topic_map(guardian, topic_id)
-
# Sam: complicated reports are really hard in AR
builder = DB.build(<<~SQL)
SELECT ftl.url,
@@ -56,16 +54,18 @@ class TopicLink < ActiveRecord::Base
LIMIT 50
SQL
- builder.where('ftl.topic_id = :topic_id', topic_id: topic_id)
- builder.where('ft.deleted_at IS NULL')
+ builder.where("ftl.topic_id = :topic_id", topic_id: topic_id)
+ builder.where("ft.deleted_at IS NULL")
builder.where("ftl.extension IS NULL OR ftl.extension NOT IN ('png','jpg','gif')")
- builder.where("COALESCE(ft.archetype, 'regular') <> :archetype", archetype: Archetype.private_message)
+ builder.where(
+ "COALESCE(ft.archetype, 'regular') <> :archetype",
+ archetype: Archetype.private_message,
+ )
builder.where("clicks > 0")
builder.secure_category(guardian.secure_category_ids)
builder.query
-
end
def self.counts_for(guardian, topic, posts)
@@ -73,7 +73,9 @@ class TopicLink < ActiveRecord::Base
# Sam: this is not tidy in AR and also happens to be a critical path
# for topic view
- builder = DB.build("SELECT
+ builder =
+ DB.build(
+ "SELECT
l.post_id,
l.url,
l.clicks,
@@ -86,28 +88,39 @@ class TopicLink < ActiveRecord::Base
LEFT JOIN categories AS c ON c.id = t.category_id
/*left_join*/
/*where*/
- ORDER BY reflection ASC, clicks DESC")
+ ORDER BY reflection ASC, clicks DESC",
+ )
- builder.where('t.deleted_at IS NULL')
- builder.where("COALESCE(t.archetype, 'regular') <> :archetype", archetype: Archetype.private_message)
+ builder.where("t.deleted_at IS NULL")
+ builder.where(
+ "COALESCE(t.archetype, 'regular') <> :archetype",
+ archetype: Archetype.private_message,
+ )
if guardian.authenticated?
- builder.left_join("topic_users AS tu ON (t.id = tu.topic_id AND tu.user_id = #{guardian.user.id.to_i})")
- builder.where('COALESCE(tu.notification_level,1) > :muted', muted: TopicUser.notification_levels[:muted])
+ builder.left_join(
+ "topic_users AS tu ON (t.id = tu.topic_id AND tu.user_id = #{guardian.user.id.to_i})",
+ )
+ builder.where(
+ "COALESCE(tu.notification_level,1) > :muted",
+ muted: TopicUser.notification_levels[:muted],
+ )
end
# not certain if pluck is right, cause it may interfere with caching
- builder.where('l.post_id in (:post_ids)', post_ids: posts.map(&:id))
+ builder.where("l.post_id in (:post_ids)", post_ids: posts.map(&:id))
builder.secure_category(guardian.secure_category_ids)
result = {}
builder.query.each do |l|
result[l.post_id] ||= []
- result[l.post_id] << { url: l.url,
- clicks: l.clicks,
- title: l.title,
- internal: l.internal,
- reflection: l.reflection }
+ result[l.post_id] << {
+ url: l.url,
+ clicks: l.clicks,
+ title: l.title,
+ internal: l.internal,
+ reflection: l.reflection,
+ }
end
result
end
@@ -127,22 +140,20 @@ class TopicLink < ActiveRecord::Base
.reject { |_, p| p.nil? || "mailto" == p.scheme }
.uniq { |_, p| p }
.each do |link, parsed|
-
- TopicLink.transaction do
- begin
- url, reflected_id = self.ensure_entry_for(post, link, parsed)
- current_urls << url unless url.nil?
- reflected_ids << reflected_id unless reflected_id.nil?
- rescue URI::Error
- # if the URI is invalid, don't store it.
- rescue ActionController::RoutingError
- # If we can't find the route, no big deal
+ TopicLink.transaction do
+ begin
+ url, reflected_id = self.ensure_entry_for(post, link, parsed)
+ current_urls << url unless url.nil?
+ reflected_ids << reflected_id unless reflected_id.nil?
+ rescue URI::Error
+ # if the URI is invalid, don't store it.
+ rescue ActionController::RoutingError
+ # If we can't find the route, no big deal
+ end
end
end
- end
self.cleanup_entries(post, current_urls, reflected_ids)
-
end
def self.crawl_link_title(topic_link_id)
@@ -154,20 +165,23 @@ class TopicLink < ActiveRecord::Base
end
def self.duplicate_lookup(topic)
- results = TopicLink
- .includes(:post, :user)
- .joins(:post, :user)
- .where("posts.id IS NOT NULL AND users.id IS NOT NULL")
- .where(topic_id: topic.id, reflection: false)
- .last(200)
+ results =
+ TopicLink
+ .includes(:post, :user)
+ .joins(:post, :user)
+ .where("posts.id IS NOT NULL AND users.id IS NOT NULL")
+ .where(topic_id: topic.id, reflection: false)
+ .last(200)
lookup = {}
results.each do |tl|
- normalized = tl.url.downcase.sub(/^https?:\/\//, '').sub(/\/$/, '')
- lookup[normalized] = { domain: tl.domain,
- username: tl.user.username_lower,
- posted_at: tl.post.created_at,
- post_number: tl.post.post_number }
+ normalized = tl.url.downcase.sub(%r{^https?://}, "").sub(%r{/$}, "")
+ lookup[normalized] = {
+ domain: tl.domain,
+ username: tl.user.username_lower,
+ posted_at: tl.post.created_at,
+ post_number: tl.post.post_number,
+ }
end
lookup
@@ -199,7 +213,6 @@ class TopicLink < ActiveRecord::Base
extension: nil,
reflection: false
)
-
domain ||= Discourse.current_hostname
sql = <<~SQL
@@ -242,26 +255,24 @@ class TopicLink < ActiveRecord::Base
), (SELECT id FROM new_row) IS NOT NULL
SQL
- topic_link_id, new_record = DB.query_single(sql,
- post_id: post_id,
- user_id: user_id,
- topic_id: topic_id,
- url: url,
- domain: domain,
- internal: internal,
- link_topic_id: link_topic_id,
- link_post_id: link_post_id,
- quote: quote,
- extension: extension,
- reflection: reflection,
- now: Time.now
- )
+ topic_link_id, new_record =
+ DB.query_single(
+ sql,
+ post_id: post_id,
+ user_id: user_id,
+ topic_id: topic_id,
+ url: url,
+ domain: domain,
+ internal: internal,
+ link_topic_id: link_topic_id,
+ link_post_id: link_post_id,
+ quote: quote,
+ extension: extension,
+ reflection: reflection,
+ now: Time.now,
+ )
- if new_record
- DB.after_commit do
- crawl_link_title(topic_link_id)
- end
- end
+ DB.after_commit { crawl_link_title(topic_link_id) } if new_record
topic_link_id
end
@@ -314,7 +325,8 @@ class TopicLink < ActiveRecord::Base
url = url[0...TopicLink.max_url_length]
return nil if parsed && parsed.host && parsed.host.length > TopicLink.max_domain_length
- file_extension = File.extname(parsed.path)[1..10].downcase unless parsed.path.nil? || File.extname(parsed.path).empty?
+ file_extension = File.extname(parsed.path)[1..10].downcase unless parsed.path.nil? ||
+ File.extname(parsed.path).empty?
safe_create_topic_link(
post_id: post.id,
@@ -332,22 +344,23 @@ class TopicLink < ActiveRecord::Base
reflected_id = nil
# Create the reflection if we can
- if topic && post.topic && topic.archetype != 'private_message' && post.topic.archetype != 'private_message' && post.topic.visible?
+ if topic && post.topic && topic.archetype != "private_message" &&
+ post.topic.archetype != "private_message" && post.topic.visible?
prefix = Discourse.base_url_no_prefix
reflected_url = "#{prefix}#{post.topic.relative_url(post.post_number)}"
- reflected_id = safe_create_topic_link(
- user_id: post.user_id,
- topic_id: topic&.id,
- post_id: reflected_post&.id,
- url: reflected_url,
- domain: Discourse.current_hostname,
- reflection: true,
- internal: true,
- link_topic_id: post.topic_id,
- link_post_id: post.id
- )
-
+ reflected_id =
+ safe_create_topic_link(
+ user_id: post.user_id,
+ topic_id: topic&.id,
+ post_id: reflected_post&.id,
+ url: reflected_url,
+ domain: Discourse.current_hostname,
+ reflection: true,
+ internal: true,
+ link_topic_id: post.topic_id,
+ link_post_id: post.id,
+ )
end
[url, reflected_id]
@@ -358,27 +371,25 @@ class TopicLink < ActiveRecord::Base
if current_urls.present?
TopicLink.where(
"(url not in (:urls)) AND (post_id = :post_id AND NOT reflection)",
- urls: current_urls, post_id: post.id
+ urls: current_urls,
+ post_id: post.id,
).delete_all
current_reflected_ids.compact!
if current_reflected_ids.present?
TopicLink.where(
"(id not in (:reflected_ids)) AND (link_post_id = :post_id AND reflection)",
- reflected_ids: current_reflected_ids, post_id: post.id
+ reflected_ids: current_reflected_ids,
+ post_id: post.id,
).delete_all
else
- TopicLink
- .where("link_post_id = :post_id AND reflection", post_id: post.id)
- .delete_all
+ TopicLink.where("link_post_id = :post_id AND reflection", post_id: post.id).delete_all
end
else
- TopicLink
- .where(
- "(post_id = :post_id AND NOT reflection) OR (link_post_id = :post_id AND reflection)",
- post_id: post.id
- )
- .delete_all
+ TopicLink.where(
+ "(post_id = :post_id AND NOT reflection) OR (link_post_id = :post_id AND reflection)",
+ post_id: post.id,
+ ).delete_all
end
end
end
diff --git a/app/models/topic_link_click.rb b/app/models/topic_link_click.rb
index 8770567997d..a1f121ee844 100644
--- a/app/models/topic_link_click.rb
+++ b/app/models/topic_link_click.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'ipaddr'
-require 'url_helper'
+require "ipaddr"
+require "url_helper"
class TopicLinkClick < ActiveRecord::Base
belongs_to :topic_link, counter_cache: :clicks
@@ -9,9 +9,9 @@ class TopicLinkClick < ActiveRecord::Base
validates_presence_of :topic_link_id
- ALLOWED_REDIRECT_HOSTNAMES = Set.new(%W{www.youtube.com youtu.be})
+ ALLOWED_REDIRECT_HOSTNAMES = Set.new(%W[www.youtube.com youtu.be])
include ActiveSupport::Deprecation::DeprecatedConstantAccessor
- deprecate_constant 'WHITELISTED_REDIRECT_HOSTNAMES', 'TopicLinkClick::ALLOWED_REDIRECT_HOSTNAMES'
+ deprecate_constant "WHITELISTED_REDIRECT_HOSTNAMES", "TopicLinkClick::ALLOWED_REDIRECT_HOSTNAMES"
# Create a click from a URL and post_id
def self.create_from(args = {})
@@ -22,32 +22,33 @@ class TopicLinkClick < ActiveRecord::Base
urls = Set.new
urls << url
if url =~ /^http/
- urls << url.sub(/^https/, 'http')
- urls << url.sub(/^http:/, 'https:')
+ urls << url.sub(/^https/, "http")
+ urls << url.sub(/^http:/, "https:")
urls << UrlHelper.schemaless(url)
end
urls << UrlHelper.absolute_without_cdn(url)
urls << uri.path if uri.try(:host) == Discourse.current_hostname
- query = url.index('?')
+ query = url.index("?")
unless query.nil?
- endpos = url.index('#') || url.size
+ endpos = url.index("#") || url.size
urls << url[0..query - 1] + url[endpos..-1]
end
# link can have query params, and analytics can add more to the end:
i = url.length
- while i = url.rindex('&', i - 1)
+ while i = url.rindex("&", i - 1)
urls << url[0...i]
end
# add a cdn link
if uri
if Discourse.asset_host.present?
- cdn_uri = begin
- URI.parse(Discourse.asset_host)
- rescue URI::Error
- end
+ cdn_uri =
+ begin
+ URI.parse(Discourse.asset_host)
+ rescue URI::Error
+ end
if cdn_uri && cdn_uri.hostname == uri.hostname && uri.path.starts_with?(cdn_uri.path)
is_cdn_link = true
@@ -56,10 +57,11 @@ class TopicLinkClick < ActiveRecord::Base
end
if SiteSetting.Upload.s3_cdn_url.present?
- cdn_uri = begin
- URI.parse(SiteSetting.Upload.s3_cdn_url)
- rescue URI::Error
- end
+ cdn_uri =
+ begin
+ URI.parse(SiteSetting.Upload.s3_cdn_url)
+ rescue URI::Error
+ end
if cdn_uri && cdn_uri.hostname == uri.hostname && uri.path.starts_with?(cdn_uri.path)
is_cdn_link = true
@@ -80,12 +82,15 @@ class TopicLinkClick < ActiveRecord::Base
link = link.where(topic_id: args[:topic_id]) if args[:topic_id].present?
# select the TopicLink associated to first url
- link = link.order("array_position(ARRAY[#{urls.map { |s| "#{ActiveRecord::Base.connection.quote(s)}" }.join(',')}], url::text)").first
+ link =
+ link.order(
+ "array_position(ARRAY[#{urls.map { |s| "#{ActiveRecord::Base.connection.quote(s)}" }.join(",")}], url::text)",
+ ).first
# If no link is found...
unless link.present?
# ... return the url for relative links or when using the same host
- return url if url =~ /^\/[^\/]/ || uri.try(:host) == Discourse.current_hostname
+ return url if url =~ %r{^/[^/]} || uri.try(:host) == Discourse.current_hostname
# If we have it somewhere else on the site, just allow the redirect.
# This is likely due to a onebox of another topic.
@@ -112,7 +117,6 @@ class TopicLinkClick < ActiveRecord::Base
url
end
-
end
# == Schema Information
diff --git a/app/models/topic_list.rb b/app/models/topic_list.rb
index 815e9c23085..b4be8c367fd 100644
--- a/app/models/topic_list.rb
+++ b/app/models/topic_list.rb
@@ -13,16 +13,12 @@ class TopicList
def self.cancel_preload(&blk)
if @preload
@preload.delete blk
- if @preload.length == 0
- @preload = nil
- end
+ @preload = nil if @preload.length == 0
end
end
def self.preload(topics, object)
- if @preload
- @preload.each { |preload| preload.call(topics, object) }
- end
+ @preload.each { |preload| preload.call(topics, object) } if @preload
end
def self.on_preload_user_ids(&blk)
@@ -49,7 +45,7 @@ class TopicList
:tags,
:shared_drafts,
:category,
- :publish_read_state
+ :publish_read_state,
)
def initialize(filter, current_user, topics, opts = nil)
@@ -58,13 +54,9 @@ class TopicList
@topics_input = topics
@opts = opts || {}
- if @opts[:category]
- @category = Category.find_by(id: @opts[:category_id])
- end
+ @category = Category.find_by(id: @opts[:category_id]) if @opts[:category]
- if @opts[:tags]
- @tags = Tag.where(id: @opts[:tags]).all
- end
+ @tags = Tag.where(id: @opts[:tags]).all if @opts[:tags]
@publish_read_state = !!@opts[:publish_read_state]
end
@@ -89,19 +81,19 @@ class TopicList
# Attach some data for serialization to each topic
@topic_lookup = TopicUser.lookup_for(@current_user, @topics) if @current_user
- @dismissed_topic_users_lookup = DismissedTopicUser.lookup_for(@current_user, @topics) if @current_user
+ @dismissed_topic_users_lookup =
+ DismissedTopicUser.lookup_for(@current_user, @topics) if @current_user
post_action_type =
if @current_user
if @opts[:filter].present?
- if @opts[:filter] == "liked"
- PostActionType.types[:like]
- end
+ PostActionType.types[:like] if @opts[:filter] == "liked"
end
end
# Data for bookmarks or likes
- post_action_lookup = PostAction.lookup_for(@current_user, @topics, post_action_type) if post_action_type
+ post_action_lookup =
+ PostAction.lookup_for(@current_user, @topics, post_action_type) if post_action_type
# Create a lookup for all the user ids we need
user_ids = []
@@ -125,23 +117,19 @@ class TopicList
ft.user_data.post_action_data = { post_action_type => actions }
end
- ft.posters = ft.posters_summary(
- user_lookup: user_lookup
- )
+ ft.posters = ft.posters_summary(user_lookup: user_lookup)
- ft.participants = ft.participants_summary(
- user_lookup: user_lookup,
- user: @current_user
- )
+ ft.participants = ft.participants_summary(user_lookup: user_lookup, user: @current_user)
ft.topic_list = self
end
topic_preloader_associations = [:image_upload, { topic_thumbnails: :optimized_image }]
topic_preloader_associations.concat(DiscoursePluginRegistry.topic_preloader_associations.to_a)
- ActiveRecord::Associations::Preloader
- .new(records: @topics, associations: topic_preloader_associations)
- .call
+ ActiveRecord::Associations::Preloader.new(
+ records: @topics,
+ associations: topic_preloader_associations,
+ ).call
if preloaded_custom_fields.present?
Topic.preload_custom_fields(@topics, preloaded_custom_fields)
@@ -153,18 +141,19 @@ class TopicList
end
def attributes
- { 'more_topics_url' => page }
+ { "more_topics_url" => page }
end
private
def category_user_lookup
- @category_user_lookup ||= begin
- if @current_user
- CategoryUser.lookup_for(@current_user, @topics.map(&:category_id).uniq)
- else
- []
+ @category_user_lookup ||=
+ begin
+ if @current_user
+ CategoryUser.lookup_for(@current_user, @topics.map(&:category_id).uniq)
+ else
+ []
+ end
end
- end
end
end
diff --git a/app/models/topic_notifier.rb b/app/models/topic_notifier.rb
index 2bcc6beb1c0..d733698d3d5 100644
--- a/app/models/topic_notifier.rb
+++ b/app/models/topic_notifier.rb
@@ -5,15 +5,15 @@ class TopicNotifier
@topic = topic
end
- { watch!: :watching,
+ {
+ watch!: :watching,
track!: :tracking,
regular!: :regular,
- mute!: :muted }.each_pair do |method_name, level|
-
+ mute!: :muted,
+ }.each_pair do |method_name, level|
define_method method_name do |user_id|
change_level user_id, level
end
-
end
def watch_topic!(user_id, reason = :created_topic)
diff --git a/app/models/topic_participants_summary.rb b/app/models/topic_participants_summary.rb
index ba365075228..8f098bd84cc 100644
--- a/app/models/topic_participants_summary.rb
+++ b/app/models/topic_participants_summary.rb
@@ -18,7 +18,7 @@ class TopicParticipantsSummary
def new_topic_poster_for(user)
TopicPoster.new.tap do |topic_poster|
topic_poster.user = user
- topic_poster.extras = 'latest' if is_latest_poster?(user)
+ topic_poster.extras = "latest" if is_latest_poster?(user)
end
end
diff --git a/app/models/topic_poster.rb b/app/models/topic_poster.rb
index 762734799c2..99d8e3741d9 100644
--- a/app/models/topic_poster.rb
+++ b/app/models/topic_poster.rb
@@ -7,11 +7,11 @@ class TopicPoster < OpenStruct
def attributes
{
- 'user' => user,
- 'description' => description,
- 'extras' => extras,
- 'id' => id,
- 'primary_group' => primary_group
+ "user" => user,
+ "description" => description,
+ "extras" => extras,
+ "id" => id,
+ "primary_group" => primary_group,
}
end
diff --git a/app/models/topic_posters_summary.rb b/app/models/topic_posters_summary.rb
index cded3ebbce8..abf47658ef9 100644
--- a/app/models/topic_posters_summary.rb
+++ b/app/models/topic_posters_summary.rb
@@ -2,7 +2,6 @@
# This is used in topic lists
class TopicPostersSummary
-
# localization is fast, but this allows us to avoid
# calling it in a loop which adds up
def self.translations
@@ -10,7 +9,7 @@ class TopicPostersSummary
original_poster: I18n.t(:original_poster),
most_recent_poster: I18n.t(:most_recent_poster),
frequent_poster: I18n.t(:frequent_poster),
- joiner: I18n.t(:poster_description_joiner)
+ joiner: I18n.t(:poster_description_joiner),
}
end
@@ -35,34 +34,35 @@ class TopicPostersSummary
topic_poster.primary_group = user_lookup.primary_groups[user.id]
topic_poster.flair_group = user_lookup.flair_groups[user.id]
if topic.last_post_user_id == user.id
- topic_poster.extras = +'latest'
- topic_poster.extras << ' single' if user_ids.uniq.size == 1
+ topic_poster.extras = +"latest"
+ topic_poster.extras << " single" if user_ids.uniq.size == 1
end
topic_poster
end
def descriptions_by_id(ids: nil)
- @descriptions_by_id ||= begin
- result = {}
- ids = ids || user_ids
+ @descriptions_by_id ||=
+ begin
+ result = {}
+ ids = ids || user_ids
- if id = ids.shift
- result[id] ||= []
- result[id] << @translations[:original_poster]
+ if id = ids.shift
+ result[id] ||= []
+ result[id] << @translations[:original_poster]
+ end
+
+ if id = ids.shift
+ result[id] ||= []
+ result[id] << @translations[:most_recent_poster]
+ end
+
+ while id = ids.shift
+ result[id] ||= []
+ result[id] << @translations[:frequent_poster]
+ end
+
+ result
end
-
- if id = ids.shift
- result[id] ||= []
- result[id] << @translations[:most_recent_poster]
- end
-
- while id = ids.shift
- result[id] ||= []
- result[id] << @translations[:frequent_poster]
- end
-
- result
- end
end
def descriptions_for(user)
@@ -90,7 +90,7 @@ class TopicPostersSummary
end
def user_ids
- [ topic.user_id, topic.last_post_user_id, *topic.featured_user_ids ]
+ [topic.user_id, topic.last_post_user_id, *topic.featured_user_ids]
end
def user_lookup
diff --git a/app/models/topic_tag.rb b/app/models/topic_tag.rb
index 60943b393ca..67a8218d94a 100644
--- a/app/models/topic_tag.rb
+++ b/app/models/topic_tag.rb
@@ -27,7 +27,8 @@ class TopicTag < ActiveRecord::Base
if topic.archetype == Archetype.private_message
tag.decrement!(:pm_topic_count)
else
- if topic.category_id && stat = CategoryTagStat.find_by(tag_id: tag_id, category: topic.category_id)
+ if topic.category_id &&
+ stat = CategoryTagStat.find_by(tag_id: tag_id, category: topic.category_id)
stat.topic_count == 1 ? stat.destroy : stat.decrement!(:topic_count)
end
diff --git a/app/models/topic_thumbnail.rb b/app/models/topic_thumbnail.rb
index f12161510f0..7800e4ed0b6 100644
--- a/app/models/topic_thumbnail.rb
+++ b/app/models/topic_thumbnail.rb
@@ -10,30 +10,34 @@ class TopicThumbnail < ActiveRecord::Base
belongs_to :upload
belongs_to :optimized_image
- def self.find_or_create_for!(original, max_width: , max_height:)
- existing = TopicThumbnail.find_by(upload: original, max_width: max_width, max_height: max_height)
+ def self.find_or_create_for!(original, max_width:, max_height:)
+ existing =
+ TopicThumbnail.find_by(upload: original, max_width: max_width, max_height: max_height)
return existing if existing
return nil if !SiteSetting.create_thumbnails?
- target_width, target_height = ImageSizer.resize(original.width, original.height, { max_width: max_width, max_height: max_height })
+ target_width, target_height =
+ ImageSizer.resize(
+ original.width,
+ original.height,
+ { max_width: max_width, max_height: max_height },
+ )
if target_width < original.width && target_height < original.height
optimized = OptimizedImage.create_for(original, target_width, target_height)
end
# may have been associated already, bulk insert will skip dupes
- TopicThumbnail.insert_all([
- upload_id: original.id,
- max_width: max_width,
- max_height: max_height,
- optimized_image_id: optimized&.id
- ])
-
- TopicThumbnail.find_by(
- upload: original,
- max_width: max_width,
- max_height: max_height
+ TopicThumbnail.insert_all(
+ [
+ upload_id: original.id,
+ max_width: max_width,
+ max_height: max_height,
+ optimized_image_id: optimized&.id,
+ ],
)
+
+ TopicThumbnail.find_by(upload: original, max_width: max_width, max_height: max_height)
end
def self.ensure_consistency!
@@ -48,8 +52,11 @@ class TopicThumbnail < ActiveRecord::Base
.delete_all
# Delete records for sizes which are no longer needed
- sizes = Topic.thumbnail_sizes + ThemeModifierHelper.new(theme_ids: Theme.pluck(:id)).topic_thumbnail_sizes
- sizes_sql = sizes.map { |s| "(max_width = #{s[0].to_i} AND max_height = #{s[1].to_i})" }.join(" OR ")
+ sizes =
+ Topic.thumbnail_sizes +
+ ThemeModifierHelper.new(theme_ids: Theme.pluck(:id)).topic_thumbnail_sizes
+ sizes_sql =
+ sizes.map { |s| "(max_width = #{s[0].to_i} AND max_height = #{s[1].to_i})" }.join(" OR ")
TopicThumbnail.where.not(sizes_sql).delete_all
end
end
diff --git a/app/models/topic_timer.rb b/app/models/topic_timer.rb
index 82a00e8dc3c..22abd8b3c96 100644
--- a/app/models/topic_timer.rb
+++ b/app/models/topic_timer.rb
@@ -13,25 +13,26 @@ class TopicTimer < ActiveRecord::Base
validates :topic_id, presence: true
validates :execute_at, presence: true
validates :status_type, presence: true
- validates :status_type, uniqueness: { scope: [:topic_id, :deleted_at] }, if: :public_type?
- validates :status_type, uniqueness: { scope: [:topic_id, :deleted_at, :user_id] }, if: :private_type?
+ validates :status_type, uniqueness: { scope: %i[topic_id deleted_at] }, if: :public_type?
+ validates :status_type, uniqueness: { scope: %i[topic_id deleted_at user_id] }, if: :private_type?
validates :category_id, presence: true, if: :publishing_to_category?
validate :executed_at_in_future?
validate :duration_in_range?
- scope :scheduled_bump_topics, -> { where(status_type: TopicTimer.types[:bump], deleted_at: nil).pluck(:topic_id) }
- scope :pending_timers, ->(before_time = Time.now.utc) do
- where("execute_at <= :before_time AND deleted_at IS NULL", before_time: before_time)
- end
+ scope :scheduled_bump_topics,
+ -> { where(status_type: TopicTimer.types[:bump], deleted_at: nil).pluck(:topic_id) }
+ scope :pending_timers,
+ ->(before_time = Time.now.utc) {
+ where("execute_at <= :before_time AND deleted_at IS NULL", before_time: before_time)
+ }
before_save do
self.created_at ||= Time.zone.now if execute_at
self.public_type = self.public_type?
- if (will_save_change_to_execute_at? &&
- !attribute_in_database(:execute_at).nil?) ||
- will_save_change_to_user_id?
+ if (will_save_change_to_execute_at? && !attribute_in_database(:execute_at).nil?) ||
+ will_save_change_to_user_id?
end
end
@@ -46,10 +47,10 @@ class TopicTimer < ActiveRecord::Base
after_save do
if (saved_change_to_execute_at? || saved_change_to_user_id?)
if status_type == TopicTimer.types[:silent_close] || status_type == TopicTimer.types[:close]
- topic.update_status('closed', false, user) if topic.closed?
+ topic.update_status("closed", false, user) if topic.closed?
end
if status_type == TopicTimer.types[:open]
- topic.update_status('closed', true, user) if topic.open?
+ topic.update_status("closed", true, user) if topic.open?
end
end
end
@@ -72,22 +73,23 @@ class TopicTimer < ActiveRecord::Base
bump: :bump_topic,
delete_replies: :delete_replies,
silent_close: :close_topic,
- clear_slow_mode: :clear_slow_mode
+ clear_slow_mode: :clear_slow_mode,
}
end
def self.types
- @types ||= Enum.new(
- close: 1,
- open: 2,
- publish_to_category: 3,
- delete: 4,
- reminder: 5,
- bump: 6,
- delete_replies: 7,
- silent_close: 8,
- clear_slow_mode: 9
- )
+ @types ||=
+ Enum.new(
+ close: 1,
+ open: 2,
+ publish_to_category: 3,
+ delete: 4,
+ reminder: 5,
+ bump: 6,
+ delete_replies: 7,
+ silent_close: 8,
+ clear_slow_mode: 9,
+ )
end
def self.public_types
@@ -126,24 +128,29 @@ class TopicTimer < ActiveRecord::Base
return if duration_minutes.blank?
if duration_minutes.to_i <= 0
- errors.add(:duration_minutes, I18n.t(
- 'activerecord.errors.models.topic_timer.attributes.duration_minutes.cannot_be_zero'
- ))
+ errors.add(
+ :duration_minutes,
+ I18n.t("activerecord.errors.models.topic_timer.attributes.duration_minutes.cannot_be_zero"),
+ )
end
if duration_minutes.to_i > MAX_DURATION_MINUTES
- errors.add(:duration_minutes, I18n.t(
- 'activerecord.errors.models.topic_timer.attributes.duration_minutes.exceeds_maximum'
- ))
+ errors.add(
+ :duration_minutes,
+ I18n.t(
+ "activerecord.errors.models.topic_timer.attributes.duration_minutes.exceeds_maximum",
+ ),
+ )
end
end
def executed_at_in_future?
return if created_at.blank? || (execute_at > created_at)
- errors.add(:execute_at, I18n.t(
- 'activerecord.errors.models.topic_timer.attributes.execute_at.in_the_past'
- ))
+ errors.add(
+ :execute_at,
+ I18n.t("activerecord.errors.models.topic_timer.attributes.execute_at.in_the_past"),
+ )
end
def schedule_auto_delete_replies_job
diff --git a/app/models/topic_tracking_state.rb b/app/models/topic_tracking_state.rb
index 65bf2fa59ca..038f7ba7eb2 100644
--- a/app/models/topic_tracking_state.rb
+++ b/app/models/topic_tracking_state.rb
@@ -35,9 +35,7 @@ class TopicTrackingState
return unless topic.regular?
tag_ids, tags = nil
- if SiteSetting.tagging_enabled
- tag_ids, tags = topic.tags.pluck(:id, :name).transpose
- end
+ tag_ids, tags = topic.tags.pluck(:id, :name).transpose if SiteSetting.tagging_enabled
payload = {
last_read_post_number: nil,
@@ -45,7 +43,7 @@ class TopicTrackingState
created_at: topic.created_at,
category_id: topic.category_id,
archetype: topic.archetype,
- created_in_new_period: true
+ created_in_new_period: true,
}
if tags
@@ -53,11 +51,7 @@ class TopicTrackingState
payload[:topic_tag_ids] = tag_ids
end
- message = {
- topic_id: topic.id,
- message_type: NEW_TOPIC_MESSAGE_TYPE,
- payload: payload
- }
+ message = { topic_id: topic.id, message_type: NEW_TOPIC_MESSAGE_TYPE, payload: payload }
group_ids = topic.category && topic.category.secure_group_ids
@@ -69,9 +63,7 @@ class TopicTrackingState
return unless topic.regular?
tag_ids, tags = nil
- if SiteSetting.tagging_enabled
- tag_ids, tags = topic.tags.pluck(:id, :name).transpose
- end
+ tag_ids, tags = topic.tags.pluck(:id, :name).transpose if SiteSetting.tagging_enabled
message = {
topic_id: topic.id,
@@ -79,8 +71,8 @@ class TopicTrackingState
payload: {
bumped_at: topic.bumped_at,
category_id: topic.category_id,
- archetype: topic.archetype
- }
+ archetype: topic.archetype,
+ },
}
if tags
@@ -102,32 +94,30 @@ class TopicTrackingState
end
def self.publish_muted(topic)
- user_ids = topic.topic_users
- .where(notification_level: NotificationLevels.all[:muted])
- .joins(:user)
- .where("users.last_seen_at > ?", 7.days.ago)
- .order("users.last_seen_at DESC")
- .limit(100)
- .pluck(:user_id)
+ user_ids =
+ topic
+ .topic_users
+ .where(notification_level: NotificationLevels.all[:muted])
+ .joins(:user)
+ .where("users.last_seen_at > ?", 7.days.ago)
+ .order("users.last_seen_at DESC")
+ .limit(100)
+ .pluck(:user_id)
return if user_ids.blank?
- message = {
- topic_id: topic.id,
- message_type: MUTED_MESSAGE_TYPE,
- }
+ message = { topic_id: topic.id, message_type: MUTED_MESSAGE_TYPE }
MessageBus.publish("/latest", message.as_json, user_ids: user_ids)
end
def self.publish_unmuted(topic)
- user_ids = User.watching_topic(topic)
- .where("users.last_seen_at > ?", 7.days.ago)
- .order("users.last_seen_at DESC")
- .limit(100)
- .pluck(:id)
+ user_ids =
+ User
+ .watching_topic(topic)
+ .where("users.last_seen_at > ?", 7.days.ago)
+ .order("users.last_seen_at DESC")
+ .limit(100)
+ .pluck(:id)
return if user_ids.blank?
- message = {
- topic_id: topic.id,
- message_type: UNMUTED_MESSAGE_TYPE,
- }
+ message = { topic_id: topic.id, message_type: UNMUTED_MESSAGE_TYPE }
MessageBus.publish("/latest", message.as_json, user_ids: user_ids)
end
@@ -137,16 +127,12 @@ class TopicTrackingState
# perhaps cut down to users that are around in the last 7 days as well
tags = nil
tag_ids = nil
- if include_tags_in_report?
- tag_ids, tags = post.topic.tags.pluck(:id, :name).transpose
- end
+ tag_ids, tags = post.topic.tags.pluck(:id, :name).transpose if include_tags_in_report?
# We don't need to publish unread to the person who just made the post,
# this is why they are excluded from the initial scope.
- scope = TopicUser
- .tracking(post.topic_id)
- .includes(user: :user_stat)
- .where.not(user_id: post.user_id)
+ scope =
+ TopicUser.tracking(post.topic_id).includes(user: :user_stat).where.not(user_id: post.user_id)
group_ids =
if post.post_type == Post.types[:whisper]
@@ -156,9 +142,11 @@ class TopicTrackingState
end
if group_ids.present?
- scope = scope
- .joins("INNER JOIN group_users gu ON gu.user_id = topic_users.user_id")
- .where("gu.group_id IN (?)", group_ids)
+ scope =
+ scope.joins("INNER JOIN group_users gu ON gu.user_id = topic_users.user_id").where(
+ "gu.group_id IN (?)",
+ group_ids,
+ )
end
user_ids = scope.pluck(:user_id)
@@ -177,36 +165,23 @@ class TopicTrackingState
payload[:topic_tag_ids] = tag_ids
end
- message = {
- topic_id: post.topic_id,
- message_type: UNREAD_MESSAGE_TYPE,
- payload: payload
- }
+ message = { topic_id: post.topic_id, message_type: UNREAD_MESSAGE_TYPE, payload: payload }
- MessageBus.publish("/unread", message.as_json,
- user_ids: user_ids
- )
+ MessageBus.publish("/unread", message.as_json, user_ids: user_ids)
end
def self.publish_recover(topic)
group_ids = topic.category && topic.category.secure_group_ids
- message = {
- topic_id: topic.id,
- message_type: RECOVER_MESSAGE_TYPE
- }
+ message = { topic_id: topic.id, message_type: RECOVER_MESSAGE_TYPE }
MessageBus.publish("/recover", message.as_json, group_ids: group_ids)
-
end
def self.publish_delete(topic)
group_ids = topic.category && topic.category.secure_group_ids
- message = {
- topic_id: topic.id,
- message_type: DELETE_MESSAGE_TYPE
- }
+ message = { topic_id: topic.id, message_type: DELETE_MESSAGE_TYPE }
MessageBus.publish("/delete", message.as_json, group_ids: group_ids)
end
@@ -214,10 +189,7 @@ class TopicTrackingState
def self.publish_destroy(topic)
group_ids = topic.category && topic.category.secure_group_ids
- message = {
- topic_id: topic.id,
- message_type: DESTROY_MESSAGE_TYPE
- }
+ message = { topic_id: topic.id, message_type: DESTROY_MESSAGE_TYPE }
MessageBus.publish("/destroy", message.as_json, group_ids: group_ids)
end
@@ -229,25 +201,21 @@ class TopicTrackingState
topic_id: topic_id,
user: user,
last_read_post_number: last_read_post_number,
- notification_level: notification_level
+ notification_level: notification_level,
)
end
def self.publish_dismiss_new(user_id, topic_ids: [])
- message = {
- message_type: DISMISS_NEW_MESSAGE_TYPE,
- payload: {
- topic_ids: topic_ids
- }
- }
+ message = { message_type: DISMISS_NEW_MESSAGE_TYPE, payload: { topic_ids: topic_ids } }
MessageBus.publish(self.unread_channel_key(user_id), message.as_json, user_ids: [user_id])
end
def self.new_filter_sql
- TopicQuery.new_filter(
- Topic, treat_as_new_topic_clause_sql: treat_as_new_topic_clause
- ).where_clause.ast.to_sql +
- " AND topics.created_at > :min_new_topic_date" +
+ TopicQuery
+ .new_filter(Topic, treat_as_new_topic_clause_sql: treat_as_new_topic_clause)
+ .where_clause
+ .ast
+ .to_sql + " AND topics.created_at > :min_new_topic_date" +
" AND dismissed_topic_users.id IS NULL"
end
@@ -256,13 +224,18 @@ class TopicTrackingState
end
def self.treat_as_new_topic_clause
- User.where("GREATEST(CASE
+ User
+ .where(
+ "GREATEST(CASE
WHEN COALESCE(uo.new_topic_duration_minutes, :default_duration) = :always THEN u.created_at
WHEN COALESCE(uo.new_topic_duration_minutes, :default_duration) = :last_visit THEN COALESCE(u.previous_visit_at,u.created_at)
ELSE (:now::timestamp - INTERVAL '1 MINUTE' * COALESCE(uo.new_topic_duration_minutes, :default_duration))
END, u.created_at, :min_date)",
- treat_as_new_topic_params
- ).where_clause.ast.to_sql
+ treat_as_new_topic_params,
+ )
+ .where_clause
+ .ast
+ .to_sql
end
def self.treat_as_new_topic_params
@@ -271,7 +244,7 @@ class TopicTrackingState
last_visit: User::NewTopicDuration::LAST_VISIT,
always: User::NewTopicDuration::ALWAYS,
default_duration: SiteSetting.default_other_new_topic_duration_minutes,
- min_date: Time.at(SiteSetting.min_new_topics_time).to_datetime
+ min_date: Time.at(SiteSetting.min_new_topics_time).to_datetime,
}
end
@@ -296,31 +269,32 @@ class TopicTrackingState
sql = new_and_unread_sql(topic_id, user, tag_ids)
sql = tags_included_wrapped_sql(sql)
- report = DB.query(
- sql + "\n\n LIMIT :max_topics",
- {
- user_id: user.id,
- topic_id: topic_id,
- min_new_topic_date: Time.at(SiteSetting.min_new_topics_time).to_datetime,
- max_topics: TopicTrackingState::MAX_TOPICS,
- }
- .merge(treat_as_new_topic_params)
- )
+ report =
+ DB.query(
+ sql + "\n\n LIMIT :max_topics",
+ {
+ user_id: user.id,
+ topic_id: topic_id,
+ min_new_topic_date: Time.at(SiteSetting.min_new_topics_time).to_datetime,
+ max_topics: TopicTrackingState::MAX_TOPICS,
+ }.merge(treat_as_new_topic_params),
+ )
report
end
def self.new_and_unread_sql(topic_id, user, tag_ids)
- sql = report_raw_sql(
- topic_id: topic_id,
- skip_unread: true,
- skip_order: true,
- staff: user.staff?,
- admin: user.admin?,
- whisperer: user.whisperer?,
- user: user,
- muted_tag_ids: tag_ids
- )
+ sql =
+ report_raw_sql(
+ topic_id: topic_id,
+ skip_unread: true,
+ skip_order: true,
+ staff: user.staff?,
+ admin: user.admin?,
+ whisperer: user.whisperer?,
+ user: user,
+ muted_tag_ids: tag_ids,
+ )
sql << "\nUNION ALL\n\n"
@@ -333,13 +307,12 @@ class TopicTrackingState
admin: user.admin?,
whisperer: user.whisperer?,
user: user,
- muted_tag_ids: tag_ids
+ muted_tag_ids: tag_ids,
)
end
def self.tags_included_wrapped_sql(sql)
- if SiteSetting.tagging_enabled && TopicTrackingState.include_tags_in_report?
- return <<~SQL
+ return <<~SQL if SiteSetting.tagging_enabled && TopicTrackingState.include_tags_in_report?
WITH tags_included_cte AS (
#{sql}
)
@@ -350,7 +323,6 @@ class TopicTrackingState
) tags
FROM tags_included_cte
SQL
- end
sql
end
@@ -395,7 +367,9 @@ class TopicTrackingState
new_filter_sql
end
- select_sql = select || "
+ select_sql =
+ select ||
+ "
DISTINCT topics.id as topic_id,
u.id as user_id,
topics.created_at,
@@ -441,11 +415,13 @@ class TopicTrackingState
tags_filter = ""
- if muted_tag_ids.present? && ['always', 'only_muted'].include?(SiteSetting.remove_muted_tags_from_latest)
- existing_tags_sql = "(select array_agg(tag_id) from topic_tags where topic_tags.topic_id = topics.id)"
- muted_tags_array_sql = "ARRAY[#{muted_tag_ids.join(',')}]"
+ if muted_tag_ids.present? &&
+ %w[always only_muted].include?(SiteSetting.remove_muted_tags_from_latest)
+ existing_tags_sql =
+ "(select array_agg(tag_id) from topic_tags where topic_tags.topic_id = topics.id)"
+ muted_tags_array_sql = "ARRAY[#{muted_tag_ids.join(",")}]"
- if SiteSetting.remove_muted_tags_from_latest == 'always'
+ if SiteSetting.remove_muted_tags_from_latest == "always"
tags_filter = <<~SQL
NOT (
COALESCE(#{existing_tags_sql}, ARRAY[]::int[]) && #{muted_tags_array_sql}
@@ -487,13 +463,9 @@ class TopicTrackingState
)
SQL
- if topic_id
- sql << " AND topics.id = :topic_id"
- end
+ sql << " AND topics.id = :topic_id" if topic_id
- unless skip_order
- sql << " ORDER BY topics.bumped_at DESC"
- end
+ sql << " ORDER BY topics.bumped_at DESC" unless skip_order
sql
end
@@ -503,7 +475,11 @@ class TopicTrackingState
end
def self.publish_read_indicator_on_write(topic_id, last_read_post_number, user_id)
- topic = Topic.includes(:allowed_groups).select(:highest_post_number, :archetype, :id).find_by(id: topic_id)
+ topic =
+ Topic
+ .includes(:allowed_groups)
+ .select(:highest_post_number, :archetype, :id)
+ .find_by(id: topic_id)
if topic&.private_message?
groups = read_allowed_groups_of(topic)
@@ -512,7 +488,11 @@ class TopicTrackingState
end
def self.publish_read_indicator_on_read(topic_id, last_read_post_number, user_id)
- topic = Topic.includes(:allowed_groups).select(:highest_post_number, :archetype, :id).find_by(id: topic_id)
+ topic =
+ Topic
+ .includes(:allowed_groups)
+ .select(:highest_post_number, :archetype, :id)
+ .find_by(id: topic_id)
if topic&.private_message?
groups = read_allowed_groups_of(topic)
@@ -523,14 +503,21 @@ class TopicTrackingState
end
def self.read_allowed_groups_of(topic)
- topic.allowed_groups
+ topic
+ .allowed_groups
.joins(:group_users)
.where(publish_read_state: true)
- .select('ARRAY_AGG(group_users.user_id) AS members', :name, :id)
- .group('groups.id')
+ .select("ARRAY_AGG(group_users.user_id) AS members", :name, :id)
+ .group("groups.id")
end
- def self.update_topic_list_read_indicator(topic, groups, last_read_post_number, user_id, write_event)
+ def self.update_topic_list_read_indicator(
+ topic,
+ groups,
+ last_read_post_number,
+ user_id,
+ write_event
+ )
return unless last_read_post_number == topic.highest_post_number
message = { topic_id: topic.id, show_indicator: write_event }.as_json
groups_to_update = []
@@ -546,7 +533,11 @@ class TopicTrackingState
end
return if groups_to_update.empty?
- MessageBus.publish("/private-messages/unread-indicator/#{topic.id}", message, user_ids: groups_to_update.flat_map(&:members))
+ MessageBus.publish(
+ "/private-messages/unread-indicator/#{topic.id}",
+ message,
+ user_ids: groups_to_update.flat_map(&:members),
+ )
end
def self.trigger_post_read_count_update(post, groups, last_read_post_number, user_id)
diff --git a/app/models/topic_user.rb b/app/models/topic_user.rb
index 638fa4f891c..0e00f68f2de 100644
--- a/app/models/topic_user.rb
+++ b/app/models/topic_user.rb
@@ -2,7 +2,7 @@
class TopicUser < ActiveRecord::Base
self.ignored_columns = [
- :highest_seen_post_number # Remove after 01 Jan 2022
+ :highest_seen_post_number, # Remove after 01 Jan 2022
]
belongs_to :user
@@ -11,20 +11,18 @@ class TopicUser < ActiveRecord::Base
# used for serialization
attr_accessor :post_action_data
- scope :level, lambda { |topic_id, level|
- where(topic_id: topic_id)
- .where("COALESCE(topic_users.notification_level, :regular) >= :level",
- regular: TopicUser.notification_levels[:regular],
- level: TopicUser.notification_levels[level])
- }
+ scope :level,
+ lambda { |topic_id, level|
+ where(topic_id: topic_id).where(
+ "COALESCE(topic_users.notification_level, :regular) >= :level",
+ regular: TopicUser.notification_levels[:regular],
+ level: TopicUser.notification_levels[level],
+ )
+ }
- scope :tracking, lambda { |topic_id|
- level(topic_id, :tracking)
- }
+ scope :tracking, lambda { |topic_id| level(topic_id, :tracking) }
- scope :watching, lambda { |topic_id|
- level(topic_id, :watching)
- }
+ scope :watching, lambda { |topic_id| level(topic_id, :watching) }
def topic_bookmarks
Bookmark.where(topic: topic, user: user)
@@ -32,38 +30,62 @@ class TopicUser < ActiveRecord::Base
# Class methods
class << self
-
# Enums
def notification_levels
NotificationLevels.topic_levels
end
def notification_reasons
- @notification_reasons ||= Enum.new(created_topic: 1,
- user_changed: 2,
- user_interacted: 3,
- created_post: 4,
- auto_watch: 5,
- auto_watch_category: 6,
- auto_mute_category: 7,
- auto_track_category: 8,
- plugin_changed: 9,
- auto_watch_tag: 10,
- auto_mute_tag: 11,
- auto_track_tag: 12)
+ @notification_reasons ||=
+ Enum.new(
+ created_topic: 1,
+ user_changed: 2,
+ user_interacted: 3,
+ created_post: 4,
+ auto_watch: 5,
+ auto_watch_category: 6,
+ auto_mute_category: 7,
+ auto_track_category: 8,
+ plugin_changed: 9,
+ auto_watch_tag: 10,
+ auto_mute_tag: 11,
+ auto_track_tag: 12,
+ )
end
def auto_notification(user_id, topic_id, reason, notification_level)
- should_change = TopicUser
- .where(user_id: user_id, topic_id: topic_id)
- .where("notifications_reason_id IS NULL OR (notification_level < :max AND notification_level > :min)", max: notification_level, min: notification_levels[:regular])
- .exists?
+ should_change =
+ TopicUser
+ .where(user_id: user_id, topic_id: topic_id)
+ .where(
+ "notifications_reason_id IS NULL OR (notification_level < :max AND notification_level > :min)",
+ max: notification_level,
+ min: notification_levels[:regular],
+ )
+ .exists?
- change(user_id, topic_id, notification_level: notification_level, notifications_reason_id: reason) if should_change
+ if should_change
+ change(
+ user_id,
+ topic_id,
+ notification_level: notification_level,
+ notifications_reason_id: reason,
+ )
+ end
end
- def auto_notification_for_staging(user_id, topic_id, reason, notification_level = notification_levels[:watching])
- change(user_id, topic_id, notification_level: notification_level, notifications_reason_id: reason)
+ def auto_notification_for_staging(
+ user_id,
+ topic_id,
+ reason,
+ notification_level = notification_levels[:watching]
+ )
+ change(
+ user_id,
+ topic_id,
+ notification_level: notification_level,
+ notifications_reason_id: reason,
+ )
end
def unwatch_categories!(user, category_ids)
@@ -80,14 +102,15 @@ class TopicUser < ActiveRecord::Base
WHERE t.id = tu.topic_id AND tu.notification_level <> :muted AND category_id IN (:category_ids) AND tu.user_id = :user_id
SQL
- DB.exec(sql,
+ DB.exec(
+ sql,
watching: notification_levels[:watching],
tracking: notification_levels[:tracking],
regular: notification_levels[:regular],
muted: notification_levels[:muted],
category_ids: category_ids,
user_id: user.id,
- track_threshold: track_threshold
+ track_threshold: track_threshold,
)
end
@@ -119,9 +142,7 @@ class TopicUser < ActiveRecord::Base
# it then creates the row instead.
def change(user_id, topic_id, attrs)
# For plugin compatibility, remove after 01 Jan 2022
- if attrs[:highest_seen_post_number]
- attrs.delete(:highest_seen_post_number)
- end
+ attrs.delete(:highest_seen_post_number) if attrs[:highest_seen_post_number]
# Sometimes people pass objs instead of the ids. We can handle that.
topic_id = topic_id.id if topic_id.is_a?(::Topic)
@@ -143,15 +164,17 @@ class TopicUser < ActiveRecord::Base
rows = TopicUser.where(topic_id: topic_id, user_id: user_id).update_all([attrs_sql, *vals])
- if rows == 0
- create_missing_record(user_id, topic_id, attrs)
- end
+ create_missing_record(user_id, topic_id, attrs) if rows == 0
end
if attrs[:notification_level]
- notification_level_change(user_id, topic_id, attrs[:notification_level], attrs[:notifications_reason_id])
+ notification_level_change(
+ user_id,
+ topic_id,
+ attrs[:notification_level],
+ attrs[:notifications_reason_id],
+ )
end
-
rescue ActiveRecord::RecordNotUnique
# In case of a race condition to insert, do nothing
end
@@ -161,67 +184,90 @@ class TopicUser < ActiveRecord::Base
message[:notifications_reason_id] = reason_id if reason_id
MessageBus.publish("/topic/#{topic_id}", message, user_ids: [user_id])
- DiscourseEvent.trigger(:topic_notification_level_changed,
+ DiscourseEvent.trigger(
+ :topic_notification_level_changed,
notification_level,
user_id,
- topic_id
+ topic_id,
)
-
end
def create_missing_record(user_id, topic_id, attrs)
now = DateTime.now
unless attrs[:notification_level]
- category_notification_level = CategoryUser.where(user_id: user_id)
- .where("category_id IN (SELECT category_id FROM topics WHERE id = :id)", id: topic_id)
- .where("notification_level IN (:levels)", levels: [CategoryUser.notification_levels[:watching],
- CategoryUser.notification_levels[:tracking]])
- .order("notification_level DESC")
- .limit(1)
- .pluck(:notification_level)
- .first
+ category_notification_level =
+ CategoryUser
+ .where(user_id: user_id)
+ .where("category_id IN (SELECT category_id FROM topics WHERE id = :id)", id: topic_id)
+ .where(
+ "notification_level IN (:levels)",
+ levels: [
+ CategoryUser.notification_levels[:watching],
+ CategoryUser.notification_levels[:tracking],
+ ],
+ )
+ .order("notification_level DESC")
+ .limit(1)
+ .pluck(:notification_level)
+ .first
- tag_notification_level = TagUser.where(user_id: user_id)
- .where("tag_id IN (SELECT tag_id FROM topic_tags WHERE topic_id = :id)", id: topic_id)
- .where("notification_level IN (:levels)", levels: [CategoryUser.notification_levels[:watching],
- CategoryUser.notification_levels[:tracking]])
- .order("notification_level DESC")
- .limit(1)
- .pluck(:notification_level)
- .first
+ tag_notification_level =
+ TagUser
+ .where(user_id: user_id)
+ .where("tag_id IN (SELECT tag_id FROM topic_tags WHERE topic_id = :id)", id: topic_id)
+ .where(
+ "notification_level IN (:levels)",
+ levels: [
+ CategoryUser.notification_levels[:watching],
+ CategoryUser.notification_levels[:tracking],
+ ],
+ )
+ .order("notification_level DESC")
+ .limit(1)
+ .pluck(:notification_level)
+ .first
- if category_notification_level && !(tag_notification_level && (tag_notification_level > category_notification_level))
+ if category_notification_level &&
+ !(tag_notification_level && (tag_notification_level > category_notification_level))
attrs[:notification_level] = category_notification_level
attrs[:notifications_changed_at] = DateTime.now
- attrs[:notifications_reason_id] = category_notification_level == CategoryUser.notification_levels[:watching] ?
- TopicUser.notification_reasons[:auto_watch_category] :
+ attrs[:notifications_reason_id] = (
+ if category_notification_level == CategoryUser.notification_levels[:watching]
+ TopicUser.notification_reasons[:auto_watch_category]
+ else
TopicUser.notification_reasons[:auto_track_category]
-
+ end
+ )
elsif tag_notification_level
attrs[:notification_level] = tag_notification_level
attrs[:notifications_changed_at] = DateTime.now
- attrs[:notifications_reason_id] = tag_notification_level == TagUser.notification_levels[:watching] ?
- TopicUser.notification_reasons[:auto_watch_tag] :
+ attrs[:notifications_reason_id] = (
+ if tag_notification_level == TagUser.notification_levels[:watching]
+ TopicUser.notification_reasons[:auto_watch_tag]
+ else
TopicUser.notification_reasons[:auto_track_tag]
+ end
+ )
end
-
end
unless attrs[:notification_level]
if Topic.private_messages.where(id: topic_id).exists? &&
- Notification.where(
- user_id: user_id,
- topic_id: topic_id,
- notification_type: Notification.types[:invited_to_private_message]
- ).exists?
-
- group_notification_level = Group
- .joins("LEFT OUTER JOIN group_users gu ON gu.group_id = groups.id AND gu.user_id = #{user_id}")
- .joins("LEFT OUTER JOIN topic_allowed_groups tag ON tag.topic_id = #{topic_id}")
- .where("gu.id IS NOT NULL AND tag.id IS NOT NULL")
- .pluck(:default_notification_level)
- .first
+ Notification.where(
+ user_id: user_id,
+ topic_id: topic_id,
+ notification_type: Notification.types[:invited_to_private_message],
+ ).exists?
+ group_notification_level =
+ Group
+ .joins(
+ "LEFT OUTER JOIN group_users gu ON gu.group_id = groups.id AND gu.user_id = #{user_id}",
+ )
+ .joins("LEFT OUTER JOIN topic_allowed_groups tag ON tag.topic_id = #{topic_id}")
+ .where("gu.id IS NOT NULL AND tag.id IS NOT NULL")
+ .pluck(:default_notification_level)
+ .first
if group_notification_level.present?
attrs[:notification_level] = group_notification_level
@@ -229,7 +275,8 @@ class TopicUser < ActiveRecord::Base
attrs[:notification_level] = notification_levels[:watching]
end
else
- auto_track_after = UserOption.where(user_id: user_id).pluck_first(:auto_track_topics_after_msecs)
+ auto_track_after =
+ UserOption.where(user_id: user_id).pluck_first(:auto_track_topics_after_msecs)
auto_track_after ||= SiteSetting.default_other_auto_track_topics_after_msecs
if auto_track_after >= 0 && auto_track_after <= (attrs[:total_msecs_viewed].to_i || 0)
@@ -238,12 +285,14 @@ class TopicUser < ActiveRecord::Base
end
end
- TopicUser.create!(attrs.merge!(
- user_id: user_id,
- topic_id: topic_id,
- first_visited_at: now ,
- last_visited_at: now
- ))
+ TopicUser.create!(
+ attrs.merge!(
+ user_id: user_id,
+ topic_id: topic_id,
+ first_visited_at: now,
+ last_visited_at: now,
+ ),
+ )
DiscourseEvent.trigger(:topic_first_visited_by_user, topic_id, user_id)
end
@@ -252,9 +301,7 @@ class TopicUser < ActiveRecord::Base
now = DateTime.now
rows = TopicUser.where(topic_id: topic_id, user_id: user_id).update_all(last_visited_at: now)
- if rows == 0
- change(user_id, topic_id, last_visited_at: now, first_visited_at: now)
- end
+ change(user_id, topic_id, last_visited_at: now, first_visited_at: now) if rows == 0
end
# Update the last read and the last seen post count, but only if it doesn't exist.
@@ -289,7 +336,8 @@ class TopicUser < ActiveRecord::Base
t.archetype
SQL
- INSERT_TOPIC_USER_SQL = "INSERT INTO topic_users (user_id, topic_id, last_read_post_number, last_visited_at, first_visited_at, notification_level)
+ INSERT_TOPIC_USER_SQL =
+ "INSERT INTO topic_users (user_id, topic_id, last_read_post_number, last_visited_at, first_visited_at, notification_level)
SELECT :user_id, :topic_id, :post_number, :now, :now, :new_status
FROM topics AS ft
JOIN users u on u.id = :user_id
@@ -309,7 +357,7 @@ class TopicUser < ActiveRecord::Base
now: DateTime.now,
msecs: msecs,
tracking: notification_levels[:tracking],
- threshold: SiteSetting.default_other_auto_track_topics_after_msecs
+ threshold: SiteSetting.default_other_auto_track_topics_after_msecs,
}
rows = DB.query(UPDATE_TOPIC_USER_SQL, args)
@@ -327,23 +375,22 @@ class TopicUser < ActiveRecord::Base
post_number: post_number,
user: user,
notification_level: after,
- private_message: archetype == Archetype.private_message
+ private_message: archetype == Archetype.private_message,
)
end
- if new_posts_read > 0
- user.update_posts_read!(new_posts_read, mobile: opts[:mobile])
- end
+ user.update_posts_read!(new_posts_read, mobile: opts[:mobile]) if new_posts_read > 0
- if before != after
- notification_level_change(user.id, topic_id, after, nil)
- end
+ notification_level_change(user.id, topic_id, after, nil) if before != after
end
if rows.length == 0
# The user read at least one post in a topic that they haven't viewed before.
args[:new_status] = notification_levels[:regular]
- if (user.user_option.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs) == 0
+ if (
+ user.user_option.auto_track_topics_after_msecs ||
+ SiteSetting.default_other_auto_track_topics_after_msecs
+ ) == 0
args[:new_status] = notification_levels[:tracking]
end
@@ -352,10 +399,7 @@ class TopicUser < ActiveRecord::Base
post_number: post_number,
user: user,
notification_level: args[:new_status],
- private_message: Topic.exists?(
- archetype: Archetype.private_message,
- id: topic_id
- )
+ private_message: Topic.exists?(archetype: Archetype.private_message, id: topic_id),
)
user.update_posts_read!(new_posts_read, mobile: opts[:mobile])
@@ -387,14 +431,8 @@ class TopicUser < ActiveRecord::Base
TopicTrackingState
end
- klass.publish_read(
- topic_id,
- post_number,
- user,
- notification_level
- )
+ klass.publish_read(topic_id, post_number, user, notification_level)
end
-
end
# Update the cached topic_user.liked column based on data
@@ -441,16 +479,17 @@ class TopicUser < ActiveRecord::Base
WHERE x.topic_id = tu.topic_id AND x.user_id = tu.user_id AND x.state != tu.#{action_type_name}
SQL
- if user_id
- builder.where("tu2.user_id IN (:user_id)", user_id: user_id)
- end
+ builder.where("tu2.user_id IN (:user_id)", user_id: user_id) if user_id
- if topic_id
- builder.where("tu2.topic_id IN (:topic_id)", topic_id: topic_id)
- end
+ builder.where("tu2.topic_id IN (:topic_id)", topic_id: topic_id) if topic_id
if post_id
- builder.where("tu2.topic_id IN (SELECT topic_id FROM posts WHERE id IN (:post_id))", post_id: post_id) if !topic_id
+ if !topic_id
+ builder.where(
+ "tu2.topic_id IN (SELECT topic_id FROM posts WHERE id IN (:post_id))",
+ post_id: post_id,
+ )
+ end
builder.where(<<~SQL, post_id: post_id)
tu2.user_id IN (
SELECT user_id FROM post_actions
@@ -515,13 +554,10 @@ SQL
)
SQL
- if topic_id
- builder.where("t.topic_id = :topic_id", topic_id: topic_id)
- end
+ builder.where("t.topic_id = :topic_id", topic_id: topic_id) if topic_id
builder.exec
end
-
end
# == Schema Information
diff --git a/app/models/topic_view_item.rb b/app/models/topic_view_item.rb
index d37e8ec7a62..4472ed4b1d6 100644
--- a/app/models/topic_view_item.rb
+++ b/app/models/topic_view_item.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-require 'ipaddr'
+require "ipaddr"
# awkward TopicView is taken
class TopicViewItem < ActiveRecord::Base
- self.table_name = 'topic_views'
+ self.table_name = "topic_views"
belongs_to :user
belongs_to :topic
validates_presence_of :topic_id, :ip_address, :viewed_at
@@ -24,7 +24,8 @@ class TopicViewItem < ActiveRecord::Base
TopicViewItem.transaction do
# this is called real frequently, working hard to avoid exceptions
- sql = "INSERT INTO topic_views (topic_id, ip_address, viewed_at, user_id)
+ sql =
+ "INSERT INTO topic_views (topic_id, ip_address, viewed_at, user_id)
SELECT :topic_id, :ip_address, :viewed_at, :user_id
WHERE NOT EXISTS (
SELECT 1 FROM topic_views
@@ -42,17 +43,18 @@ class TopicViewItem < ActiveRecord::Base
result = builder.exec(topic_id: topic_id, ip_address: ip, viewed_at: at, user_id: user_id)
- Topic.where(id: topic_id).update_all 'views = views + 1'
+ Topic.where(id: topic_id).update_all "views = views + 1"
if result > 0
- UserStat.where(user_id: user_id).update_all 'topics_entered = topics_entered + 1' if user_id
+ if user_id
+ UserStat.where(user_id: user_id).update_all "topics_entered = topics_entered + 1"
+ end
end
# Update the views count in the parent, if it exists.
end
end
end
-
end
# == Schema Information
diff --git a/app/models/translation_override.rb b/app/models/translation_override.rb
index 932ac08fa66..73137243ed0 100644
--- a/app/models/translation_override.rb
+++ b/app/models/translation_override.rb
@@ -3,17 +3,17 @@
class TranslationOverride < ActiveRecord::Base
# Allowlist i18n interpolation keys that can be included when customizing translations
ALLOWED_CUSTOM_INTERPOLATION_KEYS = {
- [
- "user_notifications.user_",
- "user_notifications.only_reply_by_email",
- "user_notifications.reply_by_email",
- "user_notifications.visit_link_to_respond",
- "user_notifications.header_instructions",
- "user_notifications.pm_participants",
- "unsubscribe_mailing_list",
- "unsubscribe_link_and_mail",
- "unsubscribe_link",
- ] => %w{
+ %w[
+ user_notifications.user_
+ user_notifications.only_reply_by_email
+ user_notifications.reply_by_email
+ user_notifications.visit_link_to_respond
+ user_notifications.header_instructions
+ user_notifications.pm_participants
+ unsubscribe_mailing_list
+ unsubscribe_link_and_mail
+ unsubscribe_link
+ ] => %w[
topic_title
topic_title_url_encoded
message
@@ -34,12 +34,13 @@ class TranslationOverride < ActiveRecord::Base
optional_pm
optional_cat
optional_tags
- }
+ ],
}
include HasSanitizableFields
include ActiveSupport::Deprecation::DeprecatedConstantAccessor
- deprecate_constant 'CUSTOM_INTERPOLATION_KEYS_WHITELIST', 'TranslationOverride::ALLOWED_CUSTOM_INTERPOLATION_KEYS'
+ deprecate_constant "CUSTOM_INTERPOLATION_KEYS_WHITELIST",
+ "TranslationOverride::ALLOWED_CUSTOM_INTERPOLATION_KEYS"
validates_uniqueness_of :translation_key, scope: :locale
validates_presence_of :locale, :translation_key, :value
@@ -50,10 +51,11 @@ class TranslationOverride < ActiveRecord::Base
params = { locale: locale, translation_key: key }
translation_override = find_or_initialize_by(params)
- sanitized_value = translation_override.sanitize_field(value, additional_attributes: ['data-auto-route'])
+ sanitized_value =
+ translation_override.sanitize_field(value, additional_attributes: ["data-auto-route"])
data = { value: sanitized_value }
- if key.end_with?('_MF')
+ if key.end_with?("_MF")
_, filename = JsLocaleHelper.find_message_format_locale([locale], fallback_to_english: false)
data[:compiled_js] = JsLocaleHelper.compile_message_format(filename, locale, sanitized_value)
end
@@ -74,22 +76,18 @@ class TranslationOverride < ActiveRecord::Base
overrides = TranslationOverride.pluck(:locale, :translation_key)
overrides = overrides.group_by(&:first).map { |k, a| [k, a.map(&:last)] }
- overrides.each do |locale, keys|
- clear_cached_keys!(locale, keys)
- end
+ overrides.each { |locale, keys| clear_cached_keys!(locale, keys) }
end
def self.reload_locale!
I18n.reload!
ExtraLocalesController.clear_cache!
- MessageBus.publish('/i18n-flush', refresh: true)
+ MessageBus.publish("/i18n-flush", refresh: true)
end
def self.clear_cached_keys!(locale, keys)
should_clear_anon_cache = false
- keys.each do |key|
- should_clear_anon_cache |= expire_cache(locale, key)
- end
+ keys.each { |key| should_clear_anon_cache |= expire_cache(locale, key) }
Site.clear_anon_cache! if should_clear_anon_cache
end
@@ -99,9 +97,9 @@ class TranslationOverride < ActiveRecord::Base
end
def self.expire_cache(locale, key)
- if key.starts_with?('post_action_types.')
+ if key.starts_with?("post_action_types.")
ApplicationSerializer.expire_cache_fragment!("post_action_types_#{locale}")
- elsif key.starts_with?('topic_flag_types.')
+ elsif key.starts_with?("topic_flag_types.")
ApplicationSerializer.expire_cache_fragment!("post_action_flag_types_#{locale}")
else
return false
@@ -119,9 +117,7 @@ class TranslationOverride < ActiveRecord::Base
def check_interpolation_keys
transformed_key = transform_pluralized_key(translation_key)
- original_text = I18n.overrides_disabled do
- I18n.t(transformed_key, locale: :en)
- end
+ original_text = I18n.overrides_disabled { I18n.t(transformed_key, locale: :en) }
if original_text
original_interpolation_keys = I18nInterpolationKeysFinder.find(original_text)
@@ -129,20 +125,21 @@ class TranslationOverride < ActiveRecord::Base
custom_interpolation_keys = []
ALLOWED_CUSTOM_INTERPOLATION_KEYS.select do |keys, value|
- if keys.any? { |key| transformed_key.start_with?(key) }
- custom_interpolation_keys = value
- end
+ custom_interpolation_keys = value if keys.any? { |key| transformed_key.start_with?(key) }
end
- invalid_keys = (original_interpolation_keys | new_interpolation_keys) -
- original_interpolation_keys -
- custom_interpolation_keys
+ invalid_keys =
+ (original_interpolation_keys | new_interpolation_keys) - original_interpolation_keys -
+ custom_interpolation_keys
if invalid_keys.present?
- self.errors.add(:base, I18n.t(
- 'activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys',
- keys: invalid_keys.join(', ')
- ))
+ self.errors.add(
+ :base,
+ I18n.t(
+ "activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
+ keys: invalid_keys.join(", "),
+ ),
+ )
false
end
@@ -151,7 +148,7 @@ class TranslationOverride < ActiveRecord::Base
def transform_pluralized_key(key)
match = key.match(/(.*)\.(zero|two|few|many)$/)
- match ? match.to_a.second + '.other' : key
+ match ? match.to_a.second + ".other" : key
end
end
diff --git a/app/models/trust_level3_requirements.rb b/app/models/trust_level3_requirements.rb
index 61970b2b9eb..8c2889d6fa7 100644
--- a/app/models/trust_level3_requirements.rb
+++ b/app/models/trust_level3_requirements.rb
@@ -3,13 +3,12 @@
# This class performs calculations to determine if a user qualifies for
# the Leader (3) trust level.
class TrustLevel3Requirements
-
class PenaltyCounts
attr_reader :silenced, :suspended
def initialize(user, row)
- @silenced = row['silence_count'] || 0
- @suspended = row['suspend_count'] || 0
+ @silenced = row["silence_count"] || 0
+ @suspended = row["suspend_count"] || 0
# If penalty started more than 6 months ago and still continues, it will
# not be selected by the query from 'penalty_counts'.
@@ -27,19 +26,32 @@ class TrustLevel3Requirements
LOW_WATER_MARK = 0.9
FORGIVENESS_PERIOD = 6.months
- attr_accessor :days_visited, :min_days_visited,
- :num_topics_replied_to, :min_topics_replied_to,
- :topics_viewed, :min_topics_viewed,
- :posts_read, :min_posts_read,
- :topics_viewed_all_time, :min_topics_viewed_all_time,
- :posts_read_all_time, :min_posts_read_all_time,
- :num_flagged_posts, :max_flagged_posts,
- :num_likes_given, :min_likes_given,
- :num_likes_received, :min_likes_received,
- :num_likes_received, :min_likes_received,
- :num_likes_received_days, :min_likes_received_days,
- :num_likes_received_users, :min_likes_received_users,
- :trust_level_locked, :on_grace_period
+ attr_accessor :days_visited,
+ :min_days_visited,
+ :num_topics_replied_to,
+ :min_topics_replied_to,
+ :topics_viewed,
+ :min_topics_viewed,
+ :posts_read,
+ :min_posts_read,
+ :topics_viewed_all_time,
+ :min_topics_viewed_all_time,
+ :posts_read_all_time,
+ :min_posts_read_all_time,
+ :num_flagged_posts,
+ :max_flagged_posts,
+ :num_likes_given,
+ :min_likes_given,
+ :num_likes_received,
+ :min_likes_received,
+ :num_likes_received,
+ :min_likes_received,
+ :num_likes_received_days,
+ :min_likes_received_days,
+ :num_likes_received_users,
+ :min_likes_received_users,
+ :trust_level_locked,
+ :on_grace_period
def initialize(user)
@user = user
@@ -48,18 +60,12 @@ class TrustLevel3Requirements
def requirements_met?
return false if trust_level_locked
- (!@user.suspended?) &&
- (!@user.silenced?) &&
- penalty_counts.total == 0 &&
- days_visited >= min_days_visited &&
- num_topics_replied_to >= min_topics_replied_to &&
- topics_viewed >= min_topics_viewed &&
- posts_read >= min_posts_read &&
- num_flagged_posts <= max_flagged_posts &&
- num_flagged_by_users <= max_flagged_by_users &&
+ (!@user.suspended?) && (!@user.silenced?) && penalty_counts.total == 0 &&
+ days_visited >= min_days_visited && num_topics_replied_to >= min_topics_replied_to &&
+ topics_viewed >= min_topics_viewed && posts_read >= min_posts_read &&
+ num_flagged_posts <= max_flagged_posts && num_flagged_by_users <= max_flagged_by_users &&
topics_viewed_all_time >= min_topics_viewed_all_time &&
- posts_read_all_time >= min_posts_read_all_time &&
- num_likes_given >= min_likes_given &&
+ posts_read_all_time >= min_posts_read_all_time && num_likes_given >= min_likes_given &&
num_likes_received >= min_likes_received &&
num_likes_received_users >= min_likes_received_users &&
num_likes_received_days >= min_likes_received_days
@@ -69,14 +75,11 @@ class TrustLevel3Requirements
return false if trust_level_locked
return false if SiteSetting.default_trust_level > 2
- @user.suspended? ||
- @user.silenced? ||
- penalty_counts.total > 0 ||
+ @user.suspended? || @user.silenced? || penalty_counts.total > 0 ||
days_visited < min_days_visited * LOW_WATER_MARK ||
num_topics_replied_to < min_topics_replied_to * LOW_WATER_MARK ||
topics_viewed < min_topics_viewed * LOW_WATER_MARK ||
- posts_read < min_posts_read * LOW_WATER_MARK ||
- num_flagged_posts > max_flagged_posts ||
+ posts_read < min_posts_read * LOW_WATER_MARK || num_flagged_posts > max_flagged_posts ||
num_flagged_by_users > max_flagged_by_users ||
topics_viewed_all_time < min_topics_viewed_all_time ||
posts_read_all_time < min_posts_read_all_time ||
@@ -110,7 +113,7 @@ class TrustLevel3Requirements
unsilence_user: UserHistory.actions[:unsilence_user],
suspend_user: UserHistory.actions[:suspend_user],
unsuspend_user: UserHistory.actions[:unsuspend_user],
- since: FORGIVENESS_PERIOD.ago
+ since: FORGIVENESS_PERIOD.ago,
}
sql = <<~SQL
@@ -151,31 +154,38 @@ class TrustLevel3Requirements
end
def topics_viewed_query
- TopicViewItem.where(user_id: @user.id)
+ TopicViewItem
+ .where(user_id: @user.id)
.joins(:topic)
.where("topics.archetype <> ?", Archetype.private_message)
.select("topic_id")
end
def topics_viewed
- topics_viewed_query.where('viewed_at > ?', time_period.days.ago).count
+ topics_viewed_query.where("viewed_at > ?", time_period.days.ago).count
end
def min_topics_viewed
[
- (TrustLevel3Requirements.num_topics_in_time_period.to_i * (SiteSetting.tl3_requires_topics_viewed.to_f / 100.0)).round,
- SiteSetting.tl3_requires_topics_viewed_cap
+ (
+ TrustLevel3Requirements.num_topics_in_time_period.to_i *
+ (SiteSetting.tl3_requires_topics_viewed.to_f / 100.0)
+ ).round,
+ SiteSetting.tl3_requires_topics_viewed_cap,
].min
end
def posts_read
- @user.user_visits.where('visited_at > ?', time_period.days.ago).pluck(:posts_read).sum
+ @user.user_visits.where("visited_at > ?", time_period.days.ago).pluck(:posts_read).sum
end
def min_posts_read
[
- (TrustLevel3Requirements.num_posts_in_time_period.to_i * (SiteSetting.tl3_requires_posts_read.to_f / 100.0)).round,
- SiteSetting.tl3_requires_posts_read_cap
+ (
+ TrustLevel3Requirements.num_posts_in_time_period.to_i *
+ (SiteSetting.tl3_requires_posts_read.to_f / 100.0)
+ ).round,
+ SiteSetting.tl3_requires_posts_read_cap,
].min
end
@@ -196,12 +206,14 @@ class TrustLevel3Requirements
end
def num_flagged_posts
- PostAction.with_deleted
+ PostAction
+ .with_deleted
.where(post_id: flagged_post_ids)
.where.not(user_id: @user.id)
.where.not(agreed_at: nil)
.pluck(:post_id)
- .uniq.count
+ .uniq
+ .count
end
def max_flagged_posts
@@ -209,12 +221,15 @@ class TrustLevel3Requirements
end
def num_flagged_by_users
- @_num_flagged_by_users ||= PostAction.with_deleted
- .where(post_id: flagged_post_ids)
- .where.not(user_id: @user.id)
- .where.not(agreed_at: nil)
- .pluck(:user_id)
- .uniq.count
+ @_num_flagged_by_users ||=
+ PostAction
+ .with_deleted
+ .where(post_id: flagged_post_ids)
+ .where.not(user_id: @user.id)
+ .where.not(agreed_at: nil)
+ .pluck(:user_id)
+ .uniq
+ .count
end
def max_flagged_by_users
@@ -222,7 +237,8 @@ class TrustLevel3Requirements
end
def num_likes_given
- UserAction.where(user_id: @user.id, action_type: UserAction::LIKE)
+ UserAction
+ .where(user_id: @user.id, action_type: UserAction::LIKE)
.where("user_actions.created_at > ?", time_period.days.ago)
.joins(:target_topic)
.where("topics.archetype <> ?", Archetype.private_message)
@@ -234,7 +250,8 @@ class TrustLevel3Requirements
end
def num_likes_received_query
- UserAction.where(user_id: @user.id, action_type: UserAction::WAS_LIKED)
+ UserAction
+ .where(user_id: @user.id, action_type: UserAction::WAS_LIKED)
.where("user_actions.created_at > ?", time_period.days.ago)
.joins(:target_topic)
.where("topics.archetype <> ?", Archetype.private_message)
@@ -250,7 +267,7 @@ class TrustLevel3Requirements
def num_likes_received_days
# don't do a COUNT(DISTINCT date(created_at)) here!
- num_likes_received_query.pluck('date(user_actions.created_at)').uniq.size
+ num_likes_received_query.pluck("date(user_actions.created_at)").uniq.size
end
def min_likes_received_days
@@ -275,28 +292,36 @@ class TrustLevel3Requirements
CACHE_DURATION = 1.day.seconds - 60
NUM_TOPICS_KEY = "tl3_num_topics"
- NUM_POSTS_KEY = "tl3_num_posts"
+ NUM_POSTS_KEY = "tl3_num_posts"
def self.num_topics_in_time_period
- Discourse.redis.get(NUM_TOPICS_KEY) || begin
- count = Topic.listable_topics.visible.created_since(SiteSetting.tl3_time_period.days.ago).count
- Discourse.redis.setex NUM_TOPICS_KEY, CACHE_DURATION, count
- count
- end
+ Discourse.redis.get(NUM_TOPICS_KEY) ||
+ begin
+ count =
+ Topic.listable_topics.visible.created_since(SiteSetting.tl3_time_period.days.ago).count
+ Discourse.redis.setex NUM_TOPICS_KEY, CACHE_DURATION, count
+ count
+ end
end
def self.num_posts_in_time_period
- Discourse.redis.get(NUM_POSTS_KEY) || begin
- count = Post.public_posts.visible.created_since(SiteSetting.tl3_time_period.days.ago).count
- Discourse.redis.setex NUM_POSTS_KEY, CACHE_DURATION, count
- count
- end
+ Discourse.redis.get(NUM_POSTS_KEY) ||
+ begin
+ count = Post.public_posts.visible.created_since(SiteSetting.tl3_time_period.days.ago).count
+ Discourse.redis.setex NUM_POSTS_KEY, CACHE_DURATION, count
+ count
+ end
end
def flagged_post_ids
- @_flagged_post_ids ||= @user.posts
- .with_deleted
- .where('created_at > ? AND (spam_count > 0 OR inappropriate_count > 0)', time_period.days.ago)
- .pluck(:id)
+ @_flagged_post_ids ||=
+ @user
+ .posts
+ .with_deleted
+ .where(
+ "created_at > ? AND (spam_count > 0 OR inappropriate_count > 0)",
+ time_period.days.ago,
+ )
+ .pluck(:id)
end
end
diff --git a/app/models/trust_level_and_staff_and_disabled_setting.rb b/app/models/trust_level_and_staff_and_disabled_setting.rb
index 3b1a4336c28..4edc2c9519f 100644
--- a/app/models/trust_level_and_staff_and_disabled_setting.rb
+++ b/app/models/trust_level_and_staff_and_disabled_setting.rb
@@ -6,12 +6,12 @@ class TrustLevelAndStaffAndDisabledSetting < TrustLevelAndStaffSetting
end
def self.valid_values
- ['disabled'] + TrustLevel.valid_range.to_a + special_groups
+ ["disabled"] + TrustLevel.valid_range.to_a + special_groups
end
def self.translation(value)
- if value == 'disabled'
- I18n.t('site_settings.disabled')
+ if value == "disabled"
+ I18n.t("site_settings.disabled")
else
super
end
@@ -19,11 +19,11 @@ class TrustLevelAndStaffAndDisabledSetting < TrustLevelAndStaffSetting
def self.matches?(value, user)
case value
- when 'disabled'
+ when "disabled"
false
- when 'staff'
+ when "staff"
user.staff?
- when 'admin'
+ when "admin"
user.admin?
else
user.has_trust_level?(value.to_i) || user.staff?
diff --git a/app/models/trust_level_and_staff_setting.rb b/app/models/trust_level_and_staff_setting.rb
index a72f6346673..17cc8bead7d 100644
--- a/app/models/trust_level_and_staff_setting.rb
+++ b/app/models/trust_level_and_staff_setting.rb
@@ -2,9 +2,7 @@
class TrustLevelAndStaffSetting < TrustLevelSetting
def self.valid_value?(val)
- special_group?(val) ||
- (val.to_i.to_s == val.to_s &&
- valid_values.any? { |v| v == val.to_i })
+ special_group?(val) || (val.to_i.to_s == val.to_s && valid_values.any? { |v| v == val.to_i })
end
def self.valid_values
@@ -16,7 +14,7 @@ class TrustLevelAndStaffSetting < TrustLevelSetting
end
def self.special_groups
- ['staff', 'admin']
+ %w[staff admin]
end
def self.translation(value)
diff --git a/app/models/trust_level_setting.rb b/app/models/trust_level_setting.rb
index fc48bf8a10d..e1d4f2c0ce1 100644
--- a/app/models/trust_level_setting.rb
+++ b/app/models/trust_level_setting.rb
@@ -1,16 +1,12 @@
# frozen_string_literal: true
class TrustLevelSetting < EnumSiteSetting
-
def self.valid_value?(val)
- val.to_i.to_s == val.to_s &&
- valid_values.any? { |v| v == val.to_i }
+ val.to_i.to_s == val.to_s && valid_values.any? { |v| v == val.to_i }
end
def self.values
- valid_values.map do |value|
- { name: translation(value), value: value }
- end
+ valid_values.map { |value| { name: translation(value), value: value } }
end
def self.valid_values
@@ -18,11 +14,7 @@ class TrustLevelSetting < EnumSiteSetting
end
def self.translation(value)
- I18n.t(
- "js.trust_levels.detailed_name",
- level: value,
- name: TrustLevel.name(value)
- )
+ I18n.t("js.trust_levels.detailed_name", level: value, name: TrustLevel.name(value))
end
private_class_method :valid_values
diff --git a/app/models/unsubscribe_key.rb b/app/models/unsubscribe_key.rb
index da81fdfb33c..fbc199e169d 100644
--- a/app/models/unsubscribe_key.rb
+++ b/app/models/unsubscribe_key.rb
@@ -7,9 +7,9 @@ class UnsubscribeKey < ActiveRecord::Base
before_create :generate_random_key
- ALL_TYPE = 'all'
- DIGEST_TYPE = 'digest'
- TOPIC_TYPE = 'topic'
+ ALL_TYPE = "all"
+ DIGEST_TYPE = "digest"
+ TOPIC_TYPE = "topic"
class << self
def create_key_for(user, type, post: nil)
@@ -32,7 +32,7 @@ class UnsubscribeKey < ActiveRecord::Base
strategies = {
DIGEST_TYPE => EmailControllerHelper::DigestEmailUnsubscriber,
TOPIC_TYPE => EmailControllerHelper::TopicEmailUnsubscriber,
- ALL_TYPE => EmailControllerHelper::BaseEmailUnsubscriber
+ ALL_TYPE => EmailControllerHelper::BaseEmailUnsubscriber,
}
DiscoursePluginRegistry.email_unsubscribers.each do |unsubcriber|
diff --git a/app/models/upload.rb b/app/models/upload.rb
index ad004f6e668..964ef52d1dd 100644
--- a/app/models/upload.rb
+++ b/app/models/upload.rb
@@ -8,12 +8,12 @@ class Upload < ActiveRecord::Base
SHA1_LENGTH = 40
SEEDED_ID_THRESHOLD = 0
- URL_REGEX ||= /(\/original\/\dX[\/\.\w]*\/(\h+)[\.\w]*)/
+ URL_REGEX ||= %r{(/original/\dX[/\.\w]*/(\h+)[\.\w]*)}
MAX_IDENTIFY_SECONDS = 5
DOMINANT_COLOR_COMMAND_TIMEOUT_SECONDS = 5
belongs_to :user
- belongs_to :access_control_post, class_name: 'Post'
+ belongs_to :access_control_post, class_name: "Post"
# when we access this post we don't care if the post
# is deleted
@@ -25,7 +25,7 @@ class Upload < ActiveRecord::Base
has_many :optimized_images, dependent: :destroy
has_many :user_uploads, dependent: :destroy
has_many :upload_references, dependent: :destroy
- has_many :posts, through: :upload_references, source: :target, source_type: 'Post'
+ has_many :posts, through: :upload_references, source: :target, source_type: "Post"
has_many :topic_thumbnails
attr_accessor :for_group_message
@@ -44,7 +44,9 @@ class Upload < ActiveRecord::Base
before_destroy do
UserProfile.where(card_background_upload_id: self.id).update_all(card_background_upload_id: nil)
- UserProfile.where(profile_background_upload_id: self.id).update_all(profile_background_upload_id: nil)
+ UserProfile.where(profile_background_upload_id: self.id).update_all(
+ profile_background_upload_id: nil,
+ )
end
after_destroy do
@@ -56,11 +58,7 @@ class Upload < ActiveRecord::Base
scope :by_users, -> { where("uploads.id > ?", SEEDED_ID_THRESHOLD) }
def self.verification_statuses
- @verification_statuses ||= Enum.new(
- unchecked: 1,
- verified: 2,
- invalid_etag: 3
- )
+ @verification_statuses ||= Enum.new(unchecked: 1, verified: 2, invalid_etag: 3)
end
def self.add_unused_callback(&block)
@@ -88,9 +86,9 @@ class Upload < ActiveRecord::Base
end
def self.with_no_non_post_relations
- self
- .joins("LEFT JOIN upload_references ur ON ur.upload_id = uploads.id AND ur.target_type != 'Post'")
- .where("ur.upload_id IS NULL")
+ self.joins(
+ "LEFT JOIN upload_references ur ON ur.upload_id = uploads.id AND ur.target_type != 'Post'",
+ ).where("ur.upload_id IS NULL")
end
def initialize(*args)
@@ -114,18 +112,14 @@ class Upload < ActiveRecord::Base
return unless SiteSetting.create_thumbnails?
opts ||= {}
- if get_optimized_image(width, height, opts)
- save(validate: false)
- end
+ save(validate: false) if get_optimized_image(width, height, opts)
end
# this method attempts to correct old incorrect extensions
def get_optimized_image(width, height, opts = nil)
opts ||= {}
- if (!extension || extension.length == 0)
- fix_image_extension
- end
+ fix_image_extension if (!extension || extension.length == 0)
opts = opts.merge(raise_on_error: true)
begin
@@ -152,9 +146,7 @@ class Upload < ActiveRecord::Base
File.read(original_path)
ensure
- if external_copy
- File.unlink(external_copy.path)
- end
+ File.unlink(external_copy.path) if external_copy
end
def fix_image_extension
@@ -164,18 +156,28 @@ class Upload < ActiveRecord::Base
# this is relatively cheap once cached
original_path = Discourse.store.path_for(self)
if original_path.blank?
- external_copy = Discourse.store.download(self) rescue nil
+ external_copy =
+ begin
+ Discourse.store.download(self)
+ rescue StandardError
+ nil
+ end
original_path = external_copy.try(:path)
end
- image_info = FastImage.new(original_path) rescue nil
+ image_info =
+ begin
+ FastImage.new(original_path)
+ rescue StandardError
+ nil
+ end
new_extension = image_info&.type&.to_s || "unknown"
if new_extension != self.extension
self.update_columns(extension: new_extension)
true
end
- rescue
+ rescue StandardError
self.update_columns(extension: "unknown")
true
end
@@ -211,7 +213,9 @@ class Upload < ActiveRecord::Base
def self.consider_for_reuse(upload, post)
return upload if !SiteSetting.secure_uploads? || upload.blank? || post.blank?
- return nil if !upload.matching_access_control_post?(post) || upload.uploaded_before_secure_uploads_enabled?
+ if !upload.matching_access_control_post?(post) || upload.uploaded_before_secure_uploads_enabled?
+ return nil
+ end
upload
end
@@ -220,7 +224,8 @@ class Upload < ActiveRecord::Base
# have secure-uploads in the URL e.g. /t/secure-uploads-are-cool/223452
route = UrlHelper.rails_route_from_url(url)
return false if route.blank?
- route[:action] == "show_secure" && route[:controller] == "uploads" && FileHelper.is_supported_media?(url)
+ route[:action] == "show_secure" && route[:controller] == "uploads" &&
+ FileHelper.is_supported_media?(url)
rescue ActionController::RoutingError
false
end
@@ -239,17 +244,14 @@ class Upload < ActiveRecord::Base
controller: "uploads",
action: "show_secure",
path: uri.path[1..-1],
- only_path: true
+ only_path: true,
)
end
def self.short_path(sha1:, extension:)
@url_helpers ||= Rails.application.routes.url_helpers
- @url_helpers.upload_short_path(
- base62: self.base62_sha1(sha1),
- extension: extension
- )
+ @url_helpers.upload_short_path(base62: self.base62_sha1(sha1), extension: extension)
end
def self.base62_sha1(sha1)
@@ -261,7 +263,7 @@ class Upload < ActiveRecord::Base
end
def local?
- !(url =~ /^(https?:)?\/\//)
+ !(url =~ %r{^(https?:)?//})
end
def fix_dimensions!
@@ -275,8 +277,19 @@ class Upload < ActiveRecord::Base
end
begin
- if extension == 'svg'
- w, h = Discourse::Utils.execute_command("identify", "-format", "%w %h", path, timeout: MAX_IDENTIFY_SECONDS).split(' ') rescue [0, 0]
+ if extension == "svg"
+ w, h =
+ begin
+ Discourse::Utils.execute_command(
+ "identify",
+ "-format",
+ "%w %h",
+ path,
+ timeout: MAX_IDENTIFY_SECONDS,
+ ).split(" ")
+ rescue StandardError
+ [0, 0]
+ end
else
w, h = FastImage.new(path, raise_on_failure: true).size
end
@@ -290,7 +303,7 @@ class Upload < ActiveRecord::Base
width: width,
height: height,
thumbnail_width: thumbnail_width,
- thumbnail_height: thumbnail_height
+ thumbnail_height: thumbnail_height,
)
rescue => e
Discourse.warn_exception(e, message: "Error getting image dimensions")
@@ -337,9 +350,7 @@ class Upload < ActiveRecord::Base
def calculate_dominant_color!(local_path = nil)
color = nil
- if !FileHelper.is_supported_image?("image.#{extension}") || extension == "svg"
- color = ""
- end
+ color = "" if !FileHelper.is_supported_image?("image.#{extension}") || extension == "svg"
if color.nil?
local_path ||=
@@ -360,37 +371,39 @@ class Upload < ActiveRecord::Base
color = ""
end
- color ||= begin
- data = Discourse::Utils.execute_command(
- "nice",
- "-n",
- "10",
- "convert",
- local_path,
- "-resize",
- "1x1",
- "-define",
- "histogram:unique-colors=true",
- "-format",
- "%c",
- "histogram:info:",
- timeout: DOMINANT_COLOR_COMMAND_TIMEOUT_SECONDS
- )
+ color ||=
+ begin
+ data =
+ Discourse::Utils.execute_command(
+ "nice",
+ "-n",
+ "10",
+ "convert",
+ local_path,
+ "-resize",
+ "1x1",
+ "-define",
+ "histogram:unique-colors=true",
+ "-format",
+ "%c",
+ "histogram:info:",
+ timeout: DOMINANT_COLOR_COMMAND_TIMEOUT_SECONDS,
+ )
- # Output format:
- # 1: (110.873,116.226,93.8821) #6F745E srgb(43.4798%,45.5789%,36.8165%)
+ # Output format:
+ # 1: (110.873,116.226,93.8821) #6F745E srgb(43.4798%,45.5789%,36.8165%)
- color = data[/#([0-9A-F]{6})/, 1]
+ color = data[/#([0-9A-F]{6})/, 1]
- raise "Calculated dominant color but unable to parse output:\n#{data}" if color.nil?
+ raise "Calculated dominant color but unable to parse output:\n#{data}" if color.nil?
- color
- rescue Discourse::Utils::CommandError => e
- # Timeout or unable to parse image
- # This can happen due to bad user input - ignore and save
- # an empty string to prevent re-evaluation
- ""
- end
+ color
+ rescue Discourse::Utils::CommandError => e
+ # Timeout or unable to parse image
+ # This can happen due to bad user input - ignore and save
+ # an empty string to prevent re-evaluation
+ ""
+ end
end
if persisted?
@@ -401,23 +414,28 @@ class Upload < ActiveRecord::Base
end
def target_image_quality(local_path, test_quality)
- @file_quality ||= Discourse::Utils.execute_command("identify", "-format", "%Q", local_path, timeout: MAX_IDENTIFY_SECONDS).to_i rescue 0
+ @file_quality ||=
+ begin
+ Discourse::Utils.execute_command(
+ "identify",
+ "-format",
+ "%Q",
+ local_path,
+ timeout: MAX_IDENTIFY_SECONDS,
+ ).to_i
+ rescue StandardError
+ 0
+ end
- if @file_quality == 0 || @file_quality > test_quality
- test_quality
- end
+ test_quality if @file_quality == 0 || @file_quality > test_quality
end
def self.sha1_from_short_path(path)
- if path =~ /(\/uploads\/short-url\/)([a-zA-Z0-9]+)(\..*)?/
- self.sha1_from_base62_encoded($2)
- end
+ self.sha1_from_base62_encoded($2) if path =~ %r{(/uploads/short-url/)([a-zA-Z0-9]+)(\..*)?}
end
def self.sha1_from_short_url(url)
- if url =~ /(upload:\/\/)?([a-zA-Z0-9]+)(\..*)?/
- self.sha1_from_base62_encoded($2)
- end
+ self.sha1_from_base62_encoded($2) if url =~ %r{(upload://)?([a-zA-Z0-9]+)(\..*)?}
end
def self.sha1_from_base62_encoded(encoded_sha1)
@@ -426,7 +444,7 @@ class Upload < ActiveRecord::Base
if sha1.length > SHA1_LENGTH
nil
else
- sha1.rjust(SHA1_LENGTH, '0')
+ sha1.rjust(SHA1_LENGTH, "0")
end
end
@@ -457,7 +475,10 @@ class Upload < ActiveRecord::Base
begin
Discourse.store.update_upload_ACL(self)
rescue Aws::S3::Errors::NotImplemented => err
- Discourse.warn_exception(err, message: "The file store object storage provider does not support setting ACLs")
+ Discourse.warn_exception(
+ err,
+ message: "The file store object storage provider does not support setting ACLs",
+ )
end
end
@@ -468,7 +489,7 @@ class Upload < ActiveRecord::Base
{
secure: secure,
security_last_changed_reason: reason + " | source: #{source}",
- security_last_changed_at: Time.zone.now
+ security_last_changed_at: Time.zone.now,
}
end
@@ -479,15 +500,17 @@ class Upload < ActiveRecord::Base
if SiteSetting.migrate_to_new_scheme
max_file_size_kb = [
SiteSetting.max_image_size_kb,
- SiteSetting.max_attachment_size_kb
+ SiteSetting.max_attachment_size_kb,
].max.kilobytes
local_store = FileStore::LocalStore.new
db = RailsMultisite::ConnectionManagement.current_db
- scope = Upload.by_users
- .where("url NOT LIKE '%/original/_X/%' AND url LIKE ?", "%/uploads/#{db}%")
- .order(id: :desc)
+ scope =
+ Upload
+ .by_users
+ .where("url NOT LIKE '%/original/_X/%' AND url LIKE ?", "%/uploads/#{db}%")
+ .order(id: :desc)
scope = scope.limit(limit) if limit
@@ -503,7 +526,7 @@ class Upload < ActiveRecord::Base
# keep track of the url
previous_url = upload.url.dup
# where is the file currently stored?
- external = previous_url =~ /^\/\//
+ external = previous_url =~ %r{^//}
# download if external
if external
url = SiteSetting.scheme + ":" + previous_url
@@ -511,12 +534,13 @@ class Upload < ActiveRecord::Base
begin
retries ||= 0
- file = FileHelper.download(
- url,
- max_file_size: max_file_size_kb,
- tmp_file_name: "discourse",
- follow_redirect: true
- )
+ file =
+ FileHelper.download(
+ url,
+ max_file_size: max_file_size_kb,
+ tmp_file_name: "discourse",
+ follow_redirect: true,
+ )
rescue OpenURI::HTTPError
retry if (retries += 1) < 1
next
@@ -527,9 +551,7 @@ class Upload < ActiveRecord::Base
path = local_store.path_for(upload)
end
# compute SHA if missing
- if upload.sha1.blank?
- upload.sha1 = Upload.generate_digest(path)
- end
+ upload.sha1 = Upload.generate_digest(path) if upload.sha1.blank?
# store to new location & update the filesize
File.open(path) do |f|
@@ -543,7 +565,7 @@ class Upload < ActiveRecord::Base
DbHelper.remap(
previous_url,
upload.url,
- excluded_tables: %w{
+ excluded_tables: %w[
posts
post_search_data
incoming_emails
@@ -555,28 +577,32 @@ class Upload < ActiveRecord::Base
user_emails
draft_sequences
optimized_images
- }
+ ],
)
- remap_scope ||= begin
- Post.with_deleted
- .where("raw ~ '/uploads/#{db}/\\d+/' OR raw ~ '/uploads/#{db}/original/(\\d|[a-z])/'")
- .select(:id, :raw, :cooked)
- .all
- end
+ remap_scope ||=
+ begin
+ Post
+ .with_deleted
+ .where(
+ "raw ~ '/uploads/#{db}/\\d+/' OR raw ~ '/uploads/#{db}/original/(\\d|[a-z])/'",
+ )
+ .select(:id, :raw, :cooked)
+ .all
+ end
remap_scope.each do |post|
post.raw.gsub!(previous_url, upload.url)
post.cooked.gsub!(previous_url, upload.url)
- Post.with_deleted.where(id: post.id).update_all(raw: post.raw, cooked: post.cooked) if post.changed?
+ if post.changed?
+ Post.with_deleted.where(id: post.id).update_all(raw: post.raw, cooked: post.cooked)
+ end
end
upload.optimized_images.find_each(&:destroy!)
upload.rebake_posts_on_old_scheme
# remove the old file (when local)
- unless external
- FileUtils.rm(path, force: true)
- end
+ FileUtils.rm(path, force: true) unless external
rescue => e
problems << { upload: upload, ex: e }
ensure
@@ -595,21 +621,21 @@ class Upload < ActiveRecord::Base
sha1s = []
- raw.scan(/\/(\h{40})/).each do |match|
- sha1s << match[0]
- end
+ raw.scan(/\/(\h{40})/).each { |match| sha1s << match[0] }
- raw.scan(/\/([a-zA-Z0-9]+)/).each do |match|
- sha1s << Upload.sha1_from_base62_encoded(match[0])
- end
+ raw
+ .scan(%r{/([a-zA-Z0-9]+)})
+ .each { |match| sha1s << Upload.sha1_from_base62_encoded(match[0]) }
Upload.where(sha1: sha1s.uniq).pluck(:id)
end
def self.backfill_dominant_colors!(count)
- Upload.where(dominant_color: nil).order("id desc").first(count).each do |upload|
- upload.calculate_dominant_color!
- end
+ Upload
+ .where(dominant_color: nil)
+ .order("id desc")
+ .first(count)
+ .each { |upload| upload.calculate_dominant_color! }
end
private
@@ -617,7 +643,6 @@ class Upload < ActiveRecord::Base
def short_url_basename
"#{Upload.base62_sha1(sha1)}#{extension.present? ? ".#{extension}" : ""}"
end
-
end
# == Schema Information
diff --git a/app/models/upload_reference.rb b/app/models/upload_reference.rb
index 58cf8f86d19..73de830f545 100644
--- a/app/models/upload_reference.rb
+++ b/app/models/upload_reference.rb
@@ -5,7 +5,9 @@ class UploadReference < ActiveRecord::Base
belongs_to :target, polymorphic: true
def self.ensure_exist!(upload_ids: [], target: nil, target_type: nil, target_id: nil)
- raise "target OR target_type and target_id are required" if !target && !(target_type && target_id)
+ if !target && !(target_type && target_id)
+ raise "target OR target_type and target_id are required"
+ end
if target.present?
target_type = target.class
@@ -16,22 +18,21 @@ class UploadReference < ActiveRecord::Base
target_type = target_type.to_s
if upload_ids.empty?
- UploadReference
- .where(target_type: target_type, target_id: target_id)
- .delete_all
+ UploadReference.where(target_type: target_type, target_id: target_id).delete_all
return
end
- rows = upload_ids.map do |upload_id|
- {
- upload_id: upload_id,
- target_type: target_type,
- target_id: target_id,
- created_at: Time.zone.now,
- updated_at: Time.zone.now,
- }
- end
+ rows =
+ upload_ids.map do |upload_id|
+ {
+ upload_id: upload_id,
+ target_type: target_type,
+ target_id: target_id,
+ created_at: Time.zone.now,
+ updated_at: Time.zone.now,
+ }
+ end
UploadReference.transaction do |transaction|
UploadReference
diff --git a/app/models/user.rb b/app/models/user.rb
index 54d358ec737..d0d9846a433 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -34,22 +34,40 @@ class User < ActiveRecord::Base
has_many :user_warnings, dependent: :destroy
has_many :api_keys, dependent: :destroy
has_many :push_subscriptions, dependent: :destroy
- has_many :acting_group_histories, dependent: :destroy, foreign_key: :acting_user_id, class_name: 'GroupHistory'
- has_many :targeted_group_histories, dependent: :destroy, foreign_key: :target_user_id, class_name: 'GroupHistory'
+ has_many :acting_group_histories,
+ dependent: :destroy,
+ foreign_key: :acting_user_id,
+ class_name: "GroupHistory"
+ has_many :targeted_group_histories,
+ dependent: :destroy,
+ foreign_key: :target_user_id,
+ class_name: "GroupHistory"
has_many :reviewable_scores, dependent: :destroy
has_many :invites, foreign_key: :invited_by_id, dependent: :destroy
has_many :user_custom_fields, dependent: :destroy
has_many :user_associated_groups, dependent: :destroy
- has_many :pending_posts, -> { merge(Reviewable.pending) }, class_name: 'ReviewableQueuedPost', foreign_key: :created_by_id
+ has_many :pending_posts,
+ -> { merge(Reviewable.pending) },
+ class_name: "ReviewableQueuedPost",
+ foreign_key: :created_by_id
has_one :user_option, dependent: :destroy
has_one :user_avatar, dependent: :destroy
- has_one :primary_email, -> { where(primary: true) }, class_name: 'UserEmail', dependent: :destroy, autosave: true, validate: false
+ has_one :primary_email,
+ -> { where(primary: true) },
+ class_name: "UserEmail",
+ dependent: :destroy,
+ autosave: true,
+ validate: false
has_one :user_stat, dependent: :destroy
has_one :user_profile, dependent: :destroy, inverse_of: :user
has_one :single_sign_on_record, dependent: :destroy
- has_one :anonymous_user_master, class_name: 'AnonymousUser', dependent: :destroy
- has_one :anonymous_user_shadow, ->(record) { where(active: true) }, foreign_key: :master_user_id, class_name: 'AnonymousUser', dependent: :destroy
+ has_one :anonymous_user_master, class_name: "AnonymousUser", dependent: :destroy
+ has_one :anonymous_user_shadow,
+ ->(record) { where(active: true) },
+ foreign_key: :master_user_id,
+ class_name: "AnonymousUser",
+ dependent: :destroy
has_one :invited_user, dependent: :destroy
has_one :user_notification_schedule, dependent: :destroy
@@ -61,8 +79,8 @@ class User < ActiveRecord::Base
has_many :user_visits, dependent: :delete_all
has_many :user_auth_token_logs, dependent: :delete_all
has_many :group_requests, dependent: :delete_all
- has_many :muted_user_records, class_name: 'MutedUser', dependent: :delete_all
- has_many :ignored_user_records, class_name: 'IgnoredUser', dependent: :delete_all
+ has_many :muted_user_records, class_name: "MutedUser", dependent: :delete_all
+ has_many :ignored_user_records, class_name: "IgnoredUser", dependent: :delete_all
has_many :do_not_disturb_timings, dependent: :delete_all
has_one :user_status, dependent: :destroy
@@ -72,16 +90,22 @@ class User < ActiveRecord::Base
has_many :post_timings
has_many :directory_items
has_many :email_logs
- has_many :security_keys, -> {
- where(enabled: true)
- }, class_name: "UserSecurityKey"
+ has_many :security_keys, -> { where(enabled: true) }, class_name: "UserSecurityKey"
has_many :badges, through: :user_badges
- has_many :default_featured_user_badges, -> {
- max_featured_rank = SiteSetting.max_favorite_badges > 0 ? SiteSetting.max_favorite_badges + 1
- : DEFAULT_FEATURED_BADGE_COUNT
- for_enabled_badges.grouped_with_count.where("featured_rank <= ?", max_featured_rank)
- }, class_name: "UserBadge"
+ has_many :default_featured_user_badges,
+ -> {
+ max_featured_rank =
+ (
+ if SiteSetting.max_favorite_badges > 0
+ SiteSetting.max_favorite_badges + 1
+ else
+ DEFAULT_FEATURED_BADGE_COUNT
+ end
+ )
+ for_enabled_badges.grouped_with_count.where("featured_rank <= ?", max_featured_rank)
+ },
+ class_name: "UserBadge"
has_many :topics_allowed, through: :topic_allowed_users, source: :topic
has_many :groups, through: :group_users
@@ -89,27 +113,32 @@ class User < ActiveRecord::Base
has_many :associated_groups, through: :user_associated_groups, dependent: :destroy
# deleted in user_second_factors relationship
- has_many :totps, -> {
- where(method: UserSecondFactor.methods[:totp], enabled: true)
- }, class_name: "UserSecondFactor"
+ has_many :totps,
+ -> { where(method: UserSecondFactor.methods[:totp], enabled: true) },
+ class_name: "UserSecondFactor"
has_one :master_user, through: :anonymous_user_master
has_one :shadow_user, through: :anonymous_user_shadow, source: :user
has_one :profile_background_upload, through: :user_profile
has_one :card_background_upload, through: :user_profile
- belongs_to :approved_by, class_name: 'User'
- belongs_to :primary_group, class_name: 'Group'
- belongs_to :flair_group, class_name: 'Group'
+ belongs_to :approved_by, class_name: "User"
+ belongs_to :primary_group, class_name: "Group"
+ belongs_to :flair_group, class_name: "Group"
has_many :muted_users, through: :muted_user_records
has_many :ignored_users, through: :ignored_user_records
- belongs_to :uploaded_avatar, class_name: 'Upload'
+ belongs_to :uploaded_avatar, class_name: "Upload"
has_many :sidebar_section_links, dependent: :delete_all
- has_many :category_sidebar_section_links, -> { where(linkable_type: "Category") }, class_name: 'SidebarSectionLink'
- has_many :custom_sidebar_tags, through: :sidebar_section_links, source: :linkable, source_type: "Tag"
+ has_many :category_sidebar_section_links,
+ -> { where(linkable_type: "Category") },
+ class_name: "SidebarSectionLink"
+ has_many :custom_sidebar_tags,
+ through: :sidebar_section_links,
+ source: :linkable,
+ source_type: "Tag"
delegate :last_sent_email_address, to: :email_logs
@@ -121,7 +150,8 @@ class User < ActiveRecord::Base
validates :ip_address, allowed_ip_address: { on: :create, message: :signup_not_allowed }
validates :primary_email, presence: true
validates :validatable_user_fields_values, watched_words: true, unless: :custom_fields_clean?
- validates_associated :primary_email, message: -> (_, user_email) { user_email[:value]&.errors[:email]&.first }
+ validates_associated :primary_email,
+ message: ->(_, user_email) { user_email[:value]&.errors[:email]&.first }
after_initialize :add_trust_level
@@ -137,17 +167,12 @@ class User < ActiveRecord::Base
after_create :set_default_tags_preferences
after_create :add_default_sidebar_section_links
- after_update :update_default_sidebar_section_links, if: Proc.new {
- self.saved_change_to_admin?
- }
+ after_update :update_default_sidebar_section_links, if: Proc.new { self.saved_change_to_admin? }
- after_update :add_default_sidebar_section_links, if: Proc.new {
- self.saved_change_to_staged?
- }
+ after_update :add_default_sidebar_section_links, if: Proc.new { self.saved_change_to_staged? }
- after_update :trigger_user_updated_event, if: Proc.new {
- self.human? && self.saved_change_to_uploaded_avatar_id?
- }
+ after_update :trigger_user_updated_event,
+ if: Proc.new { self.human? && self.saved_change_to_uploaded_avatar_id? }
after_update :trigger_user_automatic_group_refresh, if: :saved_change_to_staged?
@@ -178,7 +203,10 @@ class User < ActiveRecord::Base
# These tables don't have primary keys, so destroying them with activerecord is tricky:
PostTiming.where(user_id: self.id).delete_all
TopicViewItem.where(user_id: self.id).delete_all
- UserAction.where('user_id = :user_id OR target_user_id = :user_id OR acting_user_id = :user_id', user_id: self.id).delete_all
+ UserAction.where(
+ "user_id = :user_id OR target_user_id = :user_id OR acting_user_id = :user_id",
+ user_id: self.id,
+ ).delete_all
# we need to bypass the default scope here, which appears not bypassed for :delete_all
# however :destroy it is bypassed
@@ -186,8 +214,9 @@ class User < ActiveRecord::Base
# This is a perf optimisation to ensure we hit the index
# without this we need to scan a much larger number of rows
- DirectoryItem.where(user_id: self.id)
- .where('period_type in (?)', DirectoryItem.period_types.values)
+ DirectoryItem
+ .where(user_id: self.id)
+ .where("period_type in (?)", DirectoryItem.period_types.values)
.delete_all
# our relationship filters on enabled, this makes sure everything is deleted
@@ -216,70 +245,95 @@ class User < ActiveRecord::Base
# Cache for user custom fields. Currently it is used to display quick search results
attr_accessor :custom_data
- scope :with_email, ->(email) do
- joins(:user_emails).where("lower(user_emails.email) IN (?)", email)
- end
+ scope :with_email,
+ ->(email) { joins(:user_emails).where("lower(user_emails.email) IN (?)", email) }
- scope :with_primary_email, ->(email) do
- joins(:user_emails).where("lower(user_emails.email) IN (?) AND user_emails.primary", email)
- end
+ scope :with_primary_email,
+ ->(email) {
+ joins(:user_emails).where(
+ "lower(user_emails.email) IN (?) AND user_emails.primary",
+ email,
+ )
+ }
- scope :human_users, -> { where('users.id > 0') }
+ scope :human_users, -> { where("users.id > 0") }
# excluding fake users like the system user or anonymous users
- scope :real, -> { human_users.where('NOT EXISTS(
+ scope :real,
+ -> {
+ human_users.where(
+ "NOT EXISTS(
SELECT 1
FROM anonymous_users a
WHERE a.user_id = users.id
- )') }
+ )",
+ )
+ }
# TODO-PERF: There is no indexes on any of these
# and NotifyMailingListSubscribers does a select-all-and-loop
# may want to create an index on (active, silence, suspended_till)?
scope :silenced, -> { where("silenced_till IS NOT NULL AND silenced_till > ?", Time.zone.now) }
scope :not_silenced, -> { where("silenced_till IS NULL OR silenced_till <= ?", Time.zone.now) }
- scope :suspended, -> { where('suspended_till IS NOT NULL AND suspended_till > ?', Time.zone.now) }
- scope :not_suspended, -> { where('suspended_till IS NULL OR suspended_till <= ?', Time.zone.now) }
+ scope :suspended, -> { where("suspended_till IS NOT NULL AND suspended_till > ?", Time.zone.now) }
+ scope :not_suspended, -> { where("suspended_till IS NULL OR suspended_till <= ?", Time.zone.now) }
scope :activated, -> { where(active: true) }
scope :not_staged, -> { where(staged: false) }
- scope :filter_by_username, ->(filter) do
- if filter.is_a?(Array)
- where('username_lower ~* ?', "(#{filter.join('|')})")
- else
- where('username_lower ILIKE ?', "%#{filter}%")
- end
- end
+ scope :filter_by_username,
+ ->(filter) {
+ if filter.is_a?(Array)
+ where("username_lower ~* ?", "(#{filter.join("|")})")
+ else
+ where("username_lower ILIKE ?", "%#{filter}%")
+ end
+ }
- scope :filter_by_username_or_email, ->(filter) do
- if filter.is_a?(String) && filter =~ /.+@.+/
- # probably an email so try the bypass
- if user_id = UserEmail.where("lower(email) = ?", filter.downcase).pluck_first(:user_id)
- return where('users.id = ?', user_id)
- end
- end
+ scope :filter_by_username_or_email,
+ ->(filter) {
+ if filter.is_a?(String) && filter =~ /.+@.+/
+ # probably an email so try the bypass
+ if user_id = UserEmail.where("lower(email) = ?", filter.downcase).pluck_first(:user_id)
+ return where("users.id = ?", user_id)
+ end
+ end
- users = joins(:primary_email)
+ users = joins(:primary_email)
- if filter.is_a?(Array)
- users.where(
- 'username_lower ~* :filter OR lower(user_emails.email) SIMILAR TO :filter',
- filter: "(#{filter.join('|')})"
- )
- else
- users.where(
- 'username_lower ILIKE :filter OR lower(user_emails.email) ILIKE :filter',
- filter: "%#{filter}%"
- )
- end
- end
+ if filter.is_a?(Array)
+ users.where(
+ "username_lower ~* :filter OR lower(user_emails.email) SIMILAR TO :filter",
+ filter: "(#{filter.join("|")})",
+ )
+ else
+ users.where(
+ "username_lower ILIKE :filter OR lower(user_emails.email) ILIKE :filter",
+ filter: "%#{filter}%",
+ )
+ end
+ }
- scope :watching_topic, ->(topic) do
- joins(DB.sql_fragment("LEFT JOIN category_users ON category_users.user_id = users.id AND category_users.category_id = :category_id", category_id: topic.category_id))
- .joins(DB.sql_fragment("LEFT JOIN topic_users ON topic_users.user_id = users.id AND topic_users.topic_id = :topic_id", topic_id: topic.id))
- .joins("LEFT JOIN tag_users ON tag_users.user_id = users.id AND tag_users.tag_id IN (#{topic.tag_ids.join(",").presence || 'NULL'})")
- .where("category_users.notification_level > 0 OR topic_users.notification_level > 0 OR tag_users.notification_level > 0")
- end
+ scope :watching_topic,
+ ->(topic) {
+ joins(
+ DB.sql_fragment(
+ "LEFT JOIN category_users ON category_users.user_id = users.id AND category_users.category_id = :category_id",
+ category_id: topic.category_id,
+ ),
+ )
+ .joins(
+ DB.sql_fragment(
+ "LEFT JOIN topic_users ON topic_users.user_id = users.id AND topic_users.topic_id = :topic_id",
+ topic_id: topic.id,
+ ),
+ )
+ .joins(
+ "LEFT JOIN tag_users ON tag_users.user_id = users.id AND tag_users.tag_id IN (#{topic.tag_ids.join(",").presence || "NULL"})",
+ )
+ .where(
+ "category_users.notification_level > 0 OR topic_users.notification_level > 0 OR tag_users.notification_level > 0",
+ )
+ }
module NewTopicDuration
ALWAYS = -1
@@ -289,13 +343,14 @@ class User < ActiveRecord::Base
MAX_STAFF_DELETE_POST_COUNT ||= 5
def self.user_tips
- @user_tips ||= Enum.new(
- first_notification: 1,
- topic_timeline: 2,
- post_menu: 3,
- topic_notification_levels: 4,
- suggested_topics: 5,
- )
+ @user_tips ||=
+ Enum.new(
+ first_notification: 1,
+ topic_timeline: 2,
+ post_menu: 3,
+ topic_notification_levels: 4,
+ suggested_topics: 5,
+ )
end
def visible_sidebar_tags(user_guardian = nil)
@@ -318,10 +373,18 @@ class User < ActiveRecord::Base
def self.username_available?(username, email = nil, allow_reserved_username: false)
lower = normalize_username(username)
return false if !allow_reserved_username && reserved_username?(lower)
- return true if !username_exists?(lower)
+ return true if !username_exists?(lower)
# staged users can use the same username since they will take over the account
- email.present? && User.joins(:user_emails).exists?(staged: true, username_lower: lower, user_emails: { primary: true, email: email })
+ email.present? &&
+ User.joins(:user_emails).exists?(
+ staged: true,
+ username_lower: lower,
+ user_emails: {
+ primary: true,
+ email: email,
+ },
+ )
end
def self.reserved_username?(username)
@@ -329,9 +392,11 @@ class User < ActiveRecord::Base
return true if SiteSetting.here_mention == username
- SiteSetting.reserved_usernames.unicode_normalize.split("|").any? do |reserved|
- username.match?(/^#{Regexp.escape(reserved).gsub('\*', '.*')}$/)
- end
+ SiteSetting
+ .reserved_usernames
+ .unicode_normalize
+ .split("|")
+ .any? { |reserved| username.match?(/^#{Regexp.escape(reserved).gsub('\*', ".*")}$/) }
end
def self.editable_user_custom_fields(by_staff: false)
@@ -348,12 +413,12 @@ class User < ActiveRecord::Base
fields.push(*DiscoursePluginRegistry.public_user_custom_fields)
if SiteSetting.public_user_custom_fields.present?
- fields.push(*SiteSetting.public_user_custom_fields.split('|'))
+ fields.push(*SiteSetting.public_user_custom_fields.split("|"))
end
if guardian.is_staff?
if SiteSetting.staff_user_custom_fields.present?
- fields.push(*SiteSetting.staff_user_custom_fields.split('|'))
+ fields.push(*SiteSetting.staff_user_custom_fields.split("|"))
end
fields.push(*DiscoursePluginRegistry.staff_user_custom_fields)
@@ -386,7 +451,7 @@ class User < ActiveRecord::Base
bookmarks.where(bookmarkable_type: type)
end
- EMAIL = %r{([^@]+)@([^\.]+)}
+ EMAIL = /([^@]+)@([^\.]+)/
FROM_STAGED = "from_staged"
def self.new_from_params(params)
@@ -417,7 +482,7 @@ class User < ActiveRecord::Base
end
def self.find_by_username_or_email(username_or_email)
- if username_or_email.include?('@')
+ if username_or_email.include?("@")
find_by_email(username_or_email)
else
find_by_username(username_or_email)
@@ -445,10 +510,7 @@ class User < ActiveRecord::Base
end
def group_granted_trust_level
- GroupUser
- .where(user_id: id)
- .includes(:group)
- .maximum("groups.grant_trust_level")
+ GroupUser.where(user_id: id).includes(:group).maximum("groups.grant_trust_level")
end
def visible_groups
@@ -477,10 +539,10 @@ class User < ActiveRecord::Base
Jobs.enqueue(
:send_system_message,
user_id: id,
- message_type: 'welcome_staff',
+ message_type: "welcome_staff",
message_options: {
- role: role.to_s
- }
+ role: role.to_s,
+ },
)
end
@@ -501,7 +563,8 @@ class User < ActiveRecord::Base
end
def invited_by
- used_invite = Invite.with_deleted.joins(:invited_users).where("invited_users.user_id = ?", self.id).first
+ used_invite =
+ Invite.with_deleted.joins(:invited_users).where("invited_users.user_id = ?", self.id).first
used_invite.try(:invited_by)
end
@@ -605,7 +668,7 @@ class User < ActiveRecord::Base
args = {
user_id: self.id,
seen_notification_id: self.seen_notification_id,
- private_message: Notification.types[:private_message]
+ private_message: Notification.types[:private_message],
}
DB.query_single(<<~SQL, args).first
@@ -632,9 +695,10 @@ class User < ActiveRecord::Base
end
def unread_notifications
- @unread_notifications ||= begin
- # perf critical, much more efficient than AR
- sql = <<~SQL
+ @unread_notifications ||=
+ begin
+ # perf critical, much more efficient than AR
+ sql = <<~SQL
SELECT COUNT(*) FROM (
SELECT 1 FROM
notifications n
@@ -648,17 +712,21 @@ class User < ActiveRecord::Base
) AS X
SQL
- DB.query_single(sql,
- user_id: id,
- seen_notification_id: seen_notification_id,
- limit: User.max_unread_notifications
- )[0].to_i
- end
+ DB.query_single(
+ sql,
+ user_id: id,
+ seen_notification_id: seen_notification_id,
+ limit: User.max_unread_notifications,
+ )[
+ 0
+ ].to_i
+ end
end
def all_unread_notifications_count
- @all_unread_notifications_count ||= begin
- sql = <<~SQL
+ @all_unread_notifications_count ||=
+ begin
+ sql = <<~SQL
SELECT COUNT(*) FROM (
SELECT 1 FROM
notifications n
@@ -671,12 +739,15 @@ class User < ActiveRecord::Base
) AS X
SQL
- DB.query_single(sql,
- user_id: id,
- seen_notification_id: seen_notification_id,
- limit: User.max_unread_notifications
- )[0].to_i
- end
+ DB.query_single(
+ sql,
+ user_id: id,
+ seen_notification_id: seen_notification_id,
+ limit: User.max_unread_notifications,
+ )[
+ 0
+ ].to_i
+ end
end
def total_unread_notifications
@@ -684,10 +755,7 @@ class User < ActiveRecord::Base
end
def reviewable_count
- Reviewable.list_for(
- self,
- include_claimed_by_others: !redesigned_user_menu_enabled?
- ).count
+ Reviewable.list_for(self, include_claimed_by_others: !redesigned_user_menu_enabled?).count
end
def saw_notification_id(notification_id)
@@ -704,9 +772,7 @@ class User < ActiveRecord::Base
def bump_last_seen_notification!
query = self.notifications.visible
- if seen_notification_id
- query = query.where("notifications.id > ?", seen_notification_id)
- end
+ query = query.where("notifications.id > ?", seen_notification_id) if seen_notification_id
if max_notification_id = query.maximum(:id)
update!(seen_notification_id: max_notification_id)
true
@@ -718,9 +784,7 @@ class User < ActiveRecord::Base
def bump_last_seen_reviewable!
query = Reviewable.unseen_list_for(self, preload: false)
- if last_seen_reviewable_id
- query = query.where("reviewables.id > ?", last_seen_reviewable_id)
- end
+ query = query.where("reviewables.id > ?", last_seen_reviewable_id) if last_seen_reviewable_id
max_reviewable_id = query.maximum(:id)
if max_reviewable_id
@@ -732,7 +796,7 @@ class User < ActiveRecord::Base
def publish_reviewable_counts(extra_data = nil)
data = {
reviewable_count: self.reviewable_count,
- unseen_reviewable_count: Reviewable.unseen_reviewable_count(self)
+ unseen_reviewable_count: Reviewable.unseen_reviewable_count(self),
}
data.merge!(extra_data) if extra_data.present?
MessageBus.publish("/reviewable_counts/#{self.id}", data, user_ids: [self.id])
@@ -741,10 +805,13 @@ class User < ActiveRecord::Base
TRACK_FIRST_NOTIFICATION_READ_DURATION = 1.week.to_i
def read_first_notification?
- if (trust_level > TrustLevel[1] ||
- (first_seen_at.present? && first_seen_at < TRACK_FIRST_NOTIFICATION_READ_DURATION.seconds.ago) ||
- user_option.skip_new_user_tips)
-
+ if (
+ trust_level > TrustLevel[1] ||
+ (
+ first_seen_at.present? &&
+ first_seen_at < TRACK_FIRST_NOTIFICATION_READ_DURATION.seconds.ago
+ ) || user_option.skip_new_user_tips
+ )
return true
end
@@ -755,7 +822,7 @@ class User < ActiveRecord::Base
return if !self.allow_live_notifications?
# publish last notification json with the message so we can apply an update
- notification = notifications.visible.order('notifications.created_at desc').first
+ notification = notifications.visible.order("notifications.created_at desc").first
json = NotificationSerializer.new(notification).as_json if notification
sql = (<<~SQL)
@@ -783,9 +850,7 @@ class User < ActiveRecord::Base
) AS y
SQL
- recent = DB.query(sql, user_id: id).map! do |r|
- [r.id, r.read]
- end
+ recent = DB.query(sql, user_id: id).map! { |r| [r.id, r.read] }
payload = {
unread_notifications: unread_notifications,
@@ -800,7 +865,9 @@ class User < ActiveRecord::Base
if self.redesigned_user_menu_enabled?
payload[:all_unread_notifications_count] = all_unread_notifications_count
payload[:grouped_unread_notifications] = grouped_unread_notifications
- payload[:new_personal_messages_notifications_count] = new_personal_messages_notifications_count
+ payload[
+ :new_personal_messages_notifications_count
+ ] = new_personal_messages_notifications_count
end
MessageBus.publish("/notification/#{id}", payload, user_ids: [id])
@@ -815,24 +882,26 @@ class User < ActiveRecord::Base
payload = {
description: status.description,
emoji: status.emoji,
- ends_at: status.ends_at&.iso8601
+ ends_at: status.ends_at&.iso8601,
}
else
payload = nil
end
- MessageBus.publish("/user-status", { id => payload }, group_ids: [Group::AUTO_GROUPS[:trust_level_0]])
+ MessageBus.publish(
+ "/user-status",
+ { id => payload },
+ group_ids: [Group::AUTO_GROUPS[:trust_level_0]],
+ )
end
def password=(password)
# special case for passwordless accounts
- unless password.blank?
- @raw_password = password
- end
+ @raw_password = password unless password.blank?
end
def password
- '' # so that validator doesn't complain that a password attribute doesn't exist
+ "" # so that validator doesn't complain that a password attribute doesn't exist
end
# Indicate that this is NOT a passwordless account for the purposes of validation
@@ -862,14 +931,15 @@ class User < ActiveRecord::Base
end
def new_user_posting_on_first_day?
- !staff? &&
- trust_level < TrustLevel[2] &&
- (trust_level == TrustLevel[0] || self.first_post_created_at.nil? || self.first_post_created_at >= 24.hours.ago)
+ !staff? && trust_level < TrustLevel[2] &&
+ (
+ trust_level == TrustLevel[0] || self.first_post_created_at.nil? ||
+ self.first_post_created_at >= 24.hours.ago
+ )
end
def new_user?
- (created_at >= 24.hours.ago || trust_level == TrustLevel[0]) &&
- trust_level < TrustLevel[2] &&
+ (created_at >= 24.hours.ago || trust_level == TrustLevel[0]) && trust_level < TrustLevel[2] &&
!staff?
end
@@ -883,7 +953,11 @@ class User < ActiveRecord::Base
def create_visit_record!(date, opts = {})
user_stat.update_column(:days_visited, user_stat.days_visited + 1)
- user_visits.create!(visited_at: date, posts_read: opts[:posts_read] || 0, mobile: opts[:mobile] || false)
+ user_visits.create!(
+ visited_at: date,
+ posts_read: opts[:posts_read] || 0,
+ mobile: opts[:mobile] || false,
+ )
end
def visit_record_for(date)
@@ -898,9 +972,7 @@ class User < ActiveRecord::Base
return if timezone.blank? || !TimezoneValidator.valid?(timezone)
# we only want to update the user's timezone if they have not set it themselves
- UserOption
- .where(user_id: self.id, timezone: nil)
- .update_all(timezone: timezone)
+ UserOption.where(user_id: self.id, timezone: nil).update_all(timezone: timezone)
end
def update_posts_read!(num_posts, opts = {})
@@ -927,7 +999,6 @@ class User < ActiveRecord::Base
def self.update_ip_address!(user_id, new_ip:, old_ip:)
unless old_ip == new_ip || new_ip.blank?
-
DB.exec(<<~SQL, user_id: user_id, ip_address: new_ip)
UPDATE users
SET ip_address = :ip_address
@@ -979,9 +1050,10 @@ class User < ActiveRecord::Base
return true if SiteSetting.active_user_rate_limit_secs <= 0
Discourse.redis.set(
- last_seen_redis_key(user_id, now), "1",
+ last_seen_redis_key(user_id, now),
+ "1",
nx: true,
- ex: SiteSetting.active_user_rate_limit_secs
+ ex: SiteSetting.active_user_rate_limit_secs,
)
end
@@ -1015,9 +1087,12 @@ class User < ActiveRecord::Base
end
def self.username_hash(username)
- username.each_char.reduce(0) do |result, char|
- [((result << 5) - result) + char.ord].pack('L').unpack('l').first
- end.abs
+ username
+ .each_char
+ .reduce(0) do |result, char|
+ [((result << 5) - result) + char.ord].pack("L").unpack("l").first
+ end
+ .abs
end
def self.default_template(username)
@@ -1042,10 +1117,11 @@ class User < ActiveRecord::Base
# TODO it may be worth caching this in a distributed cache, should be benched
if SiteSetting.external_system_avatars_enabled
url = SiteSetting.external_system_avatars_url.dup
- url = +"#{Discourse.base_path}#{url}" unless url =~ /^https?:\/\//
+ url = +"#{Discourse.base_path}#{url}" unless url =~ %r{^https?://}
url.gsub! "{color}", letter_avatar_color(normalized_username)
url.gsub! "{username}", UrlHelper.encode_component(username)
- url.gsub! "{first_letter}", UrlHelper.encode_component(normalized_username.grapheme_clusters.first)
+ url.gsub! "{first_letter}",
+ UrlHelper.encode_component(normalized_username.grapheme_clusters.first)
url.gsub! "{hostname}", Discourse.current_hostname
url
else
@@ -1064,7 +1140,7 @@ class User < ActiveRecord::Base
colors[index, hex_length]
else
color = LetterAvatar::COLORS[color_index(username, LetterAvatar::COLORS.length)]
- color.map { |c| c.to_s(16).rjust(2, '0') }.join
+ color.map { |c| c.to_s(16).rjust(2, "0") }.join
end
end
@@ -1077,8 +1153,8 @@ class User < ActiveRecord::Base
end
def avatar_template
- use_small_logo = is_system_user? &&
- SiteSetting.logo_small && SiteSetting.use_site_small_logo_as_system_avatar
+ use_small_logo =
+ is_system_user? && SiteSetting.logo_small && SiteSetting.use_site_small_logo_as_system_avatar
if use_small_logo
Discourse.store.cdn_url(SiteSetting.logo_small.url)
@@ -1110,7 +1186,10 @@ class User < ActiveRecord::Base
end
def flags_given_count
- PostAction.where(user_id: id, post_action_type_id: PostActionType.flag_types_without_custom.values).count
+ PostAction.where(
+ user_id: id,
+ post_action_type_id: PostActionType.flag_types_without_custom.values,
+ ).count
end
def warnings_received_count
@@ -1118,7 +1197,10 @@ class User < ActiveRecord::Base
end
def flags_received_count
- posts.includes(:post_actions).where('post_actions.post_action_type_id' => PostActionType.flag_types_without_custom.values).count
+ posts
+ .includes(:post_actions)
+ .where("post_actions.post_action_type_id" => PostActionType.flag_types_without_custom.values)
+ .count
end
def private_topics_count
@@ -1134,7 +1216,7 @@ class User < ActiveRecord::Base
last_action_in_topic = UserAction.last_action_in_topic(id, topic_id)
since_reply = Post.where(user_id: id, topic_id: topic_id)
- since_reply = since_reply.where('id > ?', last_action_in_topic) if last_action_in_topic
+ since_reply = since_reply.where("id > ?", last_action_in_topic) if last_action_in_topic
(since_reply.count >= SiteSetting.newuser_max_replies_per_topic)
end
@@ -1144,9 +1226,10 @@ class User < ActiveRecord::Base
Reviewable.where(created_by_id: id).delete_all
- posts.order("post_number desc").limit(batch_size).each do |p|
- PostDestroyer.new(guardian.user, p).destroy
- end
+ posts
+ .order("post_number desc")
+ .limit(batch_size)
+ .each { |p| PostDestroyer.new(guardian.user, p).destroy }
end
def suspended?
@@ -1158,7 +1241,7 @@ class User < ActiveRecord::Base
end
def silenced_record
- UserHistory.for(self, :silence_user).order('id DESC').first
+ UserHistory.for(self, :silence_user).order("id DESC").first
end
def silence_reason
@@ -1174,7 +1257,7 @@ class User < ActiveRecord::Base
end
def suspend_record
- UserHistory.for(self, :suspend_user).order('id DESC').first
+ UserHistory.for(self, :suspend_user).order("id DESC").first
end
def full_suspend_reason
@@ -1201,9 +1284,11 @@ class User < ActiveRecord::Base
end
end
- I18n.t(message,
- date: I18n.l(suspended_till, format: :date_only),
- reason: Rack::Utils.escape_html(suspend_reason))
+ I18n.t(
+ message,
+ date: I18n.l(suspended_till, format: :date_only),
+ reason: Rack::Utils.escape_html(suspend_reason),
+ )
end
def suspended_forever?
@@ -1213,16 +1298,14 @@ class User < ActiveRecord::Base
# Use this helper to determine if the user has a particular trust level.
# Takes into account admin, etc.
def has_trust_level?(level)
- unless TrustLevel.valid?(level)
- raise InvalidTrustLevel.new("Invalid trust level #{level}")
- end
+ raise InvalidTrustLevel.new("Invalid trust level #{level}") unless TrustLevel.valid?(level)
admin? || moderator? || staged? || TrustLevel.compare(trust_level, level)
end
def has_trust_level_or_staff?(level)
- return admin? if level.to_s == 'admin'
- return staff? if level.to_s == 'staff'
+ return admin? if level.to_s == "admin"
+ return staff? if level.to_s == "staff"
has_trust_level?(level.to_i)
end
@@ -1236,13 +1319,12 @@ class User < ActiveRecord::Base
end
def username_format_validator
- UsernameValidator.perform_validation(self, 'username')
+ UsernameValidator.perform_validation(self, "username")
end
def email_confirmed?
- email_tokens.where(email: email, confirmed: true).present? ||
- email_tokens.empty? ||
- single_sign_on_record&.external_email&.downcase == email
+ email_tokens.where(email: email, confirmed: true).present? || email_tokens.empty? ||
+ single_sign_on_record&.external_email&.downcase == email
end
def activate
@@ -1297,11 +1379,16 @@ class User < ActiveRecord::Base
end
def self.count_by_first_post(start_date = nil, end_date = nil)
- result = joins('INNER JOIN user_stats AS us ON us.user_id = users.id')
+ result = joins("INNER JOIN user_stats AS us ON us.user_id = users.id")
if start_date && end_date
result = result.group("date(us.first_post_created_at)")
- result = result.where("us.first_post_created_at > ? AND us.first_post_created_at < ?", start_date, end_date)
+ result =
+ result.where(
+ "us.first_post_created_at > ? AND us.first_post_created_at < ?",
+ start_date,
+ end_date,
+ )
result = result.order("date(us.first_post_created_at)")
end
@@ -1316,7 +1403,7 @@ class User < ActiveRecord::Base
secure_categories.references(:categories)
end
- cats.pluck('categories.id').sort
+ cats.pluck("categories.id").sort
end
def topic_create_allowed_category_ids
@@ -1327,21 +1414,24 @@ class User < ActiveRecord::Base
def flag_linked_posts_as_spam
results = []
- disagreed_flag_post_ids = PostAction.where(post_action_type_id: PostActionType.types[:spam])
- .where.not(disagreed_at: nil)
- .pluck(:post_id)
+ disagreed_flag_post_ids =
+ PostAction
+ .where(post_action_type_id: PostActionType.types[:spam])
+ .where.not(disagreed_at: nil)
+ .pluck(:post_id)
- topic_links.includes(:post)
+ topic_links
+ .includes(:post)
.where.not(post_id: disagreed_flag_post_ids)
.each do |tl|
-
- message = I18n.t(
- 'flag_reason.spam_hosts',
- base_path: Discourse.base_path,
- locale: SiteSetting.default_locale
- )
- results << PostActionCreator.create(Discourse.system_user, tl.post, :spam, message: message)
- end
+ message =
+ I18n.t(
+ "flag_reason.spam_hosts",
+ base_path: Discourse.base_path,
+ locale: SiteSetting.default_locale,
+ )
+ results << PostActionCreator.create(Discourse.system_user, tl.post, :spam, message: message)
+ end
results
end
@@ -1351,7 +1441,12 @@ class User < ActiveRecord::Base
end
def find_email
- last_sent_email_address.present? && EmailAddressValidator.valid_value?(last_sent_email_address) ? last_sent_email_address : email
+ if last_sent_email_address.present? &&
+ EmailAddressValidator.valid_value?(last_sent_email_address)
+ last_sent_email_address
+ else
+ email
+ end
end
def tl3_requirements
@@ -1361,8 +1456,9 @@ class User < ActiveRecord::Base
def on_tl3_grace_period?
return true if SiteSetting.tl3_promotion_min_duration.to_i.days.ago.year < 2013
- UserHistory.for(self, :auto_trust_level_change)
- .where('created_at >= ?', SiteSetting.tl3_promotion_min_duration.to_i.days.ago)
+ UserHistory
+ .for(self, :auto_trust_level_change)
+ .where("created_at >= ?", SiteSetting.tl3_promotion_min_duration.to_i.days.ago)
.where(previous_value: TrustLevel[2].to_s)
.where(new_value: TrustLevel[3].to_s)
.exists?
@@ -1373,10 +1469,8 @@ class User < ActiveRecord::Base
avatar = user_avatar || create_user_avatar
- if self.primary_email.present? &&
- SiteSetting.automatically_download_gravatars? &&
- !avatar.last_gravatar_download_attempt
-
+ if self.primary_email.present? && SiteSetting.automatically_download_gravatars? &&
+ !avatar.last_gravatar_download_attempt
Jobs.cancel_scheduled_job(:update_gravatar, user_id: self.id, avatar_id: avatar.id)
Jobs.enqueue_in(1.second, :update_gravatar, user_id: self.id, avatar_id: avatar.id)
end
@@ -1395,10 +1489,7 @@ class User < ActiveRecord::Base
Discourse.authenticators.each do |authenticator|
account_description = authenticator.description_for_user(self)
unless account_description.empty?
- result << {
- name: authenticator.name,
- description: account_description,
- }
+ result << { name: authenticator.name, description: account_description }
end
end
@@ -1408,14 +1499,12 @@ class User < ActiveRecord::Base
USER_FIELD_PREFIX ||= "user_field_"
def user_fields(field_ids = nil)
- if field_ids.nil?
- field_ids = (@all_user_field_ids ||= UserField.pluck(:id))
- end
+ field_ids = (@all_user_field_ids ||= UserField.pluck(:id)) if field_ids.nil?
@user_fields_cache ||= {}
# Memoize based on requested fields
- @user_fields_cache[field_ids.join(':')] ||= {}.tap do |hash|
+ @user_fields_cache[field_ids.join(":")] ||= {}.tap do |hash|
field_ids.each do |fid|
# The hash keys are strings for backwards compatibility
hash[fid.to_s] = custom_fields["#{USER_FIELD_PREFIX}#{fid}"]
@@ -1439,16 +1528,14 @@ class User < ActiveRecord::Base
def validatable_user_fields
# ignore multiselect fields since they are admin-set and thus not user generated content
- @public_user_field_ids ||= UserField.public_fields.where.not(field_type: 'multiselect').pluck(:id)
+ @public_user_field_ids ||=
+ UserField.public_fields.where.not(field_type: "multiselect").pluck(:id)
user_fields(@public_user_field_ids)
end
def number_of_deleted_posts
- Post.with_deleted
- .where(user_id: self.id)
- .where.not(deleted_at: nil)
- .count
+ Post.with_deleted.where(user_id: self.id).where.not(deleted_at: nil).count
end
def number_of_flagged_posts
@@ -1456,14 +1543,12 @@ class User < ActiveRecord::Base
end
def number_of_rejected_posts
- ReviewableQueuedPost
- .rejected
- .where(created_by_id: self.id)
- .count
+ ReviewableQueuedPost.rejected.where(created_by_id: self.id).count
end
def number_of_flags_given
- PostAction.where(user_id: self.id)
+ PostAction
+ .where(user_id: self.id)
.where(disagreed_at: nil)
.where(post_action_type_id: PostActionType.notify_flag_type_ids)
.count
@@ -1487,9 +1572,7 @@ class User < ActiveRecord::Base
end
def anonymous?
- SiteSetting.allow_anonymous_posting &&
- trust_level >= 1 &&
- !!anonymous_user_master
+ SiteSetting.allow_anonymous_posting && trust_level >= 1 && !!anonymous_user_master
end
def is_singular_admin?
@@ -1504,25 +1587,23 @@ class User < ActiveRecord::Base
def logged_in
DiscourseEvent.trigger(:user_logged_in, self)
- if !self.seen_before?
- DiscourseEvent.trigger(:user_first_logged_in, self)
- end
+ DiscourseEvent.trigger(:user_first_logged_in, self) if !self.seen_before?
end
def set_automatic_groups
return if !active || staged || !email_confirmed?
- Group.where(automatic: false)
+ Group
+ .where(automatic: false)
.where("LENGTH(COALESCE(automatic_membership_email_domains, '')) > 0")
.each do |group|
+ domains = group.automatic_membership_email_domains.gsub(".", '\.')
- domains = group.automatic_membership_email_domains.gsub('.', '\.')
-
- if email =~ Regexp.new("@(#{domains})$", true) && !group.users.include?(self)
- group.add(self)
- GroupActionLogger.new(Discourse.system_user, group).log_add_user_to_group(self)
+ if email =~ Regexp.new("@(#{domains})$", true) && !group.users.include?(self)
+ group.add(self)
+ GroupActionLogger.new(Discourse.system_user, group).log_add_user_to_group(self)
+ end
end
- end
@belonging_to_group_ids = nil
end
@@ -1540,7 +1621,10 @@ class User < ActiveRecord::Base
build_primary_email email: new_email, skip_validate_email: !should_validate_email_address?
end
- if secondary_match = user_emails.detect { |ue| !ue.primary && Email.downcase(ue.email) == Email.downcase(new_email) }
+ if secondary_match =
+ user_emails.detect { |ue|
+ !ue.primary && Email.downcase(ue.email) == Email.downcase(new_email)
+ }
secondary_match.mark_for_destruction
primary_email.skip_validate_unique_email = true
end
@@ -1557,16 +1641,21 @@ class User < ActiveRecord::Base
end
def unconfirmed_emails
- self.email_change_requests.where.not(change_state: EmailChangeRequest.states[:complete]).pluck(:new_email)
+ self
+ .email_change_requests
+ .where.not(change_state: EmailChangeRequest.states[:complete])
+ .pluck(:new_email)
end
RECENT_TIME_READ_THRESHOLD ||= 60.days
def self.preload_recent_time_read(users)
- times = UserVisit.where(user_id: users.map(&:id))
- .where('visited_at >= ?', RECENT_TIME_READ_THRESHOLD.ago)
- .group(:user_id)
- .sum(:time_read)
+ times =
+ UserVisit
+ .where(user_id: users.map(&:id))
+ .where("visited_at >= ?", RECENT_TIME_READ_THRESHOLD.ago)
+ .group(:user_id)
+ .sum(:time_read)
users.each { |u| u.preload_recent_time_read(times[u.id] || 0) }
end
@@ -1575,7 +1664,8 @@ class User < ActiveRecord::Base
end
def recent_time_read
- @recent_time_read ||= self.user_visits.where('visited_at >= ?', RECENT_TIME_READ_THRESHOLD.ago).sum(:time_read)
+ @recent_time_read ||=
+ self.user_visits.where("visited_at >= ?", RECENT_TIME_READ_THRESHOLD.ago).sum(:time_read)
end
def from_staged?
@@ -1588,7 +1678,8 @@ class User < ActiveRecord::Base
def next_best_title
group_titles_query = groups.where("groups.title <> ''")
- group_titles_query = group_titles_query.order("groups.id = #{primary_group_id} DESC") if primary_group_id
+ group_titles_query =
+ group_titles_query.order("groups.id = #{primary_group_id} DESC") if primary_group_id
group_titles_query = group_titles_query.order("groups.primary_group DESC").limit(1)
if next_best_group_title = group_titles_query.pluck_first(:title)
@@ -1661,7 +1752,7 @@ class User < ActiveRecord::Base
def active_do_not_disturb_timings
now = Time.zone.now
- do_not_disturb_timings.where('starts_at <= ? AND ends_at > ?', now, now)
+ do_not_disturb_timings.where("starts_at <= ? AND ends_at > ?", now, now)
end
def do_not_disturb_until
@@ -1698,12 +1789,7 @@ class User < ActiveRecord::Base
end
def set_status!(description, emoji, ends_at = nil)
- status = {
- description: description,
- emoji: emoji,
- set_at: Time.zone.now,
- ends_at: ends_at
- }
+ status = { description: description, emoji: emoji, set_at: Time.zone.now, ends_at: ends_at }
if user_status
user_status.update!(status)
@@ -1730,7 +1816,7 @@ class User < ActiveRecord::Base
def expire_old_email_tokens
if saved_change_to_password_hash? && !saved_change_to_id?
- email_tokens.where('not expired').update_all(expired: true)
+ email_tokens.where("not expired").update_all(expired: true)
end
end
@@ -1785,7 +1871,12 @@ class User < ActiveRecord::Base
def hash_password(password, salt)
raise StandardError.new("password is too long") if password.size > User.max_password_length
- Pbkdf2.hash_password(password, salt, Rails.configuration.pbkdf2_iterations, Rails.configuration.pbkdf2_algorithm)
+ Pbkdf2.hash_password(
+ password,
+ salt,
+ Rails.configuration.pbkdf2_iterations,
+ Rails.configuration.pbkdf2_algorithm,
+ )
end
def add_trust_level
@@ -1815,25 +1906,22 @@ class User < ActiveRecord::Base
end
def username_validator
- username_format_validator || begin
- if will_save_change_to_username?
- existing = DB.query(
- USERNAME_EXISTS_SQL,
- username: self.class.normalize_username(username)
- )
+ username_format_validator ||
+ begin
+ if will_save_change_to_username?
+ existing =
+ DB.query(USERNAME_EXISTS_SQL, username: self.class.normalize_username(username))
- user_id = existing.select { |u| u.is_user }.first&.id
- same_user = user_id && user_id == self.id
+ user_id = existing.select { |u| u.is_user }.first&.id
+ same_user = user_id && user_id == self.id
- if existing.present? && !same_user
- errors.add(:username, I18n.t(:'user.username.unique'))
- end
+ errors.add(:username, I18n.t(:"user.username.unique")) if existing.present? && !same_user
- if confirm_password?(username) || confirm_password?(username.downcase)
- errors.add(:username, :same_as_password)
+ if confirm_password?(username) || confirm_password?(username.downcase)
+ errors.add(:username, :same_as_password)
+ end
end
end
- end
end
def name_validator
@@ -1858,14 +1946,14 @@ class User < ActiveRecord::Base
# * default_categories_watching_first_post
# * default_categories_normal
# * default_categories_muted
- %w{watching watching_first_post tracking normal muted}.each do |setting|
+ %w[watching watching_first_post tracking normal muted].each do |setting|
category_ids = SiteSetting.get("default_categories_#{setting}").split("|").map(&:to_i)
category_ids.each do |category_id|
next if category_id == 0
values << {
user_id: self.id,
category_id: category_id,
- notification_level: CategoryUser.notification_levels[setting.to_sym]
+ notification_level: CategoryUser.notification_levels[setting.to_sym],
}
end
end
@@ -1885,19 +1973,22 @@ class User < ActiveRecord::Base
# * default_tags_tracking
# * default_tags_watching_first_post
# * default_tags_muted
- %w{watching watching_first_post tracking muted}.each do |setting|
+ %w[watching watching_first_post tracking muted].each do |setting|
tag_names = SiteSetting.get("default_tags_#{setting}").split("|")
now = Time.zone.now
- Tag.where(name: tag_names).pluck(:id).each do |tag_id|
- values << {
- user_id: self.id,
- tag_id: tag_id,
- notification_level: TagUser.notification_levels[setting.to_sym],
- created_at: now,
- updated_at: now
- }
- end
+ Tag
+ .where(name: tag_names)
+ .pluck(:id)
+ .each do |tag_id|
+ values << {
+ user_id: self.id,
+ tag_id: tag_id,
+ notification_level: TagUser.notification_levels[setting.to_sym],
+ created_at: now,
+ updated_at: now,
+ }
+ end
end
TagUser.insert_all!(values) if values.present?
@@ -1912,20 +2003,24 @@ class User < ActiveRecord::Base
.where(active: false)
.where("created_at < ?", SiteSetting.purge_unactivated_users_grace_period_days.days.ago)
.where("NOT admin AND NOT moderator")
- .where("NOT EXISTS
+ .where(
+ "NOT EXISTS
(SELECT 1 FROM topic_allowed_users tu JOIN topics t ON t.id = tu.topic_id AND t.user_id > 0 WHERE tu.user_id = users.id LIMIT 1)
- ")
- .where("NOT EXISTS
+ ",
+ )
+ .where(
+ "NOT EXISTS
(SELECT 1 FROM posts p WHERE p.user_id = users.id LIMIT 1)
- ")
+ ",
+ )
.limit(200)
.find_each do |user|
- begin
- destroyer.destroy(user, context: I18n.t(:purge_reason))
- rescue Discourse::InvalidAccess
- # keep going
+ begin
+ destroyer.destroy(user, context: I18n.t(:purge_reason))
+ rescue Discourse::InvalidAccess
+ # keep going
+ end
end
- end
end
def match_primary_group_changes
@@ -1935,16 +2030,15 @@ class User < ActiveRecord::Base
self.title = primary_group&.title
end
- if flair_group_id == primary_group_id_was
- self.flair_group_id = primary_group&.id
- end
+ self.flair_group_id = primary_group&.id if flair_group_id == primary_group_id_was
end
def self.first_login_admin_id
- User.where(admin: true)
+ User
+ .where(admin: true)
.human_users
.joins(:user_auth_tokens)
- .order('user_auth_tokens.created_at')
+ .order("user_auth_tokens.created_at")
.pluck_first(:id)
end
@@ -1958,15 +2052,18 @@ class User < ActiveRecord::Base
categories_to_update = SiteSetting.default_sidebar_categories.split("|")
if update
- filtered_default_category_ids = Category.secured(self.guardian).where(id: categories_to_update).pluck(:id)
- existing_category_ids = SidebarSectionLink.where(user: self, linkable_type: 'Category').pluck(:linkable_id)
+ filtered_default_category_ids =
+ Category.secured(self.guardian).where(id: categories_to_update).pluck(:id)
+ existing_category_ids =
+ SidebarSectionLink.where(user: self, linkable_type: "Category").pluck(:linkable_id)
- categories_to_update = existing_category_ids + (filtered_default_category_ids & self.secure_category_ids)
+ categories_to_update =
+ existing_category_ids + (filtered_default_category_ids & self.secure_category_ids)
end
SidebarSectionLinksUpdater.update_category_section_links(
self,
- category_ids: categories_to_update
+ category_ids: categories_to_update,
)
end
@@ -1975,18 +2072,24 @@ class User < ActiveRecord::Base
if update
default_tag_ids = Tag.where(name: tags_to_update).pluck(:id)
- filtered_default_tags = DiscourseTagging.filter_visible(Tag, self.guardian).where(id: default_tag_ids).pluck(:name)
+ filtered_default_tags =
+ DiscourseTagging
+ .filter_visible(Tag, self.guardian)
+ .where(id: default_tag_ids)
+ .pluck(:name)
- existing_tag_ids = SidebarSectionLink.where(user: self, linkable_type: 'Tag').pluck(:linkable_id)
- existing_tags = DiscourseTagging.filter_visible(Tag, self.guardian).where(id: existing_tag_ids).pluck(:name)
+ existing_tag_ids =
+ SidebarSectionLink.where(user: self, linkable_type: "Tag").pluck(:linkable_id)
+ existing_tags =
+ DiscourseTagging
+ .filter_visible(Tag, self.guardian)
+ .where(id: existing_tag_ids)
+ .pluck(:name)
tags_to_update = existing_tags + (filtered_default_tags & DiscourseTagging.hidden_tag_names)
end
- SidebarSectionLinksUpdater.update_tag_section_links(
- self,
- tag_names: tags_to_update
- )
+ SidebarSectionLinksUpdater.update_tag_section_links(self, tag_names: tags_to_update)
end
end
@@ -2003,9 +2106,7 @@ class User < ActiveRecord::Base
end
def trigger_user_automatic_group_refresh
- if !staged
- Group.user_trust_level_change!(id, trust_level)
- end
+ Group.user_trust_level_change!(id, trust_level) if !staged
true
end
@@ -2016,12 +2117,14 @@ class User < ActiveRecord::Base
def check_if_title_is_badged_granted
if title_changed? && !new_record? && user_profile
- badge_matching_title = title && badges.find do |badge|
- badge.allow_title? && (badge.display_name == title || badge.name == title)
- end
+ badge_matching_title =
+ title &&
+ badges.find do |badge|
+ badge.allow_title? && (badge.display_name == title || badge.name == title)
+ end
user_profile.update(
badge_granted_title: badge_matching_title.present?,
- granted_title_badge_id: badge_matching_title&.id
+ granted_title_badge_id: badge_matching_title&.id,
)
end
end
@@ -2032,9 +2135,7 @@ class User < ActiveRecord::Base
def update_previous_visit(timestamp)
update_visit_record!(timestamp.to_date)
- if previous_visit_at_update_required?(timestamp)
- update_column(:previous_visit_at, last_seen_at)
- end
+ update_column(:previous_visit_at, last_seen_at) if previous_visit_at_update_required?(timestamp)
end
def trigger_user_created_event
@@ -2048,16 +2149,14 @@ class User < ActiveRecord::Base
end
def set_skip_validate_email
- if self.primary_email
- self.primary_email.skip_validate_email = !should_validate_email_address?
- end
+ self.primary_email.skip_validate_email = !should_validate_email_address? if self.primary_email
true
end
def check_site_contact_username
if (saved_change_to_admin? || saved_change_to_moderator?) &&
- self.username == SiteSetting.site_contact_username && !staff?
+ self.username == SiteSetting.site_contact_username && !staff?
SiteSetting.set_and_log(:site_contact_username, SiteSetting.defaults[:site_contact_username])
end
end
diff --git a/app/models/user_action.rb b/app/models/user_action.rb
index 25eabac3ff4..d605324de47 100644
--- a/app/models/user_action.rb
+++ b/app/models/user_action.rb
@@ -21,59 +21,58 @@ class UserAction < ActiveRecord::Base
SOLVED = 15
ASSIGNED = 16
- ORDER = Hash[*[
- GOT_PRIVATE_MESSAGE,
- NEW_PRIVATE_MESSAGE,
- NEW_TOPIC,
- REPLY,
- RESPONSE,
- LIKE,
- WAS_LIKED,
- MENTION,
- QUOTE,
- EDIT,
- SOLVED,
- ASSIGNED,
- ].each_with_index.to_a.flatten]
+ ORDER =
+ Hash[
+ *[
+ GOT_PRIVATE_MESSAGE,
+ NEW_PRIVATE_MESSAGE,
+ NEW_TOPIC,
+ REPLY,
+ RESPONSE,
+ LIKE,
+ WAS_LIKED,
+ MENTION,
+ QUOTE,
+ EDIT,
+ SOLVED,
+ ASSIGNED,
+ ].each_with_index.to_a.flatten
+ ]
USER_ACTED_TYPES = [LIKE, NEW_TOPIC, REPLY, NEW_PRIVATE_MESSAGE]
def self.types
- @types ||= Enum.new(
- like: 1,
- was_liked: 2,
- # NOTE: Previously type 3 was bookmark but this was removed when we
- # changed to using the Bookmark model.
- new_topic: 4,
- reply: 5,
- response: 6,
- mention: 7,
- quote: 9,
- edit: 11,
- new_private_message: 12,
- got_private_message: 13,
- solved: 15,
- assigned: 16)
+ @types ||=
+ Enum.new(
+ like: 1,
+ was_liked: 2,
+ # NOTE: Previously type 3 was bookmark but this was removed when we
+ # changed to using the Bookmark model.
+ new_topic: 4,
+ reply: 5,
+ response: 6,
+ mention: 7,
+ quote: 9,
+ edit: 11,
+ new_private_message: 12,
+ got_private_message: 13,
+ solved: 15,
+ assigned: 16,
+ )
end
def self.private_types
- @private_types ||= [
- WAS_LIKED,
- RESPONSE,
- MENTION,
- QUOTE,
- EDIT
- ]
+ @private_types ||= [WAS_LIKED, RESPONSE, MENTION, QUOTE, EDIT]
end
def self.last_action_in_topic(user_id, topic_id)
- UserAction.where(user_id: user_id,
- target_topic_id: topic_id,
- action_type: [RESPONSE, MENTION, QUOTE]).order('created_at DESC').pluck_first(:target_post_id)
+ UserAction
+ .where(user_id: user_id, target_topic_id: topic_id, action_type: [RESPONSE, MENTION, QUOTE])
+ .order("created_at DESC")
+ .pluck_first(:target_post_id)
end
def self.stats(user_id, guardian)
-
# Sam: I tried this in AR and it got complex
builder = DB.build <<~SQL
@@ -87,7 +86,7 @@ class UserAction < ActiveRecord::Base
GROUP BY action_type
SQL
- builder.where('a.user_id = :user_id', user_id: user_id)
+ builder.where("a.user_id = :user_id", user_id: user_id)
apply_common_filters(builder, user_id, guardian)
@@ -128,23 +127,20 @@ class UserAction < ActiveRecord::Base
result = { all: all, mine: mine, unread: unread }
- DB.query(sql, user_id: user_id).each do |row|
- (result[:groups] ||= []) << { name: row.name, count: row.count.to_i }
- end
+ DB
+ .query(sql, user_id: user_id)
+ .each { |row| (result[:groups] ||= []) << { name: row.name, count: row.count.to_i } }
result
-
end
def self.count_daily_engaged_users(start_date = nil, end_date = nil)
- result = select(:user_id)
- .distinct
- .where(action_type: USER_ACTED_TYPES)
+ result = select(:user_id).distinct.where(action_type: USER_ACTED_TYPES)
if start_date && end_date
- result = result.group('date(created_at)')
- result = result.where('created_at > ? AND created_at < ?', start_date, end_date)
- result = result.order('date(created_at)')
+ result = result.group("date(created_at)")
+ result = result.where("created_at > ? AND created_at < ?", start_date, end_date)
+ result = result.order("date(created_at)")
end
result.count
@@ -154,28 +150,29 @@ class UserAction < ActiveRecord::Base
stream(action_id: action_id, guardian: guardian).first
end
- NULL_QUEUED_STREAM_COLS = %i{
- cooked
- uploaded_avatar_id
- acting_name
- acting_username
- acting_user_id
- target_name
- target_username
- target_user_id
- post_number
- post_id
- deleted
- hidden
- post_type
- action_type
- action_code
- action_code_who
- action_code_path
- topic_closed
- topic_id
- topic_archived
- }.map! { |s| "NULL as #{s}" }.join(", ")
+ NULL_QUEUED_STREAM_COLS =
+ %i[
+ cooked
+ uploaded_avatar_id
+ acting_name
+ acting_username
+ acting_user_id
+ target_name
+ target_username
+ target_user_id
+ post_number
+ post_id
+ deleted
+ hidden
+ post_type
+ action_type
+ action_code
+ action_code_who
+ action_code_path
+ topic_closed
+ topic_id
+ topic_archived
+ ].map! { |s| "NULL as #{s}" }.join(", ")
def self.stream(opts = nil)
opts ||= {}
@@ -191,13 +188,10 @@ class UserAction < ActiveRecord::Base
# Acting user columns. Can be extended by plugins to include custom avatar
# columns
- acting_cols = [
- 'u.id AS acting_user_id',
- 'u.name AS acting_name'
- ]
+ acting_cols = ["u.id AS acting_user_id", "u.name AS acting_name"]
UserLookup.lookup_columns.each do |c|
- next if c == :id || c['.']
+ next if c == :id || c["."]
acting_cols << "u.#{c} AS acting_#{c}"
end
@@ -213,7 +207,7 @@ class UserAction < ActiveRecord::Base
p.reply_to_post_number,
pu.username, pu.name, pu.id user_id,
pu.uploaded_avatar_id,
- #{acting_cols.join(', ')},
+ #{acting_cols.join(", ")},
coalesce(p.cooked, p2.cooked) cooked,
CASE WHEN coalesce(p.deleted_at, p2.deleted_at, t.deleted_at) IS NULL THEN false ELSE true END deleted,
p.hidden,
@@ -245,11 +239,14 @@ class UserAction < ActiveRecord::Base
builder.where("a.id = :id", id: action_id.to_i)
else
builder.where("a.user_id = :user_id", user_id: user_id.to_i)
- builder.where("a.action_type in (:action_types)", action_types: action_types) if action_types && action_types.length > 0
+ if action_types && action_types.length > 0
+ builder.where("a.action_type in (:action_types)", action_types: action_types)
+ end
if acting_username
- builder.where("u.username_lower = :acting_username",
- acting_username: acting_username.downcase
+ builder.where(
+ "u.username_lower = :acting_username",
+ acting_username: acting_username.downcase,
)
end
@@ -257,17 +254,14 @@ class UserAction < ActiveRecord::Base
builder.where("a.action_type <> :mention_type", mention_type: UserAction::MENTION)
end
- builder
- .order_by("a.created_at desc")
- .offset(offset.to_i)
- .limit(limit.to_i)
+ builder.order_by("a.created_at desc").offset(offset.to_i).limit(limit.to_i)
end
builder.query
end
def self.log_action!(hash)
- required_parameters = [:action_type, :user_id, :acting_user_id]
+ required_parameters = %i[action_type user_id acting_user_id]
required_parameters << :target_post_id
required_parameters << :target_topic_id
@@ -284,18 +278,14 @@ class UserAction < ActiveRecord::Base
action = self.new(hash)
- if hash[:created_at]
- action.created_at = hash[:created_at]
- end
+ action.created_at = hash[:created_at] if hash[:created_at]
action.save!
user_id = hash[:user_id]
topic = Topic.includes(:category).find_by(id: hash[:target_topic_id])
- if topic && !topic.private_message?
- update_like_count(user_id, hash[:action_type], 1)
- end
+ update_like_count(user_id, hash[:action_type], 1) if topic && !topic.private_message?
group_ids = nil
if topic && topic.category && topic.category.read_restricted
@@ -304,11 +294,15 @@ class UserAction < ActiveRecord::Base
end
if action.user
- MessageBus.publish("/u/#{action.user.username_lower}", action.id, user_ids: [user_id], group_ids: group_ids)
+ MessageBus.publish(
+ "/u/#{action.user.username_lower}",
+ action.id,
+ user_ids: [user_id],
+ group_ids: group_ids,
+ )
end
action
-
rescue ActiveRecord::RecordNotUnique
# can happen, don't care already logged
raise ActiveRecord::Rollback
@@ -317,7 +311,14 @@ class UserAction < ActiveRecord::Base
end
def self.remove_action!(hash)
- require_parameters(hash, :action_type, :user_id, :acting_user_id, :target_topic_id, :target_post_id)
+ require_parameters(
+ hash,
+ :action_type,
+ :user_id,
+ :acting_user_id,
+ :target_topic_id,
+ :target_post_id,
+ )
if action = UserAction.find_by(hash.except(:created_at))
action.destroy
MessageBus.publish("/user/#{hash[:user_id]}", user_action_id: action.id, remove: true)
@@ -329,7 +330,6 @@ class UserAction < ActiveRecord::Base
end
def self.synchronize_target_topic_ids(post_ids = nil, limit: nil)
-
# nuke all dupes, using magic
builder = DB.build <<~SQL
DELETE FROM user_actions USING user_actions ua2
@@ -345,19 +345,15 @@ class UserAction < ActiveRecord::Base
user_actions.id > ua2.id
SQL
- if limit
- builder.where(<<~SQL, limit: limit)
+ builder.where(<<~SQL, limit: limit) if limit
user_actions.target_post_id IN (
SELECT target_post_id
FROM user_actions
WHERE created_at > :limit
)
SQL
- end
- if post_ids
- builder.where("user_actions.target_post_id in (:post_ids)", post_ids: post_ids)
- end
+ builder.where("user_actions.target_post_id in (:post_ids)", post_ids: post_ids) if post_ids
builder.exec
@@ -368,19 +364,15 @@ class UserAction < ActiveRecord::Base
SQL
builder.where("target_topic_id <> (select topic_id from posts where posts.id = target_post_id)")
- if post_ids
- builder.where("target_post_id in (:post_ids)", post_ids: post_ids)
- end
+ builder.where("target_post_id in (:post_ids)", post_ids: post_ids) if post_ids
- if limit
- builder.where(<<~SQL, limit: limit)
+ builder.where(<<~SQL, limit: limit) if limit
target_post_id IN (
SELECT target_post_id
FROM user_actions
WHERE created_at > :limit
)
SQL
- end
builder.exec
end
@@ -407,11 +399,17 @@ class UserAction < ActiveRecord::Base
current_user_id = -2
current_user_id = guardian.user.id if guardian.user
- builder.where("NOT COALESCE(p.hidden, false) OR p.user_id = :current_user_id", current_user_id: current_user_id)
+ builder.where(
+ "NOT COALESCE(p.hidden, false) OR p.user_id = :current_user_id",
+ current_user_id: current_user_id,
+ )
end
visible_post_types = Topic.visible_post_types(guardian.user)
- builder.where("COALESCE(p.post_type, p2.post_type) IN (:visible_post_types)", visible_post_types: visible_post_types)
+ builder.where(
+ "COALESCE(p.post_type, p2.post_type) IN (:visible_post_types)",
+ visible_post_types: visible_post_types,
+ )
unless (guardian.user && guardian.user.id == user_id) || guardian.is_staff?
builder.where("t.visible")
@@ -423,7 +421,7 @@ class UserAction < ActiveRecord::Base
def self.filter_private_messages(builder, user_id, guardian, ignore_private_messages = false)
if !guardian.can_see_private_messages?(user_id) || ignore_private_messages || !guardian.user
- builder.where("t.archetype <> :private_message", private_message: Archetype::private_message)
+ builder.where("t.archetype <> :private_message", private_message: Archetype.private_message)
else
unless guardian.is_admin?
sql = <<~SQL
@@ -438,7 +436,11 @@ class UserAction < ActiveRecord::Base
)
SQL
- builder.where(sql, private_message: Archetype::private_message, current_user_id: guardian.user.id)
+ builder.where(
+ sql,
+ private_message: Archetype.private_message,
+ current_user_id: guardian.user.id,
+ )
end
end
builder
@@ -448,9 +450,12 @@ class UserAction < ActiveRecord::Base
unless guardian.is_admin?
allowed = guardian.secure_category_ids
if allowed.present?
- builder.where("( c.read_restricted IS NULL OR
+ builder.where(
+ "( c.read_restricted IS NULL OR
NOT c.read_restricted OR
- (c.read_restricted and c.id in (:cats)) )", cats: guardian.secure_category_ids)
+ (c.read_restricted and c.id in (:cats)) )",
+ cats: guardian.secure_category_ids,
+ )
else
builder.where("(c.read_restricted IS NULL OR NOT c.read_restricted)")
end
@@ -459,9 +464,7 @@ class UserAction < ActiveRecord::Base
end
def self.require_parameters(data, *params)
- params.each do |p|
- raise Discourse::InvalidParameters.new(p) if data[p].nil?
- end
+ params.each { |p| raise Discourse::InvalidParameters.new(p) if data[p].nil? }
end
end
diff --git a/app/models/user_api_key.rb b/app/models/user_api_key.rb
index d0238781bc7..59815a5c70c 100644
--- a/app/models/user_api_key.rb
+++ b/app/models/user_api_key.rb
@@ -2,7 +2,7 @@
class UserApiKey < ActiveRecord::Base
self.ignored_columns = [
- "scopes" # TODO(2020-12-18): remove
+ "scopes", # TODO(2020-12-18): remove
]
REVOKE_MATCHER = RouteMatcher.new(actions: "user_api_keys#revoke", methods: :post, params: [:id])
@@ -23,7 +23,9 @@ class UserApiKey < ActiveRecord::Base
end
def key
- raise ApiKey::KeyAccessError.new "API key is only accessible immediately after creation" unless key_available?
+ unless key_available?
+ raise ApiKey::KeyAccessError.new "API key is only accessible immediately after creation"
+ end
@key
end
@@ -41,7 +43,7 @@ class UserApiKey < ActiveRecord::Base
# invalidate old dupe api key for client if needed
UserApiKey
.where(client_id: client_id, user_id: self.user_id)
- .where('id <> ?', self.id)
+ .where("id <> ?", self.id)
.destroy_all
update_args[:client_id] = client_id
@@ -59,8 +61,7 @@ class UserApiKey < ActiveRecord::Base
end
def has_push?
- scopes.any? { |s| s.name == "push" || s.name == "notifications" } &&
- push_url.present? &&
+ scopes.any? { |s| s.name == "push" || s.name == "notifications" } && push_url.present? &&
SiteSetting.allowed_user_api_push_urls.include?(push_url)
end
@@ -69,8 +70,9 @@ class UserApiKey < ActiveRecord::Base
end
def self.invalid_auth_redirect?(auth_redirect)
- SiteSetting.allowed_user_api_auth_redirects
- .split('|')
+ SiteSetting
+ .allowed_user_api_auth_redirects
+ .split("|")
.none? { |u| WildcardUrlChecker.check_url(u, auth_redirect) }
end
diff --git a/app/models/user_api_key_scope.rb b/app/models/user_api_key_scope.rb
index d2f0c408a36..0ea94279649 100644
--- a/app/models/user_api_key_scope.rb
+++ b/app/models/user_api_key_scope.rb
@@ -2,26 +2,33 @@
class UserApiKeyScope < ActiveRecord::Base
SCOPES = {
- read: [ RouteMatcher.new(methods: :get) ],
- write: [ RouteMatcher.new(methods: [:get, :post, :patch, :put, :delete]) ],
- message_bus: [ RouteMatcher.new(methods: :post, actions: 'message_bus') ],
+ read: [RouteMatcher.new(methods: :get)],
+ write: [RouteMatcher.new(methods: %i[get post patch put delete])],
+ message_bus: [RouteMatcher.new(methods: :post, actions: "message_bus")],
push: [],
one_time_password: [],
notifications: [
- RouteMatcher.new(methods: :post, actions: 'message_bus'),
- RouteMatcher.new(methods: :get, actions: 'notifications#index'),
- RouteMatcher.new(methods: :put, actions: 'notifications#mark_read')
+ RouteMatcher.new(methods: :post, actions: "message_bus"),
+ RouteMatcher.new(methods: :get, actions: "notifications#index"),
+ RouteMatcher.new(methods: :put, actions: "notifications#mark_read"),
],
session_info: [
- RouteMatcher.new(methods: :get, actions: 'session#current'),
- RouteMatcher.new(methods: :get, actions: 'users#topic_tracking_state')
+ RouteMatcher.new(methods: :get, actions: "session#current"),
+ RouteMatcher.new(methods: :get, actions: "users#topic_tracking_state"),
+ ],
+ bookmarks_calendar: [
+ RouteMatcher.new(
+ methods: :get,
+ actions: "users#bookmarks",
+ formats: :ics,
+ params: %i[username],
+ ),
],
- bookmarks_calendar: [ RouteMatcher.new(methods: :get, actions: 'users#bookmarks', formats: :ics, params: %i[username]) ],
user_status: [
- RouteMatcher.new(methods: :get, actions: 'user_status#get'),
- RouteMatcher.new(methods: :put, actions: 'user_status#set'),
- RouteMatcher.new(methods: :delete, actions: 'user_status#clear')
- ]
+ RouteMatcher.new(methods: :get, actions: "user_status#get"),
+ RouteMatcher.new(methods: :put, actions: "user_status#set"),
+ RouteMatcher.new(methods: :delete, actions: "user_status#clear"),
+ ],
}
def self.all_scopes
diff --git a/app/models/user_archived_message.rb b/app/models/user_archived_message.rb
index 2410f50e2e2..787209c702c 100644
--- a/app/models/user_archived_message.rb
+++ b/app/models/user_archived_message.rb
@@ -7,11 +7,15 @@ class UserArchivedMessage < ActiveRecord::Base
def self.move_to_inbox!(user_id, topic)
topic_id = topic.id
- return if (TopicUser.where(
- user_id: user_id,
- topic_id: topic_id,
- notification_level: TopicUser.notification_levels[:muted]
- ).exists?)
+ if (
+ TopicUser.where(
+ user_id: user_id,
+ topic_id: topic_id,
+ notification_level: TopicUser.notification_levels[:muted],
+ ).exists?
+ )
+ return
+ end
UserArchivedMessage.where(user_id: user_id, topic_id: topic_id).destroy_all
trigger(:move_to_inbox, user_id, topic_id)
@@ -29,9 +33,7 @@ class UserArchivedMessage < ActiveRecord::Base
def self.trigger(event, user_id, topic_id)
user = User.find_by(id: user_id)
topic = Topic.find_by(id: topic_id)
- if user && topic
- DiscourseEvent.trigger(event, user: user, topic: topic)
- end
+ DiscourseEvent.trigger(event, user: user, topic: topic) if user && topic
end
end
diff --git a/app/models/user_associated_group.rb b/app/models/user_associated_group.rb
index 1413efb7c67..815309d1aaa 100644
--- a/app/models/user_associated_group.rb
+++ b/app/models/user_associated_group.rb
@@ -4,7 +4,7 @@ class UserAssociatedGroup < ActiveRecord::Base
belongs_to :user
belongs_to :associated_group
- after_commit :add_to_associated_groups, on: [:create, :update]
+ after_commit :add_to_associated_groups, on: %i[create update]
before_destroy :remove_from_associated_groups
def add_to_associated_groups
@@ -14,7 +14,9 @@ class UserAssociatedGroup < ActiveRecord::Base
end
def remove_from_associated_groups
- Group.where("NOT EXISTS(
+ Group
+ .where(
+ "NOT EXISTS(
SELECT 1
FROM user_associated_groups uag
JOIN group_associated_groups gag
@@ -22,9 +24,11 @@ class UserAssociatedGroup < ActiveRecord::Base
WHERE uag.user_id = :user_id
AND uag.id != :uag_id
AND gag.group_id = groups.id
- )", uag_id: id, user_id: user_id).each do |group|
- group.remove_automatically(user, subject: associated_group.label)
- end
+ )",
+ uag_id: id,
+ user_id: user_id,
+ )
+ .each { |group| group.remove_automatically(user, subject: associated_group.label) }
end
end
diff --git a/app/models/user_auth_token.rb b/app/models/user_auth_token.rb
index 6566371b206..97eb0372ff7 100644
--- a/app/models/user_auth_token.rb
+++ b/app/models/user_auth_token.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'digest/sha1'
+require "digest/sha1"
class UserAuthToken < ActiveRecord::Base
belongs_to :user
@@ -11,13 +11,13 @@ class UserAuthToken < ActiveRecord::Base
MAX_SESSION_COUNT = 60
- USER_ACTIONS = ['generate']
+ USER_ACTIONS = ["generate"]
attr_accessor :unhashed_auth_token
before_destroy do
UserAuthToken.log_verbose(
- action: 'destroy',
+ action: "destroy",
user_auth_token_id: self.id,
user_id: self.user_id,
user_agent: self.user_agent,
@@ -31,9 +31,7 @@ class UserAuthToken < ActiveRecord::Base
end
def self.log_verbose(info)
- if SiteSetting.verbose_auth_token_logging
- log(info)
- end
+ log(info) if SiteSetting.verbose_auth_token_logging
end
RAD_PER_DEG = Math::PI / 180
@@ -49,8 +47,10 @@ class UserAuthToken < ActiveRecord::Base
lat1_rad, lon1_rad = loc1[0] * RAD_PER_DEG, loc1[1] * RAD_PER_DEG
lat2_rad, lon2_rad = loc2[0] * RAD_PER_DEG, loc2[1] * RAD_PER_DEG
- a = Math.sin((lat2_rad - lat1_rad) / 2)**2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin((lon2_rad - lon1_rad) / 2)**2
- c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1 - a))
+ a =
+ Math.sin((lat2_rad - lat1_rad) / 2)**2 +
+ Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin((lon2_rad - lon1_rad) / 2)**2
+ c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
c * EARTH_RADIUS_KM
end
@@ -72,21 +72,29 @@ class UserAuthToken < ActiveRecord::Base
end
end
- def self.generate!(user_id: , user_agent: nil, client_ip: nil, path: nil, staff: nil, impersonate: false)
+ def self.generate!(
+ user_id:,
+ user_agent: nil,
+ client_ip: nil,
+ path: nil,
+ staff: nil,
+ impersonate: false
+ )
token = SecureRandom.hex(16)
hashed_token = hash_token(token)
- user_auth_token = UserAuthToken.create!(
- user_id: user_id,
- user_agent: user_agent,
- client_ip: client_ip,
- auth_token: hashed_token,
- prev_auth_token: hashed_token,
- rotated_at: Time.zone.now
- )
+ user_auth_token =
+ UserAuthToken.create!(
+ user_id: user_id,
+ user_agent: user_agent,
+ client_ip: client_ip,
+ auth_token: hashed_token,
+ prev_auth_token: hashed_token,
+ rotated_at: Time.zone.now,
+ )
user_auth_token.unhashed_auth_token = token
log(
- action: 'generate',
+ action: "generate",
user_auth_token_id: user_auth_token.id,
user_id: user_id,
user_agent: user_agent,
@@ -96,10 +104,12 @@ class UserAuthToken < ActiveRecord::Base
)
if staff && !impersonate
- Jobs.enqueue(:suspicious_login,
+ Jobs.enqueue(
+ :suspicious_login,
user_id: user_id,
client_ip: client_ip,
- user_agent: user_agent)
+ user_agent: user_agent,
+ )
end
user_auth_token
@@ -111,12 +121,15 @@ class UserAuthToken < ActiveRecord::Base
token = hash_token(unhashed_token)
expire_before = SiteSetting.maximum_session_age.hours.ago
- user_token = find_by("(auth_token = :token OR
+ user_token =
+ find_by(
+ "(auth_token = :token OR
prev_auth_token = :token) AND rotated_at > :expire_before",
- token: token, expire_before: expire_before)
+ token: token,
+ expire_before: expire_before,
+ )
if !user_token
-
log_verbose(
action: "miss token",
user_id: nil,
@@ -129,11 +142,13 @@ class UserAuthToken < ActiveRecord::Base
return nil
end
- if user_token.auth_token != token && user_token.prev_auth_token == token && user_token.auth_token_seen
- changed_rows = UserAuthToken
- .where("rotated_at < ?", 1.minute.ago)
- .where(id: user_token.id, prev_auth_token: token)
- .update_all(auth_token_seen: false)
+ if user_token.auth_token != token && user_token.prev_auth_token == token &&
+ user_token.auth_token_seen
+ changed_rows =
+ UserAuthToken
+ .where("rotated_at < ?", 1.minute.ago)
+ .where(id: user_token.id, prev_auth_token: token)
+ .update_all(auth_token_seen: false)
# not updating AR model cause we want to give it one more req
# with wrong cookie
@@ -144,15 +159,17 @@ class UserAuthToken < ActiveRecord::Base
auth_token: user_token.auth_token,
user_agent: opts && opts[:user_agent],
path: opts && opts[:path],
- client_ip: opts && opts[:client_ip]
+ client_ip: opts && opts[:client_ip],
)
end
if mark_seen && user_token && !user_token.auth_token_seen && user_token.auth_token == token
# we must protect against concurrency issues here
- changed_rows = UserAuthToken
- .where(id: user_token.id, auth_token: token)
- .update_all(auth_token_seen: true, seen_at: Time.zone.now)
+ changed_rows =
+ UserAuthToken.where(id: user_token.id, auth_token: token).update_all(
+ auth_token_seen: true,
+ seen_at: Time.zone.now,
+ )
if changed_rows == 1
# not doing a reload so we don't risk loading a rotated token
@@ -179,15 +196,17 @@ class UserAuthToken < ActiveRecord::Base
end
def self.cleanup!
-
if SiteSetting.verbose_auth_token_logging
- UserAuthTokenLog.where('created_at < :time',
- time: SiteSetting.maximum_session_age.hours.ago - ROTATE_TIME).delete_all
+ UserAuthTokenLog.where(
+ "created_at < :time",
+ time: SiteSetting.maximum_session_age.hours.ago - ROTATE_TIME,
+ ).delete_all
end
- where('rotated_at < :time',
- time: SiteSetting.maximum_session_age.hours.ago - ROTATE_TIME).delete_all
-
+ where(
+ "rotated_at < :time",
+ time: SiteSetting.maximum_session_age.hours.ago - ROTATE_TIME,
+ ).delete_all
end
def rotate!(info = nil)
@@ -196,7 +215,9 @@ class UserAuthToken < ActiveRecord::Base
token = SecureRandom.hex(16)
- result = DB.exec("
+ result =
+ DB.exec(
+ "
UPDATE user_auth_tokens
SET
auth_token_seen = false,
@@ -207,13 +228,14 @@ class UserAuthToken < ActiveRecord::Base
auth_token = :new_token,
rotated_at = :now
WHERE id = :id AND (auth_token_seen or rotated_at < :safeguard_time)
-", id: self.id,
- user_agent: user_agent,
- client_ip: client_ip&.to_s,
- now: Time.zone.now,
- new_token: UserAuthToken.hash_token(token),
- safeguard_time: 30.seconds.ago
- )
+",
+ id: self.id,
+ user_agent: user_agent,
+ client_ip: client_ip&.to_s,
+ now: Time.zone.now,
+ new_token: UserAuthToken.hash_token(token),
+ safeguard_time: 30.seconds.ago,
+ )
if result > 0
reload
@@ -226,20 +248,21 @@ class UserAuthToken < ActiveRecord::Base
auth_token: auth_token,
user_agent: user_agent,
client_ip: client_ip,
- path: info && info[:path]
+ path: info && info[:path],
)
true
else
false
end
-
end
def self.enforce_session_count_limit!(user_id)
- tokens_to_destroy = where(user_id: user_id).
- where('rotated_at > ?', SiteSetting.maximum_session_age.hours.ago).
- order("rotated_at DESC").offset(MAX_SESSION_COUNT)
+ tokens_to_destroy =
+ where(user_id: user_id)
+ .where("rotated_at > ?", SiteSetting.maximum_session_age.hours.ago)
+ .order("rotated_at DESC")
+ .offset(MAX_SESSION_COUNT)
tokens_to_destroy.delete_all # Returns the number of deleted rows
end
diff --git a/app/models/user_avatar.rb b/app/models/user_avatar.rb
index 349509d0149..20f0e1d21bb 100644
--- a/app/models/user_avatar.rb
+++ b/app/models/user_avatar.rb
@@ -2,8 +2,8 @@
class UserAvatar < ActiveRecord::Base
belongs_to :user
- belongs_to :gravatar_upload, class_name: 'Upload'
- belongs_to :custom_upload, class_name: 'Upload'
+ belongs_to :gravatar_upload, class_name: "Upload"
+ belongs_to :custom_upload, class_name: "Upload"
has_many :upload_references, as: :target, dependent: :destroy
after_save do
@@ -14,7 +14,7 @@ class UserAvatar < ActiveRecord::Base
end
@@custom_user_gravatar_email_hash = {
- Discourse::SYSTEM_USER_ID => User.email_hash("info@discourse.org")
+ Discourse::SYSTEM_USER_ID => User.email_hash("info@discourse.org"),
}
def self.register_custom_user_gravatar_email_hash(user_id, email)
@@ -36,33 +36,36 @@ class UserAvatar < ActiveRecord::Base
return if user.blank? || user.primary_email.blank?
email_hash = @@custom_user_gravatar_email_hash[user_id] || user.email_hash
- gravatar_url = "https://#{SiteSetting.gravatar_base_url}/avatar/#{email_hash}.png?s=#{max}&d=404&reset_cache=#{SecureRandom.urlsafe_base64(5)}"
+ gravatar_url =
+ "https://#{SiteSetting.gravatar_base_url}/avatar/#{email_hash}.png?s=#{max}&d=404&reset_cache=#{SecureRandom.urlsafe_base64(5)}"
if SiteSetting.verbose_upload_logging
Rails.logger.warn("Verbose Upload Logging: Downloading gravatar from #{gravatar_url}")
end
# follow redirects in case gravatar change rules on us
- tempfile = FileHelper.download(
- gravatar_url,
- max_file_size: SiteSetting.max_image_size_kb.kilobytes,
- tmp_file_name: "gravatar",
- skip_rate_limit: true,
- verbose: false,
- follow_redirect: true
- )
+ tempfile =
+ FileHelper.download(
+ gravatar_url,
+ max_file_size: SiteSetting.max_image_size_kb.kilobytes,
+ tmp_file_name: "gravatar",
+ skip_rate_limit: true,
+ verbose: false,
+ follow_redirect: true,
+ )
if tempfile
ext = File.extname(tempfile)
- ext = '.png' if ext.blank?
+ ext = ".png" if ext.blank?
- upload = UploadCreator.new(
- tempfile,
- "gravatar#{ext}",
- origin: gravatar_url,
- type: "avatar",
- for_gravatar: true
- ).create_for(user_id)
+ upload =
+ UploadCreator.new(
+ tempfile,
+ "gravatar#{ext}",
+ origin: gravatar_url,
+ type: "avatar",
+ for_gravatar: true,
+ ).create_for(user_id)
if gravatar_upload_id != upload.id
User.transaction do
@@ -75,9 +78,7 @@ class UserAvatar < ActiveRecord::Base
end
end
rescue OpenURI::HTTPError => e
- if e.io&.status[0].to_i != 404
- raise e
- end
+ raise e if e.io&.status[0].to_i != 404
ensure
tempfile&.close!
end
@@ -111,19 +112,26 @@ class UserAvatar < ActiveRecord::Base
Rails.logger.warn("Verbose Upload Logging: Downloading sso-avatar from #{avatar_url}")
end
- tempfile = FileHelper.download(
- avatar_url,
- max_file_size: SiteSetting.max_image_size_kb.kilobytes,
- tmp_file_name: "sso-avatar",
- follow_redirect: true
- )
+ tempfile =
+ FileHelper.download(
+ avatar_url,
+ max_file_size: SiteSetting.max_image_size_kb.kilobytes,
+ tmp_file_name: "sso-avatar",
+ follow_redirect: true,
+ )
return unless tempfile
ext = FastImage.type(tempfile).to_s
tempfile.rewind
- upload = UploadCreator.new(tempfile, "external-avatar." + ext, origin: avatar_url, type: "avatar").create_for(user.id)
+ upload =
+ UploadCreator.new(
+ tempfile,
+ "external-avatar." + ext,
+ origin: avatar_url,
+ type: "avatar",
+ ).create_for(user.id)
user.create_user_avatar! unless user.user_avatar
@@ -132,13 +140,10 @@ class UserAvatar < ActiveRecord::Base
override_gravatar = !options || options[:override_gravatar]
if user.uploaded_avatar_id.nil? ||
- !user.user_avatar.contains_upload?(user.uploaded_avatar_id) ||
- override_gravatar
-
+ !user.user_avatar.contains_upload?(user.uploaded_avatar_id) || override_gravatar
user.update!(uploaded_avatar_id: upload.id)
end
end
-
rescue Net::ReadTimeout, OpenURI::HTTPError
# skip saving, we are not connected to the net
ensure
diff --git a/app/models/user_badge.rb b/app/models/user_badge.rb
index ec820a18089..dd919156314 100644
--- a/app/models/user_badge.rb
+++ b/app/models/user_badge.rb
@@ -3,49 +3,49 @@
class UserBadge < ActiveRecord::Base
belongs_to :badge
belongs_to :user
- belongs_to :granted_by, class_name: 'User'
+ belongs_to :granted_by, class_name: "User"
belongs_to :notification, dependent: :destroy
belongs_to :post
- BOOLEAN_ATTRIBUTES = %w(is_favorite)
+ BOOLEAN_ATTRIBUTES = %w[is_favorite]
- scope :grouped_with_count, -> {
- group(:badge_id, :user_id)
- .select_for_grouping
- .order('MAX(featured_rank) ASC')
- .includes(:user, :granted_by, { badge: :badge_type }, post: :topic)
- }
+ scope :grouped_with_count,
+ -> {
+ group(:badge_id, :user_id)
+ .select_for_grouping
+ .order("MAX(featured_rank) ASC")
+ .includes(:user, :granted_by, { badge: :badge_type }, post: :topic)
+ }
- scope :select_for_grouping, -> {
- select(
- UserBadge.attribute_names.map do |name|
- operation = BOOLEAN_ATTRIBUTES.include?(name) ? "BOOL_OR" : "MAX"
- "#{operation}(user_badges.#{name}) AS #{name}"
- end,
- 'COUNT(*) AS "count"'
- )
- }
+ scope :select_for_grouping,
+ -> {
+ select(
+ UserBadge.attribute_names.map do |name|
+ operation = BOOLEAN_ATTRIBUTES.include?(name) ? "BOOL_OR" : "MAX"
+ "#{operation}(user_badges.#{name}) AS #{name}"
+ end,
+ 'COUNT(*) AS "count"',
+ )
+ }
- scope :for_enabled_badges, -> { where('user_badges.badge_id IN (SELECT id FROM badges WHERE enabled)') }
+ scope :for_enabled_badges,
+ -> { where("user_badges.badge_id IN (SELECT id FROM badges WHERE enabled)") }
- validates :badge_id,
- presence: true,
- uniqueness: { scope: :user_id },
- if: :single_grant_badge?
+ validates :badge_id, presence: true, uniqueness: { scope: :user_id }, if: :single_grant_badge?
validates :user_id, presence: true
validates :granted_at, presence: true
validates :granted_by, presence: true
after_create do
- Badge.increment_counter 'grant_count', self.badge_id
+ Badge.increment_counter "grant_count", self.badge_id
UserStat.update_distinct_badge_count self.user_id
UserBadge.update_featured_ranks! self.user_id
self.trigger_user_badge_granted_event
end
after_destroy do
- Badge.decrement_counter 'grant_count', self.badge_id
+ Badge.decrement_counter "grant_count", self.badge_id
UserStat.update_distinct_badge_count self.user_id
UserBadge.update_featured_ranks! self.user_id
DiscourseEvent.trigger(:user_badge_removed, self.badge_id, self.user_id)
diff --git a/app/models/user_badges.rb b/app/models/user_badges.rb
index 4b0f8588307..65de5a66162 100644
--- a/app/models/user_badges.rb
+++ b/app/models/user_badges.rb
@@ -2,7 +2,7 @@
# view model for user badges
class UserBadges
- alias :read_attribute_for_serialization :send
+ alias read_attribute_for_serialization send
attr_accessor :user_badges, :username, :grant_count
diff --git a/app/models/user_custom_field.rb b/app/models/user_custom_field.rb
index a4f757536e8..92255cc5648 100644
--- a/app/models/user_custom_field.rb
+++ b/app/models/user_custom_field.rb
@@ -3,7 +3,12 @@
class UserCustomField < ActiveRecord::Base
belongs_to :user
- scope :searchable, -> { joins("INNER JOIN user_fields ON user_fields.id = REPLACE(user_custom_fields.name, 'user_field_', '')::INTEGER AND user_fields.searchable IS TRUE AND user_custom_fields.name like 'user_field_%'") }
+ scope :searchable,
+ -> {
+ joins(
+ "INNER JOIN user_fields ON user_fields.id = REPLACE(user_custom_fields.name, 'user_field_', '')::INTEGER AND user_fields.searchable IS TRUE AND user_custom_fields.name like 'user_field_%'",
+ )
+ }
end
# == Schema Information
diff --git a/app/models/user_email.rb b/app/models/user_email.rb
index 50ee27318b2..ff175a9bfd9 100644
--- a/app/models/user_email.rb
+++ b/app/models/user_email.rb
@@ -12,22 +12,23 @@ class UserEmail < ActiveRecord::Base
validates :email, presence: true
validates :email, email: true, if: :validate_email?
- validates :primary, uniqueness: { scope: [:user_id] }, if: [:user_id, :primary]
+ validates :primary, uniqueness: { scope: [:user_id] }, if: %i[user_id primary]
validate :user_id_not_changed, if: :primary
validate :unique_email, if: :validate_unique_email?
scope :secondary, -> { where(primary: false) }
- before_save ->() { destroy_email_tokens(self.email_was) }, if: :will_save_change_to_email?
+ before_save -> { destroy_email_tokens(self.email_was) }, if: :will_save_change_to_email?
after_destroy { destroy_email_tokens(self.email) }
def normalize_email
- self.normalized_email = if self.email.present?
- username, domain = self.email.split('@', 2)
- username = username.gsub('.', '').gsub(/\+.*/, '')
- "#{username}@#{domain}"
- end
+ self.normalized_email =
+ if self.email.present?
+ username, domain = self.email.split("@", 2)
+ username = username.gsub(".", "").gsub(/\+.*/, "")
+ "#{username}@#{domain}"
+ end
end
private
@@ -50,19 +51,26 @@ class UserEmail < ActiveRecord::Base
end
def unique_email
- email_exists = if SiteSetting.normalize_emails?
- self.class.where("lower(email) = ? OR lower(normalized_email) = ?", email, normalized_email).exists?
- else
- self.class.where("lower(email) = ?", email).exists?
- end
+ email_exists =
+ if SiteSetting.normalize_emails?
+ self
+ .class
+ .where("lower(email) = ? OR lower(normalized_email) = ?", email, normalized_email)
+ .exists?
+ else
+ self.class.where("lower(email) = ?", email).exists?
+ end
self.errors.add(:email, :taken) if email_exists
end
def user_id_not_changed
if self.will_save_change_to_user_id? && self.persisted?
- self.errors.add(:user_id, I18n.t(
- 'active_record.errors.model.user_email.attributes.user_id.reassigning_primary_email')
+ self.errors.add(
+ :user_id,
+ I18n.t(
+ "active_record.errors.model.user_email.attributes.user_id.reassigning_primary_email",
+ ),
)
end
end
diff --git a/app/models/user_export.rb b/app/models/user_export.rb
index 35059147250..32fcca5f75a 100644
--- a/app/models/user_export.rb
+++ b/app/models/user_export.rb
@@ -16,22 +16,31 @@ class UserExport < ActiveRecord::Base
DESTROY_CREATED_BEFORE = 2.days.ago
def self.remove_old_exports
- UserExport.where('created_at < ?', DESTROY_CREATED_BEFORE).find_each do |user_export|
- UserExport.transaction do
- begin
- Post.where(topic_id: user_export.topic_id).find_each { |p| p.destroy! }
- user_export.destroy!
- rescue => e
- Rails.logger.warn("Failed to remove user_export record with id #{user_export.id}: #{e.message}\n#{e.backtrace.join("\n")}")
+ UserExport
+ .where("created_at < ?", DESTROY_CREATED_BEFORE)
+ .find_each do |user_export|
+ UserExport.transaction do
+ begin
+ Post.where(topic_id: user_export.topic_id).find_each { |p| p.destroy! }
+ user_export.destroy!
+ rescue => e
+ Rails.logger.warn(
+ "Failed to remove user_export record with id #{user_export.id}: #{e.message}\n#{e.backtrace.join("\n")}",
+ )
+ end
end
end
- end
end
def self.base_directory
- File.join(Rails.root, "public", "uploads", "csv_exports", RailsMultisite::ConnectionManagement.current_db)
+ File.join(
+ Rails.root,
+ "public",
+ "uploads",
+ "csv_exports",
+ RailsMultisite::ConnectionManagement.current_db,
+ )
end
-
end
# == Schema Information
diff --git a/app/models/user_field.rb b/app/models/user_field.rb
index a872af740f5..3d492ab28ed 100644
--- a/app/models/user_field.rb
+++ b/app/models/user_field.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class UserField < ActiveRecord::Base
-
include AnonCacheInvalidator
include HasSanitizableFields
@@ -21,14 +20,16 @@ class UserField < ActiveRecord::Base
end
def queue_index_search
- SearchIndexer.queue_users_reindex(UserCustomField.where(name: "user_field_#{self.id}").pluck(:user_id))
+ SearchIndexer.queue_users_reindex(
+ UserCustomField.where(name: "user_field_#{self.id}").pluck(:user_id),
+ )
end
private
def sanitize_description
if description_changed?
- self.description = sanitize_field(self.description, additional_attributes: ['target'])
+ self.description = sanitize_field(self.description, additional_attributes: ["target"])
end
end
end
diff --git a/app/models/user_history.rb b/app/models/user_history.rb
index 1ddde529e94..e3a98fe9b27 100644
--- a/app/models/user_history.rb
+++ b/app/models/user_history.rb
@@ -4,8 +4,8 @@
# like deleting users, changing site settings, dismissing notifications, etc.
# Use other classes, like StaffActionLogger, to log records to this table.
class UserHistory < ActiveRecord::Base
- belongs_to :acting_user, class_name: 'User'
- belongs_to :target_user, class_name: 'User'
+ belongs_to :acting_user, class_name: "User"
+ belongs_to :target_user, class_name: "User"
belongs_to :post
belongs_to :topic
@@ -18,200 +18,201 @@ class UserHistory < ActiveRecord::Base
before_save :set_admin_only
def self.actions
- @actions ||= Enum.new(
- delete_user: 1,
- change_trust_level: 2,
- change_site_setting: 3,
- change_theme: 4,
- delete_theme: 5,
- checked_for_custom_avatar: 6, # not used anymore
- notified_about_avatar: 7,
- notified_about_sequential_replies: 8,
- notified_about_dominating_topic: 9,
- suspend_user: 10,
- unsuspend_user: 11,
- facebook_no_email: 12, # not used anymore
- grant_badge: 13,
- revoke_badge: 14,
- auto_trust_level_change: 15,
- check_email: 16,
- delete_post: 17,
- delete_topic: 18,
- impersonate: 19,
- roll_up: 20,
- change_username: 21,
- custom: 22,
- custom_staff: 23,
- anonymize_user: 24,
- reviewed_post: 25,
- change_category_settings: 26,
- delete_category: 27,
- create_category: 28,
- change_site_text: 29,
- silence_user: 30,
- unsilence_user: 31,
- grant_admin: 32,
- revoke_admin: 33,
- grant_moderation: 34,
- revoke_moderation: 35,
- backup_create: 36,
- rate_limited_like: 37, # not used anymore
- revoke_email: 38,
- deactivate_user: 39,
- wizard_step: 40,
- lock_trust_level: 41,
- unlock_trust_level: 42,
- activate_user: 43,
- change_readonly_mode: 44,
- backup_download: 45,
- backup_destroy: 46,
- notified_about_get_a_room: 47,
- change_name: 48,
- post_locked: 49,
- post_unlocked: 50,
- check_personal_message: 51,
- disabled_second_factor: 52,
- post_edit: 53,
- topic_published: 54,
- recover_topic: 55,
- post_approved: 56,
- create_badge: 57,
- change_badge: 58,
- delete_badge: 59,
- removed_silence_user: 60,
- removed_suspend_user: 61,
- removed_unsilence_user: 62,
- removed_unsuspend_user: 63,
- post_rejected: 64,
- merge_user: 65,
- entity_export: 66,
- change_password: 67,
- topic_timestamps_changed: 68,
- approve_user: 69,
- web_hook_create: 70,
- web_hook_update: 71,
- web_hook_destroy: 72,
- embeddable_host_create: 73,
- embeddable_host_update: 74,
- embeddable_host_destroy: 75,
- web_hook_deactivate: 76,
- change_theme_setting: 77,
- disable_theme_component: 78,
- enable_theme_component: 79,
- api_key_create: 80,
- api_key_update: 81,
- api_key_destroy: 82,
- revoke_title: 83,
- change_title: 84,
- override_upload_secure_status: 85,
- page_published: 86,
- page_unpublished: 87,
- add_email: 88,
- update_email: 89,
- destroy_email: 90,
- topic_closed: 91,
- topic_opened: 92,
- topic_archived: 93,
- topic_unarchived: 94,
- post_staff_note_create: 95,
- post_staff_note_destroy: 96,
- watched_word_create: 97,
- watched_word_destroy: 98,
- delete_group: 99
- )
+ @actions ||=
+ Enum.new(
+ delete_user: 1,
+ change_trust_level: 2,
+ change_site_setting: 3,
+ change_theme: 4,
+ delete_theme: 5,
+ checked_for_custom_avatar: 6, # not used anymore
+ notified_about_avatar: 7,
+ notified_about_sequential_replies: 8,
+ notified_about_dominating_topic: 9,
+ suspend_user: 10,
+ unsuspend_user: 11,
+ facebook_no_email: 12, # not used anymore
+ grant_badge: 13,
+ revoke_badge: 14,
+ auto_trust_level_change: 15,
+ check_email: 16,
+ delete_post: 17,
+ delete_topic: 18,
+ impersonate: 19,
+ roll_up: 20,
+ change_username: 21,
+ custom: 22,
+ custom_staff: 23,
+ anonymize_user: 24,
+ reviewed_post: 25,
+ change_category_settings: 26,
+ delete_category: 27,
+ create_category: 28,
+ change_site_text: 29,
+ silence_user: 30,
+ unsilence_user: 31,
+ grant_admin: 32,
+ revoke_admin: 33,
+ grant_moderation: 34,
+ revoke_moderation: 35,
+ backup_create: 36,
+ rate_limited_like: 37, # not used anymore
+ revoke_email: 38,
+ deactivate_user: 39,
+ wizard_step: 40,
+ lock_trust_level: 41,
+ unlock_trust_level: 42,
+ activate_user: 43,
+ change_readonly_mode: 44,
+ backup_download: 45,
+ backup_destroy: 46,
+ notified_about_get_a_room: 47,
+ change_name: 48,
+ post_locked: 49,
+ post_unlocked: 50,
+ check_personal_message: 51,
+ disabled_second_factor: 52,
+ post_edit: 53,
+ topic_published: 54,
+ recover_topic: 55,
+ post_approved: 56,
+ create_badge: 57,
+ change_badge: 58,
+ delete_badge: 59,
+ removed_silence_user: 60,
+ removed_suspend_user: 61,
+ removed_unsilence_user: 62,
+ removed_unsuspend_user: 63,
+ post_rejected: 64,
+ merge_user: 65,
+ entity_export: 66,
+ change_password: 67,
+ topic_timestamps_changed: 68,
+ approve_user: 69,
+ web_hook_create: 70,
+ web_hook_update: 71,
+ web_hook_destroy: 72,
+ embeddable_host_create: 73,
+ embeddable_host_update: 74,
+ embeddable_host_destroy: 75,
+ web_hook_deactivate: 76,
+ change_theme_setting: 77,
+ disable_theme_component: 78,
+ enable_theme_component: 79,
+ api_key_create: 80,
+ api_key_update: 81,
+ api_key_destroy: 82,
+ revoke_title: 83,
+ change_title: 84,
+ override_upload_secure_status: 85,
+ page_published: 86,
+ page_unpublished: 87,
+ add_email: 88,
+ update_email: 89,
+ destroy_email: 90,
+ topic_closed: 91,
+ topic_opened: 92,
+ topic_archived: 93,
+ topic_unarchived: 94,
+ post_staff_note_create: 95,
+ post_staff_note_destroy: 96,
+ watched_word_create: 97,
+ watched_word_destroy: 98,
+ delete_group: 99,
+ )
end
# Staff actions is a subset of all actions, used to audit actions taken by staff users.
def self.staff_actions
- @staff_actions ||= [
- :delete_user,
- :change_trust_level,
- :change_site_setting,
- :change_theme,
- :delete_theme,
- :change_site_text,
- :suspend_user,
- :unsuspend_user,
- :removed_suspend_user,
- :removed_unsuspend_user,
- :grant_badge,
- :revoke_badge,
- :check_email,
- :delete_post,
- :delete_topic,
- :impersonate,
- :roll_up,
- :change_username,
- :custom_staff,
- :anonymize_user,
- :reviewed_post,
- :change_category_settings,
- :delete_category,
- :create_category,
- :silence_user,
- :unsilence_user,
- :removed_silence_user,
- :removed_unsilence_user,
- :grant_admin,
- :revoke_admin,
- :grant_moderation,
- :revoke_moderation,
- :backup_create,
- :revoke_email,
- :deactivate_user,
- :lock_trust_level,
- :unlock_trust_level,
- :activate_user,
- :change_readonly_mode,
- :backup_download,
- :backup_destroy,
- :post_locked,
- :post_unlocked,
- :check_personal_message,
- :disabled_second_factor,
- :post_edit,
- :topic_published,
- :recover_topic,
- :post_approved,
- :create_badge,
- :change_badge,
- :delete_badge,
- :post_rejected,
- :merge_user,
- :entity_export,
- :change_name,
- :topic_timestamps_changed,
- :approve_user,
- :web_hook_create,
- :web_hook_update,
- :web_hook_destroy,
- :web_hook_deactivate,
- :embeddable_host_create,
- :embeddable_host_update,
- :embeddable_host_destroy,
- :change_theme_setting,
- :disable_theme_component,
- :enable_theme_component,
- :revoke_title,
- :change_title,
- :api_key_create,
- :api_key_update,
- :api_key_destroy,
- :override_upload_secure_status,
- :page_published,
- :page_unpublished,
- :add_email,
- :update_email,
- :destroy_email,
- :topic_closed,
- :topic_opened,
- :topic_archived,
- :topic_unarchived,
- :post_staff_note_create,
- :post_staff_note_destroy,
- :watched_word_create,
- :watched_word_destroy,
- :delete_group
+ @staff_actions ||= %i[
+ delete_user
+ change_trust_level
+ change_site_setting
+ change_theme
+ delete_theme
+ change_site_text
+ suspend_user
+ unsuspend_user
+ removed_suspend_user
+ removed_unsuspend_user
+ grant_badge
+ revoke_badge
+ check_email
+ delete_post
+ delete_topic
+ impersonate
+ roll_up
+ change_username
+ custom_staff
+ anonymize_user
+ reviewed_post
+ change_category_settings
+ delete_category
+ create_category
+ silence_user
+ unsilence_user
+ removed_silence_user
+ removed_unsilence_user
+ grant_admin
+ revoke_admin
+ grant_moderation
+ revoke_moderation
+ backup_create
+ revoke_email
+ deactivate_user
+ lock_trust_level
+ unlock_trust_level
+ activate_user
+ change_readonly_mode
+ backup_download
+ backup_destroy
+ post_locked
+ post_unlocked
+ check_personal_message
+ disabled_second_factor
+ post_edit
+ topic_published
+ recover_topic
+ post_approved
+ create_badge
+ change_badge
+ delete_badge
+ post_rejected
+ merge_user
+ entity_export
+ change_name
+ topic_timestamps_changed
+ approve_user
+ web_hook_create
+ web_hook_update
+ web_hook_destroy
+ web_hook_deactivate
+ embeddable_host_create
+ embeddable_host_update
+ embeddable_host_destroy
+ change_theme_setting
+ disable_theme_component
+ enable_theme_component
+ revoke_title
+ change_title
+ api_key_create
+ api_key_update
+ api_key_destroy
+ override_upload_secure_status
+ page_published
+ page_unpublished
+ add_email
+ update_email
+ destroy_email
+ topic_closed
+ topic_opened
+ topic_archived
+ topic_unarchived
+ post_staff_note_create
+ post_staff_note_destroy
+ watched_word_create
+ watched_word_destroy
+ delete_group
]
end
@@ -228,7 +229,7 @@ class UserHistory < ActiveRecord::Base
query = query.where(action: filters[:action_id]) if filters[:action_id].present?
query = query.where(custom_type: filters[:custom_type]) if filters[:custom_type].present?
- [:acting_user, :target_user].each do |key|
+ %i[acting_user target_user].each do |key|
if filters[key] && (obj_id = User.where(username_lower: filters[key].downcase).pluck(:id))
query = query.where("#{key}_id = ?", obj_id)
end
@@ -249,7 +250,7 @@ class UserHistory < ActiveRecord::Base
end
def self.staff_filters
- [:action_id, :custom_type, :acting_user, :target_user, :subject, :action_name]
+ %i[action_id custom_type acting_user target_user subject action_name]
end
def self.staff_action_records(viewer, opts = nil)
@@ -262,11 +263,12 @@ class UserHistory < ActiveRecord::Base
opts[:action_id] = self.actions[opts[:action_name].to_sym] if opts[:action_name]
end
- query = self
- .with_filters(opts.slice(*staff_filters))
- .only_staff_actions
- .order('id DESC')
- .includes(:acting_user, :target_user)
+ query =
+ self
+ .with_filters(opts.slice(*staff_filters))
+ .only_staff_actions
+ .order("id DESC")
+ .includes(:acting_user, :target_user)
query = query.where(admin_only: false) unless viewer && viewer.admin?
query
end
diff --git a/app/models/user_notification_schedule.rb b/app/models/user_notification_schedule.rb
index b80b4406a53..4a2bfac0fef 100644
--- a/app/models/user_notification_schedule.rb
+++ b/app/models/user_notification_schedule.rb
@@ -3,17 +3,17 @@
class UserNotificationSchedule < ActiveRecord::Base
belongs_to :user
- DEFAULT = -> {
+ DEFAULT = -> do
attrs = { enabled: false }
7.times do |n|
attrs["day_#{n}_start_time".to_sym] = 480
attrs["day_#{n}_end_time".to_sym] = 1020
end
attrs
- }.call
+ end.call
validate :has_valid_times
- validates :enabled, inclusion: { in: [ true, false ] }
+ validates :enabled, inclusion: { in: [true, false] }
scope :enabled, -> { where(enabled: true) }
@@ -37,9 +37,7 @@ class UserNotificationSchedule < ActiveRecord::Base
errors.add(start_key, "is invalid")
end
- if self[end_key].nil? || self[end_key] > 1440
- errors.add(end_key, "is invalid")
- end
+ errors.add(end_key, "is invalid") if self[end_key].nil? || self[end_key] > 1440
if self[start_key] && self[end_key] && self[start_key] > self[end_key]
errors.add(start_key, "is after end time")
diff --git a/app/models/user_option.rb b/app/models/user_option.rb
index 1bf0062d202..70d80d80522 100644
--- a/app/models/user_option.rb
+++ b/app/models/user_option.rb
@@ -11,10 +11,15 @@ class UserOption < ActiveRecord::Base
after_save :update_tracked_topics
- scope :human_users, -> { where('user_id > 0') }
+ scope :human_users, -> { where("user_id > 0") }
enum default_calendar: { none_selected: 0, ics: 1, google: 2 }, _scopes: false
- enum sidebar_list_destination: { none_selected: 0, default: 0, unread_new: 1 }, _prefix: "sidebar_list"
+ enum sidebar_list_destination: {
+ none_selected: 0,
+ default: 0,
+ unread_new: 1,
+ },
+ _prefix: "sidebar_list"
def self.ensure_consistency!
sql = <<~SQL
@@ -23,9 +28,7 @@ class UserOption < ActiveRecord::Base
WHERE o.user_id IS NULL
SQL
- DB.query_single(sql).each do |id|
- UserOption.create(user_id: id)
- end
+ DB.query_single(sql).each { |id| UserOption.create(user_id: id) }
end
def self.previous_replies_type
@@ -33,7 +36,8 @@ class UserOption < ActiveRecord::Base
end
def self.like_notification_frequency_type
- @like_notification_frequency_type ||= Enum.new(always: 0, first_time_and_daily: 1, first_time: 2, never: 3)
+ @like_notification_frequency_type ||=
+ Enum.new(always: 0, first_time_and_daily: 1, first_time: 2, never: 3)
end
def self.text_sizes
@@ -70,7 +74,8 @@ class UserOption < ActiveRecord::Base
self.new_topic_duration_minutes = SiteSetting.default_other_new_topic_duration_minutes
self.auto_track_topics_after_msecs = SiteSetting.default_other_auto_track_topics_after_msecs
- self.notification_level_when_replying = SiteSetting.default_other_notification_level_when_replying
+ self.notification_level_when_replying =
+ SiteSetting.default_other_notification_level_when_replying
self.like_notification_frequency = SiteSetting.default_other_like_notification_frequency
@@ -111,7 +116,12 @@ class UserOption < ActiveRecord::Base
Discourse.redis.expire(key, delay)
# delay the update
- Jobs.enqueue_in(delay / 2, :update_top_redirection, user_id: self.user_id, redirected_at: Time.zone.now.to_s)
+ Jobs.enqueue_in(
+ delay / 2,
+ :update_top_redirection,
+ user_id: self.user_id,
+ redirected_at: Time.zone.now.to_s,
+ )
end
def should_be_redirected_to_top
@@ -133,16 +143,10 @@ class UserOption < ActiveRecord::Base
if !user.seen_before? || (user.trust_level == 0 && !redirected_to_top_yet?)
update_last_redirected_to_top!
- return {
- reason: I18n.t('redirected_to_top_reasons.new_user'),
- period: period
- }
+ return { reason: I18n.t("redirected_to_top_reasons.new_user"), period: period }
elsif user.last_seen_at < 1.month.ago
update_last_redirected_to_top!
- return {
- reason: I18n.t('redirected_to_top_reasons.not_seen_in_a_month'),
- period: period
- }
+ return { reason: I18n.t("redirected_to_top_reasons.not_seen_in_a_month"), period: period }
end
# don't redirect to top
@@ -150,7 +154,8 @@ class UserOption < ActiveRecord::Base
end
def treat_as_new_topic_start_date
- duration = new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes.to_i
+ duration =
+ new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes.to_i
times = [
case duration
when User::NewTopicDuration::ALWAYS
@@ -161,7 +166,7 @@ class UserOption < ActiveRecord::Base
duration.minutes.ago
end,
user.created_at,
- Time.at(SiteSetting.min_new_topics_time).to_datetime
+ Time.at(SiteSetting.min_new_topics_time).to_datetime,
]
times.max
@@ -169,14 +174,22 @@ class UserOption < ActiveRecord::Base
def homepage
case homepage_id
- when 1 then "latest"
- when 2 then "categories"
- when 3 then "unread"
- when 4 then "new"
- when 5 then "top"
- when 6 then "bookmarks"
- when 7 then "unseen"
- else SiteSetting.homepage
+ when 1
+ "latest"
+ when 2
+ "categories"
+ when 3
+ "unread"
+ when 4
+ "new"
+ when 5
+ "top"
+ when 6
+ "bookmarks"
+ when 7
+ "unseen"
+ else
+ SiteSetting.homepage
end
end
@@ -197,9 +210,7 @@ class UserOption < ActiveRecord::Base
end
def unsubscribed_from_all?
- !mailing_list_mode &&
- !email_digests &&
- email_level == UserOption.email_level_types[:never] &&
+ !mailing_list_mode && !email_digests && email_level == UserOption.email_level_types[:never] &&
email_messages_level == UserOption.email_level_types[:never]
end
@@ -208,14 +219,16 @@ class UserOption < ActiveRecord::Base
end
def self.user_tzinfo(user_id)
- timezone = UserOption.where(user_id: user_id).pluck(:timezone).first || 'UTC'
+ timezone = UserOption.where(user_id: user_id).pluck(:timezone).first || "UTC"
tzinfo = nil
begin
tzinfo = ActiveSupport::TimeZone.find_tzinfo(timezone)
rescue TZInfo::InvalidTimezoneIdentifier
- Rails.logger.warn("#{User.find_by(id: user_id)&.username} has the timezone #{timezone} set, we do not know how to parse it in Rails, fallback to UTC")
- tzinfo = ActiveSupport::TimeZone.find_tzinfo('UTC')
+ Rails.logger.warn(
+ "#{User.find_by(id: user_id)&.username} has the timezone #{timezone} set, we do not know how to parse it in Rails, fallback to UTC",
+ )
+ tzinfo = ActiveSupport::TimeZone.find_tzinfo("UTC")
end
tzinfo
@@ -227,7 +240,6 @@ class UserOption < ActiveRecord::Base
return unless saved_change_to_auto_track_topics_after_msecs?
TrackedTopicsUpdater.new(id, auto_track_topics_after_msecs).call
end
-
end
# == Schema Information
diff --git a/app/models/user_profile.rb b/app/models/user_profile.rb
index e3136c65261..2ed6d1b0279 100644
--- a/app/models/user_profile.rb
+++ b/app/models/user_profile.rb
@@ -7,13 +7,19 @@ class UserProfile < ActiveRecord::Base
belongs_to :card_background_upload, class_name: "Upload"
belongs_to :profile_background_upload, class_name: "Upload"
belongs_to :granted_title_badge, class_name: "Badge"
- belongs_to :featured_topic, class_name: 'Topic'
+ belongs_to :featured_topic, class_name: "Topic"
has_many :upload_references, as: :target, dependent: :destroy
has_many :user_profile_views, dependent: :destroy
validates :bio_raw, length: { maximum: 3000 }, watched_words: true
- validates :website, url: true, length: { maximum: 3000 }, allow_blank: true, if: :validate_website?
+ validates :website,
+ url: true,
+ length: {
+ maximum: 3000,
+ },
+ allow_blank: true,
+ if: :validate_website?
validates :location, length: { maximum: 3000 }, watched_words: true
validates :user, presence: true
@@ -26,8 +32,11 @@ class UserProfile < ActiveRecord::Base
after_save :pull_hotlinked_image
after_save do
- if saved_change_to_profile_background_upload_id? || saved_change_to_card_background_upload_id? || saved_change_to_bio_raw?
- upload_ids = [self.profile_background_upload_id, self.card_background_upload_id] + Upload.extract_upload_ids(self.bio_raw)
+ if saved_change_to_profile_background_upload_id? ||
+ saved_change_to_card_background_upload_id? || saved_change_to_bio_raw?
+ upload_ids =
+ [self.profile_background_upload_id, self.card_background_upload_id] +
+ Upload.extract_upload_ids(self.bio_raw)
UploadReference.ensure_exist!(upload_ids: upload_ids, target: self)
end
end
@@ -36,13 +45,15 @@ class UserProfile < ActiveRecord::Base
def bio_excerpt(length = 350, opts = {})
return nil if bio_cooked.blank?
- excerpt = PrettyText.excerpt(bio_cooked, length, opts).sub(/
$/, '')
+ excerpt = PrettyText.excerpt(bio_cooked, length, opts).sub(/
$/, "")
return excerpt if excerpt.blank? || (user.has_trust_level?(TrustLevel[1]) && !user.suspended?)
PrettyText.strip_links(excerpt)
end
def bio_processed
- return bio_cooked if bio_cooked.blank? || (user.has_trust_level?(TrustLevel[1]) && !user.suspended?)
+ if bio_cooked.blank? || (user.has_trust_level?(TrustLevel[1]) && !user.suspended?)
+ return bio_cooked
+ end
PrettyText.strip_links(bio_cooked)
end
@@ -73,14 +84,16 @@ class UserProfile < ActiveRecord::Base
def self.rebake_old(limit)
problems = []
- UserProfile.where('bio_cooked_version IS NULL OR bio_cooked_version < ?', BAKED_VERSION)
- .limit(limit).each do |p|
- begin
- p.rebake!
- rescue => e
- problems << { profile: p, ex: e }
+ UserProfile
+ .where("bio_cooked_version IS NULL OR bio_cooked_version < ?", BAKED_VERSION)
+ .limit(limit)
+ .each do |p|
+ begin
+ p.rebake!
+ rescue => e
+ problems << { profile: p, ex: e }
+ end
end
- end
problems
end
@@ -90,15 +103,18 @@ class UserProfile < ActiveRecord::Base
def self.import_url_for_user(background_url, user, options = nil)
if SiteSetting.verbose_upload_logging
- Rails.logger.warn("Verbose Upload Logging: Downloading profile background from #{background_url}")
+ Rails.logger.warn(
+ "Verbose Upload Logging: Downloading profile background from #{background_url}",
+ )
end
- tempfile = FileHelper.download(
- background_url,
- max_file_size: SiteSetting.max_image_size_kb.kilobytes,
- tmp_file_name: "sso-profile-background",
- follow_redirect: true
- )
+ tempfile =
+ FileHelper.download(
+ background_url,
+ max_file_size: SiteSetting.max_image_size_kb.kilobytes,
+ tmp_file_name: "sso-profile-background",
+ follow_redirect: true,
+ )
return unless tempfile
@@ -108,14 +124,19 @@ class UserProfile < ActiveRecord::Base
is_card_background = !options || options[:is_card_background]
type = is_card_background ? "card_background" : "profile_background"
- upload = UploadCreator.new(tempfile, "external-profile-background." + ext, origin: background_url, type: type).create_for(user.id)
+ upload =
+ UploadCreator.new(
+ tempfile,
+ "external-profile-background." + ext,
+ origin: background_url,
+ type: type,
+ ).create_for(user.id)
if (is_card_background)
user.user_profile.upload_card_background(upload)
else
user.user_profile.upload_profile_background(upload)
end
-
rescue Net::ReadTimeout, OpenURI::HTTPError
# skip saving, we are not connected to the net
ensure
@@ -133,7 +154,7 @@ class UserProfile < ActiveRecord::Base
Jobs.enqueue_in(
SiteSetting.editing_grace_period,
:pull_user_profile_hotlinked_images,
- user_id: self.user_id
+ user_id: self.user_id,
)
end
end
@@ -146,7 +167,10 @@ class UserProfile < ActiveRecord::Base
def cooked
if self.bio_raw.present?
- PrettyText.cook(self.bio_raw, omit_nofollow: user.has_trust_level?(TrustLevel[3]) && !SiteSetting.tl3_links_no_follow)
+ PrettyText.cook(
+ self.bio_raw,
+ omit_nofollow: user.has_trust_level?(TrustLevel[3]) && !SiteSetting.tl3_links_no_follow,
+ )
else
nil
end
@@ -171,11 +195,20 @@ class UserProfile < ActiveRecord::Base
allowed_domains = SiteSetting.allowed_user_website_domains
return if (allowed_domains.blank? || self.website.blank?)
- domain = begin
- URI.parse(self.website).host
- rescue URI::Error
+ domain =
+ begin
+ URI.parse(self.website).host
+ rescue URI::Error
+ end
+ unless allowed_domains.split("|").include?(domain)
+ self.errors.add :base,
+ (
+ I18n.t(
+ "user.website.domain_not_allowed",
+ domains: allowed_domains.split("|").join(", "),
+ )
+ )
end
- self.errors.add :base, (I18n.t('user.website.domain_not_allowed', domains: allowed_domains.split('|').join(", "))) unless allowed_domains.split('|').include?(domain)
end
def validate_website?
diff --git a/app/models/user_profile_view.rb b/app/models/user_profile_view.rb
index 5bc6acbe145..0648b75eb0b 100644
--- a/app/models/user_profile_view.rb
+++ b/app/models/user_profile_view.rb
@@ -16,11 +16,13 @@ class UserProfileView < ActiveRecord::Base
redis_key << ":ip-#{ip}"
end
- if skip_redis || Discourse.redis.setnx(redis_key, '1')
- skip_redis || Discourse.redis.expire(redis_key, SiteSetting.user_profile_view_duration_hours.hours)
+ if skip_redis || Discourse.redis.setnx(redis_key, "1")
+ skip_redis ||
+ Discourse.redis.expire(redis_key, SiteSetting.user_profile_view_duration_hours.hours)
self.transaction do
- sql = "INSERT INTO user_profile_views (user_profile_id, ip_address, viewed_at, user_id)
+ sql =
+ "INSERT INTO user_profile_views (user_profile_id, ip_address, viewed_at, user_id)
SELECT :user_profile_id, :ip_address, :viewed_at, :user_id
WHERE NOT EXISTS (
SELECT 1 FROM user_profile_views
@@ -30,16 +32,24 @@ class UserProfileView < ActiveRecord::Base
builder = DB.build(sql)
if !user_id
- builder.where("viewed_at = :viewed_at AND ip_address = :ip_address AND user_profile_id = :user_profile_id AND user_id IS NULL")
+ builder.where(
+ "viewed_at = :viewed_at AND ip_address = :ip_address AND user_profile_id = :user_profile_id AND user_id IS NULL",
+ )
else
- builder.where("viewed_at = :viewed_at AND user_id = :user_id AND user_profile_id = :user_profile_id")
+ builder.where(
+ "viewed_at = :viewed_at AND user_id = :user_id AND user_profile_id = :user_profile_id",
+ )
end
- result = builder.exec(user_profile_id: user_profile_id, ip_address: ip, viewed_at: at, user_id: user_id)
+ result =
+ builder.exec(
+ user_profile_id: user_profile_id,
+ ip_address: ip,
+ viewed_at: at,
+ user_id: user_id,
+ )
- if result > 0
- UserProfile.find(user_profile_id).increment!(:views)
- end
+ UserProfile.find(user_profile_id).increment!(:views) if result > 0
end
end
end
@@ -47,8 +57,10 @@ class UserProfileView < ActiveRecord::Base
def self.profile_views_by_day(start_date, end_date, group_id = nil)
profile_views = self.where("viewed_at >= ? AND viewed_at < ?", start_date, end_date + 1.day)
if group_id
- profile_views = profile_views.joins("INNER JOIN users ON users.id = user_profile_views.user_id")
- profile_views = profile_views.joins("INNER JOIN group_users ON group_users.user_id = users.id")
+ profile_views =
+ profile_views.joins("INNER JOIN users ON users.id = user_profile_views.user_id")
+ profile_views =
+ profile_views.joins("INNER JOIN group_users ON group_users.user_id = users.id")
profile_views = profile_views.where("group_users.group_id = ?", group_id)
end
profile_views.group("date(viewed_at)").order("date(viewed_at)").count
diff --git a/app/models/user_search.rb b/app/models/user_search.rb
index baa25dfffac..7b21ff6b7fe 100644
--- a/app/models/user_search.rb
+++ b/app/models/user_search.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class UserSearch
-
MAX_SIZE_PRIORITY_MENTION ||= 500
def initialize(term, opts = {})
@@ -31,17 +30,16 @@ class UserSearch
users = users.not_suspended unless @searching_user&.staff?
if @groups
- users = users
- .joins(:group_users)
- .where("group_users.group_id IN (?)", @groups.map(&:id))
+ users = users.joins(:group_users).where("group_users.group_id IN (?)", @groups.map(&:id))
end
# Only show users who have access to private topic
if @topic_allowed_users == "true" && @topic&.category&.read_restricted
- users = users
- .references(:categories)
- .includes(:secure_categories)
- .where("users.admin OR categories.id = ?", @topic.category_id)
+ users =
+ users
+ .references(:categories)
+ .includes(:secure_categories)
+ .where("users.admin OR categories.id = ?", @topic.category_id)
end
users
@@ -70,27 +68,27 @@ class UserSearch
exact_matches = scoped_users.where(username_lower: @term)
# don't pollute mentions with users who haven't shown up in over a year
- exact_matches = exact_matches.where('last_seen_at > ?', 1.year.ago) if @topic_id || @category_id
+ exact_matches = exact_matches.where("last_seen_at > ?", 1.year.ago) if @topic_id ||
+ @category_id
- exact_matches
- .limit(@limit)
- .pluck(:id)
- .each { |id| users << id }
+ exact_matches.limit(@limit).pluck(:id).each { |id| users << id }
end
return users.to_a if users.size >= @limit
# 2. in topic
if @topic_id
- in_topic = filtered_by_term_users
- .where('users.id IN (SELECT user_id FROM posts WHERE topic_id = ? AND post_type = ? AND deleted_at IS NULL)', @topic_id, Post.types[:regular])
+ in_topic =
+ filtered_by_term_users.where(
+ "users.id IN (SELECT user_id FROM posts WHERE topic_id = ? AND post_type = ? AND deleted_at IS NULL)",
+ @topic_id,
+ Post.types[:regular],
+ )
- if @searching_user.present?
- in_topic = in_topic.where('users.id <> ?', @searching_user.id)
- end
+ in_topic = in_topic.where("users.id <> ?", @searching_user.id) if @searching_user.present?
in_topic
- .order('last_seen_at DESC NULLS LAST')
+ .order("last_seen_at DESC NULLS LAST")
.limit(@limit - users.size)
.pluck(:id)
.each { |id| users << id }
@@ -131,8 +129,7 @@ class UserSearch
category_groups = category_groups.members_visible_groups(@searching_user)
end
- in_category = filtered_by_term_users
- .where(<<~SQL, category_groups.pluck(:id))
+ in_category = filtered_by_term_users.where(<<~SQL, category_groups.pluck(:id))
users.id IN (
SELECT gu.user_id
FROM group_users gu
@@ -142,11 +139,11 @@ class UserSearch
SQL
if @searching_user.present?
- in_category = in_category.where('users.id <> ?', @searching_user.id)
+ in_category = in_category.where("users.id <> ?", @searching_user.id)
end
in_category
- .order('last_seen_at DESC NULLS LAST')
+ .order("last_seen_at DESC NULLS LAST")
.limit(@limit - users.size)
.pluck(:id)
.each { |id| users << id }
@@ -157,7 +154,7 @@ class UserSearch
# 4. global matches
if @term.present?
filtered_by_term_users
- .order('last_seen_at DESC NULLS LAST')
+ .order("last_seen_at DESC NULLS LAST")
.limit(@limit - users.size)
.pluck(:id)
.each { |id| users << id }
@@ -166,7 +163,7 @@ class UserSearch
# 5. last seen users (for search auto-suggestions)
if @last_seen_users
scoped_users
- .order('last_seen_at DESC NULLS LAST')
+ .order("last_seen_at DESC NULLS LAST")
.limit(@limit - users.size)
.pluck(:id)
.each { |id| users << id }
@@ -179,16 +176,15 @@ class UserSearch
ids = search_ids
return User.where("0=1") if ids.empty?
- results = User.joins("JOIN (SELECT unnest uid, row_number() OVER () AS rn
+ results =
+ User.joins(
+ "JOIN (SELECT unnest uid, row_number() OVER () AS rn
FROM unnest('{#{ids.join(",")}}'::int[])
- ) x on uid = users.id")
- .order("rn")
+ ) x on uid = users.id",
+ ).order("rn")
- if SiteSetting.enable_user_status
- results = results.includes(:user_status)
- end
+ results = results.includes(:user_status) if SiteSetting.enable_user_status
results
end
-
end
diff --git a/app/models/user_second_factor.rb b/app/models/user_second_factor.rb
index 7846f27ad86..3c71c6b65e7 100644
--- a/app/models/user_second_factor.rb
+++ b/app/models/user_second_factor.rb
@@ -4,24 +4,14 @@ class UserSecondFactor < ActiveRecord::Base
include SecondFactorManager
belongs_to :user
- scope :backup_codes, -> do
- where(method: UserSecondFactor.methods[:backup_codes], enabled: true)
- end
+ scope :backup_codes, -> { where(method: UserSecondFactor.methods[:backup_codes], enabled: true) }
- scope :totps, -> do
- where(method: UserSecondFactor.methods[:totp], enabled: true)
- end
+ scope :totps, -> { where(method: UserSecondFactor.methods[:totp], enabled: true) }
- scope :all_totps, -> do
- where(method: UserSecondFactor.methods[:totp])
- end
+ scope :all_totps, -> { where(method: UserSecondFactor.methods[:totp]) }
def self.methods
- @methods ||= Enum.new(
- totp: 1,
- backup_codes: 2,
- security_key: 3,
- )
+ @methods ||= Enum.new(totp: 1, backup_codes: 2, security_key: 3)
end
def totp_object
@@ -31,7 +21,6 @@ class UserSecondFactor < ActiveRecord::Base
def totp_provisioning_uri
totp_object.provisioning_uri(user.email)
end
-
end
# == Schema Information
diff --git a/app/models/user_security_key.rb b/app/models/user_security_key.rb
index 229dbbdf968..5447ee23adc 100644
--- a/app/models/user_security_key.rb
+++ b/app/models/user_security_key.rb
@@ -3,16 +3,11 @@
class UserSecurityKey < ActiveRecord::Base
belongs_to :user
- scope :second_factors, -> do
- where(factor_type: UserSecurityKey.factor_types[:second_factor], enabled: true)
- end
+ scope :second_factors,
+ -> { where(factor_type: UserSecurityKey.factor_types[:second_factor], enabled: true) }
def self.factor_types
- @factor_types ||= Enum.new(
- second_factor: 0,
- first_factor: 1,
- multi_factor: 2,
- )
+ @factor_types ||= Enum.new(second_factor: 0, first_factor: 1, multi_factor: 2)
end
end
diff --git a/app/models/user_stat.rb b/app/models/user_stat.rb
index e6a86c91152..894a888c1f4 100644
--- a/app/models/user_stat.rb
+++ b/app/models/user_stat.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
class UserStat < ActiveRecord::Base
-
belongs_to :user
after_save :trigger_badges
@@ -21,7 +20,8 @@ class UserStat < ActiveRecord::Base
def self.update_first_unread_pm(last_seen, limit: UPDATE_UNREAD_USERS_LIMIT)
whisperers_group_ids = SiteSetting.whispers_allowed_group_ids
- DB.exec(<<~SQL, archetype: Archetype.private_message, now: UPDATE_UNREAD_MINUTES_AGO.minutes.ago, last_seen: last_seen, limit: limit, whisperers_group_ids: whisperers_group_ids)
+ DB.exec(
+ <<~SQL,
UPDATE user_stats us
SET first_unread_pm_at = COALESCE(Z.min_date, :now)
FROM (
@@ -37,11 +37,11 @@ class UserStat < ActiveRecord::Base
INNER JOIN topics t ON t.id = tau.topic_id
INNER JOIN users u ON u.id = tau.user_id
LEFT JOIN topic_users tu ON t.id = tu.topic_id AND tu.user_id = tau.user_id
- #{whisperers_group_ids.present? ? 'LEFT JOIN group_users gu ON gu.group_id IN (:whisperers_group_ids) AND gu.user_id = u.id' : ''}
+ #{whisperers_group_ids.present? ? "LEFT JOIN group_users gu ON gu.group_id IN (:whisperers_group_ids) AND gu.user_id = u.id" : ""}
WHERE t.deleted_at IS NULL
AND t.archetype = :archetype
AND tu.last_read_post_number < CASE
- WHEN u.admin OR u.moderator #{whisperers_group_ids.present? ? 'OR gu.id IS NOT NULL' : ''}
+ WHEN u.admin OR u.moderator #{whisperers_group_ids.present? ? "OR gu.id IS NOT NULL" : ""}
THEN t.highest_staff_post_number
ELSE t.highest_post_number
END
@@ -67,6 +67,12 @@ class UserStat < ActiveRecord::Base
) AS Z
WHERE us.user_id = Z.user_id
SQL
+ archetype: Archetype.private_message,
+ now: UPDATE_UNREAD_MINUTES_AGO.minutes.ago,
+ last_seen: last_seen,
+ limit: limit,
+ whisperers_group_ids: whisperers_group_ids,
+ )
end
def self.update_first_unread(last_seen, limit: UPDATE_UNREAD_USERS_LIMIT)
@@ -140,14 +146,14 @@ class UserStat < ActiveRecord::Base
end
def self.reset_bounce_scores
- UserStat.where("reset_bounce_score_after < now()")
+ UserStat
+ .where("reset_bounce_score_after < now()")
.where("bounce_score > 0")
.update_all(bounce_score: 0)
end
# Updates the denormalized view counts for all users
def self.update_view_counts(last_seen = 1.hour.ago)
-
# NOTE: we only update the counts for users we have seen in the last hour
# this avoids a very expensive query that may run on the entire user base
# we also ensure we only touch the table if data changes
@@ -210,7 +216,8 @@ class UserStat < ActiveRecord::Base
def self.update_draft_count(user_id = nil)
if user_id.present?
- draft_count, has_topic_draft = DB.query_single <<~SQL, user_id: user_id, new_topic: Draft::NEW_TOPIC
+ draft_count, has_topic_draft =
+ DB.query_single <<~SQL, user_id: user_id, new_topic: Draft::NEW_TOPIC
UPDATE user_stats
SET draft_count = (SELECT COUNT(*) FROM drafts WHERE user_id = :user_id)
WHERE user_id = :user_id
@@ -219,11 +226,8 @@ class UserStat < ActiveRecord::Base
MessageBus.publish(
"/user-drafts/#{user_id}",
- {
- draft_count: draft_count,
- has_topic_draft: !!has_topic_draft
- },
- user_ids: [user_id]
+ { draft_count: draft_count, has_topic_draft: !!has_topic_draft },
+ user_ids: [user_id],
)
else
DB.exec <<~SQL
@@ -249,7 +253,7 @@ class UserStat < ActiveRecord::Base
AND topics.user_id <> posts.user_id
AND posts.deleted_at IS NULL AND topics.deleted_at IS NULL
AND topics.archetype <> 'private_message'
- #{start_time.nil? ? '' : 'AND posts.created_at > ?'}
+ #{start_time.nil? ? "" : "AND posts.created_at > ?"}
SQL
if start_time.nil?
DB.query_single(sql, self.user_id).first
@@ -303,7 +307,7 @@ class UserStat < ActiveRecord::Base
"/u/#{user.username_lower}/counters",
{ pending_posts_count: pending_posts_count },
user_ids: [user.id],
- group_ids: [Group::AUTO_GROUPS[:staff]]
+ group_ids: [Group::AUTO_GROUPS[:staff]],
)
end
diff --git a/app/models/user_summary.rb b/app/models/user_summary.rb
index f30507117d0..c5e4c93fee0 100644
--- a/app/models/user_summary.rb
+++ b/app/models/user_summary.rb
@@ -3,11 +3,10 @@
# ViewModel used on Summary tab on User page
class UserSummary
-
MAX_SUMMARY_RESULTS = 6
MAX_BADGES = 6
- alias :read_attribute_for_serialization :send
+ alias read_attribute_for_serialization send
def initialize(user, guardian)
@user = user
@@ -20,14 +19,14 @@ class UserSummary
.listable_topics
.visible
.where(user: @user)
- .order('like_count DESC, created_at DESC')
+ .order("like_count DESC, created_at DESC")
.limit(MAX_SUMMARY_RESULTS)
end
def replies
post_query
- .where('post_number > 1')
- .order('posts.like_count DESC, posts.created_at DESC')
+ .where("post_number > 1")
+ .order("posts.like_count DESC, posts.created_at DESC")
.limit(MAX_SUMMARY_RESULTS)
end
@@ -36,11 +35,11 @@ class UserSummary
.joins(:topic, :post)
.where(posts: { user_id: @user.id })
.includes(:topic, :post)
- .where('posts.post_type IN (?)', Topic.visible_post_types(@guardian && @guardian.user))
+ .where("posts.post_type IN (?)", Topic.visible_post_types(@guardian && @guardian.user))
.merge(Topic.listable_topics.visible.secured(@guardian))
.where(user: @user)
.where(internal: false, reflection: false, quote: false)
- .order('clicks DESC, topic_links.created_at DESC')
+ .order("clicks DESC, topic_links.created_at DESC")
.limit(MAX_SUMMARY_RESULTS)
end
@@ -50,14 +49,15 @@ class UserSummary
def most_liked_by_users
likers = {}
- UserAction.joins(:target_topic, :target_post)
+ UserAction
+ .joins(:target_topic, :target_post)
.merge(Topic.listable_topics.visible.secured(@guardian))
.where(user: @user)
.where(action_type: UserAction::WAS_LIKED)
.group(:acting_user_id)
- .order('COUNT(*) DESC')
+ .order("COUNT(*) DESC")
.limit(MAX_SUMMARY_RESULTS)
- .pluck('acting_user_id, COUNT(*)')
+ .pluck("acting_user_id, COUNT(*)")
.each { |l| likers[l[0]] = l[1] }
user_counts(likers)
@@ -65,14 +65,15 @@ class UserSummary
def most_liked_users
liked_users = {}
- UserAction.joins(:target_topic, :target_post)
+ UserAction
+ .joins(:target_topic, :target_post)
.merge(Topic.listable_topics.visible.secured(@guardian))
.where(action_type: UserAction::WAS_LIKED)
.where(acting_user_id: @user.id)
.group(:user_id)
- .order('COUNT(*) DESC')
+ .order("COUNT(*) DESC")
.limit(MAX_SUMMARY_RESULTS)
- .pluck('user_actions.user_id, COUNT(*)')
+ .pluck("user_actions.user_id, COUNT(*)")
.each { |l| liked_users[l[0]] = l[1] }
user_counts(liked_users)
@@ -84,12 +85,14 @@ class UserSummary
replied_users = {}
post_query
- .joins('JOIN posts replies ON posts.topic_id = replies.topic_id AND posts.reply_to_post_number = replies.post_number')
- .where('replies.user_id <> ?', @user.id)
- .group('replies.user_id')
- .order('COUNT(*) DESC')
+ .joins(
+ "JOIN posts replies ON posts.topic_id = replies.topic_id AND posts.reply_to_post_number = replies.post_number",
+ )
+ .where("replies.user_id <> ?", @user.id)
+ .group("replies.user_id")
+ .order("COUNT(*) DESC")
.limit(MAX_SUMMARY_RESULTS)
- .pluck('replies.user_id, COUNT(*)')
+ .pluck("replies.user_id, COUNT(*)")
.each { |r| replied_users[r[0]] = r[1] }
user_counts(replied_users)
@@ -121,44 +124,42 @@ class UserSummary
class CategoryWithCounts < OpenStruct
include ActiveModel::SerializerSupport
- KEYS = [:id, :name, :color, :text_color, :slug, :read_restricted, :parent_category_id]
+ KEYS = %i[id name color text_color slug read_restricted parent_category_id]
end
def top_categories
- post_count_query = post_query.group('topics.category_id')
+ post_count_query = post_query.group("topics.category_id")
top_categories = {}
- Category.where(id: post_count_query.order("count(*) DESC").limit(MAX_SUMMARY_RESULTS).pluck('category_id'))
+ Category
+ .where(
+ id: post_count_query.order("count(*) DESC").limit(MAX_SUMMARY_RESULTS).pluck("category_id"),
+ )
.pluck(:id, :name, :color, :text_color, :slug, :read_restricted, :parent_category_id)
.each do |c|
top_categories[c[0].to_i] = CategoryWithCounts.new(
- Hash[CategoryWithCounts::KEYS.zip(c)].merge(
- topic_count: 0,
- post_count: 0
- )
+ Hash[CategoryWithCounts::KEYS.zip(c)].merge(topic_count: 0, post_count: 0),
)
end
- post_count_query.where('post_number > 1')
- .where('topics.category_id in (?)', top_categories.keys)
- .pluck('category_id, COUNT(*)')
- .each do |r|
- top_categories[r[0].to_i].post_count = r[1]
- end
+ post_count_query
+ .where("post_number > 1")
+ .where("topics.category_id in (?)", top_categories.keys)
+ .pluck("category_id, COUNT(*)")
+ .each { |r| top_categories[r[0].to_i].post_count = r[1] }
- Topic.listable_topics.visible.secured(@guardian)
- .where('topics.category_id in (?)', top_categories.keys)
+ Topic
+ .listable_topics
+ .visible
+ .secured(@guardian)
+ .where("topics.category_id in (?)", top_categories.keys)
.where(user: @user)
- .group('topics.category_id')
- .pluck('category_id, COUNT(*)')
- .each do |r|
- top_categories[r[0].to_i].topic_count = r[1]
- end
+ .group("topics.category_id")
+ .pluck("category_id, COUNT(*)")
+ .each { |r| top_categories[r[0].to_i].topic_count = r[1] }
- top_categories.values.sort_by do |r|
- -(r[:post_count] + r[:topic_count])
- end
+ top_categories.values.sort_by { |r| -(r[:post_count] + r[:topic_count]) }
end
delegate :likes_given,
@@ -171,37 +172,42 @@ class UserSummary
:time_read,
to: :user_stat
-protected
+ protected
def user_counts(user_hash)
user_ids = user_hash.keys
lookup = UserLookup.new(user_ids)
- user_ids.map do |user_id|
- lookup_hash = lookup[user_id]
+ user_ids
+ .map do |user_id|
+ lookup_hash = lookup[user_id]
- if lookup_hash.present?
- primary_group = lookup.primary_groups[user_id]
- flair_group = lookup.flair_groups[user_id]
+ if lookup_hash.present?
+ primary_group = lookup.primary_groups[user_id]
+ flair_group = lookup.flair_groups[user_id]
- UserWithCount.new(
- lookup_hash.attributes.merge(
- count: user_hash[user_id],
- primary_group: primary_group,
- flair_group: flair_group
+ UserWithCount.new(
+ lookup_hash.attributes.merge(
+ count: user_hash[user_id],
+ primary_group: primary_group,
+ flair_group: flair_group,
+ ),
)
- )
+ end
end
- end.compact.sort_by { |u| -u[:count] }
+ .compact
+ .sort_by { |u| -u[:count] }
end
def post_query
Post
.joins(:topic)
.includes(:topic)
- .where('posts.post_type IN (?)', Topic.visible_post_types(@guardian&.user, include_moderator_actions: false))
+ .where(
+ "posts.post_type IN (?)",
+ Topic.visible_post_types(@guardian&.user, include_moderator_actions: false),
+ )
.merge(Topic.listable_topics.visible.secured(@guardian))
.where(user: @user)
end
-
end
diff --git a/app/models/user_visit.rb b/app/models/user_visit.rb
index ca08bc67477..57353a91a9d 100644
--- a/app/models/user_visit.rb
+++ b/app/models/user_visit.rb
@@ -2,7 +2,7 @@
class UserVisit < ActiveRecord::Base
def self.counts_by_day_query(start_date, end_date, group_id = nil)
- result = where('visited_at >= ? and visited_at <= ?', start_date.to_date, end_date.to_date)
+ result = where("visited_at >= ? and visited_at <= ?", start_date.to_date, end_date.to_date)
if group_id
result = result.joins("INNER JOIN users ON users.id = user_visits.user_id")
diff --git a/app/models/user_warning.rb b/app/models/user_warning.rb
index b11bff29949..11602880416 100644
--- a/app/models/user_warning.rb
+++ b/app/models/user_warning.rb
@@ -3,7 +3,7 @@
class UserWarning < ActiveRecord::Base
belongs_to :user
belongs_to :topic
- belongs_to :created_by, class_name: 'User'
+ belongs_to :created_by, class_name: "User"
end
# == Schema Information
diff --git a/app/models/username_validator.rb b/app/models/username_validator.rb
index 747eb2f777e..8c82653b205 100644
--- a/app/models/username_validator.rb
+++ b/app/models/username_validator.rb
@@ -54,16 +54,14 @@ class UsernameValidator
def username_present?
return unless errors.empty?
- if username.blank?
- self.errors << I18n.t(:'user.username.blank')
- end
+ self.errors << I18n.t(:"user.username.blank") if username.blank?
end
def username_length_min?
return unless errors.empty?
if username_grapheme_clusters.size < User.username_length.begin
- self.errors << I18n.t(:'user.username.short', min: User.username_length.begin)
+ self.errors << I18n.t(:"user.username.short", min: User.username_length.begin)
end
end
@@ -71,9 +69,9 @@ class UsernameValidator
return unless errors.empty?
if username_grapheme_clusters.size > User.username_length.end
- self.errors << I18n.t(:'user.username.long', max: User.username_length.end)
+ self.errors << I18n.t(:"user.username.long", max: User.username_length.end)
elsif username.length > MAX_CHARS
- self.errors << I18n.t(:'user.username.too_long')
+ self.errors << I18n.t(:"user.username.too_long")
end
end
@@ -81,7 +79,7 @@ class UsernameValidator
return unless errors.empty?
if self.class.invalid_char_pattern.match?(username)
- self.errors << I18n.t(:'user.username.characters')
+ self.errors << I18n.t(:"user.username.characters")
end
end
@@ -89,7 +87,7 @@ class UsernameValidator
return unless errors.empty? && self.class.char_allowlist_exists?
if username.chars.any? { |c| !self.class.allowed_char?(c) }
- self.errors << I18n.t(:'user.username.characters')
+ self.errors << I18n.t(:"user.username.characters")
end
end
@@ -97,7 +95,7 @@ class UsernameValidator
return unless errors.empty?
if INVALID_LEADING_CHAR_PATTERN.match?(username_grapheme_clusters.first)
- self.errors << I18n.t(:'user.username.must_begin_with_alphanumeric_or_underscore')
+ self.errors << I18n.t(:"user.username.must_begin_with_alphanumeric_or_underscore")
end
end
@@ -105,7 +103,7 @@ class UsernameValidator
return unless errors.empty?
if INVALID_TRAILING_CHAR_PATTERN.match?(username_grapheme_clusters.last)
- self.errors << I18n.t(:'user.username.must_end_with_alphanumeric')
+ self.errors << I18n.t(:"user.username.must_end_with_alphanumeric")
end
end
@@ -113,7 +111,7 @@ class UsernameValidator
return unless errors.empty?
if REPEATED_SPECIAL_CHAR_PATTERN.match?(username)
- self.errors << I18n.t(:'user.username.must_not_contain_two_special_chars_in_seq')
+ self.errors << I18n.t(:"user.username.must_not_contain_two_special_chars_in_seq")
end
end
@@ -121,7 +119,7 @@ class UsernameValidator
return unless errors.empty?
if CONFUSING_EXTENSIONS.match?(username)
- self.errors << I18n.t(:'user.username.must_not_end_with_confusing_suffix')
+ self.errors << I18n.t(:"user.username.must_not_end_with_confusing_suffix")
end
end
diff --git a/app/models/watched_word.rb b/app/models/watched_word.rb
index e396544e87d..e493f50e416 100644
--- a/app/models/watched_word.rb
+++ b/app/models/watched_word.rb
@@ -1,30 +1,31 @@
# frozen_string_literal: true
class WatchedWord < ActiveRecord::Base
-
def self.actions
- @actions ||= Enum.new(
- block: 1,
- censor: 2,
- require_approval: 3,
- flag: 4,
- link: 8,
- replace: 5,
- tag: 6,
- silence: 7,
- )
+ @actions ||=
+ Enum.new(
+ block: 1,
+ censor: 2,
+ require_approval: 3,
+ flag: 4,
+ link: 8,
+ replace: 5,
+ tag: 6,
+ silence: 7,
+ )
end
MAX_WORDS_PER_ACTION = 2000
before_validation do
self.word = self.class.normalize_word(self.word)
- if self.action == WatchedWord.actions[:link] && !(self.replacement =~ /^https?:\/\//)
- self.replacement = "#{Discourse.base_url}#{self.replacement&.starts_with?("/") ? "" : "/"}#{self.replacement}"
+ if self.action == WatchedWord.actions[:link] && !(self.replacement =~ %r{^https?://})
+ self.replacement =
+ "#{Discourse.base_url}#{self.replacement&.starts_with?("/") ? "" : "/"}#{self.replacement}"
end
end
- validates :word, presence: true, uniqueness: true, length: { maximum: 100 }
+ validates :word, presence: true, uniqueness: true, length: { maximum: 100 }
validates :action, presence: true
validate :replacement_is_url, if: -> { action == WatchedWord.actions[:link] }
@@ -36,26 +37,28 @@ class WatchedWord < ActiveRecord::Base
end
end
- after_save :clear_cache
+ after_save :clear_cache
after_destroy :clear_cache
scope :by_action, -> { order("action ASC, word ASC") }
- scope :for, ->(word:) do
- where("(word ILIKE :word AND case_sensitive = 'f') OR (word LIKE :word AND case_sensitive = 't')", word: word)
- end
+ scope :for,
+ ->(word:) {
+ where(
+ "(word ILIKE :word AND case_sensitive = 'f') OR (word LIKE :word AND case_sensitive = 't')",
+ word: word,
+ )
+ }
def self.normalize_word(w)
- w.strip.squeeze('*')
+ w.strip.squeeze("*")
end
def replacement_is_url
- if !(replacement =~ URI::regexp)
- errors.add(:base, :invalid_url)
- end
+ errors.add(:base, :invalid_url) if !(replacement =~ URI.regexp)
end
def replacement_is_tag_list
- tag_list = replacement&.split(',')
+ tag_list = replacement&.split(",")
tags = Tag.where(name: tag_list)
if (tag_list.blank? || tags.empty? || tag_list.size != tags.size)
errors.add(:base, :invalid_tag_list)
diff --git a/app/models/web_crawler_request.rb b/app/models/web_crawler_request.rb
index 7f7ceff9874..c1660f65555 100644
--- a/app/models/web_crawler_request.rb
+++ b/app/models/web_crawler_request.rb
@@ -16,8 +16,9 @@ class WebCrawlerRequest < ActiveRecord::Base
end
def self.write_cache!(user_agent, count, date)
- where(id: request_id(date: date, user_agent: user_agent))
- .update_all(["count = count + ?", count])
+ where(id: request_id(date: date, user_agent: user_agent)).update_all(
+ ["count = count + ?", count],
+ )
end
protected
@@ -25,14 +26,13 @@ class WebCrawlerRequest < ActiveRecord::Base
def self.request_id(date:, user_agent:, retries: 0)
id = where(date: date, user_agent: user_agent).pluck_first(:id)
id ||= create!({ date: date, user_agent: user_agent }.merge(count: 0)).id
- rescue # primary key violation
+ rescue StandardError # primary key violation
if retries == 0
request_id(date: date, user_agent: user_agent, retries: 1)
else
raise
end
end
-
end
# == Schema Information
diff --git a/app/models/web_hook.rb b/app/models/web_hook.rb
index d14a0dddad2..7ebfd01de10 100644
--- a/app/models/web_hook.rb
+++ b/app/models/web_hook.rb
@@ -8,9 +8,9 @@ class WebHook < ActiveRecord::Base
has_many :web_hook_events, dependent: :destroy
- default_scope { order('id ASC') }
+ default_scope { order("id ASC") }
- validates :payload_url, presence: true, format: URI::regexp(%w(http https))
+ validates :payload_url, presence: true, format: URI.regexp(%w[http https])
validates :secret, length: { minimum: 12 }, allow_blank: true
validates_presence_of :content_type
validates_presence_of :last_delivery_status
@@ -24,15 +24,11 @@ class WebHook < ActiveRecord::Base
end
def self.content_types
- @content_types ||= Enum.new('application/json' => 1,
- 'application/x-www-form-urlencoded' => 2)
+ @content_types ||= Enum.new("application/json" => 1, "application/x-www-form-urlencoded" => 2)
end
def self.last_delivery_statuses
- @last_delivery_statuses ||= Enum.new(inactive: 1,
- failed: 2,
- successful: 3,
- disabled: 4)
+ @last_delivery_statuses ||= Enum.new(inactive: 1, failed: 2, successful: 3, disabled: 4)
end
def self.default_event_types
@@ -44,7 +40,8 @@ class WebHook < ActiveRecord::Base
end
def self.active_web_hooks(type)
- WebHook.where(active: true)
+ WebHook
+ .where(active: true)
.joins(:web_hook_event_types)
.where("web_hooks.wildcard_web_hook = ? OR web_hook_event_types.name = ?", true, type.to_s)
.distinct
@@ -52,9 +49,10 @@ class WebHook < ActiveRecord::Base
def self.enqueue_hooks(type, event, opts = {})
active_web_hooks(type).each do |web_hook|
- Jobs.enqueue(:emit_web_hook_event, opts.merge(
- web_hook_id: web_hook.id, event_name: event.to_s, event_type: type.to_s
- ))
+ Jobs.enqueue(
+ :emit_web_hook_event,
+ opts.merge(web_hook_id: web_hook.id, event_name: event.to_s, event_type: type.to_s),
+ )
end
end
@@ -62,39 +60,40 @@ class WebHook < ActiveRecord::Base
if active_web_hooks(type).exists?
payload = WebHook.generate_payload(type, object, serializer)
- WebHook.enqueue_hooks(type, event, opts.merge(
- id: object.id,
- payload: payload
- )
- )
+ WebHook.enqueue_hooks(type, event, opts.merge(id: object.id, payload: payload))
end
end
def self.enqueue_topic_hooks(event, topic, payload = nil)
- if active_web_hooks('topic').exists? && topic.present?
- payload ||= begin
- topic_view = TopicView.new(topic.id, Discourse.system_user)
- WebHook.generate_payload(:topic, topic_view, WebHookTopicViewSerializer)
- end
+ if active_web_hooks("topic").exists? && topic.present?
+ payload ||=
+ begin
+ topic_view = TopicView.new(topic.id, Discourse.system_user)
+ WebHook.generate_payload(:topic, topic_view, WebHookTopicViewSerializer)
+ end
- WebHook.enqueue_hooks(:topic, event,
+ WebHook.enqueue_hooks(
+ :topic,
+ event,
id: topic.id,
category_id: topic.category_id,
tag_ids: topic.tags.pluck(:id),
- payload: payload
+ payload: payload,
)
end
end
def self.enqueue_post_hooks(event, post, payload = nil)
- if active_web_hooks('post').exists? && post.present?
+ if active_web_hooks("post").exists? && post.present?
payload ||= WebHook.generate_payload(:post, post)
- WebHook.enqueue_hooks(:post, event,
+ WebHook.enqueue_hooks(
+ :post,
+ event,
id: post.id,
category_id: post.topic&.category_id,
tag_ids: post.topic&.tags&.pluck(:id),
- payload: payload
+ payload: payload,
)
end
end
@@ -103,10 +102,7 @@ class WebHook < ActiveRecord::Base
serializer ||= TagSerializer if type == :tag
serializer ||= "WebHook#{type.capitalize}Serializer".constantize
- serializer.new(object,
- scope: self.guardian,
- root: false
- ).to_json
+ serializer.new(object, scope: self.guardian, root: false).to_json
end
private
@@ -121,15 +117,14 @@ class WebHook < ActiveRecord::Base
return if payload_url.blank?
uri = URI(payload_url.strip)
- allowed = begin
- FinalDestination::SSRFDetector.lookup_and_filter_ips(uri.hostname).present?
- rescue FinalDestination::SSRFDetector::DisallowedIpError
- false
- end
+ allowed =
+ begin
+ FinalDestination::SSRFDetector.lookup_and_filter_ips(uri.hostname).present?
+ rescue FinalDestination::SSRFDetector::DisallowedIpError
+ false
+ end
- if !allowed
- self.errors.add(:base, I18n.t("webhooks.payload_url.blocked_or_internal"))
- end
+ self.errors.add(:base, I18n.t("webhooks.payload_url.blocked_or_internal")) if !allowed
end
end
diff --git a/app/models/web_hook_event.rb b/app/models/web_hook_event.rb
index 9e7ac9cc601..d9a53041f29 100644
--- a/app/models/web_hook_event.rb
+++ b/app/models/web_hook_event.rb
@@ -5,12 +5,10 @@ class WebHookEvent < ActiveRecord::Base
after_save :update_web_hook_delivery_status
- default_scope { order('created_at DESC') }
+ default_scope { order("created_at DESC") }
def self.purge_old
- where(
- 'created_at < ?', SiteSetting.retain_web_hook_events_period_days.days.ago
- ).delete_all
+ where("created_at < ?", SiteSetting.retain_web_hook_events_period_days.days.ago).delete_all
end
def update_web_hook_delivery_status
diff --git a/app/models/web_hook_event_type.rb b/app/models/web_hook_event_type.rb
index a8852aeeb97..df3274802b4 100644
--- a/app/models/web_hook_event_type.rb
+++ b/app/models/web_hook_event_type.rb
@@ -18,18 +18,21 @@ class WebHookEventType < ActiveRecord::Base
has_and_belongs_to_many :web_hooks
- default_scope { order('id ASC') }
+ default_scope { order("id ASC") }
validates :name, presence: true, uniqueness: true
def self.active
ids_to_exclude = []
- ids_to_exclude << SOLVED unless defined?(SiteSetting.solved_enabled) && SiteSetting.solved_enabled
- ids_to_exclude << ASSIGN unless defined?(SiteSetting.assign_enabled) && SiteSetting.assign_enabled
+ unless defined?(SiteSetting.solved_enabled) && SiteSetting.solved_enabled
+ ids_to_exclude << SOLVED
+ end
+ unless defined?(SiteSetting.assign_enabled) && SiteSetting.assign_enabled
+ ids_to_exclude << ASSIGN
+ end
self.where.not(id: ids_to_exclude)
end
-
end
# == Schema Information
diff --git a/app/serializers/about_serializer.rb b/app/serializers/about_serializer.rb
index f55bdd34767..7a26822d299 100644
--- a/app/serializers/about_serializer.rb
+++ b/app/serializers/about_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class AboutSerializer < ApplicationSerializer
-
class UserAboutSerializer < BasicUserSerializer
attributes :title, :last_seen_at
end
diff --git a/app/serializers/admin_detailed_user_serializer.rb b/app/serializers/admin_detailed_user_serializer.rb
index 525036512bf..e82bf8ac346 100644
--- a/app/serializers/admin_detailed_user_serializer.rb
+++ b/app/serializers/admin_detailed_user_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class AdminDetailedUserSerializer < AdminUserSerializer
-
attributes :moderator,
:can_grant_admin,
:can_revoke_admin,
@@ -108,11 +107,11 @@ class AdminDetailedUserSerializer < AdminUserSerializer
def next_penalty
step_number = penalty_counts.total
- steps = SiteSetting.penalty_step_hours.split('|')
+ steps = SiteSetting.penalty_step_hours.split("|")
step_number = [step_number, steps.length].min
penalty_hours = steps[step_number]
Integer(penalty_hours, 10).hours.from_now
- rescue
+ rescue StandardError
nil
end
diff --git a/app/serializers/admin_email_template_serializer.rb b/app/serializers/admin_email_template_serializer.rb
index 07bfa929915..d48256dcaba 100644
--- a/app/serializers/admin_email_template_serializer.rb
+++ b/app/serializers/admin_email_template_serializer.rb
@@ -11,7 +11,7 @@ class AdminEmailTemplateSerializer < ApplicationSerializer
if I18n.exists?("#{object}.title")
I18n.t("#{object}.title")
else
- object.gsub(/.*\./, '').titleize
+ object.gsub(/.*\./, "").titleize
end
end
diff --git a/app/serializers/admin_user_action_serializer.rb b/app/serializers/admin_user_action_serializer.rb
index 1bff61203db..a07f99b594f 100644
--- a/app/serializers/admin_user_action_serializer.rb
+++ b/app/serializers/admin_user_action_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require_relative 'post_item_excerpt'
+require_relative "post_item_excerpt"
class AdminUserActionSerializer < ApplicationSerializer
include PostItemExcerpt
@@ -24,7 +24,7 @@ class AdminUserActionSerializer < ApplicationSerializer
:deleted_at,
:deleted_by,
:reply_to_post_number,
- :action_type
+ :action_type,
)
def post_id
@@ -64,7 +64,8 @@ class AdminUserActionSerializer < ApplicationSerializer
end
def moderator_action
- object.post_type == Post.types[:moderator_action] || object.post_type == Post.types[:small_action]
+ object.post_type == Post.types[:moderator_action] ||
+ object.post_type == Post.types[:small_action]
end
def deleted_by
@@ -76,9 +77,12 @@ class AdminUserActionSerializer < ApplicationSerializer
end
def action_type
- object.user_actions.select { |ua| ua.user_id = object.user_id }
+ object
+ .user_actions
+ .select { |ua| ua.user_id = object.user_id }
.select { |ua| [UserAction::REPLY, UserAction::RESPONSE].include? ua.action_type }
- .first.try(:action_type)
+ .first
+ .try(:action_type)
end
# we need this to handle deleted topics which aren't loaded via
diff --git a/app/serializers/admin_user_list_serializer.rb b/app/serializers/admin_user_list_serializer.rb
index dd9ce3f6f04..9a6be3c71ab 100644
--- a/app/serializers/admin_user_list_serializer.rb
+++ b/app/serializers/admin_user_list_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class AdminUserListSerializer < BasicUserSerializer
-
attributes :email,
:secondary_emails,
:active,
@@ -28,7 +27,7 @@ class AdminUserListSerializer < BasicUserSerializer
:staged,
:second_factor_enabled
- [:days_visited, :posts_read_count, :topics_entered, :post_count].each do |sym|
+ %i[days_visited posts_read_count topics_entered post_count].each do |sym|
attributes sym
define_method sym do
object.user_stat.public_send(sym)
@@ -106,13 +105,11 @@ class AdminUserListSerializer < BasicUserSerializer
end
def include_second_factor_enabled?
- !SiteSetting.enable_discourse_connect &&
- SiteSetting.enable_local_logins &&
+ !SiteSetting.enable_discourse_connect && SiteSetting.enable_local_logins &&
object.has_any_second_factor_methods_enabled?
end
def second_factor_enabled
true
end
-
end
diff --git a/app/serializers/admin_user_serializer.rb b/app/serializers/admin_user_serializer.rb
index e864578f919..fc396fc4bdd 100644
--- a/app/serializers/admin_user_serializer.rb
+++ b/app/serializers/admin_user_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class AdminUserSerializer < AdminUserListSerializer
-
attributes :name,
:associated_accounts,
:can_send_activation_email,
@@ -40,5 +39,4 @@ class AdminUserSerializer < AdminUserListSerializer
def registration_ip_address
object.registration_ip_address.try(:to_s)
end
-
end
diff --git a/app/serializers/admin_web_hook_serializer.rb b/app/serializers/admin_web_hook_serializer.rb
index cf3134188b2..1fa79e384e9 100644
--- a/app/serializers/admin_web_hook_serializer.rb
+++ b/app/serializers/admin_web_hook_serializer.rb
@@ -12,7 +12,12 @@ class AdminWebHookSerializer < ApplicationSerializer
:web_hook_event_types
has_many :categories, serializer: BasicCategorySerializer, embed: :ids, include: false
- has_many :tags, key: :tag_names, serializer: TagSerializer, embed: :ids, embed_key: :name, include: false
+ has_many :tags,
+ key: :tag_names,
+ serializer: TagSerializer,
+ embed: :ids,
+ embed_key: :name,
+ include: false
has_many :groups, serializer: BasicGroupSerializer, embed: :ids, include: false
def web_hook_event_types
diff --git a/app/serializers/api_key_scope_serializer.rb b/app/serializers/api_key_scope_serializer.rb
index f874efcf204..3386ab387a4 100644
--- a/app/serializers/api_key_scope_serializer.rb
+++ b/app/serializers/api_key_scope_serializer.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
class ApiKeyScopeSerializer < ApplicationSerializer
-
- attributes :resource,
- :action,
- :parameters,
- :urls,
- :allowed_parameters,
- :key
+ attributes :resource, :action, :parameters, :urls, :allowed_parameters, :key
def parameters
ApiKeyScope.scope_mappings.dig(object.resource.to_sym, object.action.to_sym, :params).to_a
@@ -18,7 +12,7 @@ class ApiKeyScopeSerializer < ApplicationSerializer
end
def action
- object.action.to_s.gsub('_', ' ')
+ object.action.to_s.gsub("_", " ")
end
def key
diff --git a/app/serializers/api_key_serializer.rb b/app/serializers/api_key_serializer.rb
index ab2a7a2e4d5..d1ccac58de0 100644
--- a/app/serializers/api_key_serializer.rb
+++ b/app/serializers/api_key_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ApiKeySerializer < ApplicationSerializer
-
attributes :id,
:key,
:truncated_key,
diff --git a/app/serializers/application_serializer.rb b/app/serializers/application_serializer.rb
index 40ee57b0622..aeecb045916 100644
--- a/app/serializers/application_serializer.rb
+++ b/app/serializers/application_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'distributed_cache'
+require "distributed_cache"
class ApplicationSerializer < ActiveModel::Serializer
embed :ids, include: true
@@ -19,7 +19,9 @@ class ApplicationSerializer < ActiveModel::Serializer
when String
fragment_cache.delete(name_or_regexp)
when Regexp
- fragment_cache.hash.keys
+ fragment_cache
+ .hash
+ .keys
.select { |k| k =~ name_or_regexp }
.each { |k| fragment_cache.delete(k) }
end
diff --git a/app/serializers/archetype_serializer.rb b/app/serializers/archetype_serializer.rb
index 469b1195f3b..8b74d5140a6 100644
--- a/app/serializers/archetype_serializer.rb
+++ b/app/serializers/archetype_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ArchetypeSerializer < ApplicationSerializer
-
attributes :id, :name, :options
def options
@@ -10,7 +9,7 @@ class ArchetypeSerializer < ApplicationSerializer
key: k,
title: I18n.t("archetypes.#{object.id}.options.#{k}.title"),
description: I18n.t("archetypes.#{object.id}.options.#{k}.description"),
- option_type: object.options[k]
+ option_type: object.options[k],
}
end
end
@@ -18,5 +17,4 @@ class ArchetypeSerializer < ApplicationSerializer
def name
I18n.t("archetypes.#{object.id}.title")
end
-
end
diff --git a/app/serializers/associated_group_serializer.rb b/app/serializers/associated_group_serializer.rb
index db7dec87238..121afd7d0ba 100644
--- a/app/serializers/associated_group_serializer.rb
+++ b/app/serializers/associated_group_serializer.rb
@@ -1,8 +1,5 @@
# frozen_string_literal: true
class AssociatedGroupSerializer < ApplicationSerializer
- attributes :id,
- :name,
- :provider_name,
- :label
+ attributes :id, :name, :provider_name, :label
end
diff --git a/app/serializers/auth_provider_serializer.rb b/app/serializers/auth_provider_serializer.rb
index 78cfcffd0b9..d7bc83afc29 100644
--- a/app/serializers/auth_provider_serializer.rb
+++ b/app/serializers/auth_provider_serializer.rb
@@ -1,9 +1,14 @@
# frozen_string_literal: true
class AuthProviderSerializer < ApplicationSerializer
-
- attributes :name, :custom_url, :pretty_name_override, :title_override,
- :frame_width, :frame_height, :can_connect, :can_revoke,
+ attributes :name,
+ :custom_url,
+ :pretty_name_override,
+ :title_override,
+ :frame_width,
+ :frame_height,
+ :can_connect,
+ :can_revoke,
:icon
def title_override
@@ -15,5 +20,4 @@ class AuthProviderSerializer < ApplicationSerializer
return SiteSetting.get(object.pretty_name_setting) if object.pretty_name_setting
object.pretty_name
end
-
end
diff --git a/app/serializers/backup_file_serializer.rb b/app/serializers/backup_file_serializer.rb
index 1ccab21a15a..239c8952c9f 100644
--- a/app/serializers/backup_file_serializer.rb
+++ b/app/serializers/backup_file_serializer.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
class BackupFileSerializer < ApplicationSerializer
- attributes :filename,
- :size,
- :last_modified
+ attributes :filename, :size, :last_modified
end
diff --git a/app/serializers/badge_index_serializer.rb b/app/serializers/badge_index_serializer.rb
index 81e58b3d9e0..127bec384ab 100644
--- a/app/serializers/badge_index_serializer.rb
+++ b/app/serializers/badge_index_serializer.rb
@@ -11,5 +11,4 @@ class BadgeIndexSerializer < BadgeSerializer
def has_badge
@options[:user_badges].include?(object.id)
end
-
end
diff --git a/app/serializers/badge_serializer.rb b/app/serializers/badge_serializer.rb
index cd837ac1cd9..004f0193230 100644
--- a/app/serializers/badge_serializer.rb
+++ b/app/serializers/badge_serializer.rb
@@ -1,9 +1,22 @@
# frozen_string_literal: true
class BadgeSerializer < ApplicationSerializer
- attributes :id, :name, :description, :grant_count, :allow_title,
- :multiple_grant, :icon, :image_url, :listable, :enabled, :badge_grouping_id,
- :system, :long_description, :slug, :has_badge, :manually_grantable?
+ attributes :id,
+ :name,
+ :description,
+ :grant_count,
+ :allow_title,
+ :multiple_grant,
+ :icon,
+ :image_url,
+ :listable,
+ :enabled,
+ :badge_grouping_id,
+ :system,
+ :long_description,
+ :slug,
+ :has_badge,
+ :manually_grantable?
has_one :badge_type
diff --git a/app/serializers/basic_category_serializer.rb b/app/serializers/basic_category_serializer.rb
index fe1b8cd2f71..06dfa9628eb 100644
--- a/app/serializers/basic_category_serializer.rb
+++ b/app/serializers/basic_category_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class BasicCategorySerializer < ApplicationSerializer
-
attributes :id,
:name,
:color,
@@ -42,19 +41,35 @@ class BasicCategorySerializer < ApplicationSerializer
end
def name
- object.uncategorized? ? I18n.t('uncategorized_category_name', locale: SiteSetting.default_locale) : object.name
+ if object.uncategorized?
+ I18n.t("uncategorized_category_name", locale: SiteSetting.default_locale)
+ else
+ object.name
+ end
end
def description_text
- object.uncategorized? ? I18n.t('category.uncategorized_description', locale: SiteSetting.default_locale) : object.description_text
+ if object.uncategorized?
+ I18n.t("category.uncategorized_description", locale: SiteSetting.default_locale)
+ else
+ object.description_text
+ end
end
def description
- object.uncategorized? ? I18n.t('category.uncategorized_description', locale: SiteSetting.default_locale) : object.description
+ if object.uncategorized?
+ I18n.t("category.uncategorized_description", locale: SiteSetting.default_locale)
+ else
+ object.description
+ end
end
def description_excerpt
- object.uncategorized? ? I18n.t('category.uncategorized_description', locale: SiteSetting.default_locale) : object.description_excerpt
+ if object.uncategorized?
+ I18n.t("category.uncategorized_description", locale: SiteSetting.default_locale)
+ else
+ object.description_excerpt
+ end
end
def can_edit
diff --git a/app/serializers/basic_group_history_serializer.rb b/app/serializers/basic_group_history_serializer.rb
index afd1c60f709..40518bd8ec8 100644
--- a/app/serializers/basic_group_history_serializer.rb
+++ b/app/serializers/basic_group_history_serializer.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
class BasicGroupHistorySerializer < ApplicationSerializer
- attributes :action,
- :subject,
- :prev_value,
- :new_value,
- :created_at
+ attributes :action, :subject, :prev_value, :new_value, :created_at
has_one :acting_user, embed: :objects, serializer: BasicUserSerializer
has_one :target_user, embed: :objects, serializer: BasicUserSerializer
diff --git a/app/serializers/basic_group_serializer.rb b/app/serializers/basic_group_serializer.rb
index e51e6000022..ab64df800a1 100644
--- a/app/serializers/basic_group_serializer.rb
+++ b/app/serializers/basic_group_serializer.rb
@@ -44,7 +44,9 @@ class BasicGroupSerializer < ApplicationSerializer
end
def bio_excerpt
- PrettyText.excerpt(object.bio_cooked, 110, keep_emoji_images: true) if object.bio_cooked.present?
+ if object.bio_cooked.present?
+ PrettyText.excerpt(object.bio_cooked, 110, keep_emoji_images: true)
+ end
end
def include_incoming_email?
diff --git a/app/serializers/basic_post_serializer.rb b/app/serializers/basic_post_serializer.rb
index 3486c47bc2c..029b04bdbf6 100644
--- a/app/serializers/basic_post_serializer.rb
+++ b/app/serializers/basic_post_serializer.rb
@@ -2,13 +2,7 @@
# The most basic attributes of a topic that we need to create a link for it.
class BasicPostSerializer < ApplicationSerializer
- attributes :id,
- :name,
- :username,
- :avatar_template,
- :created_at,
- :cooked,
- :cooked_hidden
+ attributes :id, :name, :username, :avatar_template, :created_at, :cooked, :cooked_hidden
attr_accessor :topic_view
@@ -35,9 +29,9 @@ class BasicPostSerializer < ApplicationSerializer
def cooked
if cooked_hidden
if scope.current_user && object.user_id == scope.current_user.id
- I18n.t('flagging.you_must_edit', path: "/my/messages")
+ I18n.t("flagging.you_must_edit", path: "/my/messages")
else
- I18n.t('flagging.user_must_edit')
+ I18n.t("flagging.user_must_edit")
end
else
object.filter_quotes(@parent_post)
@@ -49,11 +43,11 @@ class BasicPostSerializer < ApplicationSerializer
end
def post_custom_fields
- @post_custom_fields ||= if @topic_view
- (@topic_view.post_custom_fields || {})[object.id] || {}
- else
- object.custom_fields
- end
+ @post_custom_fields ||=
+ if @topic_view
+ (@topic_view.post_custom_fields || {})[object.id] || {}
+ else
+ object.custom_fields
+ end
end
-
end
diff --git a/app/serializers/basic_user_serializer.rb b/app/serializers/basic_user_serializer.rb
index fc580931f60..769002d0f00 100644
--- a/app/serializers/basic_user_serializer.rb
+++ b/app/serializers/basic_user_serializer.rb
@@ -28,9 +28,9 @@ class BasicUserSerializer < ApplicationSerializer
end
def categories_with_notification_level(lookup_level)
- category_user_notification_levels.select do |id, level|
- level == CategoryUser.notification_levels[lookup_level]
- end.keys
+ category_user_notification_levels
+ .select { |id, level| level == CategoryUser.notification_levels[lookup_level] }
+ .keys
end
def category_user_notification_levels
diff --git a/app/serializers/category_and_topic_lists_serializer.rb b/app/serializers/category_and_topic_lists_serializer.rb
index 863164fb108..55983ebc4a8 100644
--- a/app/serializers/category_and_topic_lists_serializer.rb
+++ b/app/serializers/category_and_topic_lists_serializer.rb
@@ -7,9 +7,7 @@ class CategoryAndTopicListsSerializer < ApplicationSerializer
has_many :primary_groups, serializer: PrimaryGroupSerializer, embed: :objects
def users
- users = object.topic_list.topics.map do |t|
- t.posters.map { |poster| poster.try(:user) }
- end
+ users = object.topic_list.topics.map { |t| t.posters.map { |poster| poster.try(:user) } }
users.flatten!
users.compact!
users.uniq!(&:id)
@@ -17,13 +15,11 @@ class CategoryAndTopicListsSerializer < ApplicationSerializer
end
def primary_groups
- groups = object.topic_list.topics.map do |t|
- t.posters.map { |poster| poster.try(:primary_group) }
- end
+ groups =
+ object.topic_list.topics.map { |t| t.posters.map { |poster| poster.try(:primary_group) } }
groups.flatten!
groups.compact!
groups.uniq!(&:id)
groups
end
-
end
diff --git a/app/serializers/category_detailed_serializer.rb b/app/serializers/category_detailed_serializer.rb
index 1349cd44aa8..39197008e2b 100644
--- a/app/serializers/category_detailed_serializer.rb
+++ b/app/serializers/category_detailed_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class CategoryDetailedSerializer < BasicCategorySerializer
-
attributes :topic_count,
:post_count,
:topics_day,
@@ -14,7 +13,10 @@ class CategoryDetailedSerializer < BasicCategorySerializer
has_many :displayable_topics, serializer: ListableTopicSerializer, embed: :objects, key: :topics
- has_many :subcategory_list, serializer: CategoryDetailedSerializer, embed: :objects, key: :subcategory_list
+ has_many :subcategory_list,
+ serializer: CategoryDetailedSerializer,
+ embed: :objects,
+ key: :subcategory_list
def include_displayable_topics?
displayable_topics.present?
@@ -55,11 +57,8 @@ class CategoryDetailedSerializer < BasicCategorySerializer
def count_with_subcategories(method)
count = object.public_send(method) || 0
- object.subcategories.each do |category|
- count += (category.public_send(method) || 0)
- end
+ object.subcategories.each { |category| count += (category.public_send(method) || 0) }
count
end
-
end
diff --git a/app/serializers/category_list_serializer.rb b/app/serializers/category_list_serializer.rb
index 1fe73e2229e..9f159e6fe16 100644
--- a/app/serializers/category_list_serializer.rb
+++ b/app/serializers/category_list_serializer.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
class CategoryListSerializer < ApplicationSerializer
-
- attributes :can_create_category,
- :can_create_topic
+ attributes :can_create_category, :can_create_topic
has_many :categories, serializer: CategoryDetailedSerializer, embed: :objects
@@ -14,5 +12,4 @@ class CategoryListSerializer < ApplicationSerializer
def can_create_topic
scope.can_create?(Topic)
end
-
end
diff --git a/app/serializers/category_serializer.rb b/app/serializers/category_serializer.rb
index b7ab43b5806..d2bfbb16121 100644
--- a/app/serializers/category_serializer.rb
+++ b/app/serializers/category_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class CategorySerializer < SiteCategorySerializer
-
attributes :read_restricted,
:available_groups,
:auto_close_hours,
@@ -32,25 +31,25 @@ class CategorySerializer < SiteCategorySerializer
end
def group_permissions
- @group_permissions ||= begin
- perms = object
- .category_groups
- .joins(:group)
- .includes(:group)
- .merge(Group.visible_groups(scope&.user, "groups.name ASC", include_everyone: true))
- .map do |cg|
- {
- permission_type: cg.permission_type,
- group_name: cg.group.name
+ @group_permissions ||=
+ begin
+ perms =
+ object
+ .category_groups
+ .joins(:group)
+ .includes(:group)
+ .merge(Group.visible_groups(scope&.user, "groups.name ASC", include_everyone: true))
+ .map { |cg| { permission_type: cg.permission_type, group_name: cg.group.name } }
+
+ if perms.length == 0 && !object.read_restricted
+ perms << {
+ permission_type: CategoryGroup.permission_types[:full],
+ group_name: Group[:everyone]&.name.presence || :everyone,
}
end
- if perms.length == 0 && !object.read_restricted
- perms << { permission_type: CategoryGroup.permission_types[:full], group_name: Group[:everyone]&.name.presence || :everyone }
+ perms
end
-
- perms
- end
end
def include_group_permissions?
@@ -70,8 +69,11 @@ class CategorySerializer < SiteCategorySerializer
end
def include_is_special?
- [SiteSetting.meta_category_id, SiteSetting.staff_category_id, SiteSetting.uncategorized_category_id]
- .include? object.id
+ [
+ SiteSetting.meta_category_id,
+ SiteSetting.staff_category_id,
+ SiteSetting.uncategorized_category_id,
+ ].include? object.id
end
def is_special
@@ -101,8 +103,8 @@ class CategorySerializer < SiteCategorySerializer
def notification_level
user = scope && scope.user
object.notification_level ||
- (user && CategoryUser.where(user: user, category: object).first.try(:notification_level)) ||
- CategoryUser.default_notification_level
+ (user && CategoryUser.where(user: user, category: object).first.try(:notification_level)) ||
+ CategoryUser.default_notification_level
end
def custom_fields
diff --git a/app/serializers/concerns/email_logs_mixin.rb b/app/serializers/concerns/email_logs_mixin.rb
index f0fe239309a..4f76679f746 100644
--- a/app/serializers/concerns/email_logs_mixin.rb
+++ b/app/serializers/concerns/email_logs_mixin.rb
@@ -3,12 +3,12 @@
module EmailLogsMixin
def self.included(klass)
klass.attributes :id,
- :to_address,
- :email_type,
- :user_id,
- :created_at,
- :post_url,
- :post_description
+ :to_address,
+ :email_type,
+ :user_id,
+ :created_at,
+ :post_url,
+ :post_description
klass.has_one :user, serializer: BasicUserSerializer, embed: :objects
end
diff --git a/app/serializers/concerns/topic_tags_mixin.rb b/app/serializers/concerns/topic_tags_mixin.rb
index 5c39cd5a5d4..2704ba33611 100644
--- a/app/serializers/concerns/topic_tags_mixin.rb
+++ b/app/serializers/concerns/topic_tags_mixin.rb
@@ -27,10 +27,15 @@ module TopicTagsMixin
def all_tags
return @tags if defined?(@tags)
# Calling method `pluck` or `order` along with `includes` causing N+1 queries
- tags = (SiteSetting.tags_sort_alphabetically ? topic.tags.sort_by(&:name) : topic.tags.sort_by(&:topic_count).reverse)
- if !scope.is_staff?
- tags = tags.reject { |tag| scope.hidden_tag_names.include?(tag[:name]) }
- end
+ tags =
+ (
+ if SiteSetting.tags_sort_alphabetically
+ topic.tags.sort_by(&:name)
+ else
+ topic.tags.sort_by(&:topic_count).reverse
+ end
+ )
+ tags = tags.reject { |tag| scope.hidden_tag_names.include?(tag[:name]) } if !scope.is_staff?
@tags = tags
end
end
diff --git a/app/serializers/concerns/user_auth_tokens_mixin.rb b/app/serializers/concerns/user_auth_tokens_mixin.rb
index 8e963f7fadb..aaa0b752eaa 100644
--- a/app/serializers/concerns/user_auth_tokens_mixin.rb
+++ b/app/serializers/concerns/user_auth_tokens_mixin.rb
@@ -3,16 +3,7 @@
module UserAuthTokensMixin
extend ActiveSupport::Concern
- included do
- attributes :id,
- :client_ip,
- :location,
- :browser,
- :device,
- :os,
- :icon,
- :created_at
- end
+ included { attributes :id, :client_ip, :location, :browser, :device, :os, :icon, :created_at }
def client_ip
object.client_ip.to_s
@@ -20,7 +11,7 @@ module UserAuthTokensMixin
def location
ipinfo = DiscourseIpInfo.get(client_ip, locale: I18n.locale)
- ipinfo[:location].presence || I18n.t('staff_action_logs.unknown')
+ ipinfo[:location].presence || I18n.t("staff_action_logs.unknown")
end
def browser
@@ -41,17 +32,17 @@ module UserAuthTokensMixin
def icon
case BrowserDetection.os(object.user_agent)
when :android
- 'fab-android'
+ "fab-android"
when :chromeos
- 'fab-chrome'
+ "fab-chrome"
when :macos, :ios
- 'fab-apple'
+ "fab-apple"
when :linux
- 'fab-linux'
+ "fab-linux"
when :windows
- 'fab-windows'
+ "fab-windows"
else
- 'question'
+ "question"
end
end
end
diff --git a/app/serializers/concerns/user_primary_group_mixin.rb b/app/serializers/concerns/user_primary_group_mixin.rb
index 65441ebba47..0bd2538b1eb 100644
--- a/app/serializers/concerns/user_primary_group_mixin.rb
+++ b/app/serializers/concerns/user_primary_group_mixin.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module UserPrimaryGroupMixin
-
def self.included(klass)
klass.attributes :primary_group_name,
:flair_name,
diff --git a/app/serializers/concerns/user_sidebar_mixin.rb b/app/serializers/concerns/user_sidebar_mixin.rb
index 1149b639602..cd872195858 100644
--- a/app/serializers/concerns/user_sidebar_mixin.rb
+++ b/app/serializers/concerns/user_sidebar_mixin.rb
@@ -2,13 +2,11 @@
module UserSidebarMixin
def sidebar_tags
- object.visible_sidebar_tags(scope)
+ object
+ .visible_sidebar_tags(scope)
.pluck(:name, :topic_count, :pm_topic_count)
.reduce([]) do |tags, sidebar_tag|
- tags.push(
- name: sidebar_tag[0],
- pm_only: sidebar_tag[1] == 0 && sidebar_tag[2] > 0
- )
+ tags.push(name: sidebar_tag[0], pm_only: sidebar_tag[1] == 0 && sidebar_tag[2] > 0)
end
end
@@ -33,7 +31,11 @@ module UserSidebarMixin
end
def sidebar_list_destination
- object.user_option.sidebar_list_none_selected? ? SiteSetting.default_sidebar_list_destination : object.user_option.sidebar_list_destination
+ if object.user_option.sidebar_list_none_selected?
+ SiteSetting.default_sidebar_list_destination
+ else
+ object.user_option.sidebar_list_destination
+ end
end
def include_sidebar_list_destination?
diff --git a/app/serializers/concerns/user_tag_notifications_mixin.rb b/app/serializers/concerns/user_tag_notifications_mixin.rb
index dfa367d6165..74c56ec1db7 100644
--- a/app/serializers/concerns/user_tag_notifications_mixin.rb
+++ b/app/serializers/concerns/user_tag_notifications_mixin.rb
@@ -22,9 +22,9 @@ module UserTagNotificationsMixin
end
def tags_with_notification_level(lookup_level)
- tag_user_notification_levels.select do |id, level|
- level == TagUser.notification_levels[lookup_level]
- end.keys
+ tag_user_notification_levels
+ .select { |id, level| level == TagUser.notification_levels[lookup_level] }
+ .keys
end
def tag_user_notification_levels
diff --git a/app/serializers/current_user_option_serializer.rb b/app/serializers/current_user_option_serializer.rb
index edfabcf3d6c..f3223f79243 100644
--- a/app/serializers/current_user_option_serializer.rb
+++ b/app/serializers/current_user_option_serializer.rb
@@ -18,10 +18,9 @@ class CurrentUserOptionSerializer < ApplicationSerializer
:should_be_redirected_to_top,
:redirected_to_top,
:treat_as_new_topic_start_date,
-
- def likes_notifications_disabled
- object.likes_notifications_disabled?
- end
+ def likes_notifications_disabled
+ object.likes_notifications_disabled?
+ end
def include_redirected_to_top?
object.redirected_to_top.present?
diff --git a/app/serializers/current_user_serializer.rb b/app/serializers/current_user_serializer.rb
index cb4153edefc..9a7cb1d9f11 100644
--- a/app/serializers/current_user_serializer.rb
+++ b/app/serializers/current_user_serializer.rb
@@ -79,11 +79,14 @@ class CurrentUserSerializer < BasicUserSerializer
def groups
owned_group_ids = GroupUser.where(user_id: id, owner: true).pluck(:group_id).to_set
- object.visible_groups.pluck(:id, :name, :has_messages).map do |id, name, has_messages|
- group = { id: id, name: name, has_messages: has_messages }
- group[:owner] = true if owned_group_ids.include?(id)
- group
- end
+ object
+ .visible_groups
+ .pluck(:id, :name, :has_messages)
+ .map do |id, name, has_messages|
+ group = { id: id, name: name, has_messages: has_messages }
+ group[:owner] = true if owned_group_ids.include?(id)
+ group
+ end
end
def link_posting_access
@@ -141,7 +144,7 @@ class CurrentUserSerializer < BasicUserSerializer
def custom_fields
fields = nil
if SiteSetting.public_user_custom_fields.present?
- fields = SiteSetting.public_user_custom_fields.split('|')
+ fields = SiteSetting.public_user_custom_fields.split("|")
end
DiscoursePluginRegistry.serialized_current_user_fields.each do |f|
fields ||= []
@@ -184,15 +187,21 @@ class CurrentUserSerializer < BasicUserSerializer
end
def top_category_ids
- omitted_notification_levels = [CategoryUser.notification_levels[:muted], CategoryUser.notification_levels[:regular]]
- CategoryUser.where(user_id: object.id)
+ omitted_notification_levels = [
+ CategoryUser.notification_levels[:muted],
+ CategoryUser.notification_levels[:regular],
+ ]
+ CategoryUser
+ .where(user_id: object.id)
.where.not(notification_level: omitted_notification_levels)
- .order("
+ .order(
+ "
CASE
WHEN notification_level = 3 THEN 1
WHEN notification_level = 2 THEN 2
WHEN notification_level = 4 THEN 3
- END")
+ END",
+ )
.pluck(:category_id)
.slice(0, SiteSetting.header_dropdown_category_count)
end
@@ -293,7 +302,9 @@ class CurrentUserSerializer < BasicUserSerializer
def redesigned_topic_timeline_enabled
if SiteSetting.enable_experimental_topic_timeline_groups.present?
- object.in_any_groups?(SiteSetting.enable_experimental_topic_timeline_groups.split("|").map(&:to_i))
+ object.in_any_groups?(
+ SiteSetting.enable_experimental_topic_timeline_groups.split("|").map(&:to_i),
+ )
else
false
end
diff --git a/app/serializers/detailed_tag_serializer.rb b/app/serializers/detailed_tag_serializer.rb
index 79354be61fb..83570c3d5e0 100644
--- a/app/serializers/detailed_tag_serializer.rb
+++ b/app/serializers/detailed_tag_serializer.rb
@@ -28,9 +28,8 @@ class DetailedTagSerializer < TagSerializer
private
def category_ids
- @_category_ids ||= object.categories.pluck(:id) +
- object.tag_groups.includes(:categories).map do |tg|
- tg.categories.map(&:id)
- end.flatten
+ @_category_ids ||=
+ object.categories.pluck(:id) +
+ object.tag_groups.includes(:categories).map { |tg| tg.categories.map(&:id) }.flatten
end
end
diff --git a/app/serializers/detailed_user_badge_serializer.rb b/app/serializers/detailed_user_badge_serializer.rb
index e31d8f8e8a7..693ceffb0e1 100644
--- a/app/serializers/detailed_user_badge_serializer.rb
+++ b/app/serializers/detailed_user_badge_serializer.rb
@@ -33,7 +33,7 @@ class DetailedUserBadgeSerializer < BasicUserBadgeSerializer
def can_favorite
SiteSetting.max_favorite_badges > 0 &&
- (scope.current_user.present? && object.user_id == scope.current_user.id) &&
- !(1..4).include?(object.badge_id)
+ (scope.current_user.present? && object.user_id == scope.current_user.id) &&
+ !(1..4).include?(object.badge_id)
end
end
diff --git a/app/serializers/directory_column_serializer.rb b/app/serializers/directory_column_serializer.rb
index 4e172d3e9e6..608ec4d2ddf 100644
--- a/app/serializers/directory_column_serializer.rb
+++ b/app/serializers/directory_column_serializer.rb
@@ -1,12 +1,7 @@
# frozen_string_literal: true
class DirectoryColumnSerializer < ApplicationSerializer
- attributes :id,
- :name,
- :type,
- :position,
- :icon,
- :user_field_id
+ attributes :id, :name, :type, :position, :icon, :user_field_id
def name
object.name || object.user_field.name
diff --git a/app/serializers/directory_item_serializer.rb b/app/serializers/directory_item_serializer.rb
index c4923cbbd10..bd218f982bf 100644
--- a/app/serializers/directory_item_serializer.rb
+++ b/app/serializers/directory_item_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class DirectoryItemSerializer < ApplicationSerializer
-
class UserSerializer < UserNameSerializer
include UserPrimaryGroupMixin
@@ -12,9 +11,7 @@ class DirectoryItemSerializer < ApplicationSerializer
object.user_custom_fields.each do |cuf|
user_field_id = @options[:user_custom_field_map][cuf.name]
- if user_field_id
- fields[user_field_id] = cuf.value
- end
+ fields[user_field_id] = cuf.value if user_field_id
end
fields
@@ -38,9 +35,7 @@ class DirectoryItemSerializer < ApplicationSerializer
def attributes
hash = super
- @options[:attributes].each do |attr|
- hash.merge!("#{attr}": object[attr])
- end
+ @options[:attributes].each { |attr| hash.merge!("#{attr}": object[attr]) }
if object.period_type == DirectoryItem.period_types[:all]
hash.merge!(time_read: object.user_stat.time_read)
diff --git a/app/serializers/draft_serializer.rb b/app/serializers/draft_serializer.rb
index bcdfa257fcf..8ca8111ccfb 100644
--- a/app/serializers/draft_serializer.rb
+++ b/app/serializers/draft_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require_relative 'post_item_excerpt'
+require_relative "post_item_excerpt"
class DraftSerializer < ApplicationSerializer
include PostItemExcerpt
@@ -24,7 +24,7 @@ class DraftSerializer < ApplicationSerializer
:archived
def cooked
- object.parsed_data['reply'] || ""
+ object.parsed_data["reply"] || ""
end
def draft_username
@@ -86,5 +86,4 @@ class DraftSerializer < ApplicationSerializer
def include_category_id?
object.topic&.category_id&.present?
end
-
end
diff --git a/app/serializers/edit_directory_column_serializer.rb b/app/serializers/edit_directory_column_serializer.rb
index 7c703d59659..ac9824c5000 100644
--- a/app/serializers/edit_directory_column_serializer.rb
+++ b/app/serializers/edit_directory_column_serializer.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
class EditDirectoryColumnSerializer < DirectoryColumnSerializer
- attributes :enabled,
- :automatic_position
+ attributes :enabled, :automatic_position
has_one :user_field, serializer: UserFieldSerializer, embed: :objects
end
diff --git a/app/serializers/email_log_serializer.rb b/app/serializers/email_log_serializer.rb
index 803a55c2e56..0e8640bc16e 100644
--- a/app/serializers/email_log_serializer.rb
+++ b/app/serializers/email_log_serializer.rb
@@ -3,10 +3,7 @@
class EmailLogSerializer < ApplicationSerializer
include EmailLogsMixin
- attributes :reply_key,
- :bounced,
- :has_bounce_key,
- :smtp_transaction_response
+ attributes :reply_key, :bounced, :has_bounce_key, :smtp_transaction_response
has_one :user, serializer: BasicUserSerializer, embed: :objects
diff --git a/app/serializers/embeddable_host_serializer.rb b/app/serializers/embeddable_host_serializer.rb
index 28bf3e905bc..d6a36de5c27 100644
--- a/app/serializers/embeddable_host_serializer.rb
+++ b/app/serializers/embeddable_host_serializer.rb
@@ -1,13 +1,9 @@
# frozen_string_literal: true
class EmbeddableHostSerializer < ApplicationSerializer
-
- TO_SERIALIZE = [:id, :host, :allowed_paths, :class_name, :category_id]
+ TO_SERIALIZE = %i[id host allowed_paths class_name category_id]
attributes *TO_SERIALIZE
- TO_SERIALIZE.each do |attr|
- define_method(attr) { object.public_send(attr) }
- end
-
+ TO_SERIALIZE.each { |attr| define_method(attr) { object.public_send(attr) } }
end
diff --git a/app/serializers/flagged_topic_summary_serializer.rb b/app/serializers/flagged_topic_summary_serializer.rb
index 0679e1ac4b0..251bcd4ca1c 100644
--- a/app/serializers/flagged_topic_summary_serializer.rb
+++ b/app/serializers/flagged_topic_summary_serializer.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
class FlaggedTopicSummarySerializer < ActiveModel::Serializer
-
- attributes(
- :id,
- :flag_counts,
- :user_ids,
- :last_flag_at
- )
+ attributes(:id, :flag_counts, :user_ids, :last_flag_at)
has_one :topic, serializer: FlaggedTopicSerializer
diff --git a/app/serializers/flagged_user_serializer.rb b/app/serializers/flagged_user_serializer.rb
index 92a383559aa..ed98e77ac12 100644
--- a/app/serializers/flagged_user_serializer.rb
+++ b/app/serializers/flagged_user_serializer.rb
@@ -39,11 +39,8 @@ class FlaggedUserSerializer < BasicUserSerializer
fields = User.allowed_user_custom_fields(scope)
result = {}
- fields.each do |k|
- result[k] = object.custom_fields[k] if object.custom_fields[k].present?
- end
+ fields.each { |k| result[k] = object.custom_fields[k] if object.custom_fields[k].present? }
result
end
-
end
diff --git a/app/serializers/group_post_serializer.rb b/app/serializers/group_post_serializer.rb
index 1176fc36094..0eed59b7a63 100644
--- a/app/serializers/group_post_serializer.rb
+++ b/app/serializers/group_post_serializer.rb
@@ -1,18 +1,11 @@
# frozen_string_literal: true
-require_relative 'post_item_excerpt'
+require_relative "post_item_excerpt"
class GroupPostSerializer < ApplicationSerializer
include PostItemExcerpt
- attributes :id,
- :created_at,
- :title,
- :url,
- :category_id,
- :post_number,
- :topic_id,
- :post_type
+ attributes :id, :created_at, :title, :url, :category_id, :post_number, :topic_id, :post_type
has_one :user, serializer: GroupPostUserSerializer, embed: :object
has_one :topic, serializer: BasicTopicSerializer, embed: :object
diff --git a/app/serializers/group_show_serializer.rb b/app/serializers/group_show_serializer.rb
index f3b520d19ac..f70c379a4a2 100644
--- a/app/serializers/group_show_serializer.rb
+++ b/app/serializers/group_show_serializer.rb
@@ -1,7 +1,13 @@
# frozen_string_literal: true
class GroupShowSerializer < BasicGroupSerializer
- attributes :is_group_user, :is_group_owner, :is_group_owner_display, :mentionable, :messageable, :flair_icon, :flair_type
+ attributes :is_group_user,
+ :is_group_owner,
+ :is_group_owner_display,
+ :mentionable,
+ :messageable,
+ :flair_icon,
+ :flair_type
def self.admin_attributes(*attrs)
attributes(*attrs)
@@ -108,19 +114,16 @@ class GroupShowSerializer < BasicGroupSerializer
flair_type.present? && (is_group_owner || scope.is_admin?)
end
- [:watching, :regular, :tracking, :watching_first_post, :muted].each do |level|
+ %i[watching regular tracking watching_first_post muted].each do |level|
define_method("#{level}_category_ids") do
group_category_notifications[NotificationLevels.all[level]] || []
end
define_method("include_#{level}_tags?") do
- SiteSetting.tagging_enabled? &&
- scope.is_admin? || (include_is_group_owner? && is_group_owner)
+ SiteSetting.tagging_enabled? && scope.is_admin? || (include_is_group_owner? && is_group_owner)
end
- define_method("#{level}_tags") do
- group_tag_notifications[NotificationLevels.all[level]] || []
- end
+ define_method("#{level}_tags") { group_tag_notifications[NotificationLevels.all[level]] || [] }
end
def associated_group_ids
@@ -144,7 +147,8 @@ class GroupShowSerializer < BasicGroupSerializer
def group_category_notifications
@group_category_notification_defaults ||=
- GroupCategoryNotificationDefault.where(group_id: object.id)
+ GroupCategoryNotificationDefault
+ .where(group_id: object.id)
.pluck(:notification_level, :category_id)
.inject({}) do |h, arr|
h[arr[0]] ||= []
@@ -155,7 +159,8 @@ class GroupShowSerializer < BasicGroupSerializer
def group_tag_notifications
@group_tag_notification_defaults ||=
- GroupTagNotificationDefault.where(group_id: object.id)
+ GroupTagNotificationDefault
+ .where(group_id: object.id)
.joins(:tag)
.pluck(:notification_level, :name)
.inject({}) do |h, arr|
diff --git a/app/serializers/group_user_serializer.rb b/app/serializers/group_user_serializer.rb
index fa5bbda7867..bc286d109b7 100644
--- a/app/serializers/group_user_serializer.rb
+++ b/app/serializers/group_user_serializer.rb
@@ -3,13 +3,7 @@
class GroupUserSerializer < BasicUserSerializer
include UserPrimaryGroupMixin
- attributes :name,
- :title,
- :last_posted_at,
- :last_seen_at,
- :added_at,
- :timezone,
- :status
+ attributes :name, :title, :last_posted_at, :last_seen_at, :added_at, :timezone, :status
def timezone
user.user_option.timezone
diff --git a/app/serializers/grouped_screened_url_serializer.rb b/app/serializers/grouped_screened_url_serializer.rb
index 9e2a4a1ff71..5117420070c 100644
--- a/app/serializers/grouped_screened_url_serializer.rb
+++ b/app/serializers/grouped_screened_url_serializer.rb
@@ -1,13 +1,9 @@
# frozen_string_literal: true
class GroupedScreenedUrlSerializer < ApplicationSerializer
- attributes :domain,
- :action,
- :match_count,
- :last_match_at,
- :created_at
+ attributes :domain, :action, :match_count, :last_match_at, :created_at
def action
- 'do_nothing'
+ "do_nothing"
end
end
diff --git a/app/serializers/grouped_search_result_serializer.rb b/app/serializers/grouped_search_result_serializer.rb
index 653ac70ac84..66c49602693 100644
--- a/app/serializers/grouped_search_result_serializer.rb
+++ b/app/serializers/grouped_search_result_serializer.rb
@@ -6,7 +6,14 @@ class GroupedSearchResultSerializer < ApplicationSerializer
has_many :categories, serializer: BasicCategorySerializer
has_many :tags, serializer: TagSerializer
has_many :groups, serializer: BasicGroupSerializer
- attributes :more_posts, :more_users, :more_categories, :term, :search_log_id, :more_full_page_results, :can_create_topic, :error
+ attributes :more_posts,
+ :more_users,
+ :more_categories,
+ :term,
+ :search_log_id,
+ :more_full_page_results,
+ :can_create_topic,
+ :error
def search_log_id
object.search_log_id
@@ -23,5 +30,4 @@ class GroupedSearchResultSerializer < ApplicationSerializer
def can_create_topic
scope.can_create?(Topic)
end
-
end
diff --git a/app/serializers/hidden_profile_serializer.rb b/app/serializers/hidden_profile_serializer.rb
index f2a04db807b..f0b8e00d3b6 100644
--- a/app/serializers/hidden_profile_serializer.rb
+++ b/app/serializers/hidden_profile_serializer.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
class HiddenProfileSerializer < BasicUserSerializer
- attributes(
- :profile_hidden?,
- :title,
- :primary_group_name
- )
+ attributes(:profile_hidden?, :title, :primary_group_name)
def profile_hidden?
true
diff --git a/app/serializers/incoming_email_details_serializer.rb b/app/serializers/incoming_email_details_serializer.rb
index d248a3ac588..490b692e88f 100644
--- a/app/serializers/incoming_email_details_serializer.rb
+++ b/app/serializers/incoming_email_details_serializer.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
class IncomingEmailDetailsSerializer < ApplicationSerializer
-
- attributes :error,
- :error_description,
- :rejection_message,
- :headers,
- :subject,
- :body
+ attributes :error, :error_description, :rejection_message, :headers, :subject, :body
def initialize(incoming_email, opts)
super
@@ -39,15 +33,30 @@ class IncomingEmailDetailsSerializer < ApplicationSerializer
end
def body
- body = @mail.text_part.decoded rescue nil
- body ||= @mail.html_part.decoded rescue nil
- body ||= @mail.body.decoded rescue nil
+ body =
+ begin
+ @mail.text_part.decoded
+ rescue StandardError
+ nil
+ end
+ body ||=
+ begin
+ @mail.html_part.decoded
+ rescue StandardError
+ nil
+ end
+ body ||=
+ begin
+ @mail.body.decoded
+ rescue StandardError
+ nil
+ end
return I18n.t("emails.incoming.no_body") if body.blank?
- body.encode("utf-8", invalid: :replace, undef: :replace, replace: "")
+ body
+ .encode("utf-8", invalid: :replace, undef: :replace, replace: "")
.strip
.truncate_words(100, escape: false)
end
-
end
diff --git a/app/serializers/incoming_email_serializer.rb b/app/serializers/incoming_email_serializer.rb
index 54830995a12..116c36a43a5 100644
--- a/app/serializers/incoming_email_serializer.rb
+++ b/app/serializers/incoming_email_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class IncomingEmailSerializer < ApplicationSerializer
-
attributes :id,
:created_at,
:from_address,
@@ -34,5 +33,4 @@ class IncomingEmailSerializer < ApplicationSerializer
def error
@object.error.presence || I18n.t("emails.incoming.unrecognized_error")
end
-
end
diff --git a/app/serializers/invite_link_serializer.rb b/app/serializers/invite_link_serializer.rb
index 21a64509189..8f454f87274 100644
--- a/app/serializers/invite_link_serializer.rb
+++ b/app/serializers/invite_link_serializer.rb
@@ -1,7 +1,13 @@
# frozen_string_literal: true
class InviteLinkSerializer < ApplicationSerializer
- attributes :id, :invite_key, :created_at, :max_redemptions_allowed, :redemption_count, :expires_at, :group_names
+ attributes :id,
+ :invite_key,
+ :created_at,
+ :max_redemptions_allowed,
+ :redemption_count,
+ :expires_at,
+ :group_names
def group_names
object.groups.pluck(:name).join(", ")
diff --git a/app/serializers/invited_serializer.rb b/app/serializers/invited_serializer.rb
index a0f76017e44..c1acf056b2f 100644
--- a/app/serializers/invited_serializer.rb
+++ b/app/serializers/invited_serializer.rb
@@ -6,10 +6,17 @@ class InvitedSerializer < ApplicationSerializer
def invites
ActiveModel::ArraySerializer.new(
object.invite_list,
- each_serializer: object.type == "pending" || object.type == "expired" ? InviteSerializer : InvitedUserSerializer,
+ each_serializer:
+ (
+ if object.type == "pending" || object.type == "expired"
+ InviteSerializer
+ else
+ InvitedUserSerializer
+ end
+ ),
scope: scope,
root: false,
- show_emails: object.show_emails
+ show_emails: object.show_emails,
).as_json
end
diff --git a/app/serializers/invited_user_record_serializer.rb b/app/serializers/invited_user_record_serializer.rb
index 027e8f60da2..66cd1e5d202 100644
--- a/app/serializers/invited_user_record_serializer.rb
+++ b/app/serializers/invited_user_record_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class InvitedUserRecordSerializer < BasicUserSerializer
-
attributes :topics_entered,
:posts_read_count,
:last_seen_at,
@@ -56,5 +55,4 @@ class InvitedUserRecordSerializer < BasicUserSerializer
def can_see_invite_details?
@can_see_invite_details ||= scope.can_see_invite_details?(invited_by)
end
-
end
diff --git a/app/serializers/listable_topic_serializer.rb b/app/serializers/listable_topic_serializer.rb
index afcbb6fa6c1..de117bc1026 100644
--- a/app/serializers/listable_topic_serializer.rb
+++ b/app/serializers/listable_topic_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ListableTopicSerializer < BasicTopicSerializer
-
attributes :reply_count,
:highest_post_number,
:image_url,
@@ -114,29 +113,30 @@ class ListableTopicSerializer < BasicTopicSerializer
object.excerpt
end
- alias :include_last_read_post_number? :has_user_data
+ alias include_last_read_post_number? has_user_data
# TODO: For backwards compatibility with themes,
# Remove once Discourse 2.8 is released
def unread
0
end
- alias :include_unread? :has_user_data
+ alias include_unread? has_user_data
# TODO: For backwards compatibility with themes,
# Remove once Discourse 2.8 is released
def new_posts
unread_helper.unread_posts
end
- alias :include_new_posts? :has_user_data
+ alias include_new_posts? has_user_data
def unread_posts
unread_helper.unread_posts
end
- alias :include_unread_posts? :has_user_data
+ alias include_unread_posts? has_user_data
def include_excerpt?
- pinned || SiteSetting.always_include_topic_excerpts || theme_modifier_helper.serialize_topic_excerpts
+ pinned || SiteSetting.always_include_topic_excerpts ||
+ theme_modifier_helper.serialize_topic_excerpts
end
def pinned
@@ -170,5 +170,4 @@ class ListableTopicSerializer < BasicTopicSerializer
def theme_modifier_helper
@theme_modifier_helper ||= ThemeModifierHelper.new(request: scope.request)
end
-
end
diff --git a/app/serializers/new_post_result_serializer.rb b/app/serializers/new_post_result_serializer.rb
index e15af2fad14..f5ad629c808 100644
--- a/app/serializers/new_post_result_serializer.rb
+++ b/app/serializers/new_post_result_serializer.rb
@@ -1,14 +1,7 @@
# frozen_string_literal: true
class NewPostResultSerializer < ApplicationSerializer
- attributes :action,
- :post,
- :errors,
- :success,
- :pending_count,
- :reason,
- :message,
- :route_to
+ attributes :action, :post, :errors, :success, :pending_count, :reason, :message, :route_to
has_one :pending_post, serializer: TopicPendingPostSerializer, root: false, embed: :objects
@@ -81,5 +74,4 @@ class NewPostResultSerializer < ApplicationSerializer
def include_message?
object.message.present?
end
-
end
diff --git a/app/serializers/notification_serializer.rb b/app/serializers/notification_serializer.rb
index 40ff319b762..63092363f28 100644
--- a/app/serializers/notification_serializer.rb
+++ b/app/serializers/notification_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class NotificationSerializer < ApplicationSerializer
-
attributes :id,
:user_id,
:external_id,
@@ -47,5 +46,4 @@ class NotificationSerializer < ApplicationSerializer
def include_external_id?
SiteSetting.enable_discourse_connect
end
-
end
diff --git a/app/serializers/permalink_serializer.rb b/app/serializers/permalink_serializer.rb
index 78b46fd9a76..7aa66affa29 100644
--- a/app/serializers/permalink_serializer.rb
+++ b/app/serializers/permalink_serializer.rb
@@ -1,10 +1,22 @@
# frozen_string_literal: true
class PermalinkSerializer < ApplicationSerializer
- attributes :id, :url, :topic_id, :topic_title, :topic_url,
- :post_id, :post_url, :post_number, :post_topic_title,
- :category_id, :category_name, :category_url, :external_url,
- :tag_id, :tag_name, :tag_url
+ attributes :id,
+ :url,
+ :topic_id,
+ :topic_title,
+ :topic_url,
+ :post_id,
+ :post_url,
+ :post_number,
+ :post_topic_title,
+ :category_id,
+ :category_name,
+ :category_url,
+ :external_url,
+ :tag_id,
+ :tag_name,
+ :tag_url
def topic_title
object&.topic&.title
diff --git a/app/serializers/post_action_type_serializer.rb b/app/serializers/post_action_type_serializer.rb
index 915edb4da1a..a829d91fd8e 100644
--- a/app/serializers/post_action_type_serializer.rb
+++ b/app/serializers/post_action_type_serializer.rb
@@ -1,16 +1,7 @@
# frozen_string_literal: true
class PostActionTypeSerializer < ApplicationSerializer
-
- attributes(
- :id,
- :name_key,
- :name,
- :description,
- :short_description,
- :is_flag,
- :is_custom_flag
- )
+ attributes(:id, :name_key, :name, :description, :short_description, :is_flag, :is_custom_flag)
include ConfigurableUrls
@@ -23,15 +14,15 @@ class PostActionTypeSerializer < ApplicationSerializer
end
def name
- i18n('title')
+ i18n("title")
end
def description
- i18n('description', tos_url: tos_path, base_path: Discourse.base_path)
+ i18n("description", tos_url: tos_path, base_path: Discourse.base_path)
end
def short_description
- i18n('short_description', tos_url: tos_path, base_path: Discourse.base_path)
+ i18n("short_description", tos_url: tos_path, base_path: Discourse.base_path)
end
def name_key
diff --git a/app/serializers/post_action_user_serializer.rb b/app/serializers/post_action_user_serializer.rb
index 40d81451ac5..b58a5723e3f 100644
--- a/app/serializers/post_action_user_serializer.rb
+++ b/app/serializers/post_action_user_serializer.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
class PostActionUserSerializer < BasicUserSerializer
- attributes :post_url,
- :username_lower,
- :unknown
+ attributes :post_url, :username_lower, :unknown
def id
object.user.id
@@ -32,5 +30,4 @@ class PostActionUserSerializer < BasicUserSerializer
def include_unknown?
(@options[:unknown_user_ids] || []).include?(object.user.id)
end
-
end
diff --git a/app/serializers/post_item_excerpt.rb b/app/serializers/post_item_excerpt.rb
index e7f9f004153..164eb861dec 100644
--- a/app/serializers/post_item_excerpt.rb
+++ b/app/serializers/post_item_excerpt.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module PostItemExcerpt
-
def self.included(base)
base.attributes(:excerpt, :truncated)
end
@@ -22,5 +21,4 @@ module PostItemExcerpt
def include_truncated?
cooked.length > 300
end
-
end
diff --git a/app/serializers/post_revision_serializer.rb b/app/serializers/post_revision_serializer.rb
index de4430fafc3..46c2835ff09 100644
--- a/app/serializers/post_revision_serializer.rb
+++ b/app/serializers/post_revision_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class PostRevisionSerializer < ApplicationSerializer
-
attributes :created_at,
:post_id,
# which revision is hidden
@@ -35,13 +34,9 @@ class PostRevisionSerializer < ApplicationSerializer
changes_name = "#{field}_changes".to_sym
self.attributes changes_name
- define_method(changes_name) do
- { previous: previous[field], current: current[field] }
- end
+ define_method(changes_name) { { previous: previous[field], current: current[field] } }
- define_method("include_#{changes_name}?") do
- previous[field] != current[field]
- end
+ define_method("include_#{changes_name}?") { previous[field] != current[field] }
end
add_compared_field :wiki
@@ -59,9 +54,12 @@ class PostRevisionSerializer < ApplicationSerializer
end
def previous_revision
- @previous_revision ||= revisions.select { |r| r["revision"] >= first_revision }
- .select { |r| r["revision"] < current_revision }
- .last.try(:[], "revision")
+ @previous_revision ||=
+ revisions
+ .select { |r| r["revision"] >= first_revision }
+ .select { |r| r["revision"] < current_revision }
+ .last
+ .try(:[], "revision")
end
def current_revision
@@ -69,9 +67,12 @@ class PostRevisionSerializer < ApplicationSerializer
end
def next_revision
- @next_revision ||= revisions.select { |r| r["revision"] <= last_revision }
- .select { |r| r["revision"] > current_revision }
- .first.try(:[], "revision")
+ @next_revision ||=
+ revisions
+ .select { |r| r["revision"] <= last_revision }
+ .select { |r| r["revision"] > current_revision }
+ .first
+ .try(:[], "revision")
end
def last_revision
@@ -108,8 +109,9 @@ class PostRevisionSerializer < ApplicationSerializer
def edit_reason
# only show 'edit_reason' when revisions are consecutive
- current["edit_reason"] if scope.can_view_hidden_post_revisions? ||
- current["revision"] == previous["revision"] + 1
+ if scope.can_view_hidden_post_revisions? || current["revision"] == previous["revision"] + 1
+ current["edit_reason"]
+ end
end
def body_changes
@@ -119,23 +121,20 @@ class PostRevisionSerializer < ApplicationSerializer
{
inline: cooked_diff.inline_html,
side_by_side: cooked_diff.side_by_side_html,
- side_by_side_markdown: raw_diff.side_by_side_markdown
+ side_by_side_markdown: raw_diff.side_by_side_markdown,
}
end
def title_changes
- prev = "#{previous["title"] && CGI::escapeHTML(previous["title"])}
"
- cur = "#{current["title"] && CGI::escapeHTML(current["title"])}
"
+ prev = "#{previous["title"] && CGI.escapeHTML(previous["title"])}
"
+ cur = "#{current["title"] && CGI.escapeHTML(current["title"])}
"
# always show the title for post_number == 1
return if object.post.post_number > 1 && prev == cur
diff = DiscourseDiff.new(prev, cur)
- {
- inline: diff.inline_html,
- side_by_side: diff.side_by_side_html
- }
+ { inline: diff.inline_html, side_by_side: diff.side_by_side_html }
end
def user_changes
@@ -148,23 +147,23 @@ class PostRevisionSerializer < ApplicationSerializer
current = User.find_by(id: cur) || Discourse.system_user
{
- previous: {
- username: previous.username_lower,
- display_username: previous.username,
- avatar_template: previous.avatar_template
- },
- current: {
- username: current.username_lower,
- display_username: current.username,
- avatar_template: current.avatar_template
- }
+ previous: {
+ username: previous.username_lower,
+ display_username: previous.username,
+ avatar_template: previous.avatar_template,
+ },
+ current: {
+ username: current.username_lower,
+ display_username: current.username,
+ avatar_template: current.avatar_template,
+ },
}
end
def tags_changes
changes = {
previous: filter_visible_tags(previous["tags"]),
- current: filter_visible_tags(current["tags"])
+ current: filter_visible_tags(current["tags"]),
}
changes[:previous] == changes[:current] ? nil : changes
end
@@ -184,18 +183,15 @@ class PostRevisionSerializer < ApplicationSerializer
end
def revisions
- @revisions ||= all_revisions.select { |r| scope.can_view_hidden_post_revisions? || !r["hidden"] }
+ @revisions ||=
+ all_revisions.select { |r| scope.can_view_hidden_post_revisions? || !r["hidden"] }
end
def all_revisions
return @all_revisions if @all_revisions
- post_revisions = PostRevision
- .where(post_id: object.post_id)
- .order(number: :desc)
- .limit(99)
- .to_a
- .reverse
+ post_revisions =
+ PostRevision.where(post_id: object.post_id).order(number: :desc).limit(99).to_a.reverse
latest_modifications = {
"raw" => [post.raw],
@@ -203,24 +199,24 @@ class PostRevisionSerializer < ApplicationSerializer
"edit_reason" => [post.edit_reason],
"wiki" => [post.wiki],
"post_type" => [post.post_type],
- "user_id" => [post.user_id]
+ "user_id" => [post.user_id],
}
# Retrieve any `tracked_topic_fields`
PostRevisor.tracked_topic_fields.each_key do |field|
next if field == :tags # Special handling below
- if topic.respond_to?(field)
- latest_modifications[field.to_s] = [topic.public_send(field)]
- end
+ latest_modifications[field.to_s] = [topic.public_send(field)] if topic.respond_to?(field)
end
- latest_modifications["featured_link"] = [post.topic.featured_link] if SiteSetting.topic_featured_link_enabled
+ latest_modifications["featured_link"] = [
+ post.topic.featured_link,
+ ] if SiteSetting.topic_featured_link_enabled
latest_modifications["tags"] = [topic.tags.pluck(:name)] if scope.can_see_tags?(topic)
post_revisions << PostRevision.new(
number: post_revisions.last.number + 1,
hidden: post.hidden,
- modifications: latest_modifications
+ modifications: latest_modifications,
)
@all_revisions = []
@@ -231,22 +227,20 @@ class PostRevisionSerializer < ApplicationSerializer
revision[:revision] = pr.number
revision[:hidden] = pr.hidden
- pr.modifications.each_key do |field|
- revision[field] = pr.modifications[field][0]
- end
+ pr.modifications.each_key { |field| revision[field] = pr.modifications[field][0] }
@all_revisions << revision
end
# waterfall
- (@all_revisions.count - 1).downto(1).each do |r|
- cur = @all_revisions[r]
- prev = @all_revisions[r - 1]
+ (@all_revisions.count - 1)
+ .downto(1)
+ .each do |r|
+ cur = @all_revisions[r]
+ prev = @all_revisions[r - 1]
- cur.each_key do |field|
- prev[field] = prev.has_key?(field) ? prev[field] : cur[field]
+ cur.each_key { |field| prev[field] = prev.has_key?(field) ? prev[field] : cur[field] }
end
- end
@all_revisions
end
@@ -272,5 +266,4 @@ class PostRevisionSerializer < ApplicationSerializer
tags
end
end
-
end
diff --git a/app/serializers/post_serializer.rb b/app/serializers/post_serializer.rb
index 426c31f220a..78e559c031a 100644
--- a/app/serializers/post_serializer.rb
+++ b/app/serializers/post_serializer.rb
@@ -1,22 +1,19 @@
# frozen_string_literal: true
class PostSerializer < BasicPostSerializer
-
# To pass in additional information we might need
- INSTANCE_VARS ||= [
- :parent_post,
- :add_raw,
- :add_title,
- :single_post_link_counts,
- :draft_sequence,
- :post_actions,
- :all_post_actions,
- :add_excerpt
+ INSTANCE_VARS ||= %i[
+ parent_post
+ add_raw
+ add_title
+ single_post_link_counts
+ draft_sequence
+ post_actions
+ all_post_actions
+ add_excerpt
]
- INSTANCE_VARS.each do |v|
- self.public_send(:attr_accessor, v)
- end
+ INSTANCE_VARS.each { |v| self.public_send(:attr_accessor, v) }
attributes :post_number,
:post_type,
@@ -95,9 +92,7 @@ class PostSerializer < BasicPostSerializer
super(object, opts)
PostSerializer::INSTANCE_VARS.each do |name|
- if opts.include? name
- self.public_send("#{name}=", opts[name])
- end
+ self.public_send("#{name}=", opts[name]) if opts.include? name
end
end
@@ -150,13 +145,14 @@ class PostSerializer < BasicPostSerializer
end
def include_group_moderator?
- @group_moderator ||= begin
- if @topic_view
- @topic_view.category_group_moderator_user_ids.include?(object.user_id)
- else
- object&.user&.guardian&.is_category_group_moderator?(object&.topic&.category)
+ @group_moderator ||=
+ begin
+ if @topic_view
+ @topic_view.category_group_moderator_user_ids.include?(object.user_id)
+ else
+ object&.user&.guardian&.is_category_group_moderator?(object&.topic&.category)
+ end
end
- end
end
def yours
@@ -260,7 +256,7 @@ class PostSerializer < BasicPostSerializer
{
username: object.reply_to_user.username,
name: object.reply_to_user.name,
- avatar_template: object.reply_to_user.avatar_template
+ avatar_template: object.reply_to_user.avatar_template,
}
end
@@ -290,16 +286,22 @@ class PostSerializer < BasicPostSerializer
count = object.public_send(count_col) if object.respond_to?(count_col)
summary = { id: id, count: count }
- if scope.post_can_act?(object, sym, opts: { taken_actions: actions }, can_see_post: can_see_post)
+ if scope.post_can_act?(
+ object,
+ sym,
+ opts: {
+ taken_actions: actions,
+ },
+ can_see_post: can_see_post,
+ )
summary[:can_act] = true
end
if sym == :notify_user &&
- (
- (scope.current_user.present? && scope.current_user == object.user) ||
- (object.user && object.user.bot?)
- )
-
+ (
+ (scope.current_user.present? && scope.current_user == object.user) ||
+ (object.user && object.user.bot?)
+ )
summary.delete(:can_act)
end
@@ -316,9 +318,7 @@ class PostSerializer < BasicPostSerializer
summary.delete(:count) if summary[:count] == 0
# Only include it if the user can do it or it has a count
- if summary[:can_act] || summary[:count]
- result << summary
- end
+ result << summary if summary[:can_act] || summary[:count]
end
result
@@ -339,7 +339,8 @@ class PostSerializer < BasicPostSerializer
def include_link_counts?
return true if @single_post_link_counts.present?
- @topic_view.present? && @topic_view.link_counts.present? && @topic_view.link_counts[object.id].present?
+ @topic_view.present? && @topic_view.link_counts.present? &&
+ @topic_view.link_counts[object.id].present?
end
def include_read?
@@ -496,9 +497,7 @@ class PostSerializer < BasicPostSerializer
end
def include_last_wiki_edit?
- object.wiki &&
- object.post_number == 1 &&
- object.revisions.size > 0
+ object.wiki && object.post_number == 1 && object.revisions.size > 0
end
def include_hidden_reason_id?
@@ -563,9 +562,7 @@ class PostSerializer < BasicPostSerializer
def mentioned_users
if @topic_view && (mentions = @topic_view.mentions[object.id])
- users = mentions
- .map { |username| @topic_view.mentioned_users[username] }
- .compact
+ users = mentions.map { |username| @topic_view.mentioned_users[username] }.compact
else
users = User.where(username: object.mentions)
end
@@ -573,7 +570,7 @@ class PostSerializer < BasicPostSerializer
users.map { |user| BasicUserWithStatusSerializer.new(user, root: false) }
end
-private
+ private
def can_review_topic?
return @can_review_topic unless @can_review_topic.nil?
diff --git a/app/serializers/post_stream_serializer_mixin.rb b/app/serializers/post_stream_serializer_mixin.rb
index 662e187b82c..e3e8612aab5 100644
--- a/app/serializers/post_stream_serializer_mixin.rb
+++ b/app/serializers/post_stream_serializer_mixin.rb
@@ -42,17 +42,17 @@ module PostStreamSerializerMixin
end
def posts
- @posts ||= begin
- (object.posts || []).map do |post|
- post.topic = object.topic
+ @posts ||=
+ begin
+ (object.posts || []).map do |post|
+ post.topic = object.topic
- serializer = PostSerializer.new(post, scope: scope, root: false)
- serializer.add_raw = true if @options[:include_raw]
- serializer.topic_view = object
+ serializer = PostSerializer.new(post, scope: scope, root: false)
+ serializer.add_raw = true if @options[:include_raw]
+ serializer.topic_view = object
- serializer.as_json
+ serializer.as_json
+ end
end
- end
end
-
end
diff --git a/app/serializers/post_wordpress_serializer.rb b/app/serializers/post_wordpress_serializer.rb
index a415d225833..d8839115d66 100644
--- a/app/serializers/post_wordpress_serializer.rb
+++ b/app/serializers/post_wordpress_serializer.rb
@@ -11,5 +11,4 @@ class PostWordpressSerializer < BasicPostSerializer
nil
end
end
-
end
diff --git a/app/serializers/queued_post_serializer.rb b/app/serializers/queued_post_serializer.rb
index f9dc0dcdefd..91d64f26bfb 100644
--- a/app/serializers/queued_post_serializer.rb
+++ b/app/serializers/queued_post_serializer.rb
@@ -14,13 +14,13 @@ class QueuedPostSerializer < ApplicationSerializer
:post_options,
:created_at,
:category_id,
- :can_delete_user
+ :can_delete_user,
)
has_one :created_by, serializer: AdminUserListSerializer, root: :users
has_one :topic, serializer: BasicTopicSerializer
def queue
- 'default'
+ "default"
end
def user_id
@@ -40,11 +40,11 @@ class QueuedPostSerializer < ApplicationSerializer
end
def raw
- object.payload['raw']
+ object.payload["raw"]
end
def post_options
- object.payload.except('raw')
+ object.payload.except("raw")
end
def can_delete_user
@@ -58,9 +58,6 @@ class QueuedPostSerializer < ApplicationSerializer
private
def post_history
- object.
- reviewable_histories.
- transitioned.
- order(:created_at)
+ object.reviewable_histories.transitioned.order(:created_at)
end
end
diff --git a/app/serializers/reviewable_action_serializer.rb b/app/serializers/reviewable_action_serializer.rb
index fbba925f27d..469164bc26d 100644
--- a/app/serializers/reviewable_action_serializer.rb
+++ b/app/serializers/reviewable_action_serializer.rb
@@ -1,7 +1,15 @@
# frozen_string_literal: true
class ReviewableActionSerializer < ApplicationSerializer
- attributes :id, :icon, :button_class, :label, :confirm_message, :description, :client_action, :require_reject_reason, :custom_modal
+ attributes :id,
+ :icon,
+ :button_class,
+ :label,
+ :confirm_message,
+ :description,
+ :client_action,
+ :require_reject_reason,
+ :custom_modal
def label
I18n.t(object.label)
diff --git a/app/serializers/reviewable_bundled_action_serializer.rb b/app/serializers/reviewable_bundled_action_serializer.rb
index 45875ac2bdb..e55241af05d 100644
--- a/app/serializers/reviewable_bundled_action_serializer.rb
+++ b/app/serializers/reviewable_bundled_action_serializer.rb
@@ -2,7 +2,7 @@
class ReviewableBundledActionSerializer < ApplicationSerializer
attributes :id, :icon, :label
- has_many :actions, serializer: ReviewableActionSerializer, root: 'actions'
+ has_many :actions, serializer: ReviewableActionSerializer, root: "actions"
def label
I18n.t(object.label, default: nil)
diff --git a/app/serializers/reviewable_conversation_post_serializer.rb b/app/serializers/reviewable_conversation_post_serializer.rb
index cccd746b364..e6608db5f8e 100644
--- a/app/serializers/reviewable_conversation_post_serializer.rb
+++ b/app/serializers/reviewable_conversation_post_serializer.rb
@@ -2,5 +2,5 @@
class ReviewableConversationPostSerializer < ApplicationSerializer
attributes :id, :excerpt
- has_one :user, serializer: BasicUserSerializer, root: 'users'
+ has_one :user, serializer: BasicUserSerializer, root: "users"
end
diff --git a/app/serializers/reviewable_explanation_serializer.rb b/app/serializers/reviewable_explanation_serializer.rb
index f268d12794a..d2cc51c6062 100644
--- a/app/serializers/reviewable_explanation_serializer.rb
+++ b/app/serializers/reviewable_explanation_serializer.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
class ReviewableExplanationSerializer < ApplicationSerializer
- attributes(
- :id,
- :total_score,
- :scores,
- :min_score_visibility,
- :hide_post_score
- )
+ attributes(:id, :total_score, :scores, :min_score_visibility, :hide_post_score)
has_many :scores, serializer: ReviewableScoreExplanationSerializer, embed: :objects
diff --git a/app/serializers/reviewable_history_serializer.rb b/app/serializers/reviewable_history_serializer.rb
index d4ae2e78383..30feff77301 100644
--- a/app/serializers/reviewable_history_serializer.rb
+++ b/app/serializers/reviewable_history_serializer.rb
@@ -6,5 +6,5 @@ class ReviewableHistorySerializer < ApplicationSerializer
attribute :reviewable_history_type_for_database, key: :reviewable_history_type
attribute :status_for_database, key: :status
- has_one :created_by, serializer: BasicUserSerializer, root: 'users'
+ has_one :created_by, serializer: BasicUserSerializer, root: "users"
end
diff --git a/app/serializers/reviewable_perform_result_serializer.rb b/app/serializers/reviewable_perform_result_serializer.rb
index b5ff078fe84..84b8974fa6d 100644
--- a/app/serializers/reviewable_perform_result_serializer.rb
+++ b/app/serializers/reviewable_perform_result_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ReviewablePerformResultSerializer < ApplicationSerializer
-
attributes(
:success,
:transition_to,
@@ -11,7 +10,7 @@ class ReviewablePerformResultSerializer < ApplicationSerializer
:remove_reviewable_ids,
:version,
:reviewable_count,
- :unseen_reviewable_count
+ :unseen_reviewable_count,
)
def success
diff --git a/app/serializers/reviewable_queued_post_serializer.rb b/app/serializers/reviewable_queued_post_serializer.rb
index c2ce6fecf22..94a7918a238 100644
--- a/app/serializers/reviewable_queued_post_serializer.rb
+++ b/app/serializers/reviewable_queued_post_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ReviewableQueuedPostSerializer < ReviewableSerializer
-
attributes :reply_to_post_number
payload_attributes(
@@ -18,15 +17,14 @@ class ReviewableQueuedPostSerializer < ReviewableSerializer
:composer_open_duration_msecs,
:tags,
:via_email,
- :raw_email
+ :raw_email,
)
def reply_to_post_number
- object.payload['reply_to_post_number'].to_i
+ object.payload["reply_to_post_number"].to_i
end
def include_reply_to_post_number?
- object.payload.present? && object.payload['reply_to_post_number'].present?
+ object.payload.present? && object.payload["reply_to_post_number"].present?
end
-
end
diff --git a/app/serializers/reviewable_score_explanation_serializer.rb b/app/serializers/reviewable_score_explanation_serializer.rb
index f0082022883..0c100c23929 100644
--- a/app/serializers/reviewable_score_explanation_serializer.rb
+++ b/app/serializers/reviewable_score_explanation_serializer.rb
@@ -10,6 +10,6 @@ class ReviewableScoreExplanationSerializer < ApplicationSerializer
:flags_disagreed,
:flags_ignored,
:user_accuracy_bonus,
- :score
+ :score,
)
end
diff --git a/app/serializers/reviewable_score_serializer.rb b/app/serializers/reviewable_score_serializer.rb
index 5a4d1f05ded..bbf26b62ce8 100644
--- a/app/serializers/reviewable_score_serializer.rb
+++ b/app/serializers/reviewable_score_serializer.rb
@@ -2,33 +2,33 @@
class ReviewableScoreSerializer < ApplicationSerializer
REASONS_AND_SETTINGS = {
- post_count: 'approve_post_count',
- trust_level: 'approve_unless_trust_level',
- new_topics_unless_trust_level: 'approve_new_topics_unless_trust_level',
- fast_typer: 'min_first_post_typing_time',
- auto_silence_regex: 'auto_silence_first_post_regex',
- staged: 'approve_unless_staged',
- must_approve_users: 'must_approve_users',
- invite_only: 'invite_only',
- email_spam: 'email_in_spam_header',
- suspect_user: 'approve_suspect_users',
- contains_media: 'review_media_unless_trust_level',
+ post_count: "approve_post_count",
+ trust_level: "approve_unless_trust_level",
+ new_topics_unless_trust_level: "approve_new_topics_unless_trust_level",
+ fast_typer: "min_first_post_typing_time",
+ auto_silence_regex: "auto_silence_first_post_regex",
+ staged: "approve_unless_staged",
+ must_approve_users: "must_approve_users",
+ invite_only: "invite_only",
+ email_spam: "email_in_spam_header",
+ suspect_user: "approve_suspect_users",
+ contains_media: "review_media_unless_trust_level",
}
attributes :id, :score, :agree_stats, :reason, :created_at, :reviewed_at
attribute :status_for_database, key: :status
- has_one :user, serializer: BasicUserSerializer, root: 'users'
+ has_one :user, serializer: BasicUserSerializer, root: "users"
has_one :score_type, serializer: ReviewableScoreTypeSerializer
has_one :reviewable_conversation, serializer: ReviewableConversationSerializer
- has_one :reviewed_by, serializer: BasicUserSerializer, root: 'users'
+ has_one :reviewed_by, serializer: BasicUserSerializer, root: "users"
def agree_stats
{
agreed: user.user_stat.flags_agreed,
disagreed: user.user_stat.flags_disagreed,
- ignored: user.user_stat.flags_ignored
+ ignored: user.user_stat.flags_ignored,
}
end
@@ -69,9 +69,9 @@ class ReviewableScoreSerializer < ApplicationSerializer
def url_for(reason, text)
case reason
- when 'watched_word'
+ when "watched_word"
"#{Discourse.base_url}/admin/customize/watched_words"
- when 'category'
+ when "category"
"#{Discourse.base_url}/c/#{object.reviewable.category&.slug}/edit/settings"
else
"#{Discourse.base_url}/admin/site_settings/category/all_results?filter=#{text}"
@@ -79,8 +79,8 @@ class ReviewableScoreSerializer < ApplicationSerializer
end
def build_link_for(reason, text)
- return text.gsub('_', ' ') unless scope.is_staff?
+ return text.gsub("_", " ") unless scope.is_staff?
- "#{text.gsub('_', ' ')}"
+ "#{text.gsub("_", " ")}"
end
end
diff --git a/app/serializers/reviewable_score_type_serializer.rb b/app/serializers/reviewable_score_type_serializer.rb
index 60368ebcbce..e31e5fafd9a 100644
--- a/app/serializers/reviewable_score_type_serializer.rb
+++ b/app/serializers/reviewable_score_type_serializer.rb
@@ -20,5 +20,4 @@ class ReviewableScoreTypeSerializer < ApplicationSerializer
def icon
"flag"
end
-
end
diff --git a/app/serializers/reviewable_serializer.rb b/app/serializers/reviewable_serializer.rb
index 2260a4f9db1..20c02e4b72e 100644
--- a/app/serializers/reviewable_serializer.rb
+++ b/app/serializers/reviewable_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ReviewableSerializer < ApplicationSerializer
-
class_attribute :_payload_for_serialization
attributes(
@@ -16,18 +15,18 @@ class ReviewableSerializer < ApplicationSerializer
:can_edit,
:score,
:version,
- :target_created_by_trust_level
+ :target_created_by_trust_level,
)
attribute :status_for_database, key: :status
- has_one :created_by, serializer: UserWithCustomFieldsSerializer, root: 'users'
- has_one :target_created_by, serializer: UserWithCustomFieldsSerializer, root: 'users'
+ has_one :created_by, serializer: UserWithCustomFieldsSerializer, root: "users"
+ has_one :target_created_by, serializer: UserWithCustomFieldsSerializer, root: "users"
has_one :topic, serializer: ListableTopicSerializer
has_many :editable_fields, serializer: ReviewableEditableFieldSerializer, embed: :objects
has_many :reviewable_scores, serializer: ReviewableScoreSerializer
has_many :bundled_actions, serializer: ReviewableBundledActionSerializer
- has_one :claimed_by, serializer: UserWithCustomFieldsSerializer, root: 'users'
+ has_one :claimed_by, serializer: UserWithCustomFieldsSerializer, root: "users"
# Used to keep track of our payload attributes
class_attribute :_payload_for_serialization
@@ -73,9 +72,7 @@ class ReviewableSerializer < ApplicationSerializer
# This is easier than creating an AMS method for each attribute
def self.target_attributes(*attributes)
- attributes.each do |a|
- create_attribute(a, "object.target&.#{a}")
- end
+ attributes.each { |a| create_attribute(a, "object.target&.#{a}") }
end
def self.payload_attributes(*attributes)
@@ -108,7 +105,9 @@ class ReviewableSerializer < ApplicationSerializer
end
def target_url
- return Discourse.base_url + object.target.url if object.target.is_a?(Post) && object.target.present?
+ if object.target.is_a?(Post) && object.target.present?
+ return Discourse.base_url + object.target.url
+ end
topic_url
end
@@ -135,5 +134,4 @@ class ReviewableSerializer < ApplicationSerializer
def target_created_by_trust_level
object&.target_created_by&.trust_level
end
-
end
diff --git a/app/serializers/reviewable_settings_serializer.rb b/app/serializers/reviewable_settings_serializer.rb
index f2a34e4e962..5b21101000a 100644
--- a/app/serializers/reviewable_settings_serializer.rb
+++ b/app/serializers/reviewable_settings_serializer.rb
@@ -14,8 +14,6 @@ class ReviewableSettingsSerializer < ApplicationSerializer
end
def reviewable_priorities
- Reviewable.priorities.map do |p|
- { id: p[1], name: I18n.t("reviewables.priorities.#{p[0]}") }
- end
+ Reviewable.priorities.map { |p| { id: p[1], name: I18n.t("reviewables.priorities.#{p[0]}") } }
end
end
diff --git a/app/serializers/reviewable_topic_serializer.rb b/app/serializers/reviewable_topic_serializer.rb
index 70e0d7fa036..59bf143f869 100644
--- a/app/serializers/reviewable_topic_serializer.rb
+++ b/app/serializers/reviewable_topic_serializer.rb
@@ -12,10 +12,10 @@ class ReviewableTopicSerializer < ApplicationSerializer
:archetype,
:relative_url,
:stats,
- :reviewable_score
+ :reviewable_score,
)
- has_one :claimed_by, serializer: BasicUserSerializer, root: 'users'
+ has_one :claimed_by, serializer: BasicUserSerializer, root: "users"
def stats
@options[:stats][object.id]
@@ -28,5 +28,4 @@ class ReviewableTopicSerializer < ApplicationSerializer
def include_claimed_by?
@options[:claimed_topics]
end
-
end
diff --git a/app/serializers/reviewable_user_serializer.rb b/app/serializers/reviewable_user_serializer.rb
index 5841899cfd3..c5173382012 100644
--- a/app/serializers/reviewable_user_serializer.rb
+++ b/app/serializers/reviewable_user_serializer.rb
@@ -1,16 +1,9 @@
# frozen_string_literal: true
class ReviewableUserSerializer < ReviewableSerializer
-
attributes :link_admin, :user_fields, :reject_reason
- payload_attributes(
- :username,
- :email,
- :name,
- :bio,
- :website
- )
+ payload_attributes(:username, :email, :name, :bio, :website)
def link_admin
scope.is_staff? && object.target.present?
@@ -23,5 +16,4 @@ class ReviewableUserSerializer < ReviewableSerializer
def include_user_fields?
object.target.present? && object.target.user_fields.present?
end
-
end
diff --git a/app/serializers/screened_email_serializer.rb b/app/serializers/screened_email_serializer.rb
index bb38bd9093e..799d122a3f1 100644
--- a/app/serializers/screened_email_serializer.rb
+++ b/app/serializers/screened_email_serializer.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
class ScreenedEmailSerializer < ApplicationSerializer
- attributes :email,
- :action,
- :match_count,
- :last_match_at,
- :created_at,
- :ip_address,
- :id
+ attributes :email, :action, :match_count, :last_match_at, :created_at, :ip_address, :id
def action
ScreenedEmail.actions.key(object.action_type).to_s
@@ -16,5 +10,4 @@ class ScreenedEmailSerializer < ApplicationSerializer
def ip_address
object.ip_address.try(:to_s)
end
-
end
diff --git a/app/serializers/screened_ip_address_serializer.rb b/app/serializers/screened_ip_address_serializer.rb
index f833e0b5fd2..75853a2aaab 100644
--- a/app/serializers/screened_ip_address_serializer.rb
+++ b/app/serializers/screened_ip_address_serializer.rb
@@ -1,12 +1,7 @@
# frozen_string_literal: true
class ScreenedIpAddressSerializer < ApplicationSerializer
- attributes :id,
- :ip_address,
- :action_name,
- :match_count,
- :last_match_at,
- :created_at
+ attributes :id, :ip_address, :action_name, :match_count, :last_match_at, :created_at
def action_name
ScreenedIpAddress.actions.key(object.action_type).to_s
@@ -15,5 +10,4 @@ class ScreenedIpAddressSerializer < ApplicationSerializer
def ip_address
object.ip_address_with_mask
end
-
end
diff --git a/app/serializers/screened_url_serializer.rb b/app/serializers/screened_url_serializer.rb
index 7c071349fae..c4f561071ec 100644
--- a/app/serializers/screened_url_serializer.rb
+++ b/app/serializers/screened_url_serializer.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
class ScreenedUrlSerializer < ApplicationSerializer
- attributes :url,
- :domain,
- :action,
- :match_count,
- :last_match_at,
- :created_at,
- :ip_address
+ attributes :url, :domain, :action, :match_count, :last_match_at, :created_at, :ip_address
def action
ScreenedUrl.actions.key(object.action_type).to_s
@@ -16,5 +10,4 @@ class ScreenedUrlSerializer < ApplicationSerializer
def ip_address
object.ip_address.try(:to_s)
end
-
end
diff --git a/app/serializers/search_logs_serializer.rb b/app/serializers/search_logs_serializer.rb
index 81f70e0694c..910aeb66069 100644
--- a/app/serializers/search_logs_serializer.rb
+++ b/app/serializers/search_logs_serializer.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
class SearchLogsSerializer < ApplicationSerializer
- attributes :term,
- :searches,
- :ctr
+ attributes :term, :searches, :ctr
end
diff --git a/app/serializers/similar_admin_user_serializer.rb b/app/serializers/similar_admin_user_serializer.rb
index 3f343ed8416..542d4885c28 100644
--- a/app/serializers/similar_admin_user_serializer.rb
+++ b/app/serializers/similar_admin_user_serializer.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
class SimilarAdminUserSerializer < AdminUserListSerializer
- attributes :can_be_suspended,
- :can_be_silenced
+ attributes :can_be_suspended, :can_be_silenced
def can_be_suspended
scope.can_suspend?(object)
diff --git a/app/serializers/similar_topic_serializer.rb b/app/serializers/similar_topic_serializer.rb
index 68d6ec73744..7c73730f2ba 100644
--- a/app/serializers/similar_topic_serializer.rb
+++ b/app/serializers/similar_topic_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class SimilarTopicSerializer < ApplicationSerializer
-
has_one :topic, serializer: TopicListItemSerializer, embed: :ids
attributes :id, :blurb, :created_at, :url
diff --git a/app/serializers/single_sign_on_record_serializer.rb b/app/serializers/single_sign_on_record_serializer.rb
index 55af0fb7bcb..5bc88037159 100644
--- a/app/serializers/single_sign_on_record_serializer.rb
+++ b/app/serializers/single_sign_on_record_serializer.rb
@@ -1,9 +1,12 @@
# frozen_string_literal: true
class SingleSignOnRecordSerializer < ApplicationSerializer
- attributes :user_id, :external_id,
- :created_at, :updated_at,
- :external_username, :external_name,
+ attributes :user_id,
+ :external_id,
+ :created_at,
+ :updated_at,
+ :external_username,
+ :external_name,
:external_avatar_url,
:external_profile_background_url,
:external_card_background_url
diff --git a/app/serializers/site_category_serializer.rb b/app/serializers/site_category_serializer.rb
index 1d29b7c7af0..869e9b7868a 100644
--- a/app/serializers/site_category_serializer.rb
+++ b/app/serializers/site_category_serializer.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
class SiteCategorySerializer < BasicCategorySerializer
-
- attributes :allowed_tags,
- :allowed_tag_groups,
- :allow_global_tags,
- :read_only_banner
+ attributes :allowed_tags, :allowed_tag_groups, :allow_global_tags, :read_only_banner
has_many :category_required_tag_groups, key: :required_tag_groups, embed: :objects
diff --git a/app/serializers/site_serializer.rb b/app/serializers/site_serializer.rb
index 0ddc329fd8e..4aa21862328 100644
--- a/app/serializers/site_serializer.rb
+++ b/app/serializers/site_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class SiteSerializer < ApplicationSerializer
-
attributes(
:default_archetype,
:notification_types,
@@ -40,7 +39,7 @@ class SiteSerializer < ApplicationSerializer
:displayed_about_plugin_stat_groups,
:show_welcome_topic_banner,
:anonymous_default_sidebar_tags,
- :whispers_allowed_groups_names
+ :whispers_allowed_groups_names,
)
has_many :archetypes, embed: :objects, serializer: ArchetypeSerializer
@@ -49,19 +48,29 @@ class SiteSerializer < ApplicationSerializer
def user_themes
cache_fragment("user_themes") do
- Theme.where('id = :default OR user_selectable',
- default: SiteSetting.default_theme_id)
+ Theme
+ .where("id = :default OR user_selectable", default: SiteSetting.default_theme_id)
.order("lower(name)")
.pluck(:id, :name, :color_scheme_id)
- .map { |id, n, cs| { theme_id: id, name: n, default: id == SiteSetting.default_theme_id, color_scheme_id: cs } }
+ .map do |id, n, cs|
+ {
+ theme_id: id,
+ name: n,
+ default: id == SiteSetting.default_theme_id,
+ color_scheme_id: cs,
+ }
+ end
.as_json
end
end
def user_color_schemes
cache_fragment("user_color_schemes") do
- schemes = ColorScheme.includes(:color_scheme_colors).where('user_selectable').order(:name)
- ActiveModel::ArraySerializer.new(schemes, each_serializer: ColorSchemeSelectableSerializer).as_json
+ schemes = ColorScheme.includes(:color_scheme_colors).where("user_selectable").order(:name)
+ ActiveModel::ArraySerializer.new(
+ schemes,
+ each_serializer: ColorSchemeSelectableSerializer,
+ ).as_json
end
end
@@ -71,7 +80,9 @@ class SiteSerializer < ApplicationSerializer
def groups
cache_anon_fragment("group_names") do
- object.groups.order(:name)
+ object
+ .groups
+ .order(:name)
.select(:id, :name, :flair_icon, :flair_upload_id, :flair_bg_color, :flair_color)
.map do |g|
{
@@ -81,7 +92,8 @@ class SiteSerializer < ApplicationSerializer
flair_bg_color: g.flair_bg_color,
flair_color: g.flair_color,
}
- end.as_json
+ end
+ .as_json
end
end
@@ -244,7 +256,8 @@ class SiteSerializer < ApplicationSerializer
end
def include_anonymous_default_sidebar_tags?
- scope.anonymous? && !SiteSetting.legacy_navigation_menu? && SiteSetting.tagging_enabled && SiteSetting.default_sidebar_tags.present?
+ scope.anonymous? && !SiteSetting.legacy_navigation_menu? && SiteSetting.tagging_enabled &&
+ SiteSetting.default_sidebar_tags.present?
end
def whispers_allowed_groups_names
diff --git a/app/serializers/suggested_topic_serializer.rb b/app/serializers/suggested_topic_serializer.rb
index f2ad535fbbe..5796ede9121 100644
--- a/app/serializers/suggested_topic_serializer.rb
+++ b/app/serializers/suggested_topic_serializer.rb
@@ -10,7 +10,12 @@ class SuggestedTopicSerializer < ListableTopicSerializer
has_one :user, serializer: BasicUserSerializer, embed: :objects
end
- attributes :archetype, :like_count, :views, :category_id, :featured_link, :featured_link_root_domain
+ attributes :archetype,
+ :like_count,
+ :views,
+ :category_id,
+ :featured_link,
+ :featured_link_root_domain
has_many :posters, serializer: SuggestedPosterSerializer, embed: :objects
def posters
diff --git a/app/serializers/suggested_topics_mixin.rb b/app/serializers/suggested_topics_mixin.rb
index cf0de7b4a10..a899d73f7d1 100644
--- a/app/serializers/suggested_topics_mixin.rb
+++ b/app/serializers/suggested_topics_mixin.rb
@@ -26,10 +26,12 @@ module SuggestedTopicsMixin
return if object.topic.topic_allowed_users.exists?(user_id: scope.user.id)
if object.topic_allowed_group_ids.present?
- Group.joins(:group_users)
+ Group
+ .joins(:group_users)
.where(
"group_users.group_id IN (?) AND group_users.user_id = ?",
- object.topic_allowed_group_ids, scope.user.id
+ object.topic_allowed_group_ids,
+ scope.user.id,
)
.pluck_first(:name)
end
diff --git a/app/serializers/tag_group_serializer.rb b/app/serializers/tag_group_serializer.rb
index db61936fceb..6ccdd3e2d66 100644
--- a/app/serializers/tag_group_serializer.rb
+++ b/app/serializers/tag_group_serializer.rb
@@ -12,17 +12,22 @@ class TagGroupSerializer < ApplicationSerializer
end
def permissions
- @permissions ||= begin
- h = {}
+ @permissions ||=
+ begin
+ h = {}
- object.tag_group_permissions.joins(:group).includes(:group).find_each do |tgp|
- name = Group::AUTO_GROUP_IDS.fetch(tgp.group_id, tgp.group.name).to_s
- h[name] = tgp.permission_type
+ object
+ .tag_group_permissions
+ .joins(:group)
+ .includes(:group)
+ .find_each do |tgp|
+ name = Group::AUTO_GROUP_IDS.fetch(tgp.group_id, tgp.group.name).to_s
+ h[name] = tgp.permission_type
+ end
+
+ h["everyone"] = TagGroupPermission.permission_types[:full] if h.empty?
+
+ h
end
-
- h["everyone"] = TagGroupPermission.permission_types[:full] if h.empty?
-
- h
- end
end
end
diff --git a/app/serializers/theme_serializer.rb b/app/serializers/theme_serializer.rb
index b0edeaa7c4d..d3307a6825d 100644
--- a/app/serializers/theme_serializer.rb
+++ b/app/serializers/theme_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'base64'
+require "base64"
class ThemeFieldSerializer < ApplicationSerializer
attributes :name, :target, :value, :error, :type_id, :upload_id, :url, :filename
@@ -47,9 +47,23 @@ class BasicThemeSerializer < ApplicationSerializer
end
class RemoteThemeSerializer < ApplicationSerializer
- attributes :id, :remote_url, :remote_version, :local_version, :commits_behind, :branch,
- :remote_updated_at, :updated_at, :github_diff_link, :last_error_text, :is_git?,
- :license_url, :about_url, :authors, :theme_version, :minimum_discourse_version, :maximum_discourse_version
+ attributes :id,
+ :remote_url,
+ :remote_version,
+ :local_version,
+ :commits_behind,
+ :branch,
+ :remote_updated_at,
+ :updated_at,
+ :github_diff_link,
+ :last_error_text,
+ :is_git?,
+ :license_url,
+ :about_url,
+ :authors,
+ :theme_version,
+ :minimum_discourse_version,
+ :maximum_discourse_version
# wow, AMS has some pretty nutty logic where it tries to find the path here
# from action dispatch, tell it not to
@@ -63,9 +77,17 @@ class RemoteThemeSerializer < ApplicationSerializer
end
class ThemeSerializer < BasicThemeSerializer
- attributes :color_scheme, :color_scheme_id, :user_selectable, :auto_update,
- :remote_theme_id, :settings, :errors, :supported?, :description,
- :enabled?, :disabled_at
+ attributes :color_scheme,
+ :color_scheme_id,
+ :user_selectable,
+ :auto_update,
+ :remote_theme_id,
+ :settings,
+ :errors,
+ :supported?,
+ :description,
+ :enabled?,
+ :disabled_at
has_one :user, serializer: UserNameSerializer, embed: :object
has_one :disabled_by, serializer: UserNameSerializer, embed: :object
@@ -80,9 +102,7 @@ class ThemeSerializer < BasicThemeSerializer
super
@errors = []
- object.theme_fields.each do |o|
- @errors << o.error if o.error
- end
+ object.theme_fields.each { |o| @errors << o.error if o.error }
end
def child_themes
@@ -113,7 +133,7 @@ class ThemeSerializer < BasicThemeSerializer
end
def description
- object.internal_translations.find { |t| t.key == "theme_metadata.description" } &.value
+ object.internal_translations.find { |t| t.key == "theme_metadata.description" }&.value
end
def include_disabled_at?
diff --git a/app/serializers/theme_settings_serializer.rb b/app/serializers/theme_settings_serializer.rb
index 987003d06a1..cbd01da5a87 100644
--- a/app/serializers/theme_settings_serializer.rb
+++ b/app/serializers/theme_settings_serializer.rb
@@ -1,8 +1,15 @@
# frozen_string_literal: true
class ThemeSettingsSerializer < ApplicationSerializer
- attributes :setting, :type, :default, :value, :description, :valid_values,
- :list_type, :textarea, :json_schema
+ attributes :setting,
+ :type,
+ :default,
+ :value,
+ :description,
+ :valid_values,
+ :list_type,
+ :textarea,
+ :json_schema
def setting
object.name
@@ -21,7 +28,12 @@ class ThemeSettingsSerializer < ApplicationSerializer
end
def description
- locale_file_description = object.theme.internal_translations.find { |t| t.key == "theme_metadata.settings.#{setting}" } &.value
+ locale_file_description =
+ object
+ .theme
+ .internal_translations
+ .find { |t| t.key == "theme_metadata.settings.#{setting}" }
+ &.value
locale_file_description || object.description
end
diff --git a/app/serializers/topic_embed_serializer.rb b/app/serializers/topic_embed_serializer.rb
index d31ab6e89a9..928d3ec5d04 100644
--- a/app/serializers/topic_embed_serializer.rb
+++ b/app/serializers/topic_embed_serializer.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
class TopicEmbedSerializer < ApplicationSerializer
- attributes \
- :topic_id,
- :post_id,
- :topic_slug,
- :comment_count
+ attributes :topic_id, :post_id, :topic_slug, :comment_count
def topic_slug
object.topic.slug
diff --git a/app/serializers/topic_flag_type_serializer.rb b/app/serializers/topic_flag_type_serializer.rb
index 6532f4918db..ccee54a0aaf 100644
--- a/app/serializers/topic_flag_type_serializer.rb
+++ b/app/serializers/topic_flag_type_serializer.rb
@@ -1,12 +1,10 @@
# frozen_string_literal: true
class TopicFlagTypeSerializer < PostActionTypeSerializer
-
protected
def i18n(field, vars = nil)
key = "topic_flag_types.#{name_key}.#{field}"
vars ? I18n.t(key, vars) : I18n.t(key)
end
-
end
diff --git a/app/serializers/topic_link_serializer.rb b/app/serializers/topic_link_serializer.rb
index d3d3fb686c4..d4b814d2c98 100644
--- a/app/serializers/topic_link_serializer.rb
+++ b/app/serializers/topic_link_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class TopicLinkSerializer < ApplicationSerializer
-
attributes :url,
:title,
# :fancy_title,
@@ -12,10 +11,9 @@ class TopicLinkSerializer < ApplicationSerializer
:user_id,
:domain,
:root_domain,
-
- def attachment
- Discourse.store.has_been_uploaded?(object.url)
- end
+ def attachment
+ Discourse.store.has_been_uploaded?(object.url)
+ end
def include_user_id?
object.user_id.present?
@@ -24,5 +22,4 @@ class TopicLinkSerializer < ApplicationSerializer
def root_domain
MiniSuffix.domain(domain)
end
-
end
diff --git a/app/serializers/topic_list_item_serializer.rb b/app/serializers/topic_list_item_serializer.rb
index 4a8f12b37c8..3d43c0848a8 100644
--- a/app/serializers/topic_list_item_serializer.rb
+++ b/app/serializers/topic_list_item_serializer.rb
@@ -32,7 +32,6 @@ class TopicListItemSerializer < ListableTopicSerializer
end
def category_id
-
# If it's a shared draft, show the destination topic instead
if object.includes_destination_category && object.shared_draft
return object.shared_draft.category_id
@@ -50,8 +49,7 @@ class TopicListItemSerializer < ListableTopicSerializer
end
def include_post_action?(action)
- object.user_data &&
- object.user_data.post_action_data &&
+ object.user_data && object.user_data.post_action_data &&
object.user_data.post_action_data.key?(PostActionType.types[action])
end
@@ -86,5 +84,4 @@ class TopicListItemSerializer < ListableTopicSerializer
def include_allowed_user_count?
object.private_message?
end
-
end
diff --git a/app/serializers/topic_list_serializer.rb b/app/serializers/topic_list_serializer.rb
index a3ece4822f2..5e78f344a3e 100644
--- a/app/serializers/topic_list_serializer.rb
+++ b/app/serializers/topic_list_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class TopicListSerializer < ApplicationSerializer
-
attributes :can_create_topic,
:more_topics_url,
:for_period,
diff --git a/app/serializers/topic_pending_post_serializer.rb b/app/serializers/topic_pending_post_serializer.rb
index c07fc479e5e..da02c073583 100644
--- a/app/serializers/topic_pending_post_serializer.rb
+++ b/app/serializers/topic_pending_post_serializer.rb
@@ -4,11 +4,10 @@ class TopicPendingPostSerializer < ApplicationSerializer
attributes :id, :raw, :created_at
def raw
- object.payload['raw']
+ object.payload["raw"]
end
def include_raw?
- object.payload && object.payload['raw'].present?
+ object.payload && object.payload["raw"].present?
end
-
end
diff --git a/app/serializers/topic_post_count_serializer.rb b/app/serializers/topic_post_count_serializer.rb
index 90f5a89fa49..4495019bec5 100644
--- a/app/serializers/topic_post_count_serializer.rb
+++ b/app/serializers/topic_post_count_serializer.rb
@@ -1,14 +1,18 @@
# frozen_string_literal: true
class TopicPostCountSerializer < BasicUserSerializer
-
- attributes :post_count, :primary_group_name,
- :flair_name, :flair_url, :flair_color, :flair_bg_color,
- :admin, :moderator, :trust_level,
-
- def id
- object[:user].id
- end
+ attributes :post_count,
+ :primary_group_name,
+ :flair_name,
+ :flair_url,
+ :flair_color,
+ :flair_bg_color,
+ :admin,
+ :moderator,
+ :trust_level,
+ def id
+ object[:user].id
+ end
def username
object[:user].username
@@ -58,5 +62,4 @@ class TopicPostCountSerializer < BasicUserSerializer
def trust_level
object[:user].trust_level
end
-
end
diff --git a/app/serializers/topic_timer_serializer.rb b/app/serializers/topic_timer_serializer.rb
index b7f3b88788d..9f9934f6342 100644
--- a/app/serializers/topic_timer_serializer.rb
+++ b/app/serializers/topic_timer_serializer.rb
@@ -1,12 +1,7 @@
# frozen_string_literal: true
class TopicTimerSerializer < ApplicationSerializer
- attributes :id,
- :execute_at,
- :duration_minutes,
- :based_on_last_post,
- :status_type,
- :category_id
+ attributes :id, :execute_at, :duration_minutes, :based_on_last_post, :status_type, :category_id
def status_type
TopicTimer.types[object.status_type]
diff --git a/app/serializers/topic_view_details_serializer.rb b/app/serializers/topic_view_details_serializer.rb
index ffe51d4db33..22ae968e3fb 100644
--- a/app/serializers/topic_view_details_serializer.rb
+++ b/app/serializers/topic_view_details_serializer.rb
@@ -1,29 +1,30 @@
# frozen_string_literal: true
class TopicViewDetailsSerializer < ApplicationSerializer
-
def self.can_attributes
- [:can_move_posts,
- :can_delete,
- :can_permanently_delete,
- :can_recover,
- :can_remove_allowed_users,
- :can_invite_to,
- :can_invite_via_email,
- :can_create_post,
- :can_reply_as_new_topic,
- :can_flag_topic,
- :can_convert_topic,
- :can_review_topic,
- :can_edit_tags,
- :can_publish_page,
- :can_close_topic,
- :can_archive_topic,
- :can_split_merge_topic,
- :can_edit_staff_notes,
- :can_toggle_topic_visibility,
- :can_pin_unpin_topic,
- :can_moderate_category]
+ %i[
+ can_move_posts
+ can_delete
+ can_permanently_delete
+ can_recover
+ can_remove_allowed_users
+ can_invite_to
+ can_invite_via_email
+ can_create_post
+ can_reply_as_new_topic
+ can_flag_topic
+ can_convert_topic
+ can_review_topic
+ can_edit_tags
+ can_publish_page
+ can_close_topic
+ can_archive_topic
+ can_split_merge_topic
+ can_edit_staff_notes
+ can_toggle_topic_visibility
+ can_pin_unpin_topic
+ can_moderate_category
+ ]
end
# NOTE: `can_edit` is defined as an attribute because we explicitly want
@@ -35,7 +36,7 @@ class TopicViewDetailsSerializer < ApplicationSerializer
*can_attributes,
:can_remove_self_id,
:participants,
- :allowed_users
+ :allowed_users,
)
has_one :created_by, serializer: BasicUserSerializer, embed: :objects
@@ -46,9 +47,10 @@ class TopicViewDetailsSerializer < ApplicationSerializer
has_many :allowed_groups, serializer: BasicGroupSerializer, embed: :objects
def participants
- object.post_counts_by_user.reject { |p| object.participants[p].blank? }.map do |pc|
- { user: object.participants[pc[0]], post_count: pc[1] }
- end
+ object
+ .post_counts_by_user
+ .reject { |p| object.participants[p].blank? }
+ .map { |pc| { user: object.participants[pc[0]], post_count: pc[1] } }
end
def include_participants?
@@ -88,9 +90,7 @@ class TopicViewDetailsSerializer < ApplicationSerializer
scope.can_remove_allowed_users?(object.topic, scope.user)
end
- can_attributes.each do |ca|
- define_method(ca) { true }
- end
+ can_attributes.each { |ca| define_method(ca) { true } }
# NOTE: A Category Group Moderator moving a topic to a different category
# may result in the 'can_edit?' result changing from `true` to `false`.
@@ -160,13 +160,14 @@ class TopicViewDetailsSerializer < ApplicationSerializer
end
def can_perform_action_available_to_group_moderators?
- @can_perform_action_available_to_group_moderators ||= scope.can_perform_action_available_to_group_moderators?(object.topic)
+ @can_perform_action_available_to_group_moderators ||=
+ scope.can_perform_action_available_to_group_moderators?(object.topic)
end
- alias :include_can_close_topic? :can_perform_action_available_to_group_moderators?
- alias :include_can_archive_topic? :can_perform_action_available_to_group_moderators?
- alias :include_can_split_merge_topic? :can_perform_action_available_to_group_moderators?
- alias :include_can_edit_staff_notes? :can_perform_action_available_to_group_moderators?
- alias :include_can_moderate_category? :can_perform_action_available_to_group_moderators?
+ alias include_can_close_topic? can_perform_action_available_to_group_moderators?
+ alias include_can_archive_topic? can_perform_action_available_to_group_moderators?
+ alias include_can_split_merge_topic? can_perform_action_available_to_group_moderators?
+ alias include_can_edit_staff_notes? can_perform_action_available_to_group_moderators?
+ alias include_can_moderate_category? can_perform_action_available_to_group_moderators?
def include_can_publish_page?
scope.can_publish_page?(object.topic)
@@ -189,5 +190,4 @@ class TopicViewDetailsSerializer < ApplicationSerializer
def include_allowed_groups?
object.personal_message
end
-
end
diff --git a/app/serializers/topic_view_posts_serializer.rb b/app/serializers/topic_view_posts_serializer.rb
index 8afcac3e9ff..8dbb4d2b059 100644
--- a/app/serializers/topic_view_posts_serializer.rb
+++ b/app/serializers/topic_view_posts_serializer.rb
@@ -21,5 +21,4 @@ class TopicViewPostsSerializer < ApplicationSerializer
def include_timeline_lookup?
false
end
-
end
diff --git a/app/serializers/topic_view_serializer.rb b/app/serializers/topic_view_serializer.rb
index 57bd35aaf48..91eb2a6f2f1 100644
--- a/app/serializers/topic_view_serializer.rb
+++ b/app/serializers/topic_view_serializer.rb
@@ -42,7 +42,7 @@ class TopicViewSerializer < ApplicationSerializer
:pinned_until,
:image_url,
:slow_mode_seconds,
- :external_id
+ :external_id,
)
attributes(
@@ -77,7 +77,7 @@ class TopicViewSerializer < ApplicationSerializer
:thumbnails,
:user_last_posted_at,
:is_shared_draft,
- :slow_mode_enabled_until
+ :slow_mode_enabled_until,
)
has_one :details, serializer: TopicViewDetailsSerializer, root: false, embed: :objects
@@ -247,7 +247,8 @@ class TopicViewSerializer < ApplicationSerializer
end
def include_destination_category_id?
- scope.can_see_shared_draft? && SiteSetting.shared_drafts_enabled? && object.topic.shared_draft.present?
+ scope.can_see_shared_draft? && SiteSetting.shared_drafts_enabled? &&
+ object.topic.shared_draft.present?
end
def is_shared_draft
@@ -276,20 +277,21 @@ class TopicViewSerializer < ApplicationSerializer
Group
.joins(:group_users)
.where(
- id: object.topic.custom_fields['requested_group_id'].to_i,
- group_users: { user_id: scope.user.id, owner: true }
+ id: object.topic.custom_fields["requested_group_id"].to_i,
+ group_users: {
+ user_id: scope.user.id,
+ owner: true,
+ },
)
.pluck_first(:name)
end
def include_requested_group_name?
- object.personal_message && object.topic.custom_fields['requested_group_id']
+ object.personal_message && object.topic.custom_fields["requested_group_id"]
end
def include_published_page?
- SiteSetting.enable_page_publishing? &&
- scope.is_staff? &&
- object.published_page.present? &&
+ SiteSetting.enable_page_publishing? && scope.is_staff? && object.published_page.present? &&
!SiteSetting.secure_uploads
end
diff --git a/app/serializers/topic_view_wordpress_serializer.rb b/app/serializers/topic_view_wordpress_serializer.rb
index b4e76103190..ce94b630b41 100644
--- a/app/serializers/topic_view_wordpress_serializer.rb
+++ b/app/serializers/topic_view_wordpress_serializer.rb
@@ -1,13 +1,8 @@
# frozen_string_literal: true
class TopicViewWordpressSerializer < ApplicationSerializer
-
# These attributes will be delegated to the topic
- attributes :id,
- :category_id,
- :posts_count,
- :filtered_posts_count,
- :posts
+ attributes :id, :category_id, :posts_count, :filtered_posts_count, :posts
has_many :participants, serializer: UserWordpressSerializer, embed: :objects
has_many :posts, serializer: PostWordpressSerializer, embed: :objects
@@ -35,5 +30,4 @@ class TopicViewWordpressSerializer < ApplicationSerializer
def posts
object.posts
end
-
end
diff --git a/app/serializers/trust_level3_requirements_serializer.rb b/app/serializers/trust_level3_requirements_serializer.rb
index 2cf83317595..690e9682391 100644
--- a/app/serializers/trust_level3_requirements_serializer.rb
+++ b/app/serializers/trust_level3_requirements_serializer.rb
@@ -1,25 +1,37 @@
# frozen_string_literal: true
class TrustLevel3RequirementsSerializer < ApplicationSerializer
-
has_one :penalty_counts, embed: :object, serializer: PenaltyCountsSerializer
attributes :time_period,
:requirements_met,
:requirements_lost,
- :trust_level_locked, :on_grace_period,
- :days_visited, :min_days_visited,
- :num_topics_replied_to, :min_topics_replied_to,
- :topics_viewed, :min_topics_viewed,
- :posts_read, :min_posts_read,
- :topics_viewed_all_time, :min_topics_viewed_all_time,
- :posts_read_all_time, :min_posts_read_all_time,
- :num_flagged_posts, :max_flagged_posts,
- :num_flagged_by_users, :max_flagged_by_users,
- :num_likes_given, :min_likes_given,
- :num_likes_received, :min_likes_received,
- :num_likes_received_days, :min_likes_received_days,
- :num_likes_received_users, :min_likes_received_users
+ :trust_level_locked,
+ :on_grace_period,
+ :days_visited,
+ :min_days_visited,
+ :num_topics_replied_to,
+ :min_topics_replied_to,
+ :topics_viewed,
+ :min_topics_viewed,
+ :posts_read,
+ :min_posts_read,
+ :topics_viewed_all_time,
+ :min_topics_viewed_all_time,
+ :posts_read_all_time,
+ :min_posts_read_all_time,
+ :num_flagged_posts,
+ :max_flagged_posts,
+ :num_flagged_by_users,
+ :max_flagged_by_users,
+ :num_likes_given,
+ :min_likes_given,
+ :num_likes_received,
+ :min_likes_received,
+ :num_likes_received_days,
+ :min_likes_received_days,
+ :num_likes_received_users,
+ :min_likes_received_users
def requirements_met
object.requirements_met?
diff --git a/app/serializers/upload_serializer.rb b/app/serializers/upload_serializer.rb
index 7626c0e1e23..eb32b011813 100644
--- a/app/serializers/upload_serializer.rb
+++ b/app/serializers/upload_serializer.rb
@@ -17,6 +17,10 @@ class UploadSerializer < ApplicationSerializer
:dominant_color
def url
- object.for_site_setting ? object.url : UrlHelper.cook_url(object.url, secure: SiteSetting.secure_uploads? && object.secure)
+ if object.for_site_setting
+ object.url
+ else
+ UrlHelper.cook_url(object.url, secure: SiteSetting.secure_uploads? && object.secure)
+ end
end
end
diff --git a/app/serializers/user_action_serializer.rb b/app/serializers/user_action_serializer.rb
index 29ed526dc06..0958de3d9dd 100644
--- a/app/serializers/user_action_serializer.rb
+++ b/app/serializers/user_action_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require_relative 'post_item_excerpt'
+require_relative "post_item_excerpt"
class UserActionSerializer < ApplicationSerializer
include PostItemExcerpt
@@ -98,5 +98,4 @@ class UserActionSerializer < ApplicationSerializer
def action_code_path
object.action_code_path
end
-
end
diff --git a/app/serializers/user_badge_serializer.rb b/app/serializers/user_badge_serializer.rb
index 4b2b536ef5a..752ae5c8341 100644
--- a/app/serializers/user_badge_serializer.rb
+++ b/app/serializers/user_badge_serializer.rb
@@ -6,9 +6,7 @@ class UserBadgeSerializer < ApplicationSerializer
class UserSerializer < BasicUserSerializer
include UserPrimaryGroupMixin
- attributes :name,
- :moderator,
- :admin
+ attributes :name, :moderator, :admin
end
attributes :id, :granted_at, :created_at, :count, :post_id, :post_number
@@ -26,7 +24,7 @@ class UserBadgeSerializer < ApplicationSerializer
include_post_attributes?
end
- alias :include_post_number? :include_post_id?
+ alias include_post_number? include_post_id?
def post_number
object.post && object.post.post_number
diff --git a/app/serializers/user_bookmark_list_serializer.rb b/app/serializers/user_bookmark_list_serializer.rb
index cefdd95114c..b70349a1e83 100644
--- a/app/serializers/user_bookmark_list_serializer.rb
+++ b/app/serializers/user_bookmark_list_serializer.rb
@@ -9,7 +9,7 @@ class UserBookmarkListSerializer < ApplicationSerializer
bm,
**object.bookmark_serializer_opts,
scope: scope,
- root: false
+ root: false,
)
end
end
diff --git a/app/serializers/user_card_serializer.rb b/app/serializers/user_card_serializer.rb
index 5e208169c7a..d2c32facdc9 100644
--- a/app/serializers/user_card_serializer.rb
+++ b/app/serializers/user_card_serializer.rb
@@ -73,11 +73,7 @@ class UserCardSerializer < BasicUserSerializer
:pending_posts_count,
:status
- untrusted_attributes :bio_excerpt,
- :website,
- :website_name,
- :location,
- :card_background_upload_url
+ untrusted_attributes :bio_excerpt, :website, :website_name, :location, :card_background_upload_url
staff_attributes :staged
@@ -91,8 +87,7 @@ class UserCardSerializer < BasicUserSerializer
end
def include_email?
- (object.id && object.id == scope.user.try(:id)) ||
- (scope.is_staff? && object.staged?)
+ (object.id && object.id == scope.user.try(:id)) || (scope.is_staff? && object.staged?)
end
alias_method :include_secondary_emails?, :include_email?
@@ -111,13 +106,14 @@ class UserCardSerializer < BasicUserSerializer
end
def website_name
- uri = begin
- URI(website.to_s)
- rescue URI::Error
- end
+ uri =
+ begin
+ URI(website.to_s)
+ rescue URI::Error
+ end
return if uri.nil? || uri.host.nil?
- uri.host.sub(/^www\./, '') + uri.path
+ uri.host.sub(/^www\./, "") + uri.path
end
def ignored
diff --git a/app/serializers/user_history_serializer.rb b/app/serializers/user_history_serializer.rb
index be3f26c97de..d188eccb99d 100644
--- a/app/serializers/user_history_serializer.rb
+++ b/app/serializers/user_history_serializer.rb
@@ -22,7 +22,7 @@ class UserHistorySerializer < ApplicationSerializer
def action_name
key = UserHistory.actions.key(object.action)
- [:custom, :custom_staff].include?(key) ? object.custom_type : key.to_s
+ %i[custom custom_staff].include?(key) ? object.custom_type : key.to_s
end
def new_value
diff --git a/app/serializers/user_option_serializer.rb b/app/serializers/user_option_serializer.rb
index 8cc65d1779f..bd16f075364 100644
--- a/app/serializers/user_option_serializer.rb
+++ b/app/serializers/user_option_serializer.rb
@@ -37,13 +37,14 @@ class UserOptionSerializer < ApplicationSerializer
:default_calendar,
:oldest_search_log_date,
:seen_popups,
-
- def auto_track_topics_after_msecs
- object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
- end
+ def auto_track_topics_after_msecs
+ object.auto_track_topics_after_msecs ||
+ SiteSetting.default_other_auto_track_topics_after_msecs
+ end
def notification_level_when_replying
- object.notification_level_when_replying || SiteSetting.default_other_notification_level_when_replying
+ object.notification_level_when_replying ||
+ SiteSetting.default_other_notification_level_when_replying
end
def new_topic_duration_minutes
diff --git a/app/serializers/user_post_topic_bookmark_base_serializer.rb b/app/serializers/user_post_topic_bookmark_base_serializer.rb
index ca5d50e684d..02798d061ad 100644
--- a/app/serializers/user_post_topic_bookmark_base_serializer.rb
+++ b/app/serializers/user_post_topic_bookmark_base_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require_relative 'post_item_excerpt'
+require_relative "post_item_excerpt"
class UserPostTopicBookmarkBaseSerializer < UserBookmarkBaseSerializer
include TopicTagsMixin
diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb
index 505d7364544..eeda5132f68 100644
--- a/app/serializers/user_serializer.rb
+++ b/app/serializers/user_serializer.rb
@@ -31,9 +31,7 @@ class UserSerializer < UserCardSerializer
can_edit
end
- staff_attributes :post_count,
- :can_be_deleted,
- :can_delete_all_posts
+ staff_attributes :post_count, :can_be_deleted, :can_delete_all_posts
private_attributes :locale,
:muted_category_ids,
@@ -72,14 +70,13 @@ class UserSerializer < UserCardSerializer
untrusted_attributes :bio_raw,
:bio_cooked,
:profile_background_upload_url,
-
- ###
- ### ATTRIBUTES
- ###
- #
- def user_notification_schedule
- object.user_notification_schedule || UserNotificationSchedule::DEFAULT
- end
+ ###
+ ### ATTRIBUTES
+ ###
+ #
+ def user_notification_schedule
+ object.user_notification_schedule || UserNotificationSchedule::DEFAULT
+ end
def mailing_list_posts_per_day
val = Post.estimate_posts_per_day
@@ -87,8 +84,7 @@ class UserSerializer < UserCardSerializer
end
def groups
- object.groups.order(:id)
- .visible_groups(scope.user).members_visible_groups(scope.user)
+ object.groups.order(:id).visible_groups(scope.user).members_visible_groups(scope.user)
end
def group_users
@@ -144,15 +140,19 @@ class UserSerializer < UserCardSerializer
end
def user_api_keys
- keys = object.user_api_keys.where(revoked_at: nil).map do |k|
- {
- id: k.id,
- application_name: k.application_name,
- scopes: k.scopes.map { |s| I18n.t("user_api_key.scopes.#{s.name}") },
- created_at: k.created_at,
- last_used_at: k.last_used_at,
- }
- end
+ keys =
+ object
+ .user_api_keys
+ .where(revoked_at: nil)
+ .map do |k|
+ {
+ id: k.id,
+ application_name: k.application_name,
+ scopes: k.scopes.map { |s| I18n.t("user_api_key.scopes.#{s.name}") },
+ created_at: k.created_at,
+ last_used_at: k.last_used_at,
+ }
+ end
keys.sort! { |a, b| a[:last_used_at].to_time <=> b[:last_used_at].to_time }
keys.length > 0 ? keys : nil
@@ -162,7 +162,7 @@ class UserSerializer < UserCardSerializer
ActiveModel::ArraySerializer.new(
object.user_auth_tokens,
each_serializer: UserAuthTokenSerializer,
- scope: scope
+ scope: scope,
)
end
@@ -306,7 +306,8 @@ class UserSerializer < UserCardSerializer
end
def use_logo_small_as_avatar
- object.is_system_user? && SiteSetting.logo_small && SiteSetting.use_site_small_logo_as_system_avatar
+ object.is_system_user? && SiteSetting.logo_small &&
+ SiteSetting.use_site_small_logo_as_system_avatar
end
private
@@ -314,11 +315,8 @@ class UserSerializer < UserCardSerializer
def custom_field_keys
fields = super
- if scope.can_edit?(object)
- fields += DiscoursePluginRegistry.serialized_current_user_fields.to_a
- end
+ fields += DiscoursePluginRegistry.serialized_current_user_fields.to_a if scope.can_edit?(object)
fields
end
-
end
diff --git a/app/serializers/user_summary_serializer.rb b/app/serializers/user_summary_serializer.rb
index f6e87bb0559..03faf5b90f5 100644
--- a/app/serializers/user_summary_serializer.rb
+++ b/app/serializers/user_summary_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class UserSummarySerializer < ApplicationSerializer
-
class TopicSerializer < BasicTopicSerializer
attributes :category_id, :like_count, :created_at
end
@@ -65,9 +64,15 @@ class UserSummarySerializer < ApplicationSerializer
end
class CategoryWithCountsSerializer < ApplicationSerializer
- attributes :topic_count, :post_count,
- :id, :name, :color, :text_color, :slug,
- :read_restricted, :parent_category_id
+ attributes :topic_count,
+ :post_count,
+ :id,
+ :name,
+ :color,
+ :text_color,
+ :slug,
+ :read_restricted,
+ :parent_category_id
end
has_many :topics, serializer: TopicSerializer
diff --git a/app/serializers/user_tag_notifications_serializer.rb b/app/serializers/user_tag_notifications_serializer.rb
index d2d0766a3e3..e3967cf4d4e 100644
--- a/app/serializers/user_tag_notifications_serializer.rb
+++ b/app/serializers/user_tag_notifications_serializer.rb
@@ -3,11 +3,7 @@
class UserTagNotificationsSerializer < ApplicationSerializer
include UserTagNotificationsMixin
- attributes :watched_tags,
- :watching_first_post_tags,
- :tracked_tags,
- :muted_tags,
- :regular_tags
+ attributes :watched_tags, :watching_first_post_tags, :tracked_tags, :muted_tags, :regular_tags
def user
object
diff --git a/app/serializers/user_wordpress_serializer.rb b/app/serializers/user_wordpress_serializer.rb
index c43f91076fe..6f8510b1897 100644
--- a/app/serializers/user_wordpress_serializer.rb
+++ b/app/serializers/user_wordpress_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class UserWordpressSerializer < BasicUserSerializer
-
def avatar_template
if Hash === object
UrlHelper.absolute User.avatar_template(user[:username], user[:uploaded_avatar_id])
@@ -9,5 +8,4 @@ class UserWordpressSerializer < BasicUserSerializer
UrlHelper.absolute object.avatar_template
end
end
-
end
diff --git a/app/serializers/watched_word_list_serializer.rb b/app/serializers/watched_word_list_serializer.rb
index ec3cac72a90..4b47ce16f78 100644
--- a/app/serializers/watched_word_list_serializer.rb
+++ b/app/serializers/watched_word_list_serializer.rb
@@ -4,14 +4,15 @@ class WatchedWordListSerializer < ApplicationSerializer
attributes :actions, :words, :compiled_regular_expressions
def actions
- SiteSetting.tagging_enabled ? WatchedWord.actions.keys
- : WatchedWord.actions.keys.filter { |k| k != :tag }
+ if SiteSetting.tagging_enabled
+ WatchedWord.actions.keys
+ else
+ WatchedWord.actions.keys.filter { |k| k != :tag }
+ end
end
def words
- object.map do |word|
- WatchedWordSerializer.new(word, root: false)
- end
+ object.map { |word| WatchedWordSerializer.new(word, root: false) }
end
def compiled_regular_expressions
diff --git a/app/serializers/web_hook_category_serializer.rb b/app/serializers/web_hook_category_serializer.rb
index b7fd7ba79c9..dfbd8aa184c 100644
--- a/app/serializers/web_hook_category_serializer.rb
+++ b/app/serializers/web_hook_category_serializer.rb
@@ -1,15 +1,7 @@
# frozen_string_literal: true
class WebHookCategorySerializer < CategorySerializer
-
- %i{
- can_edit
- notification_level
- available_groups
- }.each do |attr|
- define_method("include_#{attr}?") do
- false
- end
+ %i[can_edit notification_level available_groups].each do |attr|
+ define_method("include_#{attr}?") { false }
end
-
end
diff --git a/app/serializers/web_hook_flag_serializer.rb b/app/serializers/web_hook_flag_serializer.rb
index ae2bf85754f..d37ca1d5a77 100644
--- a/app/serializers/web_hook_flag_serializer.rb
+++ b/app/serializers/web_hook_flag_serializer.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
class WebHookFlagSerializer < ApplicationSerializer
- attributes :id,
- :post,
- :flag_type,
- :created_by,
- :created_at,
- :resolved_at,
- :resolved_by
+ attributes :id, :post, :flag_type, :created_by, :created_at, :resolved_at, :resolved_by
def post
WebHookPostSerializer.new(object.post, scope: scope, root: false).as_json
@@ -41,7 +35,7 @@ class WebHookFlagSerializer < ApplicationSerializer
disposed_by_id.present?
end
-protected
+ protected
def disposed_by_id
object.disagreed_by_id || object.agreed_by_id || object.deferred_by_id
diff --git a/app/serializers/web_hook_group_serializer.rb b/app/serializers/web_hook_group_serializer.rb
index d1947c2d848..e6134475054 100644
--- a/app/serializers/web_hook_group_serializer.rb
+++ b/app/serializers/web_hook_group_serializer.rb
@@ -1,14 +1,5 @@
# frozen_string_literal: true
class WebHookGroupSerializer < BasicGroupSerializer
-
- %i{
- is_group_user
- is_group_owner
- }.each do |attr|
- define_method("include_#{attr}?") do
- false
- end
- end
-
+ %i[is_group_user is_group_owner].each { |attr| define_method("include_#{attr}?") { false } }
end
diff --git a/app/serializers/web_hook_group_user_serializer.rb b/app/serializers/web_hook_group_user_serializer.rb
index 342b5a5412b..23a181a28e8 100644
--- a/app/serializers/web_hook_group_user_serializer.rb
+++ b/app/serializers/web_hook_group_user_serializer.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
class WebHookGroupUserSerializer < BasicGroupUserSerializer
- attributes :id,
- :created_at
+ attributes :id, :created_at
end
diff --git a/app/serializers/web_hook_post_serializer.rb b/app/serializers/web_hook_post_serializer.rb
index beaa6738319..f804e00833e 100644
--- a/app/serializers/web_hook_post_serializer.rb
+++ b/app/serializers/web_hook_post_serializer.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
class WebHookPostSerializer < PostSerializer
-
- attributes :topic_posts_count,
- :topic_filtered_posts_count,
- :topic_archetype,
- :category_slug
+ attributes :topic_posts_count, :topic_filtered_posts_count, :topic_archetype, :category_slug
def include_topic_title?
true
@@ -19,7 +15,7 @@ class WebHookPostSerializer < PostSerializer
true
end
- %i{
+ %i[
can_view
can_edit
can_delete
@@ -33,11 +29,7 @@ class WebHookPostSerializer < PostSerializer
flair_color
notice
mentioned_users
- }.each do |attr|
- define_method("include_#{attr}?") do
- false
- end
- end
+ ].each { |attr| define_method("include_#{attr}?") { false } }
def topic_posts_count
object.topic ? object.topic.posts_count : 0
@@ -48,7 +40,7 @@ class WebHookPostSerializer < PostSerializer
end
def topic_archetype
- object.topic ? object.topic.archetype : ''
+ object.topic ? object.topic.archetype : ""
end
def include_category_slug?
@@ -56,7 +48,7 @@ class WebHookPostSerializer < PostSerializer
end
def category_slug
- object.topic && object.topic.category ? object.topic.category.slug_for_url : ''
+ object.topic && object.topic.category ? object.topic.category.slug_for_url : ""
end
def include_readers_count?
diff --git a/app/serializers/web_hook_topic_view_serializer.rb b/app/serializers/web_hook_topic_view_serializer.rb
index 2098c7a67be..ff11424db15 100644
--- a/app/serializers/web_hook_topic_view_serializer.rb
+++ b/app/serializers/web_hook_topic_view_serializer.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
class WebHookTopicViewSerializer < TopicViewSerializer
- attributes :created_by,
- :last_poster
+ attributes :created_by, :last_poster
- %i{
+ %i[
post_stream
timeline_lookup
pm_with_non_human_user
@@ -23,11 +22,7 @@ class WebHookTopicViewSerializer < TopicViewSerializer
slow_mode_seconds
slow_mode_enabled_until
bookmarks
- }.each do |attr|
- define_method("include_#{attr}?") do
- false
- end
- end
+ ].each { |attr| define_method("include_#{attr}?") { false } }
def include_show_read_indicator?
false
diff --git a/app/serializers/web_hook_user_serializer.rb b/app/serializers/web_hook_user_serializer.rb
index e077b191006..5de175413ef 100644
--- a/app/serializers/web_hook_user_serializer.rb
+++ b/app/serializers/web_hook_user_serializer.rb
@@ -7,7 +7,7 @@ class WebHookUserSerializer < UserSerializer
def staff_attributes(*attrs)
end
- %i{
+ %i[
unconfirmed_emails
can_edit
can_edit_username
@@ -38,11 +38,7 @@ class WebHookUserSerializer < UserSerializer
use_logo_small_as_avatar
pending_posts_count
status
- }.each do |attr|
- define_method("include_#{attr}?") do
- false
- end
- end
+ ].each { |attr| define_method("include_#{attr}?") { false } }
def include_email?
scope.is_admin?
@@ -57,5 +53,4 @@ class WebHookUserSerializer < UserSerializer
def external_id
object.single_sign_on_record.external_id
end
-
end
diff --git a/app/serializers/wizard_field_serializer.rb b/app/serializers/wizard_field_serializer.rb
index 12c3db2060d..b4cb8a3b563 100644
--- a/app/serializers/wizard_field_serializer.rb
+++ b/app/serializers/wizard_field_serializer.rb
@@ -1,7 +1,17 @@
# frozen_string_literal: true
class WizardFieldSerializer < ApplicationSerializer
- attributes :id, :type, :required, :value, :label, :placeholder, :description, :extra_description, :icon, :disabled, :show_in_sidebar
+ attributes :id,
+ :type,
+ :required,
+ :value,
+ :label,
+ :placeholder,
+ :description,
+ :extra_description,
+ :icon,
+ :disabled,
+ :show_in_sidebar
has_many :choices, serializer: WizardFieldChoiceSerializer, embed: :objects
def id
diff --git a/app/serializers/wizard_step_serializer.rb b/app/serializers/wizard_step_serializer.rb
index 802a1a4be97..76ec852124d 100644
--- a/app/serializers/wizard_step_serializer.rb
+++ b/app/serializers/wizard_step_serializer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class WizardStepSerializer < ApplicationSerializer
-
attributes :id, :next, :previous, :description, :title, :index, :banner, :emoji
has_many :fields, serializer: WizardFieldSerializer, embed: :objects
@@ -68,5 +67,4 @@ class WizardStepSerializer < ApplicationSerializer
def emoji
object.emoji
end
-
end
diff --git a/app/services/anonymous_shadow_creator.rb b/app/services/anonymous_shadow_creator.rb
index 77d353b2f97..2a769c7a681 100644
--- a/app/services/anonymous_shadow_creator.rb
+++ b/app/services/anonymous_shadow_creator.rb
@@ -30,9 +30,8 @@ class AnonymousShadowCreator
shadow = user.shadow_user
- if shadow && (shadow.post_count + shadow.topic_count) > 0 &&
- shadow.last_posted_at &&
- shadow.last_posted_at < SiteSetting.anonymous_account_duration_minutes.minutes.ago
+ if shadow && (shadow.post_count + shadow.topic_count) > 0 && shadow.last_posted_at &&
+ shadow.last_posted_at < SiteSetting.anonymous_account_duration_minutes.minutes.ago
shadow = nil
end
@@ -45,23 +44,24 @@ class AnonymousShadowCreator
username = resolve_username
User.transaction do
- shadow = User.create!(
- password: SecureRandom.hex,
- email: "#{SecureRandom.hex}@anon.#{Discourse.current_hostname}",
- skip_email_validation: true,
- name: username, # prevents error when names are required
- username: username,
- active: true,
- trust_level: 1,
- manual_locked_trust_level: 1,
- approved: true,
- approved_at: 1.day.ago,
- created_at: 1.day.ago # bypass new user restrictions
- )
+ shadow =
+ User.create!(
+ password: SecureRandom.hex,
+ email: "#{SecureRandom.hex}@anon.#{Discourse.current_hostname}",
+ skip_email_validation: true,
+ name: username, # prevents error when names are required
+ username: username,
+ active: true,
+ trust_level: 1,
+ manual_locked_trust_level: 1,
+ approved: true,
+ approved_at: 1.day.ago,
+ created_at: 1.day.ago, # bypass new user restrictions
+ )
shadow.user_option.update_columns(
email_messages_level: UserOption.email_level_types[:never],
- email_digests: false
+ email_digests: false,
)
shadow.email_tokens.update_all(confirmed: true)
diff --git a/app/services/badge_granter.rb b/app/services/badge_granter.rb
index da264036c66..f32d1321f33 100644
--- a/app/services/badge_granter.rb
+++ b/app/services/badge_granter.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
class BadgeGranter
- class GrantError < StandardError; end
+ class GrantError < StandardError
+ end
def self.disable_queue
@queue_disabled = true
@@ -21,7 +22,12 @@ class BadgeGranter
BadgeGranter.new(badge, user, opts).grant
end
- def self.enqueue_mass_grant_for_users(badge, emails: [], usernames: [], ensure_users_have_badge_once: true)
+ def self.enqueue_mass_grant_for_users(
+ badge,
+ emails: [],
+ usernames: [],
+ ensure_users_have_badge_once: true
+ )
emails = emails.map(&:downcase)
usernames = usernames.map(&:downcase)
usernames_map_to_ids = {}
@@ -30,7 +36,7 @@ class BadgeGranter
usernames_map_to_ids = User.where(username_lower: usernames).pluck(:username_lower, :id).to_h
end
if emails.size > 0
- emails_map_to_ids = User.with_email(emails).pluck('LOWER(user_emails.email)', :id).to_h
+ emails_map_to_ids = User.with_email(emails).pluck("LOWER(user_emails.email)", :id).to_h
end
count_per_user = {}
@@ -57,18 +63,13 @@ class BadgeGranter
count_per_user.each do |user_id, count|
next if ensure_users_have_badge_once && existing_owners_ids.include?(user_id)
- Jobs.enqueue(
- :mass_award_badge,
- user: user_id,
- badge: badge.id,
- count: count
- )
+ Jobs.enqueue(:mass_award_badge, user: user_id, badge: badge.id, count: count)
end
{
unmatched_entries: unmatched.to_a,
matched_users_count: count_per_user.size,
- unmatched_entries_count: unmatched.size
+ unmatched_entries_count: unmatched.size,
}
end
@@ -78,7 +79,8 @@ class BadgeGranter
raise ArgumentError.new("count can't be less than 1") if count < 1
UserBadge.transaction do
- DB.exec(<<~SQL * count, now: Time.zone.now, system: Discourse.system_user.id, user_id: user.id, badge_id: badge.id)
+ DB.exec(
+ <<~SQL * count,
INSERT INTO user_badges
(granted_at, created_at, granted_by_id, user_id, badge_id, seq)
VALUES
@@ -95,6 +97,11 @@ class BadgeGranter
), 0)
);
SQL
+ now: Time.zone.now,
+ system: Discourse.system_user.id,
+ user_id: user.id,
+ badge_id: badge.id,
+ )
notification = send_notification(user.id, user.username, user.locale, badge)
DB.exec(<<~SQL, notification_id: notification.id, user_id: user.id, badge_id: badge.id)
@@ -114,9 +121,7 @@ class BadgeGranter
find_by = { badge_id: @badge.id, user_id: @user.id }
- if @badge.multiple_grant?
- find_by[:post_id] = @post_id
- end
+ find_by[:post_id] = @post_id if @badge.multiple_grant?
user_badge = UserBadge.find_by(find_by)
@@ -128,12 +133,15 @@ class BadgeGranter
seq = (seq || -1) + 1
end
- user_badge = UserBadge.create!(badge: @badge,
- user: @user,
- granted_by: @granted_by,
- granted_at: @opts[:created_at] || Time.now,
- post_id: @post_id,
- seq: seq)
+ user_badge =
+ UserBadge.create!(
+ badge: @badge,
+ user: @user,
+ granted_by: @granted_by,
+ granted_at: @opts[:created_at] || Time.now,
+ post_id: @post_id,
+ seq: seq,
+ )
return unless SiteSetting.enable_badges
@@ -143,7 +151,8 @@ class BadgeGranter
skip_new_user_tips = @user.user_option.skip_new_user_tips
unless self.class.suppress_notification?(@badge, user_badge.granted_at, skip_new_user_tips)
- notification = self.class.send_notification(@user.id, @user.username, @user.effective_locale, @badge)
+ notification =
+ self.class.send_notification(@user.id, @user.username, @user.effective_locale, @badge)
user_badge.update!(notification_id: notification.id)
end
end
@@ -160,16 +169,18 @@ class BadgeGranter
end
# If the user's title is the same as the badge name OR the custom badge name, remove their title.
- custom_badge_name = TranslationOverride.find_by(translation_key: user_badge.badge.translation_key)&.value
+ custom_badge_name =
+ TranslationOverride.find_by(translation_key: user_badge.badge.translation_key)&.value
user_title_is_badge_name = user_badge.user.title == user_badge.badge.name
- user_title_is_custom_badge_name = custom_badge_name.present? && user_badge.user.title == custom_badge_name
+ user_title_is_custom_badge_name =
+ custom_badge_name.present? && user_badge.user.title == custom_badge_name
if user_title_is_badge_name || user_title_is_custom_badge_name
if options[:revoked_by]
StaffActionLogger.new(options[:revoked_by]).log_title_revoke(
user_badge.user,
- revoke_reason: 'user title was same as revoked badge name or custom badge name',
- previous_value: user_badge.user.title
+ revoke_reason: "user title was same as revoked badge name or custom badge name",
+ previous_value: user_badge.user.title,
)
end
user_badge.user.title = nil
@@ -179,10 +190,15 @@ class BadgeGranter
end
def self.revoke_all(badge)
- custom_badge_names = TranslationOverride.where(translation_key: badge.translation_key).pluck(:value)
+ custom_badge_names =
+ TranslationOverride.where(translation_key: badge.translation_key).pluck(:value)
- users = User.joins(:user_badges).where(user_badges: { badge_id: badge.id }).where(title: badge.name)
- users = users.or(User.joins(:user_badges).where(title: custom_badge_names)) unless custom_badge_names.empty?
+ users =
+ User.joins(:user_badges).where(user_badges: { badge_id: badge.id }).where(title: badge.name)
+ users =
+ users.or(
+ User.joins(:user_badges).where(title: custom_badge_names),
+ ) unless custom_badge_names.empty?
users.update_all(title: nil)
UserBadge.where(badge: badge).delete_all
@@ -195,28 +211,16 @@ class BadgeGranter
case type
when Badge::Trigger::PostRevision
post = opt[:post]
- payload = {
- type: "PostRevision",
- post_ids: [post.id]
- }
+ payload = { type: "PostRevision", post_ids: [post.id] }
when Badge::Trigger::UserChange
user = opt[:user]
- payload = {
- type: "UserChange",
- user_ids: [user.id]
- }
+ payload = { type: "UserChange", user_ids: [user.id] }
when Badge::Trigger::TrustLevelChange
user = opt[:user]
- payload = {
- type: "TrustLevelChange",
- user_ids: [user.id]
- }
+ payload = { type: "TrustLevelChange", user_ids: [user.id] }
when Badge::Trigger::PostAction
action = opt[:post_action]
- payload = {
- type: "PostAction",
- post_ids: [action.post_id, action.related_post_id].compact!
- }
+ payload = { type: "PostAction", post_ids: [action.post_id, action.related_post_id].compact! }
end
Discourse.redis.lpush queue_key, payload.to_json if payload
@@ -242,9 +246,7 @@ class BadgeGranter
next unless post_ids.present? || user_ids.present?
- find_by_type(type).each do |badge|
- backfill(badge, post_ids: post_ids, user_ids: user_ids)
- end
+ find_by_type(type).each { |badge| backfill(badge, post_ids: post_ids, user_ids: user_ids) }
end
end
@@ -263,27 +265,47 @@ class BadgeGranter
return if sql.blank?
if Badge::Trigger.uses_post_ids?(opts[:trigger])
- raise("Contract violation:\nQuery triggers on posts, but does not reference the ':post_ids' array") unless sql.match(/:post_ids/)
- raise "Contract violation:\nQuery triggers on posts, but references the ':user_ids' array" if sql.match(/:user_ids/)
+ unless sql.match(/:post_ids/)
+ raise(
+ "Contract violation:\nQuery triggers on posts, but does not reference the ':post_ids' array",
+ )
+ end
+ if sql.match(/:user_ids/)
+ raise "Contract violation:\nQuery triggers on posts, but references the ':user_ids' array"
+ end
end
if Badge::Trigger.uses_user_ids?(opts[:trigger])
- raise "Contract violation:\nQuery triggers on users, but does not reference the ':user_ids' array" unless sql.match(/:user_ids/)
- raise "Contract violation:\nQuery triggers on users, but references the ':post_ids' array" if sql.match(/:post_ids/)
+ unless sql.match(/:user_ids/)
+ raise "Contract violation:\nQuery triggers on users, but does not reference the ':user_ids' array"
+ end
+ if sql.match(/:post_ids/)
+ raise "Contract violation:\nQuery triggers on users, but references the ':post_ids' array"
+ end
end
if opts[:trigger] && !Badge::Trigger.is_none?(opts[:trigger])
- raise "Contract violation:\nQuery is triggered, but does not reference the ':backfill' parameter.\n(Hint: if :backfill is TRUE, you should ignore the :post_ids/:user_ids)" unless sql.match(/:backfill/)
+ unless sql.match(/:backfill/)
+ raise "Contract violation:\nQuery is triggered, but does not reference the ':backfill' parameter.\n(Hint: if :backfill is TRUE, you should ignore the :post_ids/:user_ids)"
+ end
end
# TODO these three conditions have a lot of false negatives
if opts[:target_posts]
- raise "Contract violation:\nQuery targets posts, but does not return a 'post_id' column" unless sql.match(/post_id/)
+ unless sql.match(/post_id/)
+ raise "Contract violation:\nQuery targets posts, but does not return a 'post_id' column"
+ end
end
- raise "Contract violation:\nQuery does not return a 'user_id' column" unless sql.match(/user_id/)
- raise "Contract violation:\nQuery does not return a 'granted_at' column" unless sql.match(/granted_at/)
- raise "Contract violation:\nQuery ends with a semicolon. Remove the semicolon; your sql will be used in a subquery." if sql.match(/;\s*\z/)
+ unless sql.match(/user_id/)
+ raise "Contract violation:\nQuery does not return a 'user_id' column"
+ end
+ unless sql.match(/granted_at/)
+ raise "Contract violation:\nQuery does not return a 'granted_at' column"
+ end
+ if sql.match(/;\s*\z/)
+ raise "Contract violation:\nQuery ends with a semicolon. Remove the semicolon; your sql will be used in a subquery."
+ end
end
# Options:
@@ -305,8 +327,9 @@ class BadgeGranter
SQL
grant_count = DB.query_single(count_sql, params).first.to_i
- grants_sql = if opts[:target_posts]
- <<~SQL
+ grants_sql =
+ if opts[:target_posts]
+ <<~SQL
SELECT u.id, u.username, q.post_id, t.title, q.granted_at
FROM (
#{sql}
@@ -317,8 +340,8 @@ class BadgeGranter
WHERE :backfill = :backfill
LIMIT 10
SQL
- else
- <<~SQL
+ else
+ <<~SQL
SELECT u.id, u.username, q.granted_at
FROM (
#{sql}
@@ -327,7 +350,7 @@ class BadgeGranter
WHERE :backfill = :backfill
LIMIT 10
SQL
- end
+ end
query_plan = nil
# HACK: active record sanitization too flexible, force it to go down the sanitization path that cares not for % stuff
@@ -337,11 +360,17 @@ class BadgeGranter
sample = DB.query(grants_sql, params)
sample.each do |result|
- raise "Query returned a non-existent user ID:\n#{result.id}" unless User.exists?(id: result.id)
- raise "Query did not return a badge grant time\n(Try using 'current_timestamp granted_at')" unless result.granted_at
+ unless User.exists?(id: result.id)
+ raise "Query returned a non-existent user ID:\n#{result.id}"
+ end
+ unless result.granted_at
+ raise "Query did not return a badge grant time\n(Try using 'current_timestamp granted_at')"
+ end
if opts[:target_posts]
raise "Query did not return a post ID" unless result.post_id
- raise "Query returned a non-existent post ID:\n#{result.post_id}" unless Post.exists?(result.post_id).present?
+ unless Post.exists?(result.post_id).present?
+ raise "Query returned a non-existent post ID:\n#{result.post_id}"
+ end
end
end
@@ -362,7 +391,7 @@ class BadgeGranter
# safeguard fall back to full backfill if more than 200
if (post_ids && post_ids.size > MAX_ITEMS_FOR_DELTA) ||
- (user_ids && user_ids.size > MAX_ITEMS_FOR_DELTA)
+ (user_ids && user_ids.size > MAX_ITEMS_FOR_DELTA)
post_ids = nil
user_ids = nil
end
@@ -388,14 +417,16 @@ class BadgeGranter
)
SQL
- DB.exec(
- sql,
- id: badge.id,
- post_ids: [-1],
- user_ids: [-2],
- backfill: true,
- multiple_grant: true # cheat here, cause we only run on backfill and are deleting
- ) if badge.auto_revoke && full_backfill
+ if badge.auto_revoke && full_backfill
+ DB.exec(
+ sql,
+ id: badge.id,
+ post_ids: [-1],
+ user_ids: [-2],
+ backfill: true,
+ multiple_grant: true, # cheat here, cause we only run on backfill and are deleting
+ )
+ end
sql = <<~SQL
WITH w as (
@@ -434,25 +465,27 @@ class BadgeGranter
return
end
- builder.query(
- id: badge.id,
- multiple_grant: badge.multiple_grant,
- backfill: full_backfill,
- post_ids: post_ids || [-2],
- user_ids: user_ids || [-2]).each do |row|
-
- next if suppress_notification?(badge, row.granted_at, row.skip_new_user_tips)
- next if row.staff && badge.awarded_for_trust_level?
-
- notification = send_notification(row.user_id, row.username, row.locale, badge)
- UserBadge.trigger_user_badge_granted_event(badge.id, row.user_id)
-
- DB.exec(
- "UPDATE user_badges SET notification_id = :notification_id WHERE id = :id",
- notification_id: notification.id,
- id: row.id
+ builder
+ .query(
+ id: badge.id,
+ multiple_grant: badge.multiple_grant,
+ backfill: full_backfill,
+ post_ids: post_ids || [-2],
+ user_ids: user_ids || [-2],
)
- end
+ .each do |row|
+ next if suppress_notification?(badge, row.granted_at, row.skip_new_user_tips)
+ next if row.staff && badge.awarded_for_trust_level?
+
+ notification = send_notification(row.user_id, row.username, row.locale, badge)
+ UserBadge.trigger_user_badge_granted_event(badge.id, row.user_id)
+
+ DB.exec(
+ "UPDATE user_badges SET notification_id = :notification_id WHERE id = :id",
+ notification_id: notification.id,
+ id: row.id,
+ )
+ end
badge.reset_grant_count!
rescue => e
@@ -505,8 +538,8 @@ class BadgeGranter
badge_name: badge.display_name,
badge_slug: badge.slug,
badge_title: badge.allow_title,
- username: username
- }.to_json
+ username: username,
+ }.to_json,
)
end
end
diff --git a/app/services/base_bookmarkable.rb b/app/services/base_bookmarkable.rb
index 6976eece625..77c19c7147f 100644
--- a/app/services/base_bookmarkable.rb
+++ b/app/services/base_bookmarkable.rb
@@ -119,16 +119,17 @@ class BaseBookmarkable
# created.
# @return [void]
def self.send_reminder_notification(bookmark, notification_data)
- if notification_data[:data].blank? ||
- notification_data[:data][:bookmarkable_url].blank? ||
- notification_data[:data][:title].blank?
- raise Discourse::InvalidParameters.new("A `data` key must be present with at least `bookmarkable_url` and `title` entries.")
+ if notification_data[:data].blank? || notification_data[:data][:bookmarkable_url].blank? ||
+ notification_data[:data][:title].blank?
+ raise Discourse::InvalidParameters.new(
+ "A `data` key must be present with at least `bookmarkable_url` and `title` entries.",
+ )
end
notification_data[:data] = notification_data[:data].merge(
display_username: bookmark.user.username,
bookmark_name: bookmark.name,
- bookmark_id: bookmark.id
+ bookmark_id: bookmark.id,
).to_json
notification_data[:notification_type] = Notification.types[:bookmark_reminder]
bookmark.user.notifications.create!(notification_data)
diff --git a/app/services/color_scheme_revisor.rb b/app/services/color_scheme_revisor.rb
index 7515d513d3a..937c6bf7d45 100644
--- a/app/services/color_scheme_revisor.rb
+++ b/app/services/color_scheme_revisor.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ColorSchemeRevisor
-
def initialize(color_scheme, params = {})
@color_scheme = color_scheme
@params = params
@@ -14,7 +13,9 @@ class ColorSchemeRevisor
def revise
ColorScheme.transaction do
@color_scheme.name = @params[:name] if @params.has_key?(:name)
- @color_scheme.user_selectable = @params[:user_selectable] if @params.has_key?(:user_selectable)
+ @color_scheme.user_selectable = @params[:user_selectable] if @params.has_key?(
+ :user_selectable,
+ )
@color_scheme.base_scheme_id = @params[:base_scheme_id] if @params.has_key?(:base_scheme_id)
has_colors = @params[:colors]
@@ -29,15 +30,12 @@ class ColorSchemeRevisor
@color_scheme.clear_colors_cache
end
- if has_colors ||
- @color_scheme.saved_change_to_name? ||
- @color_scheme.will_save_change_to_user_selectable? ||
- @color_scheme.saved_change_to_base_scheme_id?
-
+ if has_colors || @color_scheme.saved_change_to_name? ||
+ @color_scheme.will_save_change_to_user_selectable? ||
+ @color_scheme.saved_change_to_base_scheme_id?
@color_scheme.save
end
end
@color_scheme
end
-
end
diff --git a/app/services/destroy_task.rb b/app/services/destroy_task.rb
index d06a4ad7556..fda78c9583d 100644
--- a/app/services/destroy_task.rb
+++ b/app/services/destroy_task.rb
@@ -18,9 +18,7 @@ class DestroyTask
topics.find_each do |topic|
@io.puts "Deleting #{topic.slug}..."
first_post = topic.ordered_posts.first
- if first_post.nil?
- return @io.puts "Topic.ordered_posts.first was nil"
- end
+ return @io.puts "Topic.ordered_posts.first was nil" if first_post.nil?
@io.puts PostDestroyer.new(Discourse.system_user, first_post).destroy
end
end
@@ -45,17 +43,17 @@ class DestroyTask
def destroy_topics_all_categories
categories = Category.all
- categories.each do |c|
- @io.puts destroy_topics(c.slug, c.parent_category&.slug)
- end
+ categories.each { |c| @io.puts destroy_topics(c.slug, c.parent_category&.slug) }
end
def destroy_private_messages
- Topic.where(archetype: "private_message").find_each do |pm|
- @io.puts "Destroying #{pm.slug} pm"
- first_post = pm.ordered_posts.first
- @io.puts PostDestroyer.new(Discourse.system_user, first_post).destroy
- end
+ Topic
+ .where(archetype: "private_message")
+ .find_each do |pm|
+ @io.puts "Destroying #{pm.slug} pm"
+ first_post = pm.ordered_posts.first
+ @io.puts PostDestroyer.new(Discourse.system_user, first_post).destroy
+ end
end
def destroy_category(category_id, destroy_system_topics = false)
@@ -63,9 +61,7 @@ class DestroyTask
return @io.puts "A category with the id: #{category_id} could not be found" if c.nil?
subcategories = Category.where(parent_category_id: c.id)
@io.puts "There are #{subcategories.count} subcategories to delete" if subcategories
- subcategories.each do |s|
- category_topic_destroyer(s, destroy_system_topics)
- end
+ subcategories.each { |s| category_topic_destroyer(s, destroy_system_topics) }
category_topic_destroyer(c, destroy_system_topics)
end
@@ -78,21 +74,30 @@ class DestroyTask
end
def destroy_users
- User.human_users.where(admin: false).find_each do |user|
- begin
- if UserDestroyer.new(Discourse.system_user).destroy(user, delete_posts: true, context: "destroy task")
- @io.puts "#{user.username} deleted"
- else
- @io.puts "#{user.username} not deleted"
+ User
+ .human_users
+ .where(admin: false)
+ .find_each do |user|
+ begin
+ if UserDestroyer.new(Discourse.system_user).destroy(
+ user,
+ delete_posts: true,
+ context: "destroy task",
+ )
+ @io.puts "#{user.username} deleted"
+ else
+ @io.puts "#{user.username} not deleted"
+ end
+ rescue UserDestroyer::PostsExistError
+ raise Discourse::InvalidAccess.new(
+ "User #{user.username} has #{user.post_count} posts, so can't be deleted.",
+ )
+ rescue NoMethodError
+ @io.puts "#{user.username} could not be deleted"
+ rescue Discourse::InvalidAccess => e
+ @io.puts "#{user.username} #{e.message}"
end
- rescue UserDestroyer::PostsExistError
- raise Discourse::InvalidAccess.new("User #{user.username} has #{user.post_count} posts, so can't be deleted.")
- rescue NoMethodError
- @io.puts "#{user.username} could not be deleted"
- rescue Discourse::InvalidAccess => e
- @io.puts "#{user.username} #{e.message}"
end
- end
end
def destroy_stats
@@ -112,5 +117,4 @@ class DestroyTask
@io.puts "Destroying #{category.slug} category"
category.destroy
end
-
end
diff --git a/app/services/email_settings_exception_handler.rb b/app/services/email_settings_exception_handler.rb
index ddb3fb908b8..b85a9aaa95b 100644
--- a/app/services/email_settings_exception_handler.rb
+++ b/app/services/email_settings_exception_handler.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'net/imap'
-require 'net/smtp'
-require 'net/pop'
+require "net/imap"
+require "net/smtp"
+require "net/pop"
class EmailSettingsExceptionHandler
EXPECTED_EXCEPTIONS = [
@@ -17,7 +17,7 @@ class EmailSettingsExceptionHandler
Net::OpenTimeout,
Net::ReadTimeout,
SocketError,
- Errno::ECONNREFUSED
+ Errno::ECONNREFUSED,
]
class GenericProvider
@@ -63,7 +63,10 @@ class EmailSettingsExceptionHandler
if @exception.message.match(/Invalid credentials/)
I18n.t("email_settings.imap_authentication_error")
else
- I18n.t("email_settings.imap_no_response_error", message: @exception.message.gsub(" (Failure)", ""))
+ I18n.t(
+ "email_settings.imap_no_response_error",
+ message: @exception.message.gsub(" (Failure)", ""),
+ )
end
end
diff --git a/app/services/email_settings_validator.rb b/app/services/email_settings_validator.rb
index 238b5869627..bd6dbccfe60 100644
--- a/app/services/email_settings_validator.rb
+++ b/app/services/email_settings_validator.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'net/imap'
-require 'net/smtp'
-require 'net/pop'
+require "net/imap"
+require "net/smtp"
+require "net/pop"
# Usage:
#
@@ -84,15 +84,14 @@ class EmailSettingsValidator
debug: Rails.env.development?
)
begin
- port, enable_tls, enable_starttls_auto = provider_specific_ssl_overrides(
- host, port, enable_tls, enable_starttls_auto
- )
+ port, enable_tls, enable_starttls_auto =
+ provider_specific_ssl_overrides(host, port, enable_tls, enable_starttls_auto)
if enable_tls && enable_starttls_auto
raise ArgumentError, "TLS and STARTTLS are mutually exclusive"
end
- if ![:plain, :login, :cram_md5].include?(authentication.to_sym)
+ if !%i[plain login cram_md5].include?(authentication.to_sym)
raise ArgumentError, "Invalid authentication method. Must be plain, login, or cram_md5."
end
@@ -100,7 +99,6 @@ class EmailSettingsValidator
if Rails.env.development?
domain = "localhost"
else
-
# Because we are using the SMTP settings here to send emails,
# the domain should just be the TLD of the host.
domain = MiniSuffix.domain(host)
@@ -154,7 +152,11 @@ class EmailSettingsValidator
begin
imap = Net::IMAP.new(host, port: port, ssl: ssl, open_timeout: open_timeout)
imap.login(username, password)
- imap.logout rescue nil
+ begin
+ imap.logout
+ rescue StandardError
+ nil
+ end
imap.disconnect
rescue => err
log_and_raise(err, debug)
@@ -163,7 +165,9 @@ class EmailSettingsValidator
def self.log_and_raise(err, debug)
if debug
- Rails.logger.warn("[EmailSettingsValidator] Error encountered when validating email settings: #{err.message} #{err.backtrace.join("\n")}")
+ Rails.logger.warn(
+ "[EmailSettingsValidator] Error encountered when validating email settings: #{err.message} #{err.backtrace.join("\n")}",
+ )
end
raise err
end
diff --git a/app/services/email_style_updater.rb b/app/services/email_style_updater.rb
index d13e84b78d6..42ebb0b7040 100644
--- a/app/services/email_style_updater.rb
+++ b/app/services/email_style_updater.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class EmailStyleUpdater
-
attr_reader :errors
def initialize(user)
@@ -10,11 +9,8 @@ class EmailStyleUpdater
end
def update(attrs)
- if attrs.has_key?(:html) && !attrs[:html].include?('%{email_content}')
- @errors << I18n.t(
- 'email_style.html_missing_placeholder',
- placeholder: '%{email_content}'
- )
+ if attrs.has_key?(:html) && !attrs[:html].include?("%{email_content}")
+ @errors << I18n.t("email_style.html_missing_placeholder", placeholder: "%{email_content}")
end
if attrs.has_key?(:css)
diff --git a/app/services/external_upload_manager.rb b/app/services/external_upload_manager.rb
index cfeca323c72..23523ab4bc0 100644
--- a/app/services/external_upload_manager.rb
+++ b/app/services/external_upload_manager.rb
@@ -7,10 +7,14 @@ class ExternalUploadManager
UPLOAD_TYPES_EXCLUDED_FROM_UPLOAD_PROMOTION = ["backup"].freeze
- class ChecksumMismatchError < StandardError; end
- class DownloadFailedError < StandardError; end
- class CannotPromoteError < StandardError; end
- class SizeMismatchError < StandardError; end
+ class ChecksumMismatchError < StandardError
+ end
+ class DownloadFailedError < StandardError
+ end
+ class CannotPromoteError < StandardError
+ end
+ class SizeMismatchError < StandardError
+ end
attr_reader :external_upload_stub
@@ -24,51 +28,54 @@ class ExternalUploadManager
def self.create_direct_upload(current_user:, file_name:, file_size:, upload_type:, metadata: {})
store = store_for_upload_type(upload_type)
- url = store.signed_url_for_temporary_upload(
- file_name, metadata: metadata
- )
+ url = store.signed_url_for_temporary_upload(file_name, metadata: metadata)
key = store.s3_helper.path_from_url(url)
- upload_stub = ExternalUploadStub.create!(
- key: key,
- created_by: current_user,
- original_filename: file_name,
- upload_type: upload_type,
- filesize: file_size
- )
+ upload_stub =
+ ExternalUploadStub.create!(
+ key: key,
+ created_by: current_user,
+ original_filename: file_name,
+ upload_type: upload_type,
+ filesize: file_size,
+ )
{ url: url, key: key, unique_identifier: upload_stub.unique_identifier }
end
def self.create_direct_multipart_upload(
- current_user:, file_name:, file_size:, upload_type:, metadata: {}
+ current_user:,
+ file_name:,
+ file_size:,
+ upload_type:,
+ metadata: {}
)
content_type = MiniMime.lookup_by_filename(file_name)&.content_type
store = store_for_upload_type(upload_type)
- multipart_upload = store.create_multipart(
- file_name, content_type, metadata: metadata
- )
+ multipart_upload = store.create_multipart(file_name, content_type, metadata: metadata)
- upload_stub = ExternalUploadStub.create!(
- key: multipart_upload[:key],
- created_by: current_user,
- original_filename: file_name,
- upload_type: upload_type,
- external_upload_identifier: multipart_upload[:upload_id],
- multipart: true,
- filesize: file_size
- )
+ upload_stub =
+ ExternalUploadStub.create!(
+ key: multipart_upload[:key],
+ created_by: current_user,
+ original_filename: file_name,
+ upload_type: upload_type,
+ external_upload_identifier: multipart_upload[:upload_id],
+ multipart: true,
+ filesize: file_size,
+ )
{
external_upload_identifier: upload_stub.external_upload_identifier,
key: upload_stub.key,
- unique_identifier: upload_stub.unique_identifier
+ unique_identifier: upload_stub.unique_identifier,
}
end
def self.store_for_upload_type(upload_type)
if upload_type == "backup"
- if !SiteSetting.enable_backups? || SiteSetting.backup_location != BackupLocationSiteSetting::S3
+ if !SiteSetting.enable_backups? ||
+ SiteSetting.backup_location != BackupLocationSiteSetting::S3
raise Discourse::InvalidAccess.new
end
BackupRestore::BackupStore.create
@@ -98,9 +105,11 @@ class ExternalUploadManager
if external_size != external_upload_stub.filesize
ExternalUploadManager.ban_user_from_external_uploads!(
user: external_upload_stub.created_by,
- ban_minutes: SIZE_MISMATCH_BAN_MINUTES
+ ban_minutes: SIZE_MISMATCH_BAN_MINUTES,
)
- raise SizeMismatchError.new("expected: #{external_upload_stub.filesize}, actual: #{external_size}")
+ raise SizeMismatchError.new(
+ "expected: #{external_upload_stub.filesize}, actual: #{external_size}",
+ )
end
if UPLOAD_TYPES_EXCLUDED_FROM_UPLOAD_PROMOTION.include?(external_upload_stub.upload_type)
@@ -108,7 +117,7 @@ class ExternalUploadManager
else
promote_to_upload
end
- rescue
+ rescue StandardError
if !SiteSetting.enable_upload_debug_mode
# We don't need to do anything special to abort multipart uploads here,
# because at this point (calling promote_to_upload!), the multipart
@@ -137,9 +146,7 @@ class ExternalUploadManager
raise DownloadFailedError if tempfile.blank?
actual_sha1 = Upload.generate_digest(tempfile)
- if external_sha1 && external_sha1 != actual_sha1
- raise ChecksumMismatchError
- end
+ raise ChecksumMismatchError if external_sha1 && external_sha1 != actual_sha1
end
# TODO (martin): See if these additional opts will be needed
@@ -148,11 +155,11 @@ class ExternalUploadManager
type: external_upload_stub.upload_type,
existing_external_upload_key: external_upload_stub.key,
external_upload_too_big: external_size > DOWNLOAD_LIMIT,
- filesize: external_size
+ filesize: external_size,
}.merge(@upload_create_opts)
UploadCreator.new(tempfile, external_upload_stub.original_filename, opts).create_for(
- external_upload_stub.created_by_id
+ external_upload_stub.created_by_id,
)
ensure
tempfile&.close!
@@ -163,7 +170,7 @@ class ExternalUploadManager
@store.move_existing_stored_upload(
existing_external_upload_key: external_upload_stub.key,
original_filename: external_upload_stub.original_filename,
- content_type: content_type
+ content_type: content_type,
)
Struct.new(:errors).new([])
end
@@ -190,7 +197,7 @@ class ExternalUploadManager
url,
max_file_size: DOWNLOAD_LIMIT,
tmp_file_name: "discourse-upload-#{type}",
- follow_redirect: true
+ follow_redirect: true,
)
end
end
diff --git a/app/services/group_action_logger.rb b/app/services/group_action_logger.rb
index d38d0e7c5a7..02299afb485 100644
--- a/app/services/group_action_logger.rb
+++ b/app/services/group_action_logger.rb
@@ -1,64 +1,71 @@
# frozen_string_literal: true
class GroupActionLogger
-
def initialize(acting_user, group)
@acting_user = acting_user
@group = group
end
def log_make_user_group_owner(target_user)
- GroupHistory.create!(default_params.merge(
- action: GroupHistory.actions[:make_user_group_owner],
- target_user: target_user
- ))
+ GroupHistory.create!(
+ default_params.merge(
+ action: GroupHistory.actions[:make_user_group_owner],
+ target_user: target_user,
+ ),
+ )
end
def log_remove_user_as_group_owner(target_user)
- GroupHistory.create!(default_params.merge(
- action: GroupHistory.actions[:remove_user_as_group_owner],
- target_user: target_user
- ))
+ GroupHistory.create!(
+ default_params.merge(
+ action: GroupHistory.actions[:remove_user_as_group_owner],
+ target_user: target_user,
+ ),
+ )
end
def log_add_user_to_group(target_user, subject = nil)
- GroupHistory.create!(default_params.merge(
- action: GroupHistory.actions[:add_user_to_group],
- target_user: target_user,
- subject: subject
- ))
+ GroupHistory.create!(
+ default_params.merge(
+ action: GroupHistory.actions[:add_user_to_group],
+ target_user: target_user,
+ subject: subject,
+ ),
+ )
end
def log_remove_user_from_group(target_user, subject = nil)
- GroupHistory.create!(default_params.merge(
- action: GroupHistory.actions[:remove_user_from_group],
- target_user: target_user,
- subject: subject
- ))
+ GroupHistory.create!(
+ default_params.merge(
+ action: GroupHistory.actions[:remove_user_from_group],
+ target_user: target_user,
+ subject: subject,
+ ),
+ )
end
def log_change_group_settings
- @group.previous_changes.except(*excluded_attributes).each do |attribute_name, value|
- next if value[0].blank? && value[1].blank?
+ @group
+ .previous_changes
+ .except(*excluded_attributes)
+ .each do |attribute_name, value|
+ next if value[0].blank? && value[1].blank?
- GroupHistory.create!(default_params.merge(
- action: GroupHistory.actions[:change_group_setting],
- subject: attribute_name,
- prev_value: value[0],
- new_value: value[1]
- ))
- end
+ GroupHistory.create!(
+ default_params.merge(
+ action: GroupHistory.actions[:change_group_setting],
+ subject: attribute_name,
+ prev_value: value[0],
+ new_value: value[1],
+ ),
+ )
+ end
end
private
def excluded_attributes
- [
- :bio_cooked,
- :updated_at,
- :created_at,
- :user_count
- ]
+ %i[bio_cooked updated_at created_at user_count]
end
def default_params
diff --git a/app/services/group_mentions_updater.rb b/app/services/group_mentions_updater.rb
index 5130baa43e6..8099dcde2b8 100644
--- a/app/services/group_mentions_updater.rb
+++ b/app/services/group_mentions_updater.rb
@@ -2,15 +2,16 @@
class GroupMentionsUpdater
def self.update(current_name, previous_name)
- Post.where(
- "cooked LIKE '%class=\"mention-group%' AND raw LIKE :previous_name",
- previous_name: "%@#{previous_name}%"
- ).find_in_batches do |posts|
-
- posts.each do |post|
- post.raw.gsub!(/(^|\s)(@#{previous_name})(\s|$)/, "\\1@#{current_name}\\3")
- post.save!(validate: false)
+ Post
+ .where(
+ "cooked LIKE '%class=\"mention-group%' AND raw LIKE :previous_name",
+ previous_name: "%@#{previous_name}%",
+ )
+ .find_in_batches do |posts|
+ posts.each do |post|
+ post.raw.gsub!(/(^|\s)(@#{previous_name})(\s|$)/, "\\1@#{current_name}\\3")
+ post.save!(validate: false)
+ end
end
- end
end
end
diff --git a/app/services/group_message.rb b/app/services/group_message.rb
index 1f24289434a..47ee093a3fd 100644
--- a/app/services/group_message.rb
+++ b/app/services/group_message.rb
@@ -11,7 +11,6 @@
# The default is 24 hours. Set to false to always send the message.
class GroupMessage
-
include Rails.application.routes.url_helpers
RECENT_MESSAGE_PERIOD = 3.months
@@ -29,14 +28,15 @@ class GroupMessage
def create
return false if sent_recently?
- post = PostCreator.create(
- Discourse.system_user,
- target_group_names: [@group_name],
- archetype: Archetype.private_message,
- subtype: TopicSubtype.system_message,
- title: I18n.t("system_messages.#{@message_type}.subject_template", message_params),
- raw: I18n.t("system_messages.#{@message_type}.text_body_template", message_params)
- )
+ post =
+ PostCreator.create(
+ Discourse.system_user,
+ target_group_names: [@group_name],
+ archetype: Archetype.private_message,
+ subtype: TopicSubtype.system_message,
+ title: I18n.t("system_messages.#{@message_type}.subject_template", message_params),
+ raw: I18n.t("system_messages.#{@message_type}.text_body_template", message_params),
+ )
remember_message_sent
post
end
@@ -44,38 +44,44 @@ class GroupMessage
def delete_previous!(respect_sent_recently: true, match_raw: true)
return false if respect_sent_recently && sent_recently?
- posts = Post
- .joins(topic: { topic_allowed_groups: :group })
- .where(topic: {
- posts_count: 1,
- user_id: Discourse.system_user,
- archetype: Archetype.private_message,
- subtype: TopicSubtype.system_message,
- title: I18n.t("system_messages.#{@message_type}.subject_template", message_params),
- topic_allowed_groups: {
- groups: { name: @group_name }
- }
- })
- .where("posts.created_at > ?", RECENT_MESSAGE_PERIOD.ago)
+ posts =
+ Post
+ .joins(topic: { topic_allowed_groups: :group })
+ .where(
+ topic: {
+ posts_count: 1,
+ user_id: Discourse.system_user,
+ archetype: Archetype.private_message,
+ subtype: TopicSubtype.system_message,
+ title: I18n.t("system_messages.#{@message_type}.subject_template", message_params),
+ topic_allowed_groups: {
+ groups: {
+ name: @group_name,
+ },
+ },
+ },
+ )
+ .where("posts.created_at > ?", RECENT_MESSAGE_PERIOD.ago)
if match_raw
- posts = posts.where(raw: I18n.t("system_messages.#{@message_type}.text_body_template", message_params).rstrip)
+ posts =
+ posts.where(
+ raw: I18n.t("system_messages.#{@message_type}.text_body_template", message_params).rstrip,
+ )
end
- posts.find_each do |post|
- PostDestroyer.new(Discourse.system_user, post).destroy
- end
+ posts.find_each { |post| PostDestroyer.new(Discourse.system_user, post).destroy }
end
def message_params
- @message_params ||= begin
- h = { base_url: Discourse.base_url }.merge(@opts[:message_params] || {})
- if @opts[:user]
- h.merge!(username: @opts[:user].username,
- user_url: user_path(@opts[:user].username))
+ @message_params ||=
+ begin
+ h = { base_url: Discourse.base_url }.merge(@opts[:message_params] || {})
+ if @opts[:user]
+ h.merge!(username: @opts[:user].username, user_url: user_path(@opts[:user].username))
+ end
+ h
end
- h
- end
end
def sent_recently?
@@ -85,10 +91,12 @@ class GroupMessage
# default is to send no more than once every 24 hours (24 * 60 * 60 = 86,400 seconds)
def remember_message_sent
- Discourse.redis.setex(sent_recently_key, @opts[:limit_once_per].try(:to_i) || 86_400, 1) unless @opts[:limit_once_per] == false
+ unless @opts[:limit_once_per] == false
+ Discourse.redis.setex(sent_recently_key, @opts[:limit_once_per].try(:to_i) || 86_400, 1)
+ end
end
def sent_recently_key
- "grpmsg:#{@group_name}:#{@message_type}:#{@opts[:user] ? @opts[:user].username : ''}"
+ "grpmsg:#{@group_name}:#{@message_type}:#{@opts[:user] ? @opts[:user].username : ""}"
end
end
diff --git a/app/services/handle_chunk_upload.rb b/app/services/handle_chunk_upload.rb
index d966f659aa1..cc69c1c5baa 100644
--- a/app/services/handle_chunk_upload.rb
+++ b/app/services/handle_chunk_upload.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class HandleChunkUpload
-
def initialize(chunk, params = {})
@chunk = chunk
@params = params
@@ -21,7 +20,8 @@ class HandleChunkUpload
def check_chunk
# check whether the chunk has already been uploaded
- has_chunk_been_uploaded = File.exist?(@chunk) && File.size(@chunk) == @params[:current_chunk_size]
+ has_chunk_been_uploaded =
+ File.exist?(@chunk) && File.size(@chunk) == @params[:current_chunk_size]
# 200 = exists, 404 = not uploaded yet
status = has_chunk_been_uploaded ? 200 : 404
end
@@ -36,11 +36,11 @@ class HandleChunkUpload
end
def merge_chunks
- upload_path = @params[:upload_path]
+ upload_path = @params[:upload_path]
tmp_upload_path = @params[:tmp_upload_path]
- identifier = @params[:identifier]
- filename = @params[:filename]
- tmp_directory = @params[:tmp_directory]
+ identifier = @params[:identifier]
+ filename = @params[:filename]
+ tmp_directory = @params[:tmp_directory]
# delete destination files
begin
@@ -68,5 +68,4 @@ class HandleChunkUpload
rescue Errno::ENOENT
end
end
-
end
diff --git a/app/services/heat_settings_updater.rb b/app/services/heat_settings_updater.rb
index 56666b71f47..325e87117c4 100644
--- a/app/services/heat_settings_updater.rb
+++ b/app/services/heat_settings_updater.rb
@@ -70,23 +70,20 @@ class HeatSettingsUpdater
if SiteSetting.get(name) != SiteSetting.defaults[name]
SiteSetting.set_and_log(name, SiteSetting.defaults[name])
end
- elsif SiteSetting.get(name) == 0 ||
- (new_value.to_f / SiteSetting.get(name) - 1.0).abs >= 0.05
-
- rounded_new_value = if new_value.is_a?(Integer)
- if new_value > 9
- digits = new_value.digits.reverse
- (digits[0] * 10 + digits[1]) * 10.pow(digits[2..-1].size)
+ elsif SiteSetting.get(name) == 0 || (new_value.to_f / SiteSetting.get(name) - 1.0).abs >= 0.05
+ rounded_new_value =
+ if new_value.is_a?(Integer)
+ if new_value > 9
+ digits = new_value.digits.reverse
+ (digits[0] * 10 + digits[1]) * 10.pow(digits[2..-1].size)
+ else
+ new_value
+ end
else
- new_value
+ new_value.round(2)
end
- else
- new_value.round(2)
- end
- if SiteSetting.get(name) != rounded_new_value
- SiteSetting.set_and_log(name, rounded_new_value)
- end
+ SiteSetting.set_and_log(name, rounded_new_value) if SiteSetting.get(name) != rounded_new_value
end
end
end
diff --git a/app/services/inline_uploads.rb b/app/services/inline_uploads.rb
index 62d081caa32..8feb0efc935 100644
--- a/app/services/inline_uploads.rb
+++ b/app/services/inline_uploads.rb
@@ -16,14 +16,20 @@ class InlineUploads
end
end
- cooked_fragment = Nokogiri::HTML5::fragment(PrettyText.cook(markdown, disable_emojis: true))
+ cooked_fragment = Nokogiri::HTML5.fragment(PrettyText.cook(markdown, disable_emojis: true))
link_occurrences = []
cooked_fragment.traverse do |node|
if node.name == "img"
# Do nothing
- elsif !(node.children.count == 1 && (node.children[0].name != "img" && node.children[0].children.blank?)) &&
- !(node.name == "a" && node.children.count > 1 && !node_children_names(node).include?("img"))
+ elsif !(
+ node.children.count == 1 &&
+ (node.children[0].name != "img" && node.children[0].children.blank?)
+ ) &&
+ !(
+ node.name == "a" && node.children.count > 1 &&
+ !node_children_names(node).include?("img")
+ )
next
end
@@ -55,7 +61,7 @@ class InlineUploads
end
regexps = [
- /(https?:\/\/[a-zA-Z0-9\.\/-]+\/#{Discourse.store.upload_path}#{UPLOAD_REGEXP_PATTERN})/,
+ %r{(https?://[a-zA-Z0-9\./-]+/#{Discourse.store.upload_path}#{UPLOAD_REGEXP_PATTERN})},
]
if Discourse.store.external?
@@ -103,41 +109,38 @@ class InlineUploads
raw_matches
.sort { |a, b| a[3] <=> b[3] }
.each do |match, link, replace_with, _index|
+ node_info = link_occurrences.shift
+ next unless node_info&.dig(:is_valid)
- node_info = link_occurrences.shift
- next unless node_info&.dig(:is_valid)
-
- if link.include?(node_info[:link])
- begin
- uri = URI(link)
- rescue URI::Error
- end
-
- if !Discourse.store.external?
- host = uri&.host
-
- hosts = [Discourse.current_hostname]
-
- if cdn_url = GlobalSetting.cdn_url
- hosts << URI(GlobalSetting.cdn_url).hostname
+ if link.include?(node_info[:link])
+ begin
+ uri = URI(link)
+ rescue URI::Error
end
- if host && !hosts.include?(host)
- next
+ if !Discourse.store.external?
+ host = uri&.host
+
+ hosts = [Discourse.current_hostname]
+
+ if cdn_url = GlobalSetting.cdn_url
+ hosts << URI(GlobalSetting.cdn_url).hostname
+ end
+
+ next if host && !hosts.include?(host)
end
- end
- upload = Upload.get_from_url(link)
+ upload = Upload.get_from_url(link)
- if upload
- replace_with.sub!(PLACEHOLDER, upload.short_url)
- replace_with.sub!(PATH_PLACEHOLDER, upload.short_path)
- markdown.sub!(match, replace_with)
- else
- on_missing.call(link) if on_missing
+ if upload
+ replace_with.sub!(PLACEHOLDER, upload.short_url)
+ replace_with.sub!(PATH_PLACEHOLDER, upload.short_path)
+ markdown.sub!(match, replace_with)
+ else
+ on_missing.call(link) if on_missing
+ end
end
end
- end
markdown.scan(/(__(\h{40})__)/) do |match|
upload = Upload.find_by(sha1: match[1])
@@ -161,7 +164,7 @@ class InlineUploads
end
def self.match_bbcode_img(markdown, external_src: false)
- markdown.scan(/(\[img\]\s*([^\[\]\s]+)\s*\[\/img\])/i) do |match|
+ markdown.scan(%r{(\[img\]\s*([^\[\]\s]+)\s*\[/img\])}i) do |match|
if (external_src || (matched_uploads(match[1]).present?)) && block_given?
yield(match[0], match[1], +"![](#{PLACEHOLDER})", $~.offset(0)[0])
end
@@ -182,9 +185,9 @@ class InlineUploads
end
def self.match_anchor(markdown, external_href: false)
- markdown.scan(/(()([^<\a>]*?)<\/a>)/i) do |match|
- node = Nokogiri::HTML5::fragment(match[0]).children[0]
- href = node.attributes["href"]&.value
+ markdown.scan(%r{(()([^<\a>]*?))}i) do |match|
+ node = Nokogiri::HTML5.fragment(match[0]).children[0]
+ href = node.attributes["href"]&.value
if href && (external_href || matched_uploads(href).present?)
has_attachment = node.attributes["class"]&.value
@@ -198,8 +201,8 @@ class InlineUploads
end
def self.match_img(markdown, external_src: false, uploads: nil)
- markdown.scan(/(<(?!img)[^<>]+\/?>)?(\s*)(\n]+>)/i) do |match|
- node = Nokogiri::HTML5::fragment(match[2].strip).children[0]
+ markdown.scan(%r{(<(?!img)[^<>]+/?>)?(\s*)(\n]+>)}i) do |match|
+ node = Nokogiri::HTML5.fragment(match[2].strip).children[0]
src = node&.attributes&.[]("src")&.value
if src && (external_src || matched_uploads(src).present?)
@@ -215,22 +218,20 @@ class InlineUploads
end
def self.replace_hotlinked_image_urls(raw:, &blk)
- replace = Proc.new do |match, match_src, replacement, _index|
- upload = blk.call(match_src)
- next if !upload
+ replace =
+ Proc.new do |match, match_src, replacement, _index|
+ upload = blk.call(match_src)
+ next if !upload
- replacement =
- if replacement.include?(InlineUploads::PLACEHOLDER)
- replacement.sub(InlineUploads::PLACEHOLDER, upload.short_url)
- elsif replacement.include?(InlineUploads::PATH_PLACEHOLDER)
- replacement.sub(InlineUploads::PATH_PLACEHOLDER, upload.short_path)
- end
+ replacement =
+ if replacement.include?(InlineUploads::PLACEHOLDER)
+ replacement.sub(InlineUploads::PLACEHOLDER, upload.short_url)
+ elsif replacement.include?(InlineUploads::PATH_PLACEHOLDER)
+ replacement.sub(InlineUploads::PATH_PLACEHOLDER, upload.short_path)
+ end
- raw = raw.gsub(
- match,
- replacement
- )
- end
+ raw = raw.gsub(match, replacement)
+ end
# there are 6 ways to insert an image in a post
# HTML tag -
@@ -245,40 +246,41 @@ class InlineUploads
# Markdown inline - ![alt](http://... "image title")
InlineUploads.match_md_inline_img(raw, external_src: true, &replace)
- raw = raw.gsub(/^(https?:\/\/\S+)(\s?)$/) do |match|
- if upload = blk.call(match)
- "![](#{upload.short_url})"
- else
- match
+ raw =
+ raw.gsub(%r{^(https?://\S+)(\s?)$}) do |match|
+ if upload = blk.call(match)
+ "![](#{upload.short_url})"
+ else
+ match
+ end
end
- end
raw
end
def self.matched_uploads(node)
upload_path = Discourse.store.upload_path
- base_url = Discourse.base_url.sub(/https?:\/\//, "(https?://)")
+ base_url = Discourse.base_url.sub(%r{https?://}, "(https?://)")
regexps = [
- /(upload:\/\/([a-zA-Z0-9]+)[a-zA-Z0-9\.]*)/,
- /(\/uploads\/short-url\/([a-zA-Z0-9]+)[a-zA-Z0-9\.]*)/,
- /(#{base_url}\/uploads\/short-url\/([a-zA-Z0-9]+)[a-zA-Z0-9\.]*)/,
- /(#{GlobalSetting.relative_url_root}\/#{upload_path}#{UPLOAD_REGEXP_PATTERN})/,
- /(#{base_url}\/#{upload_path}#{UPLOAD_REGEXP_PATTERN})/,
+ %r{(upload://([a-zA-Z0-9]+)[a-zA-Z0-9\.]*)},
+ %r{(/uploads/short-url/([a-zA-Z0-9]+)[a-zA-Z0-9\.]*)},
+ %r{(#{base_url}/uploads/short-url/([a-zA-Z0-9]+)[a-zA-Z0-9\.]*)},
+ %r{(#{GlobalSetting.relative_url_root}/#{upload_path}#{UPLOAD_REGEXP_PATTERN})},
+ %r{(#{base_url}/#{upload_path}#{UPLOAD_REGEXP_PATTERN})},
]
- if GlobalSetting.cdn_url && (cdn_url = GlobalSetting.cdn_url.sub(/https?:\/\//, "(https?://)"))
- regexps << /(#{cdn_url}\/#{upload_path}#{UPLOAD_REGEXP_PATTERN})/
+ if GlobalSetting.cdn_url && (cdn_url = GlobalSetting.cdn_url.sub(%r{https?://}, "(https?://)"))
+ regexps << %r{(#{cdn_url}/#{upload_path}#{UPLOAD_REGEXP_PATTERN})}
if GlobalSetting.relative_url_root.present?
- regexps << /(#{cdn_url}#{GlobalSetting.relative_url_root}\/#{upload_path}#{UPLOAD_REGEXP_PATTERN})/
+ regexps << %r{(#{cdn_url}#{GlobalSetting.relative_url_root}/#{upload_path}#{UPLOAD_REGEXP_PATTERN})}
end
end
if Discourse.store.external?
if Rails.configuration.multisite
- regexps << /((https?:)?#{SiteSetting.Upload.s3_base_url}\/#{upload_path}#{UPLOAD_REGEXP_PATTERN})/
- regexps << /(#{SiteSetting.Upload.s3_cdn_url}\/#{upload_path}#{UPLOAD_REGEXP_PATTERN})/
+ regexps << %r{((https?:)?#{SiteSetting.Upload.s3_base_url}/#{upload_path}#{UPLOAD_REGEXP_PATTERN})}
+ regexps << %r{(#{SiteSetting.Upload.s3_cdn_url}/#{upload_path}#{UPLOAD_REGEXP_PATTERN})}
else
regexps << /((https?:)?#{SiteSetting.Upload.s3_base_url}#{UPLOAD_REGEXP_PATTERN})/
regexps << /(#{SiteSetting.Upload.s3_cdn_url}#{UPLOAD_REGEXP_PATTERN})/
@@ -289,9 +291,7 @@ class InlineUploads
node = node.to_s
regexps.each do |regexp|
- node.scan(/(^|[\n\s"'\(>])#{regexp}($|[\n\s"'\)<])/) do |matched|
- matches << matched[1]
- end
+ node.scan(/(^|[\n\s"'\(>])#{regexp}($|[\n\s"'\)<])/) { |matched| matches << matched[1] }
end
matches
@@ -304,9 +304,7 @@ class InlineUploads
return names
end
- node.children.each do |child|
- names = node_children_names(child, names)
- end
+ node.children.each { |child| names = node_children_names(child, names) }
names
end
diff --git a/app/services/notification_emailer.rb b/app/services/notification_emailer.rb
index b768ae5b68b..60d124dc965 100644
--- a/app/services/notification_emailer.rb
+++ b/app/services/notification_emailer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class NotificationEmailer
-
class EmailUser
attr_reader :notification, :no_delay
@@ -84,7 +83,6 @@ class NotificationEmailer
end
def enqueue_private(type, delay = private_delay)
-
if notification.user.user_option.nil?
# this can happen if we roll back user creation really early
# or delete user
@@ -92,7 +90,9 @@ class NotificationEmailer
return
end
- return if notification.user.user_option.email_messages_level == UserOption.email_level_types[:never]
+ if notification.user.user_option.email_messages_level == UserOption.email_level_types[:never]
+ return
+ end
perform_enqueue(type, delay)
end
@@ -116,13 +116,13 @@ class NotificationEmailer
end
def post_type
- @post_type ||= begin
- type = notification.data_hash["original_post_type"] if notification.data_hash
- type ||= notification.post.try(:post_type)
- type
- end
+ @post_type ||=
+ begin
+ type = notification.data_hash["original_post_type"] if notification.data_hash
+ type ||= notification.post.try(:post_type)
+ type
+ end
end
-
end
def self.disable
@@ -136,9 +136,8 @@ class NotificationEmailer
def self.process_notification(notification, no_delay: false)
return if @disabled
- email_user = EmailUser.new(notification, no_delay: no_delay)
+ email_user = EmailUser.new(notification, no_delay: no_delay)
email_method = Notification.types[notification.notification_type]
email_user.public_send(email_method) if email_user.respond_to? email_method
end
-
end
diff --git a/app/services/notifications/consolidate_notifications.rb b/app/services/notifications/consolidate_notifications.rb
index adfeaee10fc..b50eb504e1a 100644
--- a/app/services/notifications/consolidate_notifications.rb
+++ b/app/services/notifications/consolidate_notifications.rb
@@ -34,7 +34,14 @@
module Notifications
class ConsolidateNotifications < ConsolidationPlan
- def initialize(from:, to:, consolidation_window: nil, unconsolidated_query_blk: nil, consolidated_query_blk: nil, threshold:)
+ def initialize(
+ from:,
+ to:,
+ consolidation_window: nil,
+ unconsolidated_query_blk: nil,
+ consolidated_query_blk: nil,
+ threshold:
+ )
@from = from
@to = to
@threshold = threshold
@@ -67,15 +74,21 @@ module Notifications
return unless can_consolidate_data?(notification)
update_consolidated_notification!(notification) ||
- create_consolidated_notification!(notification) ||
- notification.tap(&:save!)
+ create_consolidated_notification!(notification) || notification.tap(&:save!)
end
private
attr_reader(
- :notification, :from, :to, :data, :threshold, :consolidated_query_blk,
- :unconsolidated_query_blk, :consolidation_window, :bump_notification
+ :notification,
+ :from,
+ :to,
+ :data,
+ :threshold,
+ :consolidated_query_blk,
+ :unconsolidated_query_blk,
+ :consolidation_window,
+ :bump_notification,
)
def update_consolidated_notification!(notification)
@@ -90,18 +103,12 @@ module Notifications
data_hash = consolidated.data_hash.merge(data)
data_hash[:count] += 1 if data_hash[:count].present?
- if @before_update_blk
- @before_update_blk.call(consolidated, data_hash, notification)
- end
+ @before_update_blk.call(consolidated, data_hash, notification) if @before_update_blk
# Hack: We don't want to cache the old data if we're about to update it.
consolidated.instance_variable_set(:@data_hash, nil)
- consolidated.update!(
- data: data_hash.to_json,
- read: false,
- updated_at: timestamp,
- )
+ consolidated.update!(data: data_hash.to_json, read: false, updated_at: timestamp)
consolidated
end
@@ -119,22 +126,21 @@ module Notifications
timestamp = notifications.last.created_at
data[:count] = count_after_saving_notification
- if @before_consolidation_blk
- @before_consolidation_blk.call(notifications, data)
- end
+ @before_consolidation_blk.call(notifications, data) if @before_consolidation_blk
consolidated = nil
Notification.transaction do
notifications.destroy_all
- consolidated = Notification.create!(
- notification_type: to,
- user_id: notification.user_id,
- data: data.to_json,
- updated_at: timestamp,
- created_at: timestamp
- )
+ consolidated =
+ Notification.create!(
+ notification_type: to,
+ user_id: notification.user_id,
+ data: data.to_json,
+ updated_at: timestamp,
+ created_at: timestamp,
+ )
end
consolidated
@@ -148,7 +154,7 @@ module Notifications
notifications = super(notification, type)
if consolidation_window.present?
- notifications = notifications.where('created_at > ?', consolidation_window.ago)
+ notifications = notifications.where("created_at > ?", consolidation_window.ago)
end
notifications
diff --git a/app/services/notifications/consolidation_planner.rb b/app/services/notifications/consolidation_planner.rb
index 6d1f5cb44d0..87704b010e8 100644
--- a/app/services/notifications/consolidation_planner.rb
+++ b/app/services/notifications/consolidation_planner.rb
@@ -12,105 +12,125 @@ module Notifications
private
def plan_for(notification)
- consolidation_plans = [liked_by_two_users, liked, group_message_summary, group_membership, new_features_notification]
+ consolidation_plans = [
+ liked_by_two_users,
+ liked,
+ group_message_summary,
+ group_membership,
+ new_features_notification,
+ ]
consolidation_plans.concat(DiscoursePluginRegistry.notification_consolidation_plans)
consolidation_plans.detect { |plan| plan.can_consolidate_data?(notification) }
end
def liked
- ConsolidateNotifications.new(
- from: Notification.types[:liked],
- to: Notification.types[:liked_consolidated],
- threshold: -> { SiteSetting.notification_consolidation_threshold },
- consolidation_window: SiteSetting.likes_notification_consolidation_window_mins.minutes,
- unconsolidated_query_blk: Proc.new do |notifications, data|
- key = 'display_username'
- value = data[key.to_sym]
- filtered = notifications.where("data::json ->> 'username2' IS NULL")
+ ConsolidateNotifications
+ .new(
+ from: Notification.types[:liked],
+ to: Notification.types[:liked_consolidated],
+ threshold: -> { SiteSetting.notification_consolidation_threshold },
+ consolidation_window: SiteSetting.likes_notification_consolidation_window_mins.minutes,
+ unconsolidated_query_blk:
+ Proc.new do |notifications, data|
+ key = "display_username"
+ value = data[key.to_sym]
+ filtered = notifications.where("data::json ->> 'username2' IS NULL")
- filtered = filtered.where("data::json ->> '#{key}' = ?", value) if value
+ filtered = filtered.where("data::json ->> '#{key}' = ?", value) if value
- filtered
- end,
- consolidated_query_blk: filtered_by_data_attribute('display_username')
- ).set_mutations(
- set_data_blk: Proc.new do |notification|
- data = notification.data_hash
- data.merge(username: data[:display_username])
- end
- ).set_precondition(precondition_blk: Proc.new { |data| data[:username2].blank? })
+ filtered
+ end,
+ consolidated_query_blk: filtered_by_data_attribute("display_username"),
+ )
+ .set_mutations(
+ set_data_blk:
+ Proc.new do |notification|
+ data = notification.data_hash
+ data.merge(username: data[:display_username])
+ end,
+ )
+ .set_precondition(precondition_blk: Proc.new { |data| data[:username2].blank? })
end
def liked_by_two_users
- DeletePreviousNotifications.new(
- type: Notification.types[:liked],
- previous_query_blk: Proc.new do |notifications, data|
- notifications.where(id: data[:previous_notification_id])
- end
- ).set_mutations(
- set_data_blk: Proc.new do |notification|
- existing_notification_of_same_type = Notification
- .where(user: notification.user)
- .order("notifications.id DESC")
- .where(topic_id: notification.topic_id, post_number: notification.post_number)
- .where(notification_type: notification.notification_type)
- .where('created_at > ?', 1.day.ago)
- .first
+ DeletePreviousNotifications
+ .new(
+ type: Notification.types[:liked],
+ previous_query_blk:
+ Proc.new do |notifications, data|
+ notifications.where(id: data[:previous_notification_id])
+ end,
+ )
+ .set_mutations(
+ set_data_blk:
+ Proc.new do |notification|
+ existing_notification_of_same_type =
+ Notification
+ .where(user: notification.user)
+ .order("notifications.id DESC")
+ .where(topic_id: notification.topic_id, post_number: notification.post_number)
+ .where(notification_type: notification.notification_type)
+ .where("created_at > ?", 1.day.ago)
+ .first
- data = notification.data_hash
- if existing_notification_of_same_type
- same_type_data = existing_notification_of_same_type.data_hash
- data.merge(
- previous_notification_id: existing_notification_of_same_type.id,
- username2: same_type_data[:display_username],
- count: (same_type_data[:count] || 1).to_i + 1
- )
- else
- data
- end
- end
- ).set_precondition(
- precondition_blk: Proc.new do |data, notification|
- always_freq = UserOption.like_notification_frequency_type[:always]
+ data = notification.data_hash
+ if existing_notification_of_same_type
+ same_type_data = existing_notification_of_same_type.data_hash
+ data.merge(
+ previous_notification_id: existing_notification_of_same_type.id,
+ username2: same_type_data[:display_username],
+ count: (same_type_data[:count] || 1).to_i + 1,
+ )
+ else
+ data
+ end
+ end,
+ )
+ .set_precondition(
+ precondition_blk:
+ Proc.new do |data, notification|
+ always_freq = UserOption.like_notification_frequency_type[:always]
- notification.user&.user_option&.like_notification_frequency == always_freq &&
- data[:previous_notification_id].present?
- end
- )
+ notification.user&.user_option&.like_notification_frequency == always_freq &&
+ data[:previous_notification_id].present?
+ end,
+ )
end
def group_membership
- ConsolidateNotifications.new(
- from: Notification.types[:private_message],
- to: Notification.types[:membership_request_consolidated],
- threshold: -> { SiteSetting.notification_consolidation_threshold },
- consolidation_window: Notification::MEMBERSHIP_REQUEST_CONSOLIDATION_WINDOW_HOURS.hours,
- unconsolidated_query_blk: filtered_by_data_attribute('topic_title'),
- consolidated_query_blk: filtered_by_data_attribute('group_name')
- ).set_precondition(
- precondition_blk: Proc.new { |data| data[:group_name].present? }
- ).set_mutations(
- set_data_blk: Proc.new do |notification|
- data = notification.data_hash
- post_id = data[:original_post_id]
- custom_field = PostCustomField.select(:value).find_by(post_id: post_id, name: "requested_group_id")
- group_id = custom_field&.value
- group_name = group_id.present? ? Group.select(:name).find_by(id: group_id.to_i)&.name : nil
+ ConsolidateNotifications
+ .new(
+ from: Notification.types[:private_message],
+ to: Notification.types[:membership_request_consolidated],
+ threshold: -> { SiteSetting.notification_consolidation_threshold },
+ consolidation_window: Notification::MEMBERSHIP_REQUEST_CONSOLIDATION_WINDOW_HOURS.hours,
+ unconsolidated_query_blk: filtered_by_data_attribute("topic_title"),
+ consolidated_query_blk: filtered_by_data_attribute("group_name"),
+ )
+ .set_precondition(precondition_blk: Proc.new { |data| data[:group_name].present? })
+ .set_mutations(
+ set_data_blk:
+ Proc.new do |notification|
+ data = notification.data_hash
+ post_id = data[:original_post_id]
+ custom_field =
+ PostCustomField.select(:value).find_by(post_id: post_id, name: "requested_group_id")
+ group_id = custom_field&.value
+ group_name =
+ group_id.present? ? Group.select(:name).find_by(id: group_id.to_i)&.name : nil
- data[:group_name] = group_name
- data
- end
- )
+ data[:group_name] = group_name
+ data
+ end,
+ )
end
def group_message_summary
DeletePreviousNotifications.new(
type: Notification.types[:group_message_summary],
- previous_query_blk: filtered_by_data_attribute('group_id')
- ).set_precondition(
- precondition_blk: Proc.new { |data| data[:group_id].present? }
- )
+ previous_query_blk: filtered_by_data_attribute("group_id"),
+ ).set_precondition(precondition_blk: Proc.new { |data| data[:group_id].present? })
end
def filtered_by_data_attribute(attribute_name)
diff --git a/app/services/notifications/delete_previous_notifications.rb b/app/services/notifications/delete_previous_notifications.rb
index 955af73a012..d6f561c1b6d 100644
--- a/app/services/notifications/delete_previous_notifications.rb
+++ b/app/services/notifications/delete_previous_notifications.rb
@@ -35,9 +35,7 @@ module Notifications
return unless can_consolidate_data?(notification)
notifications = user_notifications(notification, type)
- if previous_query_blk.present?
- notifications = previous_query_blk.call(notifications, data)
- end
+ notifications = previous_query_blk.call(notifications, data) if previous_query_blk.present?
notification.data = data.to_json
diff --git a/app/services/post_action_notifier.rb b/app/services/post_action_notifier.rb
index 71bf1e5d80f..c90fa520349 100644
--- a/app/services/post_action_notifier.rb
+++ b/app/services/post_action_notifier.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class PostActionNotifier
-
def self.disable
@disabled = true
end
@@ -22,11 +21,14 @@ class PostActionNotifier
def self.refresh_like_notification(post, read)
return unless post && post.user_id && post.topic
- usernames = post.post_actions.where(post_action_type_id: PostActionType.types[:like])
- .joins(:user)
- .order('post_actions.created_at desc')
- .where('post_actions.created_at > ?', 1.day.ago)
- .pluck(:username)
+ usernames =
+ post
+ .post_actions
+ .where(post_action_type_id: PostActionType.types[:like])
+ .joins(:user)
+ .order("post_actions.created_at desc")
+ .where("post_actions.created_at > ?", 1.day.ago)
+ .pluck(:username)
if usernames.length > 0
data = {
@@ -34,7 +36,7 @@ class PostActionNotifier
username: usernames[0],
display_username: usernames[0],
username2: usernames[1],
- count: usernames.length
+ count: usernames.length,
}
Notification.create(
notification_type: Notification.types[:liked],
@@ -42,7 +44,7 @@ class PostActionNotifier
post_number: post.post_number,
user_id: post.user_id,
read: read,
- data: data.to_json
+ data: data.to_json,
)
end
end
@@ -54,18 +56,19 @@ class PostActionNotifier
return if post_action.deleted_at.blank?
if post_action.post_action_type_id == PostActionType.types[:like] && post_action.post
-
read = true
- Notification.where(
- topic_id: post_action.post.topic_id,
- user_id: post_action.post.user_id,
- post_number: post_action.post.post_number,
- notification_type: Notification.types[:liked]
- ).each do |notification|
- read = false unless notification.read
- notification.destroy
- end
+ Notification
+ .where(
+ topic_id: post_action.post.topic_id,
+ user_id: post_action.post.user_id,
+ post_number: post_action.post.post_number,
+ notification_type: Notification.types[:liked],
+ )
+ .each do |notification|
+ read = false unless notification.read
+ notification.destroy
+ end
refresh_like_notification(post_action.post, read)
else
@@ -89,7 +92,7 @@ class PostActionNotifier
post,
display_username: post_action.user.username,
post_action_id: post_action.id,
- user_id: post_action.user_id
+ user_id: post_action.user_id,
)
end
@@ -106,19 +109,18 @@ class PostActionNotifier
user_ids = []
- if post_revision.user_id != post.user_id
- user_ids << post.user_id
- end
+ user_ids << post.user_id if post_revision.user_id != post.user_id
# Notify all users watching the topic when the OP of a wiki topic is edited
# or if the topic category allows unlimited owner edits on the OP.
if post.is_first_post? &&
- (post.wiki? || post.topic.category_allows_unlimited_owner_edits_on_first_post?)
+ (post.wiki? || post.topic.category_allows_unlimited_owner_edits_on_first_post?)
user_ids.concat(
- TopicUser.watching(post.topic_id)
+ TopicUser
+ .watching(post.topic_id)
.where.not(user_id: post_revision.user_id)
.where(topic: post.topic)
- .pluck(:user_id)
+ .pluck(:user_id),
)
end
@@ -128,10 +130,7 @@ class PostActionNotifier
if user_ids.present?
DB.after_commit do
- Jobs.enqueue(:notify_post_revision,
- user_ids: user_ids,
- post_revision_id: post_revision.id
- )
+ Jobs.enqueue(:notify_post_revision, user_ids: user_ids, post_revision_id: post_revision.id)
end
end
end
@@ -145,7 +144,7 @@ class PostActionNotifier
Notification.types[:edited],
post,
display_username: post.last_editor.username,
- acting_user_id: post.last_editor.id
+ acting_user_id: post.last_editor.id,
)
end
end
@@ -162,8 +161,13 @@ class PostActionNotifier
def self.notification_is_disabled?(post_revision)
modifications = post_revision.modifications
- (SiteSetting.disable_system_edit_notifications && post_revision.user_id == Discourse::SYSTEM_USER_ID) ||
- (SiteSetting.disable_category_edit_notifications && modifications&.dig("category_id").present?) ||
- (SiteSetting.disable_tags_edit_notifications && modifications&.dig("tags").present?)
+ (
+ SiteSetting.disable_system_edit_notifications &&
+ post_revision.user_id == Discourse::SYSTEM_USER_ID
+ ) ||
+ (
+ SiteSetting.disable_category_edit_notifications &&
+ modifications&.dig("category_id").present?
+ ) || (SiteSetting.disable_tags_edit_notifications && modifications&.dig("tags").present?)
end
end
diff --git a/app/services/post_alerter.rb b/app/services/post_alerter.rb
index c20ed382f0d..8b8de6aa827 100644
--- a/app/services/post_alerter.rb
+++ b/app/services/post_alerter.rb
@@ -18,13 +18,14 @@ class PostAlerter
if post_url = post.url
payload = {
- notification_type: notification_type,
- post_number: post.post_number,
- topic_title: post.topic.title,
- topic_id: post.topic.id,
- excerpt: excerpt || post.excerpt(400, text_entities: true, strip_links: true, remap_emoji: true),
- username: username || post.username,
- post_url: post_url
+ notification_type: notification_type,
+ post_number: post.post_number,
+ topic_title: post.topic.title,
+ topic_id: post.topic.id,
+ excerpt:
+ excerpt || post.excerpt(400, text_entities: true, strip_links: true, remap_emoji: true),
+ username: username || post.username,
+ post_url: post_url,
}
DiscourseEvent.trigger(:pre_notification_alert, user, payload)
@@ -51,22 +52,25 @@ class PostAlerter
SiteSetting.push_notification_time_window_mins.minutes,
:send_push_notification,
user_id: user.id,
- payload: payload
+ payload: payload,
)
else
Jobs.enqueue(:send_push_notification, user_id: user.id, payload: payload)
end
end
- if SiteSetting.allow_user_api_key_scopes.split("|").include?("push") && SiteSetting.allowed_user_api_push_urls.present?
- clients = user.user_api_keys
- .joins(:scopes)
- .where("user_api_key_scopes.name IN ('push', 'notifications')")
- .where("push_url IS NOT NULL AND push_url <> ''")
- .where("position(push_url IN ?) > 0", SiteSetting.allowed_user_api_push_urls)
- .where("revoked_at IS NULL")
- .order(client_id: :asc)
- .pluck(:client_id, :push_url)
+ if SiteSetting.allow_user_api_key_scopes.split("|").include?("push") &&
+ SiteSetting.allowed_user_api_push_urls.present?
+ clients =
+ user
+ .user_api_keys
+ .joins(:scopes)
+ .where("user_api_key_scopes.name IN ('push', 'notifications')")
+ .where("push_url IS NOT NULL AND push_url <> ''")
+ .where("position(push_url IN ?) > 0", SiteSetting.allowed_user_api_push_urls)
+ .where("revoked_at IS NULL")
+ .order(client_id: :asc)
+ .pluck(:client_id, :push_url)
if clients.length > 0
Jobs.enqueue(:push_notification, clients: clients, payload: payload, user_id: user.id)
@@ -79,9 +83,7 @@ class PostAlerter
end
def not_allowed?(user, post)
- user.blank? ||
- user.bot? ||
- user.id == post.user_id
+ user.blank? || user.bot? || user.id == post.user_id
end
def all_allowed_users(post)
@@ -130,7 +132,11 @@ class PostAlerter
if post.last_editor_id != post.user_id
# Mention comes from an edit by someone else, so notification should say who added the mention.
- mentioned_opts = { user_id: editor.id, original_username: editor.username, display_username: editor.username }
+ mentioned_opts = {
+ user_id: editor.id,
+ original_username: editor.username,
+ display_username: editor.username,
+ }
end
if mentioned_users
@@ -141,7 +147,8 @@ class PostAlerter
expand_group_mentions(mentioned_groups, post) do |group, users|
users = only_allowed_users(users, post)
- notified += notify_users(users - notified, :group_mentioned, post, mentioned_opts.merge(group: group))
+ notified +=
+ notify_users(users - notified, :group_mentioned, post, mentioned_opts.merge(group: group))
end
if mentioned_here
@@ -162,7 +169,8 @@ class PostAlerter
end
topic_author = post.topic.user
- if topic_author && !notified.include?(topic_author) && user_watching_topic?(topic_author, post.topic)
+ if topic_author && !notified.include?(topic_author) &&
+ user_watching_topic?(topic_author, post.topic)
notified += notify_non_pm_users(topic_author, :replied, post)
end
end
@@ -187,8 +195,22 @@ class PostAlerter
notified += notify_pm_users(post, reply_to_user, quoted_users, notified)
elsif notify_about_reply?(post)
# posts
- notified += notify_post_users(post, notified, new_record: new_record, include_category_watchers: false, include_tag_watchers: false)
- notified += notify_post_users(post, notified, new_record: new_record, include_topic_watchers: false, notification_type: :watching_category_or_tag)
+ notified +=
+ notify_post_users(
+ post,
+ notified,
+ new_record: new_record,
+ include_category_watchers: false,
+ include_tag_watchers: false,
+ )
+ notified +=
+ notify_post_users(
+ post,
+ notified,
+ new_record: new_record,
+ include_topic_watchers: false,
+ notification_type: :watching_category_or_tag,
+ )
end
end
@@ -213,7 +235,7 @@ class PostAlerter
def group_watchers(topic)
GroupUser.where(
group_id: topic.allowed_groups.pluck(:group_id),
- notification_level: GroupUser.notification_levels[:watching_first_post]
+ notification_level: GroupUser.notification_levels[:watching_first_post],
).pluck(:user_id)
end
@@ -221,11 +243,13 @@ class PostAlerter
topic
.tag_users
.notification_level_visible([TagUser.notification_levels[:watching_first_post]])
- .distinct(:user_id).pluck(:user_id)
+ .distinct(:user_id)
+ .pluck(:user_id)
end
def category_watchers(topic)
- topic.category_users
+ topic
+ .category_users
.where(notification_level: CategoryUser.notification_levels[:watching_first_post])
.pluck(:user_id)
end
@@ -259,23 +283,23 @@ class PostAlerter
# running concurrently
GroupMention.insert_all(
mentioned_groups.map do |group|
- {
- post_id: post.id,
- group_id: group.id,
- created_at: now,
- updated_at: now,
- }
- end
+ { post_id: post.id, group_id: group.id, created_at: now, updated_at: now }
+ end,
)
end
def unread_posts(user, topic)
- Post.secured(Guardian.new(user))
- .where('post_number > COALESCE((
+ Post
+ .secured(Guardian.new(user))
+ .where(
+ "post_number > COALESCE((
SELECT last_read_post_number FROM topic_users tu
- WHERE tu.user_id = ? AND tu.topic_id = ? ),0)',
- user.id, topic.id)
- .where('reply_to_user_id = :user_id
+ WHERE tu.user_id = ? AND tu.topic_id = ? ),0)",
+ user.id,
+ topic.id,
+ )
+ .where(
+ "reply_to_user_id = :user_id
OR exists(SELECT 1 from topic_users tu
WHERE tu.user_id = :user_id AND
tu.topic_id = :topic_id AND
@@ -287,19 +311,19 @@ class PostAlerter
OR exists(SELECT 1 from tag_users tu
WHERE tu.user_id = :user_id AND
tu.tag_id IN (SELECT tag_id FROM topic_tags WHERE topic_id = :topic_id) AND
- notification_level = :tag_level)',
+ notification_level = :tag_level)",
user_id: user.id,
topic_id: topic.id,
category_id: topic.category_id,
topic_level: TopicUser.notification_levels[:watching],
category_level: CategoryUser.notification_levels[:watching],
- tag_level: TagUser.notification_levels[:watching]
+ tag_level: TagUser.notification_levels[:watching],
)
.where(topic_id: topic.id)
end
def first_unread_post(user, topic)
- unread_posts(user, topic).order('post_number').first
+ unread_posts(user, topic).order("post_number").first
end
def unread_count(user, topic)
@@ -311,28 +335,26 @@ class PostAlerter
return unless Guardian.new(user).can_see?(topic)
User.transaction do
- user.notifications.where(
- notification_type: types,
- topic_id: topic.id
- ).destroy_all
+ user.notifications.where(notification_type: types, topic_id: topic.id).destroy_all
# Reload so notification counts sync up correctly
user.reload
end
end
- NOTIFIABLE_TYPES = [
- :mentioned,
- :replied,
- :quoted,
- :posted,
- :linked,
- :private_message,
- :group_mentioned,
- :watching_first_post,
- :event_reminder,
- :event_invitation
- ].map { |t| Notification.types[t] }
+ NOTIFIABLE_TYPES =
+ %i[
+ mentioned
+ replied
+ quoted
+ posted
+ linked
+ private_message
+ group_mentioned
+ watching_first_post
+ event_reminder
+ event_invitation
+ ].map { |t| Notification.types[t] }
def group_stats(topic)
sql = <<~SQL
@@ -346,7 +368,7 @@ class PostAlerter
{
group_id: g.id,
group_name: g.name,
- inbox_count: DB.query_single(sql, group_id: g.id).first.to_i
+ inbox_count: DB.query_single(sql, group_id: g.id).first.to_i,
}
end
end
@@ -356,10 +378,8 @@ class PostAlerter
stats = (@group_stats[topic.id] ||= group_stats(topic))
return unless stats
- group_id = topic
- .topic_allowed_groups
- .where(group_id: user.groups.pluck(:id))
- .pluck_first(:group_id)
+ group_id =
+ topic.topic_allowed_groups.where(group_id: user.groups.pluck(:id)).pluck_first(:group_id)
stat = stats.find { |s| s[:group_id] == group_id }
return unless stat
@@ -374,11 +394,12 @@ class PostAlerter
group_id: stat[:group_id],
group_name: stat[:group_name],
inbox_count: stat[:inbox_count],
- username: user.username_lower
- }.to_json
+ username: user.username_lower,
+ }.to_json,
)
else
- Notification.where(user_id: user.id, notification_type: Notification.types[:group_message_summary])
+ Notification
+ .where(user_id: user.id, notification_type: Notification.types[:group_message_summary])
.where("data::json ->> 'group_id' = ?", stat[:group_id].to_s)
.delete_all
end
@@ -389,20 +410,31 @@ class PostAlerter
def should_notify_edit?(notification, post, opts)
notification.created_at < 1.day.ago ||
- notification.data_hash["display_username"] != (opts[:display_username].presence || post.user.username)
+ notification.data_hash["display_username"] !=
+ (opts[:display_username].presence || post.user.username)
end
def should_notify_like?(user, notification)
- return true if user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:always]
- return true if user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:first_time_and_daily] && notification.created_at < 1.day.ago
+ if user.user_option.like_notification_frequency ==
+ UserOption.like_notification_frequency_type[:always]
+ return true
+ end
+ if user.user_option.like_notification_frequency ==
+ UserOption.like_notification_frequency_type[:first_time_and_daily] &&
+ notification.created_at < 1.day.ago
+ return true
+ end
false
end
def should_notify_previous?(user, post, notification, opts)
case notification.notification_type
- when Notification.types[:edited] then should_notify_edit?(notification, post, opts)
- when Notification.types[:liked] then should_notify_like?(user, notification)
- else false
+ when Notification.types[:edited]
+ should_notify_edit?(notification, post, opts)
+ when Notification.types[:liked]
+ should_notify_like?(user, notification)
+ else
+ false
end
end
@@ -422,7 +454,11 @@ class PostAlerter
return if (topic = post.topic).blank?
is_liked = type == Notification.types[:liked]
- return if is_liked && user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:never]
+ if is_liked &&
+ user.user_option.like_notification_frequency ==
+ UserOption.like_notification_frequency_type[:never]
+ return
+ end
# Make sure the user can see the post
return unless Guardian.new(user).can_see?(post)
@@ -430,48 +466,60 @@ class PostAlerter
return if user.staged? && topic.category&.mailinglist_mirror?
notifier_id = opts[:user_id] || post.user_id # xxxxx look at revision history
- return if notifier_id && UserCommScreener.new(
- acting_user_id: notifier_id, target_user_ids: user.id
- ).ignoring_or_muting_actor?(user.id)
+ if notifier_id &&
+ UserCommScreener.new(
+ acting_user_id: notifier_id,
+ target_user_ids: user.id,
+ ).ignoring_or_muting_actor?(user.id)
+ return
+ end
# skip if muted on the topic
- return if TopicUser.where(
- topic: topic,
- user: user,
- notification_level: TopicUser.notification_levels[:muted]
- ).exists?
+ if TopicUser.where(
+ topic: topic,
+ user: user,
+ notification_level: TopicUser.notification_levels[:muted],
+ ).exists?
+ return
+ end
# skip if muted on the group
if group = opts[:group]
- return if GroupUser.where(
- group_id: opts[:group_id],
- user_id: user.id,
- notification_level: TopicUser.notification_levels[:muted]
- ).exists?
+ if GroupUser.where(
+ group_id: opts[:group_id],
+ user_id: user.id,
+ notification_level: TopicUser.notification_levels[:muted],
+ ).exists?
+ return
+ end
end
- existing_notifications = user.notifications
- .order("notifications.id DESC")
- .where(
- topic_id: post.topic_id,
- post_number: post.post_number
- ).limit(10)
+ existing_notifications =
+ user
+ .notifications
+ .order("notifications.id DESC")
+ .where(topic_id: post.topic_id, post_number: post.post_number)
+ .limit(10)
# Don't notify the same user about the same type of notification on the same post
- existing_notification_of_same_type = existing_notifications.find { |n| n.notification_type == type }
+ existing_notification_of_same_type =
+ existing_notifications.find { |n| n.notification_type == type }
- if existing_notification_of_same_type && !should_notify_previous?(user, post, existing_notification_of_same_type, opts)
+ if existing_notification_of_same_type &&
+ !should_notify_previous?(user, post, existing_notification_of_same_type, opts)
return
end
# linked, quoted, mentioned, chat_quoted may be suppressed if you already have a reply notification
if [
- Notification.types[:quoted],
- Notification.types[:linked],
- Notification.types[:mentioned],
- Notification.types[:chat_quoted]
- ].include?(type)
- return if existing_notifications.find { |n| n.notification_type == Notification.types[:replied] }
+ Notification.types[:quoted],
+ Notification.types[:linked],
+ Notification.types[:mentioned],
+ Notification.types[:chat_quoted],
+ ].include?(type)
+ if existing_notifications.find { |n| n.notification_type == Notification.types[:replied] }
+ return
+ end
end
collapsed = false
@@ -489,7 +537,7 @@ class PostAlerter
count = unread_count(user, topic)
if count > 1
I18n.with_locale(user.effective_locale) do
- opts[:display_username] = I18n.t('embed.replies', count: count)
+ opts[:display_username] = I18n.t("embed.replies", count: count)
end
end
end
@@ -513,9 +561,7 @@ class PostAlerter
display_username: opts[:display_username] || post.user.username,
}
- if opts[:custom_data]&.is_a?(Hash)
- opts[:custom_data].each { |k, v| notification_data[k] = v }
- end
+ opts[:custom_data].each { |k, v| notification_data[k] = v } if opts[:custom_data]&.is_a?(Hash)
if group = opts[:group]
notification_data[:group_id] = group.id
@@ -527,23 +573,29 @@ class PostAlerter
elsif original_post.via_email && (incoming_email = original_post.incoming_email)
skip_send_email =
incoming_email.to_addresses_split.include?(user.email) ||
- incoming_email.cc_addresses_split.include?(user.email)
+ incoming_email.cc_addresses_split.include?(user.email)
else
skip_send_email = opts[:skip_send_email]
end
# Create the notification
- created = user.notifications.consolidate_or_create!(
- notification_type: type,
- topic_id: post.topic_id,
- post_number: post.post_number,
- post_action_id: opts[:post_action_id],
- data: notification_data.to_json,
- skip_send_email: skip_send_email
- )
+ created =
+ user.notifications.consolidate_or_create!(
+ notification_type: type,
+ topic_id: post.topic_id,
+ post_number: post.post_number,
+ post_action_id: opts[:post_action_id],
+ data: notification_data.to_json,
+ skip_send_email: skip_send_email,
+ )
if created.id && existing_notifications.empty? && NOTIFIABLE_TYPES.include?(type)
- create_notification_alert(user: user, post: original_post, notification_type: type, username: original_username)
+ create_notification_alert(
+ user: user,
+ post: original_post,
+ notification_type: type,
+ username: original_username,
+ )
end
created.id ? created : nil
@@ -555,7 +607,7 @@ class PostAlerter
post: post,
notification_type: notification_type,
excerpt: excerpt,
- username: username
+ username: username,
)
end
@@ -566,11 +618,13 @@ class PostAlerter
def expand_group_mentions(groups, post)
return unless post.user && groups
- Group.mentionable(post.user, include_public: false).where(id: groups.map(&:id)).each do |group|
- next if group.user_count >= SiteSetting.max_users_notified_per_group_mention
- yield group, group.users
- end
-
+ Group
+ .mentionable(post.user, include_public: false)
+ .where(id: groups.map(&:id))
+ .each do |group|
+ next if group.user_count >= SiteSetting.max_users_notified_per_group_mention
+ yield group, group.users
+ end
end
def expand_here_mention(post, exclude_ids: nil)
@@ -583,9 +637,7 @@ class PostAlerter
posts = posts.where(post_type: Post.types[:regular])
end
- User.real
- .where(id: posts.select(:user_id))
- .limit(SiteSetting.max_here_mentioned)
+ User.real.where(id: posts.select(:user_id)).limit(SiteSetting.max_here_mentioned)
end
# TODO: Move to post-analyzer?
@@ -593,12 +645,16 @@ class PostAlerter
mentions = post.raw_mentions
return if mentions.blank?
- groups = Group.where('LOWER(name) IN (?)', mentions)
+ groups = Group.where("LOWER(name) IN (?)", mentions)
mentions -= groups.map(&:name).map(&:downcase)
groups = nil if groups.empty?
if mentions.present?
- users = User.where(username_lower: mentions).includes(:do_not_disturb_timings).where.not(id: post.user_id)
+ users =
+ User
+ .where(username_lower: mentions)
+ .includes(:do_not_disturb_timings)
+ .where.not(id: post.user_id)
users = nil if users.empty?
end
@@ -611,22 +667,28 @@ class PostAlerter
# TODO: Move to post-analyzer?
# Returns a list of users who were quoted in the post
def extract_quoted_users(post)
- usernames = if SiteSetting.display_name_on_posts && !SiteSetting.prioritize_username_in_ux
- post.raw.scan(/username:([[:alnum:]]*)"(?=\])/)
- else
- post.raw.scan(/\[quote=\"([^,]+),.+\"\]/)
- end.uniq.map { |q| q.first.strip.downcase }
+ usernames =
+ if SiteSetting.display_name_on_posts && !SiteSetting.prioritize_username_in_ux
+ post.raw.scan(/username:([[:alnum:]]*)"(?=\])/)
+ else
+ post.raw.scan(/\[quote=\"([^,]+),.+\"\]/)
+ end.uniq.map { |q| q.first.strip.downcase }
User.where.not(id: post.user_id).where(username_lower: usernames)
end
def extract_linked_users(post)
- users = post.topic_links.where(reflection: false).map do |link|
- linked_post = link.link_post
- if !linked_post && topic = link.link_topic
- linked_post = topic.posts.find_by(post_number: 1)
- end
- (linked_post && post.user_id != linked_post.user_id && linked_post.user) || nil
- end.compact
+ users =
+ post
+ .topic_links
+ .where(reflection: false)
+ .map do |link|
+ linked_post = link.link_post
+ if !linked_post && topic = link.link_topic
+ linked_post = topic.posts.find_by(post_number: 1)
+ end
+ (linked_post && post.user_id != linked_post.user_id && linked_post.user) || nil
+ end
+ .compact
DiscourseEvent.trigger(:after_extract_linked_users, users, post)
@@ -647,9 +709,7 @@ class PostAlerter
warn_if_not_sidekiq
DiscourseEvent.trigger(:before_create_notifications_for_users, users, post)
- users.each do |u|
- create_notification(u, Notification.types[type], post, opts)
- end
+ users.each { |u| create_notification(u, Notification.types[type], post, opts) }
users
end
@@ -681,7 +741,12 @@ class PostAlerter
DiscourseEvent.trigger(:before_create_notifications_for_users, users, post)
users.each do |user|
if reply_to_user == user || pm_watching_users(post).include?(user) || user.staged?
- create_notification(user, Notification.types[:private_message], post, skip_send_email_to: emails_to_skip_send)
+ create_notification(
+ user,
+ Notification.types[:private_message],
+ post,
+ skip_send_email_to: emails_to_skip_send,
+ )
end
end
@@ -711,17 +776,13 @@ class PostAlerter
return if !SiteSetting.enable_smtp || post.post_type != Post.types[:regular]
return if post.topic.allowed_groups.none?
- if post.topic.allowed_groups.count == 1
- return post.topic.first_smtp_enabled_group
- end
+ return post.topic.first_smtp_enabled_group if post.topic.allowed_groups.count == 1
topic_incoming_email = post.topic.incoming_email.first
return if topic_incoming_email.blank?
group = Group.find_by_email(topic_incoming_email.to_addresses)
- if !group&.smtp_enabled
- return post.topic.first_smtp_enabled_group
- end
+ return post.topic.first_smtp_enabled_group if !group&.smtp_enabled
group
end
@@ -735,9 +796,13 @@ class PostAlerter
# We need to use topic_allowed_users here instead of directly_targeted_users
# because we want to make sure the to_address goes to the OP of the topic.
- topic_allowed_users_by_age = post.topic.topic_allowed_users.includes(:user).order(:created_at).reject do |tau|
- not_allowed?(tau.user, post)
- end
+ topic_allowed_users_by_age =
+ post
+ .topic
+ .topic_allowed_users
+ .includes(:user)
+ .order(:created_at)
+ .reject { |tau| not_allowed?(tau.user, post) }
return emails_to_skip_send if topic_allowed_users_by_age.empty?
# This should usually be the OP of the topic, unless they are the one
@@ -778,7 +843,7 @@ class PostAlerter
group_id: group.id,
post_id: post.id,
email: to_address,
- cc_emails: cc_addresses
+ cc_emails: cc_addresses,
)
# Add the group's email_username into the array, because it is used for
@@ -790,7 +855,16 @@ class PostAlerter
emails_to_skip_send.uniq
end
- def notify_post_users(post, notified, group_ids: nil, include_topic_watchers: true, include_category_watchers: true, include_tag_watchers: true, new_record: false, notification_type: nil)
+ def notify_post_users(
+ post,
+ notified,
+ group_ids: nil,
+ include_topic_watchers: true,
+ include_category_watchers: true,
+ include_tag_watchers: true,
+ new_record: false,
+ notification_type: nil
+ )
return [] unless post.topic
warn_if_not_sidekiq
@@ -803,18 +877,15 @@ class PostAlerter
/*tags*/
)
SQL
- if include_topic_watchers
- condition.sub! "/*topic*/", <<~SQL
+ condition.sub! "/*topic*/", <<~SQL if include_topic_watchers
UNION
SELECT user_id
FROM topic_users
WHERE notification_level = :watching
AND topic_id = :topic_id
SQL
- end
- if include_category_watchers
- condition.sub! "/*category*/", <<~SQL
+ condition.sub! "/*category*/", <<~SQL if include_category_watchers
UNION
SELECT cu.user_id
@@ -825,12 +896,10 @@ class PostAlerter
AND cu.category_id = :category_id
AND (tu.user_id IS NULL OR tu.notification_level = :watching)
SQL
- end
- tag_ids = post.topic.topic_tags.pluck('topic_tags.tag_id')
+ tag_ids = post.topic.topic_tags.pluck("topic_tags.tag_id")
- if include_tag_watchers && tag_ids.present?
- condition.sub! "/*tags*/", <<~SQL
+ condition.sub! "/*tags*/", <<~SQL if include_tag_watchers && tag_ids.present?
UNION
SELECT tag_users.user_id
@@ -850,36 +919,36 @@ class PostAlerter
AND tag_users.tag_id IN (:tag_ids)
AND (tu.user_id IS NULL OR tu.notification_level = :watching))
SQL
- end
- notify = User.where(condition,
- watching: TopicUser.notification_levels[:watching],
- topic_id: post.topic_id,
- category_id: post.topic.category_id,
- tag_ids: tag_ids,
- staff_group_id: Group::AUTO_GROUPS[:staff],
- everyone_group_id: Group::AUTO_GROUPS[:everyone]
- )
+ notify =
+ User.where(
+ condition,
+ watching: TopicUser.notification_levels[:watching],
+ topic_id: post.topic_id,
+ category_id: post.topic.category_id,
+ tag_ids: tag_ids,
+ staff_group_id: Group::AUTO_GROUPS[:staff],
+ everyone_group_id: Group::AUTO_GROUPS[:everyone],
+ )
if group_ids.present?
notify = notify.joins(:group_users).where("group_users.group_id IN (?)", group_ids)
end
- if post.topic.private_message?
- notify = notify.where(staged: false).staff
- end
+ notify = notify.where(staged: false).staff if post.topic.private_message?
exclude_user_ids = notified.map(&:id)
notify = notify.where("users.id NOT IN (?)", exclude_user_ids) if exclude_user_ids.present?
DiscourseEvent.trigger(:before_create_notifications_for_users, notify, post)
- already_seen_user_ids = Set.new(
- TopicUser
- .where(topic_id: post.topic.id)
- .where("last_read_post_number >= ?", post.post_number)
- .pluck(:user_id)
- )
+ already_seen_user_ids =
+ Set.new(
+ TopicUser
+ .where(topic_id: post.topic.id)
+ .where("last_read_post_number >= ?", post.post_number)
+ .pluck(:user_id),
+ )
each_user_in_batches(notify) do |user|
calculated_type =
@@ -891,7 +960,8 @@ class PostAlerter
Notification.types[:posted]
end
opts = {}
- opts[:display_username] = post.last_editor.username if calculated_type == Notification.types[:edited]
+ opts[:display_username] = post.last_editor.username if calculated_type ==
+ Notification.types[:edited]
create_notification(user, calculated_type, post, opts)
end
@@ -899,20 +969,31 @@ class PostAlerter
end
def warn_if_not_sidekiq
- Rails.logger.warn("PostAlerter.#{caller_locations(1, 1)[0].label} was called outside of sidekiq") unless Sidekiq.server?
+ unless Sidekiq.server?
+ Rails.logger.warn(
+ "PostAlerter.#{caller_locations(1, 1)[0].label} was called outside of sidekiq",
+ )
+ end
end
private
def each_user_in_batches(users)
# This is race-condition-safe, unlike #find_in_batches
- users.pluck(:id).each_slice(USER_BATCH_SIZE) do |user_ids_batch|
- User.where(id: user_ids_batch).includes(:do_not_disturb_timings).each { |user| yield(user) }
- end
+ users
+ .pluck(:id)
+ .each_slice(USER_BATCH_SIZE) do |user_ids_batch|
+ User.where(id: user_ids_batch).includes(:do_not_disturb_timings).each { |user| yield(user) }
+ end
end
def create_pm_notification(user, post, emails_to_skip_send)
- create_notification(user, Notification.types[:private_message], post, skip_send_email_to: emails_to_skip_send)
+ create_notification(
+ user,
+ Notification.types[:private_message],
+ post,
+ skip_send_email_to: emails_to_skip_send,
+ )
end
def is_replying?(user, reply_to_user, quoted_users)
@@ -923,7 +1004,7 @@ class PostAlerter
TopicUser.exists?(
user_id: user.id,
topic_id: topic.id,
- notification_level: TopicUser.notification_levels[:watching]
+ notification_level: TopicUser.notification_levels[:watching],
)
end
end
diff --git a/app/services/post_bookmarkable.rb b/app/services/post_bookmarkable.rb
index 09373f6e99a..97086d9ba40 100644
--- a/app/services/post_bookmarkable.rb
+++ b/app/services/post_bookmarkable.rb
@@ -18,23 +18,26 @@ class PostBookmarkable < BaseBookmarkable
def self.list_query(user, guardian)
topics = Topic.listable_topics.secured(guardian)
pms = Topic.private_messages_for_user(user)
- post_bookmarks = user
- .bookmarks_of_type("Post")
- .joins("INNER JOIN posts ON posts.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'")
- .joins("LEFT JOIN topics ON topics.id = posts.topic_id")
- .joins("LEFT JOIN topic_users ON topic_users.topic_id = topics.id")
- .where("topic_users.user_id = ?", user.id)
+ post_bookmarks =
+ user
+ .bookmarks_of_type("Post")
+ .joins(
+ "INNER JOIN posts ON posts.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'",
+ )
+ .joins("LEFT JOIN topics ON topics.id = posts.topic_id")
+ .joins("LEFT JOIN topic_users ON topic_users.topic_id = topics.id")
+ .where("topic_users.user_id = ?", user.id)
guardian.filter_allowed_categories(
- post_bookmarks.merge(topics.or(pms)).merge(Post.secured(guardian))
+ post_bookmarks.merge(topics.or(pms)).merge(Post.secured(guardian)),
)
end
def self.search_query(bookmarks, query, ts_query, &bookmarkable_search)
bookmarkable_search.call(
bookmarks.joins(
- "LEFT JOIN post_search_data ON post_search_data.post_id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'"
+ "LEFT JOIN post_search_data ON post_search_data.post_id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'",
),
- "#{ts_query} @@ post_search_data.search_data"
+ "#{ts_query} @@ post_search_data.search_data",
)
end
@@ -45,8 +48,8 @@ class PostBookmarkable < BaseBookmarkable
post_number: bookmark.bookmarkable.post_number,
data: {
title: bookmark.bookmarkable.topic.title,
- bookmarkable_url: bookmark.bookmarkable.url
- }
+ bookmarkable_url: bookmark.bookmarkable.url,
+ },
)
end
@@ -59,14 +62,14 @@ class PostBookmarkable < BaseBookmarkable
end
def self.bookmark_metadata(bookmark, user)
- { topic_bookmarked: Bookmark.for_user_in_topic(user.id, bookmark.bookmarkable.topic_id).exists? }
+ {
+ topic_bookmarked: Bookmark.for_user_in_topic(user.id, bookmark.bookmarkable.topic_id).exists?,
+ }
end
def self.validate_before_create(guardian, bookmarkable)
- if bookmarkable.blank? ||
- bookmarkable.topic.blank? ||
- !guardian.can_see_topic?(bookmarkable.topic) ||
- !guardian.can_see_post?(bookmarkable)
+ if bookmarkable.blank? || bookmarkable.topic.blank? ||
+ !guardian.can_see_topic?(bookmarkable.topic) || !guardian.can_see_post?(bookmarkable)
raise Discourse::InvalidAccess
end
end
diff --git a/app/services/post_owner_changer.rb b/app/services/post_owner_changer.rb
index 702e6a8a178..7880aa95f25 100644
--- a/app/services/post_owner_changer.rb
+++ b/app/services/post_owner_changer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class PostOwnerChanger
-
def initialize(params)
@post_ids = params[:post_ids]
@topic = Topic.with_deleted.find_by(id: params[:topic_id].to_i)
@@ -9,7 +8,7 @@ class PostOwnerChanger
@acting_user = params[:acting_user]
@skip_revision = params[:skip_revision] || false
- [:post_ids, :topic, :new_owner, :acting_user].each do |arg|
+ %i[post_ids topic new_owner acting_user].each do |arg|
raise ArgumentError.new(arg) if self.instance_variable_get("@#{arg}").blank?
end
end
@@ -28,20 +27,31 @@ class PostOwnerChanger
PostActionDestroyer.destroy(@new_owner, post, :like, skip_delete_check: true)
level = post.is_first_post? ? :watching : :tracking
- TopicUser.change(@new_owner.id, @topic.id, notification_level: NotificationLevels.topic_levels[level], posted: true)
+ TopicUser.change(
+ @new_owner.id,
+ @topic.id,
+ notification_level: NotificationLevels.topic_levels[level],
+ posted: true,
+ )
- if post == @topic.posts.order("post_number DESC").where("NOT hidden AND posts.deleted_at IS NULL").first
+ if post ==
+ @topic
+ .posts
+ .order("post_number DESC")
+ .where("NOT hidden AND posts.deleted_at IS NULL")
+ .first
@topic.last_poster = @new_owner
end
@topic.update_statistics
@new_owner.user_stat.update(
- first_post_created_at: @new_owner.reload.posts.order('created_at ASC').first&.created_at
+ first_post_created_at: @new_owner.reload.posts.order("created_at ASC").first&.created_at,
)
- Post.where(topic_id: @topic.id, reply_to_post_number: post.post_number)
- .update_all(reply_to_user_id: @new_owner.id)
+ Post.where(topic_id: @topic.id, reply_to_post_number: post.post_number).update_all(
+ reply_to_user_id: @new_owner.id,
+ )
@topic.save!(validate: false)
end
diff --git a/app/services/push_notification_pusher.rb b/app/services/push_notification_pusher.rb
index a0b70935448..736f3ea2bf6 100644
--- a/app/services/push_notification_pusher.rb
+++ b/app/services/push_notification_pusher.rb
@@ -8,30 +8,36 @@ class PushNotificationPusher
message = nil
I18n.with_locale(user.effective_locale) do
notification_icon_name = Notification.types[payload[:notification_type]]
- if !File.exist?(File.expand_path("../../app/assets/images/push-notifications/#{notification_icon_name}.png", __dir__))
+ if !File.exist?(
+ File.expand_path(
+ "../../app/assets/images/push-notifications/#{notification_icon_name}.png",
+ __dir__,
+ ),
+ )
notification_icon_name = "discourse"
end
- notification_icon = ActionController::Base.helpers.image_url("push-notifications/#{notification_icon_name}.png")
+ notification_icon =
+ ActionController::Base.helpers.image_url("push-notifications/#{notification_icon_name}.png")
message = {
- title: payload[:translated_title] || I18n.t(
- "discourse_push_notifications.popup.#{Notification.types[payload[:notification_type]]}",
- site_title: SiteSetting.title,
- topic: payload[:topic_title],
- username: payload[:username]
- ),
+ title:
+ payload[:translated_title] ||
+ I18n.t(
+ "discourse_push_notifications.popup.#{Notification.types[payload[:notification_type]]}",
+ site_title: SiteSetting.title,
+ topic: payload[:topic_title],
+ username: payload[:username],
+ ),
body: payload[:excerpt],
badge: get_badge,
icon: notification_icon,
tag: payload[:tag] || "#{Discourse.current_hostname}-#{payload[:topic_id]}",
base_url: Discourse.base_url,
url: payload[:post_url],
- hide_when_active: true
+ hide_when_active: true,
}
- subscriptions(user).each do |subscription|
- send_notification(user, subscription, message)
- end
+ subscriptions(user).each { |subscription| send_notification(user, subscription, message) }
end
message
@@ -50,21 +56,22 @@ class PushNotificationPusher
subscriptions = PushSubscription.where(user: user, data: data)
subscriptions_count = subscriptions.count
- new_subscription = if subscriptions_count > 1
- subscriptions.destroy_all
- PushSubscription.create!(user: user, data: data)
- elsif subscriptions_count == 0
- PushSubscription.create!(user: user, data: data)
- end
+ new_subscription =
+ if subscriptions_count > 1
+ subscriptions.destroy_all
+ PushSubscription.create!(user: user, data: data)
+ elsif subscriptions_count == 0
+ PushSubscription.create!(user: user, data: data)
+ end
if send_confirmation == "true"
message = {
- title: I18n.t("discourse_push_notifications.popup.confirm_title",
- site_title: SiteSetting.title),
+ title:
+ I18n.t("discourse_push_notifications.popup.confirm_title", site_title: SiteSetting.title),
body: I18n.t("discourse_push_notifications.popup.confirm_body"),
icon: ActionController::Base.helpers.image_url("push-notifications/check.png"),
badge: get_badge,
- tag: "#{Discourse.current_hostname}-subscription"
+ tag: "#{Discourse.current_hostname}-subscription",
}
send_notification(user, new_subscription, message)
@@ -84,7 +91,7 @@ class PushNotificationPusher
end
MAX_ERRORS ||= 3
- MIN_ERROR_DURATION ||= 86400 # 1 day
+ MIN_ERROR_DURATION ||= 86_400 # 1 day
def self.handle_generic_error(subscription, error, user, endpoint, message)
subscription.error_count += 1
@@ -103,8 +110,8 @@ class PushNotificationPusher
env: {
user_id: user.id,
endpoint: endpoint,
- message: message.to_json
- }
+ message: message.to_json,
+ },
)
end
@@ -130,11 +137,11 @@ class PushNotificationPusher
subject: Discourse.base_url,
public_key: SiteSetting.vapid_public_key,
private_key: SiteSetting.vapid_private_key,
- expiration: TOKEN_VALID_FOR_SECONDS
+ expiration: TOKEN_VALID_FOR_SECONDS,
},
open_timeout: CONNECTION_TIMEOUT_SECONDS,
read_timeout: CONNECTION_TIMEOUT_SECONDS,
- ssl_timeout: CONNECTION_TIMEOUT_SECONDS
+ ssl_timeout: CONNECTION_TIMEOUT_SECONDS,
)
if subscription.first_error_at || subscription.error_count != 0
@@ -155,5 +162,4 @@ class PushNotificationPusher
private_class_method :send_notification
private_class_method :handle_generic_error
-
end
diff --git a/app/services/random_topic_selector.rb b/app/services/random_topic_selector.rb
index 8b8d121befe..85f3334864a 100644
--- a/app/services/random_topic_selector.rb
+++ b/app/services/random_topic_selector.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class RandomTopicSelector
-
BACKFILL_SIZE = 3000
BACKFILL_LOW_WATER_MARK = 500
@@ -11,7 +10,7 @@ class RandomTopicSelector
options = {
per_page: category ? category.num_featured_topics : 3,
visible: true,
- no_definitions: true
+ no_definitions: true,
}
options[:except_topic_ids] = [category.topic_id] if exclude
@@ -20,9 +19,7 @@ class RandomTopicSelector
options[:category] = category.id
# NOTE: at the moment this site setting scopes tightly to a category (excluding subcats)
# this is done so we don't populate a junk cache
- if SiteSetting.limit_suggested_to_category
- options[:no_subcategories] = true
- end
+ options[:no_subcategories] = true if SiteSetting.limit_suggested_to_category
# don't leak private categories into the "everything" group
options[:guardian] = Guardian.new(Discourse.system_user)
@@ -30,12 +27,15 @@ class RandomTopicSelector
query = TopicQuery.new(nil, options)
- results = query.latest_results.order('RANDOM()')
- .where(closed: false, archived: false)
- .where("topics.created_at > ?", SiteSetting.suggested_topics_max_days_old.days.ago)
- .limit(BACKFILL_SIZE)
- .reorder('RANDOM()')
- .pluck(:id)
+ results =
+ query
+ .latest_results
+ .order("RANDOM()")
+ .where(closed: false, archived: false)
+ .where("topics.created_at > ?", SiteSetting.suggested_topics_max_days_old.days.ago)
+ .limit(BACKFILL_SIZE)
+ .reorder("RANDOM()")
+ .pluck(:id)
key = cache_key(category)
@@ -56,10 +56,11 @@ class RandomTopicSelector
return results if count < 1
- results = Discourse.redis.multi do |transaction|
- transaction.lrange(key, 0, count - 1)
- transaction.ltrim(key, count, -1)
- end
+ results =
+ Discourse.redis.multi do |transaction|
+ transaction.lrange(key, 0, count - 1)
+ transaction.ltrim(key, count, -1)
+ end
if !results.is_a?(Array) # Redis is in readonly mode
results = Discourse.redis.lrange(key, 0, count - 1)
@@ -81,9 +82,7 @@ class RandomTopicSelector
end
if !backfilled && Discourse.redis.llen(key) < BACKFILL_LOW_WATER_MARK
- Scheduler::Defer.later("backfill") do
- backfill(category)
- end
+ Scheduler::Defer.later("backfill") { backfill(category) }
end
results
@@ -96,5 +95,4 @@ class RandomTopicSelector
def self.clear_cache!
Discourse.redis.delete_prefixed(cache_key)
end
-
end
diff --git a/app/services/registered_bookmarkable.rb b/app/services/registered_bookmarkable.rb
index fc40dee521e..50cd45735a9 100644
--- a/app/services/registered_bookmarkable.rb
+++ b/app/services/registered_bookmarkable.rb
@@ -65,12 +65,10 @@ class RegisteredBookmarkable
return if bookmarks_of_type.empty?
if bookmarkable_klass.has_preloads?
- ActiveRecord::Associations::Preloader
- .new(
- records: bookmarks_of_type,
- associations: [bookmarkable: bookmarkable_klass.preload_associations]
- )
- .call
+ ActiveRecord::Associations::Preloader.new(
+ records: bookmarks_of_type,
+ associations: [bookmarkable: bookmarkable_klass.preload_associations],
+ ).call
end
bookmarkable_klass.perform_custom_preload!(bookmarks_of_type, guardian)
diff --git a/app/services/search_indexer.rb b/app/services/search_indexer.rb
index 33d18b41c9a..a17ac7b34ba 100644
--- a/app/services/search_indexer.rb
+++ b/app/services/search_indexer.rb
@@ -17,25 +17,17 @@ class SearchIndexer
@disabled = false
end
- def self.update_index(table: , id: , a_weight: nil, b_weight: nil, c_weight: nil, d_weight: nil)
- raw_data = {
- a: a_weight,
- b: b_weight,
- c: c_weight,
- d: d_weight,
- }
+ def self.update_index(table:, id:, a_weight: nil, b_weight: nil, c_weight: nil, d_weight: nil)
+ raw_data = { a: a_weight, b: b_weight, c: c_weight, d: d_weight }
# The version used in excerpts
- search_data = raw_data.transform_values do |data|
- Search.prepare_data(data || "", :index)
- end
+ search_data = raw_data.transform_values { |data| Search.prepare_data(data || "", :index) }
# The version used to build the index
- indexed_data = search_data.transform_values do |data|
- data.gsub(/\S+/) { |word|
- word[0...SiteSetting.search_max_indexed_word_length]
- }
- end
+ indexed_data =
+ search_data.transform_values do |data|
+ data.gsub(/\S+/) { |word| word[0...SiteSetting.search_max_indexed_word_length] }
+ end
table_name = "#{table}_search_data"
foreign_key = "#{table}_id"
@@ -53,30 +45,32 @@ class SearchIndexer
tsvector = DB.query_single("SELECT #{ranked_index}", indexed_data)[0]
additional_lexemes = []
- tsvector.scan(/'(([a-zA-Z0-9]+\.)+[a-zA-Z0-9]+)'\:([\w+,]+)/).reduce(additional_lexemes) do |array, (lexeme, _, positions)|
- count = 0
+ tsvector
+ .scan(/'(([a-zA-Z0-9]+\.)+[a-zA-Z0-9]+)'\:([\w+,]+)/)
+ .reduce(additional_lexemes) do |array, (lexeme, _, positions)|
+ count = 0
- if lexeme !~ /^(\d+\.)?(\d+\.)*(\*|\d+)$/
- loop do
- count += 1
- break if count >= 10 # Safeguard here to prevent infinite loop when a term has many dots
- term, _, remaining = lexeme.partition(".")
- break if remaining.blank?
- array << "'#{remaining}':#{positions}"
- lexeme = remaining
+ if lexeme !~ /^(\d+\.)?(\d+\.)*(\*|\d+)$/
+ loop do
+ count += 1
+ break if count >= 10 # Safeguard here to prevent infinite loop when a term has many dots
+ term, _, remaining = lexeme.partition(".")
+ break if remaining.blank?
+ array << "'#{remaining}':#{positions}"
+ lexeme = remaining
+ end
end
+
+ array
end
- array
- end
-
- tsvector = "#{tsvector} #{additional_lexemes.join(' ')}"
+ tsvector = "#{tsvector} #{additional_lexemes.join(" ")}"
indexed_data =
if table.to_s == "post"
clean_post_raw_data!(search_data[:d])
else
- search_data.values.select { |d| d.length > 0 }.join(' ')
+ search_data.values.select { |d| d.length > 0 }.join(" ")
end
params = {
@@ -99,7 +93,9 @@ class SearchIndexer
Discourse.warn_exception(
e,
message: "Unexpected error while indexing #{table} for search",
- env: { id: id }
+ env: {
+ id: id,
+ },
)
end
end
@@ -108,16 +104,23 @@ class SearchIndexer
# a bit inconsistent that we use title as A and body as B when in
# the post index body is D
update_index(
- table: 'topic',
+ table: "topic",
id: topic_id,
a_weight: title,
- b_weight: HtmlScrubber.scrub(cooked)[0...Topic::MAX_SIMILAR_BODY_LENGTH]
+ b_weight: HtmlScrubber.scrub(cooked)[0...Topic::MAX_SIMILAR_BODY_LENGTH],
)
end
- def self.update_posts_index(post_id:, topic_title:, category_name:, topic_tags:, cooked:, private_message:)
+ def self.update_posts_index(
+ post_id:,
+ topic_title:,
+ category_name:,
+ topic_tags:,
+ cooked:,
+ private_message:
+ )
update_index(
- table: 'post',
+ table: "post",
id: post_id,
a_weight: topic_title,
b_weight: category_name,
@@ -126,36 +129,26 @@ class SearchIndexer
# the original string. Since there is no way to estimate the length of
# the expected tsvector, we limit the input to ~50% of the maximum
# length of a tsvector (1_048_576 bytes).
- d_weight: HtmlScrubber.scrub(cooked)[0..600_000]
- ) do |params|
- params["private_message"] = private_message
- end
+ d_weight: HtmlScrubber.scrub(cooked)[0..600_000],
+ ) { |params| params["private_message"] = private_message }
end
def self.update_users_index(user_id, username, name, custom_fields)
update_index(
- table: 'user',
+ table: "user",
id: user_id,
a_weight: username,
b_weight: name,
- c_weight: custom_fields
+ c_weight: custom_fields,
)
end
def self.update_categories_index(category_id, name)
- update_index(
- table: 'category',
- id: category_id,
- a_weight: name
- )
+ update_index(table: "category", id: category_id, a_weight: name)
end
def self.update_tags_index(tag_id, name)
- update_index(
- table: 'tag',
- id: tag_id,
- a_weight: name.downcase
- )
+ update_index(table: "tag", id: tag_id, a_weight: name.downcase)
end
def self.queue_category_posts_reindex(category_id)
@@ -213,17 +206,13 @@ class SearchIndexer
tags = topic.tags.select(:id, :name).to_a
if tags.present?
- tag_names = (tags.map(&:name) + Tag.where(target_tag_id: tags.map(&:id)).pluck(:name)).join(' ')
+ tag_names =
+ (tags.map(&:name) + Tag.where(target_tag_id: tags.map(&:id)).pluck(:name)).join(" ")
end
end
if Post === obj && obj.raw.present? &&
- (
- force ||
- obj.saved_change_to_cooked? ||
- obj.saved_change_to_topic_id?
- )
-
+ (force || obj.saved_change_to_cooked? || obj.saved_change_to_topic_id?)
if topic
SearchIndexer.update_posts_index(
post_id: obj.id,
@@ -231,7 +220,7 @@ class SearchIndexer
category_name: category_name,
topic_tags: tag_names,
cooked: obj.cooked,
- private_message: topic.private_message?
+ private_message: topic.private_message?,
)
SearchIndexer.update_topics_index(topic.id, topic.title, obj.cooked) if obj.is_first_post?
@@ -239,10 +228,12 @@ class SearchIndexer
end
if User === obj && (obj.saved_change_to_username? || obj.saved_change_to_name? || force)
- SearchIndexer.update_users_index(obj.id,
- obj.username_lower || '',
- obj.name ? obj.name.downcase : '',
- obj.user_custom_fields.searchable.map(&:value).join(" "))
+ SearchIndexer.update_users_index(
+ obj.id,
+ obj.username_lower || "",
+ obj.name ? obj.name.downcase : "",
+ obj.user_custom_fields.searchable.map(&:value).join(" "),
+ )
end
if Topic === obj && (obj.saved_change_to_title? || force)
@@ -254,7 +245,7 @@ class SearchIndexer
category_name: category_name,
topic_tags: tag_names,
cooked: post.cooked,
- private_message: obj.private_message?
+ private_message: obj.private_message?,
)
SearchIndexer.update_topics_index(obj.id, obj.title, post.cooked)
@@ -293,7 +284,6 @@ class SearchIndexer
private_class_method :clean_post_raw_data!
class HtmlScrubber < Nokogiri::XML::SAX::Document
-
attr_reader :scrubbed
def initialize
@@ -304,63 +294,55 @@ class SearchIndexer
return +"" if html.blank?
begin
- document = Nokogiri::HTML5("#{html}
", nil, Encoding::UTF_8.to_s)
+ document = Nokogiri.HTML5("#{html}
", nil, Encoding::UTF_8.to_s)
rescue ArgumentError
return +""
end
- nodes = document.css(
- "div.#{CookedPostProcessor::LIGHTBOX_WRAPPER_CSS_CLASS}"
- )
+ nodes = document.css("div.#{CookedPostProcessor::LIGHTBOX_WRAPPER_CSS_CLASS}")
if nodes.present?
nodes.each do |node|
node.traverse do |child_node|
next if child_node == node
- if %w{a img}.exclude?(child_node.name)
+ if %w[a img].exclude?(child_node.name)
child_node.remove
elsif child_node.name == "a"
- ATTRIBUTES.each do |attribute|
- child_node.remove_attribute(attribute)
- end
+ ATTRIBUTES.each { |attribute| child_node.remove_attribute(attribute) }
end
end
end
end
- document.css("img.emoji").each do |node|
- node.remove_attribute("alt")
- end
+ document.css("img.emoji").each { |node| node.remove_attribute("alt") }
- document.css("a[href]").each do |node|
- if node["href"] == node.text || MENTION_CLASSES.include?(node["class"])
- node.remove_attribute("href")
- end
+ document
+ .css("a[href]")
+ .each do |node|
+ if node["href"] == node.text || MENTION_CLASSES.include?(node["class"])
+ node.remove_attribute("href")
+ end
- if node["class"] == "anchor" && node["href"].starts_with?("#")
- node.remove_attribute("href")
+ if node["class"] == "anchor" && node["href"].starts_with?("#")
+ node.remove_attribute("href")
+ end
end
- end
html_scrubber = new
Nokogiri::HTML::SAX::Parser.new(html_scrubber).parse(document.to_html)
html_scrubber.scrubbed.squish
end
- MENTION_CLASSES ||= %w{mention mention-group}
- ATTRIBUTES ||= %w{alt title href data-youtube-title}
+ MENTION_CLASSES ||= %w[mention mention-group]
+ ATTRIBUTES ||= %w[alt title href data-youtube-title]
def start_element(_name, attributes = [])
attributes = Hash[*attributes.flatten]
ATTRIBUTES.each do |attribute_name|
if attributes[attribute_name].present? &&
- !(
- attribute_name == "href" &&
- UrlHelper.is_local(attributes[attribute_name])
- )
-
+ !(attribute_name == "href" && UrlHelper.is_local(attributes[attribute_name]))
characters(attributes[attribute_name])
end
end
diff --git a/app/services/sidebar_section_links_updater.rb b/app/services/sidebar_section_links_updater.rb
index 98d0d768576..b3faacb4f08 100644
--- a/app/services/sidebar_section_links_updater.rb
+++ b/app/services/sidebar_section_links_updater.rb
@@ -3,23 +3,21 @@
class SidebarSectionLinksUpdater
def self.update_category_section_links(user, category_ids:)
if category_ids.blank?
- delete_section_links(user: user, linkable_type: 'Category')
+ delete_section_links(user: user, linkable_type: "Category")
else
category_ids = Category.secured(Guardian.new(user)).where(id: category_ids).pluck(:id)
- update_section_links(user: user, linkable_type: 'Category', new_linkable_ids: category_ids)
+ update_section_links(user: user, linkable_type: "Category", new_linkable_ids: category_ids)
end
end
def self.update_tag_section_links(user, tag_names:)
if tag_names.blank?
- delete_section_links(user: user, linkable_type: 'Tag')
+ delete_section_links(user: user, linkable_type: "Tag")
else
- tag_ids = DiscourseTagging
- .filter_visible(Tag, Guardian.new(user))
- .where(name: tag_names)
- .pluck(:id)
+ tag_ids =
+ DiscourseTagging.filter_visible(Tag, Guardian.new(user)).where(name: tag_names).pluck(:id)
- update_section_links(user: user, linkable_type: 'Tag', new_linkable_ids: tag_ids)
+ update_section_links(user: user, linkable_type: "Tag", new_linkable_ids: tag_ids)
end
end
@@ -30,20 +28,24 @@ class SidebarSectionLinksUpdater
def self.update_section_links(user:, linkable_type:, new_linkable_ids:)
SidebarSectionLink.transaction do
- existing_linkable_ids = SidebarSectionLink.where(user: user, linkable_type: linkable_type).pluck(:linkable_id)
+ existing_linkable_ids =
+ SidebarSectionLink.where(user: user, linkable_type: linkable_type).pluck(:linkable_id)
to_delete = existing_linkable_ids - new_linkable_ids
to_insert = new_linkable_ids - existing_linkable_ids
- to_insert_attributes = to_insert.map do |linkable_id|
- {
- linkable_type: linkable_type,
- linkable_id: linkable_id,
- user_id: user.id
- }
- end
+ to_insert_attributes =
+ to_insert.map do |linkable_id|
+ { linkable_type: linkable_type, linkable_id: linkable_id, user_id: user.id }
+ end
- SidebarSectionLink.where(user: user, linkable_type: linkable_type, linkable_id: to_delete).delete_all if to_delete.present?
+ if to_delete.present?
+ SidebarSectionLink.where(
+ user: user,
+ linkable_type: linkable_type,
+ linkable_id: to_delete,
+ ).delete_all
+ end
SidebarSectionLink.insert_all(to_insert_attributes) if to_insert_attributes.present?
end
end
diff --git a/app/services/sidebar_site_settings_backfiller.rb b/app/services/sidebar_site_settings_backfiller.rb
index 884ff765468..7fe13f8162b 100644
--- a/app/services/sidebar_site_settings_backfiller.rb
+++ b/app/services/sidebar_site_settings_backfiller.rb
@@ -14,21 +14,17 @@ class SidebarSiteSettingsBackfiller
@linkable_klass, previous_ids, new_ids =
case setting_name
when "default_sidebar_categories"
- [
- Category,
- previous_value.split("|"),
- new_value.split("|")
- ]
+ [Category, previous_value.split("|"), new_value.split("|")]
when "default_sidebar_tags"
klass = Tag
[
klass,
klass.where(name: previous_value.split("|")).pluck(:id),
- klass.where(name: new_value.split("|")).pluck(:id)
+ klass.where(name: new_value.split("|")).pluck(:id),
]
else
- raise 'Invalid setting_name'
+ raise "Invalid setting_name"
end
@added_ids = new_ids - previous_ids
@@ -37,34 +33,43 @@ class SidebarSiteSettingsBackfiller
def backfill!
DistributedMutex.synchronize("backfill_sidebar_site_settings_#{@setting_name}") do
- SidebarSectionLink.where(linkable_type: @linkable_klass.to_s, linkable_id: @removed_ids).delete_all
+ SidebarSectionLink.where(
+ linkable_type: @linkable_klass.to_s,
+ linkable_id: @removed_ids,
+ ).delete_all
- User.real.where(staged: false).select(:id).find_in_batches do |users|
- rows = []
+ User
+ .real
+ .where(staged: false)
+ .select(:id)
+ .find_in_batches do |users|
+ rows = []
- users.each do |user|
- @added_ids.each do |linkable_id|
- rows << { user_id: user[:id], linkable_type: @linkable_klass.to_s, linkable_id: linkable_id }
+ users.each do |user|
+ @added_ids.each do |linkable_id|
+ rows << {
+ user_id: user[:id],
+ linkable_type: @linkable_klass.to_s,
+ linkable_id: linkable_id,
+ }
+ end
end
- end
- SidebarSectionLink.insert_all(rows) if rows.present?
- end
+ SidebarSectionLink.insert_all(rows) if rows.present?
+ end
end
end
def number_of_users_to_backfill
select_statements = []
- if @removed_ids.present?
- select_statements.push(<<~SQL)
+ select_statements.push(<<~SQL) if @removed_ids.present?
SELECT
sidebar_section_links.user_id
FROM sidebar_section_links
WHERE sidebar_section_links.linkable_type = '#{@linkable_klass.to_s}'
AND sidebar_section_links.linkable_id IN (#{@removed_ids.join(",")})
SQL
- end
if @added_ids.present?
# Returns the ids of users that will receive the new additions by excluding the users that already have the additions
diff --git a/app/services/site_settings_task.rb b/app/services/site_settings_task.rb
index 356d8eccf14..35d94378fba 100644
--- a/app/services/site_settings_task.rb
+++ b/app/services/site_settings_task.rb
@@ -16,7 +16,7 @@ class SiteSettingsTask
counts = { updated: 0, not_found: 0, errors: 0 }
log = []
- site_settings = YAML::safe_load(yml)
+ site_settings = YAML.safe_load(yml)
site_settings.each do |site_setting|
key = site_setting[0]
val = site_setting[1]
diff --git a/app/services/spam_rule/auto_silence.rb b/app/services/spam_rule/auto_silence.rb
index 81acb86cd2e..76f481b9634 100644
--- a/app/services/spam_rule/auto_silence.rb
+++ b/app/services/spam_rule/auto_silence.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class SpamRule::AutoSilence
-
attr_reader :group_message
def initialize(user, post = nil)
@@ -10,9 +9,7 @@ class SpamRule::AutoSilence
end
def perform
- I18n.with_locale(SiteSetting.default_locale) do
- silence_user if should_autosilence?
- end
+ I18n.with_locale(SiteSetting.default_locale) { silence_user if should_autosilence? }
end
def self.prevent_posting?(user)
@@ -36,7 +33,7 @@ class SpamRule::AutoSilence
user_id: @user.id,
spam_type: PostActionType.types[:spam],
pending: ReviewableScore.statuses[:pending],
- agreed: ReviewableScore.statuses[:agreed]
+ agreed: ReviewableScore.statuses[:agreed],
}
result = DB.query(<<~SQL, params)
@@ -53,23 +50,30 @@ class SpamRule::AutoSilence
end
def flagged_post_ids
- Post.where(user_id: @user.id)
- .where('spam_count > 0 OR off_topic_count > 0 OR inappropriate_count > 0')
+ Post
+ .where(user_id: @user.id)
+ .where("spam_count > 0 OR off_topic_count > 0 OR inappropriate_count > 0")
.pluck(:id)
end
def silence_user
Post.transaction do
-
- silencer = UserSilencer.new(
- @user,
- Discourse.system_user,
- message: :too_many_spam_flags,
- post_id: @post&.id
- )
+ silencer =
+ UserSilencer.new(
+ @user,
+ Discourse.system_user,
+ message: :too_many_spam_flags,
+ post_id: @post&.id,
+ )
if silencer.silence && SiteSetting.notify_mods_when_user_silenced
- @group_message = GroupMessage.create(Group[:moderators].name, :user_automatically_silenced, user: @user, limit_once_per: false)
+ @group_message =
+ GroupMessage.create(
+ Group[:moderators].name,
+ :user_automatically_silenced,
+ user: @user,
+ limit_once_per: false,
+ )
end
end
end
diff --git a/app/services/spam_rule/flag_sockpuppets.rb b/app/services/spam_rule/flag_sockpuppets.rb
index c51d67f4022..2a8cd2772e6 100644
--- a/app/services/spam_rule/flag_sockpuppets.rb
+++ b/app/services/spam_rule/flag_sockpuppets.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class SpamRule::FlagSockpuppets
-
def initialize(post)
@post = post
end
@@ -21,23 +20,20 @@ class SpamRule::FlagSockpuppets
return false if @post.try(:post_number) == 1
return false if first_post.user.nil?
- !first_post.user.staff? &&
- !@post.user.staff? &&
- !first_post.user.staged? &&
- !@post.user.staged? &&
- @post.user != first_post.user &&
- @post.user.ip_address == first_post.user.ip_address &&
- @post.user.new_user? &&
- !ScreenedIpAddress.is_allowed?(@post.user.ip_address)
+ !first_post.user.staff? && !@post.user.staff? && !first_post.user.staged? &&
+ !@post.user.staged? && @post.user != first_post.user &&
+ @post.user.ip_address == first_post.user.ip_address && @post.user.new_user? &&
+ !ScreenedIpAddress.is_allowed?(@post.user.ip_address)
end
def flag_sockpuppet_users
- message = I18n.t(
- 'flag_reason.sockpuppet',
- ip_address: @post.user.ip_address,
- base_path: Discourse.base_path,
- locale: SiteSetting.default_locale
- )
+ message =
+ I18n.t(
+ "flag_reason.sockpuppet",
+ ip_address: @post.user.ip_address,
+ base_path: Discourse.base_path,
+ locale: SiteSetting.default_locale,
+ )
flag_post(@post, message)
@@ -55,5 +51,4 @@ class SpamRule::FlagSockpuppets
def first_post
@first_post ||= @post.topic.posts.by_post_number.first
end
-
end
diff --git a/app/services/staff_action_logger.rb b/app/services/staff_action_logger.rb
index a4203452bb7..70c937e5613 100644
--- a/app/services/staff_action_logger.rb
+++ b/app/services/staff_action_logger.rb
@@ -2,9 +2,8 @@
# Responsible for logging the actions of admins and moderators.
class StaffActionLogger
-
def self.base_attrs
- [:topic_id, :post_id, :context, :subject, :ip_address, :previous_value, :new_value]
+ %i[topic_id post_id context subject ip_address previous_value new_value]
end
def initialize(admin)
@@ -12,20 +11,22 @@ class StaffActionLogger
raise Discourse::InvalidParameters.new(:admin) unless @admin && @admin.is_a?(User)
end
- USER_FIELDS ||= %i{id username name created_at trust_level last_seen_at last_emailed_at}
+ USER_FIELDS ||= %i[id username name created_at trust_level last_seen_at last_emailed_at]
def log_user_deletion(deleted_user, opts = {})
- raise Discourse::InvalidParameters.new(:deleted_user) unless deleted_user && deleted_user.is_a?(User)
+ unless deleted_user && deleted_user.is_a?(User)
+ raise Discourse::InvalidParameters.new(:deleted_user)
+ end
- details = USER_FIELDS.map do |x|
- "#{x}: #{deleted_user.public_send(x)}"
- end.join("\n")
+ details = USER_FIELDS.map { |x| "#{x}: #{deleted_user.public_send(x)}" }.join("\n")
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:delete_user],
- ip_address: deleted_user.ip_address.to_s,
- details: details
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:delete_user],
+ ip_address: deleted_user.ip_address.to_s,
+ details: details,
+ ),
+ )
end
def log_custom(custom_type, details = nil)
@@ -46,13 +47,15 @@ class StaffActionLogger
end
def log_post_deletion(deleted_post, opts = {})
- raise Discourse::InvalidParameters.new(:deleted_post) unless deleted_post && deleted_post.is_a?(Post)
+ unless deleted_post && deleted_post.is_a?(Post)
+ raise Discourse::InvalidParameters.new(:deleted_post)
+ end
topic = deleted_post.topic || Topic.with_deleted.find_by(id: deleted_post.topic_id)
- username = deleted_post.user.try(:username) || I18n.t('staff_action_logs.unknown')
- name = deleted_post.user.try(:name) || I18n.t('staff_action_logs.unknown')
- topic_title = topic.try(:title) || I18n.t('staff_action_logs.not_found')
+ username = deleted_post.user.try(:username) || I18n.t("staff_action_logs.unknown")
+ name = deleted_post.user.try(:name) || I18n.t("staff_action_logs.unknown")
+ topic_title = topic.try(:title) || I18n.t("staff_action_logs.not_found")
details = [
"id: #{deleted_post.id}",
@@ -60,14 +63,16 @@ class StaffActionLogger
"user: #{username} (#{name})",
"topic: #{topic_title}",
"post_number: #{deleted_post.post_number}",
- "raw: #{deleted_post.raw}"
+ "raw: #{deleted_post.raw}",
]
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:delete_post],
- post_id: deleted_post.id,
- details: details.join("\n")
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:delete_post],
+ post_id: deleted_post.id,
+ details: details.join("\n"),
+ ),
+ )
end
def log_topic_delete_recover(topic, action = "delete_topic", opts = {})
@@ -79,99 +84,120 @@ class StaffActionLogger
"id: #{topic.id}",
"created_at: #{topic.created_at}",
"user: #{user}",
- "title: #{topic.title}"
+ "title: #{topic.title}",
]
if first_post = topic.ordered_posts.with_deleted.first
details << "raw: #{first_post.raw}"
end
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[action.to_sym],
- topic_id: topic.id,
- details: details.join("\n")
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[action.to_sym],
+ topic_id: topic.id,
+ details: details.join("\n"),
+ ),
+ )
end
def log_trust_level_change(user, old_trust_level, new_trust_level, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user && user.is_a?(User)
- raise Discourse::InvalidParameters.new(:old_trust_level) unless TrustLevel.valid? old_trust_level
- raise Discourse::InvalidParameters.new(:new_trust_level) unless TrustLevel.valid? new_trust_level
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:change_trust_level],
- target_user_id: user.id,
- previous_value: old_trust_level,
- new_value: new_trust_level,
- ))
+ unless TrustLevel.valid? old_trust_level
+ raise Discourse::InvalidParameters.new(:old_trust_level)
+ end
+ unless TrustLevel.valid? new_trust_level
+ raise Discourse::InvalidParameters.new(:new_trust_level)
+ end
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:change_trust_level],
+ target_user_id: user.id,
+ previous_value: old_trust_level,
+ new_value: new_trust_level,
+ ),
+ )
end
def log_lock_trust_level(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user && user.is_a?(User)
- action = UserHistory.actions[user.manual_locked_trust_level.nil? ? :unlock_trust_level : :lock_trust_level]
- UserHistory.create!(params(opts).merge(
- action: action,
- target_user_id: user.id
- ))
+ action =
+ UserHistory.actions[
+ user.manual_locked_trust_level.nil? ? :unlock_trust_level : :lock_trust_level
+ ]
+ UserHistory.create!(params(opts).merge(action: action, target_user_id: user.id))
end
def log_topic_published(topic, opts = {})
raise Discourse::InvalidParameters.new(:topic) unless topic && topic.is_a?(Topic)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:topic_published],
- topic_id: topic.id)
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:topic_published], topic_id: topic.id),
)
end
def log_topic_timestamps_changed(topic, new_timestamp, previous_timestamp, opts = {})
raise Discourse::InvalidParameters.new(:topic) unless topic && topic.is_a?(Topic)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:topic_timestamps_changed],
- topic_id: topic.id,
- new_value: new_timestamp,
- previous_value: previous_timestamp)
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:topic_timestamps_changed],
+ topic_id: topic.id,
+ new_value: new_timestamp,
+ previous_value: previous_timestamp,
+ ),
)
end
def log_post_lock(post, opts = {})
raise Discourse::InvalidParameters.new(:post) unless post && post.is_a?(Post)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[opts[:locked] ? :post_locked : :post_unlocked],
- post_id: post.id)
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[opts[:locked] ? :post_locked : :post_unlocked],
+ post_id: post.id,
+ ),
)
end
def log_post_edit(post, opts = {})
raise Discourse::InvalidParameters.new(:post) unless post && post.is_a?(Post)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:post_edit],
- post_id: post.id,
- details: "#{opts[:old_raw]}\n\n---\n\n#{post.raw}"
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:post_edit],
+ post_id: post.id,
+ details: "#{opts[:old_raw]}\n\n---\n\n#{post.raw}",
+ ),
+ )
end
def log_topic_closed(topic, opts = {})
raise Discourse::InvalidParameters.new(:topic) unless topic && topic.is_a?(Topic)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[opts[:closed] ? :topic_closed : :topic_opened],
- topic_id: topic.id
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[opts[:closed] ? :topic_closed : :topic_opened],
+ topic_id: topic.id,
+ ),
+ )
end
def log_topic_archived(topic, opts = {})
raise Discourse::InvalidParameters.new(:topic) unless topic && topic.is_a?(Topic)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[opts[:archived] ? :topic_archived : :topic_unarchived],
- topic_id: topic.id
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[opts[:archived] ? :topic_archived : :topic_unarchived],
+ topic_id: topic.id,
+ ),
+ )
end
def log_post_staff_note(post, opts = {})
raise Discourse::InvalidParameters.new(:post) unless post && post.is_a?(Post)
- args = params(opts).merge(
- action: UserHistory.actions[opts[:new_value].present? ? :post_staff_note_create : :post_staff_note_destroy],
- post_id: post.id
- )
+ args =
+ params(opts).merge(
+ action:
+ UserHistory.actions[
+ opts[:new_value].present? ? :post_staff_note_create : :post_staff_note_destroy
+ ],
+ post_id: post.id,
+ )
args[:new_value] = opts[:new_value] if opts[:new_value].present?
args[:previous_value] = opts[:old_value] if opts[:old_value].present?
@@ -179,13 +205,17 @@ class StaffActionLogger
end
def log_site_setting_change(setting_name, previous_value, new_value, opts = {})
- raise Discourse::InvalidParameters.new(:setting_name) unless setting_name.present? && SiteSetting.respond_to?(setting_name)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:change_site_setting],
- subject: setting_name,
- previous_value: previous_value&.to_s,
- new_value: new_value&.to_s
- ))
+ unless setting_name.present? && SiteSetting.respond_to?(setting_name)
+ raise Discourse::InvalidParameters.new(:setting_name)
+ end
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:change_site_setting],
+ subject: setting_name,
+ previous_value: previous_value&.to_s,
+ new_value: new_value&.to_s,
+ ),
+ )
end
def theme_json(theme)
@@ -193,7 +223,7 @@ class StaffActionLogger
end
def strip_duplicates(old, cur)
- return [old, cur] unless old && cur
+ return old, cur unless old && cur
old = JSON.parse(old)
cur = JSON.parse(cur)
@@ -217,79 +247,97 @@ class StaffActionLogger
old_json, new_json = strip_duplicates(old_json, new_json)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:change_theme],
- subject: new_theme.name,
- previous_value: old_json,
- new_value: new_json
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:change_theme],
+ subject: new_theme.name,
+ previous_value: old_json,
+ new_value: new_json,
+ ),
+ )
end
def log_theme_destroy(theme, opts = {})
raise Discourse::InvalidParameters.new(:theme) unless theme
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:delete_theme],
- subject: theme.name,
- previous_value: theme_json(theme)
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:delete_theme],
+ subject: theme.name,
+ previous_value: theme_json(theme),
+ ),
+ )
end
def log_theme_component_disabled(component)
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:disable_theme_component],
- subject: component.name,
- context: component.id
- ))
+ UserHistory.create!(
+ params.merge(
+ action: UserHistory.actions[:disable_theme_component],
+ subject: component.name,
+ context: component.id,
+ ),
+ )
end
def log_theme_component_enabled(component)
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:enable_theme_component],
- subject: component.name,
- context: component.id
- ))
+ UserHistory.create!(
+ params.merge(
+ action: UserHistory.actions[:enable_theme_component],
+ subject: component.name,
+ context: component.id,
+ ),
+ )
end
def log_theme_setting_change(setting_name, previous_value, new_value, theme, opts = {})
raise Discourse::InvalidParameters.new(:theme) unless theme
- raise Discourse::InvalidParameters.new(:setting_name) unless theme.cached_settings.has_key?(setting_name)
+ unless theme.cached_settings.has_key?(setting_name)
+ raise Discourse::InvalidParameters.new(:setting_name)
+ end
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:change_theme_setting],
- subject: "#{theme.name}: #{setting_name.to_s}",
- previous_value: previous_value,
- new_value: new_value
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:change_theme_setting],
+ subject: "#{theme.name}: #{setting_name.to_s}",
+ previous_value: previous_value,
+ new_value: new_value,
+ ),
+ )
end
def log_site_text_change(subject, new_text = nil, old_text = nil, opts = {})
raise Discourse::InvalidParameters.new(:subject) unless subject.present?
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:change_site_text],
- subject: subject,
- previous_value: old_text,
- new_value: new_text
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:change_site_text],
+ subject: subject,
+ previous_value: old_text,
+ new_value: new_text,
+ ),
+ )
end
def log_username_change(user, old_username, new_username, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:change_username],
- target_user_id: user.id,
- previous_value: old_username,
- new_value: new_username
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:change_username],
+ target_user_id: user.id,
+ previous_value: old_username,
+ new_value: new_username,
+ ),
+ )
end
def log_name_change(user_id, old_name, new_name, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user_id
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:change_name],
- target_user_id: user_id,
- previous_value: old_name,
- new_value: new_name
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:change_name],
+ target_user_id: user_id,
+ previous_value: old_name,
+ new_value: new_name,
+ ),
+ )
end
def log_user_suspend(user, reason, opts = {})
@@ -297,161 +345,201 @@ class StaffActionLogger
details = StaffMessageFormat.new(:suspend, reason, opts[:message]).format
- args = params(opts).merge(
- action: UserHistory.actions[:suspend_user],
- target_user_id: user.id,
- details: details
- )
+ args =
+ params(opts).merge(
+ action: UserHistory.actions[:suspend_user],
+ target_user_id: user.id,
+ details: details,
+ )
args[:post_id] = opts[:post_id] if opts[:post_id]
UserHistory.create!(args)
end
def log_user_unsuspend(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:unsuspend_user],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:unsuspend_user], target_user_id: user.id),
+ )
end
def log_user_merge(user, source_username, source_email, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:merge_user],
- target_user_id: user.id,
- context: I18n.t("staff_action_logs.user_merged", username: source_username),
- email: source_email
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:merge_user],
+ target_user_id: user.id,
+ context: I18n.t("staff_action_logs.user_merged", username: source_username),
+ email: source_email,
+ ),
+ )
end
- BADGE_FIELDS ||= %i{id name description long_description icon image_upload_id badge_type_id
- badge_grouping_id query allow_title multiple_grant listable target_posts
- enabled auto_revoke show_posts system}
+ BADGE_FIELDS ||= %i[
+ id
+ name
+ description
+ long_description
+ icon
+ image_upload_id
+ badge_type_id
+ badge_grouping_id
+ query
+ allow_title
+ multiple_grant
+ listable
+ target_posts
+ enabled
+ auto_revoke
+ show_posts
+ system
+ ]
def log_badge_creation(badge)
raise Discourse::InvalidParameters.new(:badge) unless badge
- details = BADGE_FIELDS.map do |f|
- [f, badge.public_send(f)]
- end.select { |f, v| v.present? }.map { |f, v| "#{f}: #{v}" }
+ details =
+ BADGE_FIELDS
+ .map { |f| [f, badge.public_send(f)] }
+ .select { |f, v| v.present? }
+ .map { |f, v| "#{f}: #{v}" }
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:create_badge],
- details: details.join("\n")
- ))
+ UserHistory.create!(
+ params.merge(action: UserHistory.actions[:create_badge], details: details.join("\n")),
+ )
end
def log_badge_change(badge)
raise Discourse::InvalidParameters.new(:badge) unless badge
details = ["id: #{badge.id}"]
- badge.previous_changes.each { |f, values| details << "#{f}: #{values[1]}" if BADGE_FIELDS.include?(f.to_sym) }
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:change_badge],
- details: details.join("\n")
- ))
+ badge.previous_changes.each do |f, values|
+ details << "#{f}: #{values[1]}" if BADGE_FIELDS.include?(f.to_sym)
+ end
+ UserHistory.create!(
+ params.merge(action: UserHistory.actions[:change_badge], details: details.join("\n")),
+ )
end
def log_badge_deletion(badge)
raise Discourse::InvalidParameters.new(:badge) unless badge
- details = BADGE_FIELDS.map do |f|
- [f, badge.public_send(f)]
- end.select { |f, v| v.present? }.map { |f, v| "#{f}: #{v}" }
+ details =
+ BADGE_FIELDS
+ .map { |f| [f, badge.public_send(f)] }
+ .select { |f, v| v.present? }
+ .map { |f, v| "#{f}: #{v}" }
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:delete_badge],
- details: details.join("\n")
- ))
+ UserHistory.create!(
+ params.merge(action: UserHistory.actions[:delete_badge], details: details.join("\n")),
+ )
end
def log_badge_grant(user_badge, opts = {})
raise Discourse::InvalidParameters.new(:user_badge) unless user_badge
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:grant_badge],
- target_user_id: user_badge.user_id,
- details: user_badge.badge.name
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:grant_badge],
+ target_user_id: user_badge.user_id,
+ details: user_badge.badge.name,
+ ),
+ )
end
def log_badge_revoke(user_badge, opts = {})
raise Discourse::InvalidParameters.new(:user_badge) unless user_badge
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:revoke_badge],
- target_user_id: user_badge.user_id,
- details: user_badge.badge.name
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:revoke_badge],
+ target_user_id: user_badge.user_id,
+ details: user_badge.badge.name,
+ ),
+ )
end
def log_title_revoke(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:revoke_title],
- target_user_id: user.id,
- details: opts[:revoke_reason],
- previous_value: opts[:previous_value]
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:revoke_title],
+ target_user_id: user.id,
+ details: opts[:revoke_reason],
+ previous_value: opts[:previous_value],
+ ),
+ )
end
def log_title_change(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:change_title],
- target_user_id: user.id,
- details: opts[:details],
- new_value: opts[:new_value],
- previous_value: opts[:previous_value]
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:change_title],
+ target_user_id: user.id,
+ details: opts[:details],
+ new_value: opts[:new_value],
+ previous_value: opts[:previous_value],
+ ),
+ )
end
def log_change_upload_secure_status(opts = {})
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:override_upload_secure_status],
- details: [
- "upload_id: #{opts[:upload_id]}",
- "reason: #{I18n.t("uploads.marked_insecure_from_theme_component_reason")}"
- ].join("\n"),
- new_value: opts[:new_value]
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:override_upload_secure_status],
+ details: [
+ "upload_id: #{opts[:upload_id]}",
+ "reason: #{I18n.t("uploads.marked_insecure_from_theme_component_reason")}",
+ ].join("\n"),
+ new_value: opts[:new_value],
+ ),
+ )
end
def log_check_email(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:check_email],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:check_email], target_user_id: user.id),
+ )
end
def log_show_emails(users, opts = {})
return if users.blank?
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:check_email],
- details: users.map { |u| "[#{u.id}] #{u.username}" }.join("\n")
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:check_email],
+ details: users.map { |u| "[#{u.id}] #{u.username}" }.join("\n"),
+ ),
+ )
end
def log_impersonate(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:impersonate],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:impersonate], target_user_id: user.id),
+ )
end
def log_roll_up(subnet, ips, opts = {})
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:roll_up],
- details: "#{subnet} from #{ips.join(", ")}"
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:roll_up],
+ details: "#{subnet} from #{ips.join(", ")}",
+ ),
+ )
end
- def log_category_settings_change(category, category_params, old_permissions: nil, old_custom_fields: nil)
+ def log_category_settings_change(
+ category,
+ category_params,
+ old_permissions: nil,
+ old_custom_fields: nil
+ )
validate_category(category)
changed_attributes = category.previous_changes.slice(*category_params.keys)
if !old_permissions.empty? && (old_permissions != category_params[:permissions])
- changed_attributes.merge!(permissions: [old_permissions.to_json, category_params[:permissions].to_json])
+ changed_attributes.merge!(
+ permissions: [old_permissions.to_json, category_params[:permissions].to_json],
+ )
end
if old_custom_fields && category_params[:custom_fields]
@@ -462,14 +550,16 @@ class StaffActionLogger
end
changed_attributes.each do |key, value|
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:change_category_settings],
- category_id: category.id,
- context: category.url,
- subject: key,
- previous_value: value[0],
- new_value: value[1]
- ))
+ UserHistory.create!(
+ params.merge(
+ action: UserHistory.actions[:change_category_settings],
+ category_id: category.id,
+ context: category.url,
+ subject: key,
+ previous_value: value[0],
+ new_value: value[1],
+ ),
+ )
end
end
@@ -479,45 +569,47 @@ class StaffActionLogger
details = [
"created_at: #{category.created_at}",
"name: #{category.name}",
- "permissions: #{category.permissions_params}"
+ "permissions: #{category.permissions_params}",
]
if parent_category = category.parent_category
details << "parent_category: #{parent_category.name}"
end
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:delete_category],
- category_id: category.id,
- details: details.join("\n"),
- context: category.url
- ))
+ UserHistory.create!(
+ params.merge(
+ action: UserHistory.actions[:delete_category],
+ category_id: category.id,
+ details: details.join("\n"),
+ context: category.url,
+ ),
+ )
end
def log_category_creation(category)
validate_category(category)
- details = [
- "created_at: #{category.created_at}",
- "name: #{category.name}"
- ]
+ details = ["created_at: #{category.created_at}", "name: #{category.name}"]
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:create_category],
- details: details.join("\n"),
- category_id: category.id,
- context: category.url
- ))
+ UserHistory.create!(
+ params.merge(
+ action: UserHistory.actions[:create_category],
+ details: details.join("\n"),
+ category_id: category.id,
+ context: category.url,
+ ),
+ )
end
def log_silence_user(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- create_args = params(opts).merge(
- action: UserHistory.actions[:silence_user],
- target_user_id: user.id,
- details: opts[:details]
- )
+ create_args =
+ params(opts).merge(
+ action: UserHistory.actions[:silence_user],
+ target_user_id: user.id,
+ details: opts[:details],
+ )
create_args[:post_id] = opts[:post_id] if opts[:post_id]
UserHistory.create!(create_args)
@@ -525,224 +617,235 @@ class StaffActionLogger
def log_unsilence_user(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:unsilence_user],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:unsilence_user], target_user_id: user.id),
+ )
end
def log_disable_second_factor_auth(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:disabled_second_factor],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:disabled_second_factor],
+ target_user_id: user.id,
+ ),
+ )
end
def log_grant_admin(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:grant_admin],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:grant_admin], target_user_id: user.id),
+ )
end
def log_revoke_admin(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:revoke_admin],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:revoke_admin], target_user_id: user.id),
+ )
end
def log_grant_moderation(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:grant_moderation],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:grant_moderation], target_user_id: user.id),
+ )
end
def log_revoke_moderation(user, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:revoke_moderation],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:revoke_moderation], target_user_id: user.id),
+ )
end
def log_backup_create(opts = {})
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:backup_create],
- ip_address: @admin.ip_address.to_s
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:backup_create],
+ ip_address: @admin.ip_address.to_s,
+ ),
+ )
end
def log_entity_export(entity, opts = {})
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:entity_export],
- ip_address: @admin.ip_address.to_s,
- subject: entity
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:entity_export],
+ ip_address: @admin.ip_address.to_s,
+ subject: entity,
+ ),
+ )
end
def log_backup_download(backup, opts = {})
raise Discourse::InvalidParameters.new(:backup) unless backup
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:backup_download],
- ip_address: @admin.ip_address.to_s,
- details: backup.filename
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:backup_download],
+ ip_address: @admin.ip_address.to_s,
+ details: backup.filename,
+ ),
+ )
end
def log_backup_destroy(backup, opts = {})
raise Discourse::InvalidParameters.new(:backup) unless backup
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:backup_destroy],
- ip_address: @admin.ip_address.to_s,
- details: backup.filename
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:backup_destroy],
+ ip_address: @admin.ip_address.to_s,
+ details: backup.filename,
+ ),
+ )
end
def log_revoke_email(user, reason, opts = {})
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:revoke_email],
- target_user_id: user.id,
- details: reason
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:revoke_email],
+ target_user_id: user.id,
+ details: reason,
+ ),
+ )
end
def log_user_approve(user, opts = {})
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:approve_user],
- target_user_id: user.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:approve_user], target_user_id: user.id),
+ )
end
def log_user_deactivate(user, reason, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:deactivate_user],
- target_user_id: user.id,
- details: reason
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:deactivate_user],
+ target_user_id: user.id,
+ details: reason,
+ ),
+ )
end
def log_user_activate(user, reason, opts = {})
raise Discourse::InvalidParameters.new(:user) unless user
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:activate_user],
- target_user_id: user.id,
- details: reason
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:activate_user],
+ target_user_id: user.id,
+ details: reason,
+ ),
+ )
end
def log_wizard_step(step, opts = {})
raise Discourse::InvalidParameters.new(:step) unless step
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:wizard_step],
- context: step.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:wizard_step], context: step.id),
+ )
end
def log_change_readonly_mode(state)
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:change_readonly_mode],
- previous_value: !state,
- new_value: state
- ))
+ UserHistory.create!(
+ params.merge(
+ action: UserHistory.actions[:change_readonly_mode],
+ previous_value: !state,
+ new_value: state,
+ ),
+ )
end
def log_check_personal_message(topic, opts = {})
raise Discourse::InvalidParameters.new(:topic) unless topic && topic.is_a?(Topic)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:check_personal_message],
- topic_id: topic.id,
- context: topic.relative_url
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: UserHistory.actions[:check_personal_message],
+ topic_id: topic.id,
+ context: topic.relative_url,
+ ),
+ )
end
def log_post_approved(post, opts = {})
raise Discourse::InvalidParameters.new(:post) unless post.is_a?(Post)
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:post_approved],
- post_id: post.id
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:post_approved], post_id: post.id),
+ )
end
def log_post_rejected(reviewable, rejected_at, opts = {})
raise Discourse::InvalidParameters.new(:rejected_post) unless reviewable.is_a?(Reviewable)
topic = reviewable.topic || Topic.with_deleted.find_by(id: reviewable.topic_id)
- topic_title = topic&.title || I18n.t('staff_action_logs.not_found')
- username = reviewable.created_by&.username || I18n.t('staff_action_logs.unknown')
- name = reviewable.created_by&.name || I18n.t('staff_action_logs.unknown')
+ topic_title = topic&.title || I18n.t("staff_action_logs.not_found")
+ username = reviewable.created_by&.username || I18n.t("staff_action_logs.unknown")
+ name = reviewable.created_by&.name || I18n.t("staff_action_logs.unknown")
details = [
"created_at: #{reviewable.created_at}",
"rejected_at: #{rejected_at}",
"user: #{username} (#{name})",
"topic: #{topic_title}",
- "raw: #{reviewable.payload['raw']}",
+ "raw: #{reviewable.payload["raw"]}",
]
- UserHistory.create!(params(opts).merge(
- action: UserHistory.actions[:post_rejected],
- details: details.join("\n")
- ))
+ UserHistory.create!(
+ params(opts).merge(action: UserHistory.actions[:post_rejected], details: details.join("\n")),
+ )
end
def log_web_hook(web_hook, action, opts = {})
- details = [
- "webhook_id: #{web_hook.id}",
- "payload_url: #{web_hook.payload_url}"
- ]
+ details = ["webhook_id: #{web_hook.id}", "payload_url: #{web_hook.payload_url}"]
old_values, new_values = get_changes(opts[:changes])
- UserHistory.create!(params(opts).merge(
- action: action,
- context: details.join(", "),
- previous_value: old_values&.join(", "),
- new_value: new_values&.join(", ")
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: action,
+ context: details.join(", "),
+ previous_value: old_values&.join(", "),
+ new_value: new_values&.join(", "),
+ ),
+ )
end
def log_web_hook_deactivate(web_hook, response_http_status, opts = {})
- context = [
- "webhook_id: #{web_hook.id}",
- "webhook_response_status: #{response_http_status}"
- ]
+ context = ["webhook_id: #{web_hook.id}", "webhook_response_status: #{response_http_status}"]
- UserHistory.create!(params.merge(
- action: UserHistory.actions[:web_hook_deactivate],
- context: context,
- details: I18n.t('staff_action_logs.webhook_deactivation_reason', status: response_http_status)
- ))
+ UserHistory.create!(
+ params.merge(
+ action: UserHistory.actions[:web_hook_deactivate],
+ context: context,
+ details:
+ I18n.t("staff_action_logs.webhook_deactivation_reason", status: response_http_status),
+ ),
+ )
end
def log_embeddable_host(embeddable_host, action, opts = {})
old_values, new_values = get_changes(opts[:changes])
- UserHistory.create!(params(opts).merge(
- action: action,
- context: "host: #{embeddable_host.host}",
- previous_value: old_values&.join(", "),
- new_value: new_values&.join(", ")
- ))
+ UserHistory.create!(
+ params(opts).merge(
+ action: action,
+ context: "host: #{embeddable_host.host}",
+ previous_value: old_values&.join(", "),
+ new_value: new_values&.join(", "),
+ ),
+ )
end
def log_api_key(api_key, action, opts = {})
opts[:changes]&.delete("key") # Do not log the full key
- history_params = params(opts).merge(
- action: action,
- subject: api_key.truncated_key
- )
+ history_params = params(opts).merge(action: action, subject: api_key.truncated_key)
if opts[:changes]
old_values, new_values = get_changes(opts[:changes])
- history_params[:previous_value] = old_values&.join(", ") unless opts[:changes].keys.include?("id")
+ history_params[:previous_value] = old_values&.join(", ") unless opts[:changes].keys.include?(
+ "id",
+ )
history_params[:new_value] = new_values&.join(", ")
end
@@ -750,35 +853,39 @@ class StaffActionLogger
end
def log_api_key_revoke(api_key)
- UserHistory.create!(params.merge(
- subject: api_key.truncated_key,
- action: UserHistory.actions[:api_key_update],
- details: I18n.t("staff_action_logs.api_key.revoked")
- ))
+ UserHistory.create!(
+ params.merge(
+ subject: api_key.truncated_key,
+ action: UserHistory.actions[:api_key_update],
+ details: I18n.t("staff_action_logs.api_key.revoked"),
+ ),
+ )
end
def log_api_key_restore(api_key)
- UserHistory.create!(params.merge(
- subject: api_key.truncated_key,
- action: UserHistory.actions[:api_key_update],
- details: I18n.t("staff_action_logs.api_key.restored")
- ))
+ UserHistory.create!(
+ params.merge(
+ subject: api_key.truncated_key,
+ action: UserHistory.actions[:api_key_update],
+ details: I18n.t("staff_action_logs.api_key.restored"),
+ ),
+ )
end
def log_published_page(topic_id, slug)
- UserHistory.create!(params.merge(
- subject: slug,
- topic_id: topic_id,
- action: UserHistory.actions[:page_published]
- ))
+ UserHistory.create!(
+ params.merge(subject: slug, topic_id: topic_id, action: UserHistory.actions[:page_published]),
+ )
end
def log_unpublished_page(topic_id, slug)
- UserHistory.create!(params.merge(
- subject: slug,
- topic_id: topic_id,
- action: UserHistory.actions[:page_unpublished]
- ))
+ UserHistory.create!(
+ params.merge(
+ subject: slug,
+ topic_id: topic_id,
+ action: UserHistory.actions[:page_unpublished],
+ ),
+ )
end
def log_add_email(user)
@@ -787,7 +894,7 @@ class StaffActionLogger
UserHistory.create!(
action: UserHistory.actions[:add_email],
acting_user_id: @admin.id,
- target_user_id: user.id
+ target_user_id: user.id,
)
end
@@ -797,7 +904,7 @@ class StaffActionLogger
UserHistory.create!(
action: UserHistory.actions[:update_email],
acting_user_id: @admin.id,
- target_user_id: user.id
+ target_user_id: user.id,
)
end
@@ -807,7 +914,7 @@ class StaffActionLogger
UserHistory.create!(
action: UserHistory.actions[:destroy_email],
acting_user_id: @admin.id,
- target_user_id: user.id
+ target_user_id: user.id,
)
end
@@ -818,7 +925,7 @@ class StaffActionLogger
action: UserHistory.actions[:watched_word_create],
acting_user_id: @admin.id,
details: watched_word.action_log_details,
- context: WatchedWord.actions[watched_word.action]
+ context: WatchedWord.actions[watched_word.action],
)
end
@@ -829,26 +936,21 @@ class StaffActionLogger
action: UserHistory.actions[:watched_word_destroy],
acting_user_id: @admin.id,
details: watched_word.action_log_details,
- context: WatchedWord.actions[watched_word.action]
+ context: WatchedWord.actions[watched_word.action],
)
end
def log_group_deletetion(group)
raise Discourse::InvalidParameters.new(:group) if group.nil?
- details = [
- "name: #{group.name}",
- "id: #{group.id}"
- ]
+ details = ["name: #{group.name}", "id: #{group.id}"]
- if group.grant_trust_level
- details << "grant_trust_level: #{group.grant_trust_level}"
- end
+ details << "grant_trust_level: #{group.grant_trust_level}" if group.grant_trust_level
UserHistory.create!(
acting_user_id: @admin.id,
action: UserHistory.actions[:delete_group],
- details: details.join(', ')
+ details: details.join(", "),
)
end
diff --git a/app/services/themes_install_task.rb b/app/services/themes_install_task.rb
index ac32739a1bf..3eaa931944b 100644
--- a/app/services/themes_install_task.rb
+++ b/app/services/themes_install_task.rb
@@ -48,20 +48,27 @@ class ThemesInstallTask
end
def repo_name
- @url.gsub(Regexp.union('git@github.com:', 'https://github.com/', '.git'), '')
+ @url.gsub(Regexp.union("git@github.com:", "https://github.com/", ".git"), "")
end
def theme_exists?
- @remote_theme = RemoteTheme
- .where("remote_url like ?", "%#{repo_name}%")
- .where(branch: @options.fetch(:branch, nil))
- .first
+ @remote_theme =
+ RemoteTheme
+ .where("remote_url like ?", "%#{repo_name}%")
+ .where(branch: @options.fetch(:branch, nil))
+ .first
@theme = @remote_theme&.theme
@theme.present?
end
def install
- @theme = RemoteTheme.import_theme(@url, Discourse.system_user, private_key: @options[:private_key], branch: @options[:branch])
+ @theme =
+ RemoteTheme.import_theme(
+ @url,
+ Discourse.system_user,
+ private_key: @options[:private_key],
+ branch: @options[:branch],
+ )
@theme.set_default! if @options.fetch(:default, false)
add_component_to_all_themes
end
@@ -76,9 +83,13 @@ class ThemesInstallTask
def add_component_to_all_themes
return if (!@options.fetch(:add_to_all_themes, false) || !@theme.component)
- Theme.where(component: false).each do |parent_theme|
- next if ChildTheme.where(parent_theme_id: parent_theme.id, child_theme_id: @theme.id).exists?
- parent_theme.add_relative_theme!(:child, @theme)
- end
+ Theme
+ .where(component: false)
+ .each do |parent_theme|
+ if ChildTheme.where(parent_theme_id: parent_theme.id, child_theme_id: @theme.id).exists?
+ next
+ end
+ parent_theme.add_relative_theme!(:child, @theme)
+ end
end
end
diff --git a/app/services/topic_bookmarkable.rb b/app/services/topic_bookmarkable.rb
index 5a5276f64a7..f79af4c07c4 100644
--- a/app/services/topic_bookmarkable.rb
+++ b/app/services/topic_bookmarkable.rb
@@ -19,28 +19,29 @@ class TopicBookmarkable < BaseBookmarkable
topics = topic_bookmarks.map(&:bookmarkable)
topic_user_lookup = TopicUser.lookup_for(guardian.user, topics)
- topics.each do |topic|
- topic.user_data = topic_user_lookup[topic.id]
- end
+ topics.each { |topic| topic.user_data = topic_user_lookup[topic.id] }
end
def self.list_query(user, guardian)
topics = Topic.listable_topics.secured(guardian)
pms = Topic.private_messages_for_user(user)
- topic_bookmarks = user
- .bookmarks_of_type("Topic")
- .joins("INNER JOIN topics ON topics.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Topic'")
- .joins("LEFT JOIN topic_users ON topic_users.topic_id = topics.id")
- .where("topic_users.user_id = ?", user.id)
+ topic_bookmarks =
+ user
+ .bookmarks_of_type("Topic")
+ .joins(
+ "INNER JOIN topics ON topics.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Topic'",
+ )
+ .joins("LEFT JOIN topic_users ON topic_users.topic_id = topics.id")
+ .where("topic_users.user_id = ?", user.id)
guardian.filter_allowed_categories(topic_bookmarks.merge(topics.or(pms)))
end
def self.search_query(bookmarks, query, ts_query, &bookmarkable_search)
bookmarkable_search.call(
- bookmarks
- .joins("LEFT JOIN posts ON posts.topic_id = topics.id AND posts.post_number = 1")
- .joins("LEFT JOIN post_search_data ON post_search_data.post_id = posts.id"),
- "#{ts_query} @@ post_search_data.search_data"
+ bookmarks.joins(
+ "LEFT JOIN posts ON posts.topic_id = topics.id AND posts.post_number = 1",
+ ).joins("LEFT JOIN post_search_data ON post_search_data.post_id = posts.id"),
+ "#{ts_query} @@ post_search_data.search_data",
)
end
@@ -51,8 +52,8 @@ class TopicBookmarkable < BaseBookmarkable
post_number: 1,
data: {
title: bookmark.bookmarkable.title,
- bookmarkable_url: bookmark.bookmarkable.first_post.url
- }
+ bookmarkable_url: bookmark.bookmarkable.first_post.url,
+ },
)
end
diff --git a/app/services/topic_status_updater.rb b/app/services/topic_status_updater.rb
index d5e1d95d446..7008c3223a5 100644
--- a/app/services/topic_status_updater.rb
+++ b/app/services/topic_status_updater.rb
@@ -1,167 +1,176 @@
# frozen_string_literal: true
-TopicStatusUpdater = Struct.new(:topic, :user) do
- def update!(status, enabled, opts = {})
- status = Status.new(status, enabled)
+TopicStatusUpdater =
+ Struct.new(:topic, :user) do
+ def update!(status, enabled, opts = {})
+ status = Status.new(status, enabled)
- @topic_timer = topic.public_topic_timer
+ @topic_timer = topic.public_topic_timer
- updated = nil
- Topic.transaction do
- updated = change(status, opts)
- if updated
- highest_post_number = topic.highest_post_number
- create_moderator_post_for(status, opts)
- update_read_state_for(status, highest_post_number)
+ updated = nil
+ Topic.transaction do
+ updated = change(status, opts)
+ if updated
+ highest_post_number = topic.highest_post_number
+ create_moderator_post_for(status, opts)
+ update_read_state_for(status, highest_post_number)
+ end
end
+
+ updated
end
- updated
- end
+ private
- private
+ def change(status, opts = {})
+ result = true
- def change(status, opts = {})
- result = true
-
- if status.pinned? || status.pinned_globally?
- topic.update_pinned(status.enabled?, status.pinned_globally?, opts[:until])
- elsif status.autoclosed?
- rc = Topic.where(id: topic.id, closed: !status.enabled?).update_all(closed: status.enabled?)
- topic.closed = status.enabled?
- result = false if rc == 0
- else
- rc = Topic.where(:id => topic.id, status.name => !status.enabled)
- .update_all(status.name => status.enabled?)
-
- topic.public_send("#{status.name}=", status.enabled?)
- result = false if rc == 0
- end
-
- if status.manually_closing_topic?
- DiscourseEvent.trigger(:topic_closed, topic)
- end
-
- if status.visible? && status.disabled?
- UserProfile.remove_featured_topic_from_all_profiles(topic)
- end
-
- if status.visible? && result
- topic.update_category_topic_count_by(status.enabled? ? 1 : -1)
- UserStatCountUpdater.public_send(status.enabled? ? :increment! : :decrement!, topic.first_post)
- end
-
- if @topic_timer
- if status.manually_closing_topic? || status.closing_topic?
- topic.delete_topic_timer(TopicTimer.types[:close])
- topic.delete_topic_timer(TopicTimer.types[:silent_close])
- elsif status.manually_opening_topic? || status.opening_topic?
- topic.delete_topic_timer(TopicTimer.types[:open])
- topic.inherit_auto_close_from_category
- end
- end
-
- # remove featured topics if we close/archive/make them invisible. Previously we used
- # to run the whole featuring logic but that could be very slow and have concurrency
- # errors on large sites with many autocloses and topics being created.
- if ((status.enabled? && (status.autoclosed? || status.closed? || status.archived?)) ||
- (status.disabled? && status.visible?))
- CategoryFeaturedTopic.where(topic_id: topic.id).delete_all
- end
-
- result
- end
-
- def create_moderator_post_for(status, opts)
- message = opts[:message]
- topic.add_moderator_post(user, message || message_for(status), options_for(status, opts))
- topic.reload
- end
-
- def update_read_state_for(status, old_highest_read)
- if status.autoclosed? && status.enabled?
- # let's pretend all the people that read up to the autoclose message
- # actually read the topic
- PostTiming.pretend_read(topic.id, old_highest_read, topic.highest_post_number)
- end
- end
-
- def message_for(status)
- if status.autoclosed?
- locale_key = status.locale_key.dup
- locale_key << "_lastpost" if @topic_timer&.based_on_last_post
- message_for_autoclosed(locale_key)
- end
- end
-
- def message_for_autoclosed(locale_key)
- num_minutes =
- if @topic_timer&.based_on_last_post
- (@topic_timer.duration_minutes || 0).minutes.to_i
- elsif @topic_timer&.created_at
- Time.zone.now - @topic_timer.created_at
+ if status.pinned? || status.pinned_globally?
+ topic.update_pinned(status.enabled?, status.pinned_globally?, opts[:until])
+ elsif status.autoclosed?
+ rc = Topic.where(id: topic.id, closed: !status.enabled?).update_all(closed: status.enabled?)
+ topic.closed = status.enabled?
+ result = false if rc == 0
else
- Time.zone.now - topic.created_at
+ rc =
+ Topic.where(:id => topic.id, status.name => !status.enabled).update_all(
+ status.name => status.enabled?,
+ )
+
+ topic.public_send("#{status.name}=", status.enabled?)
+ result = false if rc == 0
end
- # all of the results above are in seconds, this brings them
- # back to the actual minutes integer
- num_minutes = (num_minutes / 1.minute).round
+ DiscourseEvent.trigger(:topic_closed, topic) if status.manually_closing_topic?
- if num_minutes.minutes >= 2.days
- I18n.t("#{locale_key}_days", count: (num_minutes.minutes / 1.day).round)
- else
- num_hours = (num_minutes.minutes / 1.hour).round
- if num_hours >= 2
- I18n.t("#{locale_key}_hours", count: num_hours)
+ if status.visible? && status.disabled?
+ UserProfile.remove_featured_topic_from_all_profiles(topic)
+ end
+
+ if status.visible? && result
+ topic.update_category_topic_count_by(status.enabled? ? 1 : -1)
+ UserStatCountUpdater.public_send(
+ status.enabled? ? :increment! : :decrement!,
+ topic.first_post,
+ )
+ end
+
+ if @topic_timer
+ if status.manually_closing_topic? || status.closing_topic?
+ topic.delete_topic_timer(TopicTimer.types[:close])
+ topic.delete_topic_timer(TopicTimer.types[:silent_close])
+ elsif status.manually_opening_topic? || status.opening_topic?
+ topic.delete_topic_timer(TopicTimer.types[:open])
+ topic.inherit_auto_close_from_category
+ end
+ end
+
+ # remove featured topics if we close/archive/make them invisible. Previously we used
+ # to run the whole featuring logic but that could be very slow and have concurrency
+ # errors on large sites with many autocloses and topics being created.
+ if (
+ (status.enabled? && (status.autoclosed? || status.closed? || status.archived?)) ||
+ (status.disabled? && status.visible?)
+ )
+ CategoryFeaturedTopic.where(topic_id: topic.id).delete_all
+ end
+
+ result
+ end
+
+ def create_moderator_post_for(status, opts)
+ message = opts[:message]
+ topic.add_moderator_post(user, message || message_for(status), options_for(status, opts))
+ topic.reload
+ end
+
+ def update_read_state_for(status, old_highest_read)
+ if status.autoclosed? && status.enabled?
+ # let's pretend all the people that read up to the autoclose message
+ # actually read the topic
+ PostTiming.pretend_read(topic.id, old_highest_read, topic.highest_post_number)
+ end
+ end
+
+ def message_for(status)
+ if status.autoclosed?
+ locale_key = status.locale_key.dup
+ locale_key << "_lastpost" if @topic_timer&.based_on_last_post
+ message_for_autoclosed(locale_key)
+ end
+ end
+
+ def message_for_autoclosed(locale_key)
+ num_minutes =
+ if @topic_timer&.based_on_last_post
+ (@topic_timer.duration_minutes || 0).minutes.to_i
+ elsif @topic_timer&.created_at
+ Time.zone.now - @topic_timer.created_at
+ else
+ Time.zone.now - topic.created_at
+ end
+
+ # all of the results above are in seconds, this brings them
+ # back to the actual minutes integer
+ num_minutes = (num_minutes / 1.minute).round
+
+ if num_minutes.minutes >= 2.days
+ I18n.t("#{locale_key}_days", count: (num_minutes.minutes / 1.day).round)
else
- I18n.t("#{locale_key}_minutes", count: num_minutes)
+ num_hours = (num_minutes.minutes / 1.hour).round
+ if num_hours >= 2
+ I18n.t("#{locale_key}_hours", count: num_hours)
+ else
+ I18n.t("#{locale_key}_minutes", count: num_minutes)
+ end
end
end
+
+ def options_for(status, opts = {})
+ {
+ bump: status.opening_topic?,
+ post_type: Post.types[:small_action],
+ silent: opts[:silent],
+ action_code: status.action_code,
+ }
+ end
+
+ Status =
+ Struct.new(:name, :enabled) do
+ %w[pinned_globally pinned autoclosed closed visible archived].each do |status|
+ define_method("#{status}?") { name == status }
+ end
+
+ def enabled?
+ enabled
+ end
+
+ def disabled?
+ !enabled?
+ end
+
+ def action_code
+ "#{name}.#{enabled? ? "enabled" : "disabled"}"
+ end
+
+ def locale_key
+ "topic_statuses.#{action_code.tr(".", "_")}"
+ end
+
+ def opening_topic?
+ (closed? || autoclosed?) && disabled?
+ end
+
+ def closing_topic?
+ (closed? || autoclosed?) && enabled?
+ end
+
+ def manually_closing_topic?
+ closed? && enabled?
+ end
+
+ def manually_opening_topic?
+ closed? && disabled?
+ end
+ end
end
-
- def options_for(status, opts = {})
- { bump: status.opening_topic?,
- post_type: Post.types[:small_action],
- silent: opts[:silent],
- action_code: status.action_code }
- end
-
- Status = Struct.new(:name, :enabled) do
- %w(pinned_globally pinned autoclosed closed visible archived).each do |status|
- define_method("#{status}?") { name == status }
- end
-
- def enabled?
- enabled
- end
-
- def disabled?
- !enabled?
- end
-
- def action_code
- "#{name}.#{enabled? ? 'enabled' : 'disabled'}"
- end
-
- def locale_key
- "topic_statuses.#{action_code.tr('.', '_')}"
- end
-
- def opening_topic?
- (closed? || autoclosed?) && disabled?
- end
-
- def closing_topic?
- (closed? || autoclosed?) && enabled?
- end
-
- def manually_closing_topic?
- closed? && enabled?
- end
-
- def manually_opening_topic?
- closed? && disabled?
- end
- end
-end
diff --git a/app/services/topic_timestamp_changer.rb b/app/services/topic_timestamp_changer.rb
index a8d5059c4d2..c9f1d8b552f 100644
--- a/app/services/topic_timestamp_changer.rb
+++ b/app/services/topic_timestamp_changer.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
class TopicTimestampChanger
- class InvalidTimestampError < StandardError; end
+ class InvalidTimestampError < StandardError
+ end
def initialize(timestamp:, topic: nil, topic_id: nil)
@topic = topic || Topic.with_deleted.find(topic_id)
@@ -46,11 +47,7 @@ class TopicTimestampChanger
end
def update_topic(last_posted_at)
- @topic.update(
- created_at: @timestamp,
- updated_at: @timestamp,
- last_posted_at: last_posted_at
- )
+ @topic.update(created_at: @timestamp, updated_at: @timestamp, last_posted_at: last_posted_at)
end
def update_post(post, timestamp)
diff --git a/app/services/tracked_topics_updater.rb b/app/services/tracked_topics_updater.rb
index 018303af0bd..1fc74ce2070 100644
--- a/app/services/tracked_topics_updater.rb
+++ b/app/services/tracked_topics_updater.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class TrackedTopicsUpdater
-
def initialize(user_id, threshold)
@id = user_id
@threshold = threshold
@@ -12,8 +11,14 @@ class TrackedTopicsUpdater
if @threshold < 0
topic_users.update_all(notification_level: TopicUser.notification_levels[:regular])
else
- topic_users.update_all(["notification_level = CASE WHEN total_msecs_viewed < ? THEN ? ELSE ? END",
- @threshold, TopicUser.notification_levels[:regular], TopicUser.notification_levels[:tracking]])
+ topic_users.update_all(
+ [
+ "notification_level = CASE WHEN total_msecs_viewed < ? THEN ? ELSE ? END",
+ @threshold,
+ TopicUser.notification_levels[:regular],
+ TopicUser.notification_levels[:tracking],
+ ],
+ )
end
end
end
diff --git a/app/services/trust_level_granter.rb b/app/services/trust_level_granter.rb
index db284b5dc8c..9d95d117a58 100644
--- a/app/services/trust_level_granter.rb
+++ b/app/services/trust_level_granter.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class TrustLevelGranter
-
def initialize(trust_level, user)
@trust_level, @user = trust_level, user
end
diff --git a/app/services/user_action_manager.rb b/app/services/user_action_manager.rb
index ae460b6235e..61a207687d0 100644
--- a/app/services/user_action_manager.rb
+++ b/app/services/user_action_manager.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class UserActionManager
-
def self.disable
@disabled = true
end
@@ -10,8 +9,7 @@ class UserActionManager
@disabled = false
end
- [:notification, :post, :topic, :post_action].each do |type|
- self.class_eval(<<~RUBY)
+ %i[notification post topic post_action].each { |type| self.class_eval(<<~RUBY) }
def self.#{type}_created(*args)
return if @disabled
#{type}_rows(*args).each { |row| UserAction.log_action!(row) }
@@ -21,9 +19,8 @@ class UserActionManager
#{type}_rows(*args).each { |row| UserAction.remove_action!(row) }
end
RUBY
- end
-private
+ private
def self.topic_rows(topic)
# no action to log here, this can happen if a user is deleted
@@ -36,22 +33,28 @@ private
acting_user_id: topic.user_id,
target_topic_id: topic.id,
target_post_id: -1,
- created_at: topic.created_at
+ created_at: topic.created_at,
}
- UserAction.remove_action!(row.merge(
- action_type: topic.private_message? ? UserAction::NEW_TOPIC : UserAction::NEW_PRIVATE_MESSAGE
- ))
+ UserAction.remove_action!(
+ row.merge(
+ action_type:
+ topic.private_message? ? UserAction::NEW_TOPIC : UserAction::NEW_PRIVATE_MESSAGE,
+ ),
+ )
rows = [row]
if topic.private_message?
- topic.topic_allowed_users.reject { |a| a.user_id == topic.user_id }.each do |ta|
- row = row.dup
- row[:user_id] = ta.user_id
- row[:action_type] = UserAction::GOT_PRIVATE_MESSAGE
- rows << row
- end
+ topic
+ .topic_allowed_users
+ .reject { |a| a.user_id == topic.user_id }
+ .each do |ta|
+ row = row.dup
+ row[:user_id] = ta.user_id
+ row[:action_type] = UserAction::GOT_PRIVATE_MESSAGE
+ rows << row
+ end
end
rows
end
@@ -66,7 +69,7 @@ private
acting_user_id: post.user_id,
target_post_id: post.id,
target_topic_id: post.topic_id,
- created_at: post.created_at
+ created_at: post.created_at,
}
rows = [row]
@@ -76,7 +79,13 @@ private
post.topic.topic_allowed_users.each do |ta|
row = row.dup
row[:user_id] = ta.user_id
- row[:action_type] = ta.user_id == post.user_id ? UserAction::NEW_PRIVATE_MESSAGE : UserAction::GOT_PRIVATE_MESSAGE
+ row[:action_type] = (
+ if ta.user_id == post.user_id
+ UserAction::NEW_PRIVATE_MESSAGE
+ else
+ UserAction::GOT_PRIVATE_MESSAGE
+ end
+ )
rows << row
end
end
@@ -100,13 +109,15 @@ private
# skip any invalid items, eg failed to save post and so on
return [] unless action && post && user && post.id
- [{
- action_type: action,
- user_id: user.id,
- acting_user_id: acting_user_id || post.user_id,
- target_topic_id: post.topic_id,
- target_post_id: post.id
- }]
+ [
+ {
+ action_type: action,
+ user_id: user.id,
+ acting_user_id: acting_user_id || post.user_id,
+ target_topic_id: post.topic_id,
+ target_post_id: post.id,
+ },
+ ]
end
def self.post_action_rows(post_action)
@@ -121,11 +132,13 @@ private
acting_user_id: post_action.user_id,
target_post_id: post_action.post_id,
target_topic_id: post.topic_id,
- created_at: post_action.created_at
+ created_at: post_action.created_at,
}
- post_action.is_like? ?
- [row, row.merge(action_type: UserAction::WAS_LIKED, user_id: post.user_id)] :
+ if post_action.is_like?
+ [row, row.merge(action_type: UserAction::WAS_LIKED, user_id: post.user_id)]
+ else
[row]
+ end
end
end
diff --git a/app/services/user_activator.rb b/app/services/user_activator.rb
index 4c0d14ab623..6d45907fbfe 100644
--- a/app/services/user_activator.rb
+++ b/app/services/user_activator.rb
@@ -39,7 +39,6 @@ class UserActivator
LoginActivator
end
end
-
end
class ApprovalActivator < UserActivator
@@ -69,7 +68,7 @@ class LoginActivator < UserActivator
def activate
log_on_user(user)
- user.enqueue_welcome_message('welcome_user')
+ user.enqueue_welcome_message("welcome_user")
success_message
end
diff --git a/app/services/user_anonymizer.rb b/app/services/user_anonymizer.rb
index 970d1fff42a..6f1b317c6c7 100644
--- a/app/services/user_anonymizer.rb
+++ b/app/services/user_anonymizer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class UserAnonymizer
-
attr_reader :user_history
# opts:
@@ -55,7 +54,7 @@ class UserAnonymizer
bio_raw: nil,
bio_cooked: nil,
profile_background_upload: nil,
- card_background_upload: nil
+ card_background_upload: nil,
)
end
@@ -70,15 +69,19 @@ class UserAnonymizer
@user_history = log_action
end
- UsernameChanger.update_username(user_id: @user.id,
- old_username: @prev_username,
- new_username: @user.username,
- avatar_template: @user.avatar_template)
+ UsernameChanger.update_username(
+ user_id: @user.id,
+ old_username: @prev_username,
+ new_username: @user.username,
+ avatar_template: @user.avatar_template,
+ )
- Jobs.enqueue(:anonymize_user,
- user_id: @user.id,
- prev_email: @prev_email,
- anonymize_ip: @opts[:anonymize_ip])
+ Jobs.enqueue(
+ :anonymize_user,
+ user_id: @user.id,
+ prev_email: @prev_email,
+ anonymize_ip: @opts[:anonymize_ip],
+ )
DiscourseEvent.trigger(:user_anonymized, user: @user, opts: @opts)
@user
@@ -88,7 +91,7 @@ class UserAnonymizer
def make_anon_username
100.times do
- new_username = "anon#{(SecureRandom.random_number * 100000000).to_i}"
+ new_username = "anon#{(SecureRandom.random_number * 100_000_000).to_i}"
return new_username unless User.where(username_lower: new_username).exists?
end
raise "Failed to generate an anon username"
diff --git a/app/services/user_authenticator.rb b/app/services/user_authenticator.rb
index c5cd920cf1c..73dbe04e2a4 100644
--- a/app/services/user_authenticator.rb
+++ b/app/services/user_authenticator.rb
@@ -1,8 +1,12 @@
# frozen_string_literal: true
class UserAuthenticator
-
- def initialize(user, session, authenticator_finder: Users::OmniauthCallbacksController, require_password: true)
+ def initialize(
+ user,
+ session,
+ authenticator_finder: Users::OmniauthCallbacksController,
+ require_password: true
+ )
@user = user
@session = session
if session&.dig(:authentication) && session[:authentication].is_a?(Hash)
@@ -61,5 +65,4 @@ class UserAuthenticator
def authenticator_name
@auth_result&.authenticator_name
end
-
end
diff --git a/app/services/user_destroyer.rb b/app/services/user_destroyer.rb
index ed91b77422a..0936d5cffa4 100644
--- a/app/services/user_destroyer.rb
+++ b/app/services/user_destroyer.rb
@@ -2,19 +2,19 @@
# Responsible for destroying a User record
class UserDestroyer
-
- class PostsExistError < RuntimeError; end
+ class PostsExistError < RuntimeError
+ end
def initialize(actor)
@actor = actor
- raise Discourse::InvalidParameters.new('acting user is nil') unless @actor && @actor.is_a?(User)
+ raise Discourse::InvalidParameters.new("acting user is nil") unless @actor && @actor.is_a?(User)
@guardian = Guardian.new(actor)
end
# Returns false if the user failed to be deleted.
# Returns a frozen instance of the User if the delete succeeded.
def destroy(user, opts = {})
- raise Discourse::InvalidParameters.new('user is nil') unless user && user.is_a?(User)
+ raise Discourse::InvalidParameters.new("user is nil") unless user && user.is_a?(User)
raise PostsExistError if !opts[:delete_posts] && user.posts.joins(:topic).count != 0
@guardian.ensure_can_delete_user!(user)
@@ -26,7 +26,6 @@ class UserDestroyer
result = nil
optional_transaction(open_transaction: opts[:transaction]) do
-
UserSecurityKey.where(user_id: user.id).delete_all
Bookmark.where(user_id: user.id).delete_all
Draft.where(user_id: user.id).delete_all
@@ -44,17 +43,15 @@ class UserDestroyer
delete_posts(user, category_topic_ids, opts)
end
- user.post_actions.find_each do |post_action|
- post_action.remove_act!(Discourse.system_user)
- end
+ user.post_actions.find_each { |post_action| post_action.remove_act!(Discourse.system_user) }
# Add info about the user to staff action logs
UserHistory.staff_action_records(
- Discourse.system_user, acting_user: user.username
- ).update_all([
- "details = CONCAT(details, ?)",
- "\nuser_id: #{user.id}\nusername: #{user.username}"
- ])
+ Discourse.system_user,
+ acting_user: user.username,
+ ).update_all(
+ ["details = CONCAT(details, ?)", "\nuser_id: #{user.id}\nusername: #{user.username}"],
+ )
# keep track of emails used
user_emails = user.user_emails.pluck(:email)
@@ -76,22 +73,26 @@ class UserDestroyer
Post.unscoped.where(user_id: result.id).update_all(user_id: nil)
# If this user created categories, fix those up:
- Category.where(user_id: result.id).each do |c|
- c.user_id = Discourse::SYSTEM_USER_ID
- c.save!
- if topic = Topic.unscoped.find_by(id: c.topic_id)
- topic.recover!
- topic.user_id = Discourse::SYSTEM_USER_ID
- topic.save!
+ Category
+ .where(user_id: result.id)
+ .each do |c|
+ c.user_id = Discourse::SYSTEM_USER_ID
+ c.save!
+ if topic = Topic.unscoped.find_by(id: c.topic_id)
+ topic.recover!
+ topic.user_id = Discourse::SYSTEM_USER_ID
+ topic.save!
+ end
end
- end
- Invite.where(email: user_emails).each do |invite|
- # invited_users will be removed by dependent destroy association when user is destroyed
- invite.invited_groups.destroy_all
- invite.topic_invites.destroy_all
- invite.destroy
- end
+ Invite
+ .where(email: user_emails)
+ .each do |invite|
+ # invited_users will be removed by dependent destroy association when user is destroyed
+ invite.invited_groups.destroy_all
+ invite.topic_invites.destroy_all
+ invite.destroy
+ end
unless opts[:quiet]
if @actor == user
@@ -101,7 +102,9 @@ class UserDestroyer
deleted_by = @actor
end
StaffActionLogger.new(deleted_by).log_user_deletion(user, opts.slice(:context))
- Rails.logger.warn("User destroyed without context from: #{caller_locations(14, 1)[0]}") if opts.slice(:context).blank?
+ if opts.slice(:context).blank?
+ Rails.logger.warn("User destroyed without context from: #{caller_locations(14, 1)[0]}")
+ end
end
MessageBus.publish "/logout/#{result.id}", result.id, user_ids: [result.id]
end
@@ -118,16 +121,22 @@ class UserDestroyer
protected
def block_external_urls(user)
- TopicLink.where(user: user, internal: false).find_each do |link|
- next if Oneboxer.engine(link.url) != Onebox::Engine::AllowlistedGenericOnebox
- ScreenedUrl.watch(link.url, link.domain, ip_address: user.ip_address)&.record_match!
- end
+ TopicLink
+ .where(user: user, internal: false)
+ .find_each do |link|
+ next if Oneboxer.engine(link.url) != Onebox::Engine::AllowlistedGenericOnebox
+ ScreenedUrl.watch(link.url, link.domain, ip_address: user.ip_address)&.record_match!
+ end
end
def agree_with_flags(user)
- ReviewableFlaggedPost.where(target_created_by: user).find_each do |reviewable|
- reviewable.perform(@actor, :agree_and_keep) if reviewable.actions_for(@guardian).has?(:agree_and_keep)
- end
+ ReviewableFlaggedPost
+ .where(target_created_by: user)
+ .find_each do |reviewable|
+ if reviewable.actions_for(@guardian).has?(:agree_and_keep)
+ reviewable.perform(@actor, :agree_and_keep)
+ end
+ end
end
def delete_posts(user, category_topic_ids, opts)
@@ -146,7 +155,10 @@ class UserDestroyer
def prepare_for_destroy(user)
PostAction.where(user_id: user.id).delete_all
- UserAction.where('user_id = :user_id OR target_user_id = :user_id OR acting_user_id = :user_id', user_id: user.id).delete_all
+ UserAction.where(
+ "user_id = :user_id OR target_user_id = :user_id OR acting_user_id = :user_id",
+ user_id: user.id,
+ ).delete_all
PostTiming.where(user_id: user.id).delete_all
TopicViewItem.where(user_id: user.id).delete_all
TopicUser.where(user_id: user.id).delete_all
@@ -156,10 +168,9 @@ class UserDestroyer
def optional_transaction(open_transaction: true)
if open_transaction
- User.transaction { yield }
+ User.transaction { yield }
else
yield
end
end
-
end
diff --git a/app/services/user_merger.rb b/app/services/user_merger.rb
index a17089200dc..96af036a464 100644
--- a/app/services/user_merger.rb
+++ b/app/services/user_merger.rb
@@ -33,23 +33,35 @@ class UserMerger
def update_username
return if @source_user.username == @target_user.username
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.updating_username") }, user_ids: [@acting_user.id] if @acting_user
- UsernameChanger.update_username(user_id: @source_user.id,
- old_username: @source_user.username,
- new_username: @target_user.username,
- avatar_template: @target_user.avatar_template,
- asynchronous: false)
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.updating_username") },
+ user_ids: [@acting_user.id]
+ end
+ UsernameChanger.update_username(
+ user_id: @source_user.id,
+ old_username: @source_user.username,
+ new_username: @target_user.username,
+ avatar_template: @target_user.avatar_template,
+ asynchronous: false,
+ )
end
def move_posts
- posts = Post.with_deleted
- .where(user_id: @source_user.id)
- .order(:topic_id, :post_number)
- .pluck(:topic_id, :id)
+ posts =
+ Post
+ .with_deleted
+ .where(user_id: @source_user.id)
+ .order(:topic_id, :post_number)
+ .pluck(:topic_id, :id)
return if posts.count == 0
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.changing_post_ownership") }, user_ids: [@acting_user.id] if @acting_user
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.changing_post_ownership") },
+ user_ids: [@acting_user.id]
+ end
last_topic_id = nil
post_ids = []
@@ -73,12 +85,16 @@ class UserMerger
post_ids: post_ids,
new_owner: @target_user,
acting_user: Discourse.system_user,
- skip_revision: true
+ skip_revision: true,
).change_owner!
end
def merge_given_daily_likes
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.merging_given_daily_likes") }, user_ids: [@acting_user.id] if @acting_user
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.merging_given_daily_likes") },
+ user_ids: [@acting_user.id]
+ end
sql = <<~SQL
INSERT INTO given_daily_likes AS g (user_id, likes_given, given_date, limit_reached)
@@ -107,15 +123,21 @@ class UserMerger
source_user_id: @source_user.id,
target_user_id: @target_user.id,
max_likes_per_day: SiteSetting.max_likes_per_day,
- action_type_id: PostActionType.types[:like]
+ action_type_id: PostActionType.types[:like],
)
end
def merge_post_timings
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.merging_post_timings") }, user_ids: [@acting_user.id] if @acting_user
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.merging_post_timings") },
+ user_ids: [@acting_user.id]
+ end
- update_user_id(:post_timings, conditions: ["x.topic_id = y.topic_id",
- "x.post_number = y.post_number"])
+ update_user_id(
+ :post_timings,
+ conditions: ["x.topic_id = y.topic_id", "x.post_number = y.post_number"],
+ )
sql = <<~SQL
UPDATE post_timings AS t
SET msecs = LEAST(t.msecs::bigint + s.msecs, 2^31 - 1)
@@ -128,7 +150,11 @@ class UserMerger
end
def merge_user_visits
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.merging_user_visits") }, user_ids: [@acting_user.id] if @acting_user
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.merging_user_visits") },
+ user_ids: [@acting_user.id]
+ end
update_user_id(:user_visits, conditions: "x.visited_at = y.visited_at")
@@ -146,17 +172,27 @@ class UserMerger
end
def update_site_settings
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.updating_site_settings") }, user_ids: [@acting_user.id] if @acting_user
-
- SiteSetting.all_settings(include_hidden: true).each do |setting|
- if setting[:type] == "username" && setting[:value] == @source_user.username
- SiteSetting.set_and_log(setting[:setting], @target_user.username)
- end
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.updating_site_settings") },
+ user_ids: [@acting_user.id]
end
+
+ SiteSetting
+ .all_settings(include_hidden: true)
+ .each do |setting|
+ if setting[:type] == "username" && setting[:value] == @source_user.username
+ SiteSetting.set_and_log(setting[:setting], @target_user.username)
+ end
+ end
end
def update_user_stats
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.updating_user_stats") }, user_ids: [@acting_user.id] if @acting_user
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.updating_user_stats") },
+ user_ids: [@acting_user.id]
+ end
# topics_entered
DB.exec(<<~SQL, target_user_id: @target_user.id)
@@ -212,7 +248,11 @@ class UserMerger
end
def merge_user_attributes
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.merging_user_attributes") }, user_ids: [@acting_user.id] if @acting_user
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.merging_user_attributes") },
+ user_ids: [@acting_user.id]
+ end
DB.exec(<<~SQL, source_user_id: @source_user.id, target_user_id: @target_user.id)
UPDATE users AS t
@@ -255,7 +295,11 @@ class UserMerger
end
def update_user_ids
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.updating_user_ids") }, user_ids: [@acting_user.id] if @acting_user
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.updating_user_ids") },
+ user_ids: [@acting_user.id]
+ end
Category.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
@@ -278,23 +322,44 @@ class UserMerger
IncomingEmail.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
IncomingLink.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
- IncomingLink.where(current_user_id: @source_user.id).update_all(current_user_id: @target_user.id)
+ IncomingLink.where(current_user_id: @source_user.id).update_all(
+ current_user_id: @target_user.id,
+ )
InvitedUser.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
- Invite.with_deleted.where(invited_by_id: @source_user.id).update_all(invited_by_id: @target_user.id)
- Invite.with_deleted.where(deleted_by_id: @source_user.id).update_all(deleted_by_id: @target_user.id)
+ Invite
+ .with_deleted
+ .where(invited_by_id: @source_user.id)
+ .update_all(invited_by_id: @target_user.id)
+ Invite
+ .with_deleted
+ .where(deleted_by_id: @source_user.id)
+ .update_all(deleted_by_id: @target_user.id)
update_user_id(:muted_users, conditions: "x.muted_user_id = y.muted_user_id")
- update_user_id(:muted_users, user_id_column_name: "muted_user_id", conditions: "x.user_id = y.user_id")
+ update_user_id(
+ :muted_users,
+ user_id_column_name: "muted_user_id",
+ conditions: "x.user_id = y.user_id",
+ )
update_user_id(:ignored_users, conditions: "x.ignored_user_id = y.ignored_user_id")
- update_user_id(:ignored_users, user_id_column_name: "ignored_user_id", conditions: "x.user_id = y.user_id")
+ update_user_id(
+ :ignored_users,
+ user_id_column_name: "ignored_user_id",
+ conditions: "x.user_id = y.user_id",
+ )
Notification.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
- update_user_id(:post_actions, conditions: ["x.post_id = y.post_id",
- "x.post_action_type_id = y.post_action_type_id",
- "x.targets_topic = y.targets_topic"])
+ update_user_id(
+ :post_actions,
+ conditions: [
+ "x.post_id = y.post_id",
+ "x.post_action_type_id = y.post_action_type_id",
+ "x.targets_topic = y.targets_topic",
+ ],
+ )
PostAction.where(deleted_by_id: @source_user.id).update_all(deleted_by_id: @target_user.id)
PostAction.where(deferred_by_id: @source_user.id).update_all(deferred_by_id: @target_user.id)
@@ -303,13 +368,24 @@ class UserMerger
PostRevision.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
- Post.with_deleted.where(deleted_by_id: @source_user.id).update_all(deleted_by_id: @target_user.id)
- Post.with_deleted.where(last_editor_id: @source_user.id).update_all(last_editor_id: @target_user.id)
+ Post
+ .with_deleted
+ .where(deleted_by_id: @source_user.id)
+ .update_all(deleted_by_id: @target_user.id)
+ Post
+ .with_deleted
+ .where(last_editor_id: @source_user.id)
+ .update_all(last_editor_id: @target_user.id)
Post.with_deleted.where(locked_by_id: @source_user.id).update_all(locked_by_id: @target_user.id)
- Post.with_deleted.where(reply_to_user_id: @source_user.id).update_all(reply_to_user_id: @target_user.id)
+ Post
+ .with_deleted
+ .where(reply_to_user_id: @source_user.id)
+ .update_all(reply_to_user_id: @target_user.id)
Reviewable.where(created_by_id: @source_user.id).update_all(created_by_id: @target_user.id)
- ReviewableHistory.where(created_by_id: @source_user.id).update_all(created_by_id: @target_user.id)
+ ReviewableHistory.where(created_by_id: @source_user.id).update_all(
+ created_by_id: @target_user.id,
+ )
SearchLog.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
@@ -319,22 +395,36 @@ class UserMerger
update_user_id(:topic_allowed_users, conditions: "x.topic_id = y.topic_id")
- TopicEmbed.with_deleted.where(deleted_by_id: @source_user.id).update_all(deleted_by_id: @target_user.id)
+ TopicEmbed
+ .with_deleted
+ .where(deleted_by_id: @source_user.id)
+ .update_all(deleted_by_id: @target_user.id)
TopicLink.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
TopicLinkClick.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
- TopicTimer.with_deleted.where(deleted_by_id: @source_user.id).update_all(deleted_by_id: @target_user.id)
+ TopicTimer
+ .with_deleted
+ .where(deleted_by_id: @source_user.id)
+ .update_all(deleted_by_id: @target_user.id)
- update_user_id(:topic_timers, conditions: ["x.status_type = y.status_type",
- "x.topic_id = y.topic_id",
- "y.deleted_at IS NULL"])
+ update_user_id(
+ :topic_timers,
+ conditions: [
+ "x.status_type = y.status_type",
+ "x.topic_id = y.topic_id",
+ "y.deleted_at IS NULL",
+ ],
+ )
update_user_id(:topic_users, conditions: "x.topic_id = y.topic_id")
update_user_id(:topic_views, conditions: "x.topic_id = y.topic_id")
- Topic.with_deleted.where(deleted_by_id: @source_user.id).update_all(deleted_by_id: @target_user.id)
+ Topic
+ .with_deleted
+ .where(deleted_by_id: @source_user.id)
+ .update_all(deleted_by_id: @target_user.id)
UnsubscribeKey.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
@@ -342,29 +432,46 @@ class UserMerger
update_user_id(:user_archived_messages, conditions: "x.topic_id = y.topic_id")
- update_user_id(:user_actions,
- user_id_column_name: "user_id",
- conditions: ["x.action_type = y.action_type",
- "x.target_topic_id IS NOT DISTINCT FROM y.target_topic_id",
- "x.target_post_id IS NOT DISTINCT FROM y.target_post_id",
- "(x.acting_user_id IN (:source_user_id, :target_user_id) OR x.acting_user_id IS NOT DISTINCT FROM y.acting_user_id)"])
- update_user_id(:user_actions,
- user_id_column_name: "acting_user_id",
- conditions: ["x.action_type = y.action_type",
- "x.user_id = y.user_id",
- "x.target_topic_id IS NOT DISTINCT FROM y.target_topic_id",
- "x.target_post_id IS NOT DISTINCT FROM y.target_post_id"])
+ update_user_id(
+ :user_actions,
+ user_id_column_name: "user_id",
+ conditions: [
+ "x.action_type = y.action_type",
+ "x.target_topic_id IS NOT DISTINCT FROM y.target_topic_id",
+ "x.target_post_id IS NOT DISTINCT FROM y.target_post_id",
+ "(x.acting_user_id IN (:source_user_id, :target_user_id) OR x.acting_user_id IS NOT DISTINCT FROM y.acting_user_id)",
+ ],
+ )
+ update_user_id(
+ :user_actions,
+ user_id_column_name: "acting_user_id",
+ conditions: [
+ "x.action_type = y.action_type",
+ "x.user_id = y.user_id",
+ "x.target_topic_id IS NOT DISTINCT FROM y.target_topic_id",
+ "x.target_post_id IS NOT DISTINCT FROM y.target_post_id",
+ ],
+ )
- update_user_id(:user_badges, conditions: ["x.badge_id = y.badge_id",
- "x.seq = y.seq",
- "x.post_id IS NOT DISTINCT FROM y.post_id"])
+ update_user_id(
+ :user_badges,
+ conditions: [
+ "x.badge_id = y.badge_id",
+ "x.seq = y.seq",
+ "x.post_id IS NOT DISTINCT FROM y.post_id",
+ ],
+ )
UserBadge.where(granted_by_id: @source_user.id).update_all(granted_by_id: @target_user.id)
update_user_id(:user_custom_fields, conditions: "x.name = y.name")
if @target_user.human?
- update_user_id(:user_emails, conditions: "x.email = y.email OR y.primary = false", updates: '"primary" = false')
+ update_user_id(
+ :user_emails,
+ conditions: "x.email = y.email OR y.primary = false",
+ updates: '"primary" = false',
+ )
end
UserExport.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
@@ -372,7 +479,9 @@ class UserMerger
UserHistory.where(target_user_id: @source_user.id).update_all(target_user_id: @target_user.id)
UserHistory.where(acting_user_id: @source_user.id).update_all(acting_user_id: @target_user.id)
- UserProfileView.where(user_profile_id: @source_user.id).update_all(user_profile_id: @target_user.id)
+ UserProfileView.where(user_profile_id: @source_user.id).update_all(
+ user_profile_id: @target_user.id,
+ )
UserProfileView.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
UserWarning.where(user_id: @source_user.id).update_all(user_id: @target_user.id)
@@ -382,14 +491,18 @@ class UserMerger
end
def delete_source_user
- ::MessageBus.publish '/merge_user', { message: I18n.t("admin.user.merge_user.deleting_source_user") }, user_ids: [@acting_user.id] if @acting_user
+ if @acting_user
+ ::MessageBus.publish "/merge_user",
+ { message: I18n.t("admin.user.merge_user.deleting_source_user") },
+ user_ids: [@acting_user.id]
+ end
@source_user.reload
@source_user.skip_email_validation = true
@source_user.update(
admin: false,
- email: "#{@source_user.username}_#{SecureRandom.hex}@no-email.invalid"
+ email: "#{@source_user.username}_#{SecureRandom.hex}@no-email.invalid",
)
UserDestroyer.new(Discourse.system_user).destroy(@source_user, quiet: true)
diff --git a/app/services/user_notification_renderer.rb b/app/services/user_notification_renderer.rb
index e66b7d9decd..673a53dec20 100644
--- a/app/services/user_notification_renderer.rb
+++ b/app/services/user_notification_renderer.rb
@@ -9,9 +9,10 @@ class UserNotificationRenderer < ActionView::Base
def self.render(*args)
LOCK.synchronize do
- @instance ||= UserNotificationRenderer.with_empty_template_cache.with_view_paths(
- Rails.configuration.paths["app/views"]
- )
+ @instance ||=
+ UserNotificationRenderer.with_empty_template_cache.with_view_paths(
+ Rails.configuration.paths["app/views"],
+ )
@instance.render(*args)
end
end
diff --git a/app/services/user_notification_schedule_processor.rb b/app/services/user_notification_schedule_processor.rb
index 7b924b22d43..6a340ca14ed 100644
--- a/app/services/user_notification_schedule_processor.rb
+++ b/app/services/user_notification_schedule_processor.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class UserNotificationScheduleProcessor
-
attr_accessor :schedule, :user, :timezone_name
def initialize(schedule)
@@ -38,10 +37,11 @@ class UserNotificationScheduleProcessor
user.do_not_disturb_timings.find_or_create_by(previous_timing.attributes.except("id"))
end
- next_timing = user.do_not_disturb_timings.new(
- starts_at: utc_time_at_minute(local_time, end_minute),
- scheduled: true
- )
+ next_timing =
+ user.do_not_disturb_timings.new(
+ starts_at: utc_time_at_minute(local_time, end_minute),
+ scheduled: true,
+ )
save_timing_and_continue(local_time, next_timing, days)
else
save_timing_and_continue(local_time, previous_timing, days)
@@ -53,14 +53,13 @@ class UserNotificationScheduleProcessor
def find_previous_timing(local_time)
# Try and find a previously scheduled dnd timing that we can extend if the
# ends_at is at the previous midnight. fallback to a new timing if not.
- previous = user.do_not_disturb_timings.find_by(
- ends_at: (local_time - 1.day).end_of_day.utc,
- scheduled: true
- )
- previous || user.do_not_disturb_timings.new(
- starts_at: local_time.beginning_of_day.utc,
- scheduled: true
- )
+ previous =
+ user.do_not_disturb_timings.find_by(
+ ends_at: (local_time - 1.day).end_of_day.utc,
+ scheduled: true,
+ )
+ previous ||
+ user.do_not_disturb_timings.new(starts_at: local_time.beginning_of_day.utc, scheduled: true)
end
def save_timing_and_continue(local_time, timing, days)
@@ -78,7 +77,15 @@ class UserNotificationScheduleProcessor
def utc_time_at_minute(base_time, total_minutes)
hour = total_minutes / 60
minute = total_minutes % 60
- Time.new(base_time.year, base_time.month, base_time.day, hour, minute, 0, base_time.formatted_offset).utc
+ Time.new(
+ base_time.year,
+ base_time.month,
+ base_time.day,
+ hour,
+ minute,
+ 0,
+ base_time.formatted_offset,
+ ).utc
end
def transform_wday(wday)
diff --git a/app/services/user_silencer.rb b/app/services/user_silencer.rb
index 10c3b1c74a4..50ae7b4ab72 100644
--- a/app/services/user_silencer.rb
+++ b/app/services/user_silencer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class UserSilencer
-
attr_reader :user_history
def initialize(user, by_user = nil, opts = {})
@@ -29,11 +28,7 @@ class UserSilencer
if @user.save
message_type = @opts[:message] || :silenced_by_staff
- details = StaffMessageFormat.new(
- :silence,
- @opts[:reason],
- @opts[:message_body]
- ).format
+ details = StaffMessageFormat.new(:silence, @opts[:reason], @opts[:message_body]).format
context = "#{message_type}: #{@opts[:reason]}"
@@ -41,10 +36,7 @@ class UserSilencer
log_params = { context: context, details: details }
log_params[:post_id] = @opts[:post_id].to_i if @opts[:post_id]
- @user_history = StaffActionLogger.new(@by_user).log_silence_user(
- @user,
- log_params
- )
+ @user_history = StaffActionLogger.new(@by_user).log_silence_user(@user, log_params)
end
silence_message_params = {}
@@ -58,7 +50,7 @@ class UserSilencer
post_id: @opts[:post_id],
silenced_till: @user.silenced_till,
silenced_at: DateTime.now,
- silence_message_params: silence_message_params
+ silence_message_params: silence_message_params,
)
silence_message_params.merge!(post_alert_options: { skip_send_email: true })
@@ -73,8 +65,20 @@ class UserSilencer
def hide_posts
return unless @user.trust_level == TrustLevel[0]
- Post.where(user_id: @user.id).where("created_at > ?", 24.hours.ago).update_all(["hidden = true, hidden_reason_id = COALESCE(hidden_reason_id, ?)", Post.hidden_reasons[:new_user_spam_threshold_reached]])
- topic_ids = Post.where(user_id: @user.id, post_number: 1).where("created_at > ?", 24.hours.ago).pluck(:topic_id)
+ Post
+ .where(user_id: @user.id)
+ .where("created_at > ?", 24.hours.ago)
+ .update_all(
+ [
+ "hidden = true, hidden_reason_id = COALESCE(hidden_reason_id, ?)",
+ Post.hidden_reasons[:new_user_spam_threshold_reached],
+ ],
+ )
+ topic_ids =
+ Post
+ .where(user_id: @user.id, post_number: 1)
+ .where("created_at > ?", 24.hours.ago)
+ .pluck(:topic_id)
Topic.where(id: topic_ids).update_all(visible: false) unless topic_ids.empty?
end
@@ -86,5 +90,4 @@ class UserSilencer
StaffActionLogger.new(@by_user).log_unsilence_user(@user) if @by_user
end
end
-
end
diff --git a/app/services/user_stat_count_updater.rb b/app/services/user_stat_count_updater.rb
index dac3e086b40..ed55e620acd 100644
--- a/app/services/user_stat_count_updater.rb
+++ b/app/services/user_stat_count_updater.rb
@@ -12,11 +12,11 @@ class UserStatCountUpdater
def set!(user_stat:, count:, count_column:)
return if user_stat.blank?
- return if ![:post_count, :topic_count].include?(count_column)
+ return if !%i[post_count topic_count].include?(count_column)
if SiteSetting.verbose_user_stat_count_logging && count < 0
Rails.logger.warn(
- "Attempted to insert negative count into UserStat##{count_column} for user #{user_stat.user_id}, using 0 instead. Caller:\n #{caller[0..10].join("\n")}"
+ "Attempted to insert negative count into UserStat##{count_column} for user #{user_stat.user_id}, using 0 instead. Caller:\n #{caller[0..10].join("\n")}",
)
end
@@ -47,7 +47,7 @@ class UserStatCountUpdater
if action == :decrement! && stat.public_send(column) < 1
if SiteSetting.verbose_user_stat_count_logging
Rails.logger.warn(
- "Attempted to insert negative count into UserStat##{column} for post with id '#{post.id}'. Caller:\n #{caller[0..10].join("\n")}"
+ "Attempted to insert negative count into UserStat##{column} for post with id '#{post.id}'. Caller:\n #{caller[0..10].join("\n")}",
)
end
diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb
index d537b7d0e99..511755628f4 100644
--- a/app/services/user_updater.rb
+++ b/app/services/user_updater.rb
@@ -1,66 +1,65 @@
# frozen_string_literal: true
class UserUpdater
-
CATEGORY_IDS = {
watched_first_post_category_ids: :watching_first_post,
watched_category_ids: :watching,
tracked_category_ids: :tracking,
regular_category_ids: :regular,
- muted_category_ids: :muted
+ muted_category_ids: :muted,
}
TAG_NAMES = {
watching_first_post_tags: :watching_first_post,
watched_tags: :watching,
tracked_tags: :tracking,
- muted_tags: :muted
+ muted_tags: :muted,
}
- OPTION_ATTR = [
- :mailing_list_mode,
- :mailing_list_mode_frequency,
- :email_digests,
- :email_level,
- :email_messages_level,
- :external_links_in_new_tab,
- :enable_quoting,
- :enable_defer,
- :color_scheme_id,
- :dark_scheme_id,
- :dynamic_favicon,
- :automatically_unpin_topics,
- :digest_after_minutes,
- :new_topic_duration_minutes,
- :auto_track_topics_after_msecs,
- :notification_level_when_replying,
- :email_previous_replies,
- :email_in_reply_to,
- :like_notification_frequency,
- :include_tl0_in_digests,
- :theme_ids,
- :allow_private_messages,
- :enable_allowed_pm_users,
- :homepage_id,
- :hide_profile_and_presence,
- :text_size,
- :title_count_mode,
- :timezone,
- :skip_new_user_tips,
- :seen_popups,
- :default_calendar,
- :sidebar_list_destination,
- :bookmark_auto_delete_preference
+ OPTION_ATTR = %i[
+ mailing_list_mode
+ mailing_list_mode_frequency
+ email_digests
+ email_level
+ email_messages_level
+ external_links_in_new_tab
+ enable_quoting
+ enable_defer
+ color_scheme_id
+ dark_scheme_id
+ dynamic_favicon
+ automatically_unpin_topics
+ digest_after_minutes
+ new_topic_duration_minutes
+ auto_track_topics_after_msecs
+ notification_level_when_replying
+ email_previous_replies
+ email_in_reply_to
+ like_notification_frequency
+ include_tl0_in_digests
+ theme_ids
+ allow_private_messages
+ enable_allowed_pm_users
+ homepage_id
+ hide_profile_and_presence
+ text_size
+ title_count_mode
+ timezone
+ skip_new_user_tips
+ seen_popups
+ default_calendar
+ sidebar_list_destination
+ bookmark_auto_delete_preference
]
- NOTIFICATION_SCHEDULE_ATTRS = -> {
+ NOTIFICATION_SCHEDULE_ATTRS = -> do
attrs = [:enabled]
7.times do |n|
attrs.push("day_#{n}_start_time".to_sym)
attrs.push("day_#{n}_end_time".to_sym)
end
{ user_notification_schedule: attrs }
- }.call
+ end.call
def initialize(actor, user)
@user = user
@@ -70,7 +69,9 @@ class UserUpdater
def update(attributes = {})
user_profile = user.user_profile
- user_profile.dismissed_banner_key = attributes[:dismissed_banner_key] if attributes[:dismissed_banner_key].present?
+ user_profile.dismissed_banner_key = attributes[:dismissed_banner_key] if attributes[
+ :dismissed_banner_key
+ ].present?
unless SiteSetting.enable_discourse_connect && SiteSetting.discourse_connect_overrides_bio
user_profile.bio_raw = attributes.fetch(:bio_raw) { user_profile.bio_raw }
end
@@ -83,56 +84,52 @@ class UserUpdater
user_profile.website = format_url(attributes.fetch(:website) { user_profile.website })
end
- if attributes[:profile_background_upload_url] == "" || !guardian.can_upload_profile_header?(user)
+ if attributes[:profile_background_upload_url] == "" ||
+ !guardian.can_upload_profile_header?(user)
user_profile.profile_background_upload_id = nil
elsif upload = Upload.get_from_url(attributes[:profile_background_upload_url])
user_profile.profile_background_upload_id = upload.id
end
- if attributes[:card_background_upload_url] == "" || !guardian.can_upload_user_card_background?(user)
+ if attributes[:card_background_upload_url] == "" ||
+ !guardian.can_upload_user_card_background?(user)
user_profile.card_background_upload_id = nil
elsif upload = Upload.get_from_url(attributes[:card_background_upload_url])
user_profile.card_background_upload_id = upload.id
end
if attributes[:user_notification_schedule]
- user_notification_schedule = user.user_notification_schedule || UserNotificationSchedule.new(user: user)
+ user_notification_schedule =
+ user.user_notification_schedule || UserNotificationSchedule.new(user: user)
user_notification_schedule.assign_attributes(attributes[:user_notification_schedule])
end
old_user_name = user.name.present? ? user.name : ""
- if guardian.can_edit_name?(user)
- user.name = attributes.fetch(:name) { user.name }
- end
+ user.name = attributes.fetch(:name) { user.name } if guardian.can_edit_name?(user)
user.locale = attributes.fetch(:locale) { user.locale }
user.date_of_birth = attributes.fetch(:date_of_birth) { user.date_of_birth }
- if attributes[:title] &&
- attributes[:title] != user.title &&
- guardian.can_grant_title?(user, attributes[:title])
+ if attributes[:title] && attributes[:title] != user.title &&
+ guardian.can_grant_title?(user, attributes[:title])
user.title = attributes[:title]
end
- if SiteSetting.user_selected_primary_groups &&
- attributes[:primary_group_id] &&
- attributes[:primary_group_id] != user.primary_group_id &&
- guardian.can_use_primary_group?(user, attributes[:primary_group_id])
-
+ if SiteSetting.user_selected_primary_groups && attributes[:primary_group_id] &&
+ attributes[:primary_group_id] != user.primary_group_id &&
+ guardian.can_use_primary_group?(user, attributes[:primary_group_id])
user.primary_group_id = attributes[:primary_group_id]
- elsif SiteSetting.user_selected_primary_groups &&
- attributes[:primary_group_id] &&
- attributes[:primary_group_id].blank?
-
+ elsif SiteSetting.user_selected_primary_groups && attributes[:primary_group_id] &&
+ attributes[:primary_group_id].blank?
user.primary_group_id = nil
end
- if attributes[:flair_group_id] &&
- attributes[:flair_group_id] != user.flair_group_id &&
- (attributes[:flair_group_id].blank? ||
- guardian.can_use_flair_group?(user, attributes[:flair_group_id]))
-
+ if attributes[:flair_group_id] && attributes[:flair_group_id] != user.flair_group_id &&
+ (
+ attributes[:flair_group_id].blank? ||
+ guardian.can_use_flair_group?(user, attributes[:flair_group_id])
+ )
user.flair_group_id = attributes[:flair_group_id]
end
@@ -145,7 +142,7 @@ class UserUpdater
TAG_NAMES.each do |attribute, level|
if attributes.has_key?(attribute)
- TagUser.batch_set(user, level, attributes[attribute]&.split(',') || [])
+ TagUser.batch_set(user, level, attributes[attribute]&.split(",") || [])
end
end
end
@@ -165,7 +162,8 @@ class UserUpdater
end
if attributes.key?(:text_size)
- user.user_option.text_size_seq += 1 if user.user_option.text_size.to_s != attributes[:text_size]
+ user.user_option.text_size_seq += 1 if user.user_option.text_size.to_s !=
+ attributes[:text_size]
end
OPTION_ATTR.each do |attribute|
@@ -173,7 +171,7 @@ class UserUpdater
save_options = true
if [true, false].include?(user.user_option.public_send(attribute))
- val = attributes[attribute].to_s == 'true'
+ val = attributes[attribute].to_s == "true"
user.user_option.public_send("#{attribute}=", val)
else
user.user_option.public_send("#{attribute}=", attributes[attribute])
@@ -189,16 +187,12 @@ class UserUpdater
user.user_option.email_digests = false if user.user_option.mailing_list_mode
fields = attributes[:custom_fields]
- if fields.present?
- user.custom_fields = user.custom_fields.merge(fields)
- end
+ user.custom_fields = user.custom_fields.merge(fields) if fields.present?
saved = nil
User.transaction do
- if attributes.key?(:muted_usernames)
- update_muted_users(attributes[:muted_usernames])
- end
+ update_muted_users(attributes[:muted_usernames]) if attributes.key?(:muted_usernames)
if attributes.key?(:allowed_pm_usernames)
update_allowed_pm_users(attributes[:allowed_pm_usernames])
@@ -213,11 +207,17 @@ class UserUpdater
end
if attributes.key?(:sidebar_category_ids)
- SidebarSectionLinksUpdater.update_category_section_links(user, category_ids: attributes[:sidebar_category_ids])
+ SidebarSectionLinksUpdater.update_category_section_links(
+ user,
+ category_ids: attributes[:sidebar_category_ids],
+ )
end
if attributes.key?(:sidebar_tag_names) && SiteSetting.tagging_enabled
- SidebarSectionLinksUpdater.update_tag_section_links(user, tag_names: attributes[:sidebar_tag_names])
+ SidebarSectionLinksUpdater.update_tag_section_links(
+ user,
+ tag_names: attributes[:sidebar_tag_names],
+ )
end
if SiteSetting.enable_user_status?
@@ -225,17 +225,16 @@ class UserUpdater
end
name_changed = user.name_changed?
- saved = (!save_options || user.user_option.save) &&
- (user_notification_schedule.nil? || user_notification_schedule.save) &&
- user_profile.save &&
- user.save
+ saved =
+ (!save_options || user.user_option.save) &&
+ (user_notification_schedule.nil? || user_notification_schedule.save) &&
+ user_profile.save && user.save
if saved && (name_changed && old_user_name.casecmp(attributes.fetch(:name)) != 0)
-
StaffActionLogger.new(@actor).log_name_change(
user.id,
old_user_name,
- attributes.fetch(:name) { '' }
+ attributes.fetch(:name) { "" },
)
end
rescue Addressable::URI::InvalidURIError => e
@@ -245,16 +244,14 @@ class UserUpdater
if saved
if user_notification_schedule
- user_notification_schedule.enabled ?
- user_notification_schedule.create_do_not_disturb_timings(delete_existing: true) :
+ if user_notification_schedule.enabled
+ user_notification_schedule.create_do_not_disturb_timings(delete_existing: true)
+ else
user_notification_schedule.destroy_scheduled_timings
+ end
end
if attributes.key?(:seen_popups) || attributes.key?(:skip_new_user_tips)
- MessageBus.publish(
- '/user-tips',
- user.user_option.seen_popups,
- user_ids: [user.id]
- )
+ MessageBus.publish("/user-tips", user.user_option.seen_popups, user_ids: [user.id])
end
DiscourseEvent.trigger(:user_updated, user)
end
@@ -269,7 +266,7 @@ class UserUpdater
if desired_ids.empty?
MutedUser.where(user_id: user.id).destroy_all
else
- MutedUser.where('user_id = ? AND muted_user_id not in (?)', user.id, desired_ids).destroy_all
+ MutedUser.where("user_id = ? AND muted_user_id not in (?)", user.id, desired_ids).destroy_all
# SQL is easier here than figuring out how to do the same in AR
DB.exec(<<~SQL, now: Time.now, user_id: user.id, desired_ids: desired_ids)
@@ -290,7 +287,11 @@ class UserUpdater
if desired_ids.empty?
AllowedPmUser.where(user_id: user.id).destroy_all
else
- AllowedPmUser.where('user_id = ? AND allowed_pm_user_id not in (?)', user.id, desired_ids).destroy_all
+ AllowedPmUser.where(
+ "user_id = ? AND allowed_pm_user_id not in (?)",
+ user.id,
+ desired_ids,
+ ).destroy_all
# SQL is easier here than figuring out how to do the same in AR
DB.exec(<<~SQL, now: Time.zone.now, user_id: user.id, desired_ids: desired_ids)
@@ -305,7 +306,11 @@ class UserUpdater
def updated_associated_accounts(associations)
associations.each do |association|
- user_associated_account = UserAssociatedAccount.find_or_initialize_by(user_id: user.id, provider_name: association[:provider_name])
+ user_associated_account =
+ UserAssociatedAccount.find_or_initialize_by(
+ user_id: user.id,
+ provider_name: association[:provider_name],
+ )
if association[:provider_uid].present?
user_associated_account.update!(provider_uid: association[:provider_uid])
else
@@ -329,7 +334,10 @@ class UserUpdater
sso = SingleSignOnRecord.find_or_initialize_by(user_id: user.id)
if external_id.present?
- sso.update!(external_id: discourse_connect[:external_id], last_payload: "external_id=#{discourse_connect[:external_id]}")
+ sso.update!(
+ external_id: discourse_connect[:external_id],
+ last_payload: "external_id=#{discourse_connect[:external_id]}",
+ )
else
sso.destroy!
end
diff --git a/app/services/username_changer.rb b/app/services/username_changer.rb
index bb2f7becc06..10f7d66c22c 100644
--- a/app/services/username_changer.rb
+++ b/app/services/username_changer.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class UsernameChanger
-
def initialize(user, new_username, actor = nil)
@user = user
@old_username = user.username
@@ -37,23 +36,33 @@ class UsernameChanger
StaffActionLogger.new(@actor).log_username_change(@user, @old_username, @new_username)
end
- UsernameChanger.update_username(user_id: @user.id,
- old_username: @old_username,
- new_username: @new_username,
- avatar_template: @user.avatar_template_url,
- asynchronous: asynchronous) if run_update_job
+ if run_update_job
+ UsernameChanger.update_username(
+ user_id: @user.id,
+ old_username: @old_username,
+ new_username: @new_username,
+ avatar_template: @user.avatar_template_url,
+ asynchronous: asynchronous,
+ )
+ end
return true
end
false
end
- def self.update_username(user_id:, old_username:, new_username:, avatar_template:, asynchronous: true)
+ def self.update_username(
+ user_id:,
+ old_username:,
+ new_username:,
+ avatar_template:,
+ asynchronous: true
+ )
args = {
user_id: user_id,
old_username: old_username,
new_username: new_username,
- avatar_template: avatar_template
+ avatar_template: avatar_template,
}
if asynchronous
diff --git a/app/services/username_checker_service.rb b/app/services/username_checker_service.rb
index e724e2bca20..3540d007150 100644
--- a/app/services/username_checker_service.rb
+++ b/app/services/username_checker_service.rb
@@ -17,11 +17,8 @@ class UsernameCheckerService
end
def check_username_availability(username, email)
- available = User.username_available?(
- username,
- email,
- allow_reserved_username: @allow_reserved_username
- )
+ available =
+ User.username_available?(username, email, allow_reserved_username: @allow_reserved_username)
if available
{ available: true, is_developer: is_developer?(email) }
@@ -31,11 +28,11 @@ class UsernameCheckerService
end
def is_developer?(value)
- Rails.configuration.respond_to?(:developer_emails) && Rails.configuration.developer_emails.include?(value)
+ Rails.configuration.respond_to?(:developer_emails) &&
+ Rails.configuration.developer_emails.include?(value)
end
def self.is_developer?(email)
UsernameCheckerService.new.is_developer?(email)
end
-
end
diff --git a/app/services/web_hook_emitter.rb b/app/services/web_hook_emitter.rb
index d8ac652e1c8..738026e48d5 100644
--- a/app/services/web_hook_emitter.rb
+++ b/app/services/web_hook_emitter.rb
@@ -15,17 +15,13 @@ class WebHookEmitter
request: {
write_timeout: REQUEST_TIMEOUT,
read_timeout: REQUEST_TIMEOUT,
- open_timeout: REQUEST_TIMEOUT
+ open_timeout: REQUEST_TIMEOUT,
},
}
- if !@webhook.verify_certificate
- connection_opts[:ssl] = { verify: false }
- end
+ connection_opts[:ssl] = { verify: false } if !@webhook.verify_certificate
- conn = Faraday.new(nil, connection_opts) do |f|
- f.adapter FinalDestination::FaradayAdapter
- end
+ conn = Faraday.new(nil, connection_opts) { |f| f.adapter FinalDestination::FaradayAdapter }
start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
error = nil
@@ -36,17 +32,15 @@ class WebHookEmitter
error = e
end
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - start
- event_update_args = {
- headers: MultiJson.dump(headers),
- duration: duration,
- }
+ event_update_args = { headers: MultiJson.dump(headers), duration: duration }
if response
event_update_args[:response_headers] = MultiJson.dump(response.headers)
event_update_args[:response_body] = response.body
event_update_args[:status] = response.status
else
event_update_args[:status] = -1
- if error.is_a?(Faraday::Error) && error.wrapped_exception.is_a?(FinalDestination::SSRFDetector::DisallowedIpError)
+ if error.is_a?(Faraday::Error) &&
+ error.wrapped_exception.is_a?(FinalDestination::SSRFDetector::DisallowedIpError)
error = I18n.t("webhooks.payload_url.blocked_or_internal")
end
event_update_args[:response_headers] = MultiJson.dump(error: error)
diff --git a/app/services/wildcard_domain_checker.rb b/app/services/wildcard_domain_checker.rb
index 89c64538821..2b2e983a48b 100644
--- a/app/services/wildcard_domain_checker.rb
+++ b/app/services/wildcard_domain_checker.rb
@@ -1,12 +1,11 @@
# frozen_string_literal: true
module WildcardDomainChecker
-
def self.check_domain(domain, external_domain)
- escaped_domain = domain[0] == "*" ? Regexp.escape(domain).sub("\\*", '\S*') : Regexp.escape(domain)
- domain_regex = Regexp.new("\\A#{escaped_domain}\\z", 'i')
+ escaped_domain =
+ domain[0] == "*" ? Regexp.escape(domain).sub("\\*", '\S*') : Regexp.escape(domain)
+ domain_regex = Regexp.new("\\A#{escaped_domain}\\z", "i")
external_domain.match(domain_regex)
end
-
end
diff --git a/app/services/wildcard_url_checker.rb b/app/services/wildcard_url_checker.rb
index f90defe15d0..5f9621c27b5 100644
--- a/app/services/wildcard_url_checker.rb
+++ b/app/services/wildcard_url_checker.rb
@@ -5,7 +5,7 @@ module WildcardUrlChecker
return false if !valid_url?(url_to_check)
escaped_url = Regexp.escape(url).sub("\\*", '\S*')
- url_regex = Regexp.new("\\A#{escaped_url}\\z", 'i')
+ url_regex = Regexp.new("\\A#{escaped_url}\\z", "i")
url_to_check.match?(url_regex)
end
diff --git a/app/services/word_watcher.rb b/app/services/word_watcher.rb
index 3967457e38c..90529705c43 100644
--- a/app/services/word_watcher.rb
+++ b/app/services/word_watcher.rb
@@ -34,17 +34,18 @@ class WordWatcher
def self.get_cached_words(action)
if cache_enabled?
- Discourse.cache.fetch(word_matcher_regexp_key(action), expires_in: 1.day) do
- words_for_action(action).presence
- end
+ Discourse
+ .cache
+ .fetch(word_matcher_regexp_key(action), expires_in: 1.day) do
+ words_for_action(action).presence
+ end
else
words_for_action(action).presence
end
end
def self.serializable_word_matcher_regexp(action)
- word_matcher_regexp_list(action)
- .map { |r| { r.source => { case_sensitive: !r.casefold? } } }
+ word_matcher_regexp_list(action).map { |r| { r.source => { case_sensitive: !r.casefold? } } }
end
# This regexp is run in miniracer, and the client JS app
@@ -64,9 +65,7 @@ class WordWatcher
grouped_words[group_key] << word
end
- regexps = grouped_words
- .select { |_, w| w.present? }
- .transform_values { |w| w.join("|") }
+ regexps = grouped_words.select { |_, w| w.present? }.transform_values { |w| w.join("|") }
if !SiteSetting.watched_words_regular_expressions?
regexps.transform_values! do |regexp|
@@ -75,8 +74,7 @@ class WordWatcher
end
end
- regexps
- .map { |c, regexp| Regexp.new(regexp, c == :case_sensitive ? nil : Regexp::IGNORECASE) }
+ regexps.map { |c, regexp| Regexp.new(regexp, c == :case_sensitive ? nil : Regexp::IGNORECASE) }
rescue RegexpError
raise if raise_errors
[] # Admin will be alerted via admin_dashboard_data.rb
@@ -113,7 +111,7 @@ class WordWatcher
regexps = word_matcher_regexp_list(:censor)
return html if regexps.blank?
- doc = Nokogiri::HTML5::fragment(html)
+ doc = Nokogiri::HTML5.fragment(html)
doc.traverse do |node|
regexps.each do |regexp|
node.content = censor_text_with_regexp(node.content, regexp) if node.text?
@@ -150,9 +148,7 @@ class WordWatcher
end
def self.clear_cache!
- WatchedWord.actions.each do |a, i|
- Discourse.cache.delete word_matcher_regexp_key(a)
- end
+ WatchedWord.actions.each { |a, i| Discourse.cache.delete word_matcher_regexp_key(a) }
end
def requires_approval?
@@ -188,13 +184,15 @@ class WordWatcher
if SiteSetting.watched_words_regular_expressions?
set = Set.new
- @raw.scan(regexp).each do |m|
- if Array === m
- set.add(m.find(&:present?))
- elsif String === m
- set.add(m)
+ @raw
+ .scan(regexp)
+ .each do |m|
+ if Array === m
+ set.add(m.find(&:present?))
+ elsif String === m
+ set.add(m)
+ end
end
- end
matches = set.to_a
else
@@ -214,9 +212,10 @@ class WordWatcher
end
def word_matches?(word, case_sensitive: false)
- Regexp
- .new(WordWatcher.word_to_regexp(word, whole: true), case_sensitive ? nil : Regexp::IGNORECASE)
- .match?(@raw)
+ Regexp.new(
+ WordWatcher.word_to_regexp(word, whole: true),
+ case_sensitive ? nil : Regexp::IGNORECASE,
+ ).match?(@raw)
end
def self.replace_text_with_regexp(text, regexp, replacement)