diff --git a/CHANGELOG-EE.md b/CHANGELOG-EE.md index b5a8d2fa30..1ffbd78715 100644 --- a/CHANGELOG-EE.md +++ b/CHANGELOG-EE.md @@ -1,5 +1,21 @@ Please view this file on the master branch, on stable branches it's out of date. +## 12.3.8 + +- No changes. + +## 12.3.7 + +### Security (6 changes) + +- Protect Jira integration endpoints from guest users. +- Fix private comment Elasticsearch leak on project search scope. +- Filter snippet search results by feature visibility. +- Hide AWS secret on Admin Integration page. +- Fail pull mirror when mirror user is blocked. +- Prevent IDOR when adding users to protected environments. + + ## 12.3.6 ### Security (4 changes) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79dcefc8f6..77420db25f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,23 +2,30 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 12.3.9 + +- No changes. + ## 12.3.8 - No changes. ## 12.3.7 -### Security (9 changes) +### Security (12 changes) -- Check permissions before showing a forked project's source. +- Do not create todos for approvers without access. !1442 +- Limit potential for DNS rebind SSRF in chat notifications. - Encrypt application setting tokens. - Update Workhorse and Gitaly to fix a security issue. +- Add maven file_name regex validation on incoming files. - Hide commit counts from guest users in Cycle Analytics. -- Limit potential for DNS rebind SSRF in chat notifications. +- Check permissions before showing a forked project's source. - Fix 500 error caused by invalid byte sequences in links. - Ensure are cleaned by ImportExport::AttributeCleaner. - Remove notes regarding Related Branches from Issue activity feeds for guest users. - Escape namespace in label references to prevent XSS. +- Add authorization to using filter vulnerable in Dependency List. ## 12.3.6 diff --git a/VERSION b/VERSION index 212464673d..43fcd738f0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -12.3.8 +12.3.9 diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb index fe7e07ef9f..b73ec5cb73 100644 --- a/app/services/groups/transfer_service.rb +++ b/app/services/groups/transfer_service.rb @@ -38,9 +38,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? @@ -90,9 +96,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 @@ -109,3 +122,5 @@ module Groups end end end + +Groups::TransferService.prepend_if_ee('EE::Groups::TransferService') diff --git a/core-js/features/object/index.js b/core-js/features/object/index.js index d2d658cf40..e7ea4bf747 100644 --- a/core-js/features/object/index.js +++ b/core-js/features/object/index.js @@ -1,3 +1,6 @@ var parent = require('../../es/object'); +require('../../modules/esnext.object.iterate-entries'); +require('../../modules/esnext.object.iterate-keys'); +require('../../modules/esnext.object.iterate-values'); module.exports = parent; diff --git a/core-js/features/object/iterate-entries.js b/core-js/features/object/iterate-entries.js new file mode 100644 index 0000000000..ca9cd281c5 --- /dev/null +++ b/core-js/features/object/iterate-entries.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.object.iterate-entries'); +var path = require('../../internals/path'); + +module.exports = path.Object.iterateEntries; diff --git a/core-js/features/object/iterate-keys.js b/core-js/features/object/iterate-keys.js new file mode 100644 index 0000000000..8e8fad4b2a --- /dev/null +++ b/core-js/features/object/iterate-keys.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.object.iterate-keys'); +var path = require('../../internals/path'); + +module.exports = path.Object.iterateKeys; diff --git a/core-js/features/object/iterate-values.js b/core-js/features/object/iterate-values.js new file mode 100644 index 0000000000..a77108fc2f --- /dev/null +++ b/core-js/features/object/iterate-values.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.object.iterate-values'); +var path = require('../../internals/path'); + +module.exports = path.Object.iterateValues; diff --git a/core-js/internals/inspect-source.js b/core-js/internals/inspect-source.js index e1403d3c2d..957780931c 100644 --- a/core-js/internals/inspect-source.js +++ b/core-js/internals/inspect-source.js @@ -1,7 +1,12 @@ -var shared = require('../internals/shared'); +var store = require('../internals/shared-store'); var functionToString = Function.toString; -module.exports = shared('inspectSource', function (it) { - return functionToString.call(it); -}); +// this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper +if (typeof store.inspectSource != 'function') { + store.inspectSource = function (it) { + return functionToString.call(it); + }; +} + +module.exports = store.inspectSource; diff --git a/core-js/internals/object-iterator.js b/core-js/internals/object-iterator.js new file mode 100644 index 0000000000..415824f83b --- /dev/null +++ b/core-js/internals/object-iterator.js @@ -0,0 +1,37 @@ +'use strict'; +var InternalStateModule = require('../internals/internal-state'); +var createIteratorConstructor = require('../internals/create-iterator-constructor'); +var has = require('../internals/has'); +var objectKeys = require('../internals/object-keys'); +var toObject = require('../internals/to-object'); + +var OBJECT_ITERATOR = 'Object Iterator'; +var setInternalState = InternalStateModule.set; +var getInternalState = InternalStateModule.getterFor(OBJECT_ITERATOR); + +module.exports = createIteratorConstructor(function ObjectIterator(source, mode) { + var object = toObject(source); + setInternalState(this, { + type: OBJECT_ITERATOR, + mode: mode, + object: object, + keys: objectKeys(object), + index: 0 + }); +}, 'Object', function next() { + var state = getInternalState(this); + var keys = state.keys; + while (true) { + if (keys === null || state.index >= keys.length) { + state.object = state.keys = null; + return { value: undefined, done: true }; + } + var key = keys[state.index++]; + var object = state.object; + if (!has(object, key)) continue; + switch (state.mode) { + case 'keys': return { value: key, done: false }; + case 'values': return { value: object[key], done: false }; + } /* entries */ return { value: [key, object[key]], done: false }; + } +}); diff --git a/core-js/internals/shared.js b/core-js/internals/shared.js index 0111cef0ae..4bc59be9da 100644 --- a/core-js/internals/shared.js +++ b/core-js/internals/shared.js @@ -4,7 +4,7 @@ var store = require('../internals/shared-store'); (module.exports = function (key, value) { return store[key] || (store[key] = value !== undefined ? value : {}); })('versions', []).push({ - version: '3.4.7', + version: '3.5.0', mode: IS_PURE ? 'pure' : 'global', copyright: '© 2019 Denis Pushkarev (zloirock.ru)' }); diff --git a/core-js/modules/esnext.object.iterate-entries.js b/core-js/modules/esnext.object.iterate-entries.js new file mode 100644 index 0000000000..b882ca3019 --- /dev/null +++ b/core-js/modules/esnext.object.iterate-entries.js @@ -0,0 +1,11 @@ +'use strict'; +var $ = require('../internals/export'); +var ObjectIterator = require('../internals/object-iterator'); + +// `Object.iterateEntries` method +// https://github.com/tc39/proposal-object-iteration +$({ target: 'Object', stat: true }, { + iterateEntries: function iterateEntries(object) { + return new ObjectIterator(object, 'entries'); + } +}); diff --git a/core-js/modules/esnext.object.iterate-keys.js b/core-js/modules/esnext.object.iterate-keys.js new file mode 100644 index 0000000000..e74dc372f2 --- /dev/null +++ b/core-js/modules/esnext.object.iterate-keys.js @@ -0,0 +1,11 @@ +'use strict'; +var $ = require('../internals/export'); +var ObjectIterator = require('../internals/object-iterator'); + +// `Object.iterateKeys` method +// https://github.com/tc39/proposal-object-iteration +$({ target: 'Object', stat: true }, { + iterateKeys: function iterateKeys(object) { + return new ObjectIterator(object, 'keys'); + } +}); diff --git a/core-js/modules/esnext.object.iterate-values.js b/core-js/modules/esnext.object.iterate-values.js new file mode 100644 index 0000000000..1d18fe00eb --- /dev/null +++ b/core-js/modules/esnext.object.iterate-values.js @@ -0,0 +1,11 @@ +'use strict'; +var $ = require('../internals/export'); +var ObjectIterator = require('../internals/object-iterator'); + +// `Object.iterateValues` method +// https://github.com/tc39/proposal-object-iteration +$({ target: 'Object', stat: true }, { + iterateValues: function iterateValues(object) { + return new ObjectIterator(object, 'values'); + } +}); diff --git a/core-js/package.json b/core-js/package.json index a47962325a..fa06afae12 100644 --- a/core-js/package.json +++ b/core-js/package.json @@ -1,7 +1,7 @@ { "name": "core-js", "description": "Standard library", - "version": "3.4.7", + "version": "3.5.0", "repository": { "type": "git", "url": "https://github.com/zloirock/core-js.git" diff --git a/core-js/proposals/object-iteration.js b/core-js/proposals/object-iteration.js new file mode 100644 index 0000000000..03615154c2 --- /dev/null +++ b/core-js/proposals/object-iteration.js @@ -0,0 +1,3 @@ +require('../modules/esnext.object.iterate-entries'); +require('../modules/esnext.object.iterate-keys'); +require('../modules/esnext.object.iterate-values'); diff --git a/core-js/stage/1.js b/core-js/stage/1.js index 15ea305f13..bff9b62954 100644 --- a/core-js/stage/1.js +++ b/core-js/stage/1.js @@ -5,6 +5,7 @@ require('../proposals/keys-composition'); require('../proposals/math-extensions'); require('../proposals/math-signbit'); require('../proposals/number-from-string'); +require('../proposals/object-iteration'); require('../proposals/observable'); require('../proposals/pattern-matching'); require('../proposals/promise-try'); diff --git a/derailed-benchmarks/CHANGELOG.md b/derailed-benchmarks/CHANGELOG.md index 740231210b..83a5a654f3 100644 --- a/derailed-benchmarks/CHANGELOG.md +++ b/derailed-benchmarks/CHANGELOG.md @@ -1,5 +1,9 @@ ## master (unreleased) +## 1.4.3 + +- perf:library now uses median instead of average (https://github.com/schneems/derailed_benchmarks/pull/160) + ## 1.4.2 - Fixed syntax error that resulted in ensure end error inside tasks.rb for older rubies (https://github.com/schneems/derailed_benchmarks/pull/155) diff --git a/derailed-benchmarks/README.md b/derailed-benchmarks/README.md index 8f309691b7..91c2df71a3 100644 --- a/derailed-benchmarks/README.md +++ b/derailed-benchmarks/README.md @@ -431,7 +431,7 @@ Use a comma to seperate your branch names with the `SHAS_TO_TEST` env var, or om If you only include one SHA, then derailed will grab the latest commit and compare it to that SHA. -These tests might take a along time to run so the output is stored on disk incase you want to see them in the future, they're at `tmp/library_branches/` and labeled with the same names as your commits. +These tests might take a along time to run so the output is stored on disk incase you want to see them in the future, they're at `tmp/compare_branches/` and labeled with the same names as your commits. When the test is done it will output which commit "won" and by how much: diff --git a/derailed-benchmarks/lib/derailed_benchmarks/stats_from_dir.rb b/derailed-benchmarks/lib/derailed_benchmarks/stats_from_dir.rb index c47976fa1b..378da4d066 100644 --- a/derailed-benchmarks/lib/derailed_benchmarks/stats_from_dir.rb +++ b/derailed-benchmarks/lib/derailed_benchmarks/stats_from_dir.rb @@ -66,15 +66,27 @@ module DerailedBenchmarks end def x_faster - FORMAT % (oldest.average/newest.average).to_f + (oldest.median/newest.median).to_f + end + + def faster? + newest.median < oldest.median end def percent_faster - FORMAT % (((oldest.average - newest.average) / oldest.average).to_f * 100) + (((oldest.median - newest.median) / oldest.median).to_f * 100) end def change_direction - newest.average < oldest.average ? "FASTER" : "SLOWER" + if faster? + "FASTER 🚀🚀🚀" + else + "SLOWER 🐢🐢🐢" + end + end + + def align + " " * (("%i" % percent_faster).length - ("%i" % x_faster).length) end def banner(io = Kernel) @@ -85,11 +97,11 @@ module DerailedBenchmarks io.puts "👎👎👎(NOT Statistically Significant) 👎👎👎" end io.puts - io.puts "[#{newest.name}] #{newest.desc.inspect} - (#{newest.average} seconds)" + io.puts "[#{newest.name}] #{newest.desc.inspect} - (#{newest.median} seconds)" io.puts " #{change_direction} by:" - io.puts " #{x_faster}x [older/newer]" - io.puts " #{percent_faster}\% [(older - newer) / older * 100]" - io.puts "[#{oldest.name}] #{oldest.desc.inspect} - (#{oldest.average} seconds)" + io.puts " #{align}#{FORMAT % x_faster}x [older/newer]" + io.puts " #{FORMAT % percent_faster}\% [(older - newer) / older * 100]" + io.puts "[#{oldest.name}] #{oldest.desc.inspect} - (#{oldest.median} seconds)" io.puts io.puts "Iterations per sample: #{ENV["TEST_COUNT"]}" io.puts "Samples: #{newest.values.length}" diff --git a/derailed-benchmarks/lib/derailed_benchmarks/stats_in_file.rb b/derailed-benchmarks/lib/derailed_benchmarks/stats_in_file.rb index a524f0e0e1..d7f6ce88bd 100644 --- a/derailed-benchmarks/lib/derailed_benchmarks/stats_in_file.rb +++ b/derailed-benchmarks/lib/derailed_benchmarks/stats_in_file.rb @@ -30,9 +30,14 @@ module DerailedBenchmarks def call load_file! + @median = (values[(values.length - 1) / 2] + values[values.length/ 2]) / 2.0 @average = values.inject(:+) / values.length end + def median + @median.to_f + end + def average @average.to_f end @@ -47,6 +52,8 @@ module DerailedBenchmarks raise e, "Problem with file #{@file.inspect}:\n#{@file.read}\n#{e.message}" end end + + values.sort! values.freeze end end diff --git a/derailed-benchmarks/lib/derailed_benchmarks/tasks.rb b/derailed-benchmarks/lib/derailed_benchmarks/tasks.rb index 7f7f5fd5c0..675d55ac86 100644 --- a/derailed-benchmarks/lib/derailed_benchmarks/tasks.rb +++ b/derailed-benchmarks/lib/derailed_benchmarks/tasks.rb @@ -39,7 +39,7 @@ namespace :perf do current_library_branch = "" Dir.chdir(library_dir) { current_library_branch = run!('git describe --contains --all HEAD').chomp } - out_dir = Pathname.new("tmp/library_branches/#{Time.now.strftime('%Y-%m-%d-%H-%M-%s-%N')}") + out_dir = Pathname.new("tmp/compare_branches/#{Time.now.strftime('%Y-%m-%d-%H-%M-%s-%N')}") out_dir.mkpath branches_to_test = branch_names.each_with_object({}) {|elem, hash| hash[elem] = out_dir + "#{elem.gsub('/', ':')}.bench.txt" } @@ -93,10 +93,18 @@ namespace :perf do end end - stats.call.banner if stats + if stats + stats.call.banner + + result_file = out_dir + "results.txt" + File.open(result_file, "w") do |f| + stats.banner(f) + end + + puts "Output: #{result_file.to_s}" + end end - end - + end desc "hits the url TEST_COUNT times" task :test => [:setup] do diff --git a/derailed-benchmarks/lib/derailed_benchmarks/version.rb b/derailed-benchmarks/lib/derailed_benchmarks/version.rb index e77d2c2c89..ec8dd18b05 100644 --- a/derailed-benchmarks/lib/derailed_benchmarks/version.rb +++ b/derailed-benchmarks/lib/derailed_benchmarks/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module DerailedBenchmarks - VERSION = "1.4.2" + VERSION = "1.4.3" end diff --git a/derailed-benchmarks/test/derailed_benchmarks/stats_from_dir_test.rb b/derailed-benchmarks/test/derailed_benchmarks/stats_from_dir_test.rb index 8b4a45a4c4..7aad7b037c 100644 --- a/derailed-benchmarks/test/derailed_benchmarks/stats_from_dir_test.rb +++ b/derailed-benchmarks/test/derailed_benchmarks/stats_from_dir_test.rb @@ -22,8 +22,11 @@ class StatsFromDirTest < ActiveSupport::TestCase assert_in_delta 0.1730818382602285, stats.d_critical, 0.00001 assert_equal true, stats.significant? - assert_equal "1.0062", stats.x_faster - assert_equal "0.6131", stats.percent_faster + format = DerailedBenchmarks::StatsFromDir::FORMAT + assert_equal "1.0062", format % stats.x_faster + assert_equal "0.6147", format % stats.percent_faster + + assert_equal "11.3844", format % newest.median end test "banner faster" do @@ -44,17 +47,17 @@ class StatsFromDirTest < ActiveSupport::TestCase "0.001" end - def newest.average + def newest.median 10.5 end - def oldest.average + def oldest.median 11.0 end - expected = <<-EOM + expected = <<~EOM [winner] "I am the new commit" - (10.5 seconds) - FASTER by: + FASTER 🚀🚀🚀 by: 1.0476x [older/newer] 4.5455% [(older - newer) / older * 100] [loser] "Old commit" - (11.0 seconds) @@ -75,18 +78,18 @@ EOM newest = stats.newest oldest = stats.oldest - def oldest.average + def oldest.median 10.5 end - def newest.average + def newest.median 11.0 end - expected = <<-EOM + expected = <<~EOM [loser] "I am the new commit" - (11.0 seconds) - SLOWER by: - 0.9545x [older/newer] + SLOWER 🐢🐢🐢 by: + 0.9545x [older/newer] -4.7619% [(older - newer) / older * 100] [winner] "Old commit" - (10.5 seconds) EOM diff --git a/derailed-benchmarks/test/rails_app/app/assets/config/manifest.js b/derailed-benchmarks/test/rails_app/app/assets/config/manifest.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 3abee537e2..8f103c098c 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -666,6 +666,9 @@ msgstr "" msgid "API Token" msgstr "" +msgid "AWS Secret Access Key" +msgstr "" + msgid "Abort" msgstr "" @@ -5653,6 +5656,9 @@ msgstr "" msgid "Enter merge request URLs" msgstr "" +msgid "Enter new AWS Secret Access Key" +msgstr "" + msgid "Enter the issue description" msgstr "" diff --git a/spec/features/groups/settings/group_badges_spec.rb b/spec/features/groups/settings/group_badges_spec.rb index 9328fd9dcb..72e74df368 100644 --- a/spec/features/groups/settings/group_badges_spec.rb +++ b/spec/features/groups/settings/group_badges_spec.rb @@ -7,8 +7,9 @@ describe 'Group Badges' do let(:user) { create(:user) } let(:group) { create(:group) } - let(:badge_link_url) { 'https://gitlab.com/gitlab-org/gitlab/commits/master'} - let(:badge_image_url) { 'https://gitlab.com/gitlab-org/gitlab/badges/master/build.svg'} + let(:project) { create(:project, namespace: group) } + let(:badge_link_url) { "http://#{page.server.host}:#{page.server.port}/#{project.full_path}/commits/master" } + let(:badge_image_url) { "http://#{page.server.host}:#{page.server.port}/#{project.full_path}/badges/master/pipeline.svg" } let!(:badge_1) { create(:group_badge, group: group) } let!(:badge_2) { create(:group_badge, group: group) } diff --git a/spec/features/projects/settings/project_badges_spec.rb b/spec/features/projects/settings/project_badges_spec.rb index 03d2f1cf04..c419bb1868 100644 --- a/spec/features/projects/settings/project_badges_spec.rb +++ b/spec/features/projects/settings/project_badges_spec.rb @@ -8,8 +8,8 @@ describe 'Project Badges' do let(:user) { create(:user) } let(:group) { create(:group) } let(:project) { create(:project, namespace: group) } - let(:badge_link_url) { 'https://gitlab.com/gitlab-org/gitlab/commits/master'} - let(:badge_image_url) { 'https://gitlab.com/gitlab-org/gitlab/badges/master/build.svg'} + let(:badge_link_url) { "http://#{page.server.host}:#{page.server.port}/#{project.full_path}/commits/master" } + let(:badge_image_url) { "http://#{page.server.host}:#{page.server.port}/#{project.full_path}/badges/master/pipeline.svg" } let!(:project_badge) { create(:project_badge, project: project) } let!(:group_badge) { create(:group_badge, group: group) } diff --git a/spec/support/shared_examples/models/concern/issuable_shared_examples.rb b/spec/support/shared_examples/models/concern/issuable_shared_examples.rb index 9604555c57..c7adfe3978 100644 --- a/spec/support/shared_examples/models/concern/issuable_shared_examples.rb +++ b/spec/support/shared_examples/models/concern/issuable_shared_examples.rb @@ -2,7 +2,7 @@ shared_examples_for 'matches_cross_reference_regex? fails fast' do it 'fails fast for long strings' do # took well under 1 second in CI https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/3267#note_172823 expect do - Timeout.timeout(3.seconds) { mentionable.matches_cross_reference_regex? } + Timeout.timeout(6.seconds) { mentionable.matches_cross_reference_regex? } end.not_to raise_error end end