diff --git a/CHANGELOG-EE.md b/CHANGELOG-EE.md index 9226e23795b..5ba1528d8dd 100644 --- a/CHANGELOG-EE.md +++ b/CHANGELOG-EE.md @@ -1,5 +1,12 @@ Please view this file on the master branch, on stable branches it's out of date. +## 12.5.4 + +### Security (1 change) + +- Fix stale Elasticsearch permissions when moving group from public group to private parent group. + + ## 12.5.3 ### Performance (1 change) @@ -251,6 +258,13 @@ Please view this file on the master branch, on stable branches it's out of date. - Docs for protected branch code owner approval API. !17132 +## 12.3.9 + +### Security (1 change) + +- Fix stale Elasticsearch permissions when moving group from public group to private parent group. + + ## 12.3.7 ### Security (6 changes) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c550c8c9db..7761d9ed0ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 12.5.4 + +### Security (1 change) + +- Update maven_file_name_regex for full string match. + + ## 12.5.3 ### Fixed (4 changes) @@ -756,6 +763,13 @@ entry. - Remove Postgresql specific setup tasks and move to schema.rb. +## 12.3.9 + +### Security (1 change) + +- Update maven_file_name_regex for full string match. + + ## 12.3.7 ### Security (12 changes) diff --git a/app/helpers/award_emoji_helper.rb b/app/helpers/award_emoji_helper.rb index 4bc5a7b090e..13df53a751b 100644 --- a/app/helpers/award_emoji_helper.rb +++ b/app/helpers/award_emoji_helper.rb @@ -7,7 +7,7 @@ module AwardEmojiHelper if awardable.is_a?(Note) # We render a list of notes very frequently and calling the specific method is a lot faster than the generic one (4.5x) if awardable.for_personal_snippet? - toggle_award_emoji_snippet_note_path(awardable.noteable, awardable) + gitlab_toggle_award_emoji_snippet_note_path(awardable.noteable, awardable) else toggle_award_emoji_project_note_path(@project, awardable.id) end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 656e6039dbd..c9fb28d0299 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -141,7 +141,7 @@ module BlobHelper if @build && @entry raw_project_job_artifacts_url(@project, @build, path: @entry.path, **kwargs) elsif @snippet - raw_snippet_url(@snippet) + gitlab_raw_snippet_url(@snippet) elsif @blob project_raw_url(@project, @id, **kwargs) end diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index 3810041b2af..78c41257404 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -194,88 +194,84 @@ module GitlabRoutingHelper take_ownership_project_pipeline_schedule_path(project, schedule, *args) end - def snippet_path(snippet, *args) - if snippet.type == "ProjectSnippet" - application_url_helpers.project_snippet_path(snippet.project, snippet, *args) + def gitlab_snippet_path(snippet, *args) + if snippet.is_a?(ProjectSnippet) + project_snippet_path(snippet.project, snippet, *args) else new_args = snippet_query_params(snippet, *args) - application_url_helpers.snippet_path(snippet, *new_args) + snippet_path(snippet, *new_args) end end - def snippet_url(snippet, *args) - if snippet.type == "ProjectSnippet" - application_url_helpers.project_snippet_url(snippet.project, snippet, *args) + def gitlab_snippet_url(snippet, *args) + if snippet.is_a?(ProjectSnippet) + project_snippet_url(snippet.project, snippet, *args) else new_args = snippet_query_params(snippet, *args) - application_url_helpers.snippet_url(snippet, *new_args) + snippet_url(snippet, *new_args) end end - def raw_snippet_path(snippet, *args) - if snippet.type == "ProjectSnippet" - application_url_helpers.raw_project_snippet_path(snippet.project, snippet, *args) + def gitlab_raw_snippet_path(snippet, *args) + if snippet.is_a?(ProjectSnippet) + raw_project_snippet_path(snippet.project, snippet, *args) else new_args = snippet_query_params(snippet, *args) - application_url_helpers.raw_snippet_path(snippet, *new_args) + raw_snippet_path(snippet, *new_args) end end - def raw_snippet_url(snippet, *args) - if snippet.type == "ProjectSnippet" - application_url_helpers.raw_project_snippet_url(snippet.project, snippet, *args) + def gitlab_raw_snippet_url(snippet, *args) + if snippet.is_a?(ProjectSnippet) + raw_project_snippet_url(snippet.project, snippet, *args) else new_args = snippet_query_params(snippet, *args) - application_url_helpers.raw_snippet_url(snippet, *new_args) + raw_snippet_url(snippet, *new_args) end end - def snippet_notes_path(snippet, *args) + def gitlab_snippet_notes_path(snippet, *args) new_args = snippet_query_params(snippet, *args) - application_url_helpers.snippet_notes_path(snippet, *new_args) + snippet_notes_path(snippet, *new_args) end - def snippet_notes_url(snippet, *args) + def gitlab_snippet_notes_url(snippet, *args) new_args = snippet_query_params(snippet, *args) - application_url_helpers.snippet_notes_url(snippet, *new_args) + snippet_notes_url(snippet, *new_args) end - def snippet_note_path(snippet, note, *args) + def gitlab_snippet_note_path(snippet, note, *args) new_args = snippet_query_params(snippet, *args) - application_url_helpers.snippet_note_path(snippet, note, *new_args) + snippet_note_path(snippet, note, *new_args) end - def snippet_note_url(snippet, note, *args) + def gitlab_snippet_note_url(snippet, note, *args) new_args = snippet_query_params(snippet, *args) - application_url_helpers.snippet_note_url(snippet, note, *new_args) + snippet_note_url(snippet, note, *new_args) end - def toggle_award_emoji_snippet_note_path(snippet, note, *args) + def gitlab_toggle_award_emoji_snippet_note_path(snippet, note, *args) new_args = snippet_query_params(snippet, *args) - application_url_helpers.toggle_award_emoji_snippet_note_path(snippet, note, *new_args) + toggle_award_emoji_snippet_note_path(snippet, note, *new_args) end - def toggle_award_emoji_snippet_note_url(snippet, note, *args) + def gitlab_toggle_award_emoji_snippet_note_url(snippet, note, *args) new_args = snippet_query_params(snippet, *args) - application_url_helpers.toggle_award_emoji_snippet_note_url(snippet, note, *new_args) + toggle_award_emoji_snippet_note_url(snippet, note, *new_args) end - def toggle_award_emoji_snippet_path(snippet, *args) + def gitlab_toggle_award_emoji_snippet_path(snippet, *args) new_args = snippet_query_params(snippet, *args) - application_url_helpers.toggle_award_emoji_snippet_path(snippet, *new_args) + toggle_award_emoji_snippet_path(snippet, *new_args) end - def toggle_award_emoji_snippet_url(snippet, *args) + def gitlab_toggle_award_emoji_snippet_url(snippet, *args) new_args = snippet_query_params(snippet, *args) - application_url_helpers.toggle_award_emoji_snippet_url(snippet, *new_args) + toggle_award_emoji_snippet_url(snippet, *new_args) end private - def application_url_helpers - Gitlab::Routing.url_helpers - end - def snippet_query_params(snippet, *args) opts = case args.last when Hash diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 18451bc5273..8c75a4a13e8 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -279,21 +279,32 @@ module IssuablesHelper initialDescriptionText: issuable.description, initialTaskStatus: issuable.task_status } - - data[:hasClosingMergeRequest] = issuable.merge_requests_count(current_user) != 0 if issuable.is_a?(Issue) - data[:zoomMeetingUrl] = ZoomMeeting.canonical_meeting_url(issuable) if issuable.is_a?(Issue) - - if parent.is_a?(Group) - data[:groupPath] = parent.path - else - data.merge!(projectPath: ref_project.path, projectNamespace: ref_project.namespace.full_path) - end - + data.merge!(issue_only_initial_data(issuable)) + data.merge!(path_data(parent)) data.merge!(updated_at_by(issuable)) data end + def issue_only_initial_data(issuable) + return {} unless issuable.is_a?(Issue) + + { + hasClosingMergeRequest: issuable.merge_requests_count(current_user) != 0, + zoomMeetingUrl: ZoomMeeting.canonical_meeting_url(issuable), + sentryIssueIdentifier: SentryIssue.find_by(issue: issuable)&.sentry_issue_identifier # rubocop:disable CodeReuse/ActiveRecord + } + end + + def path_data(parent) + return { groupPath: parent.path } if parent.is_a?(Group) + + { + projectPath: ref_project.path, + projectNamespace: ref_project.namespace.full_path + } + end + def updated_at_by(issuable) return {} unless issuable.edited? diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index fbbdebaa623..acf9f8c5b5b 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -95,7 +95,7 @@ module NotesHelper def notes_url(params = {}) if @snippet.is_a?(PersonalSnippet) - snippet_notes_path(@snippet, params) + gitlab_snippet_notes_path(@snippet, params) else params.merge!(target_id: @noteable.id, target_type: @noteable.class.name.underscore) @@ -105,7 +105,7 @@ module NotesHelper def note_url(note, project = @project) if note.noteable.is_a?(PersonalSnippet) - snippet_note_path(note.noteable, note) + gitlab_snippet_note_path(note.noteable, note) else project_note_path(project, note) end @@ -126,7 +126,7 @@ module NotesHelper def new_form_url return unless @snippet.is_a?(PersonalSnippet) - snippet_notes_path(@snippet) + gitlab_snippet_notes_path(@snippet) end def can_create_note? diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb index 7d7d8646c25..7b93d44190e 100644 --- a/app/helpers/snippets_helper.rb +++ b/app/helpers/snippets_helper.rb @@ -13,7 +13,7 @@ module SnippetsHelper def download_raw_snippet_button(snippet) link_to(icon('download'), - raw_snippet_path(snippet, inline: false), + gitlab_raw_snippet_path(snippet, inline: false), target: '_blank', rel: 'noopener noreferrer', class: "btn btn-sm has-tooltip", @@ -109,7 +109,7 @@ module SnippetsHelper end def snippet_embed_tag(snippet) - content_tag(:script, nil, src: snippet_url(snippet, format: :js)) + content_tag(:script, nil, src: gitlab_snippet_url(snippet, format: :js)) end def snippet_badge(snippet) @@ -134,7 +134,7 @@ module SnippetsHelper return if blob.empty? || blob.binary? || blob.stored_externally? link_to(external_snippet_icon('doc-code'), - raw_snippet_url(@snippet), + gitlab_raw_snippet_url(@snippet), class: 'btn', target: '_blank', rel: 'noopener noreferrer', @@ -143,7 +143,7 @@ module SnippetsHelper def embedded_snippet_download_button link_to(external_snippet_icon('download'), - raw_snippet_url(@snippet, inline: false), + gitlab_raw_snippet_url(@snippet, inline: false), class: 'btn', target: '_blank', title: 'Download', diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index a1c8c3455b5..de70d0073b3 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -38,7 +38,7 @@ module Emails setup_note_mail(note_id, recipient_id) @snippet = @note.noteable - @target_url = snippet_url(@note.noteable) + @target_url = gitlab_snippet_url(@note.noteable) mail_answer_note_thread(@snippet, @note, note_thread_options(recipient_id, reason)) end diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb index 24813f6ddf9..4e7875e0491 100644 --- a/app/services/groups/transfer_service.rb +++ b/app/services/groups/transfer_service.rb @@ -39,9 +39,15 @@ module Groups ensure_ownership end + post_update_hooks(@updated_project_ids) + true end + # Overridden in EE + def post_update_hooks(updated_project_ids) + end + def ensure_allowed_transfer raise_transfer_error(:group_is_already_root) if group_is_already_root? raise_transfer_error(:same_parent_as_current) if same_parent? @@ -96,9 +102,16 @@ module Groups .where(id: descendants.select(:id)) .update_all(visibility_level: @new_parent_group.visibility_level) - @group + projects_to_update = @group .all_projects .where("visibility_level > ?", @new_parent_group.visibility_level) + + # Used in post_update_hooks in EE. Must use pluck (and not select) + # here as after we perform the update below we won't be able to find + # these records again. + @updated_project_ids = projects_to_update.pluck(:id) + + projects_to_update .update_all(visibility_level: @new_parent_group.visibility_level) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/views/projects/tree/_readme.html.haml b/app/views/projects/tree/_readme.html.haml index fef019e1b69..3e3804ae204 100644 --- a/app/views/projects/tree/_readme.html.haml +++ b/app/views/projects/tree/_readme.html.haml @@ -1,9 +1,10 @@ - if readme.rich_viewer %article.file-holder.readme-holder{ id: 'readme', class: [("limited-width-container" unless fluid_layout), ("js-show-on-root" if vue_file_list_enabled?)] } - .js-file-title.file-title - = blob_icon readme.mode, readme.name - = link_to project_blob_path(@project, tree_join(@ref, readme.path)) do - %strong - = readme.name + .js-file-title.file-title-flex-parent + .file-header-content + = blob_icon readme.mode, readme.name + = link_to project_blob_path(@project, tree_join(@ref, readme.path)) do + %strong + = readme.name = render 'projects/blob/viewer', viewer: readme.rich_viewer, viewer_url: project_blob_path(@project, tree_join(@ref, readme.path), viewer: :rich, format: :json) diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml index 2dbd2a74602..0b114bf67ee 100644 --- a/app/views/search/results/_snippet_blob.html.haml +++ b/app/views/search/results/_snippet_blob.html.haml @@ -1,7 +1,7 @@ - snippet_blob = chunk_snippet(snippet_blob, @search_term) - snippet = snippet_blob[:snippet_object] - snippet_chunks = snippet_blob[:snippet_chunks] -- snippet_path = snippet_path(snippet) +- snippet_path = gitlab_snippet_path(snippet) .search-result-row %span diff --git a/app/views/search/results/_snippet_title.html.haml b/app/views/search/results/_snippet_title.html.haml index a544e59c405..81e746c55a3 100644 --- a/app/views/search/results/_snippet_title.html.haml +++ b/app/views/search/results/_snippet_title.html.haml @@ -1,6 +1,6 @@ .search-result-row %h4.snippet-title.term - = link_to snippet_path(snippet_title) do + = link_to gitlab_snippet_path(snippet_title) do = truncate(snippet_title.title, length: 60) = snippet_badge(snippet_title) %span.cgray.monospace.tiny.float-right.term diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml index 7d102a1b280..f38e30b0c55 100644 --- a/app/views/shared/snippets/_snippet.html.haml +++ b/app/views/shared/snippets/_snippet.html.haml @@ -5,7 +5,7 @@ = image_tag avatar_icon_for_user(snippet.author), class: "avatar s40 d-none d-sm-block", alt: '' .title - = link_to snippet_path(snippet) do + = link_to gitlab_snippet_path(snippet) do = snippet.title - if snippet.file_name.present? %span.snippet-filename.d-none.d-sm-inline-block.ml-2 @@ -14,7 +14,7 @@ %ul.controls %li - = link_to snippet_path(snippet, anchor: 'notes'), class: ('no-comments' if notes_count.zero?) do + = link_to gitlab_snippet_path(snippet, anchor: 'notes'), class: ('no-comments' if notes_count.zero?) do = icon('comments') = notes_count %li diff --git a/app/views/snippets/_actions.html.haml b/app/views/snippets/_actions.html.haml index a408278f7c9..5ee12a2f22a 100644 --- a/app/views/snippets/_actions.html.haml +++ b/app/views/snippets/_actions.html.haml @@ -5,7 +5,7 @@ = link_to edit_snippet_path(@snippet), class: "btn btn-grouped" do = _("Edit") - if can?(current_user, :admin_personal_snippet, @snippet) - = link_to snippet_path(@snippet), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-inverted btn-remove", title: _('Delete Snippet') do + = link_to gitlab_snippet_path(@snippet), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-inverted btn-remove", title: _('Delete Snippet') do = _("Delete") - if can?(current_user, :create_personal_snippet) = link_to new_snippet_path, class: "btn btn-grouped btn-success btn-inverted", title: _("New snippet") do @@ -24,7 +24,7 @@ = _("New snippet") - if can?(current_user, :admin_personal_snippet, @snippet) %li - = link_to snippet_path(@snippet), method: :delete, data: { confirm: _("Are you sure?") }, title: _('Delete Snippet') do + = link_to gitlab_snippet_path(@snippet), method: :delete, data: { confirm: _("Are you sure?") }, title: _('Delete Snippet') do = _("Delete") - if can?(current_user, :update_personal_snippet, @snippet) %li diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml index ebc6c0a2605..f5ffb037152 100644 --- a/app/views/snippets/edit.html.haml +++ b/app/views/snippets/edit.html.haml @@ -3,4 +3,4 @@ %h3.page-title = _("Edit Snippet") %hr -= render 'shared/snippets/form', url: snippet_path(@snippet) += render 'shared/snippets/form', url: gitlab_snippet_path(@snippet) diff --git a/changelogs/unreleased/27025-add-border-top-in-readme.yml b/changelogs/unreleased/27025-add-border-top-in-readme.yml new file mode 100644 index 00000000000..16948754db2 --- /dev/null +++ b/changelogs/unreleased/27025-add-border-top-in-readme.yml @@ -0,0 +1,5 @@ +--- +title: Fix top border of README file header in file list +merge_request: 21314 +author: +type: fixed diff --git a/changelogs/unreleased/fj-fix-snippets-routes.yml b/changelogs/unreleased/fj-fix-snippets-routes.yml new file mode 100644 index 00000000000..d1c607cc19c --- /dev/null +++ b/changelogs/unreleased/fj-fix-snippets-routes.yml @@ -0,0 +1,5 @@ +--- +title: Rename snippet refactored routes +merge_request: 21267 +author: +type: fixed diff --git a/changelogs/unreleased/security-400-path-traversal-rce2.yml b/changelogs/unreleased/security-400-path-traversal-rce2.yml new file mode 100644 index 00000000000..3a77a4b932e --- /dev/null +++ b/changelogs/unreleased/security-400-path-traversal-rce2.yml @@ -0,0 +1,5 @@ +--- +title: Update maven_file_name_regex for full string match +merge_request: +author: +type: security diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb index 5a9eef8288f..4bedf7a301e 100644 --- a/lib/gitlab/url_builder.rb +++ b/lib/gitlab/url_builder.rb @@ -25,7 +25,7 @@ module Gitlab when WikiPage wiki_page_url when Snippet - opts[:raw].present? ? raw_snippet_url(object) : snippet_url(object) + opts[:raw].present? ? gitlab_raw_snippet_url(object) : gitlab_snippet_url(object) when Milestone milestone_url(object) when ::Ci::Build @@ -65,7 +65,7 @@ module Gitlab merge_request_url(object.noteable, anchor: dom_id(object)) elsif object.for_snippet? - snippet_url(object.noteable, anchor: dom_id(object)) + gitlab_snippet_url(object.noteable, anchor: dom_id(object)) end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb index 7a47194c3a4..e0045a4d8a1 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true module QA - # https://gitlab.com/gitlab-org/gitlab-foss/issues/58158 + # https://gitlab.com/gitlab-org/gitlab/issues/26952 + # BUG_IN_CODE context 'Manage', :github, :quarantine do describe 'Project import from GitHub' do let(:imported_project) do diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb index c41cb24f4c2..e4c79bf75b5 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true module QA - # Failure issue: https://gitlab.com/gitlab-org/quality/staging/issues/66 + # Failure issue: https://gitlab.com/gitlab-org/gitlab/issues/36817 + # BUG_IN_CODE context 'Create', :quarantine do describe 'Merge request rebasing' do it 'user rebases source branch of merge request' do diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb index 3771be1a8d1..1f156dfe6d5 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb @@ -2,7 +2,8 @@ module QA # Git protocol v2 is temporarily disabled - # https://gitlab.com/gitlab-org/gitlab-foss/issues/55769 (confidential) + # https://gitlab.com/gitlab-org/gitlab/issues/27828 + # BUG_IN_CODE context 'Create', :quarantine do describe 'Push over HTTP using Git protocol version 2', :requires_git_protocol_v2 do it 'user pushes to the repository' do diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb index e2b2ee801c3..55c70656462 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb @@ -2,7 +2,8 @@ module QA # Git protocol v2 is temporarily disabled - # https://gitlab.com/gitlab-org/gitlab-foss/issues/55769 (confidential) + # https://gitlab.com/gitlab-org/gitlab/issues/27828 + # BUG_IN_CODE context 'Create', :quarantine do describe 'Push over SSH using Git protocol version 2', :requires_git_protocol_v2 do # Note: If you run this test against GDK make sure you've enabled sshd and diff --git a/scripts/security-harness b/scripts/security-harness index 8369cf06223..a1642489fe2 100755 --- a/scripts/security-harness +++ b/scripts/security-harness @@ -1,57 +1,99 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require 'digest' require 'fileutils' -harness_path = File.expand_path('../.git/security_harness', __dir__) -hook_path = File.expand_path("../.git/hooks/pre-push", __dir__) - -if File.exist?(hook_path) - # Deal with a pre-existing hook - source_sum = Digest::SHA256.hexdigest(DATA.read) - dest_sum = Digest::SHA256.file(hook_path).hexdigest - - if source_sum != dest_sum - puts "#{hook_path} exists and is different from our hook!" - puts "Remove it and re-run this script to continue." - - exit 1 - end +if ENV['NO_COLOR'] + SHELL_RED = '' + SHELL_GREEN = '' + SHELL_YELLOW = '' + SHELL_CLEAR = '' else - File.open(hook_path, 'w') do |file| - IO.copy_stream(DATA, file) - end + SHELL_RED = "\e[1;31m" + SHELL_GREEN = "\e[1;32m" + SHELL_YELLOW = "\e[1;33m" + SHELL_CLEAR = "\e[0m" +end - File.chmod(0755, hook_path) +HOOK_PATH = File.expand_path("../.git/hooks/pre-push", __dir__) +HOOK_DATA = <<~HOOK + #!/bin/bash + + set -e + + url="$2" + harness=`dirname "$0"`/../security_harness + + if [ -e "$harness" ] + then + if [[ ("$url" != *"dev.gitlab.org"*) && ("$url" != *"gitlab-org/security/"*) ]] + then + echo "Pushing to remotes other than dev.gitlab.org and gitlab.com/gitlab-org/security has been disabled!" + echo "Run scripts/security-harness to disable this check." + echo + + exit 1 + fi + fi +HOOK + +def write_hook + FileUtils.mkdir_p(File.dirname(HOOK_PATH)) + File.open(HOOK_PATH, 'w') do |file| + file.write(HOOK_DATA) + end + File.chmod(0755, HOOK_PATH) end # Toggle the harness on or off -if File.exist?(harness_path) - FileUtils.rm(harness_path) +def toggle + harness_path = File.expand_path('../.git/security_harness', __dir__) - puts "Security harness removed -- you can now push to all remotes." -else - FileUtils.touch(harness_path) + if File.exist?(harness_path) + FileUtils.rm(harness_path) - puts "Security harness installed -- you will only be able to push to dev.gitlab.org!" + puts "#{SHELL_YELLOW}Security harness removed -- you can now push to all remotes.#{SHELL_CLEAR}" + else + FileUtils.touch(harness_path) + + puts "#{SHELL_GREEN}Security harness installed -- you will only be able to push to dev.gitlab.org or gitlab.com/gitlab-org/security!#{SHELL_CLEAR}" + end end -__END__ -#!/bin/bash +# If we were to change the script and then check for a pre-existing hook before +# writing, the check would fail even if the user had an unmodified version of +# the old hook. Checking previous version hashes allows us to safely overwrite a +# script that differs from the current version, as long as it's an old one and +# not custom. +def previous_version?(dest_sum) + # SHA256 hashes of previous iterations of the script contained in `DATA` + %w[ + 010bf0363a911ebab2bd5728d80795ed02388da51815f0b2530d08ae8ac574f0 + ].include?(dest_sum) +end -set -e +if !File.exist?(HOOK_PATH) + write_hook + toggle +else + # Deal with a pre-existing hook + source_sum = Digest::SHA256.hexdigest(HOOK_DATA) + dest_sum = Digest::SHA256.file(HOOK_PATH).hexdigest -url="$2" -harness=`dirname "$0"`/../security_harness - -if [ -e "$harness" ] -then - if [[ "$url" != *"dev.gitlab.org"* ]] - then - echo "Pushing to remotes other than dev.gitlab.org has been disabled!" - echo "Run scripts/security-harness to disable this check." - echo + if previous_version?(dest_sum) + # Upgrading from a previous version, update in-place + write_hook + toggle + elsif source_sum != dest_sum + # Pre-existing hook we didn't create; do nothing + puts "#{SHELL_RED}#{HOOK_PATH} exists and is different from our hook!" + puts "Remove it and re-run this script to continue.#{SHELL_CLEAR}" exit 1 - fi -fi + else + # No hook update needed, just toggle + toggle + end +end diff --git a/spec/features/projects/snippets/user_views_snippets_spec.rb b/spec/features/projects/snippets/user_views_snippets_spec.rb index 59869244b4a..5739c9510a8 100644 --- a/spec/features/projects/snippets/user_views_snippets_spec.rb +++ b/spec/features/projects/snippets/user_views_snippets_spec.rb @@ -28,7 +28,7 @@ describe 'Projects > Snippets > User views snippets' do end it 'shows snippets' do - expect(page).to have_content(project_snippet.title) + expect(page).to have_link(project_snippet.title, href: project_snippet_path(project, project_snippet)) expect(page).not_to have_content(snippet.title) end end diff --git a/spec/features/snippets/user_snippets_spec.rb b/spec/features/snippets/user_snippets_spec.rb index c6daa19d5e6..d9faea55b29 100644 --- a/spec/features/snippets/user_snippets_spec.rb +++ b/spec/features/snippets/user_snippets_spec.rb @@ -14,9 +14,9 @@ describe 'User Snippets' do end it 'View all of my snippets' do - expect(page).to have_content(public_snippet.title) - expect(page).to have_content(internal_snippet.title) - expect(page).to have_content(private_snippet.title) + expect(page).to have_link(public_snippet.title, href: snippet_path(public_snippet)) + expect(page).to have_link(internal_snippet.title, href: snippet_path(internal_snippet)) + expect(page).to have_link(private_snippet.title, href: snippet_path(private_snippet)) end it 'View my public snippets' do diff --git a/spec/helpers/gitlab_routing_helper_spec.rb b/spec/helpers/gitlab_routing_helper_spec.rb index 9cc1a9dfd5b..e76ebcb5637 100644 --- a/spec/helpers/gitlab_routing_helper_spec.rb +++ b/spec/helpers/gitlab_routing_helper_spec.rb @@ -118,91 +118,91 @@ describe GitlabRoutingHelper do let_it_be(:project_snippet) { create(:project_snippet) } let_it_be(:note) { create(:note_on_personal_snippet, noteable: personal_snippet) } - describe '#snippet_path' do + describe '#gitlab_snippet_path' do it 'returns the personal snippet path' do - expect(snippet_path(personal_snippet)).to eq("/snippets/#{personal_snippet.id}") + expect(gitlab_snippet_path(personal_snippet)).to eq("/snippets/#{personal_snippet.id}") end it 'returns the project snippet path' do - expect(snippet_path(project_snippet)).to eq("/#{project_snippet.project.full_path}/snippets/#{project_snippet.id}") + expect(gitlab_snippet_path(project_snippet)).to eq("/#{project_snippet.project.full_path}/snippets/#{project_snippet.id}") end end - describe '#snippet_url' do + describe '#gitlab_snippet_url' do it 'returns the personal snippet url' do - expect(snippet_url(personal_snippet)).to eq("#{Settings.gitlab['url']}/snippets/#{personal_snippet.id}") + expect(gitlab_snippet_url(personal_snippet)).to eq("http://test.host/snippets/#{personal_snippet.id}") end it 'returns the project snippet url' do - expect(snippet_url(project_snippet)).to eq("#{Settings.gitlab['url']}/#{project_snippet.project.full_path}/snippets/#{project_snippet.id}") + expect(gitlab_snippet_url(project_snippet)).to eq("http://test.host/#{project_snippet.project.full_path}/snippets/#{project_snippet.id}") end end - describe '#raw_snippet_path' do + describe '#gitlab_raw_snippet_path' do it 'returns the raw personal snippet path' do - expect(raw_snippet_path(personal_snippet)).to eq("/snippets/#{personal_snippet.id}/raw") + expect(gitlab_raw_snippet_path(personal_snippet)).to eq("/snippets/#{personal_snippet.id}/raw") end it 'returns the raw project snippet path' do - expect(raw_snippet_path(project_snippet)).to eq("/#{project_snippet.project.full_path}/snippets/#{project_snippet.id}/raw") + expect(gitlab_raw_snippet_path(project_snippet)).to eq("/#{project_snippet.project.full_path}/snippets/#{project_snippet.id}/raw") end end - describe '#raw_snippet_url' do + describe '#gitlab_raw_snippet_url' do it 'returns the raw personal snippet url' do - expect(raw_snippet_url(personal_snippet)).to eq("#{Settings.gitlab['url']}/snippets/#{personal_snippet.id}/raw") + expect(gitlab_raw_snippet_url(personal_snippet)).to eq("http://test.host/snippets/#{personal_snippet.id}/raw") end it 'returns the raw project snippet url' do - expect(raw_snippet_url(project_snippet)).to eq("#{Settings.gitlab['url']}/#{project_snippet.project.full_path}/snippets/#{project_snippet.id}/raw") + expect(gitlab_raw_snippet_url(project_snippet)).to eq("http://test.host/#{project_snippet.project.full_path}/snippets/#{project_snippet.id}/raw") end end - describe '#snippet_notes_path' do + describe '#gitlab_snippet_notes_path' do it 'returns the notes path for the personal snippet' do - expect(snippet_notes_path(personal_snippet)).to eq("/snippets/#{personal_snippet.id}/notes") + expect(gitlab_snippet_notes_path(personal_snippet)).to eq("/snippets/#{personal_snippet.id}/notes") end end - describe '#snippet_notes_url' do + describe '#gitlab_snippet_notes_url' do it 'returns the notes url for the personal snippet' do - expect(snippet_notes_url(personal_snippet)).to eq("#{Settings.gitlab['url']}/snippets/#{personal_snippet.id}/notes") + expect(gitlab_snippet_notes_url(personal_snippet)).to eq("http://test.host/snippets/#{personal_snippet.id}/notes") end end - describe '#snippet_note_path' do + describe '#gitlab_snippet_note_path' do it 'returns the note path for the personal snippet' do - expect(snippet_note_path(personal_snippet, note)).to eq("/snippets/#{personal_snippet.id}/notes/#{note.id}") + expect(gitlab_snippet_note_path(personal_snippet, note)).to eq("/snippets/#{personal_snippet.id}/notes/#{note.id}") end end - describe '#snippet_note_url' do + describe '#gitlab_snippet_note_url' do it 'returns the note url for the personal snippet' do - expect(snippet_note_url(personal_snippet, note)).to eq("#{Settings.gitlab['url']}/snippets/#{personal_snippet.id}/notes/#{note.id}") + expect(gitlab_snippet_note_url(personal_snippet, note)).to eq("http://test.host/snippets/#{personal_snippet.id}/notes/#{note.id}") end end - describe '#toggle_award_emoji_snippet_note_path' do + describe '#gitlab_toggle_award_emoji_snippet_note_path' do it 'returns the note award emoji path for the personal snippet' do - expect(toggle_award_emoji_snippet_note_path(personal_snippet, note)).to eq("/snippets/#{personal_snippet.id}/notes/#{note.id}/toggle_award_emoji") + expect(gitlab_toggle_award_emoji_snippet_note_path(personal_snippet, note)).to eq("/snippets/#{personal_snippet.id}/notes/#{note.id}/toggle_award_emoji") end end - describe '#toggle_award_emoji_snippet_note_url' do + describe '#gitlab_toggle_award_emoji_snippet_note_url' do it 'returns the note award emoji url for the personal snippet' do - expect(toggle_award_emoji_snippet_note_url(personal_snippet, note)).to eq("#{Settings.gitlab['url']}/snippets/#{personal_snippet.id}/notes/#{note.id}/toggle_award_emoji") + expect(gitlab_toggle_award_emoji_snippet_note_url(personal_snippet, note)).to eq("http://test.host/snippets/#{personal_snippet.id}/notes/#{note.id}/toggle_award_emoji") end end - describe '#toggle_award_emoji_snippet_path' do + describe '#gitlab_toggle_award_emoji_snippet_path' do it 'returns the award emoji path for the personal snippet' do - expect(toggle_award_emoji_snippet_path(personal_snippet)).to eq("/snippets/#{personal_snippet.id}/toggle_award_emoji") + expect(gitlab_toggle_award_emoji_snippet_path(personal_snippet)).to eq("/snippets/#{personal_snippet.id}/toggle_award_emoji") end end - describe '#toggle_award_emoji_snippet_url' do + describe '#gitlab_toggle_award_emoji_snippet_url' do it 'returns the award url for the personal snippet' do - expect(toggle_award_emoji_snippet_url(personal_snippet)).to eq("#{Settings.gitlab['url']}/snippets/#{personal_snippet.id}/toggle_award_emoji") + expect(gitlab_toggle_award_emoji_snippet_url(personal_snippet)).to eq("http://test.host/snippets/#{personal_snippet.id}/toggle_award_emoji") end end end diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb index 1af8b7390bb..57ea5416989 100644 --- a/spec/helpers/issuables_helper_spec.rb +++ b/spec/helpers/issuables_helper_spec.rb @@ -202,6 +202,26 @@ describe IssuablesHelper do expect(helper.issuable_initial_data(issue)).to match(hash_including(expected_data)) end + describe '#sentryIssueIdentifier' do + let(:issue) { create(:issue, author: user) } + + before do + assign(:project, issue.project) + end + + it 'sets sentryIssueIdentifier to nil with no sentry issue ' do + expect(helper.issuable_initial_data(issue)[:sentryIssueIdentifier]) + .to be_nil + end + + it 'sets sentryIssueIdentifier to sentry_issue_identifier' do + sentry_issue = create(:sentry_issue, issue: issue) + + expect(helper.issuable_initial_data(issue)[:sentryIssueIdentifier]) + .to eq(sentry_issue.sentry_issue_identifier) + end + end + describe '#zoomMeetingUrl in issue' do let(:issue) { create(:issue, author: user) } diff --git a/spec/helpers/snippets_helper_spec.rb b/spec/helpers/snippets_helper_spec.rb index 2a24950502b..428fe97f172 100644 --- a/spec/helpers/snippets_helper_spec.rb +++ b/spec/helpers/snippets_helper_spec.rb @@ -14,13 +14,13 @@ describe SnippetsHelper do it 'returns view raw button of embedded snippets for personal snippets' do @snippet = create(:personal_snippet, :public) - expect(subject).to eq(download_link("#{Settings.gitlab['url']}/snippets/#{@snippet.id}/raw")) + expect(subject).to eq(download_link("http://test.host/snippets/#{@snippet.id}/raw")) end it 'returns view raw button of embedded snippets for project snippets' do @snippet = create(:project_snippet, :public) - expect(subject).to eq(download_link("#{Settings.gitlab['url']}/#{@snippet.project.path_with_namespace}/snippets/#{@snippet.id}/raw")) + expect(subject).to eq(download_link("http://test.host/#{@snippet.project.path_with_namespace}/snippets/#{@snippet.id}/raw")) end def download_link(url) @@ -34,13 +34,13 @@ describe SnippetsHelper do it 'returns download button of embedded snippets for personal snippets' do @snippet = create(:personal_snippet, :public) - expect(subject).to eq(download_link("#{Settings.gitlab['url']}/snippets/#{@snippet.id}/raw")) + expect(subject).to eq(download_link("http://test.host/snippets/#{@snippet.id}/raw")) end it 'returns download button of embedded snippets for project snippets' do @snippet = create(:project_snippet, :public) - expect(subject).to eq(download_link("#{Settings.gitlab['url']}/#{@snippet.project.path_with_namespace}/snippets/#{@snippet.id}/raw")) + expect(subject).to eq(download_link("http://test.host/#{@snippet.project.path_with_namespace}/snippets/#{@snippet.id}/raw")) end def download_link(url) @@ -56,7 +56,7 @@ describe SnippetsHelper do context 'public' do it 'returns a script tag with the snippet full url' do - expect(subject).to eq(script_embed("#{Settings.gitlab['url']}/snippets/#{snippet.id}")) + expect(subject).to eq(script_embed("http://test.host/snippets/#{snippet.id}")) end end end @@ -65,7 +65,7 @@ describe SnippetsHelper do let(:snippet) { public_project_snippet } it 'returns a script tag with the snippet full url' do - expect(subject).to eq(script_embed("#{Settings.gitlab['url']}/#{snippet.project.path_with_namespace}/snippets/#{snippet.id}")) + expect(subject).to eq(script_embed("http://test.host/#{snippet.project.path_with_namespace}/snippets/#{snippet.id}")) end end