113 lines
3.4 KiB
HTML
113 lines
3.4 KiB
HTML
{% extends "base_settings_page.html" %}
|
|
{% block content %}
|
|
|
|
|
|
<div class="alert alert-dismissible alert-warning">
|
|
<h4 class="alert-heading">Warning!</h4>
|
|
<p class="mb-0">Once a new factor has been added to your account, you can not access
|
|
your account anymore using only your password. If you remove all your second factors,
|
|
2 Factor Authentication is automatically disabled for your account.</p>
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<a href="/settings/two_factors/add_totp" type="button" class="btn btn-primary">Add Authenticator App</a>
|
|
<a href="/settings/two_factors/add_webauthn" type="button" class="btn btn-primary">Add Security Key</a>
|
|
</p>
|
|
|
|
<table class="table table-hover" style="max-width: 800px;" aria-describedby="Factors list">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">Factor type</th>
|
|
<th scope="col">Name</th>
|
|
<th scope="col">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for f in user.two_factor %}
|
|
<tr id="factor-{{ f.id.0 }}">
|
|
<td><img src="{{ f.type_image() }}" alt="Factor icon" style="height: 1.5em; margin-right: 0.5em;" />{{ f.type_str() }}</td>
|
|
<td>{{ f.name }}</td>
|
|
<td><a href="javascript:delete_factor('{{ f.id.0 }}');">Delete</a></td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
|
|
{% if !user.last_successful_2fa.is_empty() %}
|
|
<div id="2fa_history_container">
|
|
<h5 style="margin-top: 50px">Successful 2FA login history</h5>
|
|
<p>
|
|
<a type="button" class="btn btn-danger btn-sm" onclick="clear_login_history()">Clear history</a>
|
|
</p>
|
|
<table class="table table-hover" style="max-width: 800px;" aria-describedby="Factors list">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">IP address</th>
|
|
<th scope="col">Date</th>
|
|
<th scope="col">Bypass 2FA</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for e in user.get_formatted_2fa_successful_logins() %}
|
|
<tr>
|
|
<td>{{ e.ip }}</td>
|
|
<td>{{ e.fmt_time() }}</td>
|
|
<td>{% if e.can_bypass_2fa %}YES{% else %}NO{% endif %}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<script>
|
|
async function delete_factor(id) {
|
|
if (!confirm("Do you really want to remove this factor?"))
|
|
return;
|
|
|
|
try {
|
|
const res = await fetch("/settings/api/two_factor/delete_factor", {
|
|
method: "post",
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
id: id,
|
|
})
|
|
});
|
|
|
|
let text = await res.text();
|
|
alert(text);
|
|
|
|
if (res.status == 200)
|
|
document.getElementById("factor-" + id).remove();
|
|
} catch(e) {
|
|
console.error(e);
|
|
alert("Failed to remove factor!");
|
|
}
|
|
}
|
|
|
|
async function clear_login_history() {
|
|
if (!confirm("Do you really want to clear your 2FA login history?"))
|
|
return;
|
|
|
|
try {
|
|
const res = await fetch("/settings/api/two_factor/clear_login_history", {
|
|
method: "post"
|
|
});
|
|
|
|
let text = await res.text();
|
|
alert(text);
|
|
|
|
if (res.status == 200)
|
|
document.getElementById("2fa_history_container").remove();
|
|
} catch(e) {
|
|
console.error(e);
|
|
alert("Failed to clear 2FA history!");
|
|
}
|
|
}
|
|
|
|
</script>
|
|
{% endblock content %}
|