2026-03-16 19:19:22 +01:00
|
|
|
{% extends "base.html" %}
|
|
|
|
|
{% block title %}Login — diora{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block content %}
|
|
|
|
|
<div class="auth-container">
|
|
|
|
|
<h1 class="auth-title">Login</h1>
|
|
|
|
|
<form method="post" class="auth-form">
|
|
|
|
|
{% csrf_token %}
|
|
|
|
|
{% for field in form %}
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label class="form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
|
|
|
|
|
{{ field }}
|
|
|
|
|
{% if field.errors %}
|
|
|
|
|
<ul class="field-errors">
|
|
|
|
|
{% for error in field.errors %}
|
|
|
|
|
<li>{{ error }}</li>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</ul>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
{% if form.non_field_errors %}
|
|
|
|
|
<div class="form-errors">
|
|
|
|
|
{% for error in form.non_field_errors %}
|
|
|
|
|
<p>{{ error }}</p>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
<button type="submit" class="btn btn-primary btn-full">Login</button>
|
|
|
|
|
</form>
|
|
|
|
|
<p class="auth-switch">
|
|
|
|
|
Don't have an account? <a href="{% url 'register' %}">Register</a>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
{% endblock %}
|
2026-03-19 13:39:59 +01:00
|
|
|
|
|
|
|
|
{% block extra_js %}
|
|
|
|
|
<script>
|
|
|
|
|
(function () {
|
|
|
|
|
var form = document.querySelector('.auth-form');
|
|
|
|
|
if (!form) return;
|
|
|
|
|
form.addEventListener('submit', async function (e) {
|
|
|
|
|
var u = form.querySelector('[name=username]');
|
|
|
|
|
var p = form.querySelector('[name=password]');
|
|
|
|
|
if (!u || !p || !u.value || !p.value) return;
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
try {
|
|
|
|
|
var enc = new TextEncoder();
|
|
|
|
|
var mat = await crypto.subtle.importKey('raw', enc.encode(p.value), 'PBKDF2', false, ['deriveKey']);
|
|
|
|
|
var key = await crypto.subtle.deriveKey(
|
|
|
|
|
{name: 'PBKDF2', salt: enc.encode('diora:' + u.value), iterations: 200000, hash: 'SHA-256'},
|
|
|
|
|
mat, {name: 'AES-GCM', length: 256}, true, ['encrypt', 'decrypt']
|
|
|
|
|
);
|
|
|
|
|
var raw = await crypto.subtle.exportKey('raw', key);
|
|
|
|
|
localStorage.setItem('diora_pending_enc_key', btoa(String.fromCharCode(...new Uint8Array(raw))));
|
|
|
|
|
} catch (err) {}
|
|
|
|
|
form.submit();
|
|
|
|
|
});
|
|
|
|
|
})();
|
|
|
|
|
</script>
|
|
|
|
|
{% endblock %}
|