Implemented comprehensive Flask-Login authentication with single-user support. New Features: - Flask-Login integration with User model - Bcrypt password hashing via PasswordManager - Login, logout, and initial password setup routes - @login_required and @api_auth_required decorators - All API endpoints now require authentication - Bootstrap 5 dark theme UI templates - Dashboard with navigation - Remember me and next parameter redirect support Files Created (12): - web/auth/__init__.py, models.py, decorators.py, routes.py - web/routes/__init__.py, main.py - web/templates/login.html, setup.html, dashboard.html, scans.html, scan_detail.html - tests/test_authentication.py (30+ tests) Files Modified (6): - web/app.py: Added Flask-Login initialization and main routes - web/api/scans.py: Protected all endpoints with @api_auth_required - web/api/settings.py: Protected all endpoints with @api_auth_required - web/api/schedules.py: Protected all endpoints with @api_auth_required - web/api/alerts.py: Protected all endpoints with @api_auth_required - tests/conftest.py: Added authentication test fixtures Security: - Session-based authentication for both web UI and API - Secure password storage with bcrypt - Protected routes redirect to login page - Protected API endpoints return 401 Unauthorized - Health check endpoints remain accessible for monitoring Testing: - User model authentication and properties - Login success/failure flows - Logout and session management - Password setup workflow - API endpoint authentication requirements - Session persistence and remember me functionality - Next parameter redirect behavior Total: ~1,200 lines of code added 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
96 lines
3.6 KiB
HTML
96 lines
3.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" data-bs-theme="dark">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Setup - SneakyScanner</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<style>
|
|
body {
|
|
height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
}
|
|
.setup-container {
|
|
width: 100%;
|
|
max-width: 500px;
|
|
padding: 2rem;
|
|
}
|
|
.card {
|
|
border: none;
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
|
}
|
|
.brand-title {
|
|
color: #00d9ff;
|
|
font-weight: 600;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="setup-container">
|
|
<div class="card">
|
|
<div class="card-body p-5">
|
|
<div class="text-center mb-4">
|
|
<h1 class="brand-title">SneakyScanner</h1>
|
|
<p class="text-muted">Initial Setup</p>
|
|
</div>
|
|
|
|
<div class="alert alert-info mb-4">
|
|
<strong>Welcome!</strong> Please set an application password to secure your scanner.
|
|
</div>
|
|
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% if messages %}
|
|
{% for category, message in messages %}
|
|
<div class="alert alert-{{ 'danger' if category == 'error' else category }} alert-dismissible fade show" role="alert">
|
|
{{ message }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
<form method="post" action="{{ url_for('auth.setup') }}">
|
|
<div class="mb-3">
|
|
<label for="password" class="form-label">Password</label>
|
|
<input type="password"
|
|
class="form-control"
|
|
id="password"
|
|
name="password"
|
|
required
|
|
minlength="8"
|
|
autofocus
|
|
placeholder="Enter password (min 8 characters)">
|
|
<div class="form-text">Password must be at least 8 characters long.</div>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label for="confirm_password" class="form-label">Confirm Password</label>
|
|
<input type="password"
|
|
class="form-control"
|
|
id="confirm_password"
|
|
name="confirm_password"
|
|
required
|
|
minlength="8"
|
|
placeholder="Confirm your password">
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary btn-lg w-100">
|
|
Set Password
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-center mt-3">
|
|
<small class="text-muted">SneakyScanner v1.0 - Phase 2</small>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
</body>
|
|
</html>
|