From a57cec4bb89b61d210d4e413571b1d85d76179f6 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 16 Feb 2021 09:09:36 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../javascripts/lib/utils/url_utility.js | 44 +++++++++ .../components/learn_gitlab_a.vue | 27 ++++++ .../components/learn_gitlab_b.vue | 27 ++++++ .../projects/learn_gitlab/constants/index.js | 12 +++ .../projects/learn_gitlab/index/index.js | 25 +++++ .../projects/settings/access_dropdown.js | 79 +++++++--------- .../content_viewer/viewers/image_viewer.vue | 8 +- app/controllers/concerns/boards_responses.rb | 6 +- .../projects/learn_gitlab_controller.rb | 19 ++++ .../settings/repository_controller.rb | 1 - app/helpers/learn_gitlab_helper.rb | 60 ++++++++++++ app/helpers/projects_helper.rb | 2 + .../clusters/applications/cert_manager.rb | 2 + .../clusters/applications/crossplane.rb | 2 + app/models/clusters/applications/ingress.rb | 2 + app/models/clusters/applications/jupyter.rb | 2 + app/models/clusters/applications/knative.rb | 2 + app/models/onboarding_progress.rb | 4 + .../protected_branch/push_access_level.rb | 2 +- .../layouts/nav/sidebar/_project.html.haml | 7 ++ .../projects/learn_gitlab/index.html.haml | 4 + .../_create_protected_branch.html.haml | 4 +- .../_update_protected_branch.html.haml | 4 +- changelogs/unreleased/deprecate_gma_apps.yml | 5 + ...flag-deploy_keys_on_protected_branches.yml | 5 + ...defect-urlencode-image-diff-octothorpe.yml | 5 + .../learn_gitlab_a_experiment_percentage.yml} | 12 +-- .../learn_gitlab_b_experiment_percentage.yml | 8 ++ config/routes/project.rb | 2 + danger/roulette/Dangerfile | 4 +- doc/user/project/protected_branches.md | 1 + doc/user/project/requirements/index.md | 10 +- lib/gitlab/experimentation.rb | 6 ++ lib/gitlab/git_access.rb | 10 +- locale/gitlab.pot | 42 +++++++-- .../projects/learn_gitlab_controller_spec.rb | 44 +++++++++ spec/features/protected_branches_spec.rb | 6 +- spec/frontend/lib/utils/url_utility_spec.js | 33 +++++++ .../__snapshots__/learn_gitlab_a_spec.js.snap | 66 ++++++++++++++ .../__snapshots__/learn_gitlab_b_spec.js.snap | 66 ++++++++++++++ .../components/learn_gitlab_a_spec.js | 63 +++++++++++++ .../components/learn_gitlab_b_spec.js | 63 +++++++++++++ .../projects/settings/access_dropdown_spec.js | 1 - .../viewers/image_viewer_spec.js | 10 ++ spec/helpers/learn_gitlab_helper_spec.rb | 91 +++++++++++++++++++ spec/helpers/projects_helper_spec.rb | 15 +++ spec/models/onboarding_progress_spec.rb | 16 ++++ .../push_access_level_spec.rb | 10 -- ...nches_access_control_ce_shared_examples.rb | 2 + ...cted_branches_with_deploy_keys_examples.rb | 3 +- 50 files changed, 847 insertions(+), 97 deletions(-) create mode 100644 app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue create mode 100644 app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue create mode 100644 app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js create mode 100644 app/assets/javascripts/pages/projects/learn_gitlab/index/index.js create mode 100644 app/controllers/projects/learn_gitlab_controller.rb create mode 100644 app/helpers/learn_gitlab_helper.rb create mode 100644 app/views/projects/learn_gitlab/index.html.haml create mode 100644 changelogs/unreleased/deprecate_gma_apps.yml create mode 100644 changelogs/unreleased/remove-feature-flag-deploy_keys_on_protected_branches.yml create mode 100644 changelogs/unreleased/tor-defect-urlencode-image-diff-octothorpe.yml rename config/feature_flags/{development/deploy_keys_on_protected_branches.yml => experiment/learn_gitlab_a_experiment_percentage.yml} (55%) create mode 100644 config/feature_flags/experiment/learn_gitlab_b_experiment_percentage.yml create mode 100644 spec/controllers/projects/learn_gitlab_controller_spec.rb create mode 100644 spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap create mode 100644 spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap create mode 100644 spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js create mode 100644 spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js create mode 100644 spec/helpers/learn_gitlab_helper_spec.rb diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js index 0b920ba8e7a..cc2cf787a8f 100644 --- a/app/assets/javascripts/lib/utils/url_utility.js +++ b/app/assets/javascripts/lib/utils/url_utility.js @@ -16,6 +16,50 @@ function decodeUrlParameter(val) { return decodeURIComponent(val.replace(/\+/g, '%20')); } +/** + * Safely encodes a string to be used as a path + * + * Note: This function DOES encode typical URL parts like ?, =, &, #, and + + * If you need to use search parameters or URL fragments, they should be + * added AFTER calling this function, not before. + * + * Usecase: An image filename is stored verbatim, and you need to load it in + * the browser. + * + * Example: /some_path/file #1.jpg ==> /some_path/file%20%231.jpg + * Example: /some-path/file! Final!.jpg ==> /some-path/file%21%20Final%21.jpg + * + * Essentially, if a character *could* present a problem in a URL, it's escaped + * to the hexadecimal representation instead. This means it's a bit more + * aggressive than encodeURIComponent: that built-in function doesn't + * encode some characters that *could* be problematic, so this function + * adds them (#, !, ~, *, ', (, and )). + * Additionally, encodeURIComponent *does* encode `/`, but we want safer + * URLs, not non-functional URLs, so this function DEcodes slashes ('%2F'). + * + * @param {String} potentiallyUnsafePath + * @returns {String} + */ +export function encodeSaferUrl(potentiallyUnsafePath) { + const unencode = ['%2F']; + const encode = ['#', '!', '~', '\\*', "'", '\\(', '\\)']; + let saferPath = encodeURIComponent(potentiallyUnsafePath); + + unencode.forEach((code) => { + saferPath = saferPath.replace(new RegExp(code, 'g'), decodeURIComponent(code)); + }); + encode.forEach((code) => { + const encodedValue = code + .codePointAt(code.length - 1) + .toString(16) + .toUpperCase(); + + saferPath = saferPath.replace(new RegExp(code, 'g'), `%${encodedValue}`); + }); + + return saferPath; +} + export function cleanLeadingSeparator(path) { return path.replace(PATH_SEPARATOR_LEADING_REGEX, ''); } diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue new file mode 100644 index 00000000000..0393793bfe1 --- /dev/null +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue @@ -0,0 +1,27 @@ + + diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue new file mode 100644 index 00000000000..0393793bfe1 --- /dev/null +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue @@ -0,0 +1,27 @@ + + diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js new file mode 100644 index 00000000000..8606af29785 --- /dev/null +++ b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js @@ -0,0 +1,12 @@ +import { s__ } from '~/locale'; + +export const ACTION_TEXT = { + gitWrite: s__('LearnGitLab|Create a repository'), + userAdded: s__('LearnGitLab|Invite your colleagues'), + pipelineCreated: s__('LearnGitLab|Set-up CI/CD'), + trialStarted: s__('LearnGitLab|Start a free trial of GitLab Gold'), + codeOwnersEnabled: s__('LearnGitLab|Add code owners'), + requiredMrApprovalsEnabled: s__('LearnGitLab|Enable require merge approvals'), + mergeRequestCreated: s__('LearnGitLab|Submit a merge request (MR)'), + securityScanEnabled: s__('LearnGitLab|Run a Security scan using CI/CD'), +}; diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js new file mode 100644 index 00000000000..c4dec89b984 --- /dev/null +++ b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js @@ -0,0 +1,25 @@ +import Vue from 'vue'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; +import LearnGitlabA from '../components/learn_gitlab_a.vue'; +import LearnGitlabB from '../components/learn_gitlab_b.vue'; + +function initLearnGitlab() { + const el = document.getElementById('js-learn-gitlab-app'); + + if (!el) { + return false; + } + + const actions = convertObjectPropsToCamelCase(JSON.parse(el.dataset.actions)); + + const { learnGitlabA } = gon.experiments; + + return new Vue({ + el, + render(createElement) { + return createElement(learnGitlabA ? LearnGitlabA : LearnGitlabB, { props: { actions } }); + }, + }); +} + +initLearnGitlab(); diff --git a/app/assets/javascripts/projects/settings/access_dropdown.js b/app/assets/javascripts/projects/settings/access_dropdown.js index 209ae9927cf..a5e53ee3927 100644 --- a/app/assets/javascripts/projects/settings/access_dropdown.js +++ b/app/assets/javascripts/projects/settings/access_dropdown.js @@ -11,7 +11,6 @@ export default class AccessDropdown { const { $dropdown, accessLevel, accessLevelsData, hasLicense = true } = options; this.options = options; this.hasLicense = hasLicense; - this.deployKeysOnProtectedBranchesEnabled = gon.features.deployKeysOnProtectedBranches; this.groups = []; this.accessLevel = accessLevel; this.accessLevelsData = accessLevelsData.roles; @@ -330,11 +329,7 @@ export default class AccessDropdown { ); }) .catch(() => { - if (this.deployKeysOnProtectedBranchesEnabled) { - createFlash({ message: __('Failed to load groups, users and deploy keys.') }); - } else { - createFlash({ message: __('Failed to load groups & users.') }); - } + createFlash({ message: __('Failed to load groups, users and deploy keys.') }); }); } else { this.getDeployKeys(query) @@ -445,35 +440,33 @@ export default class AccessDropdown { } } - if (this.deployKeysOnProtectedBranchesEnabled) { - const deployKeys = deployKeysResponse.map((response) => { - const { - id, - fingerprint, - title, - owner: { avatar_url, name, username }, - } = response; + const deployKeys = deployKeysResponse.map((response) => { + const { + id, + fingerprint, + title, + owner: { avatar_url, name, username }, + } = response; - const shortFingerprint = `(${fingerprint.substring(0, 14)}...)`; + const shortFingerprint = `(${fingerprint.substring(0, 14)}...)`; - return { - id, - title: title.concat(' ', shortFingerprint), - avatar_url, - fullname: name, - username, - type: LEVEL_TYPES.DEPLOY_KEY, - }; - }); + return { + id, + title: title.concat(' ', shortFingerprint), + avatar_url, + fullname: name, + username, + type: LEVEL_TYPES.DEPLOY_KEY, + }; + }); - if (this.accessLevel === ACCESS_LEVELS.PUSH) { - if (deployKeys.length) { - consolidatedData = consolidatedData.concat( - [{ type: 'divider' }], - [{ type: 'header', content: s__('AccessDropdown|Deploy Keys') }], - deployKeys, - ); - } + if (this.accessLevel === ACCESS_LEVELS.PUSH) { + if (deployKeys.length) { + consolidatedData = consolidatedData.concat( + [{ type: 'divider' }], + [{ type: 'header', content: s__('AccessDropdown|Deploy Keys') }], + deployKeys, + ); } } @@ -501,19 +494,15 @@ export default class AccessDropdown { } getDeployKeys(query) { - if (this.deployKeysOnProtectedBranchesEnabled) { - return axios.get(this.buildUrl(gon.relative_url_root, this.deployKeysPath), { - params: { - search: query, - per_page: 20, - active: true, - project_id: gon.current_project_id, - push_code: true, - }, - }); - } - - return Promise.resolve({ data: [] }); + return axios.get(this.buildUrl(gon.relative_url_root, this.deployKeysPath), { + params: { + search: query, + per_page: 20, + active: true, + project_id: gon.current_project_id, + push_code: true, + }, + }); } buildUrl(urlRoot, url) { diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue index 9ece6a52805..a49eb7fd611 100644 --- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue @@ -1,6 +1,7 @@