Destroy repo mirrors instead of disabling them
It is important to destroy data related to repo mirrors when they are disabled. Use `_destroy` nested attribute instead of `enabled` for push mirrors. Call `remove_import_data` after saving a project if its pull mirror is disabled.
This commit is contained in:
parent
53823531ff
commit
18c07084a6
|
|
@ -87,7 +87,7 @@ export default class MirrorRepos {
|
|||
project: {
|
||||
remote_mirrors_attributes: {
|
||||
id: $target.data('mirrorId'),
|
||||
enabled: 0,
|
||||
_destroy: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,12 +24,6 @@ export default class SSHMirror {
|
|||
|
||||
this.$wellAuthTypeChanging = this.$form.find('.js-well-changing-auth');
|
||||
this.$wellPasswordAuth = this.$form.find('.js-well-password-auth');
|
||||
this.$wellSSHAuth = this.$form.find('.js-well-ssh-auth');
|
||||
this.$sshPublicKeyWrap = this.$form.find('.js-ssh-public-key-wrap');
|
||||
this.$regeneratePublicSshKeyButton = this.$wellSSHAuth.find('.js-btn-regenerate-ssh-key');
|
||||
this.$regeneratePublicSshKeyModal = this.$wellSSHAuth.find(
|
||||
'.js-regenerate-public-ssh-key-confirm-modal',
|
||||
);
|
||||
}
|
||||
|
||||
init() {
|
||||
|
|
@ -40,15 +34,6 @@ export default class SSHMirror {
|
|||
this.$dropdownAuthType.on('change', e => this.handleAuthTypeChange(e));
|
||||
this.$btnDetectHostKeys.on('click', e => this.handleDetectHostKeys(e));
|
||||
this.$btnSSHHostsShowAdvanced.on('click', e => this.handleSSHHostsAdvanced(e));
|
||||
this.$regeneratePublicSshKeyButton.on('click', () =>
|
||||
this.$regeneratePublicSshKeyModal.toggle(true),
|
||||
);
|
||||
$('.js-confirm', this.$regeneratePublicSshKeyModal).on('click', e =>
|
||||
this.regeneratePublicSshKey(e),
|
||||
);
|
||||
$('.js-cancel', this.$regeneratePublicSshKeyModal).on('click', () =>
|
||||
this.$regeneratePublicSshKeyModal.toggle(false),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -162,54 +147,11 @@ export default class SSHMirror {
|
|||
* Authentication method dropdown change event listener
|
||||
*/
|
||||
handleAuthTypeChange() {
|
||||
const projectMirrorAuthTypeEndpoint = `${this.$form.attr('action')}.json`;
|
||||
const $sshPublicKey = this.$sshPublicKeyWrap.find('.ssh-public-key');
|
||||
const selectedAuthType = this.$dropdownAuthType.val();
|
||||
|
||||
this.$wellPasswordAuth.collapse('hide');
|
||||
this.$wellSSHAuth.collapse('hide');
|
||||
this.updateHiddenAuthType(selectedAuthType);
|
||||
|
||||
// This request should happen only if selected Auth type was SSH
|
||||
// and SSH Public key was not present on page load
|
||||
if (selectedAuthType === AUTH_METHOD.SSH && !$sshPublicKey.text().trim()) {
|
||||
if (!this.$wellSSHAuth.length) return;
|
||||
|
||||
// Construct request body
|
||||
const authTypeData = {
|
||||
project: {
|
||||
...this.$regeneratePublicSshKeyButton.data().projectData,
|
||||
},
|
||||
};
|
||||
|
||||
this.$wellAuthTypeChanging.collapse('show');
|
||||
this.$dropdownAuthType.disable();
|
||||
|
||||
axios
|
||||
.put(projectMirrorAuthTypeEndpoint, JSON.stringify(authTypeData), {
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
})
|
||||
.then(({ data }) => {
|
||||
// Show SSH public key container and fill in public key
|
||||
this.toggleAuthWell(selectedAuthType);
|
||||
this.toggleSSHAuthWellMessage(true);
|
||||
this.setSSHPublicKey(data.import_data_attributes.ssh_public_key);
|
||||
|
||||
this.$wellAuthTypeChanging.collapse('hide');
|
||||
this.$dropdownAuthType.enable();
|
||||
})
|
||||
.catch(() => {
|
||||
Flash(__('Something went wrong on our end.'));
|
||||
|
||||
this.$wellAuthTypeChanging.collapse('hide');
|
||||
this.$dropdownAuthType.enable();
|
||||
});
|
||||
} else {
|
||||
this.toggleAuthWell(selectedAuthType);
|
||||
this.$wellSSHAuth.find('.js-ssh-public-key-present').collapse('show');
|
||||
}
|
||||
this.toggleAuthWell(selectedAuthType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -235,7 +177,6 @@ export default class SSHMirror {
|
|||
*/
|
||||
toggleAuthWell(authType) {
|
||||
this.$wellPasswordAuth.collapse(authType === AUTH_METHOD.PASSWORD ? 'show' : 'hide');
|
||||
this.$wellSSHAuth.collapse(authType === AUTH_METHOD.SSH ? 'show' : 'hide');
|
||||
this.updateHiddenAuthType(authType);
|
||||
}
|
||||
|
||||
|
|
@ -244,64 +185,11 @@ export default class SSHMirror {
|
|||
this.$hiddenAuthType.prop('disabled', authType === AUTH_METHOD.SSH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle SSH auth information message
|
||||
*/
|
||||
toggleSSHAuthWellMessage(sshKeyPresent) {
|
||||
this.$sshPublicKeyWrap.collapse(sshKeyPresent ? 'show' : 'hide');
|
||||
this.$wellSSHAuth.find('.js-ssh-public-key-present').collapse(sshKeyPresent ? 'show' : 'hide');
|
||||
this.$regeneratePublicSshKeyButton.collapse(sshKeyPresent ? 'show' : 'hide');
|
||||
this.$wellSSHAuth.find('.js-ssh-public-key-pending').collapse(sshKeyPresent ? 'hide' : 'show');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets SSH Public key to Clipboard button and shows it on UI.
|
||||
*/
|
||||
setSSHPublicKey(sshPublicKey) {
|
||||
this.$sshPublicKeyWrap.find('.ssh-public-key').text(sshPublicKey);
|
||||
this.$sshPublicKeyWrap
|
||||
.find('.btn-copy-ssh-public-key')
|
||||
.attr('data-clipboard-text', sshPublicKey);
|
||||
}
|
||||
|
||||
regeneratePublicSshKey(event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.$regeneratePublicSshKeyModal.toggle(false);
|
||||
|
||||
const button = this.$regeneratePublicSshKeyButton;
|
||||
const spinner = $('.js-spinner', button);
|
||||
const endpoint = button.data('endpoint');
|
||||
const authTypeData = {
|
||||
project: {
|
||||
...this.$regeneratePublicSshKeyButton.data().projectData,
|
||||
},
|
||||
};
|
||||
|
||||
button.attr('disabled', 'disabled');
|
||||
spinner.removeClass('d-none');
|
||||
|
||||
axios
|
||||
.patch(endpoint, authTypeData)
|
||||
.then(({ data }) => {
|
||||
button.removeAttr('disabled');
|
||||
spinner.addClass('d-none');
|
||||
|
||||
this.setSSHPublicKey(data.import_data_attributes.ssh_public_key);
|
||||
})
|
||||
.catch(() => {
|
||||
Flash(__('Unable to regenerate public ssh key.'));
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.$repositoryUrl.off('keyup');
|
||||
this.$form.find('.js-known-hosts').off('keyup');
|
||||
this.$dropdownAuthType.off('change');
|
||||
this.$btnDetectHostKeys.off('click');
|
||||
this.$btnSSHHostsShowAdvanced.off('click');
|
||||
this.$regeneratePublicSshKeyButton.off('click');
|
||||
$('.js-confirm', this.$regeneratePublicSshKeyModal).off('click');
|
||||
$('.js-cancel', this.$regeneratePublicSshKeyModal).off('click');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ class Projects::MirrorsController < Projects::ApplicationController
|
|||
password
|
||||
ssh_known_hosts
|
||||
regenerate_ssh_private_key
|
||||
_destroy
|
||||
]
|
||||
]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
- mirror = f.object
|
||||
- is_push = local_assigns.fetch(:is_push, false)
|
||||
- auth_options = [[_('Password'), 'password'], [_('SSH public key'), 'ssh_public_key']]
|
||||
- regen_data = { auth_method: 'ssh_public_key', regenerate_ssh_private_key: true }
|
||||
- ssh_public_key_present = mirror.ssh_public_key.present?
|
||||
|
||||
.form-group
|
||||
= f.label :auth_method, _('Authentication method'), class: 'label-bold'
|
||||
|
|
@ -17,21 +14,3 @@
|
|||
.well-password-auth.collapse.js-well-password-auth
|
||||
= f.label :password, _("Password"), class: "label-bold"
|
||||
= f.password_field :password, value: mirror.password, class: 'form-control qa-password', autocomplete: 'new-password'
|
||||
- unless is_push
|
||||
.well-ssh-auth.collapse.js-well-ssh-auth
|
||||
%p.js-ssh-public-key-present{ class: ('collapse' unless ssh_public_key_present) }
|
||||
= _('Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation.')
|
||||
%p.js-ssh-public-key-pending{ class: ('collapse' if ssh_public_key_present) }
|
||||
= _('An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation.')
|
||||
|
||||
.clearfix.js-ssh-public-key-wrap{ class: ('collapse' unless ssh_public_key_present) }
|
||||
%code.prepend-top-10.ssh-public-key
|
||||
= mirror.ssh_public_key
|
||||
= clipboard_button(text: mirror.ssh_public_key, title: _("Copy SSH public key to clipboard"), class: 'prepend-top-10 btn-copy-ssh-public-key')
|
||||
|
||||
= button_tag type: 'button',
|
||||
data: { endpoint: project_mirror_path(@project), project_data: { import_data_attributes: regen_data } },
|
||||
class: "btn btn-inverted btn-warning prepend-top-10 js-btn-regenerate-ssh-key#{ ' collapse' unless ssh_public_key_present }" do
|
||||
= icon('spinner spin', class: 'js-spinner d-none')
|
||||
= _('Regenerate key')
|
||||
= render 'projects/mirrors/regenerate_public_ssh_key_confirm_modal'
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
= rm_f.hidden_field :url, class: 'js-mirror-url-hidden', required: true, pattern: "(#{protocols}):\/\/.+"
|
||||
= rm_f.hidden_field :only_protected_branches, class: 'js-mirror-protected-hidden'
|
||||
= render partial: 'projects/mirrors/ssh_host_keys', locals: { f: rm_f }
|
||||
= render partial: 'projects/mirrors/authentication_method', locals: { f: rm_f, is_push: true }
|
||||
= render partial: 'projects/mirrors/authentication_method', locals: { f: rm_f }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
- verified_at = mirror.ssh_known_hosts_verified_at
|
||||
|
||||
.form-group.js-ssh-host-keys-section{ class: ('collapse' unless mirror.ssh_mirror_url?) }
|
||||
%button.btn.btn-inverted.btn-success.inline.js-detect-host-keys.append-right-10{ type: 'button' }
|
||||
%button.btn.btn-inverted.btn-secondary.inline.js-detect-host-keys.append-right-10{ type: 'button' }
|
||||
= icon('spinner spin', class: 'js-spinner d-none')
|
||||
= _('Detect host keys')
|
||||
.fingerprint-ssh-info.js-fingerprint-ssh-info.prepend-top-10.append-bottom-10{ class: ('collapse' unless mirror.ssh_mirror_url?) }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Destroy project remote mirrors instead of disabling
|
||||
merge_request: 27087
|
||||
author:
|
||||
type: security
|
||||
|
|
@ -811,9 +811,6 @@ msgstr ""
|
|||
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
|
||||
msgstr ""
|
||||
|
||||
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
|
||||
msgstr ""
|
||||
|
||||
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -2811,9 +2808,6 @@ msgstr ""
|
|||
msgid "Copy SSH public key"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy SSH public key to clipboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy URL to clipboard"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -4762,9 +4756,6 @@ msgstr ""
|
|||
msgid "Help page text and support page url."
|
||||
msgstr ""
|
||||
|
||||
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
|
||||
msgstr ""
|
||||
|
||||
msgid "Hide file browser"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -10154,9 +10145,6 @@ msgstr ""
|
|||
msgid "Unable to load the diff. %{button_try_again}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unable to regenerate public ssh key."
|
||||
msgstr ""
|
||||
|
||||
msgid "Unable to resolve"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -217,5 +217,24 @@ describe 'Projects > Settings > Repository settings' do
|
|||
expect(RepositoryCleanupWorker.jobs.count).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an existing mirror', :js do
|
||||
let(:mirrored_project) { create(:project, :repository, :remote_mirror) }
|
||||
|
||||
before do
|
||||
mirrored_project.add_maintainer(user)
|
||||
|
||||
visit project_settings_repository_path(mirrored_project)
|
||||
end
|
||||
|
||||
it 'delete remote mirrors' do
|
||||
expect(mirrored_project.remote_mirrors.count).to eq(1)
|
||||
|
||||
find('.js-delete-mirror').click
|
||||
wait_for_requests
|
||||
|
||||
expect(mirrored_project.remote_mirrors.count).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue