From 18c32a809b36fc171916ae751d91ecd49cf45910 Mon Sep 17 00:00:00 2001 From: Bianca Nenciu Date: Thu, 22 Jul 2021 17:42:47 +0300 Subject: [PATCH] FIX: Validate email_accent_bg_color color (#13778) Using an invalid value was allowed. This commit tries to automatically fix the color by adding missing # symbol or will show an error to the user if it is not possible and it is not a CSS color either. --- .../admin/addon/components/color-input.js | 18 ++++++++- config/locales/server.en.yml | 1 + config/site_settings.yml | 11 +++++- lib/validators/css_color_validator.rb | 39 +++++++++++++++++++ .../validators/css_color_validator_spec.rb | 23 +++++++++++ 5 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 lib/validators/css_color_validator.rb create mode 100644 spec/components/validators/css_color_validator_spec.rb diff --git a/app/assets/javascripts/admin/addon/components/color-input.js b/app/assets/javascripts/admin/addon/components/color-input.js index c563fedc94..91aeaec6e0 100644 --- a/app/assets/javascripts/admin/addon/components/color-input.js +++ b/app/assets/javascripts/admin/addon/components/color-input.js @@ -22,9 +22,21 @@ export default Component.extend({ return this.onlyHex ? 6 : null; }), + normalize(color) { + if (/^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(color)) { + if (!color.startsWith("#")) { + color = "#" + color; + } + } + + return color; + }, + @action onHexInput(color) { - this.attrs.onChangeColor && this.attrs.onChangeColor(color || ""); + if (this.attrs.onChangeColor) { + this.attrs.onChangeColor(this.normalize(color || "")); + } }, @observes("hexValue", "brightnessValue", "valid") @@ -32,7 +44,9 @@ export default Component.extend({ const hex = this.hexValue; let text = this.element.querySelector("input.hex-input"); - this.attrs.onChangeColor && this.attrs.onChangeColor(hex); + if (this.attrs.onChangeColor) { + this.attrs.onChangeColor(this.normalize(hex)); + } if (this.valid) { this.styleSelection && diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 6e787d7265..ce7d3b1279 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -2324,6 +2324,7 @@ en: allow_changing_staged_user_tracking: "Allow a staged user's category and tag notification preferences to be changed by an admin user." errors: + invalid_css_color: "Invalid color. Enter a color name or hex value." invalid_email: "Invalid email address." invalid_username: "There's no user with that username." invalid_group: "There's no group with that name." diff --git a/config/site_settings.yml b/config/site_settings.yml index b01c9fc426..363aacc249 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -1064,8 +1064,15 @@ email: email_accent_bg_color: type: color default: "#2F70AC" - email_accent_fg_color: "#FFFFFF" - email_link_color: "#006699" + validator: "CssColorValidator" + email_accent_fg_color: + type: color + default: "#FFFFFF" + validator: "CssColorValidator" + email_link_color: + type: color + default: "#006699" + validator: "CssColorValidator" show_topic_featured_link_in_digest: false email_custom_headers: "Auto-Submitted: auto-generated" email_subject: "[%{site_name}] %{optional_pm}%{optional_cat}%{topic_title}" diff --git a/lib/validators/css_color_validator.rb b/lib/validators/css_color_validator.rb new file mode 100644 index 0000000000..630e9cad57 --- /dev/null +++ b/lib/validators/css_color_validator.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +class CssColorValidator + COLORS = %w{ + aliceblue antiquewhite aqua aquamarine azure beige bisque black + blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse + chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan + darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta + darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen + darkslateblue darkslategray darkslategrey darkturquoise darkviolet + deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite + forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green + greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender + lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan + lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon + lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue + lightyellow lime limegreen linen magenta maroon mediumaquamarine + mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue + mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream + mistyrose moccasin navajowhite navy oldlace olive olivedrab orange + orangered orchid palegoldenrod palegreen paleturquoise palevioletred + papayawhip peachpuff peru pink plum powderblue purple red rosybrown + royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver + skyblue slateblue slategray slategrey snow springgreen steelblue tan teal + thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen + } + + def initialize(opts = {}) + @opts = opts + end + + def valid_value?(val) + !!(val =~ /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/ || COLORS.include?(val&.downcase)) + end + + def error_message + I18n.t("site_settings.errors.invalid_css_color") + end +end diff --git a/spec/components/validators/css_color_validator_spec.rb b/spec/components/validators/css_color_validator_spec.rb new file mode 100644 index 0000000000..db754808b1 --- /dev/null +++ b/spec/components/validators/css_color_validator_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe CssColorValidator do + subject { described_class.new } + + it "validates hex colors" do + expect(subject.valid_value?('#0')).to eq(false) + expect(subject.valid_value?('#00')).to eq(false) + expect(subject.valid_value?('#000')).to eq(true) + expect(subject.valid_value?('#0000')).to eq(false) + expect(subject.valid_value?('#00000')).to eq(false) + expect(subject.valid_value?('#000000')).to eq(true) + end + + it "validates css colors" do + expect(subject.valid_value?('red')).to eq(true) + expect(subject.valid_value?('green')).to eq(true) + expect(subject.valid_value?('blue')).to eq(true) + expect(subject.valid_value?('hello')).to eq(false) + end +end