Add Settings::Mascot (#13451)
* Add Settings::Mascot * Add DUS * Update usage * Fix e2e test and controller * Fix specs * Fix remaining spec
This commit is contained in:
parent
62542a35ab
commit
f2f5e911cf
35 changed files with 353 additions and 128 deletions
34
app/controllers/admin/settings/mascots_controller.rb
Normal file
34
app/controllers/admin/settings/mascots_controller.rb
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
module Admin
|
||||
module Settings
|
||||
class MascotsController < Admin::ApplicationController
|
||||
def create
|
||||
errors = upsert_config(settings_params)
|
||||
|
||||
if errors.none?
|
||||
Audit::Logger.log(:internal, current_user, params.dup)
|
||||
redirect_to admin_config_path, notice: "Site configuration was successfully updated."
|
||||
else
|
||||
redirect_to admin_config_path, alert: "😭 #{errors.to_sentence}"
|
||||
end
|
||||
end
|
||||
|
||||
def settings_params
|
||||
params
|
||||
.require(:settings_mascot)
|
||||
.permit(*::Settings::Mascot.keys)
|
||||
end
|
||||
|
||||
def upsert_config(configs)
|
||||
errors = []
|
||||
configs.each do |key, value|
|
||||
::Settings::Mascot.public_send("#{key}=", value) if value.present?
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
errors << e.message
|
||||
next
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -57,10 +57,10 @@ class ChatChannelsController < ApplicationController
|
|||
flash[:error] = chat_channel.errors.full_messages.to_sentence
|
||||
else
|
||||
if chat_channel_params[:discoverable].to_i.zero?
|
||||
ChatChannelMembership.create(user_id: SiteConfig.mascot_user_id, chat_channel_id: chat_channel.id,
|
||||
ChatChannelMembership.create(user_id: Settings::Mascot.mascot_user_id, chat_channel_id: chat_channel.id,
|
||||
role: "member", status: "active")
|
||||
else
|
||||
ChatChannelMembership.find_by(user_id: SiteConfig.mascot_user_id)&.destroy
|
||||
ChatChannelMembership.find_by(user_id: Settings::Mascot.mascot_user_id)&.destroy
|
||||
end
|
||||
flash[:settings_notice] = "Channel settings updated."
|
||||
end
|
||||
|
|
@ -76,10 +76,10 @@ class ChatChannelsController < ApplicationController
|
|||
message: "Channel settings updation failed. Try again later." }, success: :bad_request
|
||||
else
|
||||
if chat_channel_params[:discoverable]
|
||||
ChatChannelMembership.create(user_id: SiteConfig.mascot_user_id, chat_channel_id: @chat_channel.id,
|
||||
ChatChannelMembership.create(user_id: Settings::Mascot.mascot_user_id, chat_channel_id: @chat_channel.id,
|
||||
role: "member", status: "active")
|
||||
else
|
||||
ChatChannelMembership.find_by(user_id: SiteConfig.mascot_user_id)&.destroy
|
||||
ChatChannelMembership.find_by(user_id: Settings::Mascot.mascot_user_id)&.destroy
|
||||
end
|
||||
render json: { success: true, message: "Channel settings updated.", data: {} }, success: :ok
|
||||
end
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ class CommentsController < ApplicationController
|
|||
response_template = ResponseTemplate.find(params[:response_template][:id])
|
||||
authorize response_template, :moderator_create?
|
||||
|
||||
moderator = User.find(SiteConfig.mascot_user_id)
|
||||
moderator = User.find(Settings::Mascot.mascot_user_id)
|
||||
@comment = Comment.new(permitted_attributes(Comment))
|
||||
@comment.user_id = moderator.id
|
||||
@comment.body_markdown = response_template.content
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ class SearchController < ApplicationController
|
|||
def chat_channels
|
||||
user_ids =
|
||||
if chat_channel_params[:user_id].present?
|
||||
[current_user.id, SiteConfig.mascot_user_id, chat_channel_params[:user_id]].reject(&:blank?)
|
||||
[current_user.id, Settings::Mascot.mascot_user_id, chat_channel_params[:user_id]].reject(&:blank?)
|
||||
else
|
||||
[current_user.id]
|
||||
end
|
||||
|
|
|
|||
32
app/lib/constants/settings/mascot.rb
Normal file
32
app/lib/constants/settings/mascot.rb
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
module Constants
|
||||
module Settings
|
||||
module Mascot
|
||||
DETAILS = {
|
||||
footer_image_url: {
|
||||
description: "Special cute mascot image used in the footer.",
|
||||
placeholder: ::Constants::SiteConfig::IMAGE_PLACEHOLDER
|
||||
},
|
||||
footer_image_width: {
|
||||
description: "The footer mascot width will resized to this value, defaults to 52",
|
||||
placeholder: ""
|
||||
},
|
||||
footer_image_height: {
|
||||
description: "The footer mascot height will be resized to this value, defaults to 120",
|
||||
placeholder: ""
|
||||
},
|
||||
image_description: {
|
||||
description: "Used as the alt text for the mascot image",
|
||||
placeholder: ""
|
||||
},
|
||||
image_url: {
|
||||
description: "Used as the mascot image.",
|
||||
placeholder: ::Constants::SiteConfig::IMAGE_PLACEHOLDER
|
||||
},
|
||||
mascot_user_id: {
|
||||
description: "User ID of the Mascot account",
|
||||
placeholder: "1"
|
||||
}
|
||||
}.freeze
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -118,30 +118,6 @@ module Constants
|
|||
description: "Community Moderators Newsletter ID",
|
||||
placeholder: ""
|
||||
},
|
||||
mascot_footer_image_url: {
|
||||
description: "Special cute mascot image used in the footer.",
|
||||
placeholder: IMAGE_PLACEHOLDER
|
||||
},
|
||||
mascot_footer_image_width: {
|
||||
description: "The footer mascot width will resized to this value, defaults to 52",
|
||||
placeholder: ""
|
||||
},
|
||||
mascot_footer_image_height: {
|
||||
description: "The footer mascot height will be resized to this value, defaults to 120",
|
||||
placeholder: ""
|
||||
},
|
||||
mascot_image_description: {
|
||||
description: "Used as the alt text for the mascot image",
|
||||
placeholder: ""
|
||||
},
|
||||
mascot_image_url: {
|
||||
description: "Used as the mascot image.",
|
||||
placeholder: IMAGE_PLACEHOLDER
|
||||
},
|
||||
mascot_user_id: {
|
||||
description: "User ID of the Mascot account",
|
||||
placeholder: "1"
|
||||
},
|
||||
meta_keywords: {
|
||||
description: "",
|
||||
placeholder: "List of valid keywords: comma separated, letters only e.g. engineering, development"
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ class Article < ApplicationRecord
|
|||
published
|
||||
.where(user_id: User.with_role(:super_admin)
|
||||
.union(User.with_role(:admin))
|
||||
.union(id: [SiteConfig.staff_user_id, SiteConfig.mascot_user_id].compact)
|
||||
.union(id: [SiteConfig.staff_user_id, Settings::Mascot.mascot_user_id].compact)
|
||||
.select(:id)).order(published_at: :desc).tagged_with(tag_name)
|
||||
}
|
||||
|
||||
|
|
@ -792,7 +792,7 @@ class Article < ApplicationRecord
|
|||
return unless SiteConfig.spam_trigger_terms.any? { |term| Regexp.new(term.downcase).match?(title.downcase) }
|
||||
|
||||
Reaction.create(
|
||||
user_id: SiteConfig.mascot_user_id,
|
||||
user_id: Settings::Mascot.mascot_user_id,
|
||||
reactable_id: id,
|
||||
reactable_type: "Article",
|
||||
category: "vomit",
|
||||
|
|
@ -802,7 +802,7 @@ class Article < ApplicationRecord
|
|||
|
||||
user.add_role(:suspended)
|
||||
Note.create(
|
||||
author_id: SiteConfig.mascot_user_id,
|
||||
author_id: Settings::Mascot.mascot_user_id,
|
||||
noteable_id: user_id,
|
||||
noteable_type: "User",
|
||||
reason: "automatic_suspend",
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ class Comment < ApplicationRecord
|
|||
user.registered_at > 5.days.ago
|
||||
|
||||
Reaction.create(
|
||||
user_id: SiteConfig.mascot_user_id,
|
||||
user_id: Settings::Mascot.mascot_user_id,
|
||||
reactable_id: id,
|
||||
reactable_type: "Comment",
|
||||
category: "vomit",
|
||||
|
|
@ -297,7 +297,7 @@ class Comment < ApplicationRecord
|
|||
|
||||
user.add_role(:suspended)
|
||||
Note.create(
|
||||
author_id: SiteConfig.mascot_user_id,
|
||||
author_id: Settings::Mascot.mascot_user_id,
|
||||
noteable_id: user_id,
|
||||
noteable_type: "User",
|
||||
reason: "automatic_suspend",
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ class Reaction < ApplicationRecord
|
|||
end
|
||||
|
||||
def negative_reaction_from_untrusted_user?
|
||||
return if user&.any_admin? || user&.id == SiteConfig.mascot_user_id
|
||||
return if user&.any_admin? || user&.id == Settings::Mascot.mascot_user_id
|
||||
|
||||
negative? && !user.trusted
|
||||
end
|
||||
|
|
|
|||
25
app/models/settings/mascot.rb
Normal file
25
app/models/settings/mascot.rb
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
module Settings
|
||||
class Mascot < RailsSettings::Base
|
||||
self.table_name = :settings_mascots
|
||||
|
||||
# The configuration is cached, change this if you want to force update
|
||||
# the cache, or call Settings::Mascot.clear_cache
|
||||
cache_prefix { "v1" }
|
||||
|
||||
field :footer_image_height, type: :integer, default: 120
|
||||
field :footer_image_url, type: :string, validates: { url: true }
|
||||
field :footer_image_width, type: :integer, default: 52
|
||||
field :image_description, type: :string, default: "The community mascot"
|
||||
field :image_url,
|
||||
type: :string,
|
||||
default: proc { URL.local_image("mascot.png") },
|
||||
validates: { url: true }
|
||||
field :mascot_user_id, type: :integer, default: nil
|
||||
|
||||
# NOTE: @citizen428 - This is duplicated for now, I will refactor once
|
||||
# all settings models have been extracted.
|
||||
def self.get_default(field)
|
||||
get_field(field)[:default]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -312,7 +312,7 @@ class User < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.mascot_account
|
||||
find_by(id: SiteConfig.mascot_user_id)
|
||||
find_by(id: Settings::Mascot.mascot_user_id)
|
||||
end
|
||||
|
||||
def tag_line
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module Authentication
|
|||
}
|
||||
|
||||
if Rails.env.test?
|
||||
user_data[:profile_image] = SiteConfig.mascot_image_url
|
||||
user_data[:profile_image] = Settings::Mascot.image_url
|
||||
else
|
||||
user_data[:remote_profile_image_url] = Users::ProfileImageGenerator.call
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module Users
|
|||
email: "mascot@forem.com",
|
||||
username: "mascot",
|
||||
name: "Mascot",
|
||||
profile_image: SiteConfig.mascot_image_url,
|
||||
profile_image: Settings::Mascot.image_url,
|
||||
confirmed_at: Time.current,
|
||||
registered_at: Time.current,
|
||||
password: SecureRandom.hex
|
||||
|
|
@ -15,10 +15,10 @@ module Users
|
|||
end
|
||||
|
||||
def call
|
||||
raise "Mascot already set" if SiteConfig.mascot_user_id
|
||||
raise "Mascot already set" if Settings::Mascot.mascot_user_id
|
||||
|
||||
mascot = User.create!(mascot_params)
|
||||
SiteConfig.mascot_user_id = mascot.id
|
||||
Settings::Mascot.mascot_user_id = mascot.id
|
||||
end
|
||||
|
||||
def mascot_params
|
||||
|
|
|
|||
|
|
@ -768,7 +768,7 @@
|
|||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= form_for(SiteConfig.new, url: admin_config_path) do |f| %>
|
||||
<%= form_for(Settings::Mascot.new, url: admin_settings_mascots_path, html: { data: { testid: "mascotSectionForm" } }) do |f| %>
|
||||
<div class="card mt-3">
|
||||
<%= render partial: "admin/shared/card_header",
|
||||
locals: {
|
||||
|
|
@ -780,64 +780,64 @@
|
|||
<div id="mascotBodyContainer" class="card-body collapse hide" aria-labelledby="mascotBodyContainer">
|
||||
<fieldset class="grid gap-4">
|
||||
<div class="crayons-field">
|
||||
<%= admin_config_label :mascot_user_id, "Mascot user ID" %>
|
||||
<%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_user_id][:description] %>
|
||||
<%= admin_config_label :mascot_user_id, "Mascot user ID", model: Settings::Mascot %>
|
||||
<%= admin_config_description Constants::Settings::Mascot::DETAILS[:mascot_user_id][:description] %>
|
||||
<%= f.text_field :mascot_user_id,
|
||||
class: "crayons-textfield",
|
||||
value: SiteConfig.mascot_user_id,
|
||||
value: Settings::Mascot.mascot_user_id,
|
||||
min: 1,
|
||||
placeholder: Constants::SiteConfig::DETAILS[:mascot_user_id][:placeholder] %>
|
||||
placeholder: Constants::Settings::Mascot::DETAILS[:mascot_user_id][:placeholder] %>
|
||||
</div>
|
||||
|
||||
<div class="crayons-field">
|
||||
<%= admin_config_label :mascot_image_url, "Mascot Image URL" %>
|
||||
<%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_image_url][:description] %>
|
||||
<%= f.text_field :mascot_image_url,
|
||||
<%= admin_config_label :image_url, "Mascot Image URL", model: Settings::Mascot %>
|
||||
<%= admin_config_description Constants::Settings::Mascot::DETAILS[:image_url][:description] %>
|
||||
<%= f.text_field :image_url,
|
||||
class: "crayons-textfield",
|
||||
value: SiteConfig.mascot_image_url,
|
||||
placeholder: Constants::SiteConfig::DETAILS[:mascot_image_url][:placeholder] %>
|
||||
value: Settings::Mascot.image_url,
|
||||
placeholder: Constants::Settings::Mascot::DETAILS[:image_url][:placeholder] %>
|
||||
|
||||
<div class="col-12">
|
||||
<img alt="<%= SiteConfig.mascot_image_description %>" class="img-fluid" src="<%= SiteConfig.mascot_image_url %>" />
|
||||
<img alt="<%= Settings::Mascot.image_description %>" class="img-fluid" src="<%= Settings::Mascot.image_url %>" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="crayons-field">
|
||||
<%= admin_config_label :mascot_footer_image_url %>
|
||||
<%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_footer_image_url][:description] %>
|
||||
<%= f.text_field :mascot_footer_image_url,
|
||||
<%= admin_config_label :footer_image_url, model: Settings::Mascot %>
|
||||
<%= admin_config_description Constants::Settings::Mascot::DETAILS[:footer_image_url][:description] %>
|
||||
<%= f.text_field :footer_image_url,
|
||||
class: "crayons-textfield",
|
||||
value: SiteConfig.mascot_footer_image_url,
|
||||
placeholder: Constants::SiteConfig::DETAILS[:mascot_footer_image_url][:placeholder] %>
|
||||
value: Settings::Mascot.footer_image_url,
|
||||
placeholder: Constants::Settings::Mascot::DETAILS[:footer_image_url][:placeholder] %>
|
||||
|
||||
<div class="col-12">
|
||||
<img alt="<%= SiteConfig.mascot_image_description %>" class="img-fluid" src="<%= SiteConfig.mascot_footer_image_url %>" />
|
||||
<img alt="<%= Settings::Mascot.image_description %>" class="img-fluid" src="<%= Settings::Mascot.footer_image_url %>" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="crayons-field">
|
||||
<%= admin_config_label :mascot_footer_image_width %>
|
||||
<%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_footer_image_width][:description] %>
|
||||
<%= f.text_field :mascot_footer_image_width,
|
||||
<%= admin_config_label :footer_image_width, model: Settings::Mascot %>
|
||||
<%= admin_config_description Constants::Settings::Mascot::DETAILS[:footer_image_width][:description] %>
|
||||
<%= f.text_field :footer_image_width,
|
||||
class: "form-control",
|
||||
value: SiteConfig.mascot_footer_image_width %>
|
||||
value: Settings::Mascot.footer_image_width %>
|
||||
</div>
|
||||
|
||||
<div class="crayons-field">
|
||||
<%= admin_config_label :mascot_footer_image_height %>
|
||||
<%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_footer_image_height][:description] %>
|
||||
<%= f.text_field :mascot_footer_image_height,
|
||||
<%= admin_config_label :footer_image_height, model: Settings::Mascot %>
|
||||
<%= admin_config_description Constants::Settings::Mascot::DETAILS[:footer_image_height][:description] %>
|
||||
<%= f.text_field :footer_image_height,
|
||||
class: "form-control",
|
||||
value: SiteConfig.mascot_footer_image_height %>
|
||||
value: Settings::Mascot.footer_image_height %>
|
||||
</div>
|
||||
|
||||
<div class="crayons-field">
|
||||
<%= admin_config_label :mascot_image_description %>
|
||||
<%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_image_description][:description] %>
|
||||
<%= f.text_field :mascot_image_description,
|
||||
<%= admin_config_label :image_description, model: Settings::Mascot %>
|
||||
<%= admin_config_description Constants::Settings::Mascot::DETAILS[:image_description][:description] %>
|
||||
<%= f.text_field :image_description,
|
||||
class: "form-control",
|
||||
value: SiteConfig.mascot_image_description %>
|
||||
value: Settings::Mascot.image_description %>
|
||||
</div>
|
||||
|
||||
<%= render "form_submission", f: f %>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
data-reaction-url-value="<%= admin_reaction_path(reaction.id) %>">
|
||||
<span>
|
||||
🤢 <a href="<%= reaction.user.path %>" target="_blank" rel="noopener">@<%= reaction.user.username %></a>
|
||||
<% if reaction.user_id == SiteConfig.mascot_user_id %>
|
||||
<% if reaction.user_id == Settings::Mascot.mascot_user_id %>
|
||||
<strong>(auto-generated)</strong>
|
||||
<% end %>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<% if comment.deleted %>
|
||||
<span class="shrink-0 crayons-avatar <% if comment.depth == 0 %>m:crayons-avatar--l mt-4 m:mt-3<% else %>mt-4<% end %>">
|
||||
<%= image_tag(Images::Optimizer.call(SiteConfig.mascot_image_url, width: 32, height: 32, crop: "imagga_scale"), class: "crayons-avatar__image overflow-hidden", alt: "Sloan, the sloth mascot", loading: "lazy") %>
|
||||
<%= image_tag(Images::Optimizer.call(Settings::Mascot.image_url, width: 32, height: 32, crop: "imagga_scale"), class: "crayons-avatar__image overflow-hidden", alt: "Sloan, the sloth mascot", loading: "lazy") %>
|
||||
</span>
|
||||
<% else %>
|
||||
<a href="<%= URL.user(comment.user) %>" class="shrink-0 crayons-avatar <% if comment.depth == 0 %>m:crayons-avatar--l mt-4 m:mt-3<% else %>mt-4<% end %>">
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<% if decorated_comment.low_quality %>
|
||||
<div class="crayons-notice crayons-notice--warning low-quality-comment-marker">
|
||||
<%= image_tag(Images::Optimizer.call(SiteConfig.mascot_image_url, width: 50, height: 50, crop: "imagga_scale"), class: "sloan", alt: "Sloan, the sloth mascot", loading: "lazy") %>
|
||||
<%= image_tag(Images::Optimizer.call(Settings::Mascot.image_url, width: 50, height: 50, crop: "imagga_scale"), class: "sloan", alt: "Sloan, the sloth mascot", loading: "lazy") %>
|
||||
Comment marked as low quality/non-constructive by the community. <a href="/code-of-conduct">View Code of Conduct</a>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@
|
|||
<% else %>
|
||||
<div class="p-6 m:p-9 crayons-card crayons-card--secondary align-center fs-l h-100 flex items-center justify-center flex-1">
|
||||
<div>
|
||||
<% if SiteConfig.mascot_image_url.present? %>
|
||||
<% image_url = Images::Optimizer.call(SiteConfig.mascot_image_url, width: 300, crop: "imagga_scale") %>
|
||||
<%= image_tag(image_url, class: "sloan mb-7", alt: SiteConfig.mascot_image_description.to_s) %>
|
||||
<% if Settings::Mascot.image_url.present? %>
|
||||
<% image_url = Images::Optimizer.call(Settings::Mascot.image_url, width: 300, crop: "imagga_scale") %>
|
||||
<%= image_tag(image_url, class: "sloan mb-7", alt: Settings::Mascot.image_description.to_s) %>
|
||||
<% end %>
|
||||
<p class="mb-6">This is where you can manage your posts, but you haven't written anything yet.</p>
|
||||
<p><a href="/new" class="crayons-btn crayons-btn--l">Write your first post now</a></p>
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@
|
|||
<div><a href="https://www.forem.com" target="_blank" rel="noopener" class="inline-block mt-4"><%= inline_svg_tag("logo-forem.svg", aria: true, class: "crayons-icon crayons-icon--default", title: "Forem logo") %></a></div>
|
||||
</div>
|
||||
</div>
|
||||
<% if SiteConfig.mascot_footer_image_url.present? %>
|
||||
<%= image_tag(Images::Optimizer.call(SiteConfig.mascot_footer_image_url, width: 100),
|
||||
<% if Settings::Mascot.footer_image_url.present? %>
|
||||
<%= image_tag(Images::Optimizer.call(Settings::Mascot.footer_image_url, width: 100),
|
||||
class: "crayons-footer__mascot",
|
||||
alt: SiteConfig.mascot_image_description,
|
||||
width: SiteConfig.mascot_footer_image_width,
|
||||
height: SiteConfig.mascot_footer_image_height,
|
||||
alt: Settings::Mascot.image_description,
|
||||
width: Settings::Mascot.footer_image_width,
|
||||
height: Settings::Mascot.footer_image_height,
|
||||
loading: "lazy") %>
|
||||
<% end %>
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ Rails.application.routes.draw do
|
|||
namespace :settings do
|
||||
resources :authentications, only: [:create]
|
||||
resources :campaigns, only: [:create]
|
||||
resources :mascots, only: [:create]
|
||||
resources :rate_limits, only: [:create]
|
||||
end
|
||||
namespace :users do
|
||||
|
|
|
|||
77
cypress/integration/adminFlows/config/mascotSection.js
Normal file
77
cypress/integration/adminFlows/config/mascotSection.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
describe('Mascot Section', () => {
|
||||
beforeEach(() => {
|
||||
cy.testSetup();
|
||||
cy.fixture('users/adminUser.json').as('user');
|
||||
|
||||
cy.get('@user').then((user) => {
|
||||
cy.loginUser(user);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mascot image setting', () => {
|
||||
it('rejects an invalid image URL', () => {
|
||||
cy.get('@user').then(({ username }) => {
|
||||
cy.visit('/admin/config');
|
||||
cy.findByTestId('mascotSectionForm').as('mascotSectionForm');
|
||||
|
||||
cy.get('@mascotSectionForm').findByText('Mascot').click();
|
||||
cy.get('@mascotSectionForm')
|
||||
.get('#settings_mascot_image_url')
|
||||
.clear()
|
||||
.type('example.com/image.png');
|
||||
|
||||
cy.get('@mascotSectionForm')
|
||||
.findByPlaceholderText('Confirmation text')
|
||||
.type(
|
||||
`My username is @${username} and this action is 100% safe and appropriate.`,
|
||||
);
|
||||
|
||||
cy.get('@mascotSectionForm')
|
||||
.findByText('Update Site Configuration')
|
||||
.click();
|
||||
|
||||
cy.url().should('contains', '/admin/config');
|
||||
|
||||
cy.findByText(
|
||||
'😭 Validation failed: Image url is not a valid URL',
|
||||
).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('accepts a valid image URL', () => {
|
||||
cy.get('@user').then(({ username }) => {
|
||||
cy.visit('/admin/config');
|
||||
cy.findByTestId('mascotSectionForm').as('mascotSectionForm');
|
||||
|
||||
cy.get('@mascotSectionForm').findByText('Mascot').click();
|
||||
cy.get('@mascotSectionForm')
|
||||
.get('#settings_mascot_image_url')
|
||||
.clear()
|
||||
.type('https://example.com/image.png');
|
||||
|
||||
cy.get('@mascotSectionForm')
|
||||
.findByPlaceholderText('Confirmation text')
|
||||
.type(
|
||||
`My username is @${username} and this action is 100% safe and appropriate.`,
|
||||
);
|
||||
|
||||
cy.get('@mascotSectionForm')
|
||||
.findByText('Update Site Configuration')
|
||||
.click();
|
||||
|
||||
cy.url().should('contains', '/admin/config');
|
||||
|
||||
cy.findByText('Site configuration was successfully updated.').should(
|
||||
'be.visible',
|
||||
);
|
||||
|
||||
// Page reloaded so need to get a new reference to the form.
|
||||
cy.get('#new_settings_mascot').as('mascotSectionForm');
|
||||
cy.get('#settings_mascot_image_url').should(
|
||||
'have.value',
|
||||
'https://example.com/image.png',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
16
db/migrate/20210420050243_create_settings_mascots.rb
Normal file
16
db/migrate/20210420050243_create_settings_mascots.rb
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
class CreateSettingsMascots < ActiveRecord::Migration[6.1]
|
||||
def self.up
|
||||
create_table :settings_mascots do |t|
|
||||
t.string :var, null: false
|
||||
t.text :value, null: true
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :settings_mascots, :var, unique: true
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :settings_mascots
|
||||
end
|
||||
end
|
||||
|
|
@ -1082,6 +1082,14 @@ ActiveRecord::Schema.define(version: 2021_04_23_162847) do
|
|||
t.index ["var"], name: "index_settings_campaigns_on_var", unique: true
|
||||
end
|
||||
|
||||
create_table "settings_mascots", force: :cascade do |t|
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.text "value"
|
||||
t.string "var", null: false
|
||||
t.index ["var"], name: "index_settings_mascots_on_var", unique: true
|
||||
end
|
||||
|
||||
create_table "settings_rate_limits", force: :cascade do |t|
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
module DataUpdateScripts
|
||||
class MoveMascotSettings
|
||||
SETTINGS = %w[
|
||||
footer_image_height
|
||||
footer_image_url
|
||||
footer_image_width
|
||||
image_description
|
||||
image_url
|
||||
].freeze
|
||||
|
||||
def run
|
||||
SETTINGS.each do |setting|
|
||||
Settings::Mascot.public_send("#{setting}=", SiteConfig.public_send("mascot_#{setting}"))
|
||||
end
|
||||
Settings::Mascot.mascot_user_id = SiteConfig.mascot_user_id
|
||||
end
|
||||
end
|
||||
end
|
||||
28
spec/lib/data_update_scripts/move_mascot_settings_spec.rb
Normal file
28
spec/lib/data_update_scripts/move_mascot_settings_spec.rb
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
require "rails_helper"
|
||||
require Rails.root.join(
|
||||
"lib/data_update_scripts/20210420050256_move_mascot_settings.rb",
|
||||
)
|
||||
|
||||
describe DataUpdateScripts::MoveMascotSettings do
|
||||
before do
|
||||
allow(SiteConfig).to receive(:mascot_footer_image_url)
|
||||
.and_return("https://example.com/mascot.png")
|
||||
end
|
||||
|
||||
it "moves renamed settings" do
|
||||
allow(SiteConfig).to receive(:mascot_image_description).and_return("Bla")
|
||||
|
||||
expect do
|
||||
described_class.new.run
|
||||
end
|
||||
.to change(Settings::Mascot, :image_description)
|
||||
.and change(Settings::Mascot, :footer_image_url)
|
||||
end
|
||||
|
||||
it "moves the non-renamed./spec/lib/data_update_scripts/move_mascot_settings_spec.rb setting" do
|
||||
allow(SiteConfig).to receive(:mascot_user_id).and_return(42)
|
||||
expect do
|
||||
described_class.new.run
|
||||
end.to change(Settings::Mascot, :mascot_user_id).to(42)
|
||||
end
|
||||
end
|
||||
|
|
@ -55,7 +55,7 @@ RSpec.describe Article, type: :model do
|
|||
|
||||
describe "::admin_published_with" do
|
||||
it "includes mascot-published articles" do
|
||||
allow(SiteConfig).to receive(:mascot_user_id).and_return(3)
|
||||
allow(Settings::Mascot).to receive(:mascot_user_id).and_return(3)
|
||||
user = create(:user, id: 3)
|
||||
create(:article, user: user, tags: "challenge")
|
||||
expect(described_class.admin_published_with("challenge").count).to eq(1)
|
||||
|
|
@ -908,7 +908,7 @@ RSpec.describe Article, type: :model do
|
|||
|
||||
describe "spam" do
|
||||
before do
|
||||
allow(SiteConfig).to receive(:mascot_user_id).and_return(user.id)
|
||||
allow(Settings::Mascot).to receive(:mascot_user_id).and_return(user.id)
|
||||
allow(SiteConfig).to receive(:spam_trigger_terms).and_return(
|
||||
["yahoomagoo gogo", "testtestetest", "magoo.+magee"],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -431,7 +431,7 @@ RSpec.describe Comment, type: :model do
|
|||
|
||||
describe "spam" do
|
||||
before do
|
||||
allow(SiteConfig).to receive(:mascot_user_id).and_return(user.id)
|
||||
allow(Settings::Mascot).to receive(:mascot_user_id).and_return(user.id)
|
||||
allow(SiteConfig).to receive(:spam_trigger_terms).and_return(["yahoomagoo gogo", "anothertestterm"])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -44,13 +44,13 @@ RSpec.describe Reaction, type: :model do
|
|||
end
|
||||
|
||||
it "does not allow vomit reaction for users without trusted role" do
|
||||
allow(SiteConfig).to receive(:mascot_user_id).and_return(user.id + 1)
|
||||
allow(Settings::Mascot).to receive(:mascot_user_id).and_return(user.id + 1)
|
||||
reaction.category = "vomit"
|
||||
expect(reaction).not_to be_valid
|
||||
end
|
||||
|
||||
it "does not allow thumbsdown reaction for users without trusted role" do
|
||||
allow(SiteConfig).to receive(:mascot_user_id).and_return(user.id + 1)
|
||||
allow(Settings::Mascot).to receive(:mascot_user_id).and_return(user.id + 1)
|
||||
reaction.category = "thumbsdown"
|
||||
expect(reaction).not_to be_valid
|
||||
end
|
||||
|
|
|
|||
|
|
@ -839,7 +839,7 @@ RSpec.describe User, type: :model do
|
|||
end
|
||||
|
||||
it "returns the user if the account exists" do
|
||||
allow(SiteConfig).to receive(:mascot_user_id).and_return(user.id)
|
||||
allow(Settings::Mascot).to receive(:mascot_user_id).and_return(user.id)
|
||||
|
||||
expect(described_class.mascot_account).to eq(user)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -424,56 +424,66 @@ RSpec.describe "/admin/config", type: :request do
|
|||
describe "Mascot" do
|
||||
it "updates the mascot_user_id" do
|
||||
expected_mascot_user_id = 2
|
||||
post "/admin/config", params: { site_config: { mascot_user_id: expected_mascot_user_id },
|
||||
confirmation: confirmation_message }
|
||||
expect(SiteConfig.mascot_user_id).to eq(expected_mascot_user_id)
|
||||
post admin_settings_mascots_path, params: {
|
||||
settings_mascot: { mascot_user_id: expected_mascot_user_id },
|
||||
confirmation: confirmation_message
|
||||
}
|
||||
expect(Settings::Mascot.mascot_user_id).to eq(expected_mascot_user_id)
|
||||
end
|
||||
|
||||
it "updates mascot_image_url" do
|
||||
expected_default_image_url = SiteConfig.get_default(:mascot_image_url)
|
||||
it "updates image_url" do
|
||||
expected_default_image_url = Settings::Mascot.get_default(:image_url)
|
||||
expected_image_url = "https://dummyimage.com/300x300.png"
|
||||
expect do
|
||||
post "/admin/config", params: { site_config: { mascot_image_url: expected_image_url },
|
||||
confirmation: confirmation_message }
|
||||
end.to change(SiteConfig, :mascot_image_url).from(expected_default_image_url).to(expected_image_url)
|
||||
post admin_settings_mascots_path, params: {
|
||||
settings_mascot: { image_url: expected_image_url },
|
||||
confirmation: confirmation_message
|
||||
}
|
||||
end.to change(Settings::Mascot, :image_url).from(expected_default_image_url).to(expected_image_url)
|
||||
end
|
||||
|
||||
it "updates mascot_footer_image_url" do
|
||||
it "updates footer_image_url" do
|
||||
expected_image_url = "https://dummyimage.com/300x300.png"
|
||||
post "/admin/config", params: { site_config: { mascot_footer_image_url: expected_image_url },
|
||||
confirmation: confirmation_message }
|
||||
expect(SiteConfig.mascot_footer_image_url).to eq(expected_image_url)
|
||||
post admin_settings_mascots_path, params: {
|
||||
settings_mascot: { footer_image_url: expected_image_url },
|
||||
confirmation: confirmation_message
|
||||
}
|
||||
expect(Settings::Mascot.footer_image_url).to eq(expected_image_url)
|
||||
end
|
||||
|
||||
it "updates the mascot_footer_image_width" do
|
||||
expected_default_mascot_footer_image_width = SiteConfig.get_default(:mascot_footer_image_width)
|
||||
expected_mascot_footer_image_width = 1002
|
||||
it "updates the footer_image_width" do
|
||||
expected_default_footer_image_width = Settings::Mascot.get_default(:footer_image_width)
|
||||
expected_footer_image_width = 1002
|
||||
|
||||
expect(SiteConfig.mascot_footer_image_width).to eq(expected_default_mascot_footer_image_width)
|
||||
expect(Settings::Mascot.footer_image_width).to eq(expected_default_footer_image_width)
|
||||
|
||||
post "/admin/config", params: { site_config:
|
||||
{ mascot_footer_image_width: expected_mascot_footer_image_width },
|
||||
confirmation: confirmation_message }
|
||||
expect(SiteConfig.mascot_footer_image_width).to eq(expected_mascot_footer_image_width)
|
||||
post admin_settings_mascots_path, params: {
|
||||
settings_mascot: { footer_image_width: expected_footer_image_width },
|
||||
confirmation: confirmation_message
|
||||
}
|
||||
expect(Settings::Mascot.footer_image_width).to eq(expected_footer_image_width)
|
||||
end
|
||||
|
||||
it "updates the mascot_footer_image_height" do
|
||||
expected_default_mascot_footer_image_height = SiteConfig.get_default(:mascot_footer_image_height)
|
||||
expected_mascot_footer_image_height = 3002
|
||||
it "updates the footer_image_height" do
|
||||
expected_default_footer_image_height = Settings::Mascot.get_default(:footer_image_height)
|
||||
expected_footer_image_height = 3002
|
||||
|
||||
expect(SiteConfig.mascot_footer_image_height).to eq(expected_default_mascot_footer_image_height)
|
||||
expect(Settings::Mascot.footer_image_height).to eq(expected_default_footer_image_height)
|
||||
|
||||
post "/admin/config", params: { site_config:
|
||||
{ mascot_footer_image_height: expected_mascot_footer_image_height },
|
||||
confirmation: confirmation_message }
|
||||
expect(SiteConfig.mascot_footer_image_height).to eq(expected_mascot_footer_image_height)
|
||||
post admin_settings_mascots_path, params: {
|
||||
settings_mascot: { footer_image_height: expected_footer_image_height },
|
||||
confirmation: confirmation_message
|
||||
}
|
||||
expect(Settings::Mascot.footer_image_height).to eq(expected_footer_image_height)
|
||||
end
|
||||
|
||||
it "updates mascot_image_description" do
|
||||
it "updates image_description" do
|
||||
description = "Hey hey #{rand(100)}"
|
||||
post "/admin/config", params: { site_config: { mascot_image_description: description },
|
||||
confirmation: confirmation_message }
|
||||
expect(SiteConfig.mascot_image_description).to eq(description)
|
||||
post admin_settings_mascots_path, params: {
|
||||
settings_mascot: { image_description: description },
|
||||
confirmation: confirmation_message
|
||||
}
|
||||
expect(Settings::Mascot.image_description).to eq(description)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ RSpec.describe "CommentsCreate", type: :request do
|
|||
end
|
||||
|
||||
def reply_and_mention_comment_author_as_moderator(comment)
|
||||
allow(SiteConfig).to receive(:mascot_user_id)
|
||||
allow(Settings::Mascot).to receive(:mascot_user_id)
|
||||
.and_return(moderator_replier.id)
|
||||
|
||||
sign_in moderator_replier
|
||||
|
|
|
|||
|
|
@ -345,14 +345,14 @@ RSpec.describe "Registrations", type: :request do
|
|||
end
|
||||
|
||||
it "creates mascot user" do
|
||||
expect(SiteConfig.mascot_user_id).to be_nil
|
||||
expect(Settings::Mascot.mascot_user_id).to be_nil
|
||||
post "/users", params:
|
||||
{ user: { name: "test #{rand(10)}",
|
||||
username: "haha_#{rand(10)}",
|
||||
email: "yoooo#{rand(100)}@yo.co",
|
||||
password: "PaSSw0rd_yo000",
|
||||
password_confirmation: "PaSSw0rd_yo000" } }
|
||||
expect(SiteConfig.mascot_user_id).to eq User.last.id
|
||||
expect(Settings::Mascot.mascot_user_id).to eq User.last.id
|
||||
|
||||
mascot_account = User.mascot_account
|
||||
expect(mascot_account.username).to eq Users::CreateMascotAccount::MASCOT_PARAMS[:username]
|
||||
|
|
|
|||
|
|
@ -66,13 +66,13 @@ RSpec.describe Search::QueryBuilders::ChatChannelMembership, type: :service do
|
|||
end
|
||||
|
||||
it "always applies channel discoverable and status params" do
|
||||
allow(SiteConfig).to receive(:mascot_user_id).and_return(2)
|
||||
allow(Settings::Mascot).to receive(:mascot_user_id).and_return(2)
|
||||
|
||||
params = { user_id: SiteConfig.mascot_user_id }
|
||||
params = { user_id: Settings::Mascot.mascot_user_id }
|
||||
filter = described_class.new(params: params)
|
||||
expected_filters = [
|
||||
{ "terms" => { "status" => %w[active joining_request] } },
|
||||
{ "terms" => { "viewable_by" => SiteConfig.mascot_user_id } },
|
||||
{ "terms" => { "viewable_by" => Settings::Mascot.mascot_user_id } },
|
||||
]
|
||||
expect(filter.as_hash.dig("query", "bool", "filter")).to match_array(expected_filters)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ RSpec.describe Users::CreateMascotAccount, type: :service do
|
|||
end
|
||||
|
||||
context "when a mascot user doesn't exist" do
|
||||
before { allow(SiteConfig).to receive(:mascot_user_id).and_return(nil) }
|
||||
before { allow(Settings::Mascot).to receive(:mascot_user_id).and_return(nil) }
|
||||
|
||||
it "creates a mascot account" do
|
||||
expect do
|
||||
|
|
@ -21,7 +21,7 @@ RSpec.describe Users::CreateMascotAccount, type: :service do
|
|||
|
||||
context "when a mascot user already exists" do
|
||||
before do
|
||||
allow(SiteConfig).to receive(:mascot_user_id).and_return(2)
|
||||
allow(Settings::Mascot).to receive(:mascot_user_id).and_return(2)
|
||||
allow(User).to receive(:create)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ RSpec.describe "dashboards/show.html.erb", type: :view do
|
|||
stub_template "dashboards/_actions.html.erb" => "stubbed content"
|
||||
|
||||
allow(Images::Optimizer).to receive(:imgproxy_enabled?).and_return(true)
|
||||
allow(SiteConfig).to receive(:mascot_image_url).and_return("https://i.imgur.com/fKYKgo4.png")
|
||||
allow(Settings::Mascot).to receive(:image_url).and_return("https://i.imgur.com/fKYKgo4.png")
|
||||
end
|
||||
|
||||
context "when using Imgproxy" do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue