Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-09-29 15:53:15 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-09-29 15:53:43 +0300
commit8a2a8c40a84b97bd1df668b3458cf61cadce1c2a (patch)
tree838787352e579632098ddc791afe20b5ed856c12 /app
parent86842c660b55c74269649851bb694e40367e8bef (diff)
Add latest changes from gitlab-org/security/gitlab@14-3-stable-ee
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/authentication/two_factor_auth/components/manage_two_factor_form.vue98
-rw-r--r--app/assets/javascripts/authentication/two_factor_auth/index.js31
-rw-r--r--app/assets/javascripts/pages/profiles/two_factor_auths/index.js4
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb10
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml13
5 files changed, 148 insertions, 8 deletions
diff --git a/app/assets/javascripts/authentication/two_factor_auth/components/manage_two_factor_form.vue b/app/assets/javascripts/authentication/two_factor_auth/components/manage_two_factor_form.vue
new file mode 100644
index 00000000000..280c222c380
--- /dev/null
+++ b/app/assets/javascripts/authentication/two_factor_auth/components/manage_two_factor_form.vue
@@ -0,0 +1,98 @@
+<script>
+import { GlFormInput, GlFormGroup, GlButton, GlForm } from '@gitlab/ui';
+import csrf from '~/lib/utils/csrf';
+import { __ } from '~/locale';
+
+export const i18n = {
+ currentPassword: __('Current password'),
+ confirmWebAuthn: __(
+ 'Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices.',
+ ),
+ confirm: __('Are you sure? This will invalidate your registered applications and U2F devices.'),
+ disableTwoFactor: __('Disable two-factor authentication'),
+ regenerateRecoveryCodes: __('Regenerate recovery codes'),
+};
+
+export default {
+ name: 'ManageTwoFactorForm',
+ i18n,
+ components: {
+ GlForm,
+ GlFormInput,
+ GlFormGroup,
+ GlButton,
+ },
+ inject: [
+ 'webauthnEnabled',
+ 'profileTwoFactorAuthPath',
+ 'profileTwoFactorAuthMethod',
+ 'codesProfileTwoFactorAuthPath',
+ 'codesProfileTwoFactorAuthMethod',
+ ],
+ data() {
+ return {
+ method: '',
+ action: '#',
+ };
+ },
+ computed: {
+ confirmText() {
+ if (this.webauthnEnabled) {
+ return i18n.confirmWebAuthn;
+ }
+
+ return i18n.confirm;
+ },
+ },
+ methods: {
+ handleFormSubmit(event) {
+ this.method = event.submitter.dataset.formMethod;
+ this.action = event.submitter.dataset.formAction;
+ },
+ },
+ csrf,
+};
+</script>
+
+<template>
+ <gl-form
+ class="gl-display-inline-block"
+ method="post"
+ :action="action"
+ @submit="handleFormSubmit($event)"
+ >
+ <input type="hidden" name="_method" data-testid="test-2fa-method-field" :value="method" />
+ <input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
+
+ <gl-form-group :label="$options.i18n.currentPassword" label-for="current-password">
+ <gl-form-input
+ id="current-password"
+ type="password"
+ name="current_password"
+ required
+ data-qa-selector="current_password_field"
+ />
+ </gl-form-group>
+
+ <gl-button
+ type="submit"
+ class="btn-danger gl-mr-3 gl-display-inline-block"
+ data-testid="test-2fa-disable-button"
+ variant="danger"
+ :data-confirm="confirmText"
+ :data-form-action="profileTwoFactorAuthPath"
+ :data-form-method="profileTwoFactorAuthMethod"
+ >
+ {{ $options.i18n.disableTwoFactor }}
+ </gl-button>
+ <gl-button
+ type="submit"
+ class="gl-display-inline-block"
+ data-testid="test-2fa-regenerate-codes-button"
+ :data-form-action="codesProfileTwoFactorAuthPath"
+ :data-form-method="codesProfileTwoFactorAuthMethod"
+ >
+ {{ $options.i18n.regenerateRecoveryCodes }}
+ </gl-button>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/authentication/two_factor_auth/index.js b/app/assets/javascripts/authentication/two_factor_auth/index.js
index 5e59c44e8cd..f663c0705e6 100644
--- a/app/assets/javascripts/authentication/two_factor_auth/index.js
+++ b/app/assets/javascripts/authentication/two_factor_auth/index.js
@@ -1,8 +1,39 @@
import Vue from 'vue';
import { updateHistory, removeParams } from '~/lib/utils/url_utility';
+import ManageTwoFactorForm from './components/manage_two_factor_form.vue';
import RecoveryCodes from './components/recovery_codes.vue';
import { SUCCESS_QUERY_PARAM } from './constants';
+export const initManageTwoFactorForm = () => {
+ const el = document.querySelector('.js-manage-two-factor-form');
+
+ if (!el) {
+ return false;
+ }
+
+ const {
+ webauthnEnabled = false,
+ profileTwoFactorAuthPath = '',
+ profileTwoFactorAuthMethod = '',
+ codesProfileTwoFactorAuthPath = '',
+ codesProfileTwoFactorAuthMethod = '',
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ webauthnEnabled,
+ profileTwoFactorAuthPath,
+ profileTwoFactorAuthMethod,
+ codesProfileTwoFactorAuthPath,
+ codesProfileTwoFactorAuthMethod,
+ },
+ render(createElement) {
+ return createElement(ManageTwoFactorForm);
+ },
+ });
+};
+
export const initRecoveryCodes = () => {
const el = document.querySelector('.js-2fa-recovery-codes');
diff --git a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
index 50835333a54..f6f136f2402 100644
--- a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
+++ b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
@@ -1,5 +1,5 @@
import { mount2faRegistration } from '~/authentication/mount_2fa';
-import { initRecoveryCodes } from '~/authentication/two_factor_auth';
+import { initRecoveryCodes, initManageTwoFactorForm } from '~/authentication/two_factor_auth';
import { parseBoolean } from '~/lib/utils/common_utils';
const twoFactorNode = document.querySelector('.js-two-factor-auth');
@@ -14,3 +14,5 @@ if (skippable) {
mount2faRegistration();
initRecoveryCodes();
+
+initManageTwoFactorForm();
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index 5eb46421583..d1b9485f06d 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -3,6 +3,8 @@
class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
skip_before_action :check_two_factor_requirement
before_action :ensure_verified_primary_email, only: [:show, :create]
+ before_action :validate_current_password, only: [:create, :codes, :destroy]
+
before_action do
push_frontend_feature_flag(:webauthn)
end
@@ -134,6 +136,14 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
private
+ def validate_current_password
+ return if current_user.valid_password?(params[:current_password])
+
+ current_user.increment_failed_attempts!
+
+ redirect_to profile_two_factor_auth_path, alert: _('You must provide a valid current password')
+ end
+
def build_qr_code
uri = current_user.otp_provisioning_uri(account_string, issuer: issuer_host)
RQRCode.render_qrcode(uri, :svg, level: :m, unit: 3)
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 927b6d4edef..d1d6b6301b8 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -17,13 +17,7 @@
= _("You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication.")
%p
= _('If you lose your recovery codes you can generate new ones, invalidating all previous codes.')
- %div
- = link_to _('Disable two-factor authentication'), profile_two_factor_auth_path,
- method: :delete,
- data: { confirm: webauthn_enabled ? _('Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices.') : _('Are you sure? This will invalidate your registered applications and U2F devices.') },
- class: 'gl-button btn btn-danger gl-mr-3'
- = form_tag codes_profile_two_factor_auth_path, {style: 'display: inline-block', method: :post} do |f|
- = submit_tag _('Regenerate recovery codes'), class: 'gl-button btn btn-default'
+ .js-manage-two-factor-form{ data: { webauthn_enabled: webauthn_enabled, profile_two_factor_auth_path: profile_two_factor_auth_path, profile_two_factor_auth_method: 'delete', codes_profile_two_factor_auth_path: codes_profile_two_factor_auth_path, codes_profile_two_factor_auth_method: 'post' } }
- else
%p
@@ -53,6 +47,11 @@
.form-group
= label_tag :pin_code, _('Pin code'), class: "label-bold"
= text_field_tag :pin_code, nil, class: "form-control gl-form-input", required: true, data: { qa_selector: 'pin_code_field' }
+ .form-group
+ = label_tag :current_password, _('Current password'), class: 'label-bold'
+ = password_field_tag :current_password, nil, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' }
+ %p.form-text.text-muted
+ = _('Your current password is required to register a two-factor authenticator app.')
.gl-mt-3
= submit_tag _('Register with two-factor app'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'register_2fa_app_button' }