feat(auth): add session-based login/logout with bcrypt hashing, seed default admin, templates and navbar updates; add auth middleware; pin SQLAlchemy 1.4.x for Py3.13; update TODOs

This commit is contained in:
HotSwapp
2025-10-06 19:04:36 -05:00
parent 227c74294f
commit 6aa4d59a25
14 changed files with 466 additions and 17 deletions

View File

@@ -1 +1,111 @@
<!-- Login form template -->
{% extends "base.html" %}
{% block title %}Login - Delphi Database{% endblock %}
{% block content %}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 col-lg-4">
<div class="card shadow-sm">
<div class="card-body">
<div class="text-center mb-4">
<img src="{{ url_for('static', path='/logo/delphi-logo.webp') }}" alt="Delphi Logo" class="mb-3" style="width: 60px; height: 60px;">
<h2 class="card-title">Welcome Back</h2>
<p class="text-muted">Sign in to access Delphi Database</p>
</div>
{% if error %}
<div class="alert alert-danger" role="alert">
<i class="bi bi-exclamation-triangle-fill me-2"></i>{{ error }}
</div>
{% endif %}
<form method="post" action="/login">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-person"></i></span>
<input type="text" class="form-control" id="username" name="username" required
placeholder="Enter your username" autocomplete="username">
</div>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-key"></i></span>
<input type="password" class="form-control" id="password" name="password" required
placeholder="Enter your password" autocomplete="current-password">
</div>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="rememberMe">
<label class="form-check-label" for="rememberMe">
Remember me
</label>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">
<i class="bi bi-box-arrow-in-right me-2"></i>Sign In
</button>
</div>
</form>
<div class="text-center mt-4">
<small class="text-muted">
<i class="bi bi-info-circle me-1"></i>
Default credentials: admin / admin123
</small>
</div>
</div>
</div>
<div class="text-center mt-3">
<small class="text-muted">
Don't have an account? Contact your administrator.
</small>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_scripts %}
<script>
// Auto-focus on username field
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('username').focus();
});
// Show/hide password toggle (optional enhancement)
document.addEventListener('DOMContentLoaded', function() {
const passwordField = document.getElementById('password');
const toggleBtn = document.createElement('button');
toggleBtn.type = 'button';
toggleBtn.className = 'btn btn-outline-secondary';
toggleBtn.innerHTML = '<i class="bi bi-eye"></i>';
toggleBtn.style.border = 'none';
toggleBtn.style.background = 'transparent';
// Add toggle functionality
toggleBtn.addEventListener('click', function() {
if (passwordField.type === 'password') {
passwordField.type = 'text';
this.innerHTML = '<i class="bi bi-eye-slash"></i>';
} else {
passwordField.type = 'password';
this.innerHTML = '<i class="bi bi-eye"></i>';
}
});
// Insert toggle button into password input group
const passwordInputGroup = passwordField.closest('.input-group');
if (passwordInputGroup) {
const span = passwordInputGroup.querySelector('.input-group-text');
passwordInputGroup.insertBefore(toggleBtn, span.nextSibling);
}
});
</script>
{% endblock %}