|
|
<%namespace name="base" file="/base/base.mako"/>
|
|
|
|
|
|
<div class="panel panel-default">
|
|
|
<div class="panel-heading">
|
|
|
<h3 class="panel-title">${_('Enable/Disable 2FA for your account')}</h3>
|
|
|
</div>
|
|
|
<div class="panel-body">
|
|
|
<div class="form">
|
|
|
<div class="fields">
|
|
|
<div class="field">
|
|
|
<div class="label">
|
|
|
<label>${_('2FA status')}:</label>
|
|
|
</div>
|
|
|
<div class="checkboxes">
|
|
|
|
|
|
<div class="form-check">
|
|
|
<label class="form-check-label">
|
|
|
<input type="radio" id="2faEnabled" value="1" ${'checked' if c.state_of_2fa else ''}>
|
|
|
${_('Enabled')}
|
|
|
</label>
|
|
|
<label class="form-check-label">
|
|
|
<input type="radio" id="2faDisabled" value="0" ${'checked' if not c.state_of_2fa else ''}>
|
|
|
${_('Disabled')}
|
|
|
</label>
|
|
|
</div>
|
|
|
% if c.locked_2fa:
|
|
|
<span class="help-block">${_('2FA settings cannot be changed here, because 2FA was forced enabled by RhodeCode Administrator.')}</span>
|
|
|
% endif
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<button id="saveBtn" class="btn btn-primary" ${'disabled' if c.locked_2fa else ''}>${_('Save')}</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
% if c.state_of_2fa:
|
|
|
<div class="panel panel-default">
|
|
|
<div class="panel-heading">
|
|
|
<h3 class="panel-title">${_('Regenerate 2FA recovery codes for your account')}</h3>
|
|
|
</div>
|
|
|
<div class="panel-body">
|
|
|
<form id="2faForm">
|
|
|
<input type="text" name="totp" placeholder="${_('Verify the code from the app')}" pattern="\d{6}"
|
|
|
style="width: 20%">
|
|
|
<button type="button" class="btn btn-primary" onclick="submitForm()">Verify</button>
|
|
|
</form>
|
|
|
<div id="result"></div>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
% endif
|
|
|
|
|
|
<script>
|
|
|
function submitForm() {
|
|
|
let formData = new FormData(document.getElementById("2faForm"));
|
|
|
let xhr = new XMLHttpRequest();
|
|
|
|
|
|
let success = function (response) {
|
|
|
let recovery_codes = response.recovery_codes;
|
|
|
showRecoveryCodesPopup(recovery_codes);
|
|
|
}
|
|
|
|
|
|
xhr.onreadystatechange = function () {
|
|
|
if (xhr.readyState == 4 && xhr.status == 200) {
|
|
|
let responseDoc = new DOMParser().parseFromString(xhr.responseText, "text/html");
|
|
|
let contentToDisplay = responseDoc.querySelector('#formErrors');
|
|
|
if (contentToDisplay) {
|
|
|
document.getElementById("result").innerHTML = contentToDisplay.innerHTML;
|
|
|
} else {
|
|
|
let regenerate_url = pyroutes.url('my_account_regenerate_2fa_recovery_codes');
|
|
|
ajaxPOST(regenerate_url, {'csrf_token': CSRF_TOKEN}, success);
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
let url = pyroutes.url('check_2fa');
|
|
|
xhr.open("POST", url, true);
|
|
|
xhr.send(formData);
|
|
|
}
|
|
|
|
|
|
document.getElementById('2faEnabled').addEventListener('click', function () {
|
|
|
document.getElementById('2faDisabled').checked = false;
|
|
|
});
|
|
|
document.getElementById('2faDisabled').addEventListener('click', function () {
|
|
|
document.getElementById('2faEnabled').checked = false;
|
|
|
});
|
|
|
|
|
|
function getStateValue() {
|
|
|
if (document.getElementById('2faEnabled').checked) {
|
|
|
return '1';
|
|
|
} else {
|
|
|
return '0';
|
|
|
}
|
|
|
};
|
|
|
|
|
|
function saveChanges(state) {
|
|
|
|
|
|
let post_data = {'state': state, 'csrf_token': CSRF_TOKEN};
|
|
|
let url = pyroutes.url('my_account_configure_2fa');
|
|
|
|
|
|
ajaxPOST(url, post_data, function(){}, function(){})
|
|
|
}
|
|
|
|
|
|
document.getElementById('saveBtn').addEventListener('click', function () {
|
|
|
var state = getStateValue();
|
|
|
saveChanges(state);
|
|
|
});
|
|
|
|
|
|
function showRecoveryCodesPopup(recoveryCodes) {
|
|
|
let funcData = {'recoveryCodes': recoveryCodes}
|
|
|
let recoveryCodesHtml = renderTemplate('recoveryCodes', funcData)
|
|
|
|
|
|
SwalNoAnimation.fire({
|
|
|
allowOutsideClick: false,
|
|
|
confirmButtonText: _gettext('I Copied the codes'),
|
|
|
title: _gettext('2FA Recovery Codes'),
|
|
|
html: recoveryCodesHtml
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|