diff --git a/app/controllers/admin/badges_controller.rb b/app/controllers/admin/badges_controller.rb
index 53089c8e51e..e54860d0855 100644
--- a/app/controllers/admin/badges_controller.rb
+++ b/app/controllers/admin/badges_controller.rb
@@ -88,44 +88,44 @@ class Admin::BadgesController < Admin::AdminController
end
private
- def find_badge
- params.require(:id)
- Badge.find(params[:id])
- end
+ def find_badge
+ params.require(:id)
+ Badge.find(params[:id])
+ end
- # Options:
- # :new - reset the badge id to nil before saving
- 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.protected_system_fields if badge.system?
- allowed -= [:query] unless SiteSetting.enable_badge_sql
+ # Options:
+ # :new - reset the badge id to nil before saving
+ 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.protected_system_fields if badge.system?
+ allowed -= [:query] unless SiteSetting.enable_badge_sql
- params.permit(*allowed)
+ params.permit(*allowed)
- allowed.each do |key|
- badge.send("#{key}=" , params[key]) if params[key]
- end
-
- # Badge query contract checks
- begin
- if SiteSetting.enable_badge_sql
- BadgeGranter.contract_checks!(badge.query, target_posts: badge.target_posts, trigger: badge.trigger)
- end
- rescue => e
- errors << e.message
- raise ActiveRecord::Rollback
- end
-
- badge.id = nil if opts[:new]
- badge.save!
+ allowed.each do |key|
+ badge.send("#{key}=" , params[key]) if params[key]
end
- errors
- rescue ActiveRecord::RecordInvalid
- errors.push(*badge.errors.full_messages)
- errors
+ # Badge query contract checks
+ begin
+ if SiteSetting.enable_badge_sql
+ BadgeGranter.contract_checks!(badge.query, target_posts: badge.target_posts, trigger: badge.trigger)
+ end
+ rescue => e
+ errors << e.message
+ raise ActiveRecord::Rollback
+ end
+
+ badge.id = nil if opts[:new]
+ badge.save!
end
+
+ errors
+ rescue ActiveRecord::RecordInvalid
+ errors.push(*badge.errors.full_messages)
+ errors
+ end
end
diff --git a/app/controllers/admin/embeddable_hosts_controller.rb b/app/controllers/admin/embeddable_hosts_controller.rb
index 667db524fe8..e70061f0c27 100644
--- a/app/controllers/admin/embeddable_hosts_controller.rb
+++ b/app/controllers/admin/embeddable_hosts_controller.rb
@@ -17,18 +17,18 @@ class Admin::EmbeddableHostsController < Admin::AdminController
protected
- def save_host(host)
- host.host = params[:embeddable_host][:host]
- host.path_whitelist = params[:embeddable_host][:path_whitelist]
- 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?
+ def save_host(host)
+ host.host = params[:embeddable_host][:host]
+ host.path_whitelist = params[:embeddable_host][:path_whitelist]
+ 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
- render_serialized(host, EmbeddableHostSerializer, root: 'embeddable_host', rest_serializer: true)
- else
- render_json_error(host)
- end
+ if host.save
+ 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 ebac31e576e..8f86a9a22d2 100644
--- a/app/controllers/admin/embedding_controller.rb
+++ b/app/controllers/admin/embedding_controller.rb
@@ -27,7 +27,7 @@ class Admin::EmbeddingController < Admin::AdminController
protected
- def fetch_embedding
- @embedding = Embedding.find
- end
+ def fetch_embedding
+ @embedding = Embedding.find
+ end
end
diff --git a/app/controllers/admin/screened_ip_addresses_controller.rb b/app/controllers/admin/screened_ip_addresses_controller.rb
index 775f115195f..6e92777233b 100644
--- a/app/controllers/admin/screened_ip_addresses_controller.rb
+++ b/app/controllers/admin/screened_ip_addresses_controller.rb
@@ -51,13 +51,13 @@ class Admin::ScreenedIpAddressesController < Admin::AdminController
private
- def allowed_params
- params.require(:ip_address)
- params.permit(:ip_address, :action_name)
- end
+ def allowed_params
+ params.require(:ip_address)
+ params.permit(:ip_address, :action_name)
+ end
- def fetch_screened_ip_address
- @screened_ip_address = ScreenedIpAddress.find(params[:id])
- end
+ def fetch_screened_ip_address
+ @screened_ip_address = ScreenedIpAddress.find(params[:id])
+ end
end
diff --git a/app/controllers/admin/site_texts_controller.rb b/app/controllers/admin/site_texts_controller.rb
index 33e636926d5..ffc3633203c 100644
--- a/app/controllers/admin/site_texts_controller.rb
+++ b/app/controllers/admin/site_texts_controller.rb
@@ -75,19 +75,19 @@ class Admin::SiteTextsController < Admin::AdminController
protected
- def record_for(k, value = nil)
- if k.ends_with?("_MF")
- ovr = TranslationOverride.where(translation_key: k, locale: I18n.locale).pluck(:value)
- value = ovr[0] if ovr.present?
- end
-
- value ||= I18n.t(k)
- { id: k, value: value }
+ def record_for(k, value = nil)
+ if k.ends_with?("_MF")
+ ovr = TranslationOverride.where(translation_key: k, locale: I18n.locale).pluck(:value)
+ value = ovr[0] if ovr.present?
end
- def find_site_text
- raise Discourse::NotFound unless I18n.exists?(params[:id]) && !self.class.restricted_keys.include?(params[:id])
- record_for(params[:id])
- end
+ value ||= I18n.t(k)
+ { id: k, value: value }
+ end
+
+ def find_site_text
+ raise Discourse::NotFound unless I18n.exists?(params[:id]) && !self.class.restricted_keys.include?(params[:id])
+ record_for(params[:id])
+ end
end
diff --git a/app/controllers/admin/themes_controller.rb b/app/controllers/admin/themes_controller.rb
index a40ec46998d..ebc74980e09 100644
--- a/app/controllers/admin/themes_controller.rb
+++ b/app/controllers/admin/themes_controller.rb
@@ -223,59 +223,59 @@ class Admin::ThemesController < Admin::AdminController
private
- def update_default_theme
- if theme_params.key?(:default)
- is_default = theme_params[:default].to_s == "true"
- if @theme.key == SiteSetting.default_theme_key && !is_default
- Theme.clear_default!
- elsif is_default
- @theme.set_default!
- end
+ def update_default_theme
+ if theme_params.key?(:default)
+ is_default = theme_params[:default].to_s == "true"
+ if @theme.key == SiteSetting.default_theme_key && !is_default
+ Theme.clear_default!
+ elsif is_default
+ @theme.set_default!
end
end
+ end
- def theme_params
- @theme_params ||=
- begin
- # deep munge is a train wreck, work around it for now
- params[:theme][:child_theme_ids] ||= [] if params[:theme].key?(:child_theme_ids)
+ def theme_params
+ @theme_params ||=
+ begin
+ # deep munge is a train wreck, work around it for now
+ params[:theme][:child_theme_ids] ||= [] if params[:theme].key?(:child_theme_ids)
- params.require(:theme).permit(
- :name,
- :color_scheme_id,
- :default,
- :user_selectable,
- settings: {},
- theme_fields: [:name, :target, :value, :upload_id, :type_id],
- child_theme_ids: []
- )
- end
- end
-
- def set_fields
- return unless fields = theme_params[:theme_fields]
-
- fields.each do |field|
- @theme.set_field(
- target: field[:target],
- name: field[:name],
- value: field[:value],
- type_id: field[:type_id],
- upload_id: field[:upload_id]
+ params.require(:theme).permit(
+ :name,
+ :color_scheme_id,
+ :default,
+ :user_selectable,
+ settings: {},
+ theme_fields: [:name, :target, :value, :upload_id, :type_id],
+ child_theme_ids: []
)
end
- end
+ end
- def update_settings
- return unless target_settings = theme_params[:settings]
+ def set_fields
+ return unless fields = theme_params[:theme_fields]
- target_settings.each_pair do |setting_name, new_value|
- @theme.update_setting(setting_name.to_sym, new_value)
- end
+ fields.each do |field|
+ @theme.set_field(
+ target: field[:target],
+ name: field[:name],
+ value: field[:value],
+ type_id: field[:type_id],
+ upload_id: field[:upload_id]
+ )
end
+ end
- def log_theme_change(old_record, new_record)
- StaffActionLogger.new(current_user).log_theme_change(old_record, new_record)
+ def update_settings
+ return unless target_settings = theme_params[:settings]
+
+ target_settings.each_pair do |setting_name, new_value|
+ @theme.update_setting(setting_name.to_sym, new_value)
end
+ end
+
+ def log_theme_change(old_record, new_record)
+ StaffActionLogger.new(current_user).log_theme_change(old_record, new_record)
+ end
end
diff --git a/app/controllers/admin/user_fields_controller.rb b/app/controllers/admin/user_fields_controller.rb
index 2af8832e333..4ac32bb9118 100644
--- a/app/controllers/admin/user_fields_controller.rb
+++ b/app/controllers/admin/user_fields_controller.rb
@@ -47,11 +47,11 @@ class Admin::UserFieldsController < Admin::AdminController
protected
- def update_options(field)
- options = params[:user_field][:options]
- if options.present?
- UserFieldOption.where(user_field_id: field.id).delete_all
- field.user_field_options_attributes = options.map { |o| { value: o } }.uniq
- end
+ def update_options(field)
+ options = params[:user_field][:options]
+ if options.present?
+ UserFieldOption.where(user_field_id: field.id).delete_all
+ field.user_field_options_attributes = options.map { |o| { value: o } }.uniq
end
+ end
end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 7b7f42096c0..66b5daf9267 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -544,34 +544,34 @@ class Admin::UsersController < Admin::AdminController
private
- def perform_post_action
- return unless params[:post_id].present? &&
- params[:post_action].present?
+ def perform_post_action
+ 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'
- PostDestroyer.new(current_user, post).destroy
- when 'edit'
- revisor = PostRevisor.new(post)
+ if post = Post.where(id: params[:post_id]).first
+ case params[:post_action]
+ when 'delete'
+ PostDestroyer.new(current_user, post).destroy
+ when 'edit'
+ revisor = PostRevisor.new(post)
- # Take what the moderator edited in as gospel
- revisor.revise!(
- current_user,
- { raw: params[:post_edit] },
- skip_validations: true,
- skip_revision: true
- )
- end
+ # Take what the moderator edited in as gospel
+ revisor.revise!(
+ current_user,
+ { raw: params[:post_edit] },
+ skip_validations: true,
+ skip_revision: true
+ )
end
end
+ end
- def fetch_user
- @user = User.find_by(id: params[:user_id])
- end
+ def fetch_user
+ @user = User.find_by(id: params[:user_id])
+ end
- def refresh_browser(user)
- MessageBus.publish "/file-change", ["refresh"], user_ids: [user.id]
- end
+ def refresh_browser(user)
+ MessageBus.publish "/file-change", ["refresh"], user_ids: [user.id]
+ end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d75e4152c82..b9929a9e283 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -462,255 +462,255 @@ class ApplicationController < ActionController::Base
private
- def check_readonly_mode
- @readonly_mode = Discourse.readonly_mode?
+ def check_readonly_mode
+ @readonly_mode = Discourse.readonly_mode?
+ end
+
+ def locale_from_header
+ begin
+ # Rails I18n uses underscores between the locale and the region; the request
+ # headers use hyphens.
+ require 'http_accept_language' unless defined? HttpAcceptLanguage
+ available_locales = I18n.available_locales.map { |locale| locale.to_s.tr('_', '-') }
+ parser = HttpAcceptLanguage::Parser.new(request.env["HTTP_ACCEPT_LANGUAGE"])
+ parser.language_region_compatible_from(available_locales).tr('-', '_')
+ rescue
+ # If Accept-Language headers are not set.
+ I18n.default_locale
end
+ end
- def locale_from_header
- begin
- # Rails I18n uses underscores between the locale and the region; the request
- # headers use hyphens.
- require 'http_accept_language' unless defined? HttpAcceptLanguage
- available_locales = I18n.available_locales.map { |locale| locale.to_s.tr('_', '-') }
- parser = HttpAcceptLanguage::Parser.new(request.env["HTTP_ACCEPT_LANGUAGE"])
- parser.language_region_compatible_from(available_locales).tr('-', '_')
- rescue
- # If Accept-Language headers are not set.
- I18n.default_locale
- end
- end
+ def preload_anonymous_data
+ store_preloaded("site", Site.json_for(guardian))
+ store_preloaded("siteSettings", SiteSetting.client_settings_json)
+ store_preloaded("themeSettings", Theme.settings_for_client(@theme_key))
+ store_preloaded("customHTML", custom_html_json)
+ store_preloaded("banner", banner_json)
+ store_preloaded("customEmoji", custom_emoji)
+ store_preloaded("translationOverrides", I18n.client_overrides_json(I18n.locale))
+ end
- def preload_anonymous_data
- store_preloaded("site", Site.json_for(guardian))
- store_preloaded("siteSettings", SiteSetting.client_settings_json)
- store_preloaded("themeSettings", Theme.settings_for_client(@theme_key))
- store_preloaded("customHTML", custom_html_json)
- store_preloaded("banner", banner_json)
- store_preloaded("customEmoji", custom_emoji)
- store_preloaded("translationOverrides", I18n.client_overrides_json(I18n.locale))
- 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)
+ store_preloaded("topicTrackingStates", MultiJson.dump(serializer))
+ 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)
- store_preloaded("topicTrackingStates", MultiJson.dump(serializer))
- end
+ def custom_html_json
+ target = view_context.mobile_view? ? :mobile : :desktop
- def custom_html_json
- target = view_context.mobile_view? ? :mobile : :desktop
-
- data =
- if @theme_key
- {
- top: Theme.lookup_field(@theme_key, target, "after_header"),
- footer: Theme.lookup_field(@theme_key, target, "footer")
- }
- else
- {}
- end
-
- if DiscoursePluginRegistry.custom_html
- data.merge! DiscoursePluginRegistry.custom_html
- end
-
- DiscoursePluginRegistry.html_builders.each do |name, _|
- if name.start_with?("client:")
- data[name.sub(/^client:/, '')] = DiscoursePluginRegistry.build_html(name, self)
- end
- end
-
- MultiJson.dump(data)
- end
-
- def self.banner_json_cache
- @banner_json_cache ||= DistributedCache.new("banner_json")
- end
-
- def banner_json
- json = ApplicationController.banner_json_cache["json"]
-
- unless json
- topic = Topic.where(archetype: Archetype.banner).first
- banner = topic.present? ? topic.banner : {}
- ApplicationController.banner_json_cache["json"] = json = MultiJson.dump(banner)
- end
-
- json
- end
-
- def custom_emoji
- serializer = ActiveModel::ArraySerializer.new(Emoji.custom, each_serializer: EmojiSerializer)
- MultiJson.dump(serializer)
- end
-
- # Render action for a JSON error.
- #
- # obj - a translated string, an ActiveRecord model, or an array of translated strings
- # opts:
- # type - a machine-readable description of the error
- # status - HTTP status code to return
- # headers - extra headers for the response
- def render_json_error(obj, opts = {})
- opts = { status: opts } if opts.is_a?(Integer)
- opts.fetch(:headers, {}).each { |name, value| headers[name.to_s] = value }
-
- render json: MultiJson.dump(create_errors_json(obj, opts)), status: opts[:status] || 422
- end
-
- def success_json
- { success: 'OK' }
- end
-
- def failed_json
- { failed: 'FAILED' }
- end
-
- def json_result(obj, opts = {})
- if yield(obj)
- json = success_json
-
- # 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
- end
-
- render json: MultiJson.dump(json)
+ data =
+ if @theme_key
+ {
+ top: Theme.lookup_field(@theme_key, target, "after_header"),
+ footer: Theme.lookup_field(@theme_key, target, "footer")
+ }
else
- error_obj = nil
- if opts[:additional_errors]
- error_target = opts[:additional_errors].find do |o|
- target = obj.send(o)
- target && target.errors.present?
- end
- error_obj = obj.send(error_target) if error_target
+ {}
+ end
+
+ if DiscoursePluginRegistry.custom_html
+ data.merge! DiscoursePluginRegistry.custom_html
+ end
+
+ DiscoursePluginRegistry.html_builders.each do |name, _|
+ if name.start_with?("client:")
+ data[name.sub(/^client:/, '')] = DiscoursePluginRegistry.build_html(name, self)
+ end
+ end
+
+ MultiJson.dump(data)
+ end
+
+ def self.banner_json_cache
+ @banner_json_cache ||= DistributedCache.new("banner_json")
+ end
+
+ def banner_json
+ json = ApplicationController.banner_json_cache["json"]
+
+ unless json
+ topic = Topic.where(archetype: Archetype.banner).first
+ banner = topic.present? ? topic.banner : {}
+ ApplicationController.banner_json_cache["json"] = json = MultiJson.dump(banner)
+ end
+
+ json
+ end
+
+ def custom_emoji
+ serializer = ActiveModel::ArraySerializer.new(Emoji.custom, each_serializer: EmojiSerializer)
+ MultiJson.dump(serializer)
+ end
+
+ # Render action for a JSON error.
+ #
+ # obj - a translated string, an ActiveRecord model, or an array of translated strings
+ # opts:
+ # type - a machine-readable description of the error
+ # status - HTTP status code to return
+ # headers - extra headers for the response
+ def render_json_error(obj, opts = {})
+ opts = { status: opts } if opts.is_a?(Integer)
+ opts.fetch(:headers, {}).each { |name, value| headers[name.to_s] = value }
+
+ render json: MultiJson.dump(create_errors_json(obj, opts)), status: opts[:status] || 422
+ end
+
+ def success_json
+ { success: 'OK' }
+ end
+
+ def failed_json
+ { failed: 'FAILED' }
+ end
+
+ def json_result(obj, opts = {})
+ if yield(obj)
+ json = success_json
+
+ # 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
+ end
+
+ render json: MultiJson.dump(json)
+ else
+ error_obj = nil
+ if opts[:additional_errors]
+ error_target = opts[:additional_errors].find do |o|
+ target = obj.send(o)
+ target && target.errors.present?
end
- render_json_error(error_obj || obj)
+ error_obj = obj.send(error_target) if error_target
end
+ render_json_error(error_obj || obj)
end
+ end
- def mini_profiler_enabled?
- defined?(Rack::MiniProfiler) && (guardian.is_developer? || Rails.env.development?)
- end
+ def mini_profiler_enabled?
+ defined?(Rack::MiniProfiler) && (guardian.is_developer? || Rails.env.development?)
+ end
- def authorize_mini_profiler
- return unless mini_profiler_enabled?
- Rack::MiniProfiler.authorize_request
- end
+ def authorize_mini_profiler
+ return unless mini_profiler_enabled?
+ Rack::MiniProfiler.authorize_request
+ end
- 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 RenderEmpty.new unless ((request.format && request.format.json?) || request.xhr?)
- end
+ 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 RenderEmpty.new unless ((request.format && request.format.json?) || request.xhr?)
+ end
- def self.requires_login(arg = {})
- @requires_login_arg = arg
- end
+ def self.requires_login(arg = {})
+ @requires_login_arg = arg
+ end
- def self.requires_login_arg
- @requires_login_arg
- end
+ def self.requires_login_arg
+ @requires_login_arg
+ end
- def block_if_requires_login
- if arg = self.class.requires_login_arg
- check =
- if except = arg[:except]
- !except.include?(action_name.to_sym)
- elsif only = arg[:only]
- only.include?(action_name.to_sym)
- else
- true
- end
- ensure_logged_in if check
- end
- end
-
- def ensure_logged_in
- raise Discourse::NotLoggedIn.new unless current_user.present?
- end
-
- def ensure_staff
- raise Discourse::InvalidAccess.new unless current_user && current_user.staff?
- end
-
- def ensure_admin
- raise Discourse::InvalidAccess.new unless current_user && current_user.admin?
- end
-
- def ensure_wizard_enabled
- raise Discourse::InvalidAccess.new unless SiteSetting.wizard_enabled?
- end
-
- def destination_url
- request.original_url unless request.original_url =~ /uploads/
- end
-
- def redirect_to_login_if_required
- return if current_user || (request.format.json? && is_api?)
-
- if SiteSetting.login_required?
- flash.keep
-
- if SiteSetting.enable_sso?
- # save original URL in a session so we can redirect after login
- session[:destination_url] = destination_url
- redirect_to path('/session/sso')
- elsif params[:authComplete].present?
- redirect_to path("/login?authComplete=true")
+ def block_if_requires_login
+ if arg = self.class.requires_login_arg
+ check =
+ if except = arg[:except]
+ !except.include?(action_name.to_sym)
+ elsif only = arg[:only]
+ only.include?(action_name.to_sym)
else
- # save original URL in a cookie (javascript redirects after login in this case)
- cookies[:destination_url] = destination_url
- redirect_to path("/login")
+ true
end
+ ensure_logged_in if check
+ end
+ end
+
+ def ensure_logged_in
+ raise Discourse::NotLoggedIn.new unless current_user.present?
+ end
+
+ def ensure_staff
+ raise Discourse::InvalidAccess.new unless current_user && current_user.staff?
+ end
+
+ def ensure_admin
+ raise Discourse::InvalidAccess.new unless current_user && current_user.admin?
+ end
+
+ def ensure_wizard_enabled
+ raise Discourse::InvalidAccess.new unless SiteSetting.wizard_enabled?
+ end
+
+ def destination_url
+ request.original_url unless request.original_url =~ /uploads/
+ end
+
+ def redirect_to_login_if_required
+ return if current_user || (request.format.json? && is_api?)
+
+ if SiteSetting.login_required?
+ flash.keep
+
+ if SiteSetting.enable_sso?
+ # save original URL in a session so we can redirect after login
+ session[:destination_url] = destination_url
+ redirect_to path('/session/sso')
+ elsif params[:authComplete].present?
+ redirect_to path("/login?authComplete=true")
+ else
+ # save original URL in a cookie (javascript redirects after login in this case)
+ cookies[:destination_url] = destination_url
+ redirect_to path("/login")
end
end
+ end
- def block_if_readonly_mode
- return if request.fullpath.start_with?(path "/admin/backups")
- raise Discourse::ReadOnly.new if !(request.get? || request.head?) && @readonly_mode
+ def block_if_readonly_mode
+ return if request.fullpath.start_with?(path "/admin/backups")
+ raise Discourse::ReadOnly.new if !(request.get? || request.head?) && @readonly_mode
+ end
+
+ def build_not_found_page(status = 404, layout = false)
+ if SiteSetting.bootstrap_error_pages?
+ preload_json
+ layout = 'application' if layout == 'no_ember'
end
- def build_not_found_page(status = 404, layout = false)
- if SiteSetting.bootstrap_error_pages?
- preload_json
- layout = 'application' if layout == 'no_ember'
- end
+ category_topic_ids = Category.pluck(:topic_id).compact
+ @container_class = "wrap not-found-container"
+ @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)
+ @slug = params[:slug].class == String ? params[:slug] : ''
+ @slug = (params[:id].class == String ? params[:id] : '') if @slug.blank?
+ @slug.tr!('-', ' ')
+ @hide_google = true if SiteSetting.login_required
+ render_to_string status: status, layout: layout, formats: [:html], template: '/exceptions/not_found'
+ end
- category_topic_ids = Category.pluck(:topic_id).compact
- @container_class = "wrap not-found-container"
- @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)
- @slug = params[:slug].class == String ? params[:slug] : ''
- @slug = (params[:id].class == String ? params[:id] : '') if @slug.blank?
- @slug.tr!('-', ' ')
- @hide_google = true if SiteSetting.login_required
- render_to_string status: status, layout: layout, formats: [:html], template: '/exceptions/not_found'
- end
-
- def is_asset_path
- request.env['DISCOURSE_IS_ASSET_PATH'] = 1
- end
+ def is_asset_path
+ request.env['DISCOURSE_IS_ASSET_PATH'] = 1
+ end
protected
- def render_post_json(post, add_raw = true)
- post_serializer = PostSerializer.new(post, scope: guardian, root: false)
- post_serializer.add_raw = add_raw
+ def render_post_json(post, add_raw = true)
+ post_serializer = PostSerializer.new(post, scope: guardian, root: false)
+ post_serializer.add_raw = add_raw
- counts = PostAction.counts_for([post], current_user)
- if counts && counts = counts[post.id]
- post_serializer.post_actions = counts
- end
- render_json_dump(post_serializer)
+ counts = PostAction.counts_for([post], current_user)
+ if counts && counts = counts[post.id]
+ post_serializer.post_actions = counts
end
+ render_json_dump(post_serializer)
+ end
- # returns an array of integers given a param key
- # returns nil if key is not found
- def param_to_integer_list(key, delimiter = ',')
- if params[key]
- params[key].split(delimiter).map(&:to_i)
- end
+ # returns an array of integers given a param key
+ # returns nil if key is not found
+ def param_to_integer_list(key, delimiter = ',')
+ if params[key]
+ params[key].split(delimiter).map(&:to_i)
end
+ end
end
diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb
index f9216fc56be..b9e86e72760 100644
--- a/app/controllers/categories_controller.rb
+++ b/app/controllers/categories_controller.rb
@@ -201,109 +201,109 @@ class CategoriesController < ApplicationController
end
private
- def categories_and_topics(topics_filter)
- discourse_expires_in 1.minute
+ def categories_and_topics(topics_filter)
+ discourse_expires_in 1.minute
- category_options = {
- is_homepage: current_homepage == "categories".freeze,
- parent_category_id: params[:parent_category_id],
- include_topics: false
- }
+ category_options = {
+ is_homepage: current_homepage == "categories".freeze,
+ parent_category_id: params[:parent_category_id],
+ include_topics: false
+ }
- topic_options = {
- per_page: SiteSetting.categories_topics,
- no_definitions: true,
- exclude_category_ids: Category.where(suppress_from_latest: true).pluck(:id)
- }
+ topic_options = {
+ per_page: SiteSetting.categories_topics,
+ no_definitions: true,
+ exclude_category_ids: Category.where(suppress_from_latest: true).pluck(:id)
+ }
- result = CategoryAndTopicLists.new
- result.category_list = CategoryList.new(guardian, category_options)
+ result = CategoryAndTopicLists.new
+ result.category_list = CategoryList.new(guardian, category_options)
- if topics_filter == :latest
- result.topic_list = TopicQuery.new(current_user, topic_options).list_latest
- elsif topics_filter == :top
- result.topic_list = TopicQuery.new(nil, topic_options).list_top_for(SiteSetting.top_page_default_timeframe.to_sym)
+ if topics_filter == :latest
+ result.topic_list = TopicQuery.new(current_user, topic_options).list_latest
+ elsif topics_filter == :top
+ result.topic_list = TopicQuery.new(nil, topic_options).list_top_for(SiteSetting.top_page_default_timeframe.to_sym)
+ end
+
+ draft_key = Draft::NEW_TOPIC
+ draft_sequence = DraftSequence.current(current_user, draft_key)
+ draft = Draft.get(current_user, draft_key, draft_sequence) if current_user
+
+ %w{category topic}.each do |type|
+ result.send(:"#{type}_list").draft = draft
+ result.send(:"#{type}_list").draft_key = draft_key
+ result.send(:"#{type}_list").draft_sequence = draft_sequence
+ end
+
+ render_serialized(result, CategoryAndTopicListsSerializer, root: false)
+ end
+
+ def required_param_keys
+ [:name, :color, :text_color]
+ end
+
+ def category_params
+ @category_params ||= begin
+ required_param_keys.each do |key|
+ params.require(key)
end
- draft_key = Draft::NEW_TOPIC
- draft_sequence = DraftSequence.current(current_user, draft_key)
- draft = Draft.get(current_user, draft_key, draft_sequence) if current_user
-
- %w{category topic}.each do |type|
- result.send(:"#{type}_list").draft = draft
- result.send(:"#{type}_list").draft_key = draft_key
- result.send(:"#{type}_list").draft_sequence = draft_sequence
+ if p = params[:permissions]
+ p.each do |k, v|
+ p[k] = v.to_i
+ end
end
- render_serialized(result, CategoryAndTopicListsSerializer, root: false)
- end
-
- def required_param_keys
- [:name, :color, :text_color]
- end
-
- def category_params
- @category_params ||= begin
- required_param_keys.each do |key|
- params.require(key)
- end
-
- if p = params[:permissions]
- p.each do |k, v|
- p[k] = v.to_i
- end
- end
-
- if SiteSetting.tagging_enabled
- params[:allowed_tags] ||= []
- params[:allowed_tag_groups] ||= []
- end
-
- params.permit(*required_param_keys,
- :position,
- :email_in,
- :email_in_allow_strangers,
- :mailinglist_mirror,
- :suppress_from_latest,
- :all_topics_wiki,
- :parent_category_id,
- :auto_close_hours,
- :auto_close_based_on_last_post,
- :uploaded_logo_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,
- custom_fields: [params[:custom_fields].try(:keys)],
- permissions: [*p.try(:keys)],
- allowed_tags: [],
- allowed_tag_groups: [])
+ if SiteSetting.tagging_enabled
+ params[:allowed_tags] ||= []
+ params[:allowed_tag_groups] ||= []
end
- end
- def fetch_category
- @category = Category.find_by(slug: params[:id]) || Category.find_by(id: params[:id].to_i)
+ params.permit(*required_param_keys,
+ :position,
+ :email_in,
+ :email_in_allow_strangers,
+ :mailinglist_mirror,
+ :suppress_from_latest,
+ :all_topics_wiki,
+ :parent_category_id,
+ :auto_close_hours,
+ :auto_close_based_on_last_post,
+ :uploaded_logo_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,
+ custom_fields: [params[:custom_fields].try(:keys)],
+ permissions: [*p.try(:keys)],
+ allowed_tags: [],
+ allowed_tag_groups: [])
end
+ end
- def initialize_staff_action_logger
- @staff_action_logger = StaffActionLogger.new(current_user)
- end
+ def fetch_category
+ @category = Category.find_by(slug: params[:id]) || Category.find_by(id: params[:id].to_i)
+ end
- def include_topics(parent_category = nil)
- style = SiteSetting.desktop_category_page_style
- view_context.mobile_view? ||
- params[:include_topics] ||
- (parent_category && parent_category.subcategory_list_includes_topics?) ||
- style == "categories_with_featured_topics".freeze ||
- style == "categories_with_top_topics".freeze
- end
+ def initialize_staff_action_logger
+ @staff_action_logger = StaffActionLogger.new(current_user)
+ end
+
+ def include_topics(parent_category = nil)
+ style = SiteSetting.desktop_category_page_style
+ view_context.mobile_view? ||
+ params[:include_topics] ||
+ (parent_category && parent_category.subcategory_list_includes_topics?) ||
+ style == "categories_with_featured_topics".freeze ||
+ style == "categories_with_top_topics".freeze
+ end
end
diff --git a/app/controllers/clicks_controller.rb b/app/controllers/clicks_controller.rb
index 9602a486256..1aa3a29289e 100644
--- a/app/controllers/clicks_controller.rb
+++ b/app/controllers/clicks_controller.rb
@@ -31,9 +31,9 @@ class ClicksController < ApplicationController
private
- def track_params
- params.require(:url)
- params.permit(:url, :post_id, :topic_id, :redirect)
- end
+ def track_params
+ params.require(:url)
+ params.permit(:url, :post_id, :topic_id, :redirect)
+ end
end
diff --git a/app/controllers/embed_controller.rb b/app/controllers/embed_controller.rb
index 686019e8504..d43754709b2 100644
--- a/app/controllers/embed_controller.rb
+++ b/app/controllers/embed_controller.rb
@@ -92,28 +92,28 @@ class EmbedController < ApplicationController
private
- def get_embeddable_css_class
- @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?
- end
+ def get_embeddable_css_class
+ @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?
+ end
- def ensure_api_request
- raise Discourse::InvalidAccess.new('api key not set') if !is_api?
- end
+ def ensure_api_request
+ raise Discourse::InvalidAccess.new('api key not set') if !is_api?
+ end
- def ensure_embeddable
- if !(Rails.env.development? && current_user&.admin?)
- referer = request.referer
+ def ensure_embeddable
+ if !(Rails.env.development? && current_user&.admin?)
+ referer = request.referer
- unless referer && EmbeddableHost.url_allowed?(referer)
- raise Discourse::InvalidAccess.new('invalid referer host')
- end
+ unless referer && EmbeddableHost.url_allowed?(referer)
+ raise Discourse::InvalidAccess.new('invalid referer host')
end
-
- response.headers['X-Frame-Options'] = "ALLOWALL"
- rescue URI::InvalidURIError
- raise Discourse::InvalidAccess.new('invalid referer host')
end
+ response.headers['X-Frame-Options'] = "ALLOWALL"
+ rescue URI::InvalidURIError
+ raise Discourse::InvalidAccess.new('invalid referer host')
+ end
+
end
diff --git a/app/controllers/exceptions_controller.rb b/app/controllers/exceptions_controller.rb
index 33cbad301b1..540add85c49 100644
--- a/app/controllers/exceptions_controller.rb
+++ b/app/controllers/exceptions_controller.rb
@@ -14,8 +14,8 @@ class ExceptionsController < ApplicationController
private
- def hide_google
- @hide_google = true if SiteSetting.login_required
- end
+ def hide_google
+ @hide_google = true if SiteSetting.login_required
+ end
end
diff --git a/app/controllers/export_csv_controller.rb b/app/controllers/export_csv_controller.rb
index 836ad48d70d..851d1643681 100644
--- a/app/controllers/export_csv_controller.rb
+++ b/app/controllers/export_csv_controller.rb
@@ -9,10 +9,10 @@ class ExportCsvController < ApplicationController
end
private
- def export_params
- @_export_params ||= begin
- params.require(:entity)
- params.permit(:entity, args: [:name, :start_date, :end_date, :category_id, :group_id, :trust_level]).to_h
- end
+ def export_params
+ @_export_params ||= begin
+ params.require(:entity)
+ params.permit(:entity, args: [:name, :start_date, :end_date, :category_id, :group_id, :trust_level]).to_h
end
+ end
end
diff --git a/app/controllers/finish_installation_controller.rb b/app/controllers/finish_installation_controller.rb
index 4640677ebca..c896724a494 100644
--- a/app/controllers/finish_installation_controller.rb
+++ b/app/controllers/finish_installation_controller.rb
@@ -48,18 +48,18 @@ class FinishInstallationController < ApplicationController
protected
- def redirect_confirm(email)
- session[:registered_email] = email
- redirect_to(finish_installation_confirm_email_path)
- end
+ def redirect_confirm(email)
+ session[:registered_email] = email
+ redirect_to(finish_installation_confirm_email_path)
+ end
- def find_allowed_emails
- return [] unless GlobalSetting.respond_to?(:developer_emails) && GlobalSetting.developer_emails.present?
- GlobalSetting.developer_emails.split(",").map(&:strip)
- end
+ def find_allowed_emails
+ return [] unless GlobalSetting.respond_to?(:developer_emails) && GlobalSetting.developer_emails.present?
+ GlobalSetting.developer_emails.split(",").map(&:strip)
+ end
- def ensure_no_admins
- preload_anonymous_data
- raise Discourse::InvalidAccess.new unless SiteSetting.has_login_hint?
- end
+ def ensure_no_admins
+ preload_anonymous_data
+ raise Discourse::InvalidAccess.new unless SiteSetting.has_login_hint?
+ end
end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index 10933affcfe..c2c51ddf1e2 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -211,14 +211,14 @@ class InvitesController < ApplicationController
private
- def post_process_invite(user)
- user.enqueue_welcome_message('welcome_invite') if user.send_welcome_message
- if user.has_password?
- email_token = user.email_tokens.create(email: user.email)
- Jobs.enqueue(:critical_user_email, type: :signup, user_id: user.id, email_token: email_token.token)
- elsif !SiteSetting.enable_sso && SiteSetting.enable_local_logins
- Jobs.enqueue(:invite_password_instructions_email, username: user.username)
- end
+ def post_process_invite(user)
+ user.enqueue_welcome_message('welcome_invite') if user.send_welcome_message
+ if user.has_password?
+ email_token = user.email_tokens.create(email: user.email)
+ Jobs.enqueue(:critical_user_email, type: :signup, user_id: user.id, email_token: email_token.token)
+ elsif !SiteSetting.enable_sso && SiteSetting.enable_local_logins
+ Jobs.enqueue(:invite_password_instructions_email, username: user.username)
end
+ end
end
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index 7fbc06a2b06..50d715933b2 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -84,16 +84,16 @@ class NotificationsController < ApplicationController
private
- def set_notification
- @notification = Notification.find(params[:id])
- end
+ def set_notification
+ @notification = Notification.find(params[:id])
+ end
- def notification_params
- params.permit(:notification_type, :user_id, :data, :read, :topic_id, :post_number, :post_action_id)
- end
+ def notification_params
+ params.permit(:notification_type, :user_id, :data, :read, :topic_id, :post_number, :post_action_id)
+ end
- def render_notification
- render_json_dump(NotificationSerializer.new(@notification, scope: guardian, root: false))
- end
+ def render_notification
+ render_json_dump(NotificationSerializer.new(@notification, scope: guardian, root: false))
+ end
end
diff --git a/app/controllers/post_actions_controller.rb b/app/controllers/post_actions_controller.rb
index fa0314b999c..3e5b0c8e845 100644
--- a/app/controllers/post_actions_controller.rb
+++ b/app/controllers/post_actions_controller.rb
@@ -65,32 +65,32 @@ class PostActionsController < ApplicationController
private
- def fetch_post_from_params
- params.require(:id)
+ def fetch_post_from_params
+ params.require(:id)
- flag_topic = params[:flag_topic]
- flag_topic = flag_topic && (flag_topic == true || flag_topic == "true")
+ 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
- end
- else
- params[:id]
+ post_id = if flag_topic
+ begin
+ Topic.find(params[:id]).posts.first.id
+ rescue
+ raise Discourse::NotFound
end
-
- finder = Post.where(id: post_id)
-
- # Include deleted posts if the user is a staff
- finder = finder.with_deleted if guardian.is_staff?
-
- @post = finder.first
+ else
+ params[:id]
end
- def fetch_post_action_type_id_from_params
- params.require(:post_action_type_id)
- @post_action_type_id = params[:post_action_type_id].to_i
- end
+ finder = Post.where(id: post_id)
+
+ # Include deleted posts if the user is a staff
+ finder = finder.with_deleted if guardian.is_staff?
+
+ @post = finder.first
+ end
+
+ def fetch_post_action_type_id_from_params
+ params.require(:post_action_type_id)
+ @post_action_type_id = params[:post_action_type_id].to_i
+ end
end
diff --git a/app/controllers/queued_posts_controller.rb b/app/controllers/queued_posts_controller.rb
index 3360b41f7b9..7db439e929b 100644
--- a/app/controllers/queued_posts_controller.rb
+++ b/app/controllers/queued_posts_controller.rb
@@ -52,18 +52,18 @@ class QueuedPostsController < ApplicationController
private
- def user_deletion_opts
- base = {
- context: I18n.t('queue.delete_reason', performed_by: current_user.username),
- delete_posts: true,
- delete_as_spammer: true
- }
+ def user_deletion_opts
+ base = {
+ context: I18n.t('queue.delete_reason', performed_by: current_user.username),
+ delete_posts: true,
+ delete_as_spammer: true
+ }
- if Rails.env.production? && ENV["Staging"].nil?
- base.merge!(block_email: true, block_ip: true)
- end
-
- base
+ if Rails.env.production? && ENV["Staging"].nil?
+ base.merge!(block_email: true, block_ip: true)
end
+ base
+ end
+
end
diff --git a/app/controllers/stylesheets_controller.rb b/app/controllers/stylesheets_controller.rb
index 7377d479893..f7344a33930 100644
--- a/app/controllers/stylesheets_controller.rb
+++ b/app/controllers/stylesheets_controller.rb
@@ -98,11 +98,11 @@ class StylesheetsController < ApplicationController
private
- def read_file(location)
- begin
- File.read(location)
- rescue Errno::ENOENT
- end
+ def read_file(location)
+ begin
+ File.read(location)
+ rescue Errno::ENOENT
end
+ end
end
diff --git a/app/controllers/tag_groups_controller.rb b/app/controllers/tag_groups_controller.rb
index 65748f83780..4fd4f0f6e0a 100644
--- a/app/controllers/tag_groups_controller.rb
+++ b/app/controllers/tag_groups_controller.rb
@@ -64,28 +64,28 @@ class TagGroupsController < ApplicationController
private
- def fetch_tag_group
- @tag_group = TagGroup.find(params[:id])
- end
+ def fetch_tag_group
+ @tag_group = TagGroup.find(params[:id])
+ end
- def tag_groups_params
- if permissions = params[:permissions]
- permissions.each do |k, v|
- permissions[k] = v.to_i
- end
+ def tag_groups_params
+ if permissions = params[:permissions]
+ permissions.each do |k, v|
+ permissions[k] = v.to_i
end
-
- result = params.permit(
- :id,
- :name,
- :one_per_topic,
- tag_names: [],
- parent_tag_name: [],
- permissions: permissions&.keys,
- )
- result[:tag_names] ||= []
- result[:parent_tag_name] ||= []
- result[:one_per_topic] = (params[:one_per_topic] == "true")
- result
end
+
+ result = params.permit(
+ :id,
+ :name,
+ :one_per_topic,
+ tag_names: [],
+ parent_tag_name: [],
+ permissions: permissions&.keys,
+ )
+ result[:tag_names] ||= []
+ result[:parent_tag_name] ||= []
+ result[:one_per_topic] = (params[:one_per_topic] == "true")
+ result
+ end
end
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index a673bb06d08..b2916e8c9db 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -207,130 +207,130 @@ class TagsController < ::ApplicationController
private
- def ensure_tags_enabled
- raise Discourse::NotFound unless SiteSetting.tagging_enabled?
- end
+ def ensure_tags_enabled
+ raise Discourse::NotFound unless SiteSetting.tagging_enabled?
+ end
- def self.tag_counts_json(tags)
- tags.map { |t| { id: t.name, text: t.name, count: t.topic_count, pm_count: t.pm_topic_count } }
- end
+ def self.tag_counts_json(tags)
+ tags.map { |t| { id: t.name, text: t.name, count: t.topic_count, pm_count: t.pm_topic_count } }
+ end
- def set_category_from_params
- slug_or_id = params[:category]
- return true if slug_or_id.nil?
+ def set_category_from_params
+ slug_or_id = params[:category]
+ return true if slug_or_id.nil?
- if slug_or_id == 'none' && params[:parent_category]
- @filter_on_category = Category.query_category(params[:parent_category], nil)
- params[:no_subcategories] = 'true'
- else
- parent_slug_or_id = params[:parent_category]
+ if slug_or_id == 'none' && params[:parent_category]
+ @filter_on_category = Category.query_category(params[:parent_category], nil)
+ params[:no_subcategories] = 'true'
+ else
+ parent_slug_or_id = params[:parent_category]
- parent_category_id = nil
- if parent_slug_or_id.present?
- parent_category_id = Category.query_parent_category(parent_slug_or_id)
- category_redirect_or_not_found && (return) if parent_category_id.blank?
- end
-
- @filter_on_category = Category.query_category(slug_or_id, parent_category_id)
+ parent_category_id = nil
+ if parent_slug_or_id.present?
+ parent_category_id = Category.query_parent_category(parent_slug_or_id)
+ category_redirect_or_not_found && (return) if parent_category_id.blank?
end
- category_redirect_or_not_found && (return) if !@filter_on_category
-
- guardian.ensure_can_see!(@filter_on_category)
+ @filter_on_category = Category.query_category(slug_or_id, parent_category_id)
end
- # TODO: this is duplication of ListController
- def page_params(opts = nil)
- opts ||= {}
- route_params = { format: 'json' }
- route_params[:category] = @filter_on_category.slug_for_url if @filter_on_category
- route_params[:parent_category] = @filter_on_category.parent_category.slug_for_url if @filter_on_category && @filter_on_category.parent_category
- route_params[:order] = opts[:order] if opts[:order].present?
- route_params[:ascending] = opts[:ascending] if opts[:ascending].present?
- route_params
- end
+ category_redirect_or_not_found && (return) if !@filter_on_category
- def next_page_params(opts = nil)
- page_params(opts).merge(page: params[:page].to_i + 1)
- end
+ guardian.ensure_can_see!(@filter_on_category)
+ end
- def prev_page_params(opts = nil)
- pg = params[:page].to_i
- if pg > 1
- page_params(opts).merge(page: pg - 1)
- else
- page_params(opts).merge(page: nil)
+ # TODO: this is duplication of ListController
+ def page_params(opts = nil)
+ opts ||= {}
+ route_params = { format: 'json' }
+ route_params[:category] = @filter_on_category.slug_for_url if @filter_on_category
+ route_params[:parent_category] = @filter_on_category.parent_category.slug_for_url if @filter_on_category && @filter_on_category.parent_category
+ route_params[:order] = opts[:order] if opts[:order].present?
+ route_params[:ascending] = opts[:ascending] if opts[:ascending].present?
+ route_params
+ end
+
+ def next_page_params(opts = nil)
+ page_params(opts).merge(page: params[:page].to_i + 1)
+ end
+
+ def prev_page_params(opts = nil)
+ pg = params[:page].to_i
+ if pg > 1
+ page_params(opts).merge(page: pg - 1)
+ else
+ page_params(opts).merge(page: nil)
+ end
+ end
+
+ def url_method(opts = {})
+ if opts[:parent_category] && opts[:category]
+ "tag_parent_category_category_#{action_name}_path"
+ elsif opts[:category]
+ "tag_category_#{action_name}_path"
+ else
+ "tag_#{action_name}_path"
+ end
+ end
+
+ def construct_url_with(action, opts)
+ method = url_method(opts)
+
+ begin
+ url = if action == :prev
+ public_send(method, opts.merge(prev_page_params(opts)))
+ else # :next
+ public_send(method, opts.merge(next_page_params(opts)))
end
+ rescue ActionController::UrlGenerationError
+ raise Discourse::NotFound
+ end
+ url.sub('.json?', '?')
+ end
+
+ def build_topic_list_options
+ options = {
+ page: params[:page],
+ topic_ids: param_to_integer_list(:topic_ids),
+ exclude_category_ids: params[:exclude_category_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'
+ options[:slow_platform] = true if slow_platform?
+
+ if params[:tag_id] == 'none'
+ options[:no_tags] = true
+ else
+ options[:tags] = tag_params
+ options[:match_all_tags] = true
end
- def url_method(opts = {})
- if opts[:parent_category] && opts[:category]
- "tag_parent_category_category_#{action_name}_path"
- elsif opts[:category]
- "tag_category_#{action_name}_path"
- else
- "tag_#{action_name}_path"
- end
+ options
+ end
+
+ def category_redirect_or_not_found
+ # automatic redirects for renamed categories
+ url = params[:parent_category] ? "c/#{params[:parent_category]}/#{params[:category]}" : "c/#{params[:category]}"
+ permalink = Permalink.find_by_url(url)
+
+ if permalink.present? && permalink.category_id
+ redirect_to "#{Discourse::base_uri}/tags#{permalink.target_url}/#{params[:tag_id]}", status: :moved_permanently
+ else
+ # redirect to 404
+ raise Discourse::NotFound
end
+ end
- def construct_url_with(action, opts)
- method = url_method(opts)
-
- begin
- url = if action == :prev
- public_send(method, opts.merge(prev_page_params(opts)))
- else # :next
- public_send(method, opts.merge(next_page_params(opts)))
- end
- rescue ActionController::UrlGenerationError
- raise Discourse::NotFound
- end
- url.sub('.json?', '?')
- end
-
- def build_topic_list_options
- options = {
- page: params[:page],
- topic_ids: param_to_integer_list(:topic_ids),
- exclude_category_ids: params[:exclude_category_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'
- options[:slow_platform] = true if slow_platform?
-
- if params[:tag_id] == 'none'
- options[:no_tags] = true
- else
- options[:tags] = tag_params
- options[:match_all_tags] = true
- end
-
- options
- end
-
- def category_redirect_or_not_found
- # automatic redirects for renamed categories
- url = params[:parent_category] ? "c/#{params[:parent_category]}/#{params[:category]}" : "c/#{params[:category]}"
- permalink = Permalink.find_by_url(url)
-
- if permalink.present? && permalink.category_id
- redirect_to "#{Discourse::base_uri}/tags#{permalink.target_url}/#{params[:tag_id]}", status: :moved_permanently
- else
- # redirect to 404
- raise Discourse::NotFound
- end
- end
-
- def tag_params
- [@tag_id].concat(Array(@additional_tags))
- end
+ def tag_params
+ [@tag_id].concat(Array(@additional_tags))
+ end
end
diff --git a/app/controllers/user_badges_controller.rb b/app/controllers/user_badges_controller.rb
index b6b415d69a5..999c987647c 100644
--- a/app/controllers/user_badges_controller.rb
+++ b/app/controllers/user_badges_controller.rb
@@ -92,28 +92,28 @@ class UserBadgesController < ApplicationController
private
- # Get the badge from either the badge name or id specified in the params.
- def fetch_badge_from_params
- badge = nil
+ # Get the badge from either the badge name or id specified in the params.
+ def fetch_badge_from_params
+ badge = nil
- params.permit(:badge_name)
- if params[:badge_name].nil?
- params.require(:badge_id)
- badge = Badge.find_by(id: params[:badge_id], enabled: true)
- else
- badge = Badge.find_by(name: params[:badge_name], enabled: true)
- end
- raise Discourse::NotFound if badge.blank?
-
- badge
+ params.permit(:badge_name)
+ if params[:badge_name].nil?
+ params.require(:badge_id)
+ badge = Badge.find_by(id: params[:badge_id], enabled: true)
+ else
+ badge = Badge.find_by(name: params[:badge_name], enabled: true)
end
+ raise Discourse::NotFound if badge.blank?
- def can_assign_badge_to_user?(user)
- master_api_call = current_user.nil? && is_api?
- master_api_call || guardian.can_grant_badges?(user)
- end
+ badge
+ end
- def ensure_badges_enabled
- raise Discourse::NotFound unless SiteSetting.enable_badges?
- end
+ def can_assign_badge_to_user?(user)
+ master_api_call = current_user.nil? && is_api?
+ master_api_call || guardian.can_grant_badges?(user)
+ end
+
+ def ensure_badges_enabled
+ raise Discourse::NotFound unless SiteSetting.enable_badges?
+ end
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 548ce754c65..3c97ce94d77 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -994,104 +994,104 @@ class UsersController < ApplicationController
private
- def honeypot_value
- Digest::SHA1::hexdigest("#{Discourse.current_hostname}:#{GlobalSetting.safe_secret_key_base}")[0, 15]
+ def honeypot_value
+ Digest::SHA1::hexdigest("#{Discourse.current_hostname}:#{GlobalSetting.safe_secret_key_base}")[0, 15]
+ end
+
+ def challenge_value
+ challenge = $redis.get('SECRET_CHALLENGE')
+ unless challenge && challenge.length == 16 * 2
+ challenge = SecureRandom.hex(16)
+ $redis.set('SECRET_CHALLENGE', challenge)
end
- def challenge_value
- challenge = $redis.get('SECRET_CHALLENGE')
- unless challenge && challenge.length == 16 * 2
- challenge = SecureRandom.hex(16)
- $redis.set('SECRET_CHALLENGE', challenge)
- end
+ challenge
+ end
- challenge
+ def respond_to_suspicious_request
+ if suspicious?(params)
+ render json: {
+ success: true,
+ active: false,
+ message: I18n.t("login.activate_email", email: params[:email])
+ }
+ end
+ end
+
+ def suspicious?(params)
+ return false if current_user && is_api? && current_user.admin?
+ honeypot_or_challenge_fails?(params) || SiteSetting.invite_only?
+ end
+
+ def honeypot_or_challenge_fails?(params)
+ return false if is_api?
+ params[:password_confirmation] != honeypot_value ||
+ params[:challenge] != challenge_value.try(:reverse)
+ end
+
+ def user_params
+ permitted = [
+ :name,
+ :email,
+ :password,
+ :username,
+ :title,
+ :date_of_birth,
+ :muted_usernames,
+ :theme_key,
+ :locale,
+ :bio_raw,
+ :location,
+ :website,
+ :dismissed_banner_key,
+ :profile_background,
+ :card_background
+ ]
+
+ permitted.concat UserUpdater::OPTION_ATTR
+ permitted.concat UserUpdater::CATEGORY_IDS.keys.map { |k| { k => [] } }
+ permitted.concat UserUpdater::TAG_NAMES.keys
+
+ result = params
+ .permit(permitted)
+ .reverse_merge(
+ ip_address: request.remote_ip,
+ registration_ip_address: request.remote_ip,
+ locale: user_locale
+ )
+
+ if !UsernameCheckerService.is_developer?(result['email']) &&
+ is_api? &&
+ current_user.present? &&
+ current_user.admin?
+
+ result.merge!(params.permit(:active, :staged, :approved))
end
- def respond_to_suspicious_request
- if suspicious?(params)
- render json: {
- success: true,
- active: false,
- message: I18n.t("login.activate_email", email: params[:email])
- }
- end
- end
-
- def suspicious?(params)
- return false if current_user && is_api? && current_user.admin?
- honeypot_or_challenge_fails?(params) || SiteSetting.invite_only?
- end
-
- def honeypot_or_challenge_fails?(params)
- return false if is_api?
- params[:password_confirmation] != honeypot_value ||
- params[:challenge] != challenge_value.try(:reverse)
- end
-
- def user_params
- permitted = [
- :name,
- :email,
- :password,
- :username,
- :title,
- :date_of_birth,
- :muted_usernames,
- :theme_key,
- :locale,
- :bio_raw,
- :location,
- :website,
- :dismissed_banner_key,
- :profile_background,
- :card_background
- ]
-
- permitted.concat UserUpdater::OPTION_ATTR
- permitted.concat UserUpdater::CATEGORY_IDS.keys.map { |k| { k => [] } }
- permitted.concat UserUpdater::TAG_NAMES.keys
-
- result = params
- .permit(permitted)
- .reverse_merge(
- ip_address: request.remote_ip,
- registration_ip_address: request.remote_ip,
- locale: user_locale
- )
-
- if !UsernameCheckerService.is_developer?(result['email']) &&
- is_api? &&
- current_user.present? &&
- current_user.admin?
-
- result.merge!(params.permit(:active, :staged, :approved))
- end
-
- modify_user_params(result)
- end
-
- # Plugins can use this to modify user parameters
- def modify_user_params(attrs)
- attrs
- end
-
- def user_locale
- I18n.locale
- end
-
- def fail_with(key)
- render json: { success: false, message: I18n.t(key) }
- end
-
- def track_visit_to_user_profile
- user_profile_id = @user.user_profile.id
- ip = request.remote_ip
- user_id = (current_user.id if current_user)
-
- Scheduler::Defer.later 'Track profile view visit' do
- UserProfileView.add(user_profile_id, ip, user_id)
- end
+ modify_user_params(result)
+ end
+
+ # Plugins can use this to modify user parameters
+ def modify_user_params(attrs)
+ attrs
+ end
+
+ def user_locale
+ I18n.locale
+ end
+
+ def fail_with(key)
+ render json: { success: false, message: I18n.t(key) }
+ end
+
+ def track_visit_to_user_profile
+ user_profile_id = @user.user_profile.id
+ ip = request.remote_ip
+ user_id = (current_user.id if current_user)
+
+ Scheduler::Defer.later 'Track profile view visit' do
+ UserProfileView.add(user_profile_id, ip, user_id)
end
+ end
end
diff --git a/app/controllers/webhooks_controller.rb b/app/controllers/webhooks_controller.rb
index b6e1ad2093c..5480fe33680 100644
--- a/app/controllers/webhooks_controller.rb
+++ b/app/controllers/webhooks_controller.rb
@@ -119,30 +119,30 @@ class WebhooksController < ActionController::Base
private
- def mailgun_failure
- render body: nil, status: 406
- end
+ def mailgun_failure
+ render body: nil, status: 406
+ end
- def mailgun_success
- render body: nil, status: 200
- end
+ def mailgun_success
+ render body: nil, status: 200
+ end
- def mailgun_verify(timestamp, token, signature)
- digest = OpenSSL::Digest::SHA256.new
- data = "#{timestamp}#{token}"
- signature == OpenSSL::HMAC.hexdigest(digest, SiteSetting.mailgun_api_key, data)
- end
+ def mailgun_verify(timestamp, token, signature)
+ digest = OpenSSL::Digest::SHA256.new
+ data = "#{timestamp}#{token}"
+ signature == OpenSSL::HMAC.hexdigest(digest, SiteSetting.mailgun_api_key, data)
+ end
- def process_bounce(message_id, to_address, bounce_score)
- return if message_id.blank? || to_address.blank?
+ def process_bounce(message_id, to_address, bounce_score)
+ return if message_id.blank? || to_address.blank?
- email_log = EmailLog.find_by(message_id: message_id, to_address: to_address)
- return if email_log.nil?
+ email_log = EmailLog.find_by(message_id: message_id, to_address: to_address)
+ return if email_log.nil?
- email_log.update_columns(bounced: true)
- return if email_log.user.nil? || email_log.user.email.blank?
+ email_log.update_columns(bounced: true)
+ return if email_log.user.nil? || email_log.user.email.blank?
- Email::Receiver.update_bounce_score(email_log.user.email, bounce_score)
- end
+ Email::Receiver.update_bounce_score(email_log.user.email, bounce_score)
+ end
end
diff --git a/app/jobs/regular/export_csv_file.rb b/app/jobs/regular/export_csv_file.rb
index 2ebfb75df7d..d32e2b822cd 100644
--- a/app/jobs/regular/export_csv_file.rb
+++ b/app/jobs/regular/export_csv_file.rb
@@ -211,169 +211,169 @@ module Jobs
private
- def escape_comma(string)
- if string && string =~ /,/
- return "#{string}"
- else
- return string
+ def escape_comma(string)
+ if string && string =~ /,/
+ return "#{string}"
+ else
+ return string
+ end
+ end
+
+ def get_base_user_array(user)
+ user_array = []
+ user_array.push(user.id, escape_comma(user.name), user.username, user.email, escape_comma(user.title), user.created_at, user.last_seen_at, user.last_posted_at, user.last_emailed_at, user.trust_level, user.approved, user.suspended_at, user.suspended_till, user.silenced_till, user.active, user.admin, user.moderator, user.ip_address, user.staged, user.user_stat.topics_entered, user.user_stat.posts_read_count, user.user_stat.time_read, user.user_stat.topic_count, user.user_stat.post_count, user.user_stat.likes_given, user.user_stat.likes_received, escape_comma(user.user_profile.location), user.user_profile.website, user.user_profile.views)
+ end
+
+ 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)
+ else
+ user_info_array.push(nil, nil, nil, nil, nil)
+ end
+ user_info_array
+ end
+
+ 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
end
+ user_info_array
+ end
- def get_base_user_array(user)
- user_array = []
- user_array.push(user.id, escape_comma(user.name), user.username, user.email, escape_comma(user.title), user.created_at, user.last_seen_at, user.last_posted_at, user.last_emailed_at, user.trust_level, user.approved, user.suspended_at, user.suspended_till, user.silenced_till, user.active, user.admin, user.moderator, user.ip_address, user.staged, user.user_stat.topics_entered, user.user_stat.posts_read_count, user.user_stat.time_read, user.user_stat.topic_count, user.user_stat.post_count, user.user_stat.likes_given, user.user_stat.likes_received, escape_comma(user.user_profile.location), user.user_profile.website, user.user_profile.views)
+ def add_group_names(user, user_info_array)
+ group_names = user.groups.each_with_object("") do |group, names|
+ names << "#{group.name};"
end
+ user_info_array << group_names[0..-2] unless group_names.blank?
+ group_names = nil
+ user_info_array
+ end
- 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)
- else
- user_info_array.push(nil, nil, nil, nil, nil)
- end
- user_info_array
- end
-
- 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])
+ def get_user_archive_fields(user_archive)
+ user_archive_array = []
+ topic_data = user_archive.topic
+ user_archive = user_archive.as_json
+ topic_data = Topic.with_deleted.find_by(id: user_archive['topic_id']) if topic_data.nil?
+ return user_archive_array if topic_data.nil?
+ category = topic_data.category
+ sub_category_name = "-"
+ if category
+ category_name = category.name
+ if category.parent_category_id.present?
+ # sub category
+ if parent_category = Category.find_by(id: category.parent_category_id)
+ category_name = parent_category.name
+ sub_category_name = category.name
end
end
- user_info_array
+ else
+ # PM
+ category_name = "-"
+ end
+ 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']}"
+
+ topic_hash = { "post" => user_archive['raw'], "topic_title" => topic_data.title, "category" => category_name, "sub_category" => sub_category_name, "is_pm" => is_pm, "url" => url }
+ user_archive.merge!(topic_hash)
+
+ HEADER_ATTRS_FOR['user_archive'].each do |attr|
+ user_archive_array.push(user_archive[attr])
end
- def add_group_names(user, user_info_array)
- group_names = user.groups.each_with_object("") do |group, names|
- names << "#{group.name};"
- end
- user_info_array << group_names[0..-2] unless group_names.blank?
- group_names = nil
- user_info_array
- end
+ user_archive_array
+ end
- def get_user_archive_fields(user_archive)
- user_archive_array = []
- topic_data = user_archive.topic
- user_archive = user_archive.as_json
- topic_data = Topic.with_deleted.find_by(id: user_archive['topic_id']) if topic_data.nil?
- return user_archive_array if topic_data.nil?
- category = topic_data.category
- sub_category_name = "-"
- if category
- category_name = category.name
- if category.parent_category_id.present?
- # sub category
- if parent_category = Category.find_by(id: category.parent_category_id)
- category_name = parent_category.name
- sub_category_name = category.name
- end
- end
- else
- # PM
- category_name = "-"
- end
- 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']}"
+ def get_staff_action_fields(staff_action)
+ staff_action_array = []
- topic_hash = { "post" => user_archive['raw'], "topic_title" => topic_data.title, "category" => category_name, "sub_category" => sub_category_name, "is_pm" => is_pm, "url" => url }
- user_archive.merge!(topic_hash)
-
- HEADER_ATTRS_FOR['user_archive'].each do |attr|
- user_archive_array.push(user_archive[attr])
- end
-
- user_archive_array
- end
-
- def get_staff_action_fields(staff_action)
- staff_action_array = []
-
- HEADER_ATTRS_FOR['staff_action'].each do |attr|
- data =
- 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'])
- 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]}"
- else
- staff_action.attributes[attr]
- end
-
- staff_action_array.push(data)
- end
- staff_action_array
- end
-
- def get_screened_email_fields(screened_email)
- screened_email_array = []
-
- HEADER_ATTRS_FOR['screened_email'].each do |attr|
- data =
- if attr == 'action'
- ScreenedEmail.actions.key(screened_email.attributes['action_type']).to_s
- else
- screened_email.attributes[attr]
- end
-
- screened_email_array.push(data)
- end
-
- screened_email_array
- end
-
- def get_screened_ip_fields(screened_ip)
- screened_ip_array = []
-
- HEADER_ATTRS_FOR['screened_ip'].each do |attr|
- data =
- if attr == 'action'
- ScreenedIpAddress.actions.key(screened_ip.attributes['action_type']).to_s
- else
- screened_ip.attributes[attr]
- end
-
- screened_ip_array.push(data)
- end
-
- screened_ip_array
- end
-
- def get_screened_url_fields(screened_url)
- screened_url_array = []
-
- HEADER_ATTRS_FOR['screened_url'].each do |attr|
- data =
- 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]
- end
-
- screened_url_array.push(data)
- end
-
- screened_url_array
- end
-
- def notify_user(download_link, file_name, file_size, export_title)
- if @current_user
- if download_link.present?
- SystemMessage.create_from_system_user(
- @current_user,
- :csv_export_succeeded,
- download_link: download_link,
- file_name: "#{file_name}.gz",
- file_size: file_size,
- export_title: export_title
- )
+ HEADER_ATTRS_FOR['staff_action'].each do |attr|
+ data =
+ 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'])
+ 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]}"
else
- SystemMessage.create_from_system_user(@current_user, :csv_export_failed)
+ staff_action.attributes[attr]
end
+
+ staff_action_array.push(data)
+ end
+ staff_action_array
+ end
+
+ def get_screened_email_fields(screened_email)
+ screened_email_array = []
+
+ HEADER_ATTRS_FOR['screened_email'].each do |attr|
+ data =
+ if attr == 'action'
+ ScreenedEmail.actions.key(screened_email.attributes['action_type']).to_s
+ else
+ screened_email.attributes[attr]
+ end
+
+ screened_email_array.push(data)
+ end
+
+ screened_email_array
+ end
+
+ def get_screened_ip_fields(screened_ip)
+ screened_ip_array = []
+
+ HEADER_ATTRS_FOR['screened_ip'].each do |attr|
+ data =
+ if attr == 'action'
+ ScreenedIpAddress.actions.key(screened_ip.attributes['action_type']).to_s
+ else
+ screened_ip.attributes[attr]
+ end
+
+ screened_ip_array.push(data)
+ end
+
+ screened_ip_array
+ end
+
+ def get_screened_url_fields(screened_url)
+ screened_url_array = []
+
+ HEADER_ATTRS_FOR['screened_url'].each do |attr|
+ data =
+ 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]
+ end
+
+ screened_url_array.push(data)
+ end
+
+ screened_url_array
+ end
+
+ def notify_user(download_link, file_name, file_size, export_title)
+ if @current_user
+ if download_link.present?
+ SystemMessage.create_from_system_user(
+ @current_user,
+ :csv_export_succeeded,
+ download_link: download_link,
+ file_name: "#{file_name}.gz",
+ file_size: file_size,
+ export_title: export_title
+ )
+ else
+ SystemMessage.create_from_system_user(@current_user, :csv_export_failed)
end
end
+ end
end
end
diff --git a/app/jobs/regular/pull_hotlinked_images.rb b/app/jobs/regular/pull_hotlinked_images.rb
index ce88cd6546e..d6e03f782d4 100644
--- a/app/jobs/regular/pull_hotlinked_images.rb
+++ b/app/jobs/regular/pull_hotlinked_images.rb
@@ -174,9 +174,9 @@ module Jobs
private
- def remove_scheme(src)
- src.sub(/^https?:/i, "")
- end
+ def remove_scheme(src)
+ src.sub(/^https?:/i, "")
+ end
end
end
diff --git a/app/models/badge.rb b/app/models/badge.rb
index 60da562949d..9a64949980b 100644
--- a/app/models/badge.rb
+++ b/app/models/badge.rb
@@ -225,13 +225,13 @@ class Badge < ActiveRecord::Base
protected
- def ensure_not_system
- self.id = [Badge.maximum(:id) + 1, 100].max unless id
- end
+ def ensure_not_system
+ self.id = [Badge.maximum(:id) + 1, 100].max unless id
+ end
- def i18n_name
- self.name.downcase.tr(' ', '_')
- end
+ def i18n_name
+ self.name.downcase.tr(' ', '_')
+ end
end
diff --git a/app/models/category_list.rb b/app/models/category_list.rb
index 76511d5b8bc..e8bf8aefab8 100644
--- a/app/models/category_list.rb
+++ b/app/models/category_list.rb
@@ -44,127 +44,127 @@ class CategoryList
private
- def find_relevant_topics
- @topics_by_id = {}
- @topics_by_category_id = {}
+ def find_relevant_topics
+ @topics_by_id = {}
+ @topics_by_category_id = {}
- category_featured_topics = CategoryFeaturedTopic.select([:category_id, :topic_id]).order(:rank)
+ category_featured_topics = CategoryFeaturedTopic.select([:category_id, :topic_id]).order(:rank)
- @all_topics = Topic.where(id: category_featured_topics.map(&:topic_id))
- @all_topics = @all_topics.includes(:last_poster) if @options[:include_topics]
- @all_topics.each do |t|
- # hint for the serializer
- t.include_last_poster = true if @options[:include_topics]
- @topics_by_id[t.id] = t
- end
-
- category_featured_topics.each do |cft|
- @topics_by_category_id[cft.category_id] ||= []
- @topics_by_category_id[cft.category_id] << cft.topic_id
- end
+ @all_topics = Topic.where(id: category_featured_topics.map(&:topic_id))
+ @all_topics = @all_topics.includes(:last_poster) if @options[:include_topics]
+ @all_topics.each do |t|
+ # hint for the serializer
+ t.include_last_poster = true if @options[:include_topics]
+ @topics_by_id[t.id] = t
end
- def find_categories
- @categories = Category.includes(
- :uploaded_background,
- :uploaded_logo,
- :topic_only_relative_url,
- subcategories: [:topic_only_relative_url]
- ).secured(@guardian)
+ category_featured_topics.each do |cft|
+ @topics_by_category_id[cft.category_id] ||= []
+ @topics_by_category_id[cft.category_id] << cft.topic_id
+ end
+ end
- @categories = @categories.where("categories.parent_category_id = ?", @options[:parent_category_id].to_i) if @options[:parent_category_id].present?
+ def find_categories
+ @categories = Category.includes(
+ :uploaded_background,
+ :uploaded_logo,
+ :topic_only_relative_url,
+ subcategories: [:topic_only_relative_url]
+ ).secured(@guardian)
- if SiteSetting.fixed_category_positions
- @categories = @categories.order(:position, :id)
- else
- @categories = @categories.order('COALESCE(categories.posts_week, 0) DESC')
- .order('COALESCE(categories.posts_month, 0) DESC')
- .order('COALESCE(categories.posts_year, 0) DESC')
- .order('id ASC')
- end
+ @categories = @categories.where("categories.parent_category_id = ?", @options[:parent_category_id].to_i) if @options[:parent_category_id].present?
- @categories = @categories.to_a
+ if SiteSetting.fixed_category_positions
+ @categories = @categories.order(:position, :id)
+ else
+ @categories = @categories.order('COALESCE(categories.posts_week, 0) DESC')
+ .order('COALESCE(categories.posts_month, 0) DESC')
+ .order('COALESCE(categories.posts_year, 0) DESC')
+ .order('id ASC')
+ end
- category_user = {}
- default_notification_level = nil
- unless @guardian.anonymous?
- category_user = Hash[*CategoryUser.where(user: @guardian.user).pluck(:category_id, :notification_level).flatten]
- default_notification_level = CategoryUser.notification_levels[:regular]
- end
+ @categories = @categories.to_a
- allowed_topic_create = Set.new(Category.topic_create_allowed(@guardian).pluck(:id))
- @categories.each do |category|
- category.notification_level = category_user[category.id] || default_notification_level
- category.permission = CategoryGroup.permission_types[:full] if allowed_topic_create.include?(category.id)
- category.has_children = category.subcategories.present?
- end
+ category_user = {}
+ default_notification_level = nil
+ unless @guardian.anonymous?
+ category_user = Hash[*CategoryUser.where(user: @guardian.user).pluck(:category_id, :notification_level).flatten]
+ default_notification_level = CategoryUser.notification_levels[:regular]
+ end
- if @options[:parent_category_id].blank?
- subcategories = {}
- to_delete = Set.new
- @categories.each do |c|
- if c.parent_category_id.present?
- subcategories[c.parent_category_id] ||= []
- subcategories[c.parent_category_id] << c.id
- to_delete << c
- end
+ allowed_topic_create = Set.new(Category.topic_create_allowed(@guardian).pluck(:id))
+ @categories.each do |category|
+ category.notification_level = category_user[category.id] || default_notification_level
+ category.permission = CategoryGroup.permission_types[:full] if allowed_topic_create.include?(category.id)
+ category.has_children = category.subcategories.present?
+ end
+
+ if @options[:parent_category_id].blank?
+ subcategories = {}
+ to_delete = Set.new
+ @categories.each do |c|
+ if c.parent_category_id.present?
+ subcategories[c.parent_category_id] ||= []
+ subcategories[c.parent_category_id] << c.id
+ to_delete << c
end
- @categories.each { |c| c.subcategory_ids = subcategories[c.id] }
- @categories.delete_if { |c| to_delete.include?(c) }
end
+ @categories.each { |c| c.subcategory_ids = subcategories[c.id] }
+ @categories.delete_if { |c| to_delete.include?(c) }
+ end
- if @topics_by_category_id
- @categories.each do |c|
- topics_in_cat = @topics_by_category_id[c.id]
- if topics_in_cat.present?
- c.displayable_topics = []
- topics_in_cat.each do |topic_id|
- topic = @topics_by_id[topic_id]
- if topic.present? && @guardian.can_see?(topic)
- # topic.category is very slow under rails 4.2
- topic.association(:category).target = c
- c.displayable_topics << topic
- end
+ if @topics_by_category_id
+ @categories.each do |c|
+ topics_in_cat = @topics_by_category_id[c.id]
+ if topics_in_cat.present?
+ c.displayable_topics = []
+ topics_in_cat.each do |topic_id|
+ topic = @topics_by_id[topic_id]
+ if topic.present? && @guardian.can_see?(topic)
+ # topic.category is very slow under rails 4.2
+ topic.association(:category).target = c
+ c.displayable_topics << topic
end
end
end
end
end
+ end
- def prune_empty
- return if SiteSetting.allow_uncategorized_topics
- @categories.delete_if { |c| c.uncategorized? && c.displayable_topics.blank? }
+ def prune_empty
+ return if SiteSetting.allow_uncategorized_topics
+ @categories.delete_if { |c| c.uncategorized? && c.displayable_topics.blank? }
+ end
+
+ # Attach some data for serialization to each topic
+ def find_user_data
+ if @guardian.current_user && @all_topics.present?
+ topic_lookup = TopicUser.lookup_for(@guardian.current_user, @all_topics)
+ @all_topics.each { |ft| ft.user_data = topic_lookup[ft.id] }
end
+ end
- # Attach some data for serialization to each topic
- def find_user_data
- if @guardian.current_user && @all_topics.present?
- topic_lookup = TopicUser.lookup_for(@guardian.current_user, @all_topics)
- @all_topics.each { |ft| ft.user_data = topic_lookup[ft.id] }
- end
- end
-
- # Put unpinned topics at the end of the list
- def sort_unpinned
- if @guardian.current_user && @all_topics.present?
- @categories.each do |c|
- next if c.displayable_topics.blank? || c.displayable_topics.size <= c.num_featured_topics
- unpinned = []
- 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
+ # Put unpinned topics at the end of the list
+ def sort_unpinned
+ if @guardian.current_user && @all_topics.present?
+ @categories.each do |c|
+ next if c.displayable_topics.blank? || c.displayable_topics.size <= c.num_featured_topics
+ unpinned = []
+ 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
end
end
+ end
- def trim_results
- @categories.each do |c|
- next if c.displayable_topics.blank?
- c.displayable_topics = c.displayable_topics[0, c.num_featured_topics]
- end
+ def trim_results
+ @categories.each do |c|
+ next if c.displayable_topics.blank?
+ c.displayable_topics = c.displayable_topics[0, c.num_featured_topics]
end
+ end
end
diff --git a/app/models/concerns/trashable.rb b/app/models/concerns/trashable.rb
index 0a8dae3f501..3d79754980e 100644
--- a/app/models/concerns/trashable.rb
+++ b/app/models/concerns/trashable.rb
@@ -45,8 +45,8 @@ module Trashable
private
- def trash_update(deleted_at, deleted_by_id)
- self.update_columns(deleted_at: deleted_at, deleted_by_id: deleted_by_id)
- end
+ 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/embeddable_host.rb b/app/models/embeddable_host.rb
index c6f0effbbe1..aed2a253627 100644
--- a/app/models/embeddable_host.rb
+++ b/app/models/embeddable_host.rb
@@ -53,13 +53,13 @@ class EmbeddableHost < ActiveRecord::Base
private
- def host_must_be_valid
- if host !~ /\A[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,10}(:[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'))
- end
+ def host_must_be_valid
+ if host !~ /\A[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,10}(:[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'))
end
+ end
end
# == Schema Information
diff --git a/app/models/group.rb b/app/models/group.rb
index 1a895775ded..fe0c647e394 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -598,58 +598,58 @@ class Group < ActiveRecord::Base
protected
- def name_format_validator
- self.name.strip!
+ def name_format_validator
+ self.name.strip!
- UsernameValidator.perform_validation(self, 'name') || begin
- name_lower = self.name.downcase
+ UsernameValidator.perform_validation(self, 'name') || begin
+ name_lower = self.name.downcase
- if self.will_save_change_to_name? && self.name_was&.downcase != name_lower
- existing = Group.exec_sql(
- User::USERNAME_EXISTS_SQL, username: name_lower
- ).values.present?
+ if self.will_save_change_to_name? && self.name_was&.downcase != name_lower
+ existing = Group.exec_sql(
+ User::USERNAME_EXISTS_SQL, username: name_lower
+ ).values.present?
- if existing
- errors.add(:name, I18n.t("activerecord.errors.messages.taken"))
- end
+ if existing
+ 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?
+ def automatic_membership_email_domains_format_validator
+ return if self.automatic_membership_email_domains.blank?
- domains = self.automatic_membership_email_domains.split("|")
- domains.each do |domain|
- domain.sub!(/^https?:\/\//, '')
- domain.sub!(/\/.*$/, '')
- self.errors.add :base, (I18n.t('groups.errors.invalid_domain', domain: domain)) unless domain =~ /\A[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,24}(:[0-9]{1,5})?(\/.*)?\Z/i
- end
- self.automatic_membership_email_domains = domains.join("|")
+ domains = self.automatic_membership_email_domains.split("|")
+ domains.each do |domain|
+ domain.sub!(/^https?:\/\//, '')
+ domain.sub!(/\/.*$/, '')
+ self.errors.add :base, (I18n.t('groups.errors.invalid_domain', domain: domain)) unless domain =~ /\A[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,24}(:[0-9]{1,5})?(\/.*)?\Z/i
end
+ self.automatic_membership_email_domains = domains.join("|")
+ end
- # hack around AR
- def destroy_deletions
- 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'
- end
- end
- @deletions = nil
- end
-
- def automatic_group_membership
- if self.automatic_membership_retroactive
- Jobs.enqueue(:automatic_group_membership, group_id: self.id)
+ # hack around AR
+ def destroy_deletions
+ 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'
end
end
+ @deletions = nil
+ end
- def update_title
- return if new_record? && !self.title.present?
+ def automatic_group_membership
+ if self.automatic_membership_retroactive
+ Jobs.enqueue(:automatic_group_membership, group_id: self.id)
+ end
+ end
- if self.saved_change_to_title?
- sql = <<-SQL.squish
+ def update_title
+ return if new_record? && !self.title.present?
+
+ if self.saved_change_to_title?
+ sql = <<-SQL.squish
UPDATE users
SET title = :title
WHERE (title = :title_was OR title = '' OR title IS NULL)
@@ -657,71 +657,71 @@ class Group < ActiveRecord::Base
AND id IN (SELECT user_id FROM group_users WHERE group_id = :id)
SQL
- self.class.exec_sql(sql, title: title, title_was: title_before_last_save, id: id)
- end
+ self.class.exec_sql(sql, title: title, title_was: title_before_last_save, id: id)
end
+ end
- def update_primary_group
- return if new_record? && !self.primary_group?
+ def update_primary_group
+ return if new_record? && !self.primary_group?
- if self.saved_change_to_primary_group?
- sql = <<~SQL
+ if self.saved_change_to_primary_group?
+ sql = <<~SQL
UPDATE users
/*set*/
/*where*/
SQL
- builder = SqlBuilder.new(sql)
- builder.where("
- id IN (
- SELECT user_id
- FROM group_users
- WHERE group_id = :id
- )", id: id)
+ builder = SqlBuilder.new(sql)
+ builder.where("
+ id IN (
+ SELECT user_id
+ FROM group_users
+ WHERE group_id = :id
+ )", id: id)
- if primary_group
- builder.set("primary_group_id = :id")
- else
- builder.set("primary_group_id = NULL")
- builder.where("primary_group_id = :id")
- end
-
- builder.exec
+ if primary_group
+ builder.set("primary_group_id = :id")
+ else
+ builder.set("primary_group_id = NULL")
+ builder.where("primary_group_id = :id")
end
+
+ builder.exec
end
+ end
private
- 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
- ))
+ 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
+ ))
+ end
+ end
+
+ def can_allow_membership_requests
+ valid = true
+
+ valid =
+ if self.persisted?
+ self.group_users.where(owner: true).exists?
+ else
+ self.group_users.any?(&:owner)
end
+
+ if !valid
+ self.errors.add(:base, I18n.t('groups.errors.cant_allow_membership_requests'))
end
+ end
- def can_allow_membership_requests
- valid = true
-
- valid =
- if self.persisted?
- self.group_users.where(owner: true).exists?
- else
- self.group_users.any?(&:owner)
- end
-
- if !valid
- self.errors.add(:base, I18n.t('groups.errors.cant_allow_membership_requests'))
- end
- end
-
- def enqueue_update_mentions_job
- Jobs.enqueue(:update_group_mentions,
- previous_name: self.name_before_last_save,
- group_id: self.id
- )
- end
+ def enqueue_update_mentions_job
+ Jobs.enqueue(:update_group_mentions,
+ previous_name: self.name_before_last_save,
+ group_id: self.id
+ )
+ end
end
# == Schema Information
diff --git a/app/models/group_archived_message.rb b/app/models/group_archived_message.rb
index 778a3944c18..729ad8b82ad 100644
--- a/app/models/group_archived_message.rb
+++ b/app/models/group_archived_message.rb
@@ -29,11 +29,11 @@ class GroupArchivedMessage < ActiveRecord::Base
private
- def self.publish_topic_tracking_state(topic)
- TopicTrackingState.publish_private_message(
- topic, group_archive: true
- )
- end
+ def self.publish_topic_tracking_state(topic)
+ TopicTrackingState.publish_private_message(
+ topic, group_archive: true
+ )
+ end
end
# == Schema Information
diff --git a/app/models/post_analyzer.rb b/app/models/post_analyzer.rb
index 5d069c72eb9..5de5a83f8ec 100644
--- a/app/models/post_analyzer.rb
+++ b/app/models/post_analyzer.rb
@@ -127,19 +127,19 @@ class PostAnalyzer
private
- def cooked_stripped
- @cooked_stripped ||= begin
- doc = Nokogiri::HTML.fragment(cook(@raw, topic_id: @topic_id))
- doc.css("pre .mention, aside.quote > .title, aside.quote .mention, .onebox, .elided").remove
- doc
- end
+ def cooked_stripped
+ @cooked_stripped ||= begin
+ doc = Nokogiri::HTML.fragment(cook(@raw, topic_id: @topic_id))
+ doc.css("pre .mention, aside.quote > .title, aside.quote .mention, .onebox, .elided").remove
+ doc
end
+ end
- def link_is_a_mention?(l)
- html_class = l['class']
- return false if html_class.blank?
- href = l['href'].to_s
- html_class.to_s['mention'] && href[/^\/u\//] || href[/^\/users\//]
- end
+ def link_is_a_mention?(l)
+ html_class = l['class']
+ return false if html_class.blank?
+ href = l['href'].to_s
+ html_class.to_s['mention'] && href[/^\/u\//] || href[/^\/users\//]
+ end
end
diff --git a/app/models/queued_post.rb b/app/models/queued_post.rb
index fb4a390f7fc..1f2afa75fec 100644
--- a/app/models/queued_post.rb
+++ b/app/models/queued_post.rb
@@ -94,30 +94,30 @@ class QueuedPost < ActiveRecord::Base
private
- def change_to!(state, changed_by)
- state_val = QueuedPost.states[state]
+ def change_to!(state, changed_by)
+ state_val = QueuedPost.states[state]
- updates = { state: state_val,
- "#{state}_by_id" => changed_by.id,
- "#{state}_at" => Time.now }
+ updates = { state: state_val,
+ "#{state}_by_id" => changed_by.id,
+ "#{state}_at" => Time.now }
- # We use an update with `row_count` trick here to avoid stampeding requests to
- # update the same row simultaneously. Only one state change should go through and
- # we can use the DB to enforce this
- row_count = QueuedPost.where('id = ? AND state <> ?', id, state_val).update_all(updates)
- raise InvalidStateTransition.new if row_count == 0
+ # We use an update with `row_count` trick here to avoid stampeding requests to
+ # update the same row simultaneously. Only one state change should go through and
+ # we can use the DB to enforce this
+ row_count = QueuedPost.where('id = ? AND state <> ?', id, state_val).update_all(updates)
+ raise InvalidStateTransition.new if row_count == 0
- if [:rejected, :approved].include?(state)
- UserAction.where(queued_post_id: id).destroy_all
- end
-
- # Update the record in memory too, and clear the dirty flag
- updates.each { |k, v| send("#{k}=", v) }
- changes_applied
-
- QueuedPost.broadcast_new! if visible?
+ if [:rejected, :approved].include?(state)
+ UserAction.where(queued_post_id: id).destroy_all
end
+ # Update the record in memory too, and clear the dirty flag
+ updates.each { |k, v| send("#{k}=", v) }
+ changes_applied
+
+ QueuedPost.broadcast_new! if visible?
+ end
+
end
# == Schema Information
diff --git a/app/models/topic_featured_users.rb b/app/models/topic_featured_users.rb
index d3f705149be..d8a8a406cb1 100644
--- a/app/models/topic_featured_users.rb
+++ b/app/models/topic_featured_users.rb
@@ -84,8 +84,8 @@ SQL
private
- def update_participant_count
- 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
+ def update_participant_count
+ 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_timer.rb b/app/models/topic_timer.rb
index 39f882dbafa..e481ec1b26e 100644
--- a/app/models/topic_timer.rb
+++ b/app/models/topic_timer.rb
@@ -83,66 +83,66 @@ class TopicTimer < ActiveRecord::Base
private
- def ensure_update_will_happen
- if created_at && (execute_at < created_at)
- errors.add(:execute_at, I18n.t(
- 'activerecord.errors.models.topic_timer.attributes.execute_at.in_the_past'
- ))
- end
+ def ensure_update_will_happen
+ if created_at && (execute_at < created_at)
+ errors.add(:execute_at, I18n.t(
+ 'activerecord.errors.models.topic_timer.attributes.execute_at.in_the_past'
+ ))
end
+ end
- def cancel_auto_close_job
- Jobs.cancel_scheduled_job(:toggle_topic_closed, topic_timer_id: id)
- end
- alias_method :cancel_auto_open_job, :cancel_auto_close_job
+ def cancel_auto_close_job
+ Jobs.cancel_scheduled_job(:toggle_topic_closed, topic_timer_id: id)
+ end
+ alias_method :cancel_auto_open_job, :cancel_auto_close_job
- def cancel_auto_publish_to_category_job
- Jobs.cancel_scheduled_job(:publish_topic_to_category, topic_timer_id: id)
- end
+ def cancel_auto_publish_to_category_job
+ Jobs.cancel_scheduled_job(:publish_topic_to_category, topic_timer_id: id)
+ end
- def cancel_auto_delete_job
- Jobs.cancel_scheduled_job(:delete_topic, topic_timer_id: id)
- end
+ def cancel_auto_delete_job
+ Jobs.cancel_scheduled_job(:delete_topic, topic_timer_id: id)
+ end
- def cancel_auto_reminder_job
- Jobs.cancel_scheduled_job(:topic_reminder, topic_timer_id: id)
- end
+ def cancel_auto_reminder_job
+ Jobs.cancel_scheduled_job(:topic_reminder, topic_timer_id: id)
+ end
- def schedule_auto_open_job(time)
- return unless topic
- topic.update_status('closed', true, user) if !topic.closed
+ def schedule_auto_open_job(time)
+ return unless topic
+ topic.update_status('closed', true, user) if !topic.closed
- Jobs.enqueue_at(time, :toggle_topic_closed,
- topic_timer_id: id,
- state: false
- )
- end
+ Jobs.enqueue_at(time, :toggle_topic_closed,
+ topic_timer_id: id,
+ state: false
+ )
+ end
- def schedule_auto_close_job(time)
- return unless topic
- topic.update_status('closed', false, user) if topic.closed
+ def schedule_auto_close_job(time)
+ return unless topic
+ topic.update_status('closed', false, user) if topic.closed
- Jobs.enqueue_at(time, :toggle_topic_closed,
- topic_timer_id: id,
- state: true
- )
- end
+ Jobs.enqueue_at(time, :toggle_topic_closed,
+ topic_timer_id: id,
+ state: true
+ )
+ end
- def schedule_auto_publish_to_category_job(time)
- Jobs.enqueue_at(time, :publish_topic_to_category, topic_timer_id: id)
- end
+ def schedule_auto_publish_to_category_job(time)
+ Jobs.enqueue_at(time, :publish_topic_to_category, topic_timer_id: id)
+ end
- def publishing_to_category?
- self.status_type.to_i == TopicTimer.types[:publish_to_category]
- end
+ def publishing_to_category?
+ self.status_type.to_i == TopicTimer.types[:publish_to_category]
+ end
- def schedule_auto_delete_job(time)
- Jobs.enqueue_at(time, :delete_topic, topic_timer_id: id)
- end
+ def schedule_auto_delete_job(time)
+ Jobs.enqueue_at(time, :delete_topic, topic_timer_id: id)
+ end
- def schedule_auto_reminder_job(time)
- Jobs.enqueue_at(time, :topic_reminder, topic_timer_id: id)
- end
+ def schedule_auto_reminder_job(time)
+ Jobs.enqueue_at(time, :topic_reminder, topic_timer_id: id)
+ end
end
# == Schema Information
diff --git a/app/models/unsubscribe_key.rb b/app/models/unsubscribe_key.rb
index 967d8f34a13..7f5ee933cba 100644
--- a/app/models/unsubscribe_key.rb
+++ b/app/models/unsubscribe_key.rb
@@ -19,9 +19,9 @@ class UnsubscribeKey < ActiveRecord::Base
private
- def generate_random_key
- self.key = SecureRandom.hex(32)
- end
+ def generate_random_key
+ self.key = SecureRandom.hex(32)
+ end
end
# == Schema Information
diff --git a/app/models/user_archived_message.rb b/app/models/user_archived_message.rb
index 1edd3863c48..6c2c604042f 100644
--- a/app/models/user_archived_message.rb
+++ b/app/models/user_archived_message.rb
@@ -36,11 +36,11 @@ class UserArchivedMessage < ActiveRecord::Base
private
- def self.publish_topic_tracking_state(topic, user_id)
- TopicTrackingState.publish_private_message(
- topic, archive_user_id: user_id
- )
- end
+ def self.publish_topic_tracking_state(topic, user_id)
+ TopicTrackingState.publish_private_message(
+ topic, archive_user_id: user_id
+ )
+ end
end
# == Schema Information
diff --git a/app/models/user_badge.rb b/app/models/user_badge.rb
index 53979ec9cf8..b0b4ce354c5 100644
--- a/app/models/user_badge.rb
+++ b/app/models/user_badge.rb
@@ -26,9 +26,9 @@ class UserBadge < ActiveRecord::Base
private
- def single_grant_badge?
- self.badge.single_grant?
- end
+ def single_grant_badge?
+ self.badge.single_grant?
+ end
end
# == Schema Information
diff --git a/app/models/user_option.rb b/app/models/user_option.rb
index 828ac58c602..5077d8dc364 100644
--- a/app/models/user_option.rb
+++ b/app/models/user_option.rb
@@ -141,10 +141,10 @@ class UserOption < ActiveRecord::Base
private
- def update_tracked_topics
- return unless saved_change_to_auto_track_topics_after_msecs?
- TrackedTopicsUpdater.new(id, auto_track_topics_after_msecs).call
- end
+ def update_tracked_topics
+ return unless saved_change_to_auto_track_topics_after_msecs?
+ TrackedTopicsUpdater.new(id, auto_track_topics_after_msecs).call
+ end
end
diff --git a/app/models/web_hook.rb b/app/models/web_hook.rb
index c2c016741e6..8bea527b713 100644
--- a/app/models/web_hook.rb
+++ b/app/models/web_hook.rb
@@ -93,9 +93,9 @@ class WebHook < ActiveRecord::Base
private
- def self.guardian
- @guardian ||= Guardian.new(Discourse.system_user)
- end
+ def self.guardian
+ @guardian ||= Guardian.new(Discourse.system_user)
+ end
end
# == Schema Information
diff --git a/app/serializers/admin_user_action_serializer.rb b/app/serializers/admin_user_action_serializer.rb
index dfe2cbc6314..4bc1db5f5a3 100644
--- a/app/serializers/admin_user_action_serializer.rb
+++ b/app/serializers/admin_user_action_serializer.rb
@@ -81,12 +81,12 @@ class AdminUserActionSerializer < ApplicationSerializer
private
- # we need this to handle deleted topics which aren't loaded via the .includes(:topic)
- # because Rails 4 "unscoped" support is bugged (cf. https://github.com/rails/rails/issues/13775)
- def topic
- return @topic if @topic
- @topic = object.topic || Topic.with_deleted.find(object.topic_id)
- @topic
- end
+ # we need this to handle deleted topics which aren't loaded via the .includes(:topic)
+ # because Rails 4 "unscoped" support is bugged (cf. https://github.com/rails/rails/issues/13775)
+ def topic
+ return @topic if @topic
+ @topic = object.topic || Topic.with_deleted.find(object.topic_id)
+ @topic
+ end
end
diff --git a/app/serializers/basic_group_serializer.rb b/app/serializers/basic_group_serializer.rb
index 26fb3ea2dec..6ac6f23b490 100644
--- a/app/serializers/basic_group_serializer.rb
+++ b/app/serializers/basic_group_serializer.rb
@@ -68,15 +68,15 @@ class BasicGroupSerializer < ApplicationSerializer
private
- def staff?
- @staff ||= scope.is_staff?
- end
+ def staff?
+ @staff ||= scope.is_staff?
+ end
- def user_group_ids
- @options[:user_group_ids]
- end
+ def user_group_ids
+ @options[:user_group_ids]
+ end
- def owner_group_ids
- @options[:owner_group_ids]
- end
+ def owner_group_ids
+ @options[:owner_group_ids]
+ end
end
diff --git a/app/serializers/listable_topic_serializer.rb b/app/serializers/listable_topic_serializer.rb
index aeecddbeaef..40b29f63836 100644
--- a/app/serializers/listable_topic_serializer.rb
+++ b/app/serializers/listable_topic_serializer.rb
@@ -121,8 +121,8 @@ class ListableTopicSerializer < BasicTopicSerializer
protected
- def unread_helper
- @unread_helper ||= Unread.new(object, object.user_data, scope)
- end
+ def unread_helper
+ @unread_helper ||= Unread.new(object, object.user_data, scope)
+ end
end
diff --git a/app/serializers/post_action_type_serializer.rb b/app/serializers/post_action_type_serializer.rb
index 718c84a5b7e..9ea2847e9aa 100644
--- a/app/serializers/post_action_type_serializer.rb
+++ b/app/serializers/post_action_type_serializer.rb
@@ -45,9 +45,9 @@ class PostActionTypeSerializer < ApplicationSerializer
protected
- def i18n(field, vars = nil)
- key = "post_action_types.#{name_key}.#{field}"
- vars ? I18n.t(key, vars) : I18n.t(key)
- end
+ def i18n(field, vars = nil)
+ key = "post_action_types.#{name_key}.#{field}"
+ vars ? I18n.t(key, vars) : I18n.t(key)
+ end
end
diff --git a/app/serializers/post_revision_serializer.rb b/app/serializers/post_revision_serializer.rb
index e8c7e9f16ee..6bfb7dbb033 100644
--- a/app/serializers/post_revision_serializer.rb
+++ b/app/serializers/post_revision_serializer.rb
@@ -173,94 +173,94 @@ class PostRevisionSerializer < ApplicationSerializer
protected
- def post
- @post ||= object.post
+ def post
+ @post ||= object.post
+ end
+
+ def topic
+ @topic ||= object.post.topic
+ end
+
+ def revisions
+ @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).to_a
+
+ latest_modifications = {
+ "raw" => [post.raw],
+ "cooked" => [post.cooked],
+ "edit_reason" => [post.edit_reason],
+ "wiki" => [post.wiki],
+ "post_type" => [post.post_type],
+ "user_id" => [post.user_id]
+ }
+
+ # Retrieve any `tracked_topic_fields`
+ PostRevisor.tracked_topic_fields.each_key do |field|
+ latest_modifications[field.to_s] = [topic.send(field)] if topic.respond_to?(field)
end
- def topic
- @topic ||= object.post.topic
- end
+ 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)
- def revisions
- @revisions ||= all_revisions.select { |r| scope.can_view_hidden_post_revisions? || !r["hidden"] }
- end
+ post_revisions << PostRevision.new(
+ number: post_revisions.last.number + 1,
+ hidden: post.hidden,
+ modifications: latest_modifications
+ )
- def all_revisions
- return @all_revisions if @all_revisions
+ @all_revisions = []
- post_revisions = PostRevision.where(post_id: object.post_id).order(:number).to_a
+ # backtrack
+ post_revisions.each do |pr|
+ revision = HashWithIndifferentAccess.new
+ revision[:revision] = pr.number
+ revision[:hidden] = pr.hidden
- latest_modifications = {
- "raw" => [post.raw],
- "cooked" => [post.cooked],
- "edit_reason" => [post.edit_reason],
- "wiki" => [post.wiki],
- "post_type" => [post.post_type],
- "user_id" => [post.user_id]
- }
-
- # Retrieve any `tracked_topic_fields`
- PostRevisor.tracked_topic_fields.each_key do |field|
- latest_modifications[field.to_s] = [topic.send(field)] if topic.respond_to?(field)
+ pr.modifications.each_key do |field|
+ revision[field] = pr.modifications[field][0]
end
- 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
- )
-
- @all_revisions = []
-
- # backtrack
- post_revisions.each do |pr|
- revision = HashWithIndifferentAccess.new
- revision[:revision] = pr.number
- revision[:hidden] = pr.hidden
-
- pr.modifications.each_key do |field|
- revision[field] = pr.modifications[field][0]
- end
-
- @all_revisions << revision
- end
-
- # waterfall
- (@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]
- end
- end
-
- @all_revisions
+ @all_revisions << revision
end
- def previous
- @previous ||= revisions.select { |r| r["revision"] <= current_revision }.last
- end
+ # waterfall
+ (@all_revisions.count - 1).downto(1).each do |r|
+ cur = @all_revisions[r]
+ prev = @all_revisions[r - 1]
- def current
- @current ||= revisions.select { |r| r["revision"] > current_revision }.first
- end
-
- def user
- # if stuff goes pear shape attribute to system
- object.user || Discourse.system_user
- end
-
- def filter_visible_tags(tags)
- if tags.is_a?(Array) && tags.size > 0
- @hidden_tag_names ||= DiscourseTagging.hidden_tag_names(scope)
- tags - @hidden_tag_names
- else
- tags
+ cur.each_key do |field|
+ prev[field] = prev.has_key?(field) ? prev[field] : cur[field]
end
end
+ @all_revisions
+ end
+
+ def previous
+ @previous ||= revisions.select { |r| r["revision"] <= current_revision }.last
+ end
+
+ def current
+ @current ||= revisions.select { |r| r["revision"] > current_revision }.first
+ end
+
+ def user
+ # if stuff goes pear shape attribute to system
+ object.user || Discourse.system_user
+ end
+
+ def filter_visible_tags(tags)
+ if tags.is_a?(Array) && tags.size > 0
+ @hidden_tag_names ||= DiscourseTagging.hidden_tag_names(scope)
+ tags - @hidden_tag_names
+ else
+ tags
+ end
+ end
+
end
diff --git a/app/serializers/post_serializer.rb b/app/serializers/post_serializer.rb
index e66fa720fd6..d389cecafef 100644
--- a/app/serializers/post_serializer.rb
+++ b/app/serializers/post_serializer.rb
@@ -380,26 +380,26 @@ class PostSerializer < BasicPostSerializer
private
- def topic
- @topic = object.topic
- @topic ||= Topic.with_deleted.find(object.topic_id) if scope.is_staff?
- @topic
- end
+ def topic
+ @topic = object.topic
+ @topic ||= Topic.with_deleted.find(object.topic_id) if scope.is_staff?
+ @topic
+ end
- def post_actions
- @post_actions ||= (@topic_view&.all_post_actions || {})[object.id]
- end
+ def post_actions
+ @post_actions ||= (@topic_view&.all_post_actions || {})[object.id]
+ end
- def active_flags
- @active_flags ||= (@topic_view&.all_active_flags || {})[object.id]
- end
+ def active_flags
+ @active_flags ||= (@topic_view&.all_active_flags || {})[object.id]
+ end
- def post_custom_fields
- @post_custom_fields ||= if @topic_view
- (@topic_view.post_custom_fields || {})[object.id] || {}
- else
- object.custom_fields
- end
+ def post_custom_fields
+ @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/topic_flag_type_serializer.rb b/app/serializers/topic_flag_type_serializer.rb
index c0ac6951bd0..4caa98a6985 100644
--- a/app/serializers/topic_flag_type_serializer.rb
+++ b/app/serializers/topic_flag_type_serializer.rb
@@ -2,9 +2,9 @@ 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
+ 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_view_serializer.rb b/app/serializers/topic_view_serializer.rb
index 44479aa7e0a..9475da548a1 100644
--- a/app/serializers/topic_view_serializer.rb
+++ b/app/serializers/topic_view_serializer.rb
@@ -301,8 +301,8 @@ class TopicViewSerializer < ApplicationSerializer
private
- def private_message?(topic)
- @private_message ||= topic.private_message?
- end
+ def private_message?(topic)
+ @private_message ||= topic.private_message?
+ end
end
diff --git a/app/services/group_action_logger.rb b/app/services/group_action_logger.rb
index 58674016c37..bcd5e56908e 100644
--- a/app/services/group_action_logger.rb
+++ b/app/services/group_action_logger.rb
@@ -58,21 +58,21 @@ class GroupActionLogger
private
- def excluded_attributes
- [
- :bio_cooked,
- :updated_at,
- :created_at,
- :user_count
- ]
- end
+ def excluded_attributes
+ [
+ :bio_cooked,
+ :updated_at,
+ :created_at,
+ :user_count
+ ]
+ end
- def default_params
- { group: @group, acting_user: @acting_user }
- end
+ def default_params
+ { group: @group, acting_user: @acting_user }
+ end
- def can_edit?
- raise Discourse::InvalidParameters.new unless Guardian.new(@acting_user).can_log_group_changes?(@group)
- end
+ def can_edit?
+ raise Discourse::InvalidParameters.new unless Guardian.new(@acting_user).can_log_group_changes?(@group)
+ end
end
diff --git a/app/services/staff_action_logger.rb b/app/services/staff_action_logger.rb
index f9205e075e1..d8360735806 100644
--- a/app/services/staff_action_logger.rb
+++ b/app/services/staff_action_logger.rb
@@ -550,13 +550,13 @@ class StaffActionLogger
private
- def params(opts = nil)
- opts ||= {}
- { acting_user_id: @admin.id, context: opts[:context] }
- end
+ def params(opts = nil)
+ opts ||= {}
+ { acting_user_id: @admin.id, context: opts[:context] }
+ end
- def validate_category(category)
- raise Discourse::InvalidParameters.new(:category) unless category && category.is_a?(Category)
- end
+ def validate_category(category)
+ raise Discourse::InvalidParameters.new(:category) unless category && category.is_a?(Category)
+ end
end
diff --git a/app/services/user_anonymizer.rb b/app/services/user_anonymizer.rb
index 7184f1ac87b..45fd0f341d6 100644
--- a/app/services/user_anonymizer.rb
+++ b/app/services/user_anonymizer.rb
@@ -77,13 +77,13 @@ class UserAnonymizer
private
- def make_anon_username
- 100.times do
- new_username = "anon#{(SecureRandom.random_number * 100000000).to_i}"
- return new_username unless User.where(username_lower: new_username).exists?
- end
- raise "Failed to generate an anon username"
+ def make_anon_username
+ 100.times do
+ new_username = "anon#{(SecureRandom.random_number * 100000000).to_i}"
+ return new_username unless User.where(username_lower: new_username).exists?
end
+ raise "Failed to generate an anon username"
+ end
def ip_where(column = 'user_id')
["#{column} = :user_id AND ip_address IS NOT NULL", user_id: @user.id]
diff --git a/lib/auth/facebook_authenticator.rb b/lib/auth/facebook_authenticator.rb
index 50e717d7395..f4ea2f1b852 100644
--- a/lib/auth/facebook_authenticator.rb
+++ b/lib/auth/facebook_authenticator.rb
@@ -63,58 +63,58 @@ class Auth::FacebookAuthenticator < Auth::Authenticator
protected
- def parse_auth_token(auth_token)
- raw_info = auth_token["extra"]["raw_info"]
- info = auth_token["info"]
+ def parse_auth_token(auth_token)
+ raw_info = auth_token["extra"]["raw_info"]
+ info = auth_token["info"]
- email = auth_token["info"][:email]
+ email = auth_token["info"][:email]
- website = (info["urls"] && info["urls"]["Website"]) || nil
+ website = (info["urls"] && info["urls"]["Website"]) || nil
- {
- facebook: {
- facebook_user_id: auth_token["uid"],
- link: raw_info["link"],
- username: raw_info["username"],
- first_name: raw_info["first_name"],
- last_name: raw_info["last_name"],
- email: email,
- gender: raw_info["gender"],
- name: raw_info["name"],
- avatar_url: info["image"],
- location: info["location"],
- website: website,
- about_me: info["description"]
- },
+ {
+ facebook: {
+ facebook_user_id: auth_token["uid"],
+ link: raw_info["link"],
+ username: raw_info["username"],
+ first_name: raw_info["first_name"],
+ last_name: raw_info["last_name"],
email: email,
- email_valid: true
- }
+ gender: raw_info["gender"],
+ name: raw_info["name"],
+ avatar_url: info["image"],
+ location: info["location"],
+ website: website,
+ about_me: info["description"]
+ },
+ email: email,
+ email_valid: true
+ }
+ end
+
+ def retrieve_avatar(user, data)
+ return unless user
+ return if user.user_avatar.try(:custom_upload_id).present?
+
+ if (avatar_url = data[:avatar_url]).present?
+ url = "#{avatar_url}?height=#{AVATAR_SIZE}&width=#{AVATAR_SIZE}"
+ Jobs.enqueue(:download_avatar_from_url, url: url, user_id: user.id, override_gravatar: false)
end
+ end
- def retrieve_avatar(user, data)
- return unless user
- return if user.user_avatar.try(:custom_upload_id).present?
+ def retrieve_profile(user, data)
+ return unless user
- if (avatar_url = data[:avatar_url]).present?
- url = "#{avatar_url}?height=#{AVATAR_SIZE}&width=#{AVATAR_SIZE}"
- Jobs.enqueue(:download_avatar_from_url, url: url, user_id: user.id, override_gravatar: false)
- end
- end
-
- def retrieve_profile(user, data)
- return unless user
-
- bio = data[:about_me] || data[:about]
- location = data[:location]
- website = data[:website]
-
- if bio || location || website
- profile = user.user_profile
- profile.bio_raw = bio unless profile.bio_raw.present?
- profile.location = location unless profile.location.present?
- profile.website = website unless profile.website.present?
- profile.save
- end
+ bio = data[:about_me] || data[:about]
+ location = data[:location]
+ website = data[:website]
+
+ if bio || location || website
+ profile = user.user_profile
+ profile.bio_raw = bio unless profile.bio_raw.present?
+ profile.location = location unless profile.location.present?
+ profile.website = website unless profile.website.present?
+ profile.save
end
+ end
end
diff --git a/lib/auth/twitter_authenticator.rb b/lib/auth/twitter_authenticator.rb
index 36a16b1cf9d..b4ef82d9ebd 100644
--- a/lib/auth/twitter_authenticator.rb
+++ b/lib/auth/twitter_authenticator.rb
@@ -69,28 +69,28 @@ class Auth::TwitterAuthenticator < Auth::Authenticator
protected
- def retrieve_avatar(user, data)
- return unless user
- return if user.user_avatar.try(:custom_upload_id).present?
+ def retrieve_avatar(user, data)
+ return unless user
+ return if user.user_avatar.try(:custom_upload_id).present?
- if (avatar_url = data[:twitter_image]).present?
- url = avatar_url.sub("_normal", "")
- Jobs.enqueue(:download_avatar_from_url, url: url, user_id: user.id, override_gravatar: false)
- end
+ if (avatar_url = data[:twitter_image]).present?
+ url = avatar_url.sub("_normal", "")
+ Jobs.enqueue(:download_avatar_from_url, url: url, user_id: user.id, override_gravatar: false)
end
+ end
- def retrieve_profile(user, data)
- return unless user
+ def retrieve_profile(user, data)
+ return unless user
- bio = data[:twitter_description]
- location = data[:twitter_location]
+ bio = data[:twitter_description]
+ location = data[:twitter_location]
- if bio || location
- profile = user.user_profile
- profile.bio_raw = bio unless profile.bio_raw.present?
- profile.location = location unless profile.location.present?
- profile.save
- end
+ if bio || location
+ profile = user.user_profile
+ profile.bio_raw = bio unless profile.bio_raw.present?
+ profile.location = location unless profile.location.present?
+ profile.save
end
+ end
end
diff --git a/lib/common_passwords/common_passwords.rb b/lib/common_passwords/common_passwords.rb
index 0045cc8a366..bec6fca43f4 100644
--- a/lib/common_passwords/common_passwords.rb
+++ b/lib/common_passwords/common_passwords.rb
@@ -23,32 +23,32 @@ class CommonPasswords
private
- class RedisPasswordList
- def include?(password)
- CommonPasswords.redis.sismember CommonPasswords::LIST_KEY, password
- end
+ class RedisPasswordList
+ def include?(password)
+ CommonPasswords.redis.sismember CommonPasswords::LIST_KEY, password
end
+ end
- def self.password_list
- @mutex.synchronize do
- load_passwords unless redis.scard(LIST_KEY) > 0
- end
- RedisPasswordList.new
+ def self.password_list
+ @mutex.synchronize do
+ load_passwords unless redis.scard(LIST_KEY) > 0
end
+ RedisPasswordList.new
+ end
- def self.redis
- $redis.without_namespace
- end
+ def self.redis
+ $redis.without_namespace
+ end
- def self.load_passwords
- passwords = File.readlines(PASSWORD_FILE)
- passwords.map!(&:chomp).each do |pwd|
- # slower, but a tad more compatible
- redis.sadd LIST_KEY, pwd
- end
- rescue Errno::ENOENT
- # tolerate this so we don't block signups
- Rails.logger.error "Common passwords file #{PASSWORD_FILE} is not found! Common password checking is skipped."
+ def self.load_passwords
+ passwords = File.readlines(PASSWORD_FILE)
+ passwords.map!(&:chomp).each do |pwd|
+ # slower, but a tad more compatible
+ redis.sadd LIST_KEY, pwd
end
+ rescue Errno::ENOENT
+ # tolerate this so we don't block signups
+ Rails.logger.error "Common passwords file #{PASSWORD_FILE} is not found! Common password checking is skipped."
+ end
end
diff --git a/lib/composer_messages_finder.rb b/lib/composer_messages_finder.rb
index 76c582dd572..a539df70653 100644
--- a/lib/composer_messages_finder.rb
+++ b/lib/composer_messages_finder.rb
@@ -193,20 +193,20 @@ class ComposerMessagesFinder
private
- def educate_reply?(type)
- replying? &&
- @details[:topic_id] &&
- (@topic.present? && !@topic.private_message?) &&
- (@user.post_count >= SiteSetting.educate_until_posts) &&
- !UserHistory.exists_for_user?(@user, type, topic_id: @details[:topic_id])
- end
+ def educate_reply?(type)
+ replying? &&
+ @details[:topic_id] &&
+ (@topic.present? && !@topic.private_message?) &&
+ (@user.post_count >= SiteSetting.educate_until_posts) &&
+ !UserHistory.exists_for_user?(@user, type, topic_id: @details[:topic_id])
+ end
- def creating_topic?
- @details[:composer_action] == "createTopic"
- end
+ def creating_topic?
+ @details[:composer_action] == "createTopic"
+ end
- def replying?
- @details[:composer_action] == "reply"
- end
+ def replying?
+ @details[:composer_action] == "reply"
+ end
end
diff --git a/lib/email_updater.rb b/lib/email_updater.rb
index d3d8eaf339b..dd7670f75b6 100644
--- a/lib/email_updater.rb
+++ b/lib/email_updater.rb
@@ -104,19 +104,19 @@ class EmailUpdater
protected
- def notify_old(old_email, new_email)
- Jobs.enqueue :critical_user_email,
- to_address: old_email,
- type: :notify_old_email,
- user_id: @user.id
- end
+ def notify_old(old_email, new_email)
+ Jobs.enqueue :critical_user_email,
+ to_address: old_email,
+ type: :notify_old_email,
+ user_id: @user.id
+ end
- def send_email(type, email_token)
- Jobs.enqueue :critical_user_email,
- to_address: email_token.email,
- type: type,
- user_id: @user.id,
- email_token: email_token.token
- end
+ def send_email(type, email_token)
+ Jobs.enqueue :critical_user_email,
+ to_address: email_token.email,
+ type: type,
+ user_id: @user.id,
+ email_token: email_token.token
+ end
end
diff --git a/lib/file_helper.rb b/lib/file_helper.rb
index 7ef59523907..4fc4df68e48 100644
--- a/lib/file_helper.rb
+++ b/lib/file_helper.rb
@@ -96,12 +96,12 @@ class FileHelper
private
- def self.images
- @@images ||= Set.new %w{jpg jpeg png gif tif tiff bmp svg webp ico}
- end
+ def self.images
+ @@images ||= Set.new %w{jpg jpeg png gif tif tiff bmp svg webp ico}
+ end
- def self.images_regexp
- @@images_regexp ||= /\.(#{images.to_a.join("|")})$/i
- end
+ def self.images_regexp
+ @@images_regexp ||= /\.(#{images.to_a.join("|")})$/i
+ end
end
diff --git a/lib/flag_query.rb b/lib/flag_query.rb
index 11db2aa887d..1d833200d83 100644
--- a/lib/flag_query.rb
+++ b/lib/flag_query.rb
@@ -224,14 +224,14 @@ module FlagQuery
private
- def self.excerpt(cooked)
- excerpt = Post.excerpt(cooked, 200, keep_emoji_images: true)
- # remove the first link if it's the first node
- fragment = Nokogiri::HTML.fragment(excerpt)
- if fragment.children.first == fragment.css("a:first").first && fragment.children.first
- fragment.children.first.remove
- end
- fragment.to_html.strip
+ def self.excerpt(cooked)
+ excerpt = Post.excerpt(cooked, 200, keep_emoji_images: true)
+ # remove the first link if it's the first node
+ fragment = Nokogiri::HTML.fragment(excerpt)
+ if fragment.children.first == fragment.css("a:first").first && fragment.children.first
+ fragment.children.first.remove
end
+ fragment.to_html.strip
+ end
end
diff --git a/lib/freedom_patches/rack_patches.rb b/lib/freedom_patches/rack_patches.rb
index 890435d9b9c..4cdc2dce11b 100644
--- a/lib/freedom_patches/rack_patches.rb
+++ b/lib/freedom_patches/rack_patches.rb
@@ -3,40 +3,40 @@
class Rack::ETag
private
- def digest_body(body)
- parts = []
- has_body = false
+ def digest_body(body)
+ parts = []
+ has_body = false
- body.each do |part|
- parts << part
- has_body ||= part.length > 0
- end
+ body.each do |part|
+ parts << part
+ has_body ||= part.length > 0
+ end
- hexdigest =
- if has_body
- digest = Digest::MD5.new
- parts.each { |part| digest << part }
- digest.hexdigest
- end
+ hexdigest =
+ if has_body
+ digest = Digest::MD5.new
+ parts.each { |part| digest << part }
+ digest.hexdigest
+ end
- [hexdigest, parts]
- end
+ [hexdigest, parts]
+ end
end
# patch https://github.com/rack/rack/pull/596
#
class Rack::ConditionalGet
private
- def to_rfc2822(since)
- # shortest possible valid date is the obsolete: 1 Nov 97 09:55 A
- # anything shorter is invalid, this avoids exceptions for common cases
- # most common being the empty string
- if since && since.length >= 16
- # NOTE: there is no trivial way to write this in a non execption way
- # _rfc2822 returns a hash but is not that usable
- Time.rfc2822(since) rescue nil
- else
- nil
- end
- end
+ def to_rfc2822(since)
+ # shortest possible valid date is the obsolete: 1 Nov 97 09:55 A
+ # anything shorter is invalid, this avoids exceptions for common cases
+ # most common being the empty string
+ if since && since.length >= 16
+ # NOTE: there is no trivial way to write this in a non execption way
+ # _rfc2822 returns a hash but is not that usable
+ Time.rfc2822(since) rescue nil
+ else
+ nil
+ end
+ end
end
diff --git a/lib/i18n/backend/discourse_i18n.rb b/lib/i18n/backend/discourse_i18n.rb
index 1f33dd60e0d..fec8150c79f 100644
--- a/lib/i18n/backend/discourse_i18n.rb
+++ b/lib/i18n/backend/discourse_i18n.rb
@@ -52,54 +52,54 @@ module I18n
protected
- def find_results(regexp, results, translations, path = nil)
- return results if translations.blank?
+ def find_results(regexp, results, translations, path = nil)
+ return results if translations.blank?
- translations.each do |k_sym, v|
- k = k_sym.to_s
- key_path = path ? "#{path}.#{k}" : k
- if v.is_a?(String)
- unless results.has_key?(key_path)
- results[key_path] = v if key_path =~ regexp || v =~ regexp
- end
- elsif v.is_a?(Hash)
- find_results(regexp, results, v, key_path)
+ translations.each do |k_sym, v|
+ k = k_sym.to_s
+ key_path = path ? "#{path}.#{k}" : k
+ if v.is_a?(String)
+ unless results.has_key?(key_path)
+ results[key_path] = v if key_path =~ regexp || v =~ regexp
end
+ elsif v.is_a?(Hash)
+ find_results(regexp, results, v, key_path)
end
- results
end
+ results
+ end
- # Support interpolation and pluralization of overrides by first looking up
- # the original translations before applying our overrides.
- def lookup(locale, key, scope = [], options = {})
- existing_translations = super(locale, key, scope, options)
- return existing_translations if scope.is_a?(Array) && scope.include?(:models)
+ # Support interpolation and pluralization of overrides by first looking up
+ # the original translations before applying our overrides.
+ def lookup(locale, key, scope = [], options = {})
+ existing_translations = super(locale, key, scope, options)
+ return existing_translations if scope.is_a?(Array) && scope.include?(:models)
- overrides = options.dig(:overrides, locale)
+ overrides = options.dig(:overrides, locale)
- if overrides
- if existing_translations && options[:count]
- remapped_translations =
- if existing_translations.is_a?(Hash)
- Hash[existing_translations.map { |k, v| ["#{key}.#{k}", v] }]
- elsif existing_translations.is_a?(String)
- Hash[[[key, existing_translations]]]
- end
-
- result = {}
-
- remapped_translations.merge(overrides).each do |k, v|
- result[k.split('.').last.to_sym] = v if k != key && k.start_with?(key.to_s)
+ if overrides
+ if existing_translations && options[:count]
+ remapped_translations =
+ if existing_translations.is_a?(Hash)
+ Hash[existing_translations.map { |k, v| ["#{key}.#{k}", v] }]
+ elsif existing_translations.is_a?(String)
+ Hash[[[key, existing_translations]]]
end
- return result if result.size > 0
- end
- return overrides[key] if overrides[key]
+ result = {}
+
+ remapped_translations.merge(overrides).each do |k, v|
+ result[k.split('.').last.to_sym] = v if k != key && k.start_with?(key.to_s)
+ end
+ return result if result.size > 0
end
- existing_translations
+ return overrides[key] if overrides[key]
end
+ existing_translations
+ end
+
end
end
end
diff --git a/lib/i18n/duplicate_key_finder.rb b/lib/i18n/duplicate_key_finder.rb
index 745b5ce2933..f23221d13e9 100644
--- a/lib/i18n/duplicate_key_finder.rb
+++ b/lib/i18n/duplicate_key_finder.rb
@@ -10,8 +10,8 @@ class DuplicateKeyFinder < LocaleFileWalker
protected
- def handle_scalar(node, depth, parents)
- super
- @keys_with_count[parents.join('.')] += 1
- end
+ def handle_scalar(node, depth, parents)
+ super
+ @keys_with_count[parents.join('.')] += 1
+ end
end
diff --git a/lib/inline_oneboxer.rb b/lib/inline_oneboxer.rb
index aafe3b338cb..7e1ccfa29fd 100644
--- a/lib/inline_oneboxer.rb
+++ b/lib/inline_oneboxer.rb
@@ -63,20 +63,20 @@ class InlineOneboxer
private
- def self.onebox_for(url, title, opts)
- onebox = {
- url: url,
- title: title && Emoji.gsub_emoji_to_unicode(title)
- }
- unless opts[:skip_cache]
- Rails.cache.write(cache_key(url), onebox, expires_in: 1.day)
- end
-
- onebox
+ def self.onebox_for(url, title, opts)
+ onebox = {
+ url: url,
+ title: title && Emoji.gsub_emoji_to_unicode(title)
+ }
+ unless opts[:skip_cache]
+ Rails.cache.write(cache_key(url), onebox, expires_in: 1.day)
end
- def self.cache_key(url)
- "inline_onebox:#{url}"
- end
+ onebox
+ end
+
+ def self.cache_key(url)
+ "inline_onebox:#{url}"
+ end
end
diff --git a/lib/onebox/engine/whitelisted_generic_onebox.rb b/lib/onebox/engine/whitelisted_generic_onebox.rb
index f48ad2f214e..64b22dae9cc 100644
--- a/lib/onebox/engine/whitelisted_generic_onebox.rb
+++ b/lib/onebox/engine/whitelisted_generic_onebox.rb
@@ -16,22 +16,22 @@ module Onebox
private
- # overwrite to whitelist iframes
- def is_embedded?
- return false unless data[:html] && data[:height]
- return true if WhitelistedGenericOnebox.html_providers.include?(data[:provider_name])
+ # overwrite to whitelist iframes
+ def is_embedded?
+ return false unless data[:html] && data[:height]
+ return true if WhitelistedGenericOnebox.html_providers.include?(data[:provider_name])
- if data[:html]["iframe"]
- fragment = Nokogiri::HTML::fragment(data[:html])
- if iframe = fragment.at_css("iframe")
- src = iframe["src"]
- return src.present? && SiteSetting.allowed_iframes.split("|").any? { |url| src.start_with?(url) }
- end
+ if data[:html]["iframe"]
+ fragment = Nokogiri::HTML::fragment(data[:html])
+ if iframe = fragment.at_css("iframe")
+ src = iframe["src"]
+ return src.present? && SiteSetting.allowed_iframes.split("|").any? { |url| src.start_with?(url) }
end
-
- false
end
+ false
+ end
+
end
end
end
diff --git a/lib/oneboxer.rb b/lib/oneboxer.rb
index dc5b6491572..2f99c0f8145 100644
--- a/lib/oneboxer.rb
+++ b/lib/oneboxer.rb
@@ -125,151 +125,151 @@ module Oneboxer
private
- def self.preview_key(user_id)
- "onebox:preview:#{user_id}"
- end
+ def self.preview_key(user_id)
+ "onebox:preview:#{user_id}"
+ end
- def self.blank_onebox
- { preview: "", onebox: "" }
- end
+ def self.blank_onebox
+ { preview: "", onebox: "" }
+ end
- def self.onebox_cache_key(url)
- "onebox__#{url}"
- end
+ def self.onebox_cache_key(url)
+ "onebox__#{url}"
+ end
- def self.onebox_raw(url, opts = {})
- url = URI(url).to_s
- local_onebox(url, opts) || external_onebox(url)
- rescue => e
- # no point warning here, just cause we have an issue oneboxing a url
- # we can later hunt for failed oneboxes by searching logs if needed
- Rails.logger.info("Failed to onebox #{url} #{e} #{e.backtrace}")
- # return a blank hash, so rest of the code works
- blank_onebox
- end
+ def self.onebox_raw(url, opts = {})
+ url = URI(url).to_s
+ local_onebox(url, opts) || external_onebox(url)
+ rescue => e
+ # no point warning here, just cause we have an issue oneboxing a url
+ # we can later hunt for failed oneboxes by searching logs if needed
+ Rails.logger.info("Failed to onebox #{url} #{e} #{e.backtrace}")
+ # return a blank hash, so rest of the code works
+ blank_onebox
+ end
- def self.local_onebox(url, opts = {})
- return unless route = Discourse.route_for(url)
+ def self.local_onebox(url, opts = {})
+ return unless route = Discourse.route_for(url)
- html =
- case route[:controller]
- when "uploads" then local_upload_html(url)
- when "topics" then local_topic_html(url, route, opts)
- when "users" then local_user_html(url, route)
- end
-
- html = html.presence || "#{url}"
- { onebox: html, preview: html }
- end
-
- def self.local_upload_html(url)
- case File.extname(URI(url).path || "")
- when /^\.(mov|mp4|webm|ogv)$/i
- ""
- when /^\.(mp3|ogg|wav|m4a)$/i
- ""
- end
- end
-
- def self.local_topic_html(url, route, opts)
- return unless current_user = User.find_by(id: opts[:user_id])
-
- if current_category = Category.find_by(id: opts[:category_id])
- return unless Guardian.new(current_user).can_see_category?(current_category)
+ html =
+ case route[:controller]
+ when "uploads" then local_upload_html(url)
+ when "topics" then local_topic_html(url, route, opts)
+ when "users" then local_user_html(url, route)
end
- if current_topic = Topic.find_by(id: opts[:topic_id])
- return unless Guardian.new(current_user).can_see_topic?(current_topic)
- end
+ html = html.presence || "#{url}"
+ { onebox: html, preview: html }
+ end
- topic = Topic.find_by(id: route[:topic_id])
+ def self.local_upload_html(url)
+ case File.extname(URI(url).path || "")
+ when /^\.(mov|mp4|webm|ogv)$/i
+ ""
+ when /^\.(mp3|ogg|wav|m4a)$/i
+ ""
+ end
+ end
- return unless topic
- return if topic.private_message?
+ def self.local_topic_html(url, route, opts)
+ return unless current_user = User.find_by(id: opts[:user_id])
- if current_category&.id != topic.category_id
- return unless Guardian.new.can_see_topic?(topic)
- end
-
- post_number = route[:post_number].to_i
-
- post = post_number > 1 ?
- topic.posts.where(post_number: post_number).first :
- topic.ordered_posts.first
-
- return if !post || post.hidden || post.post_type != Post.types[:regular]
-
- if post_number > 1 && current_topic&.id == topic.id
- excerpt = post.excerpt(SiteSetting.post_onebox_maxlength)
- excerpt.gsub!(/[\r\n]+/, " ")
- excerpt.gsub!("[/quote]", "[quote]") # don't break my quote
-
- quote = "[quote=\"#{post.user.username}, topic:#{topic.id}, post:#{post.post_number}\"]\n#{excerpt}\n[/quote]"
-
- PrettyText.cook(quote)
- else
- args = {
- topic_id: topic.id,
- post_number: post.post_number,
- avatar: PrettyText.avatar_img(post.user.avatar_template, "tiny"),
- original_url: url,
- title: PrettyText.unescape_emoji(CGI::escapeHTML(topic.title)),
- category_html: CategoryBadge.html_for(topic.category),
- quote: PrettyText.unescape_emoji(post.excerpt(SiteSetting.post_onebox_maxlength)),
- }
-
- template = File.read("#{Rails.root}/lib/onebox/templates/discourse_topic_onebox.hbs")
- Mustache.render(template, args)
- end
+ if current_category = Category.find_by(id: opts[:category_id])
+ return unless Guardian.new(current_user).can_see_category?(current_category)
end
- def self.local_user_html(url, route)
- username = route[:username] || ""
-
- if user = User.find_by(username_lower: username.downcase)
- args = {
- user_id: user.id,
- username: user.username,
- avatar: PrettyText.avatar_img(user.avatar_template, "extra_large"),
- name: user.name,
- bio: user.user_profile.bio_excerpt(230),
- location: user.user_profile.location,
- joined: I18n.t('joined'),
- created_at: user.created_at.strftime(I18n.t('datetime_formats.formats.date_only')),
- website: user.user_profile.website,
- website_name: UserSerializer.new(user).website_name,
- original_url: url
- }
-
- template = File.read("#{Rails.root}/lib/onebox/templates/discourse_user_onebox.hbs")
- Mustache.render(template, args)
- else
- nil
- end
+ if current_topic = Topic.find_by(id: opts[:topic_id])
+ return unless Guardian.new(current_user).can_see_topic?(current_topic)
end
- def self.external_onebox(url)
- Rails.cache.fetch(onebox_cache_key(url), expires_in: 1.day) do
- fd = FinalDestination.new(url, ignore_redirects: ignore_redirects, force_get_hosts: force_get_hosts)
- uri = fd.resolve
- return blank_onebox if uri.blank? || SiteSetting.onebox_domains_blacklist.include?(uri.hostname)
+ topic = Topic.find_by(id: route[:topic_id])
- options = {
- cache: {},
- max_width: 695,
- sanitize_config: Sanitize::Config::DISCOURSE_ONEBOX
- }
+ return unless topic
+ return if topic.private_message?
- options[:cookie] = fd.cookie if fd.cookie
-
- if Rails.env.development? && SiteSetting.port.to_i > 0
- Onebox.options = { allowed_ports: [80, 443, SiteSetting.port.to_i] }
- end
-
- r = Onebox.preview(uri.to_s, options)
-
- { onebox: r.to_s, preview: r&.placeholder_html.to_s }
- end
+ if current_category&.id != topic.category_id
+ return unless Guardian.new.can_see_topic?(topic)
end
+ post_number = route[:post_number].to_i
+
+ post = post_number > 1 ?
+ topic.posts.where(post_number: post_number).first :
+ topic.ordered_posts.first
+
+ return if !post || post.hidden || post.post_type != Post.types[:regular]
+
+ if post_number > 1 && current_topic&.id == topic.id
+ excerpt = post.excerpt(SiteSetting.post_onebox_maxlength)
+ excerpt.gsub!(/[\r\n]+/, " ")
+ excerpt.gsub!("[/quote]", "[quote]") # don't break my quote
+
+ quote = "[quote=\"#{post.user.username}, topic:#{topic.id}, post:#{post.post_number}\"]\n#{excerpt}\n[/quote]"
+
+ PrettyText.cook(quote)
+ else
+ args = {
+ topic_id: topic.id,
+ post_number: post.post_number,
+ avatar: PrettyText.avatar_img(post.user.avatar_template, "tiny"),
+ original_url: url,
+ title: PrettyText.unescape_emoji(CGI::escapeHTML(topic.title)),
+ category_html: CategoryBadge.html_for(topic.category),
+ quote: PrettyText.unescape_emoji(post.excerpt(SiteSetting.post_onebox_maxlength)),
+ }
+
+ template = File.read("#{Rails.root}/lib/onebox/templates/discourse_topic_onebox.hbs")
+ Mustache.render(template, args)
+ end
+ end
+
+ def self.local_user_html(url, route)
+ username = route[:username] || ""
+
+ if user = User.find_by(username_lower: username.downcase)
+ args = {
+ user_id: user.id,
+ username: user.username,
+ avatar: PrettyText.avatar_img(user.avatar_template, "extra_large"),
+ name: user.name,
+ bio: user.user_profile.bio_excerpt(230),
+ location: user.user_profile.location,
+ joined: I18n.t('joined'),
+ created_at: user.created_at.strftime(I18n.t('datetime_formats.formats.date_only')),
+ website: user.user_profile.website,
+ website_name: UserSerializer.new(user).website_name,
+ original_url: url
+ }
+
+ template = File.read("#{Rails.root}/lib/onebox/templates/discourse_user_onebox.hbs")
+ Mustache.render(template, args)
+ else
+ nil
+ end
+ end
+
+ def self.external_onebox(url)
+ Rails.cache.fetch(onebox_cache_key(url), expires_in: 1.day) do
+ fd = FinalDestination.new(url, ignore_redirects: ignore_redirects, force_get_hosts: force_get_hosts)
+ uri = fd.resolve
+ return blank_onebox if uri.blank? || SiteSetting.onebox_domains_blacklist.include?(uri.hostname)
+
+ options = {
+ cache: {},
+ max_width: 695,
+ sanitize_config: Sanitize::Config::DISCOURSE_ONEBOX
+ }
+
+ options[:cookie] = fd.cookie if fd.cookie
+
+ if Rails.env.development? && SiteSetting.port.to_i > 0
+ Onebox.options = { allowed_ports: [80, 443, SiteSetting.port.to_i] }
+ end
+
+ r = Onebox.preview(uri.to_s, options)
+
+ { onebox: r.to_s, preview: r&.placeholder_html.to_s }
+ end
+ end
+
end
diff --git a/lib/retrieve_title.rb b/lib/retrieve_title.rb
index c8e5f8a7ed9..62c4a4022d4 100644
--- a/lib/retrieve_title.rb
+++ b/lib/retrieve_title.rb
@@ -37,36 +37,36 @@ module RetrieveTitle
private
- def self.max_chunk_size(uri)
+ def self.max_chunk_size(uri)
- # Amazon and YouTube leave the title until very late. Exceptions are bad
- # but these are large sites.
- return 500 if uri.host =~ /amazon\.(com|ca|co\.uk|es|fr|de|it|com\.au|com\.br|cn|in|co\.jp|com\.mx)$/
- return 300 if uri.host =~ /youtube\.com$/ || uri.host =~ /youtu.be/
+ # Amazon and YouTube leave the title until very late. Exceptions are bad
+ # but these are large sites.
+ return 500 if uri.host =~ /amazon\.(com|ca|co\.uk|es|fr|de|it|com\.au|com\.br|cn|in|co\.jp|com\.mx)$/
+ return 300 if uri.host =~ /youtube\.com$/ || uri.host =~ /youtu.be/
- # default is 10k
- 10
- end
+ # default is 10k
+ 10
+ end
- # Fetch the beginning of a HTML document at a url
- def self.fetch_title(url)
- fd = FinalDestination.new(url, timeout: CRAWL_TIMEOUT)
+ # Fetch the beginning of a HTML document at a url
+ def self.fetch_title(url)
+ fd = FinalDestination.new(url, timeout: CRAWL_TIMEOUT)
- current = nil
- title = nil
+ current = nil
+ title = nil
- fd.get do |_response, chunk, uri|
+ fd.get do |_response, chunk, uri|
- if current
- current << chunk
- else
- current = chunk
- end
-
- max_size = max_chunk_size(uri) * 1024
- title = extract_title(current)
- throw :done if title || max_size < current.length
+ if current
+ current << chunk
+ else
+ current = chunk
end
- return title
+
+ max_size = max_chunk_size(uri) * 1024
+ title = extract_title(current)
+ throw :done if title || max_size < current.length
end
+ return title
+ end
end
diff --git a/lib/search.rb b/lib/search.rb
index 40f80a245c4..054f7e5fd05 100644
--- a/lib/search.rb
+++ b/lib/search.rb
@@ -503,399 +503,399 @@ class Search
private
- def process_advanced_search!(term)
+ def process_advanced_search!(term)
- term.to_s.scan(/(([^" \t\n\x0B\f\r]+)?(("[^"]+")?))/).to_a.map do |(word, _)|
- next if word.blank?
+ term.to_s.scan(/(([^" \t\n\x0B\f\r]+)?(("[^"]+")?))/).to_a.map do |(word, _)|
+ next if word.blank?
- found = false
+ found = false
- Search.advanced_filters.each do |matcher, block|
- cleaned = word.gsub(/["']/, "")
- if cleaned =~ matcher
- (@filters ||= []) << [block, $1]
- found = true
+ Search.advanced_filters.each do |matcher, block|
+ cleaned = word.gsub(/["']/, "")
+ if cleaned =~ matcher
+ (@filters ||= []) << [block, $1]
+ found = true
+ end
+ end
+
+ @in_title = false
+
+ if word == 'order:latest' || word == 'l'
+ @order = :latest
+ nil
+ elsif word == 'order:latest_topic'
+ @order = :latest_topic
+ nil
+ elsif word == 'in:title'
+ @in_title = true
+ nil
+ elsif word =~ /topic:(\d+)/
+ topic_id = $1.to_i
+ if topic_id > 1
+ topic = Topic.find_by(id: topic_id)
+ if @guardian.can_see?(topic)
+ @search_context = topic
end
end
-
- @in_title = false
-
- if word == 'order:latest' || word == 'l'
- @order = :latest
- nil
- elsif word == 'order:latest_topic'
- @order = :latest_topic
- nil
- elsif word == 'in:title'
- @in_title = true
- nil
- elsif word =~ /topic:(\d+)/
- topic_id = $1.to_i
- if topic_id > 1
- topic = Topic.find_by(id: topic_id)
- if @guardian.can_see?(topic)
- @search_context = topic
- end
- end
- nil
- elsif word == 'order:views'
- @order = :views
- nil
- elsif word == 'order:likes'
- @order = :likes
- nil
- elsif word == 'in:private'
- @search_pms = true
- nil
- elsif word =~ /^private_messages:(.+)$/
- @search_pms = true
- nil
- else
- found ? nil : word
- end
- end.compact.join(' ')
- end
-
- def find_grouped_results
-
- if @results.type_filter.present?
- raise Discourse::InvalidAccess.new("invalid type filter") unless Search.facets.include?(@results.type_filter)
- send("#{@results.type_filter}_search")
+ nil
+ elsif word == 'order:views'
+ @order = :views
+ nil
+ elsif word == 'order:likes'
+ @order = :likes
+ nil
+ elsif word == 'in:private'
+ @search_pms = true
+ nil
+ elsif word =~ /^private_messages:(.+)$/
+ @search_pms = true
+ nil
else
- unless @search_context
- user_search if @term.present?
- category_search if @term.present?
- tags_search if @term.present?
+ found ? nil : word
+ end
+ end.compact.join(' ')
+ end
+
+ def find_grouped_results
+
+ if @results.type_filter.present?
+ raise Discourse::InvalidAccess.new("invalid type filter") unless Search.facets.include?(@results.type_filter)
+ send("#{@results.type_filter}_search")
+ else
+ unless @search_context
+ user_search if @term.present?
+ category_search if @term.present?
+ tags_search if @term.present?
+ end
+ topic_search
+ end
+
+ add_more_topics_if_expected
+ @results
+ rescue ActiveRecord::StatementInvalid
+ # In the event of a PG:Error return nothing, it is likely they used a foreign language whose
+ # locale is not supported by postgres
+ end
+
+ # Add more topics if we expected them
+ def add_more_topics_if_expected
+ expected_topics = 0
+ expected_topics = Search.facets.size unless @results.type_filter.present?
+ expected_topics = Search.per_facet * Search.facets.size if @results.type_filter == 'topic'
+ expected_topics -= @results.posts.length
+ if expected_topics > 0
+ extra_posts = posts_query(expected_topics * Search.burst_factor)
+ extra_posts = extra_posts.where("posts.topic_id NOT in (?)", @results.posts.map(&:topic_id)) if @results.posts.present?
+ extra_posts.each do |post|
+ @results.add(post)
+ expected_topics -= 1
+ break if expected_topics == 0
+ end
+ end
+ end
+
+ # If we're searching for a single topic
+ def single_topic(id)
+ post = Post.find_by(topic_id: id, post_number: 1)
+ return nil unless @guardian.can_see?(post)
+
+ @results.add(post)
+ @results
+ end
+
+ def secure_category_ids
+ return @secure_category_ids unless @secure_category_ids.nil?
+ @secure_category_ids = @guardian.secure_category_ids
+ end
+
+ def category_search
+ # scope is leaking onto Category, this is not good and probably a bug in Rails
+ # the secure_category_ids will invoke the same method on User, it calls Category.where
+ # however the scope from the query below is leaking in to Category, this works around
+ # the issue while we figure out what is up in Rails
+ secure_category_ids
+
+ categories = Category.includes(:category_search_data)
+ .where("category_search_data.search_data @@ #{ts_query}")
+ .references(:category_search_data)
+ .order("topics_month DESC")
+ .secured(@guardian)
+ .limit(limit)
+
+ categories.each do |category|
+ @results.add(category)
+ end
+ end
+
+ def user_search
+ return if SiteSetting.hide_user_profiles_from_public && !@guardian.user
+
+ users = User.includes(:user_search_data)
+ .references(:user_search_data)
+ .where(active: true)
+ .where(staged: false)
+ .where("user_search_data.search_data @@ #{ts_query("simple")}")
+ .order("CASE WHEN username_lower = '#{@original_term.downcase}' THEN 0 ELSE 1 END")
+ .order("last_posted_at DESC")
+ .limit(limit)
+
+ users.each do |user|
+ @results.add(user)
+ end
+ end
+
+ def tags_search
+ return unless SiteSetting.tagging_enabled
+
+ tags = Tag.includes(:tag_search_data)
+ .where("tag_search_data.search_data @@ #{ts_query}")
+ .references(:tag_search_data)
+ .order("name asc")
+ .limit(limit)
+
+ tags.each do |tag|
+ @results.add(tag)
+ end
+ end
+
+ def posts_query(limit, opts = nil)
+ opts ||= {}
+ posts = Post.where(post_type: Topic.visible_post_types(@guardian.user))
+ .joins(:post_search_data, :topic)
+ .joins("LEFT JOIN categories ON categories.id = topics.category_id")
+ .where("topics.deleted_at" => nil)
+
+ is_topic_search = @search_context.present? && @search_context.is_a?(Topic)
+
+ posts = posts.where("topics.visible") unless is_topic_search
+
+ if opts[:private_messages] || (is_topic_search && @search_context.private_message?)
+ posts = posts.where("topics.archetype = ?", Archetype.private_message)
+
+ unless @guardian.is_admin?
+ posts = posts.private_posts_for_user(@guardian.user)
+ end
+ else
+ posts = posts.where("topics.archetype <> ?", Archetype.private_message)
+ end
+
+ if @term.present?
+ if is_topic_search
+
+ term_without_quote = @term
+ if @term =~ /"(.+)"/
+ term_without_quote = $1
end
- topic_search
- end
- add_more_topics_if_expected
- @results
- rescue ActiveRecord::StatementInvalid
- # In the event of a PG:Error return nothing, it is likely they used a foreign language whose
- # locale is not supported by postgres
- end
-
- # Add more topics if we expected them
- def add_more_topics_if_expected
- expected_topics = 0
- expected_topics = Search.facets.size unless @results.type_filter.present?
- expected_topics = Search.per_facet * Search.facets.size if @results.type_filter == 'topic'
- expected_topics -= @results.posts.length
- if expected_topics > 0
- extra_posts = posts_query(expected_topics * Search.burst_factor)
- extra_posts = extra_posts.where("posts.topic_id NOT in (?)", @results.posts.map(&:topic_id)) if @results.posts.present?
- extra_posts.each do |post|
- @results.add(post)
- expected_topics -= 1
- break if expected_topics == 0
+ if @term =~ /'(.+)'/
+ term_without_quote = $1
end
- end
- end
- # If we're searching for a single topic
- def single_topic(id)
- post = Post.find_by(topic_id: id, post_number: 1)
- return nil unless @guardian.can_see?(post)
-
- @results.add(post)
- @results
- end
-
- def secure_category_ids
- return @secure_category_ids unless @secure_category_ids.nil?
- @secure_category_ids = @guardian.secure_category_ids
- end
-
- def category_search
- # scope is leaking onto Category, this is not good and probably a bug in Rails
- # the secure_category_ids will invoke the same method on User, it calls Category.where
- # however the scope from the query below is leaking in to Category, this works around
- # the issue while we figure out what is up in Rails
- secure_category_ids
-
- categories = Category.includes(:category_search_data)
- .where("category_search_data.search_data @@ #{ts_query}")
- .references(:category_search_data)
- .order("topics_month DESC")
- .secured(@guardian)
- .limit(limit)
-
- categories.each do |category|
- @results.add(category)
- end
- end
-
- def user_search
- return if SiteSetting.hide_user_profiles_from_public && !@guardian.user
-
- users = User.includes(:user_search_data)
- .references(:user_search_data)
- .where(active: true)
- .where(staged: false)
- .where("user_search_data.search_data @@ #{ts_query("simple")}")
- .order("CASE WHEN username_lower = '#{@original_term.downcase}' THEN 0 ELSE 1 END")
- .order("last_posted_at DESC")
- .limit(limit)
-
- users.each do |user|
- @results.add(user)
- end
- end
-
- def tags_search
- return unless SiteSetting.tagging_enabled
-
- tags = Tag.includes(:tag_search_data)
- .where("tag_search_data.search_data @@ #{ts_query}")
- .references(:tag_search_data)
- .order("name asc")
- .limit(limit)
-
- tags.each do |tag|
- @results.add(tag)
- end
- end
-
- def posts_query(limit, opts = nil)
- opts ||= {}
- posts = Post.where(post_type: Topic.visible_post_types(@guardian.user))
- .joins(:post_search_data, :topic)
- .joins("LEFT JOIN categories ON categories.id = topics.category_id")
- .where("topics.deleted_at" => nil)
-
- is_topic_search = @search_context.present? && @search_context.is_a?(Topic)
-
- posts = posts.where("topics.visible") unless is_topic_search
-
- if opts[:private_messages] || (is_topic_search && @search_context.private_message?)
- posts = posts.where("topics.archetype = ?", Archetype.private_message)
-
- unless @guardian.is_admin?
- posts = posts.private_posts_for_user(@guardian.user)
- end
+ posts = posts.joins('JOIN users u ON u.id = posts.user_id')
+ posts = posts.where("posts.raw || ' ' || u.username || ' ' || COALESCE(u.name, '') ilike ?", "%#{term_without_quote}%")
else
- posts = posts.where("topics.archetype <> ?", Archetype.private_message)
- end
-
- if @term.present?
- if is_topic_search
-
- term_without_quote = @term
- if @term =~ /"(.+)"/
- term_without_quote = $1
- end
-
- if @term =~ /'(.+)'/
- term_without_quote = $1
- end
-
- posts = posts.joins('JOIN users u ON u.id = posts.user_id')
- posts = posts.where("posts.raw || ' ' || u.username || ' ' || COALESCE(u.name, '') ilike ?", "%#{term_without_quote}%")
- else
- # A is for title
- # B is for category
- # C is for tags
- # D is for cooked
- weights = @in_title ? 'A' : (SiteSetting.tagging_enabled ? 'ABCD' : 'ABD')
- posts = posts.where("post_search_data.search_data @@ #{ts_query(weight_filter: weights)}")
- exact_terms = @term.scan(/"([^"]+)"/).flatten
- exact_terms.each do |exact|
- posts = posts.where("posts.raw ilike :exact OR topics.title ilike :exact", exact: "%#{exact}%")
- end
+ # A is for title
+ # B is for category
+ # C is for tags
+ # D is for cooked
+ weights = @in_title ? 'A' : (SiteSetting.tagging_enabled ? 'ABCD' : 'ABD')
+ posts = posts.where("post_search_data.search_data @@ #{ts_query(weight_filter: weights)}")
+ exact_terms = @term.scan(/"([^"]+)"/).flatten
+ exact_terms.each do |exact|
+ posts = posts.where("posts.raw ilike :exact OR topics.title ilike :exact", exact: "%#{exact}%")
end
end
+ end
- @filters.each do |block, match|
- if block.arity == 1
- posts = instance_exec(posts, &block) || posts
- else
- posts = instance_exec(posts, match, &block) || posts
- end
- end if @filters
-
- # If we have a search context, prioritize those posts first
- if @search_context.present?
-
- if @search_context.is_a?(User)
-
- if opts[:private_messages]
- posts = posts.private_posts_for_user(@search_context)
- else
- posts = posts.where("posts.user_id = #{@search_context.id}")
- end
-
- elsif @search_context.is_a?(Category)
- category_ids = [@search_context.id] + Category.where(parent_category_id: @search_context.id).pluck(:id)
- posts = posts.where("topics.category_id in (?)", category_ids)
- elsif @search_context.is_a?(Topic)
- posts = posts.where("topics.id = #{@search_context.id}")
- .order("posts.post_number #{@order == :latest ? "DESC" : ""}")
- end
-
- end
-
- if @order == :latest || (@term.blank? && !@order)
- if opts[:aggregate_search]
- posts = posts.order("MAX(posts.created_at) DESC")
- else
- posts = posts.reorder("posts.created_at DESC")
- end
- elsif @order == :latest_topic
- if opts[:aggregate_search]
- posts = posts.order("MAX(topics.created_at) DESC")
- else
- posts = posts.order("topics.created_at DESC")
- end
- elsif @order == :views
- if opts[:aggregate_search]
- posts = posts.order("MAX(topics.views) DESC")
- else
- posts = posts.order("topics.views DESC")
- end
- elsif @order == :likes
- if opts[:aggregate_search]
- posts = posts.order("MAX(posts.like_count) DESC")
- else
- posts = posts.order("posts.like_count DESC")
- end
+ @filters.each do |block, match|
+ if block.arity == 1
+ posts = instance_exec(posts, &block) || posts
else
- data_ranking = "TS_RANK_CD(post_search_data.search_data, #{ts_query})"
- if opts[:aggregate_search]
- posts = posts.order("MAX(#{data_ranking}) DESC")
+ posts = instance_exec(posts, match, &block) || posts
+ end
+ end if @filters
+
+ # If we have a search context, prioritize those posts first
+ if @search_context.present?
+
+ if @search_context.is_a?(User)
+
+ if opts[:private_messages]
+ posts = posts.private_posts_for_user(@search_context)
else
- posts = posts.order("#{data_ranking} DESC")
+ posts = posts.where("posts.user_id = #{@search_context.id}")
end
- posts = posts.order("topics.bumped_at DESC")
+
+ elsif @search_context.is_a?(Category)
+ category_ids = [@search_context.id] + Category.where(parent_category_id: @search_context.id).pluck(:id)
+ posts = posts.where("topics.category_id in (?)", category_ids)
+ elsif @search_context.is_a?(Topic)
+ posts = posts.where("topics.id = #{@search_context.id}")
+ .order("posts.post_number #{@order == :latest ? "DESC" : ""}")
end
- if secure_category_ids.present?
- posts = posts.where("(categories.id IS NULL) OR (NOT categories.read_restricted) OR (categories.id IN (?))", secure_category_ids).references(:categories)
+ end
+
+ if @order == :latest || (@term.blank? && !@order)
+ if opts[:aggregate_search]
+ posts = posts.order("MAX(posts.created_at) DESC")
else
- posts = posts.where("(categories.id IS NULL) OR (NOT categories.read_restricted)").references(:categories)
+ posts = posts.reorder("posts.created_at DESC")
end
-
- posts = posts.offset(offset)
- posts.limit(limit)
- end
-
- def self.default_ts_config
- "'#{Search.ts_config}'"
- end
-
- def default_ts_config
- self.class.default_ts_config
- end
-
- def self.ts_query(term: , ts_config: nil, joiner: "&", weight_filter: nil)
-
- data = Post.exec_sql("SELECT TO_TSVECTOR(:config, :term)",
- config: 'simple',
- term: term).values[0][0]
-
- ts_config = ActiveRecord::Base.connection.quote(ts_config) if ts_config
- all_terms = data.scan(/'([^']+)'\:\d+/).flatten
- all_terms.map! do |t|
- t.split(/[\)\(&']/)[0]
- end.compact!
-
- query = ActiveRecord::Base.connection.quote(
- all_terms
- .map { |t| "'#{PG::Connection.escape_string(t)}':*#{weight_filter}" }
- .join(" #{joiner} ")
- )
-
- "TO_TSQUERY(#{ts_config || default_ts_config}, #{query})"
- end
-
- def ts_query(ts_config = nil, weight_filter: nil)
- @ts_query_cache ||= {}
- @ts_query_cache["#{ts_config || default_ts_config} #{@term} #{weight_filter}"] ||=
- Search.ts_query(term: @term, ts_config: ts_config, weight_filter: weight_filter)
- end
-
- def wrap_rows(query)
- "SELECT *, row_number() over() row_number FROM (#{query.to_sql}) xxx"
- end
-
- def aggregate_post_sql(opts)
- min_or_max = @order == :latest ? "max" : "min"
-
- query =
- if @order == :likes
- # likes are a pain to aggregate so skip
- posts_query(limit, private_messages: opts[:private_messages])
- .select('topics.id', "posts.post_number")
- else
- posts_query(limit, aggregate_search: true, private_messages: opts[:private_messages])
- .select('topics.id', "#{min_or_max}(posts.post_number) post_number")
- .group('topics.id')
- end
-
- min_id = Search.min_post_id
- if min_id > 0
- low_set = query.dup.where("post_search_data.post_id < #{min_id}")
- high_set = query.where("post_search_data.post_id >= #{min_id}")
-
- return { default: wrap_rows(high_set), remaining: wrap_rows(low_set) }
- end
-
- # double wrapping so we get correct row numbers
- { default: wrap_rows(query) }
- end
-
- def aggregate_posts(post_sql)
- return [] unless post_sql
-
- posts_eager_loads(Post)
- .joins("JOIN (#{post_sql}) x ON x.id = posts.topic_id AND x.post_number = posts.post_number")
- .order('row_number')
- end
-
- def aggregate_search(opts = {})
- post_sql = aggregate_post_sql(opts)
-
- added = 0
-
- aggregate_posts(post_sql[:default]).each do |p|
- @results.add(p)
- added += 1
- end
-
- if added < limit
- aggregate_posts(post_sql[:remaining]).each { |p| @results.add(p) }
- end
- end
-
- def private_messages_search
- raise Discourse::InvalidAccess.new("anonymous can not search PMs") unless @guardian.user
-
- aggregate_search(private_messages: true)
- end
-
- def topic_search
- if @search_context.is_a?(Topic)
- posts = posts_eager_loads(posts_query(limit))
- .where('posts.topic_id = ?', @search_context.id)
-
- posts.each do |post|
- @results.add(post)
- end
+ elsif @order == :latest_topic
+ if opts[:aggregate_search]
+ posts = posts.order("MAX(topics.created_at) DESC")
else
- aggregate_search
+ posts = posts.order("topics.created_at DESC")
end
+ elsif @order == :views
+ if opts[:aggregate_search]
+ posts = posts.order("MAX(topics.views) DESC")
+ else
+ posts = posts.order("topics.views DESC")
+ end
+ elsif @order == :likes
+ if opts[:aggregate_search]
+ posts = posts.order("MAX(posts.like_count) DESC")
+ else
+ posts = posts.order("posts.like_count DESC")
+ end
+ else
+ data_ranking = "TS_RANK_CD(post_search_data.search_data, #{ts_query})"
+ if opts[:aggregate_search]
+ posts = posts.order("MAX(#{data_ranking}) DESC")
+ else
+ posts = posts.order("#{data_ranking} DESC")
+ end
+ posts = posts.order("topics.bumped_at DESC")
end
- def posts_eager_loads(query)
- query = query.includes(:user)
- topic_eager_loads = [:category]
+ if secure_category_ids.present?
+ posts = posts.where("(categories.id IS NULL) OR (NOT categories.read_restricted) OR (categories.id IN (?))", secure_category_ids).references(:categories)
+ else
+ posts = posts.where("(categories.id IS NULL) OR (NOT categories.read_restricted)").references(:categories)
+ end
- if SiteSetting.tagging_enabled
- topic_eager_loads << :tags
+ posts = posts.offset(offset)
+ posts.limit(limit)
+ end
+
+ def self.default_ts_config
+ "'#{Search.ts_config}'"
+ end
+
+ def default_ts_config
+ self.class.default_ts_config
+ end
+
+ def self.ts_query(term: , ts_config: nil, joiner: "&", weight_filter: nil)
+
+ data = Post.exec_sql("SELECT TO_TSVECTOR(:config, :term)",
+ config: 'simple',
+ term: term).values[0][0]
+
+ ts_config = ActiveRecord::Base.connection.quote(ts_config) if ts_config
+ all_terms = data.scan(/'([^']+)'\:\d+/).flatten
+ all_terms.map! do |t|
+ t.split(/[\)\(&']/)[0]
+ end.compact!
+
+ query = ActiveRecord::Base.connection.quote(
+ all_terms
+ .map { |t| "'#{PG::Connection.escape_string(t)}':*#{weight_filter}" }
+ .join(" #{joiner} ")
+ )
+
+ "TO_TSQUERY(#{ts_config || default_ts_config}, #{query})"
+ end
+
+ def ts_query(ts_config = nil, weight_filter: nil)
+ @ts_query_cache ||= {}
+ @ts_query_cache["#{ts_config || default_ts_config} #{@term} #{weight_filter}"] ||=
+ Search.ts_query(term: @term, ts_config: ts_config, weight_filter: weight_filter)
+ end
+
+ def wrap_rows(query)
+ "SELECT *, row_number() over() row_number FROM (#{query.to_sql}) xxx"
+ end
+
+ def aggregate_post_sql(opts)
+ min_or_max = @order == :latest ? "max" : "min"
+
+ query =
+ if @order == :likes
+ # likes are a pain to aggregate so skip
+ posts_query(limit, private_messages: opts[:private_messages])
+ .select('topics.id', "posts.post_number")
+ else
+ posts_query(limit, aggregate_search: true, private_messages: opts[:private_messages])
+ .select('topics.id', "#{min_or_max}(posts.post_number) post_number")
+ .group('topics.id')
end
- query.includes(topic: topic_eager_loads)
+ min_id = Search.min_post_id
+ if min_id > 0
+ low_set = query.dup.where("post_search_data.post_id < #{min_id}")
+ high_set = query.where("post_search_data.post_id >= #{min_id}")
+
+ return { default: wrap_rows(high_set), remaining: wrap_rows(low_set) }
end
+ # double wrapping so we get correct row numbers
+ { default: wrap_rows(query) }
+ end
+
+ def aggregate_posts(post_sql)
+ return [] unless post_sql
+
+ posts_eager_loads(Post)
+ .joins("JOIN (#{post_sql}) x ON x.id = posts.topic_id AND x.post_number = posts.post_number")
+ .order('row_number')
+ end
+
+ def aggregate_search(opts = {})
+ post_sql = aggregate_post_sql(opts)
+
+ added = 0
+
+ aggregate_posts(post_sql[:default]).each do |p|
+ @results.add(p)
+ added += 1
+ end
+
+ if added < limit
+ aggregate_posts(post_sql[:remaining]).each { |p| @results.add(p) }
+ end
+ end
+
+ def private_messages_search
+ raise Discourse::InvalidAccess.new("anonymous can not search PMs") unless @guardian.user
+
+ aggregate_search(private_messages: true)
+ end
+
+ def topic_search
+ if @search_context.is_a?(Topic)
+ posts = posts_eager_loads(posts_query(limit))
+ .where('posts.topic_id = ?', @search_context.id)
+
+ posts.each do |post|
+ @results.add(post)
+ end
+ else
+ aggregate_search
+ end
+ end
+
+ def posts_eager_loads(query)
+ query = query.includes(:user)
+ topic_eager_loads = [:category]
+
+ if SiteSetting.tagging_enabled
+ topic_eager_loads << :tags
+ end
+
+ query.includes(topic: topic_eager_loads)
+ end
+
end
diff --git a/lib/topic_query.rb b/lib/topic_query.rb
index 563eedf67a0..ad73a7848fd 100644
--- a/lib/topic_query.rb
+++ b/lib/topic_query.rb
@@ -423,147 +423,147 @@ class TopicQuery
protected
- def per_page_setting
- @options[:slow_platform] ? 15 : 30
- end
+ def per_page_setting
+ @options[:slow_platform] ? 15 : 30
+ end
- def private_messages_for(user, type)
- options = @options
- options.reverse_merge!(per_page: per_page_setting)
+ def private_messages_for(user, type)
+ options = @options
+ options.reverse_merge!(per_page: per_page_setting)
- result = Topic.includes(:tags)
+ result = Topic.includes(:tags)
- if type == :group
- result = result.includes(:allowed_users)
- result = result.where("
- topics.id IN (
- SELECT topic_id FROM topic_allowed_groups
- WHERE (
- group_id IN (
- SELECT group_id
- FROM group_users
- WHERE user_id = #{user.id.to_i}
- OR #{user.staff?}
- )
- )
- AND group_id IN (SELECT id FROM groups WHERE name ilike ?)
- )",
- @options[:group_name]
- )
- elsif type == :user
- result = result.includes(:allowed_users)
- result = result.where("topics.id IN (SELECT topic_id FROM topic_allowed_users WHERE user_id = #{user.id.to_i})")
- elsif type == :all
- result = result.includes(:allowed_users)
- result = result.where("topics.id IN (
- SELECT topic_id
- FROM topic_allowed_users
+ if type == :group
+ result = result.includes(:allowed_users)
+ result = result.where("
+ topics.id IN (
+ SELECT topic_id FROM topic_allowed_groups
+ WHERE (
+ group_id IN (
+ SELECT group_id
+ FROM group_users
WHERE user_id = #{user.id.to_i}
- UNION ALL
- SELECT topic_id FROM topic_allowed_groups
- WHERE group_id IN (
- SELECT group_id FROM group_users WHERE user_id = #{user.id.to_i}
- )
- )")
- end
-
- result = result.joins("LEFT OUTER JOIN topic_users AS tu ON (topics.id = tu.topic_id AND tu.user_id = #{user.id.to_i})")
- .order("topics.bumped_at DESC")
- .private_messages
-
- result = result.limit(options[:per_page]) unless options[:limit] == false
- result = result.visible if options[:visible] || @user.nil? || @user.regular?
-
- if options[:page]
- offset = options[:page].to_i * options[:per_page]
- result = result.offset(offset) if offset > 0
- end
- result
+ OR #{user.staff?}
+ )
+ )
+ AND group_id IN (SELECT id FROM groups WHERE name ilike ?)
+ )",
+ @options[:group_name]
+ )
+ elsif type == :user
+ result = result.includes(:allowed_users)
+ result = result.where("topics.id IN (SELECT topic_id FROM topic_allowed_users WHERE user_id = #{user.id.to_i})")
+ elsif type == :all
+ result = result.includes(:allowed_users)
+ result = result.where("topics.id IN (
+ SELECT topic_id
+ FROM topic_allowed_users
+ WHERE user_id = #{user.id.to_i}
+ UNION ALL
+ SELECT topic_id FROM topic_allowed_groups
+ WHERE group_id IN (
+ SELECT group_id FROM group_users WHERE user_id = #{user.id.to_i}
+ )
+ )")
end
- def apply_shared_drafts(result, category_id, options)
- drafts_category_id = SiteSetting.shared_drafts_category.to_i
- viewing_shared = category_id && category_id == drafts_category_id
+ result = result.joins("LEFT OUTER JOIN topic_users AS tu ON (topics.id = tu.topic_id AND tu.user_id = #{user.id.to_i})")
+ .order("topics.bumped_at DESC")
+ .private_messages
- if guardian.can_create_shared_draft?
- if options[:destination_category_id]
- destination_category_id = get_category_id(options[:destination_category_id])
- topic_ids = SharedDraft.where(category_id: destination_category_id).pluck(:topic_id)
- return result.where(id: topic_ids)
- elsif viewing_shared
- result = result.includes(:shared_draft).references(:shared_draft)
- else
- return result.where('topics.category_id != ?', drafts_category_id)
- end
+ result = result.limit(options[:per_page]) unless options[:limit] == false
+ result = result.visible if options[:visible] || @user.nil? || @user.regular?
+
+ if options[:page]
+ offset = options[:page].to_i * options[:per_page]
+ result = result.offset(offset) if offset > 0
+ end
+ result
+ end
+
+ def apply_shared_drafts(result, category_id, options)
+ drafts_category_id = SiteSetting.shared_drafts_category.to_i
+ viewing_shared = category_id && category_id == drafts_category_id
+
+ if guardian.can_create_shared_draft?
+ if options[:destination_category_id]
+ destination_category_id = get_category_id(options[:destination_category_id])
+ topic_ids = SharedDraft.where(category_id: destination_category_id).pluck(:topic_id)
+ return result.where(id: topic_ids)
+ elsif viewing_shared
+ result = result.includes(:shared_draft).references(:shared_draft)
+ else
+ return result.where('topics.category_id != ?', drafts_category_id)
end
-
- result
end
- def apply_ordering(result, options)
- sort_column = SORTABLE_MAPPING[options[:order]] || 'default'
- sort_dir = (options[:ascending] == "true") ? "ASC" : "DESC"
+ result
+ end
- # If we are sorting in the default order desc, we should consider including pinned
- # topics. Otherwise, just use bumped_at.
- if sort_column == 'default'
- if sort_dir == 'DESC'
- # If something requires a custom order, for example "unread" which sorts the least read
- # to the top, do nothing
- return result if options[:unordered]
- end
- sort_column = 'bumped_at'
+ def apply_ordering(result, options)
+ sort_column = SORTABLE_MAPPING[options[:order]] || 'default'
+ sort_dir = (options[:ascending] == "true") ? "ASC" : "DESC"
+
+ # If we are sorting in the default order desc, we should consider including pinned
+ # topics. Otherwise, just use bumped_at.
+ if sort_column == 'default'
+ if sort_dir == 'DESC'
+ # If something requires a custom order, for example "unread" which sorts the least read
+ # to the top, do nothing
+ return result if options[:unordered]
end
-
- # If we are sorting by category, actually use the name
- if sort_column == 'category_id'
- # TODO forces a table scan, slow
- return result.references(:categories).order(TopicQuerySQL.order_by_category_sql(sort_dir))
- end
-
- if sort_column == 'op_likes'
- return result.includes(:first_post).order("(SELECT like_count FROM posts p3 WHERE p3.topic_id = topics.id AND p3.post_number = 1) #{sort_dir}")
- end
-
- if sort_column.start_with?('custom_fields')
- field = sort_column.split('.')[1]
- return result.order("(SELECT CASE WHEN EXISTS (SELECT true FROM topic_custom_fields tcf WHERE tcf.topic_id::integer = topics.id::integer AND tcf.name = '#{field}') THEN (SELECT value::integer FROM topic_custom_fields tcf WHERE tcf.topic_id::integer = topics.id::integer AND tcf.name = '#{field}') ELSE 0 END) #{sort_dir}")
- end
-
- result.order("topics.#{sort_column} #{sort_dir}")
+ sort_column = 'bumped_at'
end
- def get_category_id(category_id_or_slug)
- return nil unless category_id_or_slug
- category_id = category_id_or_slug.to_i
- category_id = Category.where(slug: category_id_or_slug).pluck(:id).first if category_id == 0
- category_id
+ # If we are sorting by category, actually use the name
+ if sort_column == 'category_id'
+ # TODO forces a table scan, slow
+ return result.references(:categories).order(TopicQuerySQL.order_by_category_sql(sort_dir))
end
- # Create results based on a bunch of default options
- def default_results(options = {})
- options.reverse_merge!(@options)
- options.reverse_merge!(per_page: per_page_setting)
+ if sort_column == 'op_likes'
+ return result.includes(:first_post).order("(SELECT like_count FROM posts p3 WHERE p3.topic_id = topics.id AND p3.post_number = 1) #{sort_dir}")
+ end
- # Whether to return visible topics
- options[:visible] = true if @user.nil? || @user.regular?
- options[:visible] = false if @user && @user.id == options[:filtered_to_user]
+ if sort_column.start_with?('custom_fields')
+ field = sort_column.split('.')[1]
+ return result.order("(SELECT CASE WHEN EXISTS (SELECT true FROM topic_custom_fields tcf WHERE tcf.topic_id::integer = topics.id::integer AND tcf.name = '#{field}') THEN (SELECT value::integer FROM topic_custom_fields tcf WHERE tcf.topic_id::integer = topics.id::integer AND tcf.name = '#{field}') ELSE 0 END) #{sort_dir}")
+ end
- # Start with a list of all topics
- result = Topic.unscoped
+ result.order("topics.#{sort_column} #{sort_dir}")
+ end
- if @user
- result = result.joins("LEFT OUTER JOIN topic_users AS tu ON (topics.id = tu.topic_id AND tu.user_id = #{@user.id.to_i})")
- .references('tu')
- end
+ def get_category_id(category_id_or_slug)
+ return nil unless category_id_or_slug
+ category_id = category_id_or_slug.to_i
+ category_id = Category.where(slug: category_id_or_slug).pluck(:id).first if category_id == 0
+ category_id
+ end
- category_id = get_category_id(options[:category])
- @options[:category_id] = category_id
- if category_id
- if options[:no_subcategories]
- result = result.where('categories.id = ?', category_id)
- else
- sql = <<~SQL
+ # Create results based on a bunch of default options
+ def default_results(options = {})
+ options.reverse_merge!(@options)
+ options.reverse_merge!(per_page: per_page_setting)
+
+ # Whether to return visible topics
+ options[:visible] = true if @user.nil? || @user.regular?
+ options[:visible] = false if @user && @user.id == options[:filtered_to_user]
+
+ # Start with a list of all topics
+ result = Topic.unscoped
+
+ if @user
+ result = result.joins("LEFT OUTER JOIN topic_users AS tu ON (topics.id = tu.topic_id AND tu.user_id = #{@user.id.to_i})")
+ .references('tu')
+ end
+
+ category_id = get_category_id(options[:category])
+ @options[:category_id] = category_id
+ if category_id
+ if options[:no_subcategories]
+ result = result.where('categories.id = ?', category_id)
+ else
+ sql = <<~SQL
categories.id IN (
SELECT c2.id FROM categories c2 WHERE c2.parent_category_id = :category_id
UNION ALL
@@ -573,356 +573,356 @@ class TopicQuery
SELECT c3.topic_id FROM categories c3 WHERE c3.parent_category_id = :category_id
)
SQL
- result = result.where(sql, category_id: category_id)
- end
- result = result.references(:categories)
+ result = result.where(sql, category_id: category_id)
+ end
+ result = result.references(:categories)
- if !@options[:order]
- # category default sort order
- sort_order, sort_ascending = Category.where(id: category_id).pluck(:sort_order, :sort_ascending).first
- if sort_order
- options[:order] = sort_order
- options[:ascending] = !!sort_ascending ? 'true' : 'false'
- end
+ if !@options[:order]
+ # category default sort order
+ sort_order, sort_ascending = Category.where(id: category_id).pluck(:sort_order, :sort_ascending).first
+ if sort_order
+ options[:order] = sort_order
+ options[:ascending] = !!sort_ascending ? 'true' : 'false'
end
end
+ end
- # ALL TAGS: something like this?
- # Topic.joins(:tags).where('tags.name in (?)', @options[:tags]).group('topic_id').having('count(*)=?', @options[:tags].size).select('topic_id')
+ # ALL TAGS: something like this?
+ # Topic.joins(:tags).where('tags.name in (?)', @options[:tags]).group('topic_id').having('count(*)=?', @options[:tags].size).select('topic_id')
- if SiteSetting.tagging_enabled
- result = result.preload(:tags)
+ if SiteSetting.tagging_enabled
+ result = result.preload(:tags)
- if @options[:tags] && @options[:tags].size > 0
+ if @options[:tags] && @options[:tags].size > 0
- if @options[:match_all_tags]
- # ALL of the given tags:
- tags_count = @options[:tags].length
- @options[:tags] = Tag.where(name: @options[:tags]).pluck(:id) unless @options[:tags][0].is_a?(Integer)
+ if @options[:match_all_tags]
+ # ALL of the given tags:
+ tags_count = @options[:tags].length
+ @options[:tags] = Tag.where(name: @options[:tags]).pluck(:id) unless @options[:tags][0].is_a?(Integer)
- if tags_count == @options[:tags].length
- @options[:tags].each_with_index do |tag, index|
- sql_alias = ['t', index].join
- result = result.joins("INNER JOIN topic_tags #{sql_alias} ON #{sql_alias}.topic_id = topics.id AND #{sql_alias}.tag_id = #{tag}")
- end
- else
- result = result.none # don't return any results unless all tags exist in the database
+ if tags_count == @options[:tags].length
+ @options[:tags].each_with_index do |tag, index|
+ sql_alias = ['t', index].join
+ result = result.joins("INNER JOIN topic_tags #{sql_alias} ON #{sql_alias}.topic_id = topics.id AND #{sql_alias}.tag_id = #{tag}")
end
else
- # ANY of the given tags:
- result = result.joins(:tags)
- if @options[:tags][0].is_a?(Integer)
- result = result.where("tags.id in (?)", @options[:tags])
- else
- result = result.where("tags.name in (?)", @options[:tags])
- end
+ result = result.none # don't return any results unless all tags exist in the database
end
- elsif @options[:no_tags]
- # the following will do: ("topics"."id" NOT IN (SELECT DISTINCT "topic_tags"."topic_id" FROM "topic_tags"))
- result = result.where.not(id: TopicTag.distinct.pluck(:topic_id))
- end
- end
-
- result = apply_ordering(result, options)
- result = result.listable_topics.includes(:category)
- result = apply_shared_drafts(result, category_id, options)
-
- if options[:exclude_category_ids] && options[:exclude_category_ids].is_a?(Array) && options[:exclude_category_ids].size > 0
- result = result.where("categories.id NOT IN (?)", options[:exclude_category_ids]).references(:categories)
- end
-
- # Don't include the category topics if excluded
- if options[:no_definitions]
- result = result.where('COALESCE(categories.topic_id, 0) <> topics.id')
- end
-
- result = result.limit(options[:per_page]) unless options[:limit] == false
- result = result.visible if options[:visible]
- result = result.where.not(topics: { id: options[:except_topic_ids] }).references(:topics) if options[:except_topic_ids]
-
- if options[:page]
- offset = options[:page].to_i * options[:per_page]
- result = result.offset(offset) if offset > 0
- end
-
- if options[:topic_ids]
- result = result.where('topics.id in (?)', options[:topic_ids]).references(:topics)
- end
-
- if search = options[:search]
- result = result.where("topics.id in (select pp.topic_id from post_search_data pd join posts pp on pp.id = pd.post_id where pd.search_data @@ #{Search.ts_query(term: search.to_s)})")
- end
-
- # NOTE protect against SYM attack can be removed with Ruby 2.2
- #
- state = options[:state]
- if @user && state &&
- TopicUser.notification_levels.keys.map(&:to_s).include?(state)
- level = TopicUser.notification_levels[state.to_sym]
- result = result.where('topics.id IN (
- SELECT topic_id
- FROM topic_users
- WHERE user_id = ? AND
- notification_level = ?)', @user.id, level)
- end
-
- require_deleted_clause = true
-
- if before = options[:before]
- if (before = before.to_i) > 0
- result = result.where('topics.created_at < ?', before.to_i.days.ago)
- end
- end
-
- if bumped_before = options[:bumped_before]
- if (bumped_before = bumped_before.to_i) > 0
- result = result.where('topics.bumped_at < ?', bumped_before.to_i.days.ago)
- end
- end
-
- if status = options[:status]
- case status
- when 'open'
- result = result.where('NOT topics.closed AND NOT topics.archived')
- when 'closed'
- result = result.where('topics.closed')
- when 'archived'
- result = result.where('topics.archived')
- when 'listed'
- result = result.where('topics.visible')
- when 'unlisted'
- result = result.where('NOT topics.visible')
- when 'deleted'
- guardian = @guardian
- if guardian.is_staff?
- result = result.where('topics.deleted_at IS NOT NULL')
- require_deleted_clause = false
+ else
+ # ANY of the given tags:
+ result = result.joins(:tags)
+ if @options[:tags][0].is_a?(Integer)
+ result = result.where("tags.id in (?)", @options[:tags])
+ else
+ result = result.where("tags.name in (?)", @options[:tags])
end
end
+ elsif @options[:no_tags]
+ # the following will do: ("topics"."id" NOT IN (SELECT DISTINCT "topic_tags"."topic_id" FROM "topic_tags"))
+ result = result.where.not(id: TopicTag.distinct.pluck(:topic_id))
end
-
- if (filter = options[:filter]) && @user
- action =
- if filter == "bookmarked"
- PostActionType.types[:bookmark]
- elsif filter == "liked"
- PostActionType.types[:like]
- end
- if action
- result = result.where('topics.id IN (SELECT pp.topic_id
- FROM post_actions pa
- JOIN posts pp ON pp.id = pa.post_id
- WHERE pa.user_id = :user_id AND
- pa.post_action_type_id = :action AND
- pa.deleted_at IS NULL
- )', user_id: @user.id,
- action: action
- )
- end
- end
-
- result = result.where('topics.deleted_at IS NULL') if require_deleted_clause
- result = result.where('topics.posts_count <= ?', options[:max_posts]) if options[:max_posts].present?
- result = result.where('topics.posts_count >= ?', options[:min_posts]) if options[:min_posts].present?
-
- result = TopicQuery.apply_custom_filters(result, self)
-
- @guardian.filter_allowed_categories(result)
end
- def remove_muted_topics(list, user)
- if user
- list = list.where('COALESCE(tu.notification_level,1) > :muted', muted: TopicUser.notification_levels[:muted])
- end
+ result = apply_ordering(result, options)
+ result = result.listable_topics.includes(:category)
+ result = apply_shared_drafts(result, category_id, options)
+ if options[:exclude_category_ids] && options[:exclude_category_ids].is_a?(Array) && options[:exclude_category_ids].size > 0
+ result = result.where("categories.id NOT IN (?)", options[:exclude_category_ids]).references(:categories)
+ end
+
+ # Don't include the category topics if excluded
+ if options[:no_definitions]
+ result = result.where('COALESCE(categories.topic_id, 0) <> topics.id')
+ end
+
+ result = result.limit(options[:per_page]) unless options[:limit] == false
+ result = result.visible if options[:visible]
+ result = result.where.not(topics: { id: options[:except_topic_ids] }).references(:topics) if options[:except_topic_ids]
+
+ if options[:page]
+ offset = options[:page].to_i * options[:per_page]
+ result = result.offset(offset) if offset > 0
+ end
+
+ if options[:topic_ids]
+ result = result.where('topics.id in (?)', options[:topic_ids]).references(:topics)
+ end
+
+ if search = options[:search]
+ result = result.where("topics.id in (select pp.topic_id from post_search_data pd join posts pp on pp.id = pd.post_id where pd.search_data @@ #{Search.ts_query(term: search.to_s)})")
+ end
+
+ # NOTE protect against SYM attack can be removed with Ruby 2.2
+ #
+ state = options[:state]
+ if @user && state &&
+ TopicUser.notification_levels.keys.map(&:to_s).include?(state)
+ level = TopicUser.notification_levels[state.to_sym]
+ result = result.where('topics.id IN (
+ SELECT topic_id
+ FROM topic_users
+ WHERE user_id = ? AND
+ notification_level = ?)', @user.id, level)
+ end
+
+ require_deleted_clause = true
+
+ if before = options[:before]
+ if (before = before.to_i) > 0
+ result = result.where('topics.created_at < ?', before.to_i.days.ago)
+ end
+ end
+
+ if bumped_before = options[:bumped_before]
+ if (bumped_before = bumped_before.to_i) > 0
+ result = result.where('topics.bumped_at < ?', bumped_before.to_i.days.ago)
+ end
+ end
+
+ if status = options[:status]
+ case status
+ when 'open'
+ result = result.where('NOT topics.closed AND NOT topics.archived')
+ when 'closed'
+ result = result.where('topics.closed')
+ when 'archived'
+ result = result.where('topics.archived')
+ when 'listed'
+ result = result.where('topics.visible')
+ when 'unlisted'
+ result = result.where('NOT topics.visible')
+ when 'deleted'
+ guardian = @guardian
+ if guardian.is_staff?
+ result = result.where('topics.deleted_at IS NOT NULL')
+ require_deleted_clause = false
+ end
+ end
+ end
+
+ if (filter = options[:filter]) && @user
+ action =
+ if filter == "bookmarked"
+ PostActionType.types[:bookmark]
+ elsif filter == "liked"
+ PostActionType.types[:like]
+ end
+ if action
+ result = result.where('topics.id IN (SELECT pp.topic_id
+ FROM post_actions pa
+ JOIN posts pp ON pp.id = pa.post_id
+ WHERE pa.user_id = :user_id AND
+ pa.post_action_type_id = :action AND
+ pa.deleted_at IS NULL
+ )', user_id: @user.id,
+ action: action
+ )
+ end
+ end
+
+ result = result.where('topics.deleted_at IS NULL') if require_deleted_clause
+ result = result.where('topics.posts_count <= ?', options[:max_posts]) if options[:max_posts].present?
+ result = result.where('topics.posts_count >= ?', options[:min_posts]) if options[:min_posts].present?
+
+ result = TopicQuery.apply_custom_filters(result, self)
+
+ @guardian.filter_allowed_categories(result)
+ end
+
+ def remove_muted_topics(list, user)
+ if user
+ list = list.where('COALESCE(tu.notification_level,1) > :muted', muted: TopicUser.notification_levels[:muted])
+ end
+
+ list
+ end
+ def remove_muted_categories(list, user, opts = nil)
+ category_id = get_category_id(opts[:exclude]) if opts
+
+ if user
+ list = list.references("cu")
+ .where("
+ NOT EXISTS (
+ SELECT 1
+ FROM category_users cu
+ WHERE cu.user_id = :user_id
+ AND cu.category_id = topics.category_id
+ AND cu.notification_level = :muted
+ AND cu.category_id <> :category_id
+ AND (tu.notification_level IS NULL OR tu.notification_level < :tracking)
+ )", user_id: user.id,
+ muted: CategoryUser.notification_levels[:muted],
+ tracking: TopicUser.notification_levels[:tracking],
+ category_id: category_id || -1)
+ end
+
+ list
+ end
+ def remove_muted_tags(list, user, opts = nil)
+ if user.nil? || !SiteSetting.tagging_enabled || !SiteSetting.remove_muted_tags_from_latest
list
- end
- def remove_muted_categories(list, user, opts = nil)
- category_id = get_category_id(opts[:exclude]) if opts
-
- if user
- list = list.references("cu")
- .where("
- NOT EXISTS (
- SELECT 1
- FROM category_users cu
- WHERE cu.user_id = :user_id
- AND cu.category_id = topics.category_id
- AND cu.notification_level = :muted
- AND cu.category_id <> :category_id
- AND (tu.notification_level IS NULL OR tu.notification_level < :tracking)
- )", user_id: user.id,
- muted: CategoryUser.notification_levels[:muted],
- tracking: TopicUser.notification_levels[:tracking],
- category_id: category_id || -1)
- end
-
- list
- end
- def remove_muted_tags(list, user, opts = nil)
- if user.nil? || !SiteSetting.tagging_enabled || !SiteSetting.remove_muted_tags_from_latest
+ else
+ if !TagUser.lookup(user, :muted).exists?
list
else
- if !TagUser.lookup(user, :muted).exists?
- list
+ showing_tag = if opts[:filter]
+ f = opts[:filter].split('/')
+ f[0] == 'tags' ? f[1] : nil
else
- showing_tag = if opts[:filter]
- f = opts[:filter].split('/')
- f[0] == 'tags' ? f[1] : nil
- else
- nil
- end
+ nil
+ end
- if TagUser.lookup(user, :muted).joins(:tag).where('tags.name = ?', showing_tag).exists?
- list # if viewing the topic list for a muted tag, show all the topics
- else
- muted_tag_ids = TagUser.lookup(user, :muted).pluck(:tag_id)
- list = list.where("
- EXISTS (
- SELECT 1
- FROM topic_tags tt
- WHERE tt.tag_id NOT IN (:tag_ids)
- AND tt.topic_id = topics.id
- ) OR NOT EXISTS (SELECT 1 FROM topic_tags tt WHERE tt.topic_id = topics.id)", tag_ids: muted_tag_ids)
- end
+ if TagUser.lookup(user, :muted).joins(:tag).where('tags.name = ?', showing_tag).exists?
+ list # if viewing the topic list for a muted tag, show all the topics
+ else
+ muted_tag_ids = TagUser.lookup(user, :muted).pluck(:tag_id)
+ list = list.where("
+ EXISTS (
+ SELECT 1
+ FROM topic_tags tt
+ WHERE tt.tag_id NOT IN (:tag_ids)
+ AND tt.topic_id = topics.id
+ ) OR NOT EXISTS (SELECT 1 FROM topic_tags tt WHERE tt.topic_id = topics.id)", tag_ids: muted_tag_ids)
end
end
end
+ end
- def new_messages(params)
- TopicQuery.new_filter(messages_for_groups_or_user(params[:my_group_ids]), Time.at(SiteSetting.min_new_topics_time).to_datetime)
- .limit(params[:count])
- end
+ def new_messages(params)
+ TopicQuery.new_filter(messages_for_groups_or_user(params[:my_group_ids]), Time.at(SiteSetting.min_new_topics_time).to_datetime)
+ .limit(params[:count])
+ end
- def unread_messages(params)
- TopicQuery.unread_filter(
- messages_for_groups_or_user(params[:my_group_ids]),
- @user&.id,
- staff: @user&.staff?)
- .limit(params[:count])
- end
+ def unread_messages(params)
+ TopicQuery.unread_filter(
+ messages_for_groups_or_user(params[:my_group_ids]),
+ @user&.id,
+ staff: @user&.staff?)
+ .limit(params[:count])
+ end
- def related_messages_user(params)
- messages = messages_for_user.limit(params[:count])
- messages = allowed_messages(messages, params)
- end
+ def related_messages_user(params)
+ messages = messages_for_user.limit(params[:count])
+ messages = allowed_messages(messages, params)
+ end
- def related_messages_group(params)
- messages = messages_for_groups_or_user(params[:my_group_ids]).limit(params[:count])
- messages = allowed_messages(messages, params)
- end
+ def related_messages_group(params)
+ messages = messages_for_groups_or_user(params[:my_group_ids]).limit(params[:count])
+ messages = allowed_messages(messages, params)
+ end
- def allowed_messages(messages, params)
- user_ids = (params[:target_user_ids] || [])
- group_ids = ((params[:target_group_ids] - params[:my_group_ids]) || [])
-
- if user_ids.present?
- messages =
- messages.joins("
- LEFT JOIN topic_allowed_users ta2
- ON topics.id = ta2.topic_id
- AND ta2.user_id IN (#{sanitize_sql_array(user_ids)})
- ")
- end
-
- if group_ids.present?
- messages =
- messages.joins("
- LEFT JOIN topic_allowed_groups tg2
- ON topics.id = tg2.topic_id
- AND tg2.group_id IN (#{sanitize_sql_array(group_ids)})
- ")
- end
+ def allowed_messages(messages, params)
+ user_ids = (params[:target_user_ids] || [])
+ group_ids = ((params[:target_group_ids] - params[:my_group_ids]) || [])
+ if user_ids.present?
messages =
- if user_ids.present? && group_ids.present?
- messages.where("ta2.topic_id IS NOT NULL OR tg2.topic_id IS NOT NULL")
- elsif user_ids.present?
- messages.where("ta2.topic_id IS NOT NULL")
- elsif group_ids.present?
- messages.where("tg2.topic_id IS NOT NULL")
- end
+ messages.joins("
+ LEFT JOIN topic_allowed_users ta2
+ ON topics.id = ta2.topic_id
+ AND ta2.user_id IN (#{sanitize_sql_array(user_ids)})
+ ")
end
- def messages_for_groups_or_user(group_ids)
- if group_ids.present?
- base_messages
- .joins("
- LEFT JOIN (
- SELECT * FROM topic_allowed_groups _tg
- LEFT JOIN group_users gu
- ON gu.user_id = #{@user.id.to_i}
- AND gu.group_id = _tg.group_id
- WHERE gu.group_id IN (#{sanitize_sql_array(group_ids)})
- ) tg ON topics.id = tg.topic_id
- ")
- .where("tg.topic_id IS NOT NULL")
- else
- messages_for_user
+ if group_ids.present?
+ messages =
+ messages.joins("
+ LEFT JOIN topic_allowed_groups tg2
+ ON topics.id = tg2.topic_id
+ AND tg2.group_id IN (#{sanitize_sql_array(group_ids)})
+ ")
+ end
+
+ messages =
+ if user_ids.present? && group_ids.present?
+ messages.where("ta2.topic_id IS NOT NULL OR tg2.topic_id IS NOT NULL")
+ elsif user_ids.present?
+ messages.where("ta2.topic_id IS NOT NULL")
+ elsif group_ids.present?
+ messages.where("tg2.topic_id IS NOT NULL")
end
- end
+ end
- def messages_for_user
+ def messages_for_groups_or_user(group_ids)
+ if group_ids.present?
base_messages
.joins("
- LEFT JOIN topic_allowed_users ta
- ON topics.id = ta.topic_id
- AND ta.user_id = #{@user.id.to_i}
+ LEFT JOIN (
+ SELECT * FROM topic_allowed_groups _tg
+ LEFT JOIN group_users gu
+ ON gu.user_id = #{@user.id.to_i}
+ AND gu.group_id = _tg.group_id
+ WHERE gu.group_id IN (#{sanitize_sql_array(group_ids)})
+ ) tg ON topics.id = tg.topic_id
")
- .where("ta.topic_id IS NOT NULL")
+ .where("tg.topic_id IS NOT NULL")
+ else
+ messages_for_user
+ end
+ end
+
+ def messages_for_user
+ base_messages
+ .joins("
+ LEFT JOIN topic_allowed_users ta
+ ON topics.id = ta.topic_id
+ AND ta.user_id = #{@user.id.to_i}
+ ")
+ .where("ta.topic_id IS NOT NULL")
+ end
+
+ def base_messages
+ query = Topic
+ .where('topics.archetype = ?', Archetype.private_message)
+ .joins("LEFT JOIN topic_users tu ON topics.id = tu.topic_id AND tu.user_id = #{@user.id.to_i}")
+
+ query = query.includes(:tags) if SiteSetting.tagging_enabled
+ query.order('topics.bumped_at DESC')
+ end
+
+ def random_suggested(topic, count, excluded_topic_ids = [])
+ result = default_results(unordered: true, per_page: count).where(closed: false, archived: false)
+
+ if SiteSetting.limit_suggested_to_category
+ excluded_topic_ids += Category.where(id: topic.category_id).pluck(:id)
+ else
+ excluded_topic_ids += Category.topic_ids.to_a
+ end
+ result = result.where("topics.id NOT IN (?)", excluded_topic_ids) unless excluded_topic_ids.empty?
+
+ result = remove_muted_categories(result, @user)
+
+ # If we are in a category, prefer it for the random results
+ if topic.category_id
+ result = result.order("CASE WHEN topics.category_id = #{topic.category_id.to_i} THEN 0 ELSE 1 END")
end
- def base_messages
- query = Topic
- .where('topics.archetype = ?', Archetype.private_message)
- .joins("LEFT JOIN topic_users tu ON topics.id = tu.topic_id AND tu.user_id = #{@user.id.to_i}")
+ # Best effort, it over selects, however if you have a high number
+ # of muted categories there is tiny chance we will not select enough
+ # in particular this can happen if current category is empty and tons
+ # of muted, big edge case
+ #
+ # we over select in case cache is stale
+ max = (count * 1.3).to_i
+ ids = SiteSetting.limit_suggested_to_category ? [] : RandomTopicSelector.next(max)
+ ids.concat(RandomTopicSelector.next(max, topic.category))
- query = query.includes(:tags) if SiteSetting.tagging_enabled
- query.order('topics.bumped_at DESC')
+ result.where(id: ids.uniq)
+ end
+
+ def suggested_ordering(result, options)
+ # Prefer unread in the same category
+ if options[:topic] && options[:topic].category_id
+ result = result.order("CASE WHEN topics.category_id = #{options[:topic].category_id.to_i} THEN 0 ELSE 1 END")
end
- def random_suggested(topic, count, excluded_topic_ids = [])
- result = default_results(unordered: true, per_page: count).where(closed: false, archived: false)
-
- if SiteSetting.limit_suggested_to_category
- excluded_topic_ids += Category.where(id: topic.category_id).pluck(:id)
- else
- excluded_topic_ids += Category.topic_ids.to_a
- end
- result = result.where("topics.id NOT IN (?)", excluded_topic_ids) unless excluded_topic_ids.empty?
-
- result = remove_muted_categories(result, @user)
-
- # If we are in a category, prefer it for the random results
- if topic.category_id
- result = result.order("CASE WHEN topics.category_id = #{topic.category_id.to_i} THEN 0 ELSE 1 END")
- end
-
- # Best effort, it over selects, however if you have a high number
- # of muted categories there is tiny chance we will not select enough
- # in particular this can happen if current category is empty and tons
- # of muted, big edge case
- #
- # we over select in case cache is stale
- max = (count * 1.3).to_i
- ids = SiteSetting.limit_suggested_to_category ? [] : RandomTopicSelector.next(max)
- ids.concat(RandomTopicSelector.next(max, topic.category))
-
- result.where(id: ids.uniq)
- end
-
- def suggested_ordering(result, options)
- # Prefer unread in the same category
- if options[:topic] && options[:topic].category_id
- result = result.order("CASE WHEN topics.category_id = #{options[:topic].category_id.to_i} THEN 0 ELSE 1 END")
- end
-
- result.order('topics.bumped_at DESC')
- end
+ result.order('topics.bumped_at DESC')
+ end
private
- def sanitize_sql_array(input)
- ActiveRecord::Base.send(:sanitize_sql_array, input.join(','))
- end
+ def sanitize_sql_array(input)
+ ActiveRecord::Base.send(:sanitize_sql_array, input.join(','))
+ end
end
diff --git a/lib/topic_retriever.rb b/lib/topic_retriever.rb
index 82f815d9f7c..1addac713f5 100644
--- a/lib/topic_retriever.rb
+++ b/lib/topic_retriever.rb
@@ -12,48 +12,48 @@ class TopicRetriever
private
- def invalid_url?
- !EmbeddableHost.url_allowed?(@embed_url)
+ def invalid_url?
+ !EmbeddableHost.url_allowed?(@embed_url)
+ end
+
+ def retrieved_recently?
+ # We can disable the throttle for some users, such as staff
+ return false if @opts[:no_throttle]
+
+ # Throttle other users to once every 60 seconds
+ retrieved_key = "retrieved_topic"
+ if $redis.setnx(retrieved_key, "1")
+ $redis.expire(retrieved_key, 60)
+ return false
end
- def retrieved_recently?
- # We can disable the throttle for some users, such as staff
- return false if @opts[:no_throttle]
+ true
+ end
- # Throttle other users to once every 60 seconds
- retrieved_key = "retrieved_topic"
- if $redis.setnx(retrieved_key, "1")
- $redis.expire(retrieved_key, 60)
- return false
- end
+ def perform_retrieve
+ # It's possible another process or job found the embed already. So if that happened bail out.
+ return if TopicEmbed.where(embed_url: @embed_url).exists?
- true
- end
-
- def perform_retrieve
- # It's possible another process or job found the embed already. So if that happened bail out.
+ # First check RSS if that is enabled
+ if SiteSetting.feed_polling_enabled?
+ Jobs::PollFeed.new.execute({})
return if TopicEmbed.where(embed_url: @embed_url).exists?
-
- # First check RSS if that is enabled
- if SiteSetting.feed_polling_enabled?
- Jobs::PollFeed.new.execute({})
- return if TopicEmbed.where(embed_url: @embed_url).exists?
- end
-
- fetch_http
end
- def fetch_http
- if @author_username.nil?
- username = SiteSetting.embed_by_username.downcase
- else
- username = @author_username
- end
+ fetch_http
+ end
- user = User.where(username_lower: username.downcase).first
- return if user.blank?
-
- TopicEmbed.import_remote(user, @embed_url)
+ def fetch_http
+ if @author_username.nil?
+ username = SiteSetting.embed_by_username.downcase
+ else
+ username = @author_username
end
+ user = User.where(username_lower: username.downcase).first
+ return if user.blank?
+
+ TopicEmbed.import_remote(user, @embed_url)
+ end
+
end
diff --git a/lib/topics_bulk_action.rb b/lib/topics_bulk_action.rb
index 2d16fb5c219..b0b5e91b7a9 100644
--- a/lib/topics_bulk_action.rb
+++ b/lib/topics_bulk_action.rb
@@ -27,156 +27,156 @@ class TopicsBulkAction
private
- def find_group
- return unless @options[:group]
+ def find_group
+ return unless @options[:group]
- group = Group.where('name ilike ?', @options[:group]).first
- raise Discourse::InvalidParameters.new(:group) unless group
- unless group.group_users.where(user_id: @user.id).exists?
- raise Discourse::InvalidParameters.new(:group)
- end
- group
+ group = Group.where('name ilike ?', @options[:group]).first
+ raise Discourse::InvalidParameters.new(:group) unless group
+ unless group.group_users.where(user_id: @user.id).exists?
+ raise Discourse::InvalidParameters.new(:group)
end
+ group
+ end
- def move_messages_to_inbox
- group = find_group
- topics.each do |t|
- if guardian.can_see?(t) && t.private_message?
- if group
- GroupArchivedMessage.move_to_inbox!(group.id, t)
- else
- UserArchivedMessage.move_to_inbox!(@user.id, t)
- end
+ def move_messages_to_inbox
+ group = find_group
+ topics.each do |t|
+ if guardian.can_see?(t) && t.private_message?
+ if group
+ GroupArchivedMessage.move_to_inbox!(group.id, t)
+ else
+ UserArchivedMessage.move_to_inbox!(@user.id, t)
end
end
end
+ end
- def archive_messages
- group = find_group
- topics.each do |t|
- if guardian.can_see?(t) && t.private_message?
- if group
- GroupArchivedMessage.archive!(group.id, t)
- else
- UserArchivedMessage.archive!(@user.id, t)
- end
+ def archive_messages
+ group = find_group
+ topics.each do |t|
+ if guardian.can_see?(t) && t.private_message?
+ if group
+ GroupArchivedMessage.archive!(group.id, t)
+ else
+ UserArchivedMessage.archive!(@user.id, t)
end
end
end
+ end
- def dismiss_posts
- sql = "
- UPDATE topic_users tu
- SET highest_seen_post_number = t.highest_post_number , last_read_post_number = highest_post_number
- FROM topics t
- WHERE t.id = tu.topic_id AND tu.user_id = :user_id AND t.id IN (:topic_ids)
- "
+ def dismiss_posts
+ sql = "
+ UPDATE topic_users tu
+ SET highest_seen_post_number = t.highest_post_number , last_read_post_number = highest_post_number
+ FROM topics t
+ WHERE t.id = tu.topic_id AND tu.user_id = :user_id AND t.id IN (:topic_ids)
+ "
- Topic.exec_sql(sql, user_id: @user.id, topic_ids: @topic_ids)
- @changed_ids.concat @topic_ids
- end
+ Topic.exec_sql(sql, user_id: @user.id, topic_ids: @topic_ids)
+ @changed_ids.concat @topic_ids
+ end
- def reset_read
- PostTiming.destroy_for(@user.id, @topic_ids)
- end
+ def reset_read
+ PostTiming.destroy_for(@user.id, @topic_ids)
+ end
- def change_category
- topics.each do |t|
- if guardian.can_edit?(t)
- @changed_ids << t.id if t.change_category_to_id(@operation[:category_id])
- end
+ def change_category
+ topics.each do |t|
+ if guardian.can_edit?(t)
+ @changed_ids << t.id if t.change_category_to_id(@operation[:category_id])
end
end
+ end
- def change_notification_level
- topics.each do |t|
- if guardian.can_see?(t)
- TopicUser.change(@user, t.id, notification_level: @operation[:notification_level_id].to_i)
- @changed_ids << t.id
- end
- end
- end
-
- def close
- topics.each do |t|
- if guardian.can_moderate?(t)
- t.update_status('closed', true, @user)
- @changed_ids << t.id
- end
- end
- end
-
- def unlist
- topics.each do |t|
- if guardian.can_moderate?(t)
- t.update_status('visible', false, @user)
- @changed_ids << t.id
- end
- end
- end
-
- def relist
- topics.each do |t|
- if guardian.can_moderate?(t)
- t.update_status('visible', true, @user)
- @changed_ids << t.id
- end
- end
- end
-
- def archive
- topics.each do |t|
- if guardian.can_moderate?(t)
- t.update_status('archived', true, @user)
- @changed_ids << t.id
- end
- end
- end
-
- def delete
- topics.each do |t|
- if guardian.can_delete?(t)
- PostDestroyer.new(@user, t.ordered_posts.first).destroy
- end
- end
- end
-
- def change_tags
- tags = @operation[:tags]
- tags = DiscourseTagging.tags_for_saving(tags, guardian) if tags.present?
-
- topics.each do |t|
- if guardian.can_edit?(t)
- if tags.present?
- DiscourseTagging.tag_topic_by_names(t, guardian, tags)
- else
- t.tags = []
- end
- @changed_ids << t.id
- end
- end
- end
-
- def append_tags
- tags = @operation[:tags]
- tags = DiscourseTagging.tags_for_saving(tags, guardian) if tags.present?
-
- topics.each do |t|
- if guardian.can_edit?(t)
- if tags.present?
- DiscourseTagging.tag_topic_by_names(t, guardian, tags, append: true)
- end
+ def change_notification_level
+ topics.each do |t|
+ if guardian.can_see?(t)
+ TopicUser.change(@user, t.id, notification_level: @operation[:notification_level_id].to_i)
@changed_ids << t.id
- end
end
end
+ end
- def guardian
- @guardian ||= Guardian.new(@user)
+ def close
+ topics.each do |t|
+ if guardian.can_moderate?(t)
+ t.update_status('closed', true, @user)
+ @changed_ids << t.id
+ end
end
+ end
- def topics
- @topics ||= Topic.where(id: @topic_ids)
+ def unlist
+ topics.each do |t|
+ if guardian.can_moderate?(t)
+ t.update_status('visible', false, @user)
+ @changed_ids << t.id
+ end
end
+ end
+
+ def relist
+ topics.each do |t|
+ if guardian.can_moderate?(t)
+ t.update_status('visible', true, @user)
+ @changed_ids << t.id
+ end
+ end
+ end
+
+ def archive
+ topics.each do |t|
+ if guardian.can_moderate?(t)
+ t.update_status('archived', true, @user)
+ @changed_ids << t.id
+ end
+ end
+ end
+
+ def delete
+ topics.each do |t|
+ if guardian.can_delete?(t)
+ PostDestroyer.new(@user, t.ordered_posts.first).destroy
+ end
+ end
+ end
+
+ def change_tags
+ tags = @operation[:tags]
+ tags = DiscourseTagging.tags_for_saving(tags, guardian) if tags.present?
+
+ topics.each do |t|
+ if guardian.can_edit?(t)
+ if tags.present?
+ DiscourseTagging.tag_topic_by_names(t, guardian, tags)
+ else
+ t.tags = []
+ end
+ @changed_ids << t.id
+ end
+ end
+ end
+
+ def append_tags
+ tags = @operation[:tags]
+ tags = DiscourseTagging.tags_for_saving(tags, guardian) if tags.present?
+
+ topics.each do |t|
+ if guardian.can_edit?(t)
+ if tags.present?
+ DiscourseTagging.tag_topic_by_names(t, guardian, tags, append: true)
+ end
+ @changed_ids << t.id
+ end
+ end
+ end
+
+ def guardian
+ @guardian ||= Guardian.new(@user)
+ end
+
+ def topics
+ @topics ||= Topic.where(id: @topic_ids)
+ end
end
diff --git a/lib/validators/censored_words_validator.rb b/lib/validators/censored_words_validator.rb
index 96749c845cd..b2c70bc931b 100644
--- a/lib/validators/censored_words_validator.rb
+++ b/lib/validators/censored_words_validator.rb
@@ -10,23 +10,23 @@ class CensoredWordsValidator < ActiveModel::EachValidator
private
- def censor_words(value, regexp)
- censored_words = value.scan(regexp)
- censored_words.flatten!
- censored_words.compact!
- censored_words.map!(&:strip)
- censored_words.select!(&:present?)
- censored_words.uniq!
- censored_words
- end
+ def censor_words(value, regexp)
+ censored_words = value.scan(regexp)
+ censored_words.flatten!
+ censored_words.compact!
+ censored_words.map!(&:strip)
+ censored_words.select!(&:present?)
+ censored_words.uniq!
+ censored_words
+ end
- def join_censored_words(censored_words)
- censored_words.map!(&:downcase)
- censored_words.uniq!
- censored_words.join(", ".freeze)
- end
+ def join_censored_words(censored_words)
+ censored_words.map!(&:downcase)
+ censored_words.uniq!
+ censored_words.join(", ".freeze)
+ end
- def censored_words_regexp
- WordWatcher.word_matcher_regexp :censor
- end
+ def censored_words_regexp
+ WordWatcher.word_matcher_regexp :censor
+ end
end
diff --git a/lib/validators/pop3_polling_enabled_setting_validator.rb b/lib/validators/pop3_polling_enabled_setting_validator.rb
index d002f4eee7f..0b79dc8d889 100644
--- a/lib/validators/pop3_polling_enabled_setting_validator.rb
+++ b/lib/validators/pop3_polling_enabled_setting_validator.rb
@@ -30,15 +30,15 @@ class POP3PollingEnabledSettingValidator
private
- def authentication_works?
- @authentication_works ||= begin
- pop3 = Net::POP3.new(SiteSetting.pop3_polling_host, SiteSetting.pop3_polling_port)
- pop3.enable_ssl(OpenSSL::SSL::VERIFY_NONE) if SiteSetting.pop3_polling_ssl
- pop3.auth_only(SiteSetting.pop3_polling_username, SiteSetting.pop3_polling_password)
- rescue Net::POPAuthenticationError
- false
- else
- true
- end
+ def authentication_works?
+ @authentication_works ||= begin
+ pop3 = Net::POP3.new(SiteSetting.pop3_polling_host, SiteSetting.pop3_polling_port)
+ pop3.enable_ssl(OpenSSL::SSL::VERIFY_NONE) if SiteSetting.pop3_polling_ssl
+ pop3.auth_only(SiteSetting.pop3_polling_username, SiteSetting.pop3_polling_password)
+ rescue Net::POPAuthenticationError
+ false
+ else
+ true
end
+ end
end
diff --git a/lib/validators/topic_title_length_validator.rb b/lib/validators/topic_title_length_validator.rb
index bdee42c81c8..6e4a1d17017 100644
--- a/lib/validators/topic_title_length_validator.rb
+++ b/lib/validators/topic_title_length_validator.rb
@@ -6,17 +6,17 @@ class TopicTitleLengthValidator < ActiveModel::EachValidator
private
- def title_validator(record)
- length_range =
- if record.user.try(:admin?)
- 1..SiteSetting.max_topic_title_length
- elsif record.private_message?
- SiteSetting.private_message_title_length
- else
- SiteSetting.topic_title_length
- end
+ def title_validator(record)
+ length_range =
+ if record.user.try(:admin?)
+ 1..SiteSetting.max_topic_title_length
+ elsif record.private_message?
+ SiteSetting.private_message_title_length
+ else
+ SiteSetting.topic_title_length
+ end
- ActiveModel::Validations::LengthValidator.new(attributes: :title, in: length_range, allow_blank: true)
- end
+ ActiveModel::Validations::LengthValidator.new(attributes: :title, in: length_range, allow_blank: true)
+ end
end
diff --git a/plugins/discourse-narrative-bot/lib/discourse_narrative_bot/certificate_generator.rb b/plugins/discourse-narrative-bot/lib/discourse_narrative_bot/certificate_generator.rb
index bb1f4dbeffc..2fad2f84776 100644
--- a/plugins/discourse-narrative-bot/lib/discourse_narrative_bot/certificate_generator.rb
+++ b/plugins/discourse-narrative-bot/lib/discourse_narrative_bot/certificate_generator.rb
@@ -563,49 +563,49 @@ module DiscourseNarrativeBot
private
- def name
- @user.username.titleize
- end
+ def name
+ @user.username.titleize
+ end
- def logo_group(size, width, height)
- return unless SiteSetting.logo_small_url.present?
+ def logo_group(size, width, height)
+ return unless SiteSetting.logo_small_url.present?
- begin
- uri = URI(SiteSetting.logo_small_url)
+ begin
+ uri = URI(SiteSetting.logo_small_url)
- logo_uri =
- if uri.host.blank? || uri.scheme.blank?
- URI("#{Discourse.base_url}/#{uri.path}")
- else
- uri
- end
+ logo_uri =
+ if uri.host.blank? || uri.scheme.blank?
+ URI("#{Discourse.base_url}/#{uri.path}")
+ else
+ uri
+ end
- <<~URL
+ <<~URL
URL
- rescue URI::InvalidURIError
- ''
- end
+ rescue URI::InvalidURIError
+ ''
end
+ end
- def base64_image_link(url)
- if image = fetch_image(url)
- "xlink:href=\"data:image/png;base64,#{Base64.strict_encode64(image)}\""
- else
- ""
- end
+ def base64_image_link(url)
+ if image = fetch_image(url)
+ "xlink:href=\"data:image/png;base64,#{Base64.strict_encode64(image)}\""
+ else
+ ""
end
+ end
- def fetch_image(url)
- URI(url).open('rb', redirect: true, allow_redirections: :all).read
- rescue OpenURI::HTTPError
- # Ignore if fetching image returns a non 200 response
- end
+ def fetch_image(url)
+ URI(url).open('rb', redirect: true, allow_redirections: :all).read
+ rescue OpenURI::HTTPError
+ # Ignore if fetching image returns a non 200 response
+ end
- def avatar_url
- UrlHelper.absolute(Discourse.base_uri + @user.avatar_template.gsub('{size}', '250'))
- end
+ def avatar_url
+ UrlHelper.absolute(Discourse.base_uri + @user.avatar_template.gsub('{size}', '250'))
+ end
end
end
diff --git a/script/import_scripts/quandora/quandora_question.rb b/script/import_scripts/quandora/quandora_question.rb
index 6105ef895d5..9eb59c9e303 100644
--- a/script/import_scripts/quandora/quandora_question.rb
+++ b/script/import_scripts/quandora/quandora_question.rb
@@ -8,102 +8,102 @@ class QuandoraQuestion
@question = JSON.parse question_json
end
- def topic
- topic = {}
- topic[:id] = @question['uid']
- topic[:author_id] = @question['author']['uid']
- topic[:title] = unescape @question['title']
- topic[:raw] = unescape @question['content']
- topic[:created_at] = Time.parse @question['created']
- topic
- end
+ def topic
+ topic = {}
+ topic[:id] = @question['uid']
+ topic[:author_id] = @question['author']['uid']
+ topic[:title] = unescape @question['title']
+ topic[:raw] = unescape @question['content']
+ topic[:created_at] = Time.parse @question['created']
+ topic
+ end
- def users
- users = {}
- user = user_from_author @question['author']
- users[user[:id]] = user
- replies.each do |reply|
- user = user_from_author reply[:author]
- users[user[:id]] = user
- end
- users.values.to_a
- end
+ def users
+ users = {}
+ user = user_from_author @question['author']
+ users[user[:id]] = user
+ replies.each do |reply|
+ user = user_from_author reply[:author]
+ users[user[:id]] = user
+ end
+ users.values.to_a
+ end
- def user_from_author(author)
- email = author['email']
- email = "#{author['uid']}@noemail.com" unless email
+ def user_from_author(author)
+ email = author['email']
+ email = "#{author['uid']}@noemail.com" unless email
- user = {}
- user[:id] = author['uid']
- user[:name] = "#{author['firstName']} #{author['lastName']}"
- user[:email] = email
- user[:staged] = true
- user
- end
+ user = {}
+ user[:id] = author['uid']
+ user[:name] = "#{author['firstName']} #{author['lastName']}"
+ user[:email] = email
+ user[:staged] = true
+ user
+ end
- def replies
- posts = []
- answers = @question['answersList']
- comments = @question['comments']
- comments.each_with_index do |comment, i|
- posts << post_from_comment(comment, i, @question)
- end
- answers.each do |answer|
- posts << post_from_answer(answer)
- comments = answer['comments']
- comments.each_with_index do |comment, i|
- posts << post_from_comment(comment, i, answer)
- end
- end
- order_replies posts
- end
+ def replies
+ posts = []
+ answers = @question['answersList']
+ comments = @question['comments']
+ comments.each_with_index do |comment, i|
+ posts << post_from_comment(comment, i, @question)
+ end
+ answers.each do |answer|
+ posts << post_from_answer(answer)
+ comments = answer['comments']
+ comments.each_with_index do |comment, i|
+ posts << post_from_comment(comment, i, answer)
+ end
+ end
+ order_replies posts
+ end
- def order_replies(posts)
- posts = posts.sort_by { |p| p[:created_at] }
- posts.each_with_index do |p, i|
- p[:post_number] = i + 2
- end
- posts.each do |p|
- parent = posts.select { |pp| pp[:id] == p[:parent_id] }
- p[:reply_to_post_number] = parent[0][:post_number] if parent.size > 0
- end
- posts
- end
+ def order_replies(posts)
+ posts = posts.sort_by { |p| p[:created_at] }
+ posts.each_with_index do |p, i|
+ p[:post_number] = i + 2
+ end
+ posts.each do |p|
+ parent = posts.select { |pp| pp[:id] == p[:parent_id] }
+ p[:reply_to_post_number] = parent[0][:post_number] if parent.size > 0
+ end
+ posts
+ end
- def post_from_answer(answer)
- post = {}
- post[:id] = answer['uid']
- post[:parent_id] = @question['uid']
- post[:author] = answer['author']
- post[:author_id] = answer['author']['uid']
- post[:raw] = unescape answer['content']
- post[:created_at] = Time.parse answer['created']
- post
- end
+ def post_from_answer(answer)
+ post = {}
+ post[:id] = answer['uid']
+ post[:parent_id] = @question['uid']
+ post[:author] = answer['author']
+ post[:author_id] = answer['author']['uid']
+ post[:raw] = unescape answer['content']
+ post[:created_at] = Time.parse answer['created']
+ post
+ end
- def post_from_comment(comment, index, parent)
- if comment['created']
- created_at = Time.parse comment['created']
- else
- created_at = Time.parse parent['created']
- end
- parent_id = parent['uid']
- parent_id = "#{parent['uid']}-#{index - 1}" if index > 0
- post = {}
- id = "#{parent['uid']}-#{index}"
- post[:id] = id
- post[:parent_id] = parent_id
- post[:author] = comment['author']
- post[:author_id] = comment['author']['uid']
- post[:raw] = unescape comment['text']
- post[:created_at] = created_at
- post
- end
+ def post_from_comment(comment, index, parent)
+ if comment['created']
+ created_at = Time.parse comment['created']
+ else
+ created_at = Time.parse parent['created']
+ end
+ parent_id = parent['uid']
+ parent_id = "#{parent['uid']}-#{index - 1}" if index > 0
+ post = {}
+ id = "#{parent['uid']}-#{index}"
+ post[:id] = id
+ post[:parent_id] = parent_id
+ post[:author] = comment['author']
+ post[:author_id] = comment['author']['uid']
+ post[:raw] = unescape comment['text']
+ post[:created_at] = created_at
+ post
+ end
private
- def unescape(html)
- return nil unless html
- CGI.unescapeHTML html
- end
+ def unescape(html)
+ return nil unless html
+ CGI.unescapeHTML html
+ end
end
diff --git a/script/import_scripts/socialcast/socialcast_message.rb b/script/import_scripts/socialcast/socialcast_message.rb
index a82149f2ab1..e121c5695d0 100644
--- a/script/import_scripts/socialcast/socialcast_message.rb
+++ b/script/import_scripts/socialcast/socialcast_message.rb
@@ -18,81 +18,81 @@ class SocialcastMessage
}
}
- def initialize(message_json)
- @parsed_json = JSON.parse message_json
- end
+ def initialize(message_json)
+ @parsed_json = JSON.parse message_json
+ end
- def topic
- topic = {}
- topic[:id] = @parsed_json['id']
- topic[:author_id] = @parsed_json['user']['id']
- topic[:title] = title
- topic[:raw] = @parsed_json['body']
- topic[:created_at] = Time.parse @parsed_json['created_at']
- topic[:tags] = tags
- topic[:category] = category
- topic
- end
+ def topic
+ topic = {}
+ topic[:id] = @parsed_json['id']
+ topic[:author_id] = @parsed_json['user']['id']
+ topic[:title] = title
+ topic[:raw] = @parsed_json['body']
+ topic[:created_at] = Time.parse @parsed_json['created_at']
+ topic[:tags] = tags
+ topic[:category] = category
+ topic
+ end
- def title
- CreateTitle.from_body @parsed_json['body']
- end
+ def title
+ CreateTitle.from_body @parsed_json['body']
+ end
- def tags
- tags = []
- if group
- if TAGS_AND_CATEGORIES[group]
- tags = TAGS_AND_CATEGORIES[group][:tags]
- else
- tags << group
- end
- end
- tags << DEFAULT_TAG
- tags
- end
+ def tags
+ tags = []
+ if group
+ if TAGS_AND_CATEGORIES[group]
+ tags = TAGS_AND_CATEGORIES[group][:tags]
+ else
+ tags << group
+ end
+ end
+ tags << DEFAULT_TAG
+ tags
+ end
- def category
- category = DEFAULT_CATEGORY
- if group && TAGS_AND_CATEGORIES[group]
- category = TAGS_AND_CATEGORIES[group][:category]
- end
- category
- end
+ def category
+ category = DEFAULT_CATEGORY
+ if group && TAGS_AND_CATEGORIES[group]
+ category = TAGS_AND_CATEGORIES[group][:category]
+ end
+ category
+ end
- def group
- @parsed_json['group']['groupname'].downcase if @parsed_json['group'] && @parsed_json['group']['groupname']
- end
+ def group
+ @parsed_json['group']['groupname'].downcase if @parsed_json['group'] && @parsed_json['group']['groupname']
+ end
- def url
- @parsed_json['url']
- end
+ def url
+ @parsed_json['url']
+ end
- def message_type
- @parsed_json['message_type']
- end
+ def message_type
+ @parsed_json['message_type']
+ end
- def replies
- posts = []
- comments = @parsed_json['comments']
- comments.each do |comment|
- posts << post_from_comment(comment)
- end
- posts
- end
+ def replies
+ posts = []
+ comments = @parsed_json['comments']
+ comments.each do |comment|
+ posts << post_from_comment(comment)
+ end
+ posts
+ end
- def post_from_comment(comment)
- post = {}
- post[:id] = comment['id']
- post[:author_id] = comment['user']['id']
- post[:raw] = comment['text']
- post[:created_at] = Time.parse comment['created_at']
- post
- end
+ def post_from_comment(comment)
+ post = {}
+ post[:id] = comment['id']
+ post[:author_id] = comment['user']['id']
+ post[:raw] = comment['text']
+ post[:created_at] = Time.parse comment['created_at']
+ post
+ end
- private
+ private
- def unescape(html)
- return nil unless html
- CGI.unescapeHTML html
- end
+ def unescape(html)
+ return nil unless html
+ CGI.unescapeHTML html
+ end
end
diff --git a/script/import_scripts/socialcast/socialcast_user.rb b/script/import_scripts/socialcast/socialcast_user.rb
index 54107b46363..fb4217318c7 100644
--- a/script/import_scripts/socialcast/socialcast_user.rb
+++ b/script/import_scripts/socialcast/socialcast_user.rb
@@ -8,17 +8,17 @@ class SocialcastUser
@parsed_json = JSON.parse user_json
end
- def user
- email = @parsed_json['contact_info']['email']
- email = "#{@parsed_json['id']}@noemail.com" unless email
+ def user
+ email = @parsed_json['contact_info']['email']
+ email = "#{@parsed_json['id']}@noemail.com" unless email
- user = {}
- user[:id] = @parsed_json['id']
- user[:name] = @parsed_json['name']
- user[:username] = @parsed_json['username']
- user[:email] = email
- user[:staged] = true
- user
- end
+ user = {}
+ user[:id] = @parsed_json['id']
+ user[:name] = @parsed_json['name']
+ user[:username] = @parsed_json['username']
+ user[:email] = email
+ user[:staged] = true
+ user
+ end
end
diff --git a/script/import_scripts/vanilla.rb b/script/import_scripts/vanilla.rb
index 94712905599..0a9b057eec2 100644
--- a/script/import_scripts/vanilla.rb
+++ b/script/import_scripts/vanilla.rb
@@ -28,226 +28,226 @@ class ImportScripts::Vanilla < ImportScripts::Base
private
- def check_file_exist
- raise ArgumentError.new("File does not exist: #{@vanilla_file}") unless File.exist?(@vanilla_file)
- end
+ def check_file_exist
+ raise ArgumentError.new("File does not exist: #{@vanilla_file}") unless File.exist?(@vanilla_file)
+ end
- def parse_file
- puts "parsing file..."
- file = read_file
+ def parse_file
+ puts "parsing file..."
+ file = read_file
- # TODO: parse header & validate version number
- header = file.readline
+ # TODO: parse header & validate version number
+ header = file.readline
- until file.eof?
- line = file.readline
- next if line.blank?
- next if line.start_with?("//")
+ until file.eof?
+ line = file.readline
+ next if line.blank?
+ next if line.start_with?("//")
- if m = /^Table: (\w+)/.match(line)
- # extract table name
- table = m[1].underscore.pluralize
- # read the data until an empty line
- data = []
- # first line is the table definition, turn that into a proper csv header
- data << file.readline.split(",").map { |c| c.split(":")[0].underscore }.join(",")
- until (line = file.readline).blank?
- data << line.strip
- end
- # PERF: don't parse useless tables
- useless_tables = ["user_meta"]
- useless_tables << "activities" unless @use_lastest_activity_as_user_bio
- next if useless_tables.include?(table)
- # parse the data
- puts "parsing #{table}..."
- parsed_data = CSV.parse(data.join("\n"), headers: true, header_converters: :symbol).map { |row| row.to_hash }
- instance_variable_set("@#{table}".to_sym, parsed_data)
+ if m = /^Table: (\w+)/.match(line)
+ # extract table name
+ table = m[1].underscore.pluralize
+ # read the data until an empty line
+ data = []
+ # first line is the table definition, turn that into a proper csv header
+ data << file.readline.split(",").map { |c| c.split(":")[0].underscore }.join(",")
+ until (line = file.readline).blank?
+ data << line.strip
end
+ # PERF: don't parse useless tables
+ useless_tables = ["user_meta"]
+ useless_tables << "activities" unless @use_lastest_activity_as_user_bio
+ next if useless_tables.include?(table)
+ # parse the data
+ puts "parsing #{table}..."
+ parsed_data = CSV.parse(data.join("\n"), headers: true, header_converters: :symbol).map { |row| row.to_hash }
+ instance_variable_set("@#{table}".to_sym, parsed_data)
end
end
+ end
- def read_file
- puts "reading file..."
- string = File.read(@vanilla_file).gsub("\\N", "")
- .gsub(/\\$\n/m, "\\n")
- .gsub("\\,", ",")
- .gsub(/(? 0
- puts "", "importing first-level categories..."
- create_categories(first_level_categories) { |category| import_category(category) }
-
- # adds other categories
- second_level_categories = @categories.select { |c| c[:parent_category_id] != "-1" }
- if second_level_categories.count > 0
- puts "", "importing second-level categories..."
- create_categories(second_level_categories) { |category| import_category(category) }
- end
- end
- end
-
- def import_category(category)
- c = {
- id: category[:category_id],
- name: category[:name],
- user_id: user_id_from_imported_user_id(category[:insert_user_id]) || Discourse::SYSTEM_USER_ID,
- position: category[:sort].to_i,
- created_at: parse_category_date(category[:date_inserted]),
- description: clean_up(category[:description]),
+ u = {
+ id: user[:user_id],
+ email: user[:email],
+ username: user[:name],
+ created_at: parse_date(user[:date_inserted]),
+ bio_raw: clean_up(bio_raw),
+ avatar_url: user[:photo],
+ moderator: @user_roles.select { |ur| ur[:user_id] == user[:user_id] }.map { |ur| ur[:role_id] }.include?(moderator_role_id),
+ admin: @user_roles.select { |ur| ur[:user_id] == user[:user_id] }.map { |ur| ur[:role_id] }.include?(admin_role_id),
}
- if category[:parent_category_id] != "-1"
- c[:parent_category_id] = category_id_from_imported_category_id(category[:parent_category_id])
- end
- c
+
+ u
end
+ end
- def parse_category_date(date)
- date == "0000-00-00 00:00:00" ? @root_category_created_at : parse_date(date)
- end
+ def import_categories
+ puts "", "importing categories..."
- def import_topics
- puts "", "importing topics..."
+ # save some information about the root category
+ @root_category = @categories.select { |c| c[:category_id] == "-1" }.first
+ @root_category_created_at = parse_date(@root_category[:date_inserted])
- create_posts(@discussions) do |discussion|
- {
- id: "discussion#" + discussion[:discussion_id],
- user_id: user_id_from_imported_user_id(discussion[:insert_user_id]) || Discourse::SYSTEM_USER_ID,
- title: discussion[:name],
- category: category_id_from_imported_category_id(discussion[:category_id]),
- raw: clean_up(discussion[:body]),
- created_at: parse_date(discussion[:date_inserted]),
- }
+ # removes root category
+ @categories.reject! { |c| c[:category_id] == "-1" }
+
+ # adds root's child categories
+ first_level_categories = @categories.select { |c| c[:parent_category_id] == "-1" }
+ if first_level_categories.count > 0
+ puts "", "importing first-level categories..."
+ create_categories(first_level_categories) { |category| import_category(category) }
+
+ # adds other categories
+ second_level_categories = @categories.select { |c| c[:parent_category_id] != "-1" }
+ if second_level_categories.count > 0
+ puts "", "importing second-level categories..."
+ create_categories(second_level_categories) { |category| import_category(category) }
end
end
+ end
- def import_posts
- puts "", "importing posts..."
-
- create_posts(@comments) do |comment|
- next unless t = topic_lookup_from_imported_post_id("discussion#" + comment[:discussion_id])
-
- {
- id: "comment#" + comment[:comment_id],
- user_id: user_id_from_imported_user_id(comment[:insert_user_id]) || Discourse::SYSTEM_USER_ID,
- topic_id: t[:topic_id],
- raw: clean_up(comment[:body]),
- created_at: parse_date(comment[:date_inserted]),
- }
- end
+ def import_category(category)
+ c = {
+ id: category[:category_id],
+ name: category[:name],
+ user_id: user_id_from_imported_user_id(category[:insert_user_id]) || Discourse::SYSTEM_USER_ID,
+ position: category[:sort].to_i,
+ created_at: parse_category_date(category[:date_inserted]),
+ description: clean_up(category[:description]),
+ }
+ if category[:parent_category_id] != "-1"
+ c[:parent_category_id] = category_id_from_imported_category_id(category[:parent_category_id])
end
+ c
+ end
- def import_private_topics
- puts "", "importing private topics..."
+ def parse_category_date(date)
+ date == "0000-00-00 00:00:00" ? @root_category_created_at : parse_date(date)
+ end
- create_posts(@conversations) do |conversation|
- next if conversation[:first_message_id].blank?
+ def import_topics
+ puts "", "importing topics..."
- # list all other user ids in the conversation
- user_ids_in_conversation = @user_conversations.select { |uc| uc[:conversation_id] == conversation[:conversation_id] && uc[:user_id] != conversation[:insert_user_id] }
- .map { |uc| uc[:user_id] }
- # retrieve their emails
- user_emails_in_conversation = @users.select { |u| user_ids_in_conversation.include?(u[:user_id]) }
- .map { |u| u[:email] }
- # retrieve their usernames from the database
- target_usernames = User.where("email IN (?)", user_emails_in_conversation).pluck(:username).to_a
-
- next if target_usernames.blank?
-
- user = find_user_by_import_id(conversation[:insert_user_id]) || Discourse.system_user
- first_message = @conversation_messages.select { |cm| cm[:message_id] == conversation[:first_message_id] }.first
-
- {
- archetype: Archetype.private_message,
- id: "conversation#" + conversation[:conversation_id],
- user_id: user.id,
- title: "Private message from #{user.username}",
- target_usernames: target_usernames,
- raw: clean_up(first_message[:body]),
- created_at: parse_date(conversation[:date_inserted]),
- }
- end
+ create_posts(@discussions) do |discussion|
+ {
+ id: "discussion#" + discussion[:discussion_id],
+ user_id: user_id_from_imported_user_id(discussion[:insert_user_id]) || Discourse::SYSTEM_USER_ID,
+ title: discussion[:name],
+ category: category_id_from_imported_category_id(discussion[:category_id]),
+ raw: clean_up(discussion[:body]),
+ created_at: parse_date(discussion[:date_inserted]),
+ }
end
+ end
- def import_private_posts
- puts "", "importing private posts..."
+ def import_posts
+ puts "", "importing posts..."
- first_message_ids = Set.new(@conversations.map { |c| c[:first_message_id] }.to_a)
- @conversation_messages.reject! { |cm| first_message_ids.include?(cm[:message_id]) }
+ create_posts(@comments) do |comment|
+ next unless t = topic_lookup_from_imported_post_id("discussion#" + comment[:discussion_id])
- create_posts(@conversation_messages) do |message|
- next unless t = topic_lookup_from_imported_post_id("conversation#" + message[:conversation_id])
-
- {
- archetype: Archetype.private_message,
- id: "message#" + message[:message_id],
- user_id: user_id_from_imported_user_id(message[:insert_user_id]) || Discourse::SYSTEM_USER_ID,
- topic_id: t[:topic_id],
- raw: clean_up(message[:body]),
- created_at: parse_date(message[:date_inserted]),
- }
- end
+ {
+ id: "comment#" + comment[:comment_id],
+ user_id: user_id_from_imported_user_id(comment[:insert_user_id]) || Discourse::SYSTEM_USER_ID,
+ topic_id: t[:topic_id],
+ raw: clean_up(comment[:body]),
+ created_at: parse_date(comment[:date_inserted]),
+ }
end
+ end
- def parse_date(date)
- DateTime.strptime(date, "%Y-%m-%d %H:%M:%S")
- end
+ def import_private_topics
+ puts "", "importing private topics..."
- def clean_up(raw)
- return "" if raw.blank?
- raw.gsub("\\n", "\n")
- .gsub(/<\/?pre\s*>/i, "\n```\n")
- .gsub(/<\/?code\s*>/i, "`")
- .gsub("<", "<")
- .gsub(">", ">")
+ create_posts(@conversations) do |conversation|
+ next if conversation[:first_message_id].blank?
+
+ # list all other user ids in the conversation
+ user_ids_in_conversation = @user_conversations.select { |uc| uc[:conversation_id] == conversation[:conversation_id] && uc[:user_id] != conversation[:insert_user_id] }
+ .map { |uc| uc[:user_id] }
+ # retrieve their emails
+ user_emails_in_conversation = @users.select { |u| user_ids_in_conversation.include?(u[:user_id]) }
+ .map { |u| u[:email] }
+ # retrieve their usernames from the database
+ target_usernames = User.where("email IN (?)", user_emails_in_conversation).pluck(:username).to_a
+
+ next if target_usernames.blank?
+
+ user = find_user_by_import_id(conversation[:insert_user_id]) || Discourse.system_user
+ first_message = @conversation_messages.select { |cm| cm[:message_id] == conversation[:first_message_id] }.first
+
+ {
+ archetype: Archetype.private_message,
+ id: "conversation#" + conversation[:conversation_id],
+ user_id: user.id,
+ title: "Private message from #{user.username}",
+ target_usernames: target_usernames,
+ raw: clean_up(first_message[:body]),
+ created_at: parse_date(conversation[:date_inserted]),
+ }
end
+ end
+
+ def import_private_posts
+ puts "", "importing private posts..."
+
+ first_message_ids = Set.new(@conversations.map { |c| c[:first_message_id] }.to_a)
+ @conversation_messages.reject! { |cm| first_message_ids.include?(cm[:message_id]) }
+
+ create_posts(@conversation_messages) do |message|
+ next unless t = topic_lookup_from_imported_post_id("conversation#" + message[:conversation_id])
+
+ {
+ archetype: Archetype.private_message,
+ id: "message#" + message[:message_id],
+ user_id: user_id_from_imported_user_id(message[:insert_user_id]) || Discourse::SYSTEM_USER_ID,
+ topic_id: t[:topic_id],
+ raw: clean_up(message[:body]),
+ created_at: parse_date(message[:date_inserted]),
+ }
+ end
+ end
+
+ def parse_date(date)
+ DateTime.strptime(date, "%Y-%m-%d %H:%M:%S")
+ end
+
+ def clean_up(raw)
+ return "" if raw.blank?
+ raw.gsub("\\n", "\n")
+ .gsub(/<\/?pre\s*>/i, "\n```\n")
+ .gsub(/<\/?code\s*>/i, "`")
+ .gsub("<", "<")
+ .gsub(">", ">")
+ end
end