From f0d1467e870b51b09e91f4c8ed23d4a6fae354d9 Mon Sep 17 00:00:00 2001 From: Maja Komel Date: Sun, 17 Mar 2019 20:35:33 +0100 Subject: [PATCH] FEATURE: custom colors for default letter avatars --- app/models/user.rb | 17 +++++++++++++++-- config/locales/server.en.yml | 2 ++ config/site_settings.yml | 5 +++++ lib/validators/color_list_validator.rb | 14 ++++++++++++++ spec/models/user_spec.rb | 14 ++++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 lib/validators/color_list_validator.rb diff --git a/app/models/user.rb b/app/models/user.rb index 4c2710358c4dfa..ce151e69b5c06e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -738,8 +738,21 @@ def self.system_avatar_template(username) def self.letter_avatar_color(username) username ||= "" - color = LetterAvatar::COLORS[Digest::MD5.hexdigest(username)[0...15].to_i(16) % LetterAvatar::COLORS.length] - color.map { |c| c.to_s(16).rjust(2, '0') }.join + if SiteSetting.restrict_letter_avatar_colors.present? + hex_length = 6 + colors = SiteSetting.restrict_letter_avatar_colors + length = colors.count("|") + 1 + num = color_index(username, length) + index = (num * hex_length) + num + colors[index, hex_length] + else + color = LetterAvatar::COLORS[color_index(username, LetterAvatar::COLORS.length)] + color.map { |c| c.to_s(16).rjust(2, '0') }.join + end + end + + def self.color_index(username, length) + Digest::MD5.hexdigest(username)[0...15].to_i(16) % length end def avatar_template diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 7c40397134960c..0211b5748a1c10 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -1569,6 +1569,7 @@ en: external_system_avatars_enabled: "Use external system avatars service." external_system_avatars_url: "URL of the external system avatars service. Allowed substitutions are {username} {first_letter} {color} {size}" + restrict_letter_avatar_colors: "A list of 6-digit hexadecimal color values to be used for letter avatar background." selectable_avatars_enabled: "Force users to choose an avatar from the list." selectable_avatars: "List of avatars users can choose from." @@ -2019,6 +2020,7 @@ en: min_username_length_range: "You cannot set the minimum above the maximum." max_username_length_exists: "You cannot set the maximum username length below the longest username (%{username})." max_username_length_range: "You cannot set the maximum below the minimum." + invalid_hex_value: "Color values have to be 6-digit hexadecimal codes." placeholder: sso_provider_secrets: diff --git a/config/site_settings.yml b/config/site_settings.yml index 24e69ece6f2c09..5a8c93a4091cdf 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -1100,6 +1100,11 @@ files: client: true regex: '^((https?:)?\/)?\/.+[^\/]' shadowed_by_global: true + restrict_letter_avatar_colors: + default: '' + type: list + list_type: compact + validator: "ColorListValidator" selectable_avatars_enabled: default: false client: true diff --git a/lib/validators/color_list_validator.rb b/lib/validators/color_list_validator.rb new file mode 100644 index 00000000000000..dce170b8de6a51 --- /dev/null +++ b/lib/validators/color_list_validator.rb @@ -0,0 +1,14 @@ +class ColorListValidator + def initialize(opts = {}) + @opts = opts + end + + def valid_value?(value) + hex_regex = /\A\h{6}\z/ + value.split("|").all? { |c| c =~ hex_regex } + end + + def error_message + I18n.t('site_settings.errors.invalid_hex_value') + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index dfce0b76ef1a05..fc248f046b3751 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1138,6 +1138,20 @@ def test_user?(opts = {}) end + describe "#letter_avatar_color" do + before do + SiteSetting.restrict_letter_avatar_colors = "2F70AC|ED207B|AAAAAA|77FF33" + end + + it "returns custom color if restrict_letter_avatar_colors site setting is set" do + colors = SiteSetting.restrict_letter_avatar_colors.split("|") + expect(User.letter_avatar_color("username_one")).to eq("2F70AC") + expect(User.letter_avatar_color("username_two")).to eq("ED207B") + expect(User.letter_avatar_color("username_three")).to eq("AAAAAA") + expect(User.letter_avatar_color("username_four")).to eq("77FF33") + end + end + describe ".small_avatar_url" do let(:user) { build(:user, username: 'Sam') }