106 lines
4.1 KiB
JavaScript
106 lines
4.1 KiB
JavaScript
(() => {
|
|
const auth = window.TrafficAuth;
|
|
const $ = (id) => document.getElementById(id);
|
|
const enrollmentByUser = new Map();
|
|
const userSelect = $('loginUser');
|
|
|
|
auth.users.forEach((user) => userSelect.add(new Option(`${user.username} · ${user.role === 'admin' ? '管理员' : '普通用户'}`, user.username)));
|
|
|
|
function nextPage() {
|
|
const next = new URLSearchParams(location.search).get('next');
|
|
return ['link-generator.html', 'link-history.html'].includes(next) ? next : 'link-generator.html';
|
|
}
|
|
|
|
function showToast(message) {
|
|
const toast = $('toast');
|
|
toast.textContent = message; toast.classList.add('show');
|
|
setTimeout(() => toast.classList.remove('show'), 1600);
|
|
}
|
|
|
|
function currentEnrollment() {
|
|
const username = userSelect.value;
|
|
if (!enrollmentByUser.has(username)) enrollmentByUser.set(username, auth.createEnrollment(username));
|
|
return enrollmentByUser.get(username);
|
|
}
|
|
|
|
function renderMode() {
|
|
const username = userSelect.value;
|
|
const user = auth.findUser(username);
|
|
const enrolled = auth.isEnrolled(username);
|
|
$('selectedRole').innerHTML = `<span class="user-role ${user.role}">${user.role === 'admin' ? '管理员' : '普通用户'}</span><small>${enrolled ? '已在当前浏览器绑定' : '首次使用,需要完成本机设置'}</small>`;
|
|
$('signinForm').classList.toggle('hidden', !enrolled);
|
|
$('enrollForm').classList.toggle('hidden', enrolled);
|
|
$('loginTitle').textContent = enrolled ? '用户登录' : '首次绑定';
|
|
$('loginSubtitle').textContent = enrolled ? '密码和动态验证码双重验证' : '设置密码并绑定 Google Authenticator';
|
|
$('signinMessage').textContent = '';
|
|
$('enrollMessage').textContent = '';
|
|
if (!enrolled) {
|
|
const enrollment = currentEnrollment();
|
|
$('setupKey').textContent = enrollment.secret.match(/.{1,4}/g).join(' ');
|
|
$('authAccountName').textContent = `Traffic Intelligence (${username})`;
|
|
}
|
|
}
|
|
|
|
$('signinForm').addEventListener('submit', async (event) => {
|
|
event.preventDefault();
|
|
const button = event.submitter;
|
|
button.disabled = true;
|
|
$('signinMessage').textContent = '正在验证…';
|
|
try {
|
|
await auth.login(userSelect.value, $('signinPassword').value, $('signinCode').value);
|
|
location.href = nextPage();
|
|
} catch (error) {
|
|
$('signinMessage').textContent = error.message;
|
|
button.disabled = false;
|
|
}
|
|
});
|
|
|
|
$('enrollForm').addEventListener('submit', async (event) => {
|
|
event.preventDefault();
|
|
const password = $('newPassword').value;
|
|
if (password !== $('confirmPassword').value) {
|
|
$('enrollMessage').textContent = '两次输入的密码不一致';
|
|
return;
|
|
}
|
|
const button = event.submitter;
|
|
button.disabled = true;
|
|
$('enrollMessage').textContent = '正在绑定…';
|
|
try {
|
|
await auth.enroll(userSelect.value, password, currentEnrollment().secret, $('setupCode').value);
|
|
location.href = nextPage();
|
|
} catch (error) {
|
|
$('enrollMessage').textContent = error.message;
|
|
button.disabled = false;
|
|
}
|
|
});
|
|
|
|
$('copySetupKey').addEventListener('click', async () => {
|
|
const secret = currentEnrollment().secret;
|
|
try { await navigator.clipboard.writeText(secret); }
|
|
catch (_) {
|
|
const area = document.createElement('textarea'); area.value = secret;
|
|
document.body.appendChild(area); area.select(); document.execCommand('copy'); area.remove();
|
|
}
|
|
showToast('设置密钥已复制');
|
|
});
|
|
|
|
$('resetEnrollment').addEventListener('click', () => {
|
|
const username = userSelect.value;
|
|
if (!window.confirm(`确定清除 ${username} 在当前浏览器的密码和 Authenticator 绑定吗?`)) return;
|
|
try {
|
|
auth.clearEnrollment(username);
|
|
enrollmentByUser.delete(username);
|
|
$('signinPassword').value = '';
|
|
$('signinCode').value = '';
|
|
renderMode();
|
|
showToast('本机绑定已清除,请重新设置');
|
|
} catch (error) {
|
|
$('signinMessage').textContent = error.message;
|
|
}
|
|
});
|
|
|
|
userSelect.addEventListener('change', renderMode);
|
|
if (auth.currentUser()) location.replace(nextPage());
|
|
else renderMode();
|
|
})();
|