Files
preauth/templates/login.html.twig
T
2026-01-17 10:57:57 -05:00

126 lines
5.1 KiB
Twig

{% extends 'base.html.twig' %}
{% block content %}
<h1>{{ env.title }}</h1>
<p id="preauth-message">{{ message|default }}</p>
<form id="preauth-form">
<input id="preauth-nonce" type="hidden" name="preauth_nonce" value="{{ nonce }}">
<div class="right"><label for="preauth-id">{{ env.id_name }}:</label></div>
<div><input type="text" name="preauth_id" id="preauth-id"
autocomplete="username" required="required" autofocus="autofocus"></div>
{% if env.allow_password %}
<div class="right boxTk">
<label for="preauth-token">{{ env.token_name }}:</label><br>
<span id="preauth-use-pw">🔃 {{ env.password_name }}</span></div>
<div class="boxTk"><input type="text" name="preauth_token" id="preauth-token"
autocomplete="one-time-code" required="required"></div>
<div class="right boxPw hidden">
<label for="preauth-password">{{ env.password_name }}:</label><br>
<span id="preauth-use-tk">🔃 {{ env.token_name }}</span></div>
<div class="boxPw hidden"><input type="password" name="preauth_password" id="preauth-password"
autocomplete="password" disabled="disabled" required="required"></div>
{% else %}
<div class="right"><label for="preauth-token">{{ env.token_name }}:</label></div>
<div><input type="text" name="preauth_token" id="preauth-token"
autocomplete="one-time-code" required="required"></div>
{% endif %}
<div class="center"><button type="submit">{{ env.submit_name }}</button></div>
</form>
<script>
const form = document.getElementById('preauth-form');
const message = document.getElementById('preauth-message');
{% if env.allow_password %}
const usePw = document.getElementById('preauth-use-pw');
const useTk = document.getElementById('preauth-use-tk');
const boxPw = document.querySelectorAll('.boxPw');
const boxTk = document.querySelectorAll('.boxTk');
usePw.addEventListener('click', (event) => {
form.preauth_token.value = '';
form.preauth_token.disabled = true;
form.preauth_password.disabled = false;
boxTk.forEach((element) => {
element.classList.add('hidden');
});
boxPw.forEach((element) => {
element.classList.remove('hidden');
});
});
useTk.addEventListener('click', (event) => {
form.preauth_password.value = '';
form.preauth_password.disabled = true;
form.preauth_token.disabled = false;
boxPw.forEach((element) => {
element.classList.add('hidden');
});
boxTk.forEach((element) => {
element.classList.remove('hidden');
});
});
{% endif %}
form.addEventListener('submit', (event) => {
event.preventDefault();
{% if env.allow_password %}
/* make base64url string containing our payload json object */
/* payload will contain either token or password */
const data = btoa(JSON.stringify({
id: form.preauth_id.value,
...( form.preauth_token.value && { token: form.preauth_token.value }),
...(( ! form.preauth_token.value) && { password: form.preauth_password.value }),
nonce: form.preauth_nonce.value,
json: true
})).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
{% else %}
/* make base64url string containing our payload json object */
const data = btoa(JSON.stringify({
id: form.preauth_id.value,
token: form.preauth_token.value,
nonce: form.preauth_nonce.value,
json: true
})).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
{% endif %}
/* send our request to the server */
fetch(window.location.href, {
method: 'GET',
headers: { 'X-Preauth': data },
}).then((response) => {
if (response.headers.has('Location')) {
/* follow redirect (not needed in most browsers) */
window.location.href = response.headers.get('Location');
} else if (response.headers.get('Content-Type') === 'application/json') {
/* got json, update the page */
response.json().then((content) => {
if (Object.hasOwn(content, 'message')) {
message.innerText = content.message;
}
if (Object.hasOwn(content, 'nonce')) {
form.preauth_nonce.value = content.nonce;
form.preauth_token.value = '';
form.preauth_token.focus();
}
}).catch((error) => {
console.log('failed to parse json from response');
console.log(error);
});
} else { /* non-json, non-redirect response */
/* overwrite the page */
response.text().then((text) => {
document.open();
document.write(text);
document.close();
}).catch((error) => {
console.log('failed to get text from response');
console.log(error);
});
}
});
});
</script>
{% endblock %}