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
This commit is contained in:
parent
c243b154ab
commit
845c8d0b5c
7 changed files with 73 additions and 22 deletions
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import GfmAutoComplete from '~/gfm_auto_complete';
|
import GfmAutoComplete from '~/gfm_auto_complete';
|
||||||
|
import emojiRegex from 'emoji-regex';
|
||||||
import EmojiMenu from './emoji_menu';
|
import EmojiMenu from './emoji_menu';
|
||||||
|
|
||||||
const defaultStatusEmoji = 'speech_balloon';
|
const defaultStatusEmoji = 'speech_balloon';
|
||||||
|
@ -42,6 +43,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
const emojiAutocomplete = new GfmAutoComplete();
|
const emojiAutocomplete = new GfmAutoComplete();
|
||||||
emojiAutocomplete.setup($(statusMessageField), { emojis: true });
|
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')
|
import(/* webpackChunkName: 'emoji' */ '~/emoji')
|
||||||
.then(Emoji => {
|
.then(Emoji => {
|
||||||
const emojiMenu = new EmojiMenu(
|
const emojiMenu = new EmojiMenu(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
- @content_class = "limit-container-width" unless fluid_layout
|
- @content_class = "limit-container-width" unless fluid_layout
|
||||||
- gravatar_link = link_to Gitlab.config.gravatar.host, 'https://' + Gitlab.config.gravatar.host
|
- 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)
|
= form_errors(@user)
|
||||||
|
|
||||||
.row
|
.row
|
||||||
|
@ -77,10 +77,10 @@
|
||||||
.col-lg-8
|
.col-lg-8
|
||||||
.row
|
.row
|
||||||
- if @user.read_only_attribute?(:name)
|
- 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) }
|
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
|
- 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' }
|
= f.text_field :id, readonly: true, label: 'User ID', wrapper: { class: 'col-md-3' }
|
||||||
|
|
||||||
- if @user.read_only_attribute?(:email)
|
- if @user.read_only_attribute?(:email)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Block emojis and symbol characters from users full names
|
||||||
|
merge_request: 24523
|
||||||
|
author:
|
||||||
|
type: other
|
|
@ -5399,6 +5399,9 @@ msgstr ""
|
||||||
msgid "Profiles|Username successfully changed"
|
msgid "Profiles|Username successfully changed"
|
||||||
msgstr ""
|
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?"
|
msgid "Profiles|What's your status?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
"document-register-element": "1.3.0",
|
"document-register-element": "1.3.0",
|
||||||
"dropzone": "^4.2.0",
|
"dropzone": "^4.2.0",
|
||||||
"echarts": "^4.2.0-rc.2",
|
"echarts": "^4.2.0-rc.2",
|
||||||
|
"emoji-regex": "^7.0.3",
|
||||||
"emoji-unicode-version": "^0.2.1",
|
"emoji-unicode-version": "^0.2.1",
|
||||||
"exports-loader": "^0.7.0",
|
"exports-loader": "^0.7.0",
|
||||||
"file-loader": "^3.0.1",
|
"file-loader": "^3.0.1",
|
||||||
|
|
|
@ -10,6 +10,7 @@ describe 'User edit profile' do
|
||||||
|
|
||||||
def submit_settings
|
def submit_settings
|
||||||
click_button 'Update profile settings'
|
click_button 'Update profile settings'
|
||||||
|
wait_for_requests if respond_to?(:wait_for_requests)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'changes user profile' do
|
it 'changes user profile' do
|
||||||
|
@ -35,6 +36,17 @@ describe 'User edit profile' do
|
||||||
expect(page).to have_content('Profile was successfully updated')
|
expect(page).to have_content('Profile was successfully updated')
|
||||||
end
|
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
|
context 'user avatar' do
|
||||||
before do
|
before do
|
||||||
attach_file(:user_avatar, Rails.root.join('spec', 'fixtures', 'banana_sample.gif'))
|
attach_file(:user_avatar, Rails.root.join('spec', 'fixtures', 'banana_sample.gif'))
|
||||||
|
@ -61,6 +73,11 @@ describe 'User edit profile' do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'user status', :js do
|
context 'user status', :js do
|
||||||
|
def visit_user
|
||||||
|
visit user_path(user)
|
||||||
|
wait_for_requests
|
||||||
|
end
|
||||||
|
|
||||||
def select_emoji(emoji_name, is_modal = false)
|
def select_emoji(emoji_name, is_modal = false)
|
||||||
emoji_menu_class = is_modal ? '.js-modal-status-emoji-menu' : '.js-status-emoji-menu'
|
emoji_menu_class = is_modal ? '.js-modal-status-emoji-menu' : '.js-status-emoji-menu'
|
||||||
toggle_button = find('.js-toggle-emoji-menu')
|
toggle_button = find('.js-toggle-emoji-menu')
|
||||||
|
@ -71,18 +88,16 @@ describe 'User edit profile' do
|
||||||
|
|
||||||
context 'profile edit form' do
|
context 'profile edit form' do
|
||||||
it 'shows the user status form' do
|
it 'shows the user status form' do
|
||||||
visit(profile_path)
|
|
||||||
|
|
||||||
expect(page).to have_content('Current status')
|
expect(page).to have_content('Current status')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'adds emoji to user status' do
|
it 'adds emoji to user status' do
|
||||||
emoji = 'biohazard'
|
emoji = 'biohazard'
|
||||||
visit(profile_path)
|
|
||||||
select_emoji(emoji)
|
select_emoji(emoji)
|
||||||
submit_settings
|
submit_settings
|
||||||
|
|
||||||
visit user_path(user)
|
visit_user
|
||||||
|
|
||||||
within('.cover-status') do
|
within('.cover-status') do
|
||||||
expect(page).to have_emoji(emoji)
|
expect(page).to have_emoji(emoji)
|
||||||
end
|
end
|
||||||
|
@ -90,11 +105,11 @@ describe 'User edit profile' do
|
||||||
|
|
||||||
it 'adds message to user status' do
|
it 'adds message to user status' do
|
||||||
message = 'I have something to say'
|
message = 'I have something to say'
|
||||||
visit(profile_path)
|
|
||||||
fill_in 'js-status-message-field', with: message
|
fill_in 'js-status-message-field', with: message
|
||||||
submit_settings
|
submit_settings
|
||||||
|
|
||||||
visit user_path(user)
|
visit_user
|
||||||
|
|
||||||
within('.cover-status') do
|
within('.cover-status') do
|
||||||
expect(page).to have_emoji('speech_balloon')
|
expect(page).to have_emoji('speech_balloon')
|
||||||
expect(page).to have_content message
|
expect(page).to have_content message
|
||||||
|
@ -104,12 +119,12 @@ describe 'User edit profile' do
|
||||||
it 'adds message and emoji to user status' do
|
it 'adds message and emoji to user status' do
|
||||||
emoji = 'tanabata_tree'
|
emoji = 'tanabata_tree'
|
||||||
message = 'Playing outside'
|
message = 'Playing outside'
|
||||||
visit(profile_path)
|
|
||||||
select_emoji(emoji)
|
select_emoji(emoji)
|
||||||
fill_in 'js-status-message-field', with: message
|
fill_in 'js-status-message-field', with: message
|
||||||
submit_settings
|
submit_settings
|
||||||
|
|
||||||
visit user_path(user)
|
visit_user
|
||||||
|
|
||||||
within('.cover-status') do
|
within('.cover-status') do
|
||||||
expect(page).to have_emoji(emoji)
|
expect(page).to have_emoji(emoji)
|
||||||
expect(page).to have_content message
|
expect(page).to have_content message
|
||||||
|
@ -119,7 +134,8 @@ describe 'User edit profile' do
|
||||||
it 'clears the user status' do
|
it 'clears the user status' do
|
||||||
user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
|
user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
|
||||||
|
|
||||||
visit user_path(user)
|
visit_user
|
||||||
|
|
||||||
within('.cover-status') do
|
within('.cover-status') do
|
||||||
expect(page).to have_emoji(user_status.emoji)
|
expect(page).to have_emoji(user_status.emoji)
|
||||||
expect(page).to have_content user_status.message
|
expect(page).to have_content user_status.message
|
||||||
|
@ -129,15 +145,13 @@ describe 'User edit profile' do
|
||||||
click_button 'js-clear-user-status-button'
|
click_button 'js-clear-user-status-button'
|
||||||
submit_settings
|
submit_settings
|
||||||
|
|
||||||
wait_for_requests
|
visit_user
|
||||||
|
|
||||||
visit user_path(user)
|
|
||||||
expect(page).not_to have_selector '.cover-status'
|
expect(page).not_to have_selector '.cover-status'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'displays a default emoji if only message is entered' do
|
it 'displays a default emoji if only message is entered' do
|
||||||
message = 'a status without emoji'
|
message = 'a status without emoji'
|
||||||
visit(profile_path)
|
|
||||||
fill_in 'js-status-message-field', with: message
|
fill_in 'js-status-message-field', with: message
|
||||||
|
|
||||||
within('.js-toggle-emoji-menu') do
|
within('.js-toggle-emoji-menu') do
|
||||||
|
@ -162,6 +176,7 @@ describe 'User edit profile' do
|
||||||
page.within "#set-user-status-modal" do
|
page.within "#set-user-status-modal" do
|
||||||
click_button 'Set status'
|
click_button 'Set status'
|
||||||
end
|
end
|
||||||
|
wait_for_requests
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
@ -202,7 +217,8 @@ describe 'User edit profile' do
|
||||||
select_emoji(emoji, true)
|
select_emoji(emoji, true)
|
||||||
set_user_status_in_modal
|
set_user_status_in_modal
|
||||||
|
|
||||||
visit user_path(user)
|
visit_user
|
||||||
|
|
||||||
within('.cover-status') do
|
within('.cover-status') do
|
||||||
expect(page).to have_emoji(emoji)
|
expect(page).to have_emoji(emoji)
|
||||||
end
|
end
|
||||||
|
@ -225,7 +241,8 @@ describe 'User edit profile' do
|
||||||
find('.js-status-message-field').native.send_keys(message)
|
find('.js-status-message-field').native.send_keys(message)
|
||||||
set_user_status_in_modal
|
set_user_status_in_modal
|
||||||
|
|
||||||
visit user_path(user)
|
visit_user
|
||||||
|
|
||||||
within('.cover-status') do
|
within('.cover-status') do
|
||||||
expect(page).to have_emoji('speech_balloon')
|
expect(page).to have_emoji('speech_balloon')
|
||||||
expect(page).to have_content message
|
expect(page).to have_content message
|
||||||
|
@ -240,7 +257,8 @@ describe 'User edit profile' do
|
||||||
find('.js-status-message-field').native.send_keys(message)
|
find('.js-status-message-field').native.send_keys(message)
|
||||||
set_user_status_in_modal
|
set_user_status_in_modal
|
||||||
|
|
||||||
visit user_path(user)
|
visit_user
|
||||||
|
|
||||||
within('.cover-status') do
|
within('.cover-status') do
|
||||||
expect(page).to have_emoji(emoji)
|
expect(page).to have_emoji(emoji)
|
||||||
expect(page).to have_content message
|
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
|
it 'clears the user status with the "X" button' do
|
||||||
user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
|
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
|
within('.cover-status') do
|
||||||
expect(page).to have_emoji(user_status.emoji)
|
expect(page).to have_emoji(user_status.emoji)
|
||||||
expect(page).to have_content user_status.message
|
expect(page).to have_content user_status.message
|
||||||
|
@ -265,14 +285,18 @@ describe 'User edit profile' do
|
||||||
find('.js-clear-user-status-button').click
|
find('.js-clear-user-status-button').click
|
||||||
set_user_status_in_modal
|
set_user_status_in_modal
|
||||||
|
|
||||||
visit user_path(user)
|
visit_user
|
||||||
|
wait_for_requests
|
||||||
|
|
||||||
expect(page).not_to have_selector '.cover-status'
|
expect(page).not_to have_selector '.cover-status'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'clears the user status with the "Remove status" button' do
|
it 'clears the user status with the "Remove status" button' do
|
||||||
user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
|
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
|
within('.cover-status') do
|
||||||
expect(page).to have_emoji(user_status.emoji)
|
expect(page).to have_emoji(user_status.emoji)
|
||||||
expect(page).to have_content user_status.message
|
expect(page).to have_content user_status.message
|
||||||
|
@ -288,7 +312,8 @@ describe 'User edit profile' do
|
||||||
click_button 'Remove status'
|
click_button 'Remove status'
|
||||||
end
|
end
|
||||||
|
|
||||||
visit user_path(user)
|
visit_user
|
||||||
|
|
||||||
expect(page).not_to have_selector '.cover-status'
|
expect(page).not_to have_selector '.cover-status'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3395,6 +3395,11 @@ elliptic@^6.0.0:
|
||||||
minimalistic-assert "^1.0.0"
|
minimalistic-assert "^1.0.0"
|
||||||
minimalistic-crypto-utils "^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:
|
emoji-unicode-version@^0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc"
|
resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc"
|
||||||
|
|
Loading…
Reference in a new issue