diff --git a/.rubocop.yml b/.rubocop.yml index 8137b729a..429518d7a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -319,6 +319,12 @@ Style/IfUnlessModifier: # StyleGuide: '#single-line-blocks' # Enabled: false +Style/ClassAndModuleChildren: + Description: 'Checks style of children classes and modules.' + StyleGuide: '#namespace-definition' + Enabled: true + SafeAutoCorrect: true + # Style/OptionHash: # Description: "Don't use option hashes when you can use keyword arguments." # Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 50beb95f3..5594d28b2 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -37,38 +37,10 @@ Performance/OpenStruct: - 'spec/models/github_repo_spec.rb' - 'spec/requests/github_repos_spec.rb' -# Offense count: 4 -# Configuration parameters: Max. -RSpec/ExampleLength: - Exclude: - - 'spec/initializers/rack/attack_spec.rb' - - 'spec/liquid_tags/user_subscription_tag_spec.rb' - - 'spec/models/comment_spec.rb' - - 'spec/requests/display_ad_events_spec.rb' - # Offense count: 930 RSpec/MultipleExpectations: Max: 12 -# Offense count: 1 -RSpec/SubjectStub: - Exclude: - - 'spec/models/article_spec.rb' - -# Offense count: 1 -# Configuration parameters: Include. -# Include: app/models/**/*.rb -Rails/HasAndBelongsToMany: - Exclude: - - 'app/models/role.rb' - -# Offense count: 3 -# Configuration parameters: Include. -# Include: app/helpers/**/*.rb -Rails/HelperInstanceVariable: - Exclude: - - 'app/helpers/application_helper.rb' - # Offense count: 16 Rails/OutputSafety: Exclude: @@ -87,13 +59,6 @@ Rails/UniqueValidationWithoutIndex: Exclude: - 'app/models/article.rb' -# Offense count: 38 -# Cop supports --auto-correct. -# Configuration parameters: AutoCorrect, EnforcedStyle. -# SupportedStyles: nested, compact -Style/ClassAndModuleChildren: - Enabled: false - # Offense count: 3 # Configuration parameters: Methods. # Methods: {"reduce"=>["acc", "elem"]}, {"inject"=>["acc", "elem"]} diff --git a/app/controllers/api/v0/api_controller.rb b/app/controllers/api/v0/api_controller.rb index 66549f195..fd4b9ebe4 100644 --- a/app/controllers/api/v0/api_controller.rb +++ b/app/controllers/api/v0/api_controller.rb @@ -1,74 +1,78 @@ -class Api::V0::ApiController < ApplicationController - protect_from_forgery with: :exception, prepend: true +module Api + module V0 + class ApiController < ApplicationController + protect_from_forgery with: :exception, prepend: true - include ValidRequest + include ValidRequest - respond_to :json + respond_to :json - rescue_from ActionController::ParameterMissing do |exc| - error_unprocessable_entity(exc.message) - end + rescue_from ActionController::ParameterMissing do |exc| + error_unprocessable_entity(exc.message) + end - rescue_from ActiveRecord::RecordInvalid do |exc| - error_unprocessable_entity(exc.message) - end + rescue_from ActiveRecord::RecordInvalid do |exc| + error_unprocessable_entity(exc.message) + end - rescue_from ActiveRecord::RecordNotFound, with: :error_not_found + rescue_from ActiveRecord::RecordNotFound, with: :error_not_found - rescue_from Pundit::NotAuthorizedError, with: :error_unauthorized + rescue_from Pundit::NotAuthorizedError, with: :error_unauthorized - protected + protected - def error_unprocessable_entity(message) - render json: { error: message, status: 422 }, status: :unprocessable_entity - end + def error_unprocessable_entity(message) + render json: { error: message, status: 422 }, status: :unprocessable_entity + end - def error_unauthorized - render json: { error: "unauthorized", status: 401 }, status: :unauthorized - end + def error_unauthorized + render json: { error: "unauthorized", status: 401 }, status: :unauthorized + end - def error_not_found - render json: { error: "not found", status: 404 }, status: :not_found - end + def error_not_found + render json: { error: "not found", status: 404 }, status: :not_found + end - def authenticate! - if doorkeeper_token - @user = User.find(doorkeeper_token.resource_owner_id) - return error_unauthorized unless @user - elsif request.headers["api-key"] - @user = authenticate_with_api_key - return error_unauthorized unless @user - elsif current_user - @user = current_user - else - error_unauthorized + def authenticate! + if doorkeeper_token + @user = User.find(doorkeeper_token.resource_owner_id) + return error_unauthorized unless @user + elsif request.headers["api-key"] + @user = authenticate_with_api_key + return error_unauthorized unless @user + elsif current_user + @user = current_user + else + error_unauthorized + end + end + + # Checks if the user is authenticated, sets @user to nil otherwise + def authenticate_with_api_key_or_current_user + @user = authenticate_with_api_key || current_user + end + + # Checks if the user is authenticated, if so sets the variable @user + # Returns HTTP 401 Unauthorized otherwise + def authenticate_with_api_key_or_current_user! + @user = authenticate_with_api_key || current_user + error_unauthorized unless @user + end + + private + + def authenticate_with_api_key + api_key = request.headers["api-key"] + return unless api_key + + api_secret = ApiSecret.includes(:user).find_by(secret: api_key) + return unless api_secret + + # guard against timing attacks + # see + secure_secret = ActiveSupport::SecurityUtils.secure_compare(api_secret.secret, api_key) + return api_secret.user if secure_secret + end end end - - # Checks if the user is authenticated, sets @user to nil otherwise - def authenticate_with_api_key_or_current_user - @user = authenticate_with_api_key || current_user - end - - # Checks if the user is authenticated, if so sets the variable @user - # Returns HTTP 401 Unauthorized otherwise - def authenticate_with_api_key_or_current_user! - @user = authenticate_with_api_key || current_user - error_unauthorized unless @user - end - - private - - def authenticate_with_api_key - api_key = request.headers["api-key"] - return unless api_key - - api_secret = ApiSecret.includes(:user).find_by(secret: api_key) - return unless api_secret - - # guard against timing attacks - # see - secure_secret = ActiveSupport::SecurityUtils.secure_compare(api_secret.secret, api_key) - return api_secret.user if secure_secret - end end diff --git a/app/controllers/incoming_webhooks/mailchimp_unsubscribes_controller.rb b/app/controllers/incoming_webhooks/mailchimp_unsubscribes_controller.rb index 2b13c7902..04cd7ad42 100644 --- a/app/controllers/incoming_webhooks/mailchimp_unsubscribes_controller.rb +++ b/app/controllers/incoming_webhooks/mailchimp_unsubscribes_controller.rb @@ -1,36 +1,38 @@ -class IncomingWebhooks::MailchimpUnsubscribesController < ApplicationController - skip_before_action :verify_authenticity_token +module IncomingWebhooks + class MailchimpUnsubscribesController < ApplicationController + skip_before_action :verify_authenticity_token - class InvalidListID < StandardError; end + class InvalidListID < StandardError; end - LIST_MAPPINGS = { - mailchimp_newsletter_id: :email_newsletter, - mailchimp_sustaining_members_id: :email_membership_newsletter, - mailchimp_tag_moderators_id: :email_tag_mod_newsletter, - mailchimp_community_moderators_id: :email_community_mod_newsletter - }.freeze + LIST_MAPPINGS = { + mailchimp_newsletter_id: :email_newsletter, + mailchimp_sustaining_members_id: :email_membership_newsletter, + mailchimp_tag_moderators_id: :email_tag_mod_newsletter, + mailchimp_community_moderators_id: :email_community_mod_newsletter + }.freeze - def index - head :ok - end + def index + head :ok + end - def create - not_authorized unless valid_secret? - user = User.find_by!(email: params.dig(:data, :email)) - user.update(email_type => false) - end + def create + not_authorized unless valid_secret? + user = User.find_by!(email: params.dig(:data, :email)) + user.update(email_type => false) + end - private + private - def valid_secret? - params[:secret] == SiteConfig.mailchimp_incoming_webhook_secret - end + def valid_secret? + params[:secret] == SiteConfig.mailchimp_incoming_webhook_secret + end - def email_type - list_id = params.dig(:data, :list_id) - key = LIST_MAPPINGS.keys.detect { |k| SiteConfig.public_send(k) == list_id } - raise InvalidListID unless key + def email_type + list_id = params.dig(:data, :list_id) + key = LIST_MAPPINGS.keys.detect { |k| SiteConfig.public_send(k) == list_id } + raise InvalidListID unless key - LIST_MAPPINGS[key] + LIST_MAPPINGS[key] + end end end diff --git a/app/controllers/internal/application_controller.rb b/app/controllers/internal/application_controller.rb index 3dc7e944d..baa5467f6 100644 --- a/app/controllers/internal/application_controller.rb +++ b/app/controllers/internal/application_controller.rb @@ -1,45 +1,47 @@ -class Internal::ApplicationController < ApplicationController - before_action :authorize_admin - after_action :verify_authorized +module Internal + class ApplicationController < ApplicationController + before_action :authorize_admin + after_action :verify_authorized - # This is used in app/views/internal/shared/_navbar.html.erb to build the - # side navbar in alphabetical order. - MENU_ITEMS = [ - { name: "articles", controller: "articles" }, - { name: "broadcasts", controller: "broadcasts" }, - { name: "badges", controller: "badges" }, - { name: "chat_channels", controller: "chat_channels" }, - { name: "comments", controller: "comments" }, - { name: "config", controller: "config" }, - { name: "events", controller: "events" }, - { name: "growth", controller: "growth" }, - { name: "listings", controller: "listings" }, - { name: "moderator_actions", controller: "moderator_actions" }, - { name: "mods", controller: "mods" }, - { name: "privileged_reactions", controller: "privileged_reactions" }, - { name: "organizations", controller: "organizations" }, - { name: "path_redirects", controller: "path_redirects" }, - { name: "pages", controller: "pages" }, - { name: "permissions", controller: "permissions" }, - { name: "podcasts", controller: "podcasts" }, - { name: "reports", controller: "reports" }, - { name: "response_templates", controller: "response_templates" }, - { name: "sponsorships", controller: "sponsorships" }, - { name: "tags", controller: "tags" }, - { name: "tools", controller: "tools" }, - { name: "users", controller: "users" }, - { name: "vault secrets", controller: "secrets" }, - { name: "webhooks", controller: "webhook_endpoints" }, - { name: "welcome", controller: "welcome" }, - ].sort_by { |menu_item| menu_item[:name] }.freeze + # This is used in app/views/internal/shared/_navbar.html.erb to build the + # side navbar in alphabetical order. + MENU_ITEMS = [ + { name: "articles", controller: "articles" }, + { name: "broadcasts", controller: "broadcasts" }, + { name: "badges", controller: "badges" }, + { name: "chat_channels", controller: "chat_channels" }, + { name: "comments", controller: "comments" }, + { name: "config", controller: "config" }, + { name: "events", controller: "events" }, + { name: "growth", controller: "growth" }, + { name: "listings", controller: "listings" }, + { name: "moderator_actions", controller: "moderator_actions" }, + { name: "mods", controller: "mods" }, + { name: "privileged_reactions", controller: "privileged_reactions" }, + { name: "organizations", controller: "organizations" }, + { name: "path_redirects", controller: "path_redirects" }, + { name: "pages", controller: "pages" }, + { name: "permissions", controller: "permissions" }, + { name: "podcasts", controller: "podcasts" }, + { name: "reports", controller: "reports" }, + { name: "response_templates", controller: "response_templates" }, + { name: "sponsorships", controller: "sponsorships" }, + { name: "tags", controller: "tags" }, + { name: "tools", controller: "tools" }, + { name: "users", controller: "users" }, + { name: "vault secrets", controller: "secrets" }, + { name: "webhooks", controller: "webhook_endpoints" }, + { name: "welcome", controller: "welcome" }, + ].sort_by { |menu_item| menu_item[:name] }.freeze - private + private - def authorization_resource - self.class.name.demodulize.sub("Controller", "").singularize.constantize - end + def authorization_resource + self.class.name.demodulize.sub("Controller", "").singularize.constantize + end - def authorize_admin - authorize(authorization_resource, :access?, policy_class: InternalPolicy) + def authorize_admin + authorize(authorization_resource, :access?, policy_class: InternalPolicy) + end end end diff --git a/app/controllers/internal/articles_controller.rb b/app/controllers/internal/articles_controller.rb index 83faf9c5e..555d74dea 100644 --- a/app/controllers/internal/articles_controller.rb +++ b/app/controllers/internal/articles_controller.rb @@ -1,138 +1,140 @@ -class Internal::ArticlesController < Internal::ApplicationController - layout "internal" +module Internal + class ArticlesController < Internal::ApplicationController + layout "internal" - after_action only: [:update] do - Audit::Logger.log(:moderator, current_user, params.dup) - end + after_action only: [:update] do + Audit::Logger.log(:moderator, current_user, params.dup) + end - def index - @pending_buffer_updates = BufferUpdate.where(status: "pending").includes(:article) - @user_buffer_updates = BufferUpdate.where(status: "sent_direct", approver_user_id: current_user.id).where( - "created_at > ?", 24.hours.ago - ) + def index + @pending_buffer_updates = BufferUpdate.where(status: "pending").includes(:article) + @user_buffer_updates = BufferUpdate.where(status: "sent_direct", approver_user_id: current_user.id).where( + "created_at > ?", 24.hours.ago + ) - case params[:state] - when /not-buffered/ - days_ago = params[:state].split("-")[2].to_f - @articles = articles_not_buffered(days_ago) - when /top-/ - months_ago = params[:state].split("-")[1].to_i.months.ago - @articles = articles_top(months_ago) - when "satellite" - @articles = articles_satellite - when "satellite-not-bufffered" - @articles = articles_satellite.where(last_buffered: nil) - when "boosted-additional-articles" - @articles = articles_boosted_additional - when "chronological" - @articles = articles_chronological - else - @articles = articles_mixed - @featured_articles = articles_featured + case params[:state] + when /not-buffered/ + days_ago = params[:state].split("-")[2].to_f + @articles = articles_not_buffered(days_ago) + when /top-/ + months_ago = params[:state].split("-")[1].to_i.months.ago + @articles = articles_top(months_ago) + when "satellite" + @articles = articles_satellite + when "satellite-not-bufffered" + @articles = articles_satellite.where(last_buffered: nil) + when "boosted-additional-articles" + @articles = articles_boosted_additional + when "chronological" + @articles = articles_chronological + else + @articles = articles_mixed + @featured_articles = articles_featured + end + end + + def show + @article = Article.find(params[:id]) + end + + def update + article = Article.find(params[:id]) + article.featured = article_params[:featured].to_s == "true" + article.approved = article_params[:approved].to_s == "true" + article.email_digest_eligible = article_params[:email_digest_eligible].to_s == "true" + article.boosted_additional_articles = article_params[:boosted_additional_articles].to_s == "true" + article.boosted_dev_digest_email = article_params[:boosted_dev_digest_email].to_s == "true" + article.user_id = article_params[:user_id].to_i + article.update!(article_params) + render body: nil + end + + private + + def articles_not_buffered(days_ago) + Article.published. + where(last_buffered: nil). + where("published_at > ? OR crossposted_at > ?", days_ago.days.ago, days_ago.days.ago). + includes(:user). + limited_columns_internal_select. + order("public_reactions_count DESC"). + page(params[:page]). + per(50) + end + + def articles_top(months_ago) + Article.published. + where("published_at > ?", months_ago). + includes(user: [:notes]). + limited_columns_internal_select. + order("public_reactions_count DESC"). + page(params[:page]). + per(50) + end + + def articles_satellite + Article.published.where(last_buffered: nil). + includes(:user, :buffer_updates). + tagged_with(Tag.bufferized_tags, any: true). + limited_columns_internal_select. + order("hotness_score DESC"). + page(params[:page]). + per(60) + end + + def articles_boosted_additional + Article.boosted_via_additional_articles. + includes(:user, :buffer_updates). + limited_columns_internal_select. + order("published_at DESC"). + page(params[:page]). + per(100) + end + + def articles_chronological + Article.published. + includes(user: [:notes]). + limited_columns_internal_select. + order("published_at DESC"). + page(params[:page]). + per(50) + end + + def articles_mixed + Article.published. + includes(user: [:notes]). + limited_columns_internal_select. + order("hotness_score DESC"). + page(params[:page]). + per(30) + end + + def articles_featured + Article.published.or(Article.where(published_from_feed: true)). + where(featured: true). + where("featured_number > ?", Time.current.to_i). + includes(:user, :buffer_updates). + limited_columns_internal_select. + order("featured_number DESC") + end + + def article_params + allowed_params = %i[featured + social_image + body_markdown + approved + email_digest_eligible + boosted_additional_articles + boosted_dev_digest_email + main_image_background_hex_color + featured_number + user_id + last_buffered] + params.require(:article).permit(allowed_params) + end + + def authorize_admin + authorize Article, :access?, policy_class: InternalPolicy end end - - def show - @article = Article.find(params[:id]) - end - - def update - article = Article.find(params[:id]) - article.featured = article_params[:featured].to_s == "true" - article.approved = article_params[:approved].to_s == "true" - article.email_digest_eligible = article_params[:email_digest_eligible].to_s == "true" - article.boosted_additional_articles = article_params[:boosted_additional_articles].to_s == "true" - article.boosted_dev_digest_email = article_params[:boosted_dev_digest_email].to_s == "true" - article.user_id = article_params[:user_id].to_i - article.update!(article_params) - render body: nil - end - - private - - def articles_not_buffered(days_ago) - Article.published. - where(last_buffered: nil). - where("published_at > ? OR crossposted_at > ?", days_ago.days.ago, days_ago.days.ago). - includes(:user). - limited_columns_internal_select. - order("public_reactions_count DESC"). - page(params[:page]). - per(50) - end - - def articles_top(months_ago) - Article.published. - where("published_at > ?", months_ago). - includes(user: [:notes]). - limited_columns_internal_select. - order("public_reactions_count DESC"). - page(params[:page]). - per(50) - end - - def articles_satellite - Article.published.where(last_buffered: nil). - includes(:user, :buffer_updates). - tagged_with(Tag.bufferized_tags, any: true). - limited_columns_internal_select. - order("hotness_score DESC"). - page(params[:page]). - per(60) - end - - def articles_boosted_additional - Article.boosted_via_additional_articles. - includes(:user, :buffer_updates). - limited_columns_internal_select. - order("published_at DESC"). - page(params[:page]). - per(100) - end - - def articles_chronological - Article.published. - includes(user: [:notes]). - limited_columns_internal_select. - order("published_at DESC"). - page(params[:page]). - per(50) - end - - def articles_mixed - Article.published. - includes(user: [:notes]). - limited_columns_internal_select. - order("hotness_score DESC"). - page(params[:page]). - per(30) - end - - def articles_featured - Article.published.or(Article.where(published_from_feed: true)). - where(featured: true). - where("featured_number > ?", Time.current.to_i). - includes(:user, :buffer_updates). - limited_columns_internal_select. - order("featured_number DESC") - end - - def article_params - allowed_params = %i[featured - social_image - body_markdown - approved - email_digest_eligible - boosted_additional_articles - boosted_dev_digest_email - main_image_background_hex_color - featured_number - user_id - last_buffered] - params.require(:article).permit(allowed_params) - end - - def authorize_admin - authorize Article, :access?, policy_class: InternalPolicy - end end diff --git a/app/controllers/internal/badges_controller.rb b/app/controllers/internal/badges_controller.rb index 06c14c256..1e48af11e 100644 --- a/app/controllers/internal/badges_controller.rb +++ b/app/controllers/internal/badges_controller.rb @@ -1,26 +1,28 @@ -class Internal::BadgesController < Internal::ApplicationController - layout "internal" +module Internal + class BadgesController < Internal::ApplicationController + layout "internal" - def index - @badges = Badge.all - end + def index + @badges = Badge.all + end - def award_badges - raise ArgumentError, "Please choose a badge to award" if permitted_params[:badge].blank? + def award_badges + raise ArgumentError, "Please choose a badge to award" if permitted_params[:badge].blank? - usernames = permitted_params[:usernames].split(/\s*,\s*/) - message = permitted_params[:message_markdown].presence || "Congrats!" - BadgeRewarder.award_badges(usernames, permitted_params[:badge], message) - flash[:success] = "BadgeRewarder task ran!" - redirect_to internal_badges_url - rescue ArgumentError => e - flash[:danger] = e.message - redirect_to "/internal/badges" - end + usernames = permitted_params[:usernames].split(/\s*,\s*/) + message = permitted_params[:message_markdown].presence || "Congrats!" + BadgeRewarder.award_badges(usernames, permitted_params[:badge], message) + flash[:success] = "BadgeRewarder task ran!" + redirect_to internal_badges_url + rescue ArgumentError => e + flash[:danger] = e.message + redirect_to "/internal/badges" + end - private + private - def permitted_params - params.permit(:usernames, :badge, :message_markdown) + def permitted_params + params.permit(:usernames, :badge, :message_markdown) + end end end diff --git a/app/controllers/internal/broadcasts_controller.rb b/app/controllers/internal/broadcasts_controller.rb index 600217ac6..7ed1321be 100644 --- a/app/controllers/internal/broadcasts_controller.rb +++ b/app/controllers/internal/broadcasts_controller.rb @@ -1,69 +1,71 @@ -class Internal::BroadcastsController < Internal::ApplicationController - layout "internal" +module Internal + class BroadcastsController < Internal::ApplicationController + layout "internal" - def index - @broadcasts = if params[:type_of] - Broadcast.where(type_of: params[:type_of].capitalize) - else - Broadcast.all - end.order(title: :asc) - end - - def show - @broadcast = Broadcast.find(params[:id]) - end - - def new - @broadcast = Broadcast.new - end - - def edit - @broadcast = Broadcast.find(params[:id]) - end - - def create - @broadcast = Broadcast.new(broadcast_params) - - if @broadcast.save - flash[:success] = "Broadcast has been created!" - redirect_to internal_broadcast_path(@broadcast) - else - flash[:danger] = @broadcast.errors.full_messages.to_sentence - render new_internal_broadcast_path + def index + @broadcasts = if params[:type_of] + Broadcast.where(type_of: params[:type_of].capitalize) + else + Broadcast.all + end.order(title: :asc) end - end - def update - @broadcast = Broadcast.find(params[:id]) - - if @broadcast.update(broadcast_params) - flash[:success] = "Broadcast has been updated!" - redirect_to internal_broadcast_path(@broadcast) - else - flash[:danger] = @broadcast.errors.full_messages.to_sentence - render :edit + def show + @broadcast = Broadcast.find(params[:id]) end - end - def destroy - @broadcast = Broadcast.find(params[:id]) - - if @broadcast.destroy - flash[:success] = "Broadcast has been deleted!" - redirect_to internal_broadcasts_path - else - flash[:danger] = "Something went wrong with deleting the broadcast." - render :edit + def new + @broadcast = Broadcast.new end - end - private + def edit + @broadcast = Broadcast.find(params[:id]) + end - def broadcast_params - params.permit(:title, :processed_html, :type_of, :banner_style, :active) - end + def create + @broadcast = Broadcast.new(broadcast_params) - def authorize_admin - authorize Broadcast, :access?, policy_class: InternalPolicy + if @broadcast.save + flash[:success] = "Broadcast has been created!" + redirect_to internal_broadcast_path(@broadcast) + else + flash[:danger] = @broadcast.errors.full_messages.to_sentence + render new_internal_broadcast_path + end + end + + def update + @broadcast = Broadcast.find(params[:id]) + + if @broadcast.update(broadcast_params) + flash[:success] = "Broadcast has been updated!" + redirect_to internal_broadcast_path(@broadcast) + else + flash[:danger] = @broadcast.errors.full_messages.to_sentence + render :edit + end + end + + def destroy + @broadcast = Broadcast.find(params[:id]) + + if @broadcast.destroy + flash[:success] = "Broadcast has been deleted!" + redirect_to internal_broadcasts_path + else + flash[:danger] = "Something went wrong with deleting the broadcast." + render :edit + end + end + + private + + def broadcast_params + params.permit(:title, :processed_html, :type_of, :banner_style, :active) + end + + def authorize_admin + authorize Broadcast, :access?, policy_class: InternalPolicy + end end end diff --git a/app/controllers/internal/buffer_updates_controller.rb b/app/controllers/internal/buffer_updates_controller.rb index 5e946bf54..04c09dd24 100644 --- a/app/controllers/internal/buffer_updates_controller.rb +++ b/app/controllers/internal/buffer_updates_controller.rb @@ -1,36 +1,38 @@ -class Internal::BufferUpdatesController < Internal::ApplicationController - def create - article_id = params[:article_id] - article = Article.find(article_id) if article_id.present? - fb_post = params[:fb_post] - tweet = params[:tweet] - listing_id = params[:listing_id] - listing = Listing.find(params[:listing_id]) if listing_id.present? - article&.update(featured: true) - case params[:social_channel] - when "main_twitter" - Bufferizer.new("article", article, tweet, current_user.id).main_tweet! - render body: nil - when "satellite_twitter" - Bufferizer.new("article", article, tweet, current_user.id).satellite_tweet! - render body: nil - when "facebook" - Bufferizer.new("article", article, fb_post, current_user.id).facebook_post! - render body: nil - when "listings_twitter" - Bufferizer.new("listing", listing, tweet, current_user.id).listings_tweet! +module Internal + class BufferUpdatesController < Internal::ApplicationController + def create + article_id = params[:article_id] + article = Article.find(article_id) if article_id.present? + fb_post = params[:fb_post] + tweet = params[:tweet] + listing_id = params[:listing_id] + listing = Listing.find(params[:listing_id]) if listing_id.present? + article&.update(featured: true) + case params[:social_channel] + when "main_twitter" + Bufferizer.new("article", article, tweet, current_user.id).main_tweet! + render body: nil + when "satellite_twitter" + Bufferizer.new("article", article, tweet, current_user.id).satellite_tweet! + render body: nil + when "facebook" + Bufferizer.new("article", article, fb_post, current_user.id).facebook_post! + render body: nil + when "listings_twitter" + Bufferizer.new("listing", listing, tweet, current_user.id).listings_tweet! + render body: nil + end + end + + def update + BufferUpdate.upbuff!(params[:id], current_user.id, params[:body_text], params[:status]) render body: nil end - end - def update - BufferUpdate.upbuff!(params[:id], current_user.id, params[:body_text], params[:status]) - render body: nil - end + private - private - - def authorize_admin - authorize BufferUpdate, :access?, policy_class: InternalPolicy + def authorize_admin + authorize BufferUpdate, :access?, policy_class: InternalPolicy + end end end diff --git a/app/controllers/internal/chat_channels_controller.rb b/app/controllers/internal/chat_channels_controller.rb index e3131b7d7..ce8e278e8 100644 --- a/app/controllers/internal/chat_channels_controller.rb +++ b/app/controllers/internal/chat_channels_controller.rb @@ -1,35 +1,37 @@ -class Internal::ChatChannelsController < Internal::ApplicationController - layout "internal" +module Internal + class ChatChannelsController < Internal::ApplicationController + layout "internal" - def index - @q = ChatChannel.where(channel_type: "invite_only").includes(:users).ransack(params[:q]) - @group_chat_channels = @q.result.page(params[:page]).per(50) - end + def index + @q = ChatChannel.where(channel_type: "invite_only").includes(:users).ransack(params[:q]) + @group_chat_channels = @q.result.page(params[:page]).per(50) + end - def create - ChatChannel.create_with_users( - users: users_by_param, - channel_type: "invite_only", - contrived_name: chat_channel_params[:channel_name], - membership_role: "mod", - ) - redirect_back(fallback_location: "/internal/chat_channels") - end + def create + ChatChannel.create_with_users( + users: users_by_param, + channel_type: "invite_only", + contrived_name: chat_channel_params[:channel_name], + membership_role: "mod", + ) + redirect_back(fallback_location: "/internal/chat_channels") + end - def update - @chat_channel = ChatChannel.find(params[:id]) - @chat_channel.invite_users(users: users_by_param, membership_role: "mod") - redirect_back(fallback_location: "/internal/chat_channels") - end + def update + @chat_channel = ChatChannel.find(params[:id]) + @chat_channel.invite_users(users: users_by_param, membership_role: "mod") + redirect_back(fallback_location: "/internal/chat_channels") + end - private + private - def users_by_param - User.where(username: chat_channel_params[:usernames_string].downcase.delete(" ").split(",")) - end + def users_by_param + User.where(username: chat_channel_params[:usernames_string].downcase.delete(" ").split(",")) + end - def chat_channel_params - allowed_params = %i[usernames_string channel_name] - params.require(:chat_channel).permit(allowed_params) + def chat_channel_params + allowed_params = %i[usernames_string channel_name] + params.require(:chat_channel).permit(allowed_params) + end end end diff --git a/app/controllers/internal/comments_controller.rb b/app/controllers/internal/comments_controller.rb index 488535529..ececd7569 100644 --- a/app/controllers/internal/comments_controller.rb +++ b/app/controllers/internal/comments_controller.rb @@ -1,26 +1,28 @@ -class Internal::CommentsController < Internal::ApplicationController - layout "internal" +module Internal + class CommentsController < Internal::ApplicationController + layout "internal" - def index - @comments = if params[:state]&.start_with?("toplast-") - Comment. - includes(:user). - includes(:commentable). - order("public_reactions_count DESC"). - where("created_at > ?", params[:state].split("-").last.to_i.days.ago). - page(params[:page] || 1).per(50) - else - Comment. - includes(:user). - includes(:commentable). - order("created_at DESC"). - page(params[:page] || 1).per(50) - end - end + def index + @comments = if params[:state]&.start_with?("toplast-") + Comment. + includes(:user). + includes(:commentable). + order("public_reactions_count DESC"). + where("created_at > ?", params[:state].split("-").last.to_i.days.ago). + page(params[:page] || 1).per(50) + else + Comment. + includes(:user). + includes(:commentable). + order("created_at DESC"). + page(params[:page] || 1).per(50) + end + end - private + private - def authorize_admin - authorize Comment, :access?, policy_class: InternalPolicy + def authorize_admin + authorize Comment, :access?, policy_class: InternalPolicy + end end end diff --git a/app/controllers/internal/configs_controller.rb b/app/controllers/internal/configs_controller.rb index 05b2d1cce..10f10aea2 100644 --- a/app/controllers/internal/configs_controller.rb +++ b/app/controllers/internal/configs_controller.rb @@ -1,155 +1,157 @@ -class Internal::ConfigsController < Internal::ApplicationController - layout "internal" +module Internal + class ConfigsController < Internal::ApplicationController + layout "internal" - before_action :extra_authorization_and_confirmation, only: [:create] + before_action :extra_authorization_and_confirmation, only: [:create] - def create - clean_up_params + def create + clean_up_params - config_params.each do |key, value| - if value.is_a?(Array) - SiteConfig.public_send("#{key}=", value.reject(&:blank?)) unless value.empty? - elsif value.respond_to?(:to_h) - SiteConfig.public_send("#{key}=", value.to_h) unless value.empty? - else - SiteConfig.public_send("#{key}=", value.strip) unless value.nil? + config_params.each do |key, value| + if value.is_a?(Array) + SiteConfig.public_send("#{key}=", value.reject(&:blank?)) unless value.empty? + elsif value.respond_to?(:to_h) + SiteConfig.public_send("#{key}=", value.to_h) unless value.empty? + else + SiteConfig.public_send("#{key}=", value.strip) unless value.nil? + end + end + + bust_relevant_caches + redirect_to internal_config_path, notice: "Site configuration was successfully updated." + end + + private + + def config_params + allowed_params = %i[ + ga_view_id ga_fetch_rate + periodic_email_digest_max + periodic_email_digest_min + sidebar_tags + twitter_hashtag + shop_url + payment_pointer + health_check_token + feed_style + ] + + allowed_params = allowed_params | + campaign_params | + community_params | + newsletter_params | + rate_limit_params | + mascot_params | + image_params | + onboarding_params | + job_params + + has_emails = params[:site_config][:email_addresses].present? + params[:site_config][:email_addresses][:default] = ApplicationConfig["DEFAULT_EMAIL"] if has_emails + params.require(:site_config).permit( + allowed_params, + authentication_providers: [], + social_media_handles: SiteConfig.social_media_handles.keys, + email_addresses: SiteConfig.email_addresses.keys, + meta_keywords: SiteConfig.meta_keywords.keys, + ) + end + + def extra_authorization_and_confirmation + not_authorized unless current_user.has_role?(:single_resource_admin, Config) # Special additional permission + confirmation_message = "My username is @#{current_user.username} and this action is 100% safe and appropriate." + not_authorized if params[:confirmation] != confirmation_message + end + + def clean_up_params + config = params[:site_config] + %i[sidebar_tags suggested_tags suggested_users].each do |param| + config[param] = config[param].downcase.delete(" ") if config[param] end end - bust_relevant_caches - redirect_to internal_config_path, notice: "Site configuration was successfully updated." - end + def bust_relevant_caches + # Needs to change when suggested_tags is edited. + CacheBuster.bust("/tags/onboarding") + end - private + def campaign_params + %i[ + campaign_featured_tags + campaign_hero_html_variant_name + campaign_sidebar_enabled + campaign_sidebar_image + campaign_url + campaign_articles_require_approval + ] + end - def config_params - allowed_params = %i[ - ga_view_id ga_fetch_rate - periodic_email_digest_max - periodic_email_digest_min - sidebar_tags - twitter_hashtag - shop_url - payment_pointer - health_check_token - feed_style - ] + def community_params + %i[ + community_description + community_member_label + community_action + tagline + ] + end - allowed_params = allowed_params | - campaign_params | - community_params | - newsletter_params | - rate_limit_params | - mascot_params | - image_params | - onboarding_params | - job_params + def newsletter_params + %i[ + mailchimp_community_moderators_id + mailchimp_newsletter_id + mailchimp_sustaining_members_id + mailchimp_tag_moderators_id + ] + end - has_emails = params[:site_config][:email_addresses].present? - params[:site_config][:email_addresses][:default] = ApplicationConfig["DEFAULT_EMAIL"] if has_emails - params.require(:site_config).permit( - allowed_params, - authentication_providers: [], - social_media_handles: SiteConfig.social_media_handles.keys, - email_addresses: SiteConfig.email_addresses.keys, - meta_keywords: SiteConfig.meta_keywords.keys, - ) - end + def rate_limit_params + %i[ + rate_limit_comment_creation + rate_limit_email_recipient + rate_limit_follow_count_daily + rate_limit_image_upload + rate_limit_published_article_creation + rate_limit_organization_creation + rate_limit_user_subscription_creation + ] + end - def extra_authorization_and_confirmation - not_authorized unless current_user.has_role?(:single_resource_admin, Config) # Special additional permission - confirmation_message = "My username is @#{current_user.username} and this action is 100% safe and appropriate." - not_authorized if params[:confirmation] != confirmation_message - end + def mascot_params + %i[ + mascot_image_description + mascot_image_url + mascot_footer_image_url + mascot_user_id + ] + end - def clean_up_params - config = params[:site_config] - %i[sidebar_tags suggested_tags suggested_users].each do |param| - config[param] = config[param].downcase.delete(" ") if config[param] + def image_params + %i[ + favicon_url + logo_png + logo_svg + main_social_image + secondary_logo_url + left_navbar_svg_icon + right_navbar_svg_icon + ] + end + + def onboarding_params + %i[ + onboarding_logo_image + onboarding_background_image + onboarding_taskcard_image + suggested_tags + suggested_users + ] + end + + def job_params + %i[ + jobs_url + display_jobs_banner + ] end end - - def bust_relevant_caches - # Needs to change when suggested_tags is edited. - CacheBuster.bust("/tags/onboarding") - end - - def campaign_params - %i[ - campaign_featured_tags - campaign_hero_html_variant_name - campaign_sidebar_enabled - campaign_sidebar_image - campaign_url - campaign_articles_require_approval - ] - end - - def community_params - %i[ - community_description - community_member_label - community_action - tagline - ] - end - - def newsletter_params - %i[ - mailchimp_community_moderators_id - mailchimp_newsletter_id - mailchimp_sustaining_members_id - mailchimp_tag_moderators_id - ] - end - - def rate_limit_params - %i[ - rate_limit_comment_creation - rate_limit_email_recipient - rate_limit_follow_count_daily - rate_limit_image_upload - rate_limit_published_article_creation - rate_limit_organization_creation - rate_limit_user_subscription_creation - ] - end - - def mascot_params - %i[ - mascot_image_description - mascot_image_url - mascot_footer_image_url - mascot_user_id - ] - end - - def image_params - %i[ - favicon_url - logo_png - logo_svg - main_social_image - secondary_logo_url - left_navbar_svg_icon - right_navbar_svg_icon - ] - end - - def onboarding_params - %i[ - onboarding_logo_image - onboarding_background_image - onboarding_taskcard_image - suggested_tags - suggested_users - ] - end - - def job_params - %i[ - jobs_url - display_jobs_banner - ] - end end diff --git a/app/controllers/internal/feedback_messages_controller.rb b/app/controllers/internal/feedback_messages_controller.rb index 5c238cb22..8802c7363 100644 --- a/app/controllers/internal/feedback_messages_controller.rb +++ b/app/controllers/internal/feedback_messages_controller.rb @@ -1,121 +1,123 @@ -class Internal::FeedbackMessagesController < Internal::ApplicationController - layout "internal" +module Internal + class FeedbackMessagesController < Internal::ApplicationController + layout "internal" - def index - @q = FeedbackMessage.includes(:reporter, :offender, :affected). - order(created_at: :desc). - ransack(params[:q]) - @feedback_messages = @q.result.page(params[:page] || 1).per(5) + def index + @q = FeedbackMessage.includes(:reporter, :offender, :affected). + order(created_at: :desc). + ransack(params[:q]) + @feedback_messages = @q.result.page(params[:page] || 1).per(5) - @feedback_type = params[:state] || "abuse-reports" - @status = params[:status] || "Open" + @feedback_type = params[:state] || "abuse-reports" + @status = params[:status] || "Open" - @email_messages = EmailMessage.find_for_reports(@feedback_messages) - @new_articles = Article.published.select(:title, :user_id, :path).includes(:user). - order(created_at: :desc). - where("score > ? AND score < ?", -10, 8). - limit(120) + @email_messages = EmailMessage.find_for_reports(@feedback_messages) + @new_articles = Article.published.select(:title, :user_id, :path).includes(:user). + order(created_at: :desc). + where("score > ? AND score < ?", -10, 8). + limit(120) - @possible_spam_users = User.where( - "github_created_at > ? OR twitter_created_at > ? OR length(name) > ?", - 50.hours.ago, 50.hours.ago, 30 - ). - where("created_at > ?", 48.hours.ago). - order(created_at: :desc). - select(:username, :name, :id). - where.not("username LIKE ?", "%spam_%"). - limit(150) + @possible_spam_users = User.where( + "github_created_at > ? OR twitter_created_at > ? OR length(name) > ?", + 50.hours.ago, 50.hours.ago, 30 + ). + where("created_at > ?", 48.hours.ago). + order(created_at: :desc). + select(:username, :name, :id). + where.not("username LIKE ?", "%spam_%"). + limit(150) - @vomits = get_vomits - end - - def save_status - feedback_message = FeedbackMessage.find(params[:id]) - if feedback_message.update(status: params[:status]) - render json: { outcome: "Success" } - else - render json: { outcome: feedback_message.errors.full_messages } + @vomits = get_vomits end - end - def show - @feedback_message = FeedbackMessage.find_by(id: params[:id]) - @email_messages = EmailMessage.find_for_reports(@feedback_message.id) - end - - def send_email - if NotifyMailer.with(params).feedback_message_resolution_email.deliver_now - render json: { outcome: "Success" } - else - render json: { outcome: "Failure" } + def save_status + feedback_message = FeedbackMessage.find(params[:id]) + if feedback_message.update(status: params[:status]) + render json: { outcome: "Success" } + else + render json: { outcome: feedback_message.errors.full_messages } + end end - end - def create_note - note = Note.new( - noteable_id: params["noteable_id"], - noteable_type: params["noteable_type"], - author_id: params["author_id"], - content: params["content"], - reason: params["reason"], - ) + def show + @feedback_message = FeedbackMessage.find_by(id: params[:id]) + @email_messages = EmailMessage.find_for_reports(@feedback_message.id) + end - if note.save - params["author_name"] = note.author.name - params["feedback_message_status"] = note.noteable.status - params["feedback_type"] = note.noteable.feedback_type + def send_email + if NotifyMailer.with(params).feedback_message_resolution_email.deliver_now + render json: { outcome: "Success" } + else + render json: { outcome: "Failure" } + end + end - send_slack_message(params) - - render json: { - outcome: "Success", + def create_note + note = Note.new( + noteable_id: params["noteable_id"], + noteable_type: params["noteable_type"], + author_id: params["author_id"], content: params["content"], - author_name: note.author.name - } - else - render json: { outcome: note.errors.full_messages } + reason: params["reason"], + ) + + if note.save + params["author_name"] = note.author.name + params["feedback_message_status"] = note.noteable.status + params["feedback_type"] = note.noteable.feedback_type + + send_slack_message(params) + + render json: { + outcome: "Success", + content: params["content"], + author_name: note.author.name + } + else + render json: { outcome: note.errors.full_messages } + end end - end - private + private - def get_vomits - q = Reaction.includes(:user, :reactable). - select(:id, :user_id, :reactable_type, :reactable_id). - order(updated_at: :desc) - if params[:status] == "Open" || params[:status].blank? - q.where(category: "vomit", status: "valid") - elsif params[:status] == "Resolved" - q.where(category: "vomit", status: "confirmed").limit(10) - else - q.where(category: "vomit", status: "invalid").limit(10) + def get_vomits + q = Reaction.includes(:user, :reactable). + select(:id, :user_id, :reactable_type, :reactable_id). + order(updated_at: :desc) + if params[:status] == "Open" || params[:status].blank? + q.where(category: "vomit", status: "valid") + elsif params[:status] == "Resolved" + q.where(category: "vomit", status: "confirmed").limit(10) + else + q.where(category: "vomit", status: "invalid").limit(10) + end end - end - def send_slack_message(params) - Slack::Messengers::Note.call( - author_name: params[:author_name], - status: params[:feedback_message_status], - type: params[:feedback_type], - report_id: params[:noteable_id], - message: params[:content], - ) - end + def send_slack_message(params) + Slack::Messengers::Note.call( + author_name: params[:author_name], + status: params[:feedback_message_status], + type: params[:feedback_type], + report_id: params[:noteable_id], + message: params[:content], + ) + end - def generate_message(params) - <<~HEREDOC - *New note from #{params['author_name']}:* - *Report status: #{params['feedback_message_status']}* - Report page: https://#{ApplicationConfig['APP_DOMAIN']}/internal/reports/#{params['noteable_id']} - -------- - Message: #{params['content']} - HEREDOC - end + def generate_message(params) + <<~HEREDOC + *New note from #{params['author_name']}:* + *Report status: #{params['feedback_message_status']}* + Report page: https://#{ApplicationConfig['APP_DOMAIN']}/internal/reports/#{params['noteable_id']} + -------- + Message: #{params['content']} + HEREDOC + end - def feedback_message_params - params[:feedback_message].permit( - :id, :status, :reviewer_id, - note: %i[content reason noteable_id noteable_type author_id] - ) + def feedback_message_params + params[:feedback_message].permit( + :id, :status, :reviewer_id, + note: %i[content reason noteable_id noteable_type author_id] + ) + end end end diff --git a/app/controllers/internal/growth_controller.rb b/app/controllers/internal/growth_controller.rb index 5e3f9e32c..91c77297b 100644 --- a/app/controllers/internal/growth_controller.rb +++ b/app/controllers/internal/growth_controller.rb @@ -1,3 +1,5 @@ -class Internal::GrowthController < Internal::ApplicationController - layout "internal" +module Internal + class GrowthController < Internal::ApplicationController + layout "internal" + end end diff --git a/app/controllers/internal/listings_controller.rb b/app/controllers/internal/listings_controller.rb index 4df8cb2a3..ffceab32e 100644 --- a/app/controllers/internal/listings_controller.rb +++ b/app/controllers/internal/listings_controller.rb @@ -1,54 +1,56 @@ -class Internal::ListingsController < Internal::ApplicationController - include ListingsToolkit - layout "internal" +module Internal + class ListingsController < Internal::ApplicationController + include ListingsToolkit + layout "internal" - def index - @listings = - Listing.includes(%i[user listing_category]). - page(params[:page]).order("bumped_at DESC").per(50) + def index + @listings = + Listing.includes(%i[user listing_category]). + page(params[:page]).order("bumped_at DESC").per(50) - @listings = @listings.published unless include_unpublished? - @listings = @listings.in_category(params[:filter]) if params[:filter].present? - end + @listings = @listings.published unless include_unpublished? + @listings = @listings.in_category(params[:filter]) if params[:filter].present? + end - def edit - @listing = Listing.find(params[:id]) - end + def edit + @listing = Listing.find(params[:id]) + end - def update - @listing = Listing.find(params[:id]) - handle_publish_status if listing_params[:published] - bump_listing(@listing.cost) if listing_params[:action] == "bump" - update_listing_details - clear_listings_cache - flash[:success] = "Listing updated successfully" - redirect_to edit_internal_listing_path(@listing) - end + def update + @listing = Listing.find(params[:id]) + handle_publish_status if listing_params[:published] + bump_listing(@listing.cost) if listing_params[:action] == "bump" + update_listing_details + clear_listings_cache + flash[:success] = "Listing updated successfully" + redirect_to edit_internal_listing_path(@listing) + end - def destroy - @listing = Listing.find(params[:id]) - @listing.destroy - flash[:warning] = "'#{@listing.title}' was destroyed successfully" - redirect_to internal_listings_path - end + def destroy + @listing = Listing.find(params[:id]) + @listing.destroy + flash[:warning] = "'#{@listing.title}' was destroyed successfully" + redirect_to internal_listings_path + end - private + private - ALLOWED_PARAMS = %i[ - published body_markdown title category listing_category_id tag_list action - ].freeze - private_constant :ALLOWED_PARAMS + ALLOWED_PARAMS = %i[ + published body_markdown title category listing_category_id tag_list action + ].freeze + private_constant :ALLOWED_PARAMS - def listing_params - params.require(:listing).permit(ALLOWED_PARAMS) - end + def listing_params + params.require(:listing).permit(ALLOWED_PARAMS) + end - def handle_publish_status - unpublish_listing if listing_params[:published] == "0" - publish_listing if listing_params[:published] == "1" - end + def handle_publish_status + unpublish_listing if listing_params[:published] == "0" + publish_listing if listing_params[:published] == "1" + end - def include_unpublished? - params[:include_unpublished] == "1" + def include_unpublished? + params[:include_unpublished] == "1" + end end end diff --git a/app/controllers/internal/moderator_actions_controller.rb b/app/controllers/internal/moderator_actions_controller.rb index 4e3e4ef28..9bf79b663 100644 --- a/app/controllers/internal/moderator_actions_controller.rb +++ b/app/controllers/internal/moderator_actions_controller.rb @@ -1,12 +1,14 @@ -class Internal::ModeratorActionsController < Internal::ApplicationController - layout "internal" +module Internal + class ModeratorActionsController < Internal::ApplicationController + layout "internal" - def index - @q = AuditLog. - includes(:user). - where(category: "moderator.audit.log"). - order(created_at: :desc). - ransack(params[:q]) - @moderator_actions = @q.result.page(params[:page] || 1).per(25) + def index + @q = AuditLog. + includes(:user). + where(category: "moderator.audit.log"). + order(created_at: :desc). + ransack(params[:q]) + @moderator_actions = @q.result.page(params[:page] || 1).per(25) + end end end diff --git a/app/controllers/internal/mods_controller.rb b/app/controllers/internal/mods_controller.rb index 8fe75ea84..c024d95fe 100644 --- a/app/controllers/internal/mods_controller.rb +++ b/app/controllers/internal/mods_controller.rb @@ -1,33 +1,35 @@ -class Internal::ModsController < Internal::ApplicationController - layout "internal" +module Internal + class ModsController < Internal::ApplicationController + layout "internal" - INDEX_ATTRIBUTES = %i[ - id - username - comments_count - badge_achievements_count - last_comment_at - ].freeze + INDEX_ATTRIBUTES = %i[ + id + username + comments_count + badge_achievements_count + last_comment_at + ].freeze - def index - @mods = Internal::ModeratorsQuery.call( - relation: User.select(INDEX_ATTRIBUTES), - options: permitted_params, - ).page(params[:page]).per(50) - end + def index + @mods = Internal::ModeratorsQuery.call( + relation: User.select(INDEX_ATTRIBUTES), + options: permitted_params, + ).page(params[:page]).per(50) + end - def update - @user = User.find(params[:id]) + def update + @user = User.find(params[:id]) - AssignTagModerator.add_trusted_role(@user) + AssignTagModerator.add_trusted_role(@user) - redirect_to internal_mods_path(state: :potential), - flash: { success: "#{@user.username} now has Trusted role!" } - end + redirect_to internal_mods_path(state: :potential), + flash: { success: "#{@user.username} now has Trusted role!" } + end - private + private - def permitted_params - params.permit(:state, :search, :page) + def permitted_params + params.permit(:state, :search, :page) + end end end diff --git a/app/controllers/internal/organization_memberships_controller.rb b/app/controllers/internal/organization_memberships_controller.rb index 75e605a35..4c8b2d5c1 100644 --- a/app/controllers/internal/organization_memberships_controller.rb +++ b/app/controllers/internal/organization_memberships_controller.rb @@ -1,45 +1,47 @@ -class Internal::OrganizationMembershipsController < Internal::ApplicationController - layout "internal" +module Internal + class OrganizationMembershipsController < Internal::ApplicationController + layout "internal" - def update - organization_membership = OrganizationMembership.find_by(id: params[:id]) - if organization_membership.update(organization_membership_params) - flash[:success] = "User was successfully updated to #{organization_membership.type_of_user}" - else - flash[:danger] = organization_membership.errors.full_messages + def update + organization_membership = OrganizationMembership.find_by(id: params[:id]) + if organization_membership.update(organization_membership_params) + flash[:success] = "User was successfully updated to #{organization_membership.type_of_user}" + else + flash[:danger] = organization_membership.errors.full_messages + end + redirect_to internal_user_path(organization_membership.user_id) end - redirect_to internal_user_path(organization_membership.user_id) - end - def create - organization_membership = OrganizationMembership.new(organization_membership_params) - organization = Organization.find_by(id: organization_membership_params[:organization_id]) - if organization && organization_membership.save - flash[:success] = "User was successfully added to #{organization.name}" - elsif organization.blank? - message = "Organization ##{organization_membership_params[:organization_id]} does not exist. Perhaps a typo?" - flash[:danger] = message - else - flash[:danger] = organization_membership.errors.full_messages + def create + organization_membership = OrganizationMembership.new(organization_membership_params) + organization = Organization.find_by(id: organization_membership_params[:organization_id]) + if organization && organization_membership.save + flash[:success] = "User was successfully added to #{organization.name}" + elsif organization.blank? + message = "Organization ##{organization_membership_params[:organization_id]} does not exist. Perhaps a typo?" + flash[:danger] = message + else + flash[:danger] = organization_membership.errors.full_messages + end + redirect_to internal_user_path(organization_membership.user_id) end - redirect_to internal_user_path(organization_membership.user_id) - end - def destroy - organization_membership = OrganizationMembership.find_by(id: params[:id]) - if organization_membership.destroy - flash[:success] = "User was successfully removed from org ##{organization_membership.organization_id}" - else - message = "Something went wrong with removing the user from org ##{organization_membership.organization_id}" - flash[:danger] = message + def destroy + organization_membership = OrganizationMembership.find_by(id: params[:id]) + if organization_membership.destroy + flash[:success] = "User was successfully removed from org ##{organization_membership.organization_id}" + else + message = "Something went wrong with removing the user from org ##{organization_membership.organization_id}" + flash[:danger] = message + end + redirect_to internal_user_path(organization_membership.user_id) end - redirect_to internal_user_path(organization_membership.user_id) - end - private + private - def organization_membership_params - allowed_params = %i[type_of_user user_title organization_id user_id] - params.require(:organization_membership).permit(allowed_params) + def organization_membership_params + allowed_params = %i[type_of_user user_title organization_id user_id] + params.require(:organization_membership).permit(allowed_params) + end end end diff --git a/app/controllers/internal/organizations_controller.rb b/app/controllers/internal/organizations_controller.rb index f1f95e22d..9ebc320e2 100644 --- a/app/controllers/internal/organizations_controller.rb +++ b/app/controllers/internal/organizations_controller.rb @@ -1,47 +1,49 @@ -class Internal::OrganizationsController < Internal::ApplicationController - layout "internal" +module Internal + class OrganizationsController < Internal::ApplicationController + layout "internal" - CREDIT_ACTIONS = { - add: :add_to, - remove: :remove_from - }.with_indifferent_access.freeze + CREDIT_ACTIONS = { + add: :add_to, + remove: :remove_from + }.with_indifferent_access.freeze - def index - @organizations = Organization.order(name: :desc).page(params[:page]).per(50) + def index + @organizations = Organization.order(name: :desc).page(params[:page]).per(50) - return if params[:search].blank? + return if params[:search].blank? - @organizations = @organizations.where( - "name ILIKE ?", - "%#{params[:search].strip}%", - ) - end + @organizations = @organizations.where( + "name ILIKE ?", + "%#{params[:search].strip}%", + ) + end - def show - @organization = Organization.find(params[:id]) - end + def show + @organization = Organization.find(params[:id]) + end - def update_org_credits - org = Organization.find(params[:id]) - amount = params[:credits].to_i - update_action = CREDIT_ACTIONS.fetch(params[:credit_action]) + def update_org_credits + org = Organization.find(params[:id]) + amount = params[:credits].to_i + update_action = CREDIT_ACTIONS.fetch(params[:credit_action]) - Credit.public_send(update_action, org, amount) - add_note(org) + Credit.public_send(update_action, org, amount) + add_note(org) - flash[:notice] = "Sucessfully updated credits" - redirect_to internal_organization_path(org) - end + flash[:notice] = "Sucessfully updated credits" + redirect_to internal_organization_path(org) + end - private + private - def add_note(org) - Note.create( - author_id: current_user.id, - noteable_id: org.id, - noteable_type: "Organization", - reason: "misc_note", - content: params[:note], - ) + def add_note(org) + Note.create( + author_id: current_user.id, + noteable_id: org.id, + noteable_type: "Organization", + reason: "misc_note", + content: params[:note], + ) + end end end diff --git a/app/controllers/internal/pages_controller.rb b/app/controllers/internal/pages_controller.rb index b24fcfdef..ed237720b 100644 --- a/app/controllers/internal/pages_controller.rb +++ b/app/controllers/internal/pages_controller.rb @@ -1,41 +1,43 @@ -class Internal::PagesController < Internal::ApplicationController - layout "internal" +module Internal + class PagesController < Internal::ApplicationController + layout "internal" - def index - @pages = Page.all - end + def index + @pages = Page.all + end - def new - @page = Page.new - end + def new + @page = Page.new + end - def edit - @page = Page.find(params[:id]) - end + def edit + @page = Page.find(params[:id]) + end - def update - @page = Page.find(params[:id]) - @page.update!(page_params) - redirect_to "/internal/pages" - end + def update + @page = Page.find(params[:id]) + @page.update!(page_params) + redirect_to "/internal/pages" + end - def create - @page = Page.new(page_params) - @page.save! - redirect_to "/internal/pages" - end + def create + @page = Page.new(page_params) + @page.save! + redirect_to "/internal/pages" + end - def destroy - @page = Page.find(params[:id]) - @page.destroy - redirect_to "/internal/pages" - end + def destroy + @page = Page.find(params[:id]) + @page.destroy + redirect_to "/internal/pages" + end - private + private - def page_params - allowed_params = %i[title slug body_markdown body_html body_json description template is_top_level_path - social_image] - params.require(:page).permit(allowed_params) + def page_params + allowed_params = %i[title slug body_markdown body_html body_json description template is_top_level_path + social_image] + params.require(:page).permit(allowed_params) + end end end diff --git a/app/controllers/internal/path_redirects_controller.rb b/app/controllers/internal/path_redirects_controller.rb index 111bd4c17..95f6d78d4 100644 --- a/app/controllers/internal/path_redirects_controller.rb +++ b/app/controllers/internal/path_redirects_controller.rb @@ -1,66 +1,68 @@ -class Internal::PathRedirectsController < Internal::ApplicationController - layout "internal" +module Internal + class PathRedirectsController < Internal::ApplicationController + layout "internal" - before_action :set_path_redirect, only: %i[edit update destroy] + before_action :set_path_redirect, only: %i[edit update destroy] - after_action only: %i[update destroy create] do - Audit::Logger.log(:internal, current_user, params.dup) - end - - def new - @path_redirect = PathRedirect.new - end - - def create - @path_redirect = PathRedirect.new(new_path_redirect_params) - - if @path_redirect.save - flash[:success] = "Path Redirect created successfully!" - redirect_to internal_path_redirects_path - else - flash[:danger] = @path_redirect.errors.full_messages.to_sentence - render new_internal_path_redirect_path + after_action only: %i[update destroy create] do + Audit::Logger.log(:internal, current_user, params.dup) end - end - def index - @q = PathRedirect.order(created_at: :desc).ransack(params[:q]) - @path_redirects = @q.result.page(params[:page] || 1).per(25) - end - - def edit; end - - def update - if @path_redirect.update(edit_path_redirect_params) - flash[:success] = "Path Redirect updated successfully!" - redirect_to edit_internal_path_redirect_path(@path_redirect) - else - flash[:danger] = @path_redirect.errors.full_messages.to_sentence - render :edit + def new + @path_redirect = PathRedirect.new end - end - def destroy - if @path_redirect.destroy - flash[:success] = "Path Redirect destroyed successfully!" - redirect_to internal_path_redirects_path - else # This should never be the case - flash[:danger] = @path_redirect.errors.full_messages.to_sentence - render :edit + def create + @path_redirect = PathRedirect.new(new_path_redirect_params) + + if @path_redirect.save + flash[:success] = "Path Redirect created successfully!" + redirect_to internal_path_redirects_path + else + flash[:danger] = @path_redirect.errors.full_messages.to_sentence + render new_internal_path_redirect_path + end end - end - private + def index + @q = PathRedirect.order(created_at: :desc).ransack(params[:q]) + @path_redirects = @q.result.page(params[:page] || 1).per(25) + end - def set_path_redirect - @path_redirect = PathRedirect.find(params[:id]) - end + def edit; end - def new_path_redirect_params - params.require(:path_redirect).permit(:old_path, :new_path).merge(source: "admin") - end + def update + if @path_redirect.update(edit_path_redirect_params) + flash[:success] = "Path Redirect updated successfully!" + redirect_to edit_internal_path_redirect_path(@path_redirect) + else + flash[:danger] = @path_redirect.errors.full_messages.to_sentence + render :edit + end + end - def edit_path_redirect_params - params.require(:path_redirect).permit(:new_path).merge(source: "admin") + def destroy + if @path_redirect.destroy + flash[:success] = "Path Redirect destroyed successfully!" + redirect_to internal_path_redirects_path + else # This should never be the case + flash[:danger] = @path_redirect.errors.full_messages.to_sentence + render :edit + end + end + + private + + def set_path_redirect + @path_redirect = PathRedirect.find(params[:id]) + end + + def new_path_redirect_params + params.require(:path_redirect).permit(:old_path, :new_path).merge(source: "admin") + end + + def edit_path_redirect_params + params.require(:path_redirect).permit(:new_path).merge(source: "admin") + end end end diff --git a/app/controllers/internal/permissions_controller.rb b/app/controllers/internal/permissions_controller.rb index 63cc8025a..9b9367584 100644 --- a/app/controllers/internal/permissions_controller.rb +++ b/app/controllers/internal/permissions_controller.rb @@ -1,11 +1,13 @@ -class Internal::PermissionsController < Internal::ApplicationController - layout "internal" +module Internal + class PermissionsController < Internal::ApplicationController + layout "internal" - def index - @users = User.with_role(:admin). - union(User.with_role(:super_admin)). - union(User.with_role(:single_resource_admin, :any)). - page(params[:page]). - per(50) + def index + @users = User.with_role(:admin). + union(User.with_role(:super_admin)). + union(User.with_role(:single_resource_admin, :any)). + page(params[:page]). + per(50) + end end end diff --git a/app/controllers/internal/podcasts_controller.rb b/app/controllers/internal/podcasts_controller.rb index 8f87ef837..ae2dd5354 100644 --- a/app/controllers/internal/podcasts_controller.rb +++ b/app/controllers/internal/podcasts_controller.rb @@ -1,71 +1,73 @@ -class Internal::PodcastsController < Internal::ApplicationController - layout "internal" +module Internal + class PodcastsController < Internal::ApplicationController + layout "internal" - before_action :find_podcast, only: %i[edit update fetch remove_admin add_admin] - before_action :find_user, only: %i[remove_admin add_admin] + before_action :find_podcast, only: %i[edit update fetch remove_admin add_admin] + before_action :find_user, only: %i[remove_admin add_admin] - def index - @podcasts = Podcast.left_outer_joins(:podcast_episodes). - select("podcasts.*, count(podcast_episodes) as episodes_count"). - group("podcasts.id").order("podcasts.created_at DESC"). - page(params[:page]).per(50) + def index + @podcasts = Podcast.left_outer_joins(:podcast_episodes). + select("podcasts.*, count(podcast_episodes) as episodes_count"). + group("podcasts.id").order("podcasts.created_at DESC"). + page(params[:page]).per(50) - return if params[:search].blank? + return if params[:search].blank? - @podcasts = @podcasts.where("podcasts.title ILIKE :search", search: "%#{params[:search]}%") - end - - def edit; end - - def update - if @podcast.update(podcast_params) - redirect_to internal_podcasts_path, notice: "Podcast updated" - else - render :edit + @podcasts = @podcasts.where("podcasts.title ILIKE :search", search: "%#{params[:search]}%") end - end - def fetch - limit = params[:limit].to_i.zero? ? nil : params[:limit].to_i - force = params[:force].to_i == 1 - Podcasts::GetEpisodesWorker.perform_async(podcast_id: @podcast.id, limit: limit, force: force) - flash[:notice] = "Podcast's episodes fetching was scheduled (#{@podcast.title}, ##{@podcast.id})" - redirect_to internal_podcasts_path - end + def edit; end - def remove_admin - removed_roles = @user.remove_role(:podcast_admin, @podcast) - if removed_roles.empty? - redirect_to edit_internal_podcast_path(@podcast), notice: "Error" - else - redirect_to internal_podcasts_path, notice: "Removed admin" + def update + if @podcast.update(podcast_params) + redirect_to internal_podcasts_path, notice: "Podcast updated" + else + render :edit + end end - end - def add_admin - role = @user.add_role(:podcast_admin, @podcast) - if role.persisted? - redirect_to internal_podcasts_path, notice: "Added admin" - else - redirect_to edit_internal_podcast_path(@podcast), notice: "Error" + def fetch + limit = params[:limit].to_i.zero? ? nil : params[:limit].to_i + force = params[:force].to_i == 1 + Podcasts::GetEpisodesWorker.perform_async(podcast_id: @podcast.id, limit: limit, force: force) + flash[:notice] = "Podcast's episodes fetching was scheduled (#{@podcast.title}, ##{@podcast.id})" + redirect_to internal_podcasts_path end - end - private + def remove_admin + removed_roles = @user.remove_role(:podcast_admin, @podcast) + if removed_roles.empty? + redirect_to edit_internal_podcast_path(@podcast), notice: "Error" + else + redirect_to internal_podcasts_path, notice: "Removed admin" + end + end - def find_podcast - @podcast = Podcast.find(params[:id]) - end + def add_admin + role = @user.add_role(:podcast_admin, @podcast) + if role.persisted? + redirect_to internal_podcasts_path, notice: "Added admin" + else + redirect_to edit_internal_podcast_path(@podcast), notice: "Error" + end + end - def find_user - @user = User.find_by(id: params[:podcast][:user_id]) - redirect_to edit_internal_podcast_path(@podcast), notice: "No such user" unless @user - end + private - def podcast_params - allowed_params = %i[ - title feed_url - ] - params.require(:podcast).permit(allowed_params) + def find_podcast + @podcast = Podcast.find(params[:id]) + end + + def find_user + @user = User.find_by(id: params[:podcast][:user_id]) + redirect_to edit_internal_podcast_path(@podcast), notice: "No such user" unless @user + end + + def podcast_params + allowed_params = %i[ + title feed_url + ] + params.require(:podcast).permit(allowed_params) + end end end diff --git a/app/controllers/internal/privileged_reactions_controller.rb b/app/controllers/internal/privileged_reactions_controller.rb index f3b10422e..09ba37614 100644 --- a/app/controllers/internal/privileged_reactions_controller.rb +++ b/app/controllers/internal/privileged_reactions_controller.rb @@ -1,15 +1,17 @@ -class Internal::PrivilegedReactionsController < Internal::ApplicationController - layout "internal" +module Internal + class PrivilegedReactionsController < Internal::ApplicationController + layout "internal" - PRIVILEGED_REACTION_CATEGORIES = %i[thumbsup thumbsdown vomit].freeze + PRIVILEGED_REACTION_CATEGORIES = %i[thumbsup thumbsdown vomit].freeze - def index - @q = Reaction. - includes(:user, - :reactable). - where("category IN (?)", PRIVILEGED_REACTION_CATEGORIES). - order("reactions.created_at DESC"). - ransack(params[:q]) - @privileged_reactions = @q.result.page(params[:page] || 1).per(25) + def index + @q = Reaction. + includes(:user, + :reactable). + where("category IN (?)", PRIVILEGED_REACTION_CATEGORIES). + order("reactions.created_at DESC"). + ransack(params[:q]) + @privileged_reactions = @q.result.page(params[:page] || 1).per(25) + end end end diff --git a/app/controllers/internal/reactions_controller.rb b/app/controllers/internal/reactions_controller.rb index 3a6017f28..8fdde3452 100644 --- a/app/controllers/internal/reactions_controller.rb +++ b/app/controllers/internal/reactions_controller.rb @@ -1,21 +1,23 @@ -class Internal::ReactionsController < Internal::ApplicationController - after_action only: [:update] do - Audit::Logger.log(:moderator, current_user, params.dup) - end +module Internal + class ReactionsController < Internal::ApplicationController + after_action only: [:update] do + Audit::Logger.log(:moderator, current_user, params.dup) + end - def update - @reaction = Reaction.find(params[:id]) - if @reaction.update(status: params[:status]) - Moderator::SinkArticles.call(@reaction.reactable_id) if confirmed_vomit_reaction? - render json: { outcome: "Success" } - else - render json: { error: @reaction.errors_as_sentence }, status: :unprocessable_entity + def update + @reaction = Reaction.find(params[:id]) + if @reaction.update(status: params[:status]) + Moderator::SinkArticles.call(@reaction.reactable_id) if confirmed_vomit_reaction? + render json: { outcome: "Success" } + else + render json: { error: @reaction.errors_as_sentence }, status: :unprocessable_entity + end + end + + private + + def confirmed_vomit_reaction? + @reaction.reactable_type == "User" && @reaction.status == "confirmed" && @reaction.category == "vomit" end end - - private - - def confirmed_vomit_reaction? - @reaction.reactable_type == "User" && @reaction.status == "confirmed" && @reaction.category == "vomit" - end end diff --git a/app/controllers/internal/response_templates_controller.rb b/app/controllers/internal/response_templates_controller.rb index db3c23a60..e55314660 100644 --- a/app/controllers/internal/response_templates_controller.rb +++ b/app/controllers/internal/response_templates_controller.rb @@ -1,65 +1,67 @@ -class Internal::ResponseTemplatesController < Internal::ApplicationController - layout "internal" - after_action only: %i[create update destroy] do - Audit::Logger.log(:moderator, current_user, params.dup) - end - - def index - @response_templates = if params[:filter] - ResponseTemplate.where(type_of: params[:filter]) - else - ResponseTemplate.all - end - @response_templates = @response_templates.page(params[:page]).per(50) - end - - def new - @response_template = ResponseTemplate.new - end - - def create - @response_template = ResponseTemplate.new(permitted_params) - if @response_template.save - flash[:success] = "Response Template: \"#{@response_template.title}\" saved successfully." - redirect_to internal_response_templates_path - else - flash[:danger] = @response_template.errors_as_sentence - @response_templates = ResponseTemplate.page(params[:page]).per(50) - render new_internal_response_template_path - end - end - - def edit - @response_template = ResponseTemplate.find(params[:id]) - end - - def update - @response_template = ResponseTemplate.find(params[:id]) - - if @response_template.update(permitted_attributes(ResponseTemplate)) - flash[:success] = "The response template \"#{@response_template.title}\" was updated." - redirect_to edit_internal_response_template_path(@response_template) - else - flash[:danger] = @response_template.errors_as_sentence - render :edit - end - end - - def destroy - @response_template = ResponseTemplate.find(params[:id]) - - if @response_template.destroy - flash[:success] = "The response template \"#{@response_template.title}\" was deleted." - else - flash[:danger] = @response_template.errors_as_sentence # this will probably never fail +module Internal + class ResponseTemplatesController < Internal::ApplicationController + layout "internal" + after_action only: %i[create update destroy] do + Audit::Logger.log(:moderator, current_user, params.dup) end - redirect_back(fallback_location: internal_response_templates_path) - end + def index + @response_templates = if params[:filter] + ResponseTemplate.where(type_of: params[:filter]) + else + ResponseTemplate.all + end + @response_templates = @response_templates.page(params[:page]).per(50) + end - private + def new + @response_template = ResponseTemplate.new + end - def permitted_params - params.require(:response_template).permit(:body_markdown, :user_id, :content, :title, :type_of, :content_type) + def create + @response_template = ResponseTemplate.new(permitted_params) + if @response_template.save + flash[:success] = "Response Template: \"#{@response_template.title}\" saved successfully." + redirect_to internal_response_templates_path + else + flash[:danger] = @response_template.errors_as_sentence + @response_templates = ResponseTemplate.page(params[:page]).per(50) + render new_internal_response_template_path + end + end + + def edit + @response_template = ResponseTemplate.find(params[:id]) + end + + def update + @response_template = ResponseTemplate.find(params[:id]) + + if @response_template.update(permitted_attributes(ResponseTemplate)) + flash[:success] = "The response template \"#{@response_template.title}\" was updated." + redirect_to edit_internal_response_template_path(@response_template) + else + flash[:danger] = @response_template.errors_as_sentence + render :edit + end + end + + def destroy + @response_template = ResponseTemplate.find(params[:id]) + + if @response_template.destroy + flash[:success] = "The response template \"#{@response_template.title}\" was deleted." + else + flash[:danger] = @response_template.errors_as_sentence # this will probably never fail + end + + redirect_back(fallback_location: internal_response_templates_path) + end + + private + + def permitted_params + params.require(:response_template).permit(:body_markdown, :user_id, :content, :title, :type_of, :content_type) + end end end diff --git a/app/controllers/internal/secrets_controller.rb b/app/controllers/internal/secrets_controller.rb index 7d7545aa2..76ade0807 100644 --- a/app/controllers/internal/secrets_controller.rb +++ b/app/controllers/internal/secrets_controller.rb @@ -1,33 +1,35 @@ -class Internal::SecretsController < Internal::ApplicationController - layout "internal" +module Internal + class SecretsController < Internal::ApplicationController + layout "internal" - before_action :validate_settable_secret, only: [:update] - after_action only: [:update] do - Audit::Logger.log(:internal, current_user, params.dup) - end + before_action :validate_settable_secret, only: [:update] + after_action only: [:update] do + Audit::Logger.log(:internal, current_user, params.dup) + end - def index - @vault_enabled = AppSecrets.vault_enabled? - @secrets = AppSecrets::SETTABLE_SECRETS.map do |key| - secret_value = AppSecrets[key] - secret_value = secret_value.present? ? "#{secret_value.first(8)}******" : "Not In Vault" - [key, secret_value] + def index + @vault_enabled = AppSecrets.vault_enabled? + @secrets = AppSecrets::SETTABLE_SECRETS.map do |key| + secret_value = AppSecrets[key] + secret_value = secret_value.present? ? "#{secret_value.first(8)}******" : "Not In Vault" + [key, secret_value] + end + end + + def update + AppSecrets[params[:key_name]] = params[:key_value] + + flash[:success] = "Secret #{params[:key_name]} was successfully updated in Vault." + redirect_to internal_secrets_path + end + + private + + def validate_settable_secret + update_param = params.permit(*AppSecrets::SETTABLE_SECRETS) + params[:key_name], params[:key_value] = update_param.to_h.to_a.first + + bad_request unless update_param.present? && params[:key_name].is_a?(String) && params[:key_value].is_a?(String) end end - - def update - AppSecrets[params[:key_name]] = params[:key_value] - - flash[:success] = "Secret #{params[:key_name]} was successfully updated in Vault." - redirect_to internal_secrets_path - end - - private - - def validate_settable_secret - update_param = params.permit(*AppSecrets::SETTABLE_SECRETS) - params[:key_name], params[:key_value] = update_param.to_h.to_a.first - - bad_request unless update_param.present? && params[:key_name].is_a?(String) && params[:key_value].is_a?(String) - end end diff --git a/app/controllers/internal/sponsorships_controller.rb b/app/controllers/internal/sponsorships_controller.rb index 841322725..c0320f054 100644 --- a/app/controllers/internal/sponsorships_controller.rb +++ b/app/controllers/internal/sponsorships_controller.rb @@ -1,39 +1,41 @@ -class Internal::SponsorshipsController < Internal::ApplicationController - layout "internal" +module Internal + class SponsorshipsController < Internal::ApplicationController + layout "internal" - def index - @sponsorships = Sponsorship.includes(:organization, :user).order("created_at desc").page(params[:page]).per(50) - end + def index + @sponsorships = Sponsorship.includes(:organization, :user).order("created_at desc").page(params[:page]).per(50) + end - def edit - @sponsorship = Sponsorship.find(params[:id]) - end + def edit + @sponsorship = Sponsorship.find(params[:id]) + end - def update - @sponsorship = Sponsorship.find(params[:id]) - if @sponsorship.update(sponsorship_params) - flash[:notice] = "Sponsorship was successfully updated" + def update + @sponsorship = Sponsorship.find(params[:id]) + if @sponsorship.update(sponsorship_params) + flash[:notice] = "Sponsorship was successfully updated" + redirect_to internal_sponsorships_path + else + flash[:danger] = @sponsorship.errors_as_sentence + render action: :edit + end + end + + def destroy + @sponsorship = Sponsorship.find(params[:id]) + if @sponsorship.destroy + flash[:notice] = "Sponsorship was successfully destroyed" + else + flash[:danger] = "Sponsorship was not destroyed" + end redirect_to internal_sponsorships_path - else - flash[:danger] = @sponsorship.errors_as_sentence - render action: :edit end - end - def destroy - @sponsorship = Sponsorship.find(params[:id]) - if @sponsorship.destroy - flash[:notice] = "Sponsorship was successfully destroyed" - else - flash[:danger] = "Sponsorship was not destroyed" + private + + def sponsorship_params + params.require(:sponsorship).permit(%i[status expires_at tagline url blurb_html featured_number instructions + instructions_updated_at]) end - redirect_to internal_sponsorships_path - end - - private - - def sponsorship_params - params.require(:sponsorship).permit(%i[status expires_at tagline url blurb_html featured_number instructions - instructions_updated_at]) end end diff --git a/app/controllers/internal/tags_controller.rb b/app/controllers/internal/tags_controller.rb index 1ed43dcf4..75c77df2d 100644 --- a/app/controllers/internal/tags_controller.rb +++ b/app/controllers/internal/tags_controller.rb @@ -1,55 +1,57 @@ -class Internal::TagsController < Internal::ApplicationController - layout "internal" +module Internal + class TagsController < Internal::ApplicationController + layout "internal" - after_action only: [:update] do - Audit::Logger.log(:moderator, current_user, params.dup) - end + after_action only: [:update] do + Audit::Logger.log(:moderator, current_user, params.dup) + end - def index - @tags = if params[:state] == "supported" - Tag.where(supported: true).order("taggings_count DESC").page(params[:page]).per(50) - elsif params[:state] == "unsupported" - Tag.where(supported: false).order("taggings_count DESC").page(params[:page]).per(50) - else - Tag.order("taggings_count DESC").page(params[:page]).per(50) - end - @tags = @tags.where("tags.name ILIKE :search", search: "%#{params[:search]}%") if params[:search].present? - end + def index + @tags = if params[:state] == "supported" + Tag.where(supported: true).order("taggings_count DESC").page(params[:page]).per(50) + elsif params[:state] == "unsupported" + Tag.where(supported: false).order("taggings_count DESC").page(params[:page]).per(50) + else + Tag.order("taggings_count DESC").page(params[:page]).per(50) + end + @tags = @tags.where("tags.name ILIKE :search", search: "%#{params[:search]}%") if params[:search].present? + end - def show - @tag = Tag.find(params[:id]) - end + def show + @tag = Tag.find(params[:id]) + end - def update - @tag = Tag.find(params[:id]) - @add_user_id = params[:tag][:tag_moderator_id] - @remove_user_id = params[:tag][:remove_moderator_id] - add_moderator if @add_user_id - remove_moderator if @remove_user_id - @tag.update!(tag_params) + def update + @tag = Tag.find(params[:id]) + @add_user_id = params[:tag][:tag_moderator_id] + @remove_user_id = params[:tag][:remove_moderator_id] + add_moderator if @add_user_id + remove_moderator if @remove_user_id + @tag.update!(tag_params) - redirect_to "/internal/tags/#{params[:id]}" - end + redirect_to "/internal/tags/#{params[:id]}" + end - private + private - def remove_moderator - user = User.find(@remove_user_id) - user.update(email_tag_mod_newsletter: false) - AssignTagModerator.remove_tag_moderator(user, @tag) - end + def remove_moderator + user = User.find(@remove_user_id) + user.update(email_tag_mod_newsletter: false) + AssignTagModerator.remove_tag_moderator(user, @tag) + end - def add_moderator - User.find(@add_user_id).update(email_tag_mod_newsletter: true) - AssignTagModerator.add_tag_moderators([@add_user_id], [@tag.id]) - end + def add_moderator + User.find(@add_user_id).update(email_tag_mod_newsletter: true) + AssignTagModerator.add_tag_moderators([@add_user_id], [@tag.id]) + end - def tag_params - allowed_params = %i[ - supported rules_markdown short_summary pretty_name bg_color_hex - text_color_hex tag_moderator_id remove_moderator_id alias_for badge_id - category social_preview_template - ] - params.require(:tag).permit(allowed_params) + def tag_params + allowed_params = %i[ + supported rules_markdown short_summary pretty_name bg_color_hex + text_color_hex tag_moderator_id remove_moderator_id alias_for badge_id + category social_preview_template + ] + params.require(:tag).permit(allowed_params) + end end end diff --git a/app/controllers/internal/tools_controller.rb b/app/controllers/internal/tools_controller.rb index f46115032..1d0334e00 100644 --- a/app/controllers/internal/tools_controller.rb +++ b/app/controllers/internal/tools_controller.rb @@ -1,51 +1,53 @@ -class Internal::ToolsController < Internal::ApplicationController - layout "internal" +module Internal + class ToolsController < Internal::ApplicationController + layout "internal" - def index; end + def index; end - def bust_cache - flash[:success] = if params[:dead_link] - handle_dead_path - "#{params[:dead_link]} was successfully busted" - elsif params[:bust_user] - handle_user_cache - "User ##{params[:bust_user]} was successfully busted" - elsif params[:bust_article] - handle_article_cache - "Article ##{params[:bust_article]} was successfully busted" - end - redirect_to "/internal/tools" - rescue StandardError => e - flash[:danger] = e.message - redirect_to "/internal/tools" - end - - private - - def handle_dead_path - bust_link(params[:dead_link]) - end - - def handle_user_cache - user = User.find(params[:bust_user].to_i) - user.touch(:profile_updated_at, :last_followed_at, :last_comment_at) - bust_link(user.path) - end - - def handle_article_cache - article = Article.find(params[:bust_article].to_i) - article.touch(:last_commented_at) - CacheBuster.bust_article(article) - end - - def bust_link(link) - if link.starts_with?("https://#{ApplicationConfig['APP_DOMAIN']}") - link.sub!("https://#{ApplicationConfig['APP_DOMAIN']}", - "") + def bust_cache + flash[:success] = if params[:dead_link] + handle_dead_path + "#{params[:dead_link]} was successfully busted" + elsif params[:bust_user] + handle_user_cache + "User ##{params[:bust_user]} was successfully busted" + elsif params[:bust_article] + handle_article_cache + "Article ##{params[:bust_article]} was successfully busted" + end + redirect_to "/internal/tools" + rescue StandardError => e + flash[:danger] = e.message + redirect_to "/internal/tools" + end + + private + + def handle_dead_path + bust_link(params[:dead_link]) + end + + def handle_user_cache + user = User.find(params[:bust_user].to_i) + user.touch(:profile_updated_at, :last_followed_at, :last_comment_at) + bust_link(user.path) + end + + def handle_article_cache + article = Article.find(params[:bust_article].to_i) + article.touch(:last_commented_at) + CacheBuster.bust_article(article) + end + + def bust_link(link) + if link.starts_with?("https://#{ApplicationConfig['APP_DOMAIN']}") + link.sub!("https://#{ApplicationConfig['APP_DOMAIN']}", + "") + end + CacheBuster.bust(link) + CacheBuster.bust("#{link}/") + CacheBuster.bust("#{link}?i=i") + CacheBuster.bust("#{link}/?i=i") end - CacheBuster.bust(link) - CacheBuster.bust("#{link}/") - CacheBuster.bust("#{link}?i=i") - CacheBuster.bust("#{link}/?i=i") end end diff --git a/app/controllers/internal/users_controller.rb b/app/controllers/internal/users_controller.rb index ba915df8a..acfe76eb1 100644 --- a/app/controllers/internal/users_controller.rb +++ b/app/controllers/internal/users_controller.rb @@ -1,174 +1,176 @@ -class Internal::UsersController < Internal::ApplicationController - layout "internal" +module Internal + class UsersController < Internal::ApplicationController + layout "internal" - after_action only: %i[update user_status banish full_delete merge] do - Audit::Logger.log(:moderator, current_user, params.dup) - end - - def index - @users = Internal::UsersQuery.call( - options: params.permit(:role, :search), - ).page(params[:page]).per(50) - end - - def edit - @user = User.find(params[:id]) - @notes = @user.notes.order(created_at: :desc).limit(10).load - end - - def show - @user = User.find(params[:id]) - @organizations = @user.organizations.order(:name) - @notes = @user.notes.order(created_at: :desc).limit(10) - @organization_memberships = @user.organization_memberships. - joins(:organization). - order("organizations.name ASC"). - includes(:organization) - @last_email_verification_date = @user.email_authorizations. - where.not(verified_at: nil). - order("created_at DESC").first&.verified_at || "Never" - end - - def update - @user = User.find(params[:id]) - manage_credits - add_note if user_params[:new_note] - redirect_to "/internal/users/#{params[:id]}" - end - - def user_status - @user = User.find(params[:id]) - begin - Moderator::ManageActivityAndRoles.handle_user_roles(admin: current_user, user: @user, user_params: user_params) - flash[:success] = "User has been updated" - rescue StandardError => e - flash[:danger] = e.message - end - redirect_to "/internal/users/#{@user.id}/edit" - end - - def banish - Moderator::BanishUserWorker.perform_async(current_user.id, params[:id].to_i) - flash[:success] = "This user is being banished in the background. The job will complete soon." - redirect_to "/internal/users/#{params[:id]}/edit" - end - - def full_delete - @user = User.find(params[:id]) - begin - Moderator::DeleteUser.call(admin: current_user, user: @user, user_params: user_params) - message = "@#{@user.username} (email: #{@user.email.presence || 'no email'}, user_id: #{@user.id}) " \ - "has been fully deleted. If requested, old content may have been ghostified. " \ - "If this is a GDPR delete, delete them from Mailchimp & Google Analytics." - flash[:success] = message - rescue StandardError => e - flash[:danger] = e.message - end - redirect_to "/internal/users" - end - - def merge - @user = User.find(params[:id]) - begin - Moderator::MergeUser.call(admin: current_user, keep_user: @user, delete_user_id: user_params["merge_user_id"]) - rescue StandardError => e - flash[:danger] = e.message + after_action only: %i[update user_status banish full_delete merge] do + Audit::Logger.log(:moderator, current_user, params.dup) end - redirect_to "/internal/users/#{@user.id}/edit" - end - - def remove_identity - identity = Identity.find(user_params[:identity_id]) - @user = identity.user - begin - BackupData.backup!(identity) - identity.delete - @user.update("#{identity.provider}_username" => nil) - flash[:success] = "The #{identity.provider.capitalize} identity was successfully deleted and backed up." - rescue StandardError => e - flash[:danger] = e.message + def index + @users = Internal::UsersQuery.call( + options: params.permit(:role, :search), + ).page(params[:page]).per(50) end - redirect_to "/internal/users/#{@user.id}/edit" - end - def recover_identity - backup = BackupData.find(user_params[:backup_data_id]) - @user = backup.instance_user - begin - identity = backup.recover! - flash[:success] = "The #{identity.provider} identity was successfully recovered, and the backup was removed." - rescue StandardError => e - flash[:danger] = e.message + def edit + @user = User.find(params[:id]) + @notes = @user.notes.order(created_at: :desc).limit(10).load end - redirect_to "/internal/users/#{@user.id}/edit" - end - def send_email - if NotifyMailer.with(params).user_contact_email.deliver_now - redirect_back(fallback_location: users_path) - else - flash[:danger] = "Email failed to send!" + def show + @user = User.find(params[:id]) + @organizations = @user.organizations.order(:name) + @notes = @user.notes.order(created_at: :desc).limit(10) + @organization_memberships = @user.organization_memberships. + joins(:organization). + order("organizations.name ASC"). + includes(:organization) + @last_email_verification_date = @user.email_authorizations. + where.not(verified_at: nil). + order("created_at DESC").first&.verified_at || "Never" end - end - def verify_email_ownership - if VerificationMailer.with(user_id: params[:user_id]).account_ownership_verification_email.deliver_now - flash[:success] = "Email Verification Mailer sent!" - redirect_back(fallback_location: internal_users_path) - else - flash[:danger] = "Email failed to send!" + def update + @user = User.find(params[:id]) + manage_credits + add_note if user_params[:new_note] + redirect_to "/internal/users/#{params[:id]}" end - end - private + def user_status + @user = User.find(params[:id]) + begin + Moderator::ManageActivityAndRoles.handle_user_roles(admin: current_user, user: @user, user_params: user_params) + flash[:success] = "User has been updated" + rescue StandardError => e + flash[:danger] = e.message + end + redirect_to "/internal/users/#{@user.id}/edit" + end - def manage_credits - add_credits if user_params[:add_credits] - add_org_credits if user_params[:add_org_credits] - remove_org_credits if user_params[:remove_org_credits] - remove_credits if user_params[:remove_credits] - end + def banish + Moderator::BanishUserWorker.perform_async(current_user.id, params[:id].to_i) + flash[:success] = "This user is being banished in the background. The job will complete soon." + redirect_to "/internal/users/#{params[:id]}/edit" + end - def add_note - Note.create( - author_id: current_user.id, - noteable_id: @user.id, - noteable_type: "User", - reason: "misc_note", - content: user_params[:new_note], - ) - end + def full_delete + @user = User.find(params[:id]) + begin + Moderator::DeleteUser.call(admin: current_user, user: @user, user_params: user_params) + message = "@#{@user.username} (email: #{@user.email.presence || 'no email'}, user_id: #{@user.id}) " \ + "has been fully deleted. If requested, old content may have been ghostified. " \ + "If this is a GDPR delete, delete them from Mailchimp & Google Analytics." + flash[:success] = message + rescue StandardError => e + flash[:danger] = e.message + end + redirect_to "/internal/users" + end - def add_credits - amount = user_params[:add_credits].to_i - Credit.add_to(@user, amount) - end + def merge + @user = User.find(params[:id]) + begin + Moderator::MergeUser.call(admin: current_user, keep_user: @user, delete_user_id: user_params["merge_user_id"]) + rescue StandardError => e + flash[:danger] = e.message + end - def remove_credits - amount = user_params[:remove_credits].to_i - Credit.remove_from(@user, amount) - end + redirect_to "/internal/users/#{@user.id}/edit" + end - def add_org_credits - org = Organization.find(user_params[:organization_id]) - amount = user_params[:add_org_credits].to_i - Credit.add_to(org, amount) - end + def remove_identity + identity = Identity.find(user_params[:identity_id]) + @user = identity.user + begin + BackupData.backup!(identity) + identity.delete + @user.update("#{identity.provider}_username" => nil) + flash[:success] = "The #{identity.provider.capitalize} identity was successfully deleted and backed up." + rescue StandardError => e + flash[:danger] = e.message + end + redirect_to "/internal/users/#{@user.id}/edit" + end - def remove_org_credits - org = Organization.find(user_params[:organization_id]) - amount = user_params[:remove_org_credits].to_i - Credit.remove_from(org, amount) - end + def recover_identity + backup = BackupData.find(user_params[:backup_data_id]) + @user = backup.instance_user + begin + identity = backup.recover! + flash[:success] = "The #{identity.provider} identity was successfully recovered, and the backup was removed." + rescue StandardError => e + flash[:danger] = e.message + end + redirect_to "/internal/users/#{@user.id}/edit" + end - def user_params - allowed_params = %i[ - new_note note_for_current_role user_status - pro merge_user_id add_credits remove_credits - add_org_credits remove_org_credits ghostify - organization_id identity_id backup_data_id - ] - params.require(:user).permit(allowed_params) + def send_email + if NotifyMailer.with(params).user_contact_email.deliver_now + redirect_back(fallback_location: users_path) + else + flash[:danger] = "Email failed to send!" + end + end + + def verify_email_ownership + if VerificationMailer.with(user_id: params[:user_id]).account_ownership_verification_email.deliver_now + flash[:success] = "Email Verification Mailer sent!" + redirect_back(fallback_location: internal_users_path) + else + flash[:danger] = "Email failed to send!" + end + end + + private + + def manage_credits + add_credits if user_params[:add_credits] + add_org_credits if user_params[:add_org_credits] + remove_org_credits if user_params[:remove_org_credits] + remove_credits if user_params[:remove_credits] + end + + def add_note + Note.create( + author_id: current_user.id, + noteable_id: @user.id, + noteable_type: "User", + reason: "misc_note", + content: user_params[:new_note], + ) + end + + def add_credits + amount = user_params[:add_credits].to_i + Credit.add_to(@user, amount) + end + + def remove_credits + amount = user_params[:remove_credits].to_i + Credit.remove_from(@user, amount) + end + + def add_org_credits + org = Organization.find(user_params[:organization_id]) + amount = user_params[:add_org_credits].to_i + Credit.add_to(org, amount) + end + + def remove_org_credits + org = Organization.find(user_params[:organization_id]) + amount = user_params[:remove_org_credits].to_i + Credit.remove_from(org, amount) + end + + def user_params + allowed_params = %i[ + new_note note_for_current_role user_status + pro merge_user_id add_credits remove_credits + add_org_credits remove_org_credits ghostify + organization_id identity_id backup_data_id + ] + params.require(:user).permit(allowed_params) + end end end diff --git a/app/controllers/internal/webhook_endpoints_controller.rb b/app/controllers/internal/webhook_endpoints_controller.rb index be8d5e56f..5be28045c 100644 --- a/app/controllers/internal/webhook_endpoints_controller.rb +++ b/app/controllers/internal/webhook_endpoints_controller.rb @@ -1,9 +1,11 @@ -class Internal::WebhookEndpointsController < Internal::ApplicationController - layout "internal" +module Internal + class WebhookEndpointsController < Internal::ApplicationController + layout "internal" - def index - @endpoints = Webhook::Endpoint.includes(:user). - page(params[:page]).per(50). - order("created_at desc") + def index + @endpoints = Webhook::Endpoint.includes(:user). + page(params[:page]).per(50). + order("created_at desc") + end end end diff --git a/app/controllers/internal/welcome_controller.rb b/app/controllers/internal/welcome_controller.rb index 166d826e4..022beeefa 100644 --- a/app/controllers/internal/welcome_controller.rb +++ b/app/controllers/internal/welcome_controller.rb @@ -1,34 +1,36 @@ -class Internal::WelcomeController < Internal::ApplicationController - layout "internal" +module Internal + class WelcomeController < Internal::ApplicationController + layout "internal" - def index - @daily_threads = Article.where("title LIKE 'Welcome Thread - %'") - end + def index + @daily_threads = Article.where("title LIKE 'Welcome Thread - %'") + end - def create - welcome_thread = Article.create( - body_markdown: welcome_thread_content, - user: User.dev_account, - ) - redirect_to URI.parse(welcome_thread.path).path + "/edit" - end + def create + welcome_thread = Article.create( + body_markdown: welcome_thread_content, + user: User.dev_account, + ) + redirect_to URI.parse(welcome_thread.path).path + "/edit" + end - private + private - def welcome_thread_content - <<~HEREDOC - --- - title: Welcome Thread - v0 - published: false - description: Introduce yourself to the community! - tags: welcome - --- + def welcome_thread_content + <<~HEREDOC + --- + title: Welcome Thread - v0 + published: false + description: Introduce yourself to the community! + tags: welcome + --- - Hey there! Welcome to #{ApplicationConfig['COMMUNITY_NAME']}! + Hey there! Welcome to #{ApplicationConfig['COMMUNITY_NAME']}! - ![WELCOME TO THE INTERNET](https://slack-imgs.com/?c=1&url=http%3A%2F%2Fmedia0.giphy.com%2Fmedia%2FzhbrTTpmSCYog%2Fgiphy-downsized.gif) + ![WELCOME TO THE INTERNET](https://slack-imgs.com/?c=1&url=http%3A%2F%2Fmedia0.giphy.com%2Fmedia%2FzhbrTTpmSCYog%2Fgiphy-downsized.gif) - Leave a comment below to introduce yourself to the community!✌️ - HEREDOC + Leave a comment below to introduce yourself to the community!✌️ + HEREDOC + end end end diff --git a/app/controllers/notifications/counts_controller.rb b/app/controllers/notifications/counts_controller.rb index 161b49328..b020d235b 100644 --- a/app/controllers/notifications/counts_controller.rb +++ b/app/controllers/notifications/counts_controller.rb @@ -1,6 +1,8 @@ -class Notifications::CountsController < ApplicationController - def index - count = current_user ? current_user.notifications.unread.count : 0 - render plain: count.to_s +module Notifications + class CountsController < ApplicationController + def index + count = current_user ? current_user.notifications.unread.count : 0 + render plain: count.to_s + end end end diff --git a/app/controllers/notifications/reads_controller.rb b/app/controllers/notifications/reads_controller.rb index 2e3e32c14..8ecff2dfa 100644 --- a/app/controllers/notifications/reads_controller.rb +++ b/app/controllers/notifications/reads_controller.rb @@ -1,15 +1,17 @@ -class Notifications::ReadsController < ApplicationController - def create - render plain: "" && return unless current_user +module Notifications + class ReadsController < ApplicationController + def create + render plain: "" && return unless current_user - current_user.notifications.unread.update_all(read: true) - current_user.touch(:last_notification_activity) + current_user.notifications.unread.update_all(read: true) + current_user.touch(:last_notification_activity) - if params[:org_id] && current_user.org_member?(params[:org_id]) - org = Organization.find_by(id: params[:org_id]) - org.notifications.unread.update_all(read: true) + if params[:org_id] && current_user.org_member?(params[:org_id]) + org = Organization.find_by(id: params[:org_id]) + org.notifications.unread.update_all(read: true) + end + + render plain: "read" end - - render plain: "read" end end diff --git a/app/controllers/stories/feeds_controller.rb b/app/controllers/stories/feeds_controller.rb index e249fbf13..bf83d113d 100644 --- a/app/controllers/stories/feeds_controller.rb +++ b/app/controllers/stories/feeds_controller.rb @@ -1,52 +1,54 @@ -class Stories::FeedsController < ApplicationController - respond_to :json +module Stories + class FeedsController < ApplicationController + respond_to :json - VARIANTS = { - "more_random_experiment" => :default_home_feed_with_more_randomness_experiment, - "mix_base_more_random_experiment" => :mix_default_and_more_random_experiment, - "more_tag_weight_experiment" => :more_tag_weight_experiment, - "more_tag_weight_more_random_experiment" => :more_tag_weight_more_random_experiment, - "more_comments_experiment" => :more_comments_experiment, - "more_experience_level_weight_experiment" => :more_experience_level_weight_experiment, - "more_tag_weight_randomized_at_end_experiment" => :more_tag_weight_randomized_at_end_experiment, - "more_experience_level_weight_randomized_at_end_experiment" => - :more_experience_level_weight_randomized_at_end_experiment, - "more_comments_randomized_at_end_experiment" => :more_comments_randomized_at_end_experiment, - "more_comments_medium_weight_randomized_at_end_experiment" => - :more_comments_medium_weight_randomized_at_end_experiment, - "more_comments_minimal_weight_randomized_at_end_experiment" => - :more_comments_minimal_weight_randomized_at_end_experiment, - "mix_of_everything_experiment" => :mix_of_everything_experiment - }.freeze + VARIANTS = { + "more_random_experiment" => :default_home_feed_with_more_randomness_experiment, + "mix_base_more_random_experiment" => :mix_default_and_more_random_experiment, + "more_tag_weight_experiment" => :more_tag_weight_experiment, + "more_tag_weight_more_random_experiment" => :more_tag_weight_more_random_experiment, + "more_comments_experiment" => :more_comments_experiment, + "more_experience_level_weight_experiment" => :more_experience_level_weight_experiment, + "more_tag_weight_randomized_at_end_experiment" => :more_tag_weight_randomized_at_end_experiment, + "more_experience_level_weight_randomized_at_end_experiment" => + :more_experience_level_weight_randomized_at_end_experiment, + "more_comments_randomized_at_end_experiment" => :more_comments_randomized_at_end_experiment, + "more_comments_medium_weight_randomized_at_end_experiment" => + :more_comments_medium_weight_randomized_at_end_experiment, + "more_comments_minimal_weight_randomized_at_end_experiment" => + :more_comments_minimal_weight_randomized_at_end_experiment, + "mix_of_everything_experiment" => :mix_of_everything_experiment + }.freeze - def show - @stories = assign_feed_stories - end + def show + @stories = assign_feed_stories + end - private + private - def assign_feed_stories - feed = Articles::Feed.new(user: current_user, page: @page, tag: params[:tag]) - stories = if params[:timeframe].in?(Timeframer::FILTER_TIMEFRAMES) - feed.top_articles_by_timeframe(timeframe: params[:timeframe]) - elsif params[:timeframe] == Timeframer::LATEST_TIMEFRAME - feed.latest_feed - elsif user_signed_in? - ab_test_user_signed_in_feed(feed) - else - feed.default_home_feed(user_signed_in: user_signed_in?) - end - ArticleDecorator.decorate_collection(stories) - end + def assign_feed_stories + feed = Articles::Feed.new(user: current_user, page: @page, tag: params[:tag]) + stories = if params[:timeframe].in?(Timeframer::FILTER_TIMEFRAMES) + feed.top_articles_by_timeframe(timeframe: params[:timeframe]) + elsif params[:timeframe] == Timeframer::LATEST_TIMEFRAME + feed.latest_feed + elsif user_signed_in? + ab_test_user_signed_in_feed(feed) + else + feed.default_home_feed(user_signed_in: user_signed_in?) + end + ArticleDecorator.decorate_collection(stories) + end - def ab_test_user_signed_in_feed(feed) - test_variant = field_test(:user_home_feed, participant: current_user) - Honeycomb.add_field("field_test_user_home_feed", test_variant) # Monitoring different variants + def ab_test_user_signed_in_feed(feed) + test_variant = field_test(:user_home_feed, participant: current_user) + Honeycomb.add_field("field_test_user_home_feed", test_variant) # Monitoring different variants - if VARIANTS[test_variant].nil? || test_variant == "base" - feed.default_home_feed(user_signed_in: true) - else - feed.public_send(VARIANTS[test_variant]) + if VARIANTS[test_variant].nil? || test_variant == "base" + feed.default_home_feed(user_signed_in: true) + else + feed.public_send(VARIANTS[test_variant]) + end end end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b3a2b84ef..4b8256637 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -19,6 +19,7 @@ module ApplicationHelper "#{controller_name}-#{controller.action_name}" end + # rubocop:disable Rails/HelperInstanceVariable def view_class if @podcast_episode_show # custom due to edge cases "stories stories-show podcast_episodes-show" @@ -28,6 +29,7 @@ module ApplicationHelper "#{controller_name} #{controller_name}-#{controller.action_name}" end end + # rubocop:enable Rails/HelperInstanceVariable def title(page_title) derived_title = if page_title.include?(community_name) @@ -164,7 +166,7 @@ module ApplicationHelper end def community_name - @community_name ||= ApplicationConfig["COMMUNITY_NAME"] + @community_name ||= ApplicationConfig["COMMUNITY_NAME"] # rubocop:disable Rails/HelperInstanceVariable end def community_qualified_name diff --git a/app/models/ahoy/event.rb b/app/models/ahoy/event.rb index 4c3125b53..3620cc0f0 100644 --- a/app/models/ahoy/event.rb +++ b/app/models/ahoy/event.rb @@ -1,8 +1,10 @@ -class Ahoy::Event < ApplicationRecord - include Ahoy::QueryMethods +module Ahoy + class Event < ApplicationRecord + include Ahoy::QueryMethods - self.table_name = "ahoy_events" + self.table_name = "ahoy_events" - belongs_to :visit - belongs_to :user, optional: true + belongs_to :visit + belongs_to :user, optional: true + end end diff --git a/app/models/ahoy/visit.rb b/app/models/ahoy/visit.rb index 66f89e5d5..e528a6f50 100644 --- a/app/models/ahoy/visit.rb +++ b/app/models/ahoy/visit.rb @@ -1,6 +1,8 @@ -class Ahoy::Visit < ApplicationRecord - self.table_name = "ahoy_visits" +module Ahoy + class Visit < ApplicationRecord + self.table_name = "ahoy_visits" - has_many :events, class_name: "Ahoy::Event" - belongs_to :user, optional: true + has_many :events, class_name: "Ahoy::Event" + belongs_to :user, optional: true + end end diff --git a/app/models/role.rb b/app/models/role.rb index 08e454fed..27aa67553 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -17,7 +17,7 @@ class Role < ApplicationRecord workshop_pass ].freeze - has_and_belongs_to_many :users, join_table: :users_roles + has_and_belongs_to_many :users, join_table: :users_roles # rubocop:disable Rails/HasAndBelongsToMany belongs_to :resource, polymorphic: true, optional: true diff --git a/config/initializers/ahoy.rb b/config/initializers/ahoy.rb index b46c0ea86..ec007726b 100644 --- a/config/initializers/ahoy.rb +++ b/config/initializers/ahoy.rb @@ -1,4 +1,6 @@ -class Ahoy::Store < Ahoy::DatabaseStore +module Ahoy + class Store < Ahoy::DatabaseStore + end end # set to true to mask ip addresses diff --git a/config/initializers/rack/attack.rb b/config/initializers/rack/attack.rb index fbcfea918..1cc021eee 100644 --- a/config/initializers/rack/attack.rb +++ b/config/initializers/rack/attack.rb @@ -1,44 +1,46 @@ Rack::Attack.throttled_response_retry_after_header = true -class Rack::Attack - throttle("search_throttle", limit: 5, period: 1) do |request| - if request.path.starts_with?("/search/") - track_and_return_ip(request.env["HTTP_FASTLY_CLIENT_IP"]) - end - end - - throttle("api_throttle", limit: 3, period: 1) do |request| - if request.path.starts_with?("/api/") && request.get? - track_and_return_ip(request.env["HTTP_FASTLY_CLIENT_IP"]) - end - end - - throttle("api_write_throttle", limit: 1, period: 1) do |request| - if request.path.starts_with?("/api/") && (request.put? || request.post? || request.delete?) - Honeycomb.add_field("user_api_key", request.env["HTTP_API_KEY"]) - ip_address = track_and_return_ip(request.env["HTTP_FASTLY_CLIENT_IP"]) - if request.env["HTTP_API_KEY"].present? - "#{ip_address}-#{request.env['HTTP_API_KEY']}" - elsif ip_address.present? - ip_address +module Rack + class Attack + throttle("search_throttle", limit: 5, period: 1) do |request| + if request.path.starts_with?("/search/") + track_and_return_ip(request.env["HTTP_FASTLY_CLIENT_IP"]) end end - end - throttle("site_hits", limit: 40, period: 2) do |request| - track_and_return_ip(request.env["HTTP_FASTLY_CLIENT_IP"]) - end + throttle("api_throttle", limit: 3, period: 1) do |request| + if request.path.starts_with?("/api/") && request.get? + track_and_return_ip(request.env["HTTP_FASTLY_CLIENT_IP"]) + end + end - throttle("message_throttle", limit: 2, period: 1) do |request| - if request.path.starts_with?("/messages") && request.post? + throttle("api_write_throttle", limit: 1, period: 1) do |request| + if request.path.starts_with?("/api/") && (request.put? || request.post? || request.delete?) + Honeycomb.add_field("user_api_key", request.env["HTTP_API_KEY"]) + ip_address = track_and_return_ip(request.env["HTTP_FASTLY_CLIENT_IP"]) + if request.env["HTTP_API_KEY"].present? + "#{ip_address}-#{request.env['HTTP_API_KEY']}" + elsif ip_address.present? + ip_address + end + end + end + + throttle("site_hits", limit: 40, period: 2) do |request| track_and_return_ip(request.env["HTTP_FASTLY_CLIENT_IP"]) end - end - def self.track_and_return_ip(ip_address) - return if ip_address.blank? + throttle("message_throttle", limit: 2, period: 1) do |request| + if request.path.starts_with?("/messages") && request.post? + track_and_return_ip(request.env["HTTP_FASTLY_CLIENT_IP"]) + end + end - Honeycomb.add_field("fastly_client_ip", ip_address) - ip_address.to_s + def self.track_and_return_ip(ip_address) + return if ip_address.blank? + + Honeycomb.add_field("fastly_client_ip", ip_address) + ip_address.to_s + end end end diff --git a/spec/initializers/rack/attack_spec.rb b/spec/initializers/rack/attack_spec.rb index ae4fd93e7..ff037d008 100644 --- a/spec/initializers/rack/attack_spec.rb +++ b/spec/initializers/rack/attack_spec.rb @@ -48,12 +48,18 @@ describe Rack::Attack, type: :request, throttle: true do describe "api_write_throttle" do let(:api_secret) { create(:api_secret) } let(:another_api_secret) { create(:api_secret) } + let(:headers) do + { "api-key" => api_secret.secret, "content-type" => "application/json", "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" } + end + let(:dif_headers) do + { + "api-key" => another_api_secret.secret, + "content-type" => "application/json", + "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" + } + end it "throttles api write endpoints based on IP and API key" do - headers = { "api-key" => api_secret.secret, "content-type" => "application/json", - "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" } - dif_headers = { "api-key" => another_api_secret.secret, "content-type" => "application/json", - "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" } params = { article: { body_markdown: "", title: Faker::Book.title } }.to_json Timecop.freeze do diff --git a/spec/liquid_tags/user_subscription_tag_spec.rb b/spec/liquid_tags/user_subscription_tag_spec.rb index 3161a8eaa..24377be0e 100644 --- a/spec/liquid_tags/user_subscription_tag_spec.rb +++ b/spec/liquid_tags/user_subscription_tag_spec.rb @@ -5,7 +5,9 @@ RSpec.describe UserSubscriptionTag, type: :liquid_tag do let(:subscriber) { create(:user) } let(:author) { create(:user) } - let(:article_with_user_subscription_tag) { create(:article, :with_user_subscription_tag_role_user, with_user_subscription_tag: true) } + let(:article_with_user_subscription_tag) do + create(:article, :with_user_subscription_tag_role_user, with_user_subscription_tag: true) + end # Stub roles because adding them normally can cause flaky specs before do @@ -76,6 +78,7 @@ RSpec.describe UserSubscriptionTag, type: :liquid_tag do end end + # rubocop:disable RSpec/ExampleLength it "displays errors when there's an error creating a subscription" do # Create a subscription so it causes an error by already being subscribed create( @@ -98,6 +101,7 @@ RSpec.describe UserSubscriptionTag, type: :liquid_tag do expect(page).to have_text("Subscriber has already been taken") end end + # rubocop:enable RSpec/ExampleLength it "tells the user they're already subscribed by default if they're already subscribed" do create( diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb index bbe63a949..1d67e4f34 100644 --- a/spec/models/article_spec.rb +++ b/spec/models/article_spec.rb @@ -94,7 +94,7 @@ RSpec.describe Article, type: :model do context "when published" do before do # rubocop:disable RSpec/NamedSubject - allow(subject).to receive(:published?).and_return(true) + allow(subject).to receive(:published?).and_return(true) # rubocop:disable RSpec/SubjectStub # rubocop:enable RSpec/NamedSubject end diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index cf3f3d456..b44f3e54e 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -122,6 +122,7 @@ RSpec.describe Comment, type: :model do expect(comment.processed_html.size < 450).to be(true) end + # rubocop:disable RSpec/ExampleLength it "adds timestamp url if commentable has video and timestamp", :aggregate_failures do article.video = "https://example.com" @@ -146,6 +147,7 @@ RSpec.describe Comment, type: :model do expect(comment.processed_html.include?(">1:52:30")).to eq(true) expect(comment.processed_html.include?(">1:20")).to eq(true) end + # rubocop:enable RSpec/ExampleLength it "does not add timestamp if commentable does not have video" do article.video = nil diff --git a/spec/requests/display_ad_events_spec.rb b/spec/requests/display_ad_events_spec.rb index 227ea315d..acc222676 100644 --- a/spec/requests/display_ad_events_spec.rb +++ b/spec/requests/display_ad_events_spec.rb @@ -34,22 +34,14 @@ RSpec.describe "DisplayAdEvents", type: :request do end it "creates a display ad success rate" do + ad_event_params = { display_ad_id: display_ad.id, context_type: "home" } + 4.times do - post "/display_ad_events", params: { - display_ad_event: { - display_ad_id: display_ad.id, - context_type: "home", - category: "impression" - } - } + post "/display_ad_events", params: { display_ad_event: ad_event_params.merge(category: "impression") } end - post "/display_ad_events", params: { - display_ad_event: { - display_ad_id: display_ad.id, - context_type: "home", - category: "click" - } - } + + post "/display_ad_events", params: { display_ad_event: ad_event_params.merge(category: "click") } + expect(display_ad.reload.success_rate).to eq(0.25) end diff --git a/spec/requests/internal/configs_spec.rb b/spec/requests/internal/configs_spec.rb index 3ec39a37b..b9f56dc65 100644 --- a/spec/requests/internal/configs_spec.rb +++ b/spec/requests/internal/configs_spec.rb @@ -204,14 +204,18 @@ RSpec.describe "/internal/config", type: :request do end it "updates left_navbar_svg_icon" do - expected_svg = "" - post "/internal/config", params: { site_config: { left_navbar_svg_icon: expected_svg }, confirmation: confirmation_message } + expected_svg = "" + post "/internal/config", params: { site_config: { left_navbar_svg_icon: expected_svg }, + confirmation: confirmation_message } expect(SiteConfig.left_navbar_svg_icon).to eq(expected_svg) end it "updates right_navbar_svg_icon" do - expected_svg = "" - post "/internal/config", params: { site_config: { right_navbar_svg_icon: expected_svg }, confirmation: confirmation_message } + expected_svg = "" + post "/internal/config", params: { site_config: { right_navbar_svg_icon: expected_svg }, + confirmation: confirmation_message } expect(SiteConfig.right_navbar_svg_icon).to eq(expected_svg) end