Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-06-22 03:08:59 +00:00
parent bd9b2731b4
commit 0c924987e1
16 changed files with 257 additions and 163 deletions

View file

@ -1,31 +1,33 @@
import $ from 'jquery';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { spriteIcon } from '~/lib/utils/common_utils';
import { __, s__ } from '~/locale';
export default class Star {
constructor(container = '.project-home-panel') {
$(`${container} .toggle-star`).on('click', function toggleStarClickCallback() {
const $this = $(this);
const $starSpan = $this.find('span');
const $starIcon = $this.find('svg');
const iconClasses = $starIcon.attr('class').split(' ');
constructor(containerSelector = '.project-home-panel') {
const container = document.querySelector(containerSelector);
const starToggle = container.querySelector('.toggle-star');
starToggle.addEventListener('click', function toggleStarClickCallback() {
const starSpan = starToggle.querySelector('span');
const starIcon = starToggle.querySelector('svg');
const iconClasses = Array.from(starIcon.classList.values());
axios
.post($this.data('endpoint'))
.post(starToggle.dataset.endpoint)
.then(({ data }) => {
const isStarred = $starSpan.hasClass('starred');
$this.parent().find('.count').text(data.star_count);
const isStarred = starSpan.classList.contains('starred');
starToggle.parentNode.querySelector('.count').textContent = data.star_count;
if (isStarred) {
$starSpan.removeClass('starred').text(s__('StarProject|Star'));
$starIcon.remove();
$this.prepend(spriteIcon('star-o', iconClasses));
starSpan.classList.remove('starred');
starSpan.textContent = s__('StarProject|Star');
starIcon.remove();
starSpan.insertAdjacentHTML('beforebegin', spriteIcon('star-o', iconClasses));
} else {
$starSpan.addClass('starred').text(__('Unstar'));
$starIcon.remove();
$this.prepend(spriteIcon('star', iconClasses));
starSpan.classList.add('starred');
starSpan.textContent = __('Unstar');
starIcon.remove();
starSpan.insertAdjacentHTML('beforebegin', spriteIcon('star', iconClasses));
}
})
.catch(() =>

View file

@ -8,40 +8,6 @@ class Admin::HooksController < Admin::ApplicationController
feature_category :integrations
urgency :low, [:test]
def index
@hooks = SystemHook.all.load
@hook = SystemHook.new
end
def create
@hook = SystemHook.new(hook_params.to_h)
if @hook.save
redirect_to admin_hooks_path, notice: _('Hook was successfully created.')
else
@hooks = SystemHook.all
render :index
end
end
def edit
end
def update
if hook.update(hook_params)
flash[:notice] = _('System hook was successfully updated.')
redirect_to admin_hooks_path
else
render 'edit'
end
end
def destroy
destroy_hook(hook)
redirect_to admin_hooks_path, status: :found
end
def test
result = TestHooks::SystemService.new(hook, current_user, params[:trigger]).execute
@ -52,6 +18,10 @@ class Admin::HooksController < Admin::ApplicationController
private
def relation
SystemHook
end
def hook
@hook ||= SystemHook.find(params[:id])
end
@ -60,12 +30,11 @@ class Admin::HooksController < Admin::ApplicationController
@hook_logs ||= hook.web_hook_logs.recent.page(params[:page])
end
def hook_params
params.require(:hook).permit(
:enable_ssl_verification,
:token,
:url,
*SystemHook.triggers.values
)
def hook_param_names
%i[enable_ssl_verification token url]
end
def trigger_values
SystemHook.triggers.values
end
end

View file

@ -3,8 +3,68 @@
module Integrations::HooksExecution
extend ActiveSupport::Concern
included do
attr_writer :hooks, :hook
end
def index
self.hooks = relation.select(&:persisted?)
self.hook = relation.new
end
def create
self.hook = relation.new(hook_params)
hook.save
unless hook.valid?
self.hooks = relation.select(&:persisted?)
flash[:alert] = hook.errors.full_messages.join.html_safe
end
redirect_to action: :index
end
def update
if hook.update(hook_params)
flash[:notice] = _('Hook was successfully updated.')
redirect_to action: :index
else
render 'edit'
end
end
def destroy
destroy_hook(hook)
redirect_to action: :index, status: :found
end
def edit
redirect_to(action: :index) unless hook
end
private
def hook_params
permitted = hook_param_names + trigger_values
permitted << { url_variables: [:key, :value] }
ps = params.require(:hook).permit(*permitted).to_h
ps[:url_variables] = ps[:url_variables].to_h { [_1[:key], _1[:value].presence] } if ps.key?(:url_variables)
if action_name == 'update' && ps.key?(:url_variables)
supplied = ps[:url_variables]
ps[:url_variables] = hook.url_variables.merge(supplied).compact
end
ps
end
def hook_param_names
%i[enable_ssl_verification token url push_events_branch_filter]
end
def destroy_hook(hook)
result = WebHooks::DestroyService.new(current_user).execute(hook)

View file

@ -15,52 +15,21 @@ class Projects::HooksController < Projects::ApplicationController
feature_category :integrations
urgency :low, [:test]
def index
@hooks = @project.hooks.load
@hook = ProjectHook.new
end
def create
@hook = @project.hooks.new(hook_params)
@hook.save
unless @hook.valid?
@hooks = @project.hooks.select(&:persisted?)
flash[:alert] = @hook.errors.full_messages.join.html_safe
end
redirect_to action: :index
end
def edit
redirect_to(action: :index) unless hook
end
def update
if hook.update(hook_params)
flash[:notice] = _('Hook was successfully updated.')
redirect_to action: :index
else
render 'edit'
end
end
def test
result = TestHooks::ProjectService.new(hook, current_user, params[:trigger]).execute
trigger = params.fetch(:trigger, ::ProjectHook.triggers.each_value.first.to_s)
result = TestHooks::ProjectService.new(hook, current_user, trigger).execute
set_hook_execution_notice(result)
redirect_back_or_default(default: { action: :index })
end
def destroy
destroy_hook(hook)
redirect_to action: :index, status: :found
end
private
def relation
@project.hooks
end
def hook
@hook ||= @project.hooks.find(params[:id])
end
@ -69,13 +38,7 @@ class Projects::HooksController < Projects::ApplicationController
@hook_logs ||= hook.web_hook_logs.recent.page(params[:page])
end
def hook_params
params.require(:hook).permit(
:enable_ssl_verification,
:token,
:url,
:push_events_branch_filter,
*ProjectHook.triggers.values
)
def trigger_values
ProjectHook.triggers.values
end
end

View file

@ -1,5 +1,5 @@
= gitlab_ui_form_for @application_setting, url: reporting_admin_application_settings_path(anchor: 'js-spam-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
= form_errors(@application_setting, pajamas_alert: true)
%fieldset
%h5

View file

@ -1,5 +1,5 @@
= gitlab_ui_form_for group, url: update_auto_devops_group_settings_ci_cd_path(group), method: :patch do |f|
= form_errors(group)
= form_errors(group, pajamas_alert: true)
%fieldset
.form-group
.card.auto-devops-card

View file

@ -8,7 +8,7 @@
= s_('GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group.')
.settings-content
= gitlab_ui_form_for @group, url: group_path(@group, anchor: 'js-default-branch-name'), html: { class: 'fieldset-form' } do |f|
= form_errors(@group)
= form_errors(@group, pajamas_alert: true)
- fallback_branch_name = "<code>#{Gitlab::DefaultBranch.value(object: @group)}</code>"
%fieldset

View file

@ -1,8 +0,0 @@
---
name: migrate_vulnerability_finding_uuids
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75546
rollout_issue_url:
milestone: '14.7'
type: development
group: group::threat insights
default_enabled: true

View file

@ -6,10 +6,12 @@ module API
expose :shared_with_groups do |group, options|
SharedGroupWithGroup.represent(group.shared_with_group_links_visible_to_user(options[:current_user]))
end
expose :runners_token, if: lambda { |group, options| options[:user_can_admin_group] }
expose :runners_token, if: ->(_, options) { options[:user_can_admin_group] }
expose :prevent_sharing_groups_outside_hierarchy, if: ->(group) { group.root? }
expose :projects, using: Entities::Project do |group, options|
expose :projects,
if: ->(_, options) { options[:with_projects] },
using: Entities::Project do |group, options|
projects = GroupProjectsFinder.new(
group: group,
current_user: options[:current_user],
@ -19,7 +21,9 @@ module API
Entities::Project.prepare_relation(projects, options)
end
expose :shared_projects, using: Entities::Project do |group, options|
expose :shared_projects,
if: ->(_, options) { options[:with_projects] },
using: Entities::Project do |group, options|
projects = GroupProjectsFinder.new(
group: group,
current_user: options[:current_user],

View file

@ -109,6 +109,19 @@ module API
present paginate(groups), options
end
def present_group_details(params, group, with_projects: true)
options = {
with: Entities::GroupDetail,
with_projects: with_projects,
current_user: current_user,
user_can_admin_group: can?(current_user, :admin_group, group)
}
group, options = with_custom_attributes(group, options) if params[:with_custom_attributes]
present group, options
end
def present_groups_with_pagination_strategies(params, groups)
return present_groups(params, groups) if current_user.present?
@ -236,7 +249,7 @@ module API
authorize! :admin_group, group
if update_group(group)
present group, with: Entities::GroupDetail, current_user: current_user
present_group_details(params, group, with_projects: true)
else
render_validation_error!(group)
end
@ -254,15 +267,7 @@ module API
group = find_group!(params[:id])
group.preload_shared_group_links
options = {
with: params[:with_projects] ? Entities::GroupDetail : Entities::Group,
current_user: current_user,
user_can_admin_group: can?(current_user, :admin_group, group)
}
group, options = with_custom_attributes(group, options)
present group, options
present_group_details(params, group, with_projects: params[:with_projects])
end
desc 'Remove a group.'

View file

@ -79,10 +79,6 @@ class Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid # r
# rubocop: disable Metrics/AbcSize,Metrics/MethodLength,Metrics/BlockLength
def perform(start_id, end_id)
unless Feature.enabled?(:migrate_vulnerability_finding_uuids)
return log_info('Migration is disabled by the feature flag', start_id: start_id, end_id: end_id)
end
log_info('Migration started', start_id: start_id, end_id: end_id)
VulnerabilitiesFinding

View file

@ -18998,9 +18998,6 @@ msgstr ""
msgid "Hook execution failed. Ensure the group has a project with commits."
msgstr ""
msgid "Hook was successfully created."
msgstr ""
msgid "Hook was successfully updated."
msgstr ""
@ -37452,9 +37449,6 @@ msgstr ""
msgid "System header and footer"
msgstr ""
msgid "System hook was successfully updated."
msgstr ""
msgid "System hooks are triggered on sets of events like creating a project or adding an SSH key. You can also enable extra triggers, such as push events."
msgstr ""

View file

@ -17,16 +17,46 @@ RSpec.describe Admin::HooksController do
url: "http://example.com",
push_events: true,
tag_push_events: true,
tag_push_events: false,
repository_update_events: true,
merge_requests_events: true
merge_requests_events: false,
url_variables: [{ key: 'token', value: 'some secret value' }]
}
post :create, params: { hook: hook_params }
expect(response).to have_gitlab_http_status(:found)
expect(SystemHook.all.size).to eq(1)
expect(SystemHook.first).to have_attributes(hook_params)
expect(SystemHook.first).to have_attributes(hook_params.except(:url_variables))
expect(SystemHook.first).to have_attributes(url_variables: { 'token' => 'some secret value' })
end
end
describe 'POST #update' do
let!(:hook) { create(:system_hook) }
it 'sets all parameters' do
hook.update!(url_variables: { 'foo' => 'bar', 'baz' => 'woo' })
hook_params = {
url: 'http://example.com/{baz}?token={token}',
enable_ssl_verification: false,
url_variables: [
{ key: 'token', value: 'some secret value' },
{ key: 'foo', value: nil }
]
}
put :update, params: { id: hook.id, hook: hook_params }
hook.reload
expect(response).to have_gitlab_http_status(:found)
expect(flash[:notice]).to include('successfully updated')
expect(hook).to have_attributes(hook_params.except(:url_variables))
expect(hook).to have_attributes(
url_variables: { 'token' => 'some secret value', 'baz' => 'woo' }
)
end
end

View file

@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Projects::HooksController do
include AfterNextHelpers
let_it_be(:project) { create(:project) }
let(:user) { project.first_owner }
@ -20,6 +22,36 @@ RSpec.describe Projects::HooksController do
end
end
describe '#update' do
let_it_be(:hook) { create(:project_hook, project: project) }
let(:params) do
{ namespace_id: project.namespace, project_id: project, id: hook.id }
end
it 'adds, updates and deletes URL variables' do
hook.update!(url_variables: { 'a' => 'bar', 'b' => 'woo' })
params[:hook] = {
url_variables: [
{ key: 'a', value: 'updated' },
{ key: 'b', value: nil },
{ key: 'c', value: 'new' }
]
}
put :update, params: params
expect(response).to have_gitlab_http_status(:found)
expect(flash[:notice]).to include('successfully updated')
expect(hook.reload.url_variables).to eq(
'a' => 'updated',
'c' => 'new'
)
end
end
describe '#edit' do
let_it_be(:hook) { create(:project_hook, project: project) }
@ -87,14 +119,30 @@ RSpec.describe Projects::HooksController do
job_events: true,
pipeline_events: true,
wiki_page_events: true,
deployment_events: true
deployment_events: true,
url_variables: [{ key: 'token', value: 'some secret value' }]
}
post :create, params: { namespace_id: project.namespace, project_id: project, hook: hook_params }
expect(response).to have_gitlab_http_status(:found)
expect(ProjectHook.all.size).to eq(1)
expect(ProjectHook.first).to have_attributes(hook_params)
expect(flash[:alert]).to be_blank
expect(ProjectHook.count).to eq(1)
expect(ProjectHook.first).to have_attributes(hook_params.except(:url_variables))
expect(ProjectHook.first).to have_attributes(url_variables: { 'token' => 'some secret value' })
end
it 'alerts the user if the new hook is invalid' do
hook_params = {
token: "TEST\nTOKEN",
url: "http://example.com"
}
post :create, params: { namespace_id: project.namespace, project_id: project, hook: hook_params }
expect(flash[:alert]).to be_present
expect(ProjectHook.count).to eq(0)
end
end
@ -109,6 +157,45 @@ RSpec.describe Projects::HooksController do
describe '#test' do
let(:hook) { create(:project_hook, project: project) }
context 'when the hook executes successfully' do
before do
stub_request(:post, hook.url).to_return(status: 200)
end
it 'informs the user' do
post :test, params: { namespace_id: project.namespace, project_id: project, id: hook }
expect(flash[:notice]).to include('executed successfully')
expect(flash[:notice]).to include('HTTP 200')
end
end
context 'when the hook runs, but fails' do
before do
stub_request(:post, hook.url).to_return(status: 400)
end
it 'informs the user' do
post :test, params: { namespace_id: project.namespace, project_id: project, id: hook }
expect(flash[:alert]).to include('executed successfully but')
expect(flash[:alert]).to include('HTTP 400')
end
end
context 'when the hook fails completely' do
before do
allow_next(::TestHooks::ProjectService)
.to receive(:execute).and_return({ message: 'All is woe' })
end
it 'informs the user' do
post :test, params: { namespace_id: project.namespace, project_id: project, id: hook }
expect(flash[:alert]).to include('failed: All is woe')
end
end
context 'when the endpoint receives requests above the limit', :freeze_time, :clean_gitlab_redis_rate_limiting do
before do
allow(Gitlab::ApplicationRateLimiter).to receive(:rate_limits)

View file

@ -73,26 +73,6 @@ RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrence
subject { described_class.new.perform(start_id, end_id) }
context 'when the migration is disabled by the feature flag' do
let(:start_id) { 1 }
let(:end_id) { 1001 }
before do
stub_feature_flags(migrate_vulnerability_finding_uuids: false)
end
it 'logs the info message and does not run the migration' do
expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |instance|
expect(instance).to receive(:info).once.with(message: 'Migration is disabled by the feature flag',
migrator: 'RecalculateVulnerabilitiesOccurrencesUuid',
start_id: start_id,
end_id: end_id)
end
subject
end
end
context "when finding has a UUIDv4" do
before do
@uuid_v4 = create_finding!(

View file

@ -645,7 +645,7 @@ RSpec.describe API::Groups do
project = create(:project, namespace: group2, path: 'Foo')
create(:project_group_link, project: project, group: group1)
get api("/groups/#{group1.id}", user1), params: { with_projects: false }
get api("/groups/#{group2.id}", user1), params: { with_projects: false }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['projects']).to be_nil
@ -748,6 +748,18 @@ RSpec.describe API::Groups do
expect(json_response).to include('runners_token')
end
it "returns runners_token and no projects when with_projects option is set to false" do
project = create(:project, namespace: group2, path: 'Foo')
create(:project_group_link, project: project, group: group1)
get api("/groups/#{group2.id}", admin), params: { with_projects: false }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['projects']).to be_nil
expect(json_response['shared_projects']).to be_nil
expect(json_response).to include('runners_token')
end
it "does not return a non existing group" do
get api("/groups/#{non_existing_record_id}", admin)