password reset
This commit is contained in:
50
templates/auth/forgot_password.html
Normal file
50
templates/auth/forgot_password.html
Normal file
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Forgot Password - DocuPulse</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/auth.css') }}?v={{ 'css/auth.css'|asset_version }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/colors.css') }}?v={{ 'css/colors.css'|asset_version }}">
|
||||
<link rel="stylesheet" href="{{ url_for('main.dynamic_colors') }}?v={{ site_settings.updated_at.timestamp() }}" onload="console.log('[CSS] Dynamic colors loaded with version:', '{{ site_settings.updated_at.timestamp() }}')">
|
||||
<script src="{{ url_for('static', filename='js/color-logger.js') }}?v={{ 'js/color-logger.js'|asset_version }}"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="auth-container">
|
||||
<div class="card auth-card">
|
||||
<div class="auth-header text-center">
|
||||
<h2><i class="fas fa-key me-2"></i>Forgot Password</h2>
|
||||
<p class="mb-0">Enter your email to reset your password</p>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<form method="POST" action="{{ url_for('auth.forgot_password') }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">
|
||||
<i class="fas fa-envelope me-2" style="color: var(--primary-color);"></i>Email address
|
||||
</label>
|
||||
<input type="email" class="form-control" id="email" name="email" required>
|
||||
<div class="form-text">We'll send you a link to reset your password.</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100"
|
||||
style="background-color: var(--primary-color); border-color: var(--primary-color);"
|
||||
onmouseover="this.style.backgroundColor='var(--primary-light)'"
|
||||
onmouseout="this.style.backgroundColor='var(--primary-color)'">
|
||||
<i class="fas fa-paper-plane me-2"></i>Send Reset Link
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="text-center mt-3">
|
||||
<p class="mb-0">Remember your password? <a href="{{ url_for('auth.login') }}" class="text-decoration-none">Sign In</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -45,6 +45,11 @@
|
||||
<i class="fas fa-sign-in-alt me-2"></i>Sign In
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="text-center mt-3">
|
||||
<p class="mb-1"><a href="{{ url_for('auth.forgot_password') }}" class="text-decoration-none">Forgot your password?</a></p>
|
||||
<p class="mb-0">Don't have an account? <a href="{{ url_for('auth.register') }}" class="text-decoration-none">Sign Up</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
157
templates/auth/reset_password.html
Normal file
157
templates/auth/reset_password.html
Normal file
@@ -0,0 +1,157 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Reset Password - DocuPulse</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/auth.css') }}?v={{ 'css/auth.css'|asset_version }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/colors.css') }}?v={{ 'css/colors.css'|asset_version }}">
|
||||
<link rel="stylesheet" href="{{ url_for('main.dynamic_colors') }}?v={{ site_settings.updated_at.timestamp() }}" onload="console.log('[CSS] Dynamic colors loaded with version:', '{{ site_settings.updated_at.timestamp() }}')">
|
||||
<script src="{{ url_for('static', filename='js/color-logger.js') }}?v={{ 'js/color-logger.js'|asset_version }}"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="auth-container">
|
||||
<div class="card auth-card">
|
||||
<div class="auth-header text-center">
|
||||
<h2><i class="fas fa-lock me-2"></i>Reset Password</h2>
|
||||
<p class="mb-0">Enter your new password</p>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<form method="POST" action="{{ url_for('auth.reset_password', token=token) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">
|
||||
<i class="fas fa-lock me-2" style="color: var(--primary-color);"></i>New Password
|
||||
</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="confirm_password" class="form-label">
|
||||
<i class="fas fa-check-circle me-2" style="color: var(--primary-color);"></i>Confirm New Password
|
||||
</label>
|
||||
<input type="password" class="form-control" id="confirm_password" name="confirm_password" required>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 space-y-2">
|
||||
<h6 class="text-sm font-medium text-gray-700">Password Requirements:</h6>
|
||||
<ul class="list-unstyled" id="password-requirements">
|
||||
<li id="length-req" class="text-sm text-gray-500 mb-1">
|
||||
<i class="fas fa-times-circle mr-2"></i>At least 8 characters long
|
||||
</li>
|
||||
<li id="uppercase-req" class="text-sm text-gray-500 mb-1">
|
||||
<i class="fas fa-times-circle mr-2"></i>At least one uppercase letter
|
||||
</li>
|
||||
<li id="lowercase-req" class="text-sm text-gray-500 mb-1">
|
||||
<i class="fas fa-times-circle mr-2"></i>At least one lowercase letter
|
||||
</li>
|
||||
<li id="number-req" class="text-sm text-gray-500 mb-1">
|
||||
<i class="fas fa-times-circle mr-2"></i>At least one number
|
||||
</li>
|
||||
<li id="special-req" class="text-sm text-gray-500 mb-1">
|
||||
<i class="fas fa-times-circle mr-2"></i>At least one special character
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary w-100 mt-4"
|
||||
style="background-color: var(--primary-color); border-color: var(--primary-color);"
|
||||
onmouseover="this.style.backgroundColor='var(--primary-light)'"
|
||||
onmouseout="this.style.backgroundColor='var(--primary-color)'">
|
||||
<i class="fas fa-save me-2"></i>Reset Password
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="text-center mt-3">
|
||||
<p class="mb-0">Remember your password? <a href="{{ url_for('auth.login') }}" class="text-decoration-none">Sign In</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const passwordInput = document.getElementById('password');
|
||||
const confirmInput = document.getElementById('confirm_password');
|
||||
|
||||
function checkPasswordRequirements(password) {
|
||||
// Length check
|
||||
const lengthReq = document.getElementById('length-req');
|
||||
if (password.length >= 8) {
|
||||
lengthReq.classList.remove('text-gray-500');
|
||||
lengthReq.classList.add('text-success');
|
||||
lengthReq.querySelector('i').className = 'fas fa-check-circle mr-2';
|
||||
} else {
|
||||
lengthReq.classList.remove('text-success');
|
||||
lengthReq.classList.add('text-gray-500');
|
||||
lengthReq.querySelector('i').className = 'fas fa-times-circle mr-2';
|
||||
}
|
||||
|
||||
// Uppercase check
|
||||
const uppercaseReq = document.getElementById('uppercase-req');
|
||||
if (/[A-Z]/.test(password)) {
|
||||
uppercaseReq.classList.remove('text-gray-500');
|
||||
uppercaseReq.classList.add('text-success');
|
||||
uppercaseReq.querySelector('i').className = 'fas fa-check-circle mr-2';
|
||||
} else {
|
||||
uppercaseReq.classList.remove('text-success');
|
||||
uppercaseReq.classList.add('text-gray-500');
|
||||
uppercaseReq.querySelector('i').className = 'fas fa-times-circle mr-2';
|
||||
}
|
||||
|
||||
// Lowercase check
|
||||
const lowercaseReq = document.getElementById('lowercase-req');
|
||||
if (/[a-z]/.test(password)) {
|
||||
lowercaseReq.classList.remove('text-gray-500');
|
||||
lowercaseReq.classList.add('text-success');
|
||||
lowercaseReq.querySelector('i').className = 'fas fa-check-circle mr-2';
|
||||
} else {
|
||||
lowercaseReq.classList.remove('text-success');
|
||||
lowercaseReq.classList.add('text-gray-500');
|
||||
lowercaseReq.querySelector('i').className = 'fas fa-times-circle mr-2';
|
||||
}
|
||||
|
||||
// Number check
|
||||
const numberReq = document.getElementById('number-req');
|
||||
if (/[0-9]/.test(password)) {
|
||||
numberReq.classList.remove('text-gray-500');
|
||||
numberReq.classList.add('text-success');
|
||||
numberReq.querySelector('i').className = 'fas fa-check-circle mr-2';
|
||||
} else {
|
||||
numberReq.classList.remove('text-success');
|
||||
numberReq.classList.add('text-gray-500');
|
||||
numberReq.querySelector('i').className = 'fas fa-times-circle mr-2';
|
||||
}
|
||||
|
||||
// Special character check
|
||||
const specialReq = document.getElementById('special-req');
|
||||
if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
|
||||
specialReq.classList.remove('text-gray-500');
|
||||
specialReq.classList.add('text-success');
|
||||
specialReq.querySelector('i').className = 'fas fa-check-circle mr-2';
|
||||
} else {
|
||||
specialReq.classList.remove('text-success');
|
||||
specialReq.classList.add('text-gray-500');
|
||||
specialReq.querySelector('i').className = 'fas fa-times-circle mr-2';
|
||||
}
|
||||
}
|
||||
|
||||
passwordInput.addEventListener('input', function() {
|
||||
checkPasswordRequirements(this.value);
|
||||
});
|
||||
|
||||
confirmInput.addEventListener('input', function() {
|
||||
if (this.value === passwordInput.value) {
|
||||
this.style.borderColor = 'var(--primary-color)';
|
||||
} else {
|
||||
this.style.borderColor = '#dc2626';
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user