diff options
-rw-r--r-- | .gitlab/issue_templates/Security developer workflow.md | 7 | ||||
-rw-r--r-- | .gitlab/merge_request_templates/Security Release.md | 7 | ||||
-rw-r--r-- | app/controllers/profiles/preferences_controller.rb | 12 | ||||
-rw-r--r-- | app/views/layouts/nav/sidebar/_group.html.haml | 2 | ||||
-rw-r--r-- | app/views/profiles/preferences/show.html.haml | 3 | ||||
-rwxr-xr-x | bin/secpick | 16 | ||||
-rw-r--r-- | doc/install/installation.md | 4 | ||||
-rw-r--r-- | spec/javascripts/notes/components/noteable_note_spec.js | 93 |
8 files changed, 50 insertions, 94 deletions
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md index 4bc4215d21b..da2e2a7f87f 100644 --- a/.gitlab/issue_templates/Security developer workflow.md +++ b/.gitlab/issue_templates/Security developer workflow.md @@ -20,10 +20,9 @@ Set the title to: `Description of the original issue` - [ ] Once the MR is ready to be merged, create MRs targetting the last 3 releases, plus the current RC if between the 7th and 22nd of the month. - [ ] At this point, it might be easy to squash the commits from the MR into one - You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation] - - [ ] Create the branch `security-X-Y` from `X-Y-stable` if it doesn't exist (and make sure it's up to date with stable) - - [ ] Create each MR targetting the security branch `security-X-Y` - - [ ] Add the ~security label and prefix with the version `WIP: [X.Y]` the title of the MR -- [ ] Add the ~"Merge into Security" label to all of the MRs. + - [ ] Create each MR targetting the stable branch `stable-X-Y`, using the "Security Release" merge request template. + - Every merge request will have its own set of TODOs, so make sure to + complete those. - [ ] Make sure all MRs have a link in the [links section](#links) [secpick documentation]: https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#secpick-script diff --git a/.gitlab/merge_request_templates/Security Release.md b/.gitlab/merge_request_templates/Security Release.md index 9a0979f27a7..adf70053f8f 100644 --- a/.gitlab/merge_request_templates/Security Release.md +++ b/.gitlab/merge_request_templates/Security Release.md @@ -4,6 +4,9 @@ This MR should be created on `dev.gitlab.org`. See [the general developer security release guidelines](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md). +This merge request _must not_ close the corresponding security issue _unless_ it +targets master. + --> ## Related issues @@ -12,7 +15,7 @@ See [the general developer security release guidelines](https://gitlab.com/gitla ## Developer checklist - [ ] Link to the developer security workflow issue on `dev.gitlab.org` -- [ ] MR targets `master` or `security-X-Y` for backports +- [ ] MR targets `master`, or `stable-X-Y` for backports - [ ] Milestone is set for the version this MR applies to - [ ] Title of this MR is the same as for all backports - [ ] A [CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html) is added without a `merge_request` value, with `type` set to `security` @@ -25,4 +28,4 @@ See [the general developer security release guidelines](https://gitlab.com/gitla - [ ] Correct milestone is applied and the title is matching across all backports - [ ] Assigned to `@gitlab-release-tools-bot` with passing CI pipelines -/label ~security ~"Merge into Security" +/label ~security diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb index 37ac11dc6a1..a27e3cceaeb 100644 --- a/app/controllers/profiles/preferences_controller.rb +++ b/app/controllers/profiles/preferences_controller.rb @@ -33,12 +33,10 @@ class Profiles::PreferencesController < Profiles::ApplicationController end def preferences_params - params.require(:user).permit( - :color_scheme_id, - :layout, - :dashboard, - :project_view, - :theme_id - ) + params.require(:user).permit(preferences_param_names) + end + + def preferences_param_names + [:color_scheme_id, :layout, :dashboard, :project_view, :theme_id] end end diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml index bf475c07711..3fbaaafe89e 100644 --- a/app/views/layouts/nav/sidebar/_group.html.haml +++ b/app/views/layouts/nav/sidebar/_group.html.haml @@ -36,7 +36,7 @@ %span = _('Activity') - = render_if_exists 'groups/sidebar/security_dashboard' + = render_if_exists 'groups/sidebar/security_dashboard' # EE-specific - if group_sidebar_link?(:contribution_analytics) = nav_link(path: 'analytics#show') do diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml index 7c378633667..c1616810185 100644 --- a/app/views/profiles/preferences/show.html.haml +++ b/app/views/profiles/preferences/show.html.haml @@ -51,6 +51,9 @@ = f.label :dashboard, class: 'label-bold' do Default dashboard = f.select :dashboard, dashboard_choices, {}, class: 'form-control' + + = render_if_exists 'profiles/preferences/group_overview_selector', f: f # EE-specific + .form-group = f.label :project_view, class: 'label-bold' do Project overview content diff --git a/bin/secpick b/bin/secpick index be120a304c9..ca9d901120d 100755 --- a/bin/secpick +++ b/bin/secpick @@ -10,6 +10,7 @@ using Rainbow module Secpick BRANCH_PREFIX = 'security'.freeze + STABLE_PREFIX = 'stable'.freeze DEFAULT_REMOTE = 'dev'.freeze NEW_MR_URL = 'https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/new'.freeze @@ -36,16 +37,16 @@ module Secpick branch.freeze end - def security_branch - "#{BRANCH_PREFIX}-#{@options[:version]}".tap do |name| + def stable_branch + "#{STABLE_PREFIX}-#{@options[:version]}".tap do |name| name << "-ee" if ee? end.freeze end def git_commands - ["git fetch #{@options[:remote]} #{security_branch}", - "git checkout #{security_branch}", - "git pull #{@options[:remote]} #{security_branch}", + ["git fetch #{@options[:remote]} #{stable_branch}", + "git checkout #{stable_branch}", + "git pull #{@options[:remote]} #{stable_branch}", "git checkout -B #{source_branch}", "git cherry-pick #{@options[:sha]}", "git push #{@options[:remote]} #{source_branch}", @@ -56,9 +57,8 @@ module Secpick { merge_request: { source_branch: source_branch, - target_branch: security_branch, - title: "[#{@options[:version].tr('-', '.')}] ", - description: '/label ~security ~"Merge into Security"' + target_branch: stable_branch, + description: '/label ~security' } } end diff --git a/doc/install/installation.md b/doc/install/installation.md index 1f65e3415d1..45a76bd1d01 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -139,8 +139,8 @@ Then select 'Internet Site' and press enter to confirm the hostname. The Ruby interpreter is required to run GitLab. -**Note:** The current supported Ruby (MRI) version is 2.3.x. GitLab 9.0 dropped -support for Ruby 2.1.x. +**Note:** The current supported Ruby (MRI) version is 2.5.x. GitLab 11.6 + dropped support for Ruby 2.4.x. The use of Ruby version managers such as [RVM], [rbenv] or [chruby] with GitLab in production, frequently leads to hard to diagnose problems. For example, diff --git a/spec/javascripts/notes/components/noteable_note_spec.js b/spec/javascripts/notes/components/noteable_note_spec.js index 4a143ef089a..8ade6fc2ced 100644 --- a/spec/javascripts/notes/components/noteable_note_spec.js +++ b/spec/javascripts/notes/components/noteable_note_spec.js @@ -1,105 +1,64 @@ +import $ from 'jquery'; import _ from 'underscore'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import Vue from 'vue'; import createStore from '~/notes/stores'; import issueNote from '~/notes/components/noteable_note.vue'; -import NoteHeader from '~/notes/components/note_header.vue'; -import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; -import NoteActions from '~/notes/components/note_actions.vue'; -import NoteBody from '~/notes/components/note_body.vue'; import { noteableDataMock, notesDataMock, note } from '../mock_data'; describe('issue_note', () => { let store; - let wrapper; + let vm; beforeEach(() => { + const Component = Vue.extend(issueNote); + store = createStore(); store.dispatch('setNoteableData', noteableDataMock); store.dispatch('setNotesData', notesDataMock); - const localVue = createLocalVue(); - wrapper = shallowMount(issueNote, { + vm = new Component({ store, propsData: { note, }, - sync: false, - localVue, - }); + }).$mount(); }); afterEach(() => { - wrapper.destroy(); + vm.$destroy(); }); it('should render user information', () => { - const { author } = note; - const avatar = wrapper.find(UserAvatarLink); - const avatarProps = avatar.props(); - - expect(avatarProps.linkHref).toBe(author.path); - expect(avatarProps.imgSrc).toBe(author.avatar_url); - expect(avatarProps.imgAlt).toBe(author.name); - expect(avatarProps.imgSize).toBe(40); + expect(vm.$el.querySelector('.user-avatar-link img').getAttribute('src')).toEqual( + note.author.avatar_url, + ); }); it('should render note header content', () => { - const noteHeader = wrapper.find(NoteHeader); - const noteHeaderProps = noteHeader.props(); + const el = vm.$el.querySelector('.note-header .note-header-author-name'); - expect(noteHeaderProps.author).toEqual(note.author); - expect(noteHeaderProps.createdAt).toEqual(note.created_at); - expect(noteHeaderProps.noteId).toEqual(note.id); + expect(el.textContent.trim()).toEqual(note.author.name); }); it('should render note actions', () => { - const { author } = note; - const noteActions = wrapper.find(NoteActions); - const noteActionsProps = noteActions.props(); - - expect(noteActionsProps.authorId).toBe(author.id); - expect(noteActionsProps.noteId).toBe(note.id); - expect(noteActionsProps.noteUrl).toBe(note.noteable_note_url); - expect(noteActionsProps.accessLevel).toBe(note.human_access); - expect(noteActionsProps.canEdit).toBe(note.current_user.can_edit); - expect(noteActionsProps.canAwardEmoji).toBe(note.current_user.can_award_emoji); - expect(noteActionsProps.canDelete).toBe(note.current_user.can_edit); - expect(noteActionsProps.canReportAsAbuse).toBe(true); - expect(noteActionsProps.canResolve).toBe(false); - expect(noteActionsProps.reportAbusePath).toBe(note.report_abuse_path); - expect(noteActionsProps.resolvable).toBe(false); - expect(noteActionsProps.isResolved).toBe(false); - expect(noteActionsProps.isResolving).toBe(false); - expect(noteActionsProps.resolvedBy).toEqual({}); + expect(vm.$el.querySelector('.note-actions')).toBeDefined(); }); it('should render issue body', () => { - const noteBody = wrapper.find(NoteBody); - const noteBodyProps = noteBody.props(); - - expect(noteBodyProps.note).toEqual(note); - expect(noteBodyProps.line).toBe(null); - expect(noteBodyProps.canEdit).toBe(note.current_user.can_edit); - expect(noteBodyProps.isEditing).toBe(false); - expect(noteBodyProps.helpPagePath).toBe(''); + expect(vm.$el.querySelector('.note-text').innerHTML).toEqual(note.note_html); }); it('prevents note preview xss', done => { const imgSrc = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; const noteBody = `<img src="${imgSrc}" onload="alert(1)" />`; const alertSpy = spyOn(window, 'alert'); - store.hotUpdate({ - actions: { - updateNote() {}, - }, - }); - const noteBodyComponent = wrapper.find(NoteBody); + vm.updateNote = () => new Promise($.noop); - noteBodyComponent.vm.$emit('handleFormUpdate', noteBody, null, () => {}); + vm.formUpdateHandler(noteBody, null, $.noop); setTimeout(() => { expect(alertSpy).not.toHaveBeenCalled(); - expect(wrapper.vm.note.note_html).toEqual(_.escape(noteBody)); + expect(vm.note.note_html).toEqual(_.escape(noteBody)); done(); }, 0); }); @@ -107,23 +66,17 @@ describe('issue_note', () => { describe('cancel edit', () => { it('restores content of updated note', done => { const noteBody = 'updated note text'; - store.hotUpdate({ - actions: { - updateNote() {}, - }, - }); - const noteBodyComponent = wrapper.find(NoteBody); - noteBodyComponent.vm.resetAutoSave = () => {}; + vm.updateNote = () => Promise.resolve(); - noteBodyComponent.vm.$emit('handleFormUpdate', noteBody, null, () => {}); + vm.formUpdateHandler(noteBody, null, $.noop); setTimeout(() => { - expect(wrapper.vm.note.note_html).toEqual(noteBody); + expect(vm.note.note_html).toEqual(noteBody); - noteBodyComponent.vm.$emit('cancelForm'); + vm.formCancelHandler(); setTimeout(() => { - expect(wrapper.vm.note.note_html).toEqual(noteBody); + expect(vm.note.note_html).toEqual(noteBody); done(); }); |