hospital-management/templates/account/two_factor_device_list.html
2025-08-12 13:33:25 +03:00

521 lines
22 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Two-Factor Authentication Devices - Account Security{% endblock %}
{% block content %}
<div class="content">
<div class="container-fluid">
<!-- Page Header -->
<div class="row">
<div class="col-12">
<div class="page-header">
<div class="page-title">
<h4>Two-Factor Authentication</h4>
<h6>Manage your 2FA devices for enhanced account security</h6>
</div>
<div class="page-btn">
<a href="{% url 'accounts:two_factor_device_create' %}" class="btn btn-added">
<i class="fas fa-plus me-1"></i>Add New Device
</a>
</div>
</div>
</div>
</div>
<!-- Security Status Cards -->
<div class="row">
<div class="col-lg-3 col-sm-6 col-12">
<div class="dash-widget">
<div class="dash-widgetimg">
<span><i class="fas fa-shield-alt"></i></span>
</div>
<div class="dash-widgetcontent">
<h5>{{ stats.total_devices|default:3 }}</h5>
<h6>Total Devices</h6>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6 col-12">
<div class="dash-widget">
<div class="dash-widgetimg">
<span><i class="fas fa-check-circle"></i></span>
</div>
<div class="dash-widgetcontent">
<h5>{{ stats.active_devices|default:2 }}</h5>
<h6>Active Devices</h6>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6 col-12">
<div class="dash-widget">
<div class="dash-widgetimg">
<span><i class="fas fa-mobile-alt"></i></span>
</div>
<div class="dash-widgetcontent">
<h5>{{ stats.mobile_devices|default:2 }}</h5>
<h6>Mobile Apps</h6>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6 col-12">
<div class="dash-widget">
<div class="dash-widgetimg">
<span><i class="fas fa-key"></i></span>
</div>
<div class="dash-widgetcontent">
<h5>{{ stats.hardware_keys|default:1 }}</h5>
<h6>Hardware Keys</h6>
</div>
</div>
</div>
</div>
<!-- Security Recommendations -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-lightbulb me-2"></i>
Security Recommendations
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<div class="security-tip">
<i class="fas fa-mobile-alt text-primary fa-2x mb-2"></i>
<h6>Use Authenticator Apps</h6>
<p class="text-muted small">Apps like Google Authenticator or Authy provide secure time-based codes.</p>
</div>
</div>
<div class="col-md-4">
<div class="security-tip">
<i class="fas fa-key text-success fa-2x mb-2"></i>
<h6>Hardware Security Keys</h6>
<p class="text-muted small">Physical keys like YubiKey offer the highest level of security.</p>
</div>
</div>
<div class="col-md-4">
<div class="security-tip">
<i class="fas fa-copy text-warning fa-2x mb-2"></i>
<h6>Backup Codes</h6>
<p class="text-muted small">Keep backup codes in a safe place for account recovery.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 2FA Devices List -->
<div class="card">
<div class="card-body">
<div class="table-top">
<div class="search-set">
<div class="search-input">
<a class="btn btn-searchset">
<i class="fas fa-search"></i>
</a>
<input type="text" id="searchInput" placeholder="Search devices...">
</div>
</div>
<div class="wordset">
<ul>
<li>
<a data-bs-toggle="tooltip" data-bs-placement="top" title="Export" onclick="exportDevices()">
<i class="fas fa-download"></i>
</a>
</li>
<li>
<a data-bs-toggle="tooltip" data-bs-placement="top" title="Print" onclick="printDevices()">
<i class="fas fa-print"></i>
</a>
</li>
</ul>
</div>
</div>
<!-- Devices Table -->
<div class="table-responsive">
<table class="table" id="devicesTable">
<thead>
<tr>
<th>Device</th>
<th>Type</th>
<th>Status</th>
<th>Added</th>
<th>Last Used</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<!-- Sample Data -->
<tr>
<td>
<div class="deviceinfo">
<div class="device-icon me-3">
<i class="fas fa-mobile-alt fa-2x text-primary"></i>
</div>
<div>
<h6 class="mb-0">Google Authenticator</h6>
<small class="text-muted">Primary mobile device</small>
</div>
</div>
</td>
<td>
<span class="badge bg-primary">
<i class="fas fa-mobile-alt me-1"></i>Mobile App
</span>
</td>
<td>
<span class="badges bg-lightgreen">
<i class="fas fa-check-circle me-1"></i>Active
</span>
</td>
<td>
<div>
<strong>Jan 15, 2024</strong>
<small class="d-block text-muted">3 months ago</small>
</div>
</td>
<td>
<div>
<strong>Today 09:30 AM</strong>
<small class="d-block text-muted">2 hours ago</small>
</div>
</td>
<td>
<a class="me-3" href="{% url 'accounts:two_factor_device_detail' 1 %}" data-bs-toggle="tooltip" title="View Details">
<i class="fas fa-eye"></i>
</a>
<a class="me-3" href="#" data-bs-toggle="tooltip" title="Test Device" onclick="testDevice(1)">
<i class="fas fa-vial"></i>
</a>
<a class="confirm-text" href="{% url 'accounts:two_factor_device_delete' 1 %}" data-bs-toggle="tooltip" title="Remove Device">
<i class="fas fa-trash"></i>
</a>
</td>
</tr>
<tr>
<td>
<div class="deviceinfo">
<div class="device-icon me-3">
<i class="fas fa-key fa-2x text-success"></i>
</div>
<div>
<h6 class="mb-0">YubiKey 5 NFC</h6>
<small class="text-muted">Hardware security key</small>
</div>
</div>
</td>
<td>
<span class="badge bg-success">
<i class="fas fa-key me-1"></i>Hardware Key
</span>
</td>
<td>
<span class="badges bg-lightgreen">
<i class="fas fa-check-circle me-1"></i>Active
</span>
</td>
<td>
<div>
<strong>Dec 10, 2023</strong>
<small class="d-block text-muted">4 months ago</small>
</div>
</td>
<td>
<div>
<strong>Yesterday 02:15 PM</strong>
<small class="d-block text-muted">1 day ago</small>
</div>
</td>
<td>
<a class="me-3" href="{% url 'accounts:two_factor_device_detail' 2 %}" data-bs-toggle="tooltip" title="View Details">
<i class="fas fa-eye"></i>
</a>
<a class="me-3" href="#" data-bs-toggle="tooltip" title="Test Device" onclick="testDevice(2)">
<i class="fas fa-vial"></i>
</a>
<a class="confirm-text" href="{% url 'accounts:two_factor_device_delete' 2 %}" data-bs-toggle="tooltip" title="Remove Device">
<i class="fas fa-trash"></i>
</a>
</td>
</tr>
<tr>
<td>
<div class="deviceinfo">
<div class="device-icon me-3">
<i class="fas fa-sms fa-2x text-warning"></i>
</div>
<div>
<h6 class="mb-0">SMS Backup</h6>
<small class="text-muted">+1 (555) ***-1234</small>
</div>
</div>
</td>
<td>
<span class="badge bg-warning">
<i class="fas fa-sms me-1"></i>SMS
</span>
</td>
<td>
<span class="badges bg-lightyellow">
<i class="fas fa-pause-circle me-1"></i>Backup Only
</span>
</td>
<td>
<div>
<strong>Jan 15, 2024</strong>
<small class="d-block text-muted">3 months ago</small>
</div>
</td>
<td>
<div>
<strong>Never</strong>
<small class="d-block text-muted">Backup method</small>
</div>
</td>
<td>
<a class="me-3" href="{% url 'accounts:two_factor_device_detail' 3 %}" data-bs-toggle="tooltip" title="View Details">
<i class="fas fa-eye"></i>
</a>
<a class="me-3" href="#" data-bs-toggle="tooltip" title="Test Device" onclick="testDevice(3)">
<i class="fas fa-vial"></i>
</a>
<a class="confirm-text" href="{% url 'accounts:two_factor_device_delete' 3 %}" data-bs-toggle="tooltip" title="Remove Device">
<i class="fas fa-trash"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Empty State -->
<div id="emptyState" class="text-center py-5" style="display: none;">
<i class="fas fa-shield-alt fa-3x text-muted mb-3"></i>
<h5>No 2FA Devices Found</h5>
<p class="text-muted">Enhance your account security by adding two-factor authentication devices.</p>
<a href="{% url 'accounts:two_factor_device_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Add Your First Device
</a>
</div>
</div>
</div>
<!-- Security Tips -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-info-circle me-2"></i>
Security Best Practices
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<ul class="list-unstyled">
<li class="mb-2">
<i class="fas fa-check text-success me-2"></i>
Use multiple 2FA methods for redundancy
</li>
<li class="mb-2">
<i class="fas fa-check text-success me-2"></i>
Keep backup codes in a secure location
</li>
<li class="mb-2">
<i class="fas fa-check text-success me-2"></i>
Regularly test your 2FA devices
</li>
</ul>
</div>
<div class="col-md-6">
<ul class="list-unstyled">
<li class="mb-2">
<i class="fas fa-times text-danger me-2"></i>
Don't rely solely on SMS for 2FA
</li>
<li class="mb-2">
<i class="fas fa-times text-danger me-2"></i>
Don't share your 2FA codes with anyone
</li>
<li class="mb-2">
<i class="fas fa-times text-danger me-2"></i>
Don't screenshot or email backup codes
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize search functionality
const searchInput = document.getElementById('searchInput');
searchInput.addEventListener('keyup', function() {
filterDevices();
});
// Initialize tooltips
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
// Check if table is empty
checkEmptyState();
});
function filterDevices() {
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
const table = document.getElementById('devicesTable');
const rows = table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
let visibleRows = 0;
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
const deviceName = row.cells[0].textContent.toLowerCase();
const deviceType = row.cells[1].textContent.toLowerCase();
if (deviceName.includes(searchTerm) || deviceType.includes(searchTerm)) {
row.style.display = '';
visibleRows++;
} else {
row.style.display = 'none';
}
}
// Show/hide empty state
const emptyState = document.getElementById('emptyState');
const tableContainer = table.closest('.table-responsive');
if (visibleRows === 0) {
tableContainer.style.display = 'none';
emptyState.style.display = 'block';
} else {
tableContainer.style.display = 'block';
emptyState.style.display = 'none';
}
}
function checkEmptyState() {
const table = document.getElementById('devicesTable');
const rows = table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
if (rows.length === 0) {
const emptyState = document.getElementById('emptyState');
const tableContainer = table.closest('.table-responsive');
tableContainer.style.display = 'none';
emptyState.style.display = 'block';
}
}
function testDevice(deviceId) {
// Show loading state
const button = event.target.closest('a');
const originalIcon = button.innerHTML;
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
button.style.pointerEvents = 'none';
// Simulate test
setTimeout(() => {
alert('Test code sent to your device. Please check and verify.');
button.innerHTML = originalIcon;
button.style.pointerEvents = 'auto';
}, 2000);
}
function exportDevices() {
console.log('Exporting 2FA devices...');
alert('Export functionality would be implemented here.');
}
function printDevices() {
console.log('Printing 2FA devices...');
window.print();
}
</script>
<style>
.deviceinfo {
display: flex;
align-items: center;
}
.device-icon {
width: 50px;
text-align: center;
}
.security-tip {
text-align: center;
padding: 20px;
}
.security-tip i {
display: block;
margin: 0 auto;
}
.dash-widget {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
}
.dash-widget .dash-widgetimg span {
background: rgba(255, 255, 255, 0.2);
color: white;
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
}
.dash-widget .dash-widgetcontent h5 {
color: white;
font-size: 28px;
font-weight: 600;
margin: 10px 0 5px 0;
}
.dash-widget .dash-widgetcontent h6 {
color: rgba(255, 255, 255, 0.8);
font-size: 14px;
margin: 0;
}
@media (max-width: 768px) {
.deviceinfo {
flex-direction: column;
text-align: center;
}
.device-icon {
margin-bottom: 10px;
}
.security-tip {
padding: 15px;
}
}
</style>
{% endblock %}