From c8f773a8593926f4f2dec6f446a3b3e59e9c9909 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 30 Jan 2020 21:08:47 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- CHANGELOG-EE.md | 16 ++ GITLAB_WORKHORSE_VERSION | 2 +- Gemfile | 2 +- Gemfile.lock | 6 +- .../frequent_items/components/app.vue | 6 +- .../components/frequent_items_list.vue | 6 +- .../javascripts/frequent_items/utils.js | 7 + app/assets/javascripts/groups_select.js | 7 +- .../notes/components/notes_app.vue | 2 +- app/assets/javascripts/user_popovers.js | 146 ++++++++---------- .../components/user_popover/user_popover.vue | 11 +- app/controllers/application_controller.rb | 8 +- app/controllers/dashboard_controller.rb | 3 +- app/controllers/groups_controller.rb | 7 +- app/controllers/projects_controller.rb | 3 +- app/graphql/types/base_field.rb | 21 +++ app/graphql/types/grafana_integration_type.rb | 11 +- app/helpers/projects_helper.rb | 4 +- app/models/generic_commit_status.rb | 15 +- app/models/grafana_integration.rb | 28 +++- app/models/note.rb | 3 +- app/models/project.rb | 4 + app/policies/base_policy.rb | 8 + app/policies/global_policy.rb | 7 + app/presenters/event_presenter.rb | 12 ++ app/services/compare_service.rb | 2 +- .../projects/group_links/destroy_service.rb | 6 + .../projects/import_export/export_service.rb | 6 + .../operations/_grafana_integration.html.haml | 2 +- .../199211-fix-user-popover-glitch.yml | 5 + .../nicolasdular-broadcast-type-api.yml | 5 + .../sarnold-197129-graphql-feature-flag.yml | 5 + config/gitlab.yml.example | 4 +- doc/api/broadcast_messages.md | 16 +- .../graphql/reference/gitlab_schema.graphql | 4 +- doc/api/graphql/reference/gitlab_schema.json | 6 +- doc/api/graphql/reference/index.md | 2 +- doc/integration/omniauth.md | 4 +- doc/raketasks/backup_restore.md | 4 +- doc/user/asciidoc.md | 5 + lib/api/broadcast_messages.rb | 2 + lib/api/commit_statuses.rb | 2 + lib/api/commits.rb | 2 +- lib/api/entities.rb | 14 +- lib/api/files.rb | 1 + lib/api/helpers.rb | 10 ++ lib/api/helpers/headers_helpers.rb | 8 + lib/banzai/reference_parser/base_parser.rb | 8 +- lib/gitlab/asciidoc.rb | 2 + lib/gitlab/asciidoc/include_processor.rb | 11 +- lib/gitlab/git/cross_repo_comparer.rb | 56 +++++++ lib/gitlab/git/repository.rb | 33 +--- lib/gitlab/no_cache_headers.rb | 15 ++ lib/gitlab/reference_extractor.rb | 11 +- .../api/3_create/repository/files_spec.rb | 43 ++++++ .../create_project_with_auto_devops_spec.rb | 6 +- spec/controllers/dashboard_controller_spec.rb | 41 +++++ spec/controllers/groups_controller_spec.rb | 37 ++++- spec/controllers/projects_controller_spec.rb | 40 +++++ .../projects/user_sees_user_popover_spec.rb | 37 +++++ .../notes/components/note_app_spec.js | 2 + spec/graphql/features/authorization_spec.rb | 35 +---- spec/graphql/features/feature_flag_spec.rb | 36 +++++ spec/graphql/types/base_field_spec.rb | 65 ++++++++ spec/helpers/projects_helper_spec.rb | 4 +- spec/javascripts/frequent_items/utils_spec.js | 19 ++- spec/javascripts/user_popovers_spec.js | 83 +++++----- .../mentioned_group_parser_spec.rb | 6 +- .../mentioned_project_parser_spec.rb | 6 +- .../mentioned_user_parser_spec.rb | 6 +- .../reference_parser/project_parser_spec.rb | 8 +- .../gitlab/asciidoc/include_processor_spec.rb | 50 ++++++ spec/lib/gitlab/asciidoc_spec.rb | 18 +++ .../gitlab/git/cross_repo_comparer_spec.rb | 117 ++++++++++++++ spec/lib/gitlab/git/repository_spec.rb | 63 +------- spec/lib/gitlab/no_cache_headers_spec.rb | 17 ++ spec/lib/gitlab/reference_extractor_spec.rb | 32 +++- spec/models/generic_commit_status_spec.rb | 74 +++++++++ spec/models/grafana_integration_spec.rb | 22 ++- spec/models/note_spec.rb | 26 +++- spec/policies/global_policy_spec.rb | 56 +++++++ spec/requests/api/broadcast_messages_spec.rb | 47 +++++- spec/requests/api/commit_statuses_spec.rb | 40 +++++ spec/requests/api/commits_spec.rb | 131 +++++++++++++--- spec/requests/api/files_spec.rb | 12 ++ .../project/grafana_integration_spec.rb | 2 +- spec/requests/api/oauth_tokens_spec.rb | 34 ++-- spec/requests/api/runner_spec.rb | 14 +- .../group_links/destroy_service_spec.rb | 39 ++++- .../import_export/export_service_spec.rb | 17 ++ .../operations/update_service_spec.rb | 4 +- .../projects/update_pages_service_spec.rb | 28 +++- spec/support/helpers/filter_spec_helper.rb | 8 +- spec/support/helpers/graphql_helpers.rb | 33 ++++ .../helpers/reference_parser_helpers.rb | 5 + ...es_zip_with_spoofed_size_shared_context.rb | 41 +++++ 96 files changed, 1628 insertions(+), 372 deletions(-) create mode 100644 changelogs/unreleased/199211-fix-user-popover-glitch.yml create mode 100644 changelogs/unreleased/nicolasdular-broadcast-type-api.yml create mode 100644 changelogs/unreleased/sarnold-197129-graphql-feature-flag.yml create mode 100644 lib/gitlab/git/cross_repo_comparer.rb create mode 100644 lib/gitlab/no_cache_headers.rb create mode 100644 spec/features/projects/user_sees_user_popover_spec.rb create mode 100644 spec/graphql/features/feature_flag_spec.rb create mode 100644 spec/lib/gitlab/asciidoc/include_processor_spec.rb create mode 100644 spec/lib/gitlab/git/cross_repo_comparer_spec.rb create mode 100644 spec/lib/gitlab/no_cache_headers_spec.rb create mode 100644 spec/support/shared_contexts/pages_zip_with_spoofed_size_shared_context.rb diff --git a/CHANGELOG-EE.md b/CHANGELOG-EE.md index 4ec5e9c98fd..ab7d706fc7b 100644 --- a/CHANGELOG-EE.md +++ b/CHANGELOG-EE.md @@ -1,5 +1,9 @@ Please view this file on the master branch, on stable branches it's out of date. +## 12.7.3 + +- No changes. + ## 12.7.1 ### Fixed (1 change) @@ -95,6 +99,14 @@ Please view this file on the master branch, on stable branches it's out of date. - Remove "creations" in gitlab_subscription_histories on gitlab.com. !22278 +## 12.6.6 + +- No changes. + +## 12.6.5 + +- No changes. + ## 12.6.4 - No changes. @@ -207,6 +219,10 @@ Please view this file on the master branch, on stable branches it's out of date. - Update the alerts used in the Dependency List to follow GitLab design guidelines. !21760 +## 12.5.8 + +- No changes. + ## 12.5.5 - No changes. diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 401cc8dd3e7..ba624dacf9a 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -8.19.0 +8.20.0 diff --git a/Gemfile b/Gemfile index e816e1a1fcd..bb486a20ce4 100644 --- a/Gemfile +++ b/Gemfile @@ -65,7 +65,7 @@ gem 'u2f', '~> 0.2.1' # GitLab Pages gem 'validates_hostname', '~> 1.0.6' -gem 'rubyzip', '~> 1.3.0', require: 'zip' +gem 'rubyzip', '~> 2.0.0', require: 'zip' # GitLab Pages letsencrypt support gem 'acme-client', '~> 2.0.5' diff --git a/Gemfile.lock b/Gemfile.lock index c52150cc675..58a4f1ad53d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -274,7 +274,7 @@ GEM et-orbi (1.2.1) tzinfo eventmachine (1.2.7) - excon (0.62.0) + excon (0.71.1) execjs (2.6.0) expression_parser (0.9.0) extended-markdown-filter (0.6.0) @@ -961,7 +961,7 @@ GEM sexp_processor (~> 4.9) rubyntlm (0.6.2) rubypants (0.2.0) - rubyzip (1.3.0) + rubyzip (2.0.0) rugged (0.28.4.1) safe_yaml (1.0.4) sanitize (4.6.6) @@ -1361,7 +1361,7 @@ DEPENDENCIES ruby-prof (~> 1.0.0) ruby-progressbar ruby_parser (~> 3.8) - rubyzip (~> 1.3.0) + rubyzip (~> 2.0.0) rugged (~> 0.28) sanitize (~> 4.6) sassc-rails (~> 2.1.0) diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue index 8cf939254c1..2ffecce0a56 100644 --- a/app/assets/javascripts/frequent_items/components/app.vue +++ b/app/assets/javascripts/frequent_items/components/app.vue @@ -5,7 +5,7 @@ import AccessorUtilities from '~/lib/utils/accessor'; import eventHub from '../event_hub'; import store from '../store/'; import { FREQUENT_ITEMS, STORAGE_KEY } from '../constants'; -import { isMobile, updateExistingFrequentItem } from '../utils'; +import { isMobile, updateExistingFrequentItem, sanitizeItem } from '../utils'; import FrequentItemsSearchInput from './frequent_items_search_input.vue'; import FrequentItemsList from './frequent_items_list.vue'; import frequentItemsMixin from './frequent_items_mixin'; @@ -64,7 +64,9 @@ export default { this.fetchFrequentItems(); } }, - logItemAccess(storageKey, item) { + logItemAccess(storageKey, unsanitizedItem) { + const item = sanitizeItem(unsanitizedItem); + if (!AccessorUtilities.isLocalStorageAccessSafe()) { return false; } diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list.vue index 67ffa97a046..0ece64692ae 100644 --- a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue +++ b/app/assets/javascripts/frequent_items/components/frequent_items_list.vue @@ -1,6 +1,7 @@ @@ -59,7 +63,7 @@ export default { {{ listEmptyMessage }} ['md', 'sm', 'xs'].includes(bp.getBreakpointSize()); @@ -43,3 +44,9 @@ export const updateExistingFrequentItem = (frequentItem, item) => { lastAccessedOn: accessedOverHourAgo ? Date.now() : frequentItem.lastAccessedOn, }; }; + +export const sanitizeItem = item => ({ + ...item, + name: sanitize(item.name.toString(), { allowedTags: [] }), + namespace: sanitize(item.namespace.toString(), { allowedTags: [] }), +}); diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js index a5e38022b8d..4daa8c60e58 100644 --- a/app/assets/javascripts/groups_select.js +++ b/app/assets/javascripts/groups_select.js @@ -1,6 +1,7 @@ import $ from 'jquery'; import axios from './lib/utils/axios_utils'; import Api from './api'; +import { escape } from 'lodash'; import { normalizeHeaders } from './lib/utils/common_utils'; import { __ } from '~/locale'; @@ -75,10 +76,12 @@ const groupsSelect = () => { } }, formatResult(object) { - return `
${object.full_name}
${object.full_path}
`; + return `
${escape( + object.full_name, + )}
${object.full_path}
`; }, formatSelection(object) { - return object.full_name; + return escape(object.full_name); }, dropdownCssClass: 'ajax-groups-dropdown select2-infinite', // we do not want to escape markup since we are displaying html in results diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index be2adb07526..762228dd138 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -14,7 +14,7 @@ import placeholderSystemNote from '../../vue_shared/components/notes/placeholder import skeletonLoadingContainer from '../../vue_shared/components/notes/skeleton_note.vue'; import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user'; import { __ } from '~/locale'; -import initUserPopovers from '../../user_popovers'; +import initUserPopovers from '~/user_popovers'; export default { name: 'NotesApp', diff --git a/app/assets/javascripts/user_popovers.js b/app/assets/javascripts/user_popovers.js index 157d89a3a40..5b9e3817f3a 100644 --- a/app/assets/javascripts/user_popovers.js +++ b/app/assets/javascripts/user_popovers.js @@ -3,108 +3,92 @@ import Vue from 'vue'; import UsersCache from './lib/utils/users_cache'; import UserPopover from './vue_shared/components/user_popover/user_popover.vue'; -let renderedPopover; -let renderFn; +const removeTitle = el => { + // Removing titles so its not showing tooltips also -const handleUserPopoverMouseOut = event => { - const { target } = event; - target.removeEventListener('mouseleave', handleUserPopoverMouseOut); + el.dataset.originalTitle = ''; + el.setAttribute('title', ''); +}; - if (renderFn) { - clearTimeout(renderFn); - } - if (renderedPopover) { - renderedPopover.$destroy(); - renderedPopover = null; - } - target.removeAttribute('aria-describedby'); +const getPreloadedUserInfo = dataset => { + const userId = dataset.user || dataset.userId; + const { username, name, avatarUrl } = dataset; + + return { + userId, + username, + name, + avatarUrl, + }; }; /** * Adds a UserPopover component to the body, hands over as much data as the target element has in data attributes. * loads based on data-user-id more data about a user from the API and sets it on the popover */ -const handleUserPopoverMouseOver = event => { - const { target } = event; - // Add listener to actually remove it again - target.addEventListener('mouseleave', handleUserPopoverMouseOut); +const populateUserInfo = user => { + const { userId } = user; - renderFn = setTimeout(() => { - // Helps us to use current markdown setup without maybe breaking or duplicating for now - if (target.dataset.user) { - target.dataset.userId = target.dataset.user; - // Removing titles so its not showing tooltips also - target.dataset.originalTitle = ''; - target.setAttribute('title', ''); - } + return Promise.all([UsersCache.retrieveById(userId), UsersCache.retrieveStatusById(userId)]).then( + ([userData, status]) => { + if (userData) { + Object.assign(user, { + avatarUrl: userData.avatar_url, + username: userData.username, + name: userData.name, + location: userData.location, + bio: userData.bio, + organization: userData.organization, + loaded: true, + }); + } - const { userId, username, name, avatarUrl } = target.dataset; + if (status) { + Object.assign(user, { + status, + }); + } + + return user; + }, + ); +}; + +export default (elements = document.querySelectorAll('.js-user-link')) => { + const userLinks = Array.from(elements); + + return userLinks.map(el => { + const UserPopoverComponent = Vue.extend(UserPopover); const user = { - userId, - username, - name, - avatarUrl, location: null, bio: null, organization: null, status: null, loaded: false, }; - if (userId || username) { - const UserPopoverComponent = Vue.extend(UserPopover); - renderedPopover = new UserPopoverComponent({ - propsData: { - target, - user, - }, - }); + const renderedPopover = new UserPopoverComponent({ + propsData: { + target: el, + user, + }, + }); - renderedPopover.$mount(); + renderedPopover.$mount(); - UsersCache.retrieveById(userId) - .then(userData => { - if (!userData) { - return undefined; - } + el.addEventListener('mouseenter', ({ target }) => { + removeTitle(target); + const preloadedUserInfo = getPreloadedUserInfo(target.dataset); - Object.assign(user, { - avatarUrl: userData.avatar_url, - username: userData.username, - name: userData.name, - location: userData.location, - bio: userData.bio, - organization: userData.organization, - status: userData.status, - loaded: true, - }); + Object.assign(user, preloadedUserInfo); - if (userData.status) { - return Promise.resolve(); - } + if (preloadedUserInfo.userId) { + populateUserInfo(user); + } + }); + el.addEventListener('mouseleave', ({ target }) => { + target.removeAttribute('aria-describedby'); + }); - return UsersCache.retrieveStatusById(userId); - }) - .then(status => { - if (!status) { - return; - } - - Object.assign(user, { - status, - }); - }) - .catch(() => { - renderedPopover.$destroy(); - renderedPopover = null; - }); - } - }, 200); // 200ms delay so not every mouseover triggers Popover + API Call -}; - -export default elements => { - const userLinks = elements || [...document.querySelectorAll('.js-user-link')]; - - userLinks.forEach(el => { - el.addEventListener('mouseenter', handleUserPopoverMouseOver); + return renderedPopover; }); }; diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue index 37e3643bf6c..ca25d9ee738 100644 --- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue +++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue @@ -56,19 +56,16 @@ export default {