607 lines
25 KiB
PHP
607 lines
25 KiB
PHP
<?php
|
|
session_start();
|
|
// Define default config values
|
|
$defaultConfig = [
|
|
'chap_secrets_path' => '/etc/ppp/chap-secrets',
|
|
'admin_username' => 'admin',
|
|
'admin_password' => password_hash('change@me', PASSWORD_DEFAULT),
|
|
];
|
|
|
|
// Create config.php if it doesn't exist
|
|
if (!file_exists('config.php')) {
|
|
file_put_contents('config.php', '<?php return ' . var_export($defaultConfig, true) . ';');
|
|
}
|
|
|
|
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
|
|
header('Location: login.php');
|
|
exit();
|
|
}
|
|
|
|
$config = include 'config.php';
|
|
$file = $config['chap_secrets_path'];
|
|
|
|
// Read the file into an array
|
|
function readUsers($file) {
|
|
$users = [];
|
|
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
foreach ($lines as $line) {
|
|
if (strpos($line, '#') === 0 || strpos($line, 'tunnel') === 0) continue; // Skip comments and tunnel line
|
|
$parts = preg_split('/\s+/', $line);
|
|
if (count($parts) == 4) {
|
|
$users[] = [
|
|
'client' => $parts[0],
|
|
'server' => $parts[1],
|
|
'secret' => $parts[2],
|
|
'ip' => $parts[3]
|
|
];
|
|
}
|
|
}
|
|
return $users;
|
|
}
|
|
|
|
// Write the array back to the file
|
|
function writeUsers($file, $users) {
|
|
$content = "# Secrets for authentication using CHAP\n";
|
|
$content .= "# client server secret IP addresses\n";
|
|
$content .= "tunnel tunnel tunnel *\n";
|
|
foreach ($users as $user) {
|
|
$content .= "{$user['client']} {$user['server']} {$user['secret']} {$user['ip']}\n";
|
|
}
|
|
file_put_contents($file, $content);
|
|
}
|
|
|
|
// Generate random password
|
|
function generateRandomPassword($length = 12) {
|
|
return bin2hex(random_bytes($length / 2));
|
|
}
|
|
|
|
// Generate unique username
|
|
function generateUniqueUsername($users) {
|
|
do {
|
|
$username = 'user' . bin2hex(random_bytes(4));
|
|
$unique = true;
|
|
foreach ($users as $user) {
|
|
if ($user['client'] === $username) {
|
|
$unique = false;
|
|
break;
|
|
}
|
|
}
|
|
} while (!$unique);
|
|
return $username;
|
|
}
|
|
|
|
// Get the next available IP address
|
|
function getNextIp($users) {
|
|
if (empty($users)) {
|
|
return '10.255.10.11';
|
|
}
|
|
|
|
$lastIp = end($users)['ip'];
|
|
$lastIpLong = ip2long($lastIp);
|
|
$nextIpLong = $lastIpLong + 1;
|
|
|
|
// Define the current and next range boundaries
|
|
$currentRangeStart = ip2long('10.255.' . explode('.', $lastIp)[2] . '.2');
|
|
$currentRangeEnd = ip2long('10.255.' . explode('.', $lastIp)[2] . '.254');
|
|
|
|
// Check if the next IP exceeds the current range, move to the next range if necessary
|
|
if ($nextIpLong > $currentRangeEnd) {
|
|
$nextRangeStart = ip2long('10.255.' . (explode('.', $lastIp)[2] + 1) . '.2');
|
|
$nextRangeEnd = ip2long('10.255.' . (explode('.', $lastIp)[2] + 1) . '.254');
|
|
|
|
// Ensure the next range does not exceed the defined ranges
|
|
if ($nextRangeStart <= ip2long('10.255.255.254')) {
|
|
$nextIpLong = $nextRangeStart;
|
|
} else {
|
|
// Handle the case when all ranges are exhausted (optional)
|
|
// For simplicity, you might want to stop here or handle the wraparound
|
|
die('No more IP addresses available in the defined ranges.');
|
|
}
|
|
}
|
|
|
|
return long2ip($nextIpLong);
|
|
}
|
|
|
|
$users = readUsers($file);
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
// Handle logout
|
|
if (isset($_POST['logout'])) {
|
|
session_destroy();
|
|
header('Location: login.php');
|
|
exit();
|
|
}
|
|
|
|
// Handle add user
|
|
if (isset($_POST['add'])) {
|
|
$client = $_POST['client'];
|
|
$ip = $_POST['ip'] ?? getNextIp($users);
|
|
|
|
// Check for duplicate username and IP
|
|
foreach ($users as $user) {
|
|
if ($user['client'] === $client) {
|
|
echo json_encode(['error' => 'Username already exists']);
|
|
exit();
|
|
}
|
|
if ($user['ip'] === $ip) {
|
|
echo json_encode(['error' => 'IP address already exists']);
|
|
exit();
|
|
}
|
|
}
|
|
|
|
$newUser = [
|
|
'client' => $client,
|
|
'server' => '*',
|
|
'secret' => $_POST['secret'],
|
|
'ip' => $ip
|
|
];
|
|
$users[] = $newUser;
|
|
writeUsers($file, $users);
|
|
echo json_encode(['ip' => $newUser['ip']]);
|
|
exit();
|
|
} elseif (isset($_POST['delete'])) {
|
|
$index = (int)$_POST['index'];
|
|
array_splice($users, $index, 1);
|
|
writeUsers($file, $users);
|
|
exit();
|
|
} elseif (isset($_POST['addMultiple'])) {
|
|
$numUsers = (int)$_POST['numUsers'];
|
|
$ipRangeFrom = !empty($_POST['ipRangeFrom']) ? ip2long($_POST['ipRangeFrom']) : ip2long(getNextIp($users));
|
|
$ipRangeTo = !empty($_POST['ipRangeTo']) ? ip2long($_POST['ipRangeTo']) : $ipRangeFrom + $numUsers - 1;
|
|
|
|
$newUsers = [];
|
|
$addedUsers = 0;
|
|
|
|
for ($i = 0; $addedUsers < $numUsers; $i++) {
|
|
$username = generateUniqueUsername(array_merge($users, $newUsers));
|
|
$userIp = long2ip($ipRangeFrom + $i);
|
|
|
|
// Check for duplicate IP within existing and new users
|
|
$isDuplicateIp = false;
|
|
foreach (array_merge($users, $newUsers) as $user) {
|
|
if ($user['ip'] === $userIp) {
|
|
$isDuplicateIp = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($isDuplicateIp) {
|
|
continue;
|
|
}
|
|
|
|
// Ensure the IP range does not exceed the defined ranges
|
|
if ($ipRangeFrom + $i > ip2long('10.255.255.254')) {
|
|
echo json_encode(['error' => 'IP range exhausted. Please start a new range.']);
|
|
exit();
|
|
}
|
|
|
|
$newUsers[] = [
|
|
'client' => $username,
|
|
'server' => '*',
|
|
'secret' => generateRandomPassword(),
|
|
'ip' => $userIp
|
|
];
|
|
$addedUsers++;
|
|
}
|
|
|
|
$users = array_merge($users, $newUsers);
|
|
writeUsers($file, $users);
|
|
echo json_encode(['success' => true]);
|
|
exit();
|
|
} elseif (isset($_POST['changePassword'])) {
|
|
$newPassword = password_hash($_POST['newPassword'], PASSWORD_DEFAULT);
|
|
|
|
// Read the config file
|
|
$config = include 'config.php';
|
|
|
|
// Update the password in the config file
|
|
$config['admin_password'] = $newPassword;
|
|
|
|
// Write the updated config back to the file
|
|
file_put_contents('config.php', '<?php return ' . var_export($config, true) . ';');
|
|
|
|
echo json_encode(['success' => true]);
|
|
exit();
|
|
}
|
|
}
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Manage L2TP Users</title>
|
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
|
|
<style>
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes fadeOut {
|
|
from {
|
|
opacity: 1;
|
|
}
|
|
to {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
.fade-in {
|
|
animation: fadeIn 0.5s;
|
|
}
|
|
|
|
.fade-out {
|
|
animation: fadeOut 0.5s;
|
|
}
|
|
|
|
.table-responsive {
|
|
overflow-x: auto;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4">
|
|
<div class="container-fluid">
|
|
<a class="navbar-brand" href="#">L2TP User Manager</a>
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
<div class="collapse navbar-collapse" id="navbarNav">
|
|
<ul class="navbar-nav ms-auto">
|
|
<li class="nav-item">
|
|
<button class="btn btn-primary nav-link" data-bs-toggle="modal" data-bs-target="#changePasswordModal">Change Password</button>
|
|
</li>
|
|
<li class="nav-item">
|
|
<form method="post" action="index.php" class="d-inline">
|
|
<button type="submit" name="logout" class="btn btn-danger nav-link">Logout</button>
|
|
</form>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<div class="container mt-5">
|
|
|
|
|
|
<h2 class="mb-4 text-center">Manage L2TP Users</h2>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-bordered text-center">
|
|
<thead class="table-dark">
|
|
<tr>
|
|
<th>Username</th>
|
|
<th>Server</th>
|
|
<th>Password</th>
|
|
<th>IP Address</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="userTable">
|
|
<?php foreach ($users as $index => $user): ?>
|
|
<tr id="user-<?php echo $index; ?>">
|
|
<td><?php echo htmlspecialchars($user['client']); ?></td>
|
|
<td><?php echo htmlspecialchars($user['server']); ?></td>
|
|
<td><?php echo htmlspecialchars($user['secret']); ?></td>
|
|
<td><?php echo htmlspecialchars($user['ip']); ?></td>
|
|
<td>
|
|
<button class="btn btn-danger btn-sm" onclick="confirmDelete(<?php echo $index; ?>)" data-bs-toggle="modal" data-bs-target="#confirmDeleteModal">Delete</button>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="d-flex justify-content-center flex-wrap">
|
|
<button class="btn btn-success me-2 mb-2" data-bs-toggle="modal" data-bs-target="#userModal" onclick="resetForm()">Add User</button>
|
|
<button class="btn btn-secondary mb-2" data-bs-toggle="modal" data-bs-target="#multipleUsersModal">Add Multiple Users</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- User Modal -->
|
|
<div class="modal fade" id="userModal" tabindex="-1" aria-labelledby="userModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="userModalLabel">Add User</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="addUserForm">
|
|
<div class="mb-3">
|
|
<label for="client" class="form-label">Username</label>
|
|
<input type="text" class="form-control" id="client" name="client" required placeholder="Enter username">
|
|
<small class="form-text text-muted">Example: user123</small>
|
|
</div>
|
|
<div class="mb-3" style="display: none;">
|
|
<label for="server" class="form-label">Server</label>
|
|
<input type="text" class="form-control" id="server" name="server" value="*" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="secret" class="form-label">Password</label>
|
|
<input type="text" class="form-control" id="secret" name="secret" required placeholder="Enter password">
|
|
<small class="form-text text-muted">Example: P@ssw0rd123</small>
|
|
</div>
|
|
<div class="mb-3 form-check">
|
|
<input type="checkbox" class="form-check-input" id="manualIpCheck" onclick="toggleManualIp('single')">
|
|
<label class="form-check-label" for="manualIpCheck">Select IP Manually</label>
|
|
</div>
|
|
<div class="mb-3" id="ipInputSingle" style="display: none;">
|
|
<label for="ip" class="form-label">IP Address</label>
|
|
<input type="text" class="form-control" id="ip" name="ip" placeholder="Enter IP address">
|
|
<small class="form-text text-muted">Example: 10.255.10.15</small>
|
|
</div>
|
|
<button type="submit" class="btn btn-success w-100">Add User</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Multiple Users Modal -->
|
|
<div class="modal fade" id="multipleUsersModal" tabindex="-1" aria-labelledby="multipleUsersModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="multipleUsersModalLabel">Add Multiple Users</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="addMultipleUsersForm">
|
|
<div class="mb-3">
|
|
<label for="numUsers" class="form-label">Number of Users</label>
|
|
<input type="number" class="form-control" id="numUsers" name="numUsers" required placeholder="Enter number of users">
|
|
</div>
|
|
<div class="mb-3 form-check">
|
|
<input type="checkbox" class="form-check-input" id="manualIpCheckMultiple" onclick="toggleManualIp('multiple')">
|
|
<label class="form-check-label" for="manualIpCheckMultiple">Select IP Manually</label>
|
|
</div>
|
|
<div class="mb-3" id="ipInputMultiple" style="display: none;">
|
|
<label for="ipRangeFrom" class="form-label">IP Range From</label>
|
|
<input type="text" class="form-control" id="ipRangeFrom" name="ipRangeFrom" placeholder="Enter starting IP address">
|
|
<small class="form-text text-muted">Example: 10.255.10.15</small>
|
|
<label for="ipRangeTo" class="form-label mt-2">IP Range To</label>
|
|
<input type="text" class="form-control" id="ipRangeTo" name="ipRangeTo" placeholder="Enter ending IP address">
|
|
<small class="form-text text-muted">Example: 10.255.10.25</small>
|
|
</div>
|
|
<button type="submit" class="btn btn-success w-100">Add Users</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Confirm Delete Modal -->
|
|
<div class="modal fade" id="confirmDeleteModal" tabindex="-1" aria-labelledby="confirmDeleteModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="confirmDeleteModalLabel">Confirm Delete</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Are you sure you want to delete this user?</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<form id="deleteUserForm" method="POST" action="">
|
|
<input type="hidden" name="index" id="deleteIndex">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-danger">Delete</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Error Modal -->
|
|
<div class="modal fade" id="errorModal" tabindex="-1" aria-labelledby="errorModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="errorModalLabel">Error</h5>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p id="errorMessage"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" id="errorModalClose" aria-label="Close">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Change Password Modal -->
|
|
<div class="modal fade" id="changePasswordModal" tabindex="-1" aria-labelledby="changePasswordModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="changePasswordModalLabel">Change Password</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="changePasswordForm">
|
|
<div class="mb-3">
|
|
<label for="newPassword" class="form-label">New Password</label>
|
|
<input type="password" class="form-control" id="newPassword" name="newPassword" required placeholder="Enter new password">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="confirmPassword" class="form-label">Confirm Password</label>
|
|
<input type="password" class="form-control" id="confirmPassword" name="confirmPassword" required placeholder="Confirm new password">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary w-100">Change Password</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script>
|
|
document.getElementById('addUserForm').addEventListener('submit', function(event) {
|
|
event.preventDefault();
|
|
const client = document.getElementById('client').value;
|
|
const server = document.getElementById('server').value;
|
|
const secret = document.getElementById('secret').value;
|
|
const ip = document.getElementById('manualIpCheck').checked ? document.getElementById('ip').value : '';
|
|
|
|
const formData = new FormData();
|
|
formData.append('add', '1');
|
|
formData.append('client', client);
|
|
formData.append('server', server);
|
|
formData.append('secret', secret);
|
|
if (ip) formData.append('ip', ip);
|
|
|
|
fetch('', {
|
|
method: 'POST',
|
|
body: formData
|
|
}).then(response => response.json()) // Expecting JSON response from the server
|
|
.then(data => {
|
|
if (data.error) {
|
|
document.getElementById('errorMessage').textContent = data.error;
|
|
document.getElementById('errorModal').classList.add('show');
|
|
document.getElementById('errorModal').style.display = 'block';
|
|
} else {
|
|
const newRow = document.createElement('tr');
|
|
newRow.classList.add('fade-in');
|
|
const newIndex = document.getElementById('userTable').rows.length;
|
|
newRow.id = `user-${newIndex}`;
|
|
newRow.innerHTML = `
|
|
<td>${client}</td>
|
|
<td>${server}</td>
|
|
<td>${secret}</td>
|
|
<td>${data.ip}</td> <!-- Use the IP returned from the server -->
|
|
<td>
|
|
<button class="btn btn-danger btn-sm" onclick="confirmDelete(${newIndex})" data-bs-toggle="modal" data-bs-target="#confirmDeleteModal">Delete</button>
|
|
</td>
|
|
`;
|
|
document.getElementById('userTable').appendChild(newRow);
|
|
resetForm();
|
|
document.querySelector('#userModal .btn-close').click();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Close error modal on button click
|
|
document.getElementById('errorModalClose').addEventListener('click', function() {
|
|
document.getElementById('errorModal').classList.remove('show');
|
|
document.getElementById('errorModal').style.display = 'none';
|
|
});
|
|
|
|
document.getElementById('addMultipleUsersForm').addEventListener('submit', function(event) {
|
|
event.preventDefault();
|
|
const numUsers = document.getElementById('numUsers').value;
|
|
const ipRangeFrom = document.getElementById('manualIpCheckMultiple').checked ? document.getElementById('ipRangeFrom').value : '';
|
|
const ipRangeTo = document.getElementById('manualIpCheckMultiple').checked ? document.getElementById('ipRangeTo').value : '';
|
|
|
|
const formData = new FormData();
|
|
formData.append('addMultiple', '1');
|
|
formData.append('numUsers', numUsers);
|
|
if (ipRangeFrom && ipRangeTo) {
|
|
formData.append('ipRangeFrom', ipRangeFrom);
|
|
formData.append('ipRangeTo', ipRangeTo);
|
|
}
|
|
|
|
fetch('', {
|
|
method: 'POST',
|
|
body: formData
|
|
}).then(response => response.json())
|
|
.then(data => {
|
|
if (data.error) {
|
|
document.getElementById('errorMessage').textContent = data.error;
|
|
document.getElementById('errorModal').classList.add('show');
|
|
document.getElementById('errorModal').style.display = 'block';
|
|
} else {
|
|
location.reload();
|
|
}
|
|
});
|
|
});
|
|
|
|
document.getElementById('deleteUserForm').addEventListener('submit', function(event) {
|
|
event.preventDefault();
|
|
const index = document.getElementById('deleteIndex').value;
|
|
|
|
const formData = new FormData();
|
|
formData.append('delete', '1');
|
|
formData.append('index', index);
|
|
|
|
fetch('', {
|
|
method: 'POST',
|
|
body: formData
|
|
}).then(response => response.text())
|
|
.then(data => {
|
|
const row = document.getElementById(`user-${index}`);
|
|
row.classList.add('fade-out');
|
|
setTimeout(() => {
|
|
if (row) row.remove();
|
|
document.querySelector('#confirmDeleteModal .btn-close').click();
|
|
}, 500);
|
|
});
|
|
});
|
|
|
|
function resetForm() {
|
|
document.getElementById('client').value = '';
|
|
document.getElementById('server').value = '*';
|
|
document.getElementById('secret').value = '';
|
|
document.getElementById('ip').value = '';
|
|
document.getElementById('manualIpCheck').checked = false;
|
|
document.getElementById('ipInputSingle').style.display = 'none';
|
|
}
|
|
|
|
function toggleManualIp(formType) {
|
|
if (formType === 'single') {
|
|
const isChecked = document.getElementById('manualIpCheck').checked;
|
|
document.getElementById('ipInputSingle').style.display = isChecked ? 'block' : 'none';
|
|
} else if (formType === 'multiple') {
|
|
const isChecked = document.getElementById('manualIpCheckMultiple').checked;
|
|
document.getElementById('ipInputMultiple').style.display = isChecked ? 'block' : 'none';
|
|
}
|
|
}
|
|
|
|
function confirmDelete(index) {
|
|
document.getElementById('deleteIndex').value = index;
|
|
}
|
|
|
|
// Handle password change
|
|
document.getElementById('changePasswordForm').addEventListener('submit', function(event) {
|
|
event.preventDefault();
|
|
const newPassword = document.getElementById('newPassword').value;
|
|
const confirmPassword = document.getElementById('confirmPassword').value;
|
|
|
|
if (newPassword !== confirmPassword) {
|
|
document.getElementById('errorMessage').textContent = 'Passwords do not match';
|
|
document.getElementById('errorModal').classList.add('show');
|
|
document.getElementById('errorModal').style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData();
|
|
formData.append('changePassword', '1');
|
|
formData.append('newPassword', newPassword);
|
|
|
|
fetch('', {
|
|
method: 'POST',
|
|
body: formData
|
|
}).then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
alert('Password changed successfully');
|
|
document.getElementById('newPassword').value = '';
|
|
document.getElementById('confirmPassword').value = '';
|
|
document.querySelector('#changePasswordModal .btn-close').click();
|
|
} else {
|
|
document.getElementById('errorMessage').textContent = 'Failed to change password';
|
|
document.getElementById('errorModal').classList.add('show');
|
|
document.getElementById('errorModal').style.display = 'block';
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
|
|
</body>
|
|
</html>
|