diff --git a/app/models/user.rb b/app/models/user.rb index 3b1633b9654..a2383068fb4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -743,8 +743,21 @@ class User < ActiveRecord::Base 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 967a228f729..f050e03edb7 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -1570,6 +1570,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." @@ -2023,6 +2024,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 f4127f317dc..aa8700667ae 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -1106,6 +1106,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 00000000000..dce170b8de6 --- /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 3d1c1b8540d..a227bcf7e8f 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1138,6 +1138,20 @@ describe User do 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') }