From 845c8d0b5c5b0b59b02cea253532bec3d9d6a42f Mon Sep 17 00:00:00 2001 From: Martin Wortschack Date: Fri, 1 Feb 2019 17:24:11 +0100 Subject: Block emojis from user name - Use JS regex for emoji validation - Add test for blocking emojis in full name - Fix existing tests for user status that failed locally --- .../javascripts/pages/profiles/show/index.js | 12 +++++ app/views/profiles/show.html.haml | 6 +-- ...-symbol-characters-from-user-s-full-names-2.yml | 5 ++ locale/gitlab.pot | 3 ++ package.json | 1 + spec/features/profiles/user_edit_profile_spec.rb | 63 +++++++++++++++------- yarn.lock | 5 ++ 7 files changed, 73 insertions(+), 22 deletions(-) create mode 100644 changelogs/unreleased/50521-block-emojis-and-symbol-characters-from-user-s-full-names-2.yml diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js index c7ce4675573..0dd0d5336fc 100644 --- a/app/assets/javascripts/pages/profiles/show/index.js +++ b/app/assets/javascripts/pages/profiles/show/index.js @@ -1,6 +1,7 @@ import $ from 'jquery'; import createFlash from '~/flash'; import GfmAutoComplete from '~/gfm_auto_complete'; +import emojiRegex from 'emoji-regex'; import EmojiMenu from './emoji_menu'; const defaultStatusEmoji = 'speech_balloon'; @@ -42,6 +43,17 @@ document.addEventListener('DOMContentLoaded', () => { const emojiAutocomplete = new GfmAutoComplete(); emojiAutocomplete.setup($(statusMessageField), { emojis: true }); + const userNameInput = document.getElementById('user_name'); + userNameInput.addEventListener('input', () => { + const EMOJI_REGEX = emojiRegex(); + if (EMOJI_REGEX.test(userNameInput.value)) { + // set field to invalid so it gets detected by GlFieldErrors + userNameInput.setCustomValidity('Invalid field'); + } else { + userNameInput.setCustomValidity(''); + } + }); + import(/* webpackChunkName: 'emoji' */ '~/emoji') .then(Emoji => { const emojiMenu = new EmojiMenu( diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 2629b374e7c..753316b27e2 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -2,7 +2,7 @@ - @content_class = "limit-container-width" unless fluid_layout - gravatar_link = link_to Gitlab.config.gravatar.host, 'https://' + Gitlab.config.gravatar.host -= bootstrap_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user prepend-top-default js-quick-submit' }, authenticity_token: true do |f| += bootstrap_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user prepend-top-default js-quick-submit gl-show-field-errors' }, authenticity_token: true do |f| = form_errors(@user) .row @@ -77,10 +77,10 @@ .col-lg-8 .row - if @user.read_only_attribute?(:name) - = f.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9' }, + = f.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you") % { provider_label: attribute_provider_label(:name) } - else - = f.text_field :name, label: 'Full name', required: true, wrapper: { class: 'col-md-9' }, help: s_("Profiles|Enter your name, so people you know can recognize you") + = f.text_field :name, label: 'Full name', required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you") = f.text_field :id, readonly: true, label: 'User ID', wrapper: { class: 'col-md-3' } - if @user.read_only_attribute?(:email) diff --git a/changelogs/unreleased/50521-block-emojis-and-symbol-characters-from-user-s-full-names-2.yml b/changelogs/unreleased/50521-block-emojis-and-symbol-characters-from-user-s-full-names-2.yml new file mode 100644 index 00000000000..04caf8262c6 --- /dev/null +++ b/changelogs/unreleased/50521-block-emojis-and-symbol-characters-from-user-s-full-names-2.yml @@ -0,0 +1,5 @@ +--- +title: Block emojis and symbol characters from users full names +merge_request: 24523 +author: +type: other diff --git a/locale/gitlab.pot b/locale/gitlab.pot index a72e921dcce..dd94ba892b4 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -5399,6 +5399,9 @@ msgstr "" msgid "Profiles|Username successfully changed" msgstr "" +msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead" +msgstr "" + msgid "Profiles|What's your status?" msgstr "" diff --git a/package.json b/package.json index 6c771e377b8..d9b2a1c152b 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "document-register-element": "1.3.0", "dropzone": "^4.2.0", "echarts": "^4.2.0-rc.2", + "emoji-regex": "^7.0.3", "emoji-unicode-version": "^0.2.1", "exports-loader": "^0.7.0", "file-loader": "^3.0.1", diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb index f45bcabd196..b43711f6ef6 100644 --- a/spec/features/profiles/user_edit_profile_spec.rb +++ b/spec/features/profiles/user_edit_profile_spec.rb @@ -10,6 +10,7 @@ describe 'User edit profile' do def submit_settings click_button 'Update profile settings' + wait_for_requests if respond_to?(:wait_for_requests) end it 'changes user profile' do @@ -35,6 +36,17 @@ describe 'User edit profile' do expect(page).to have_content('Profile was successfully updated') end + it 'shows an error if the full name contains an emoji', :js do + simulate_input('#user_name', 'Martin 😀') + submit_settings + + page.within('.qa-full-name') do + expect(page).to have_css '.gl-field-error-outline' + expect(find('.gl-field-error')).not_to have_selector('.hidden') + expect(find('.gl-field-error')).to have_content('Using emojis in names seems fun, but please try to set a status message instead') + end + end + context 'user avatar' do before do attach_file(:user_avatar, Rails.root.join('spec', 'fixtures', 'banana_sample.gif')) @@ -61,6 +73,11 @@ describe 'User edit profile' do end context 'user status', :js do + def visit_user + visit user_path(user) + wait_for_requests + end + def select_emoji(emoji_name, is_modal = false) emoji_menu_class = is_modal ? '.js-modal-status-emoji-menu' : '.js-status-emoji-menu' toggle_button = find('.js-toggle-emoji-menu') @@ -71,18 +88,16 @@ describe 'User edit profile' do context 'profile edit form' do it 'shows the user status form' do - visit(profile_path) - expect(page).to have_content('Current status') end it 'adds emoji to user status' do emoji = 'biohazard' - visit(profile_path) select_emoji(emoji) submit_settings - visit user_path(user) + visit_user + within('.cover-status') do expect(page).to have_emoji(emoji) end @@ -90,11 +105,11 @@ describe 'User edit profile' do it 'adds message to user status' do message = 'I have something to say' - visit(profile_path) fill_in 'js-status-message-field', with: message submit_settings - visit user_path(user) + visit_user + within('.cover-status') do expect(page).to have_emoji('speech_balloon') expect(page).to have_content message @@ -104,12 +119,12 @@ describe 'User edit profile' do it 'adds message and emoji to user status' do emoji = 'tanabata_tree' message = 'Playing outside' - visit(profile_path) select_emoji(emoji) fill_in 'js-status-message-field', with: message submit_settings - visit user_path(user) + visit_user + within('.cover-status') do expect(page).to have_emoji(emoji) expect(page).to have_content message @@ -119,7 +134,8 @@ describe 'User edit profile' do it 'clears the user status' do user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread') - visit user_path(user) + visit_user + within('.cover-status') do expect(page).to have_emoji(user_status.emoji) expect(page).to have_content user_status.message @@ -129,15 +145,13 @@ describe 'User edit profile' do click_button 'js-clear-user-status-button' submit_settings - wait_for_requests + visit_user - visit user_path(user) expect(page).not_to have_selector '.cover-status' end it 'displays a default emoji if only message is entered' do message = 'a status without emoji' - visit(profile_path) fill_in 'js-status-message-field', with: message within('.js-toggle-emoji-menu') do @@ -162,6 +176,7 @@ describe 'User edit profile' do page.within "#set-user-status-modal" do click_button 'Set status' end + wait_for_requests end before do @@ -202,7 +217,8 @@ describe 'User edit profile' do select_emoji(emoji, true) set_user_status_in_modal - visit user_path(user) + visit_user + within('.cover-status') do expect(page).to have_emoji(emoji) end @@ -225,7 +241,8 @@ describe 'User edit profile' do find('.js-status-message-field').native.send_keys(message) set_user_status_in_modal - visit user_path(user) + visit_user + within('.cover-status') do expect(page).to have_emoji('speech_balloon') expect(page).to have_content message @@ -240,7 +257,8 @@ describe 'User edit profile' do find('.js-status-message-field').native.send_keys(message) set_user_status_in_modal - visit user_path(user) + visit_user + within('.cover-status') do expect(page).to have_emoji(emoji) expect(page).to have_content message @@ -250,7 +268,9 @@ describe 'User edit profile' do it 'clears the user status with the "X" button' do user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread') - visit user_path(user) + visit_user + wait_for_requests + within('.cover-status') do expect(page).to have_emoji(user_status.emoji) expect(page).to have_content user_status.message @@ -265,14 +285,18 @@ describe 'User edit profile' do find('.js-clear-user-status-button').click set_user_status_in_modal - visit user_path(user) + visit_user + wait_for_requests + expect(page).not_to have_selector '.cover-status' end it 'clears the user status with the "Remove status" button' do user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread') - visit user_path(user) + visit_user + wait_for_requests + within('.cover-status') do expect(page).to have_emoji(user_status.emoji) expect(page).to have_content user_status.message @@ -288,7 +312,8 @@ describe 'User edit profile' do click_button 'Remove status' end - visit user_path(user) + visit_user + expect(page).not_to have_selector '.cover-status' end diff --git a/yarn.lock b/yarn.lock index bb948ad703c..4a148271ad6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3395,6 +3395,11 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emoji-regex@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + emoji-unicode-version@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc" -- cgit v1.2.3