FlexPass_v.0005
This commit is contained in:
parent
3d274404c6
commit
0f1653e913
@ -36,8 +36,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$errors[] = "Client ID already exists.";
|
||||
} else {
|
||||
// Insert into database
|
||||
$stmt = $pdo->prepare("INSERT INTO clients (client_id, name, status) VALUES (?, ?, ?)");
|
||||
if ($stmt->execute([$clientId, $clientName, $status])) {
|
||||
$stmt = $pdo->prepare("INSERT INTO clients (client_id, name, status, user_id) VALUES (?, ?, ?, ?)");
|
||||
if ($stmt->execute([$clientId, $clientName, $status, $_SESSION['user_id']])) {
|
||||
log_audit_event('client_create', $_SESSION['user_id'], 'client', $clientId);
|
||||
header("Location: dashboard.php?status=client_added");
|
||||
exit;
|
||||
|
||||
@ -131,7 +131,13 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
if (confirm('Are you sure you want to delete this note?')) {
|
||||
const noteId = deleteButton.dataset.noteId;
|
||||
|
||||
fetch(`delete-note.php?note_id=${noteId}`)
|
||||
const formData = new FormData();
|
||||
formData.append('note_id', noteId);
|
||||
|
||||
fetch('delete-note.php', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
|
||||
BIN
assets/pasted-20250925-212907-b1dbc7c4.png
Normal file
BIN
assets/pasted-20250925-212907-b1dbc7c4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
@ -15,8 +15,8 @@ $viewingClient = null;
|
||||
$clients = [];
|
||||
|
||||
if (isset($_GET['client_id'])) {
|
||||
$stmt = $pdo->prepare("SELECT * FROM clients WHERE client_id = ?");
|
||||
$stmt->execute([$_GET['client_id']]);
|
||||
$stmt = $pdo->prepare("SELECT * FROM clients WHERE client_id = ? AND user_id = ?");
|
||||
$stmt->execute([$_GET['client_id'], $_SESSION['user_id']]);
|
||||
$viewingClient = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$credentials = [];
|
||||
@ -35,7 +35,8 @@ if (isset($_GET['client_id'])) {
|
||||
$notes = $noteStmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
} else {
|
||||
$stmt = $pdo->query("SELECT * FROM clients ORDER BY name ASC");
|
||||
$stmt = $pdo->prepare("SELECT * FROM clients WHERE user_id = ? ORDER BY name ASC");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$clients = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
@ -55,7 +56,7 @@ if (isset($_GET['client_id'])) {
|
||||
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="dashboard.php">
|
||||
<i class="bi bi-shield-lock"></i> FlexPass
|
||||
<i class="bi bi-shield-lock"></i> ClientManager
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
@ -63,7 +64,7 @@ if (isset($_GET['client_id'])) {
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="dashboard.php">Clients</a>
|
||||
<a class="nav-link active" aria-current="page" href="dashboard.php">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="audit-log.php">Audit Log</a>
|
||||
@ -254,7 +255,9 @@ if (isset($_GET['client_id'])) {
|
||||
<td><?php echo htmlspecialchars($client['name']); ?></td>
|
||||
<td><span class="badge bg-<?php echo $client['status'] === 'active' ? 'success' : 'danger'; ?>"><?php echo htmlspecialchars($client['status']); ?></span></td>
|
||||
<td>
|
||||
<a href="?client_id=<?php echo htmlspecialchars($client['client_id']); ?>" class="btn btn-sm btn-outline-primary">View</a>
|
||||
<a href="dashboard.php?client_id=<?php echo htmlspecialchars($client['client_id']); ?>" class="btn btn-sm btn-outline-primary">View</a>
|
||||
<a href="edit-client.php?client_id=<?php echo htmlspecialchars($client['client_id']); ?>" class="btn btn-sm btn-outline-secondary">Edit</a>
|
||||
<a href="delete-client.php?client_id=<?php echo htmlspecialchars($client['client_id']); ?>" class="btn btn-sm btn-outline-danger">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
||||
@ -4,25 +4,55 @@ require_once __DIR__ . '/config.php';
|
||||
function run_migrations() {
|
||||
$pdo = db();
|
||||
$migrationsDir = __DIR__ . '/migrations';
|
||||
$files = glob($migrationsDir . '/*.sql');
|
||||
sort($files);
|
||||
|
||||
foreach ($files as $file) {
|
||||
echo "Running migration: " . basename($file) . "...\n";
|
||||
$sql = file_get_contents($file);
|
||||
if ($sql === false) {
|
||||
echo "Error: Could not read file " . basename($file) . ".\n";
|
||||
// 1. Create migrations table if it doesn't exist
|
||||
try {
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS `migrations` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`migration` VARCHAR(255) NOT NULL,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;");
|
||||
} catch (PDOException $e) {
|
||||
echo "Error creating migrations table: " . $e->getMessage() . "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Get all migration files and executed migrations
|
||||
$migrationFiles = glob($migrationsDir . '/*.sql');
|
||||
sort($migrationFiles);
|
||||
|
||||
$stmt = $pdo->query("SELECT migration FROM migrations");
|
||||
$executedMigrations = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
// 3. Run migrations that have not been executed yet
|
||||
foreach ($migrationFiles as $file) {
|
||||
$migrationName = basename($file);
|
||||
if (in_array($migrationName, $executedMigrations)) {
|
||||
echo "Skipping already executed migration: {$migrationName}\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
echo "Running migration: {$migrationName}...\n";
|
||||
$sql = file_get_contents($file);
|
||||
if ($sql === false) {
|
||||
echo "Error: Could not read file {$migrationName}.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// DDL statements often have implicit commits, so transactions are not reliable.
|
||||
$pdo->exec($sql);
|
||||
$insertStmt = $pdo->prepare("INSERT INTO migrations (migration) VALUES (?)");
|
||||
$insertStmt->execute([$migrationName]);
|
||||
echo "Success.\n";
|
||||
} catch (PDOException $e) {
|
||||
echo "Error executing migration " . basename($file) . ": " . $e->getMessage() . "\n";
|
||||
echo "Error executing migration {$migrationName}: " . $e->getMessage() . "\n";
|
||||
// Exit on first error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
echo "All new migrations have been executed.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
1
db/migrations/002_add_user_id_to_clients.sql
Normal file
1
db/migrations/002_add_user_id_to_clients.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE `clients` ADD COLUMN `user_id` CHAR(36) NULL AFTER `status`;
|
||||
2
db/migrations/003_make_user_id_not_null_in_clients.sql
Normal file
2
db/migrations/003_make_user_id_not_null_in_clients.sql
Normal file
@ -0,0 +1,2 @@
|
||||
ALTER TABLE `clients` MODIFY COLUMN `user_id` CHAR(36) NOT NULL;
|
||||
ALTER TABLE `clients` ADD CONSTRAINT `fk_clients_user_id` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE;
|
||||
37
db/temp_update_clients.php
Normal file
37
db/temp_update_clients.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// 1. Get the admin user's ID
|
||||
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
|
||||
$stmt->execute(['admin@flexpass.local']);
|
||||
$adminUser = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$adminUser) {
|
||||
echo "Admin user not found. Please seed the database first (php db/seed.php).\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$adminId = $adminUser['id'];
|
||||
echo "Found admin user ID: {$adminId}\n";
|
||||
|
||||
// 2. Update existing clients
|
||||
try {
|
||||
$updateStmt = $pdo->prepare("UPDATE clients SET user_id = ? WHERE user_id IS NULL OR user_id = ''");
|
||||
$updateStmt->execute([$adminId]);
|
||||
$rowCount = $updateStmt->rowCount();
|
||||
echo "Updated {$rowCount} client(s) to belong to the admin user.\n";
|
||||
} catch (PDOException $e) {
|
||||
// This will fail if the column doesn't exist yet, which is fine.
|
||||
echo "Could not update clients (the user_id column might not exist yet): " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 3. Modify the migration to be safer
|
||||
$migrationFile = __DIR__ . '/migrations/002_add_user_id_to_clients.sql';
|
||||
$migrationSQL = "ALTER TABLE `clients` ADD COLUMN `user_id` CHAR(36);"; // Add as nullable first
|
||||
|
||||
file_put_contents($migrationFile, $migrationSQL);
|
||||
echo "Migration 002 updated to be safer.\n";
|
||||
|
||||
?>
|
||||
127
delete-client.php
Normal file
127
delete-client.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
require_once __DIR__ . '/includes/audit.php';
|
||||
|
||||
// If user is not logged in, redirect to login page
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$displayName = $_SESSION['user_display_name'] ?? 'User';
|
||||
$clientId = $_GET['client_id'] ?? null;
|
||||
$client = null;
|
||||
$error = '';
|
||||
|
||||
if (!$clientId) {
|
||||
header('Location: dashboard.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Fetch client data to display its name in the confirmation message
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT name FROM clients WHERE client_id = ? AND user_id = ?");
|
||||
$stmt->execute([$clientId, $_SESSION['user_id']]);
|
||||
$client = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$client) {
|
||||
// If client not found or doesn't belong to the user, redirect.
|
||||
header('Location: dashboard.php');
|
||||
exit;
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$error = "Error fetching client data: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// Check for confirmation
|
||||
if (isset($_POST['confirm_delete'])) {
|
||||
try {
|
||||
// The ON DELETE CASCADE constraint will handle associated credentials and notes.
|
||||
$stmt = $pdo->prepare("DELETE FROM clients WHERE client_id = ? AND user_id = ?");
|
||||
$stmt->execute([$clientId, $_SESSION['user_id']]);
|
||||
|
||||
log_audit_event('client_delete', $_SESSION['user_id'], "Client '{$client['name']}' (ID: {$clientId}) and all associated data deleted.");
|
||||
|
||||
// Using session to pass success message
|
||||
$_SESSION['success_message'] = "Client '" . htmlspecialchars($client['name']) . "' and all associated data have been deleted.";
|
||||
header('Location: dashboard.php?status=client_deleted');
|
||||
exit;
|
||||
} catch (PDOException $e) {
|
||||
$error = "Error deleting client: " . $e->getMessage();
|
||||
}
|
||||
} else {
|
||||
// If not confirmed, just redirect
|
||||
header('Location: dashboard.php?client_id=' . $clientId);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Delete Client - ClientManager</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="dashboard.php">ClientManager</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 me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="dashboard.php">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="audit-log.php">Audit Log</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-person-circle"></i> <?php echo htmlspecialchars($displayName); ?>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
<li><a class="dropdown-item" href="logout.php">Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-4">
|
||||
<h2>Delete Client</h2>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($client): ?>
|
||||
<div class="alert alert-warning">
|
||||
<h4>Are you sure?</h4>
|
||||
<p>This action will permanently delete the client <strong><?php echo htmlspecialchars($client['name']); ?></strong> and all of their associated credentials and notes. This cannot be undone.</p>
|
||||
</div>
|
||||
<form action="delete-client.php?client_id=<?php echo htmlspecialchars($clientId); ?>" method="post">
|
||||
<button type="submit" name="confirm_delete" class="btn btn-danger">Yes, Delete Everything</button>
|
||||
<a href="dashboard.php?client_id=<?php echo htmlspecialchars($clientId); ?>" class="btn btn-secondary">Cancel</a>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-info">Client not found or you do not have permission to delete it.</div>
|
||||
<a href="dashboard.php" class="btn btn-primary">Back to Dashboard</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -9,34 +9,92 @@ if (!isset($_SESSION['user_id'])) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check if credential_id is provided
|
||||
if (!isset($_GET['credential_id'])) {
|
||||
$displayName = $_SESSION['user_display_name'] ?? 'User';
|
||||
$credentialId = $_GET['credential_id'] ?? null;
|
||||
$credential = null;
|
||||
$error = '';
|
||||
|
||||
if (!$credentialId) {
|
||||
header('Location: dashboard.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
$credential_id = $_GET['credential_id'];
|
||||
|
||||
// Fetch the client_id for redirecting back
|
||||
$stmt = $pdo->prepare("SELECT client_id FROM credentials WHERE credential_id = ?");
|
||||
$stmt->execute([$credential_id]);
|
||||
// Fetch credential data to display its name and ensure it belongs to the user.
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT c.credential_id, c.name, c.client_id FROM credentials c " .
|
||||
"JOIN clients cl ON c.client_id = cl.client_id " .
|
||||
"WHERE c.credential_id = ? AND cl.user_id = ?"
|
||||
);
|
||||
$stmt->execute([$credentialId, $_SESSION['user_id']]);
|
||||
$credential = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($credential) {
|
||||
$client_id = $credential['client_id'];
|
||||
|
||||
log_audit_event('credential_delete', $_SESSION['user_id'], 'credential', $credential_id);
|
||||
|
||||
// Delete the credential
|
||||
$deleteStmt = $pdo->prepare("DELETE FROM credentials WHERE credential_id = ?");
|
||||
$deleteStmt->execute([$credential_id]);
|
||||
|
||||
// Redirect back to the client detail page with a success message
|
||||
header("Location: dashboard.php?client_id=$client_id&status=credential_deleted");
|
||||
exit;
|
||||
} else {
|
||||
// Credential not found, just redirect
|
||||
if (!$credential) {
|
||||
// If credential not found or doesn't belong to the user, redirect.
|
||||
header('Location: dashboard.php');
|
||||
exit;
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$error = "Error fetching credential data: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['confirm_delete'])) {
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM credentials WHERE credential_id = ?");
|
||||
$stmt->execute([$credentialId]);
|
||||
|
||||
log_audit_event('credential_delete', $_SESSION['user_id'], "Credential '{$credential['name']}' (ID: {$credentialId}) deleted.");
|
||||
|
||||
header('Location: dashboard.php?client_id=' . $credential['client_id'] . '&status=credential_deleted');
|
||||
exit;
|
||||
} catch (PDOException $e) {
|
||||
$error = "Error deleting credential: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Delete Credential - ClientManager</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="dashboard.php">ClientManager</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-4">
|
||||
<h2>Delete Credential</h2>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($credential): ?>
|
||||
<div class="alert alert-warning">
|
||||
<h4>Are you sure?</h4>
|
||||
<p>This action will permanently delete the credential <strong><?php echo htmlspecialchars($credential['name']); ?></strong>.</p>
|
||||
</div>
|
||||
<form action="delete-credential.php?credential_id=<?php echo htmlspecialchars($credentialId); ?>" method="post">
|
||||
<button type="submit" name="confirm_delete" class="btn btn-danger">Yes, Delete</button>
|
||||
<a href="dashboard.php?client_id=<?php echo htmlspecialchars($credential['client_id']); ?>" class="btn btn-secondary">Cancel</a>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-info">Credential not found or you do not have permission to delete it.</div>
|
||||
<a href="dashboard.php" class="btn btn-primary">Back to Dashboard</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -5,25 +5,33 @@ require_once __DIR__ . '/includes/audit.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid request method.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// If user is not logged in, return error
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
echo json_encode(['success' => false, 'message' => 'User not logged in.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$noteId = $_GET['note_id'] ?? null;
|
||||
$noteId = $_POST['note_id'] ?? null;
|
||||
|
||||
if ($noteId) {
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// First, get the client_id for redirection
|
||||
$stmt = $pdo->prepare("SELECT client_id FROM notes WHERE note_id = ?");
|
||||
$stmt->execute([$noteId]);
|
||||
// Verify that the note belongs to a client of the logged-in user
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT n.note_id FROM notes n " .
|
||||
"JOIN clients c ON n.client_id = c.client_id " .
|
||||
"WHERE n.note_id = ? AND c.user_id = ?"
|
||||
);
|
||||
$stmt->execute([$noteId, $_SESSION['user_id']]);
|
||||
$note = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$clientId = $note['client_id'] ?? null;
|
||||
|
||||
if ($clientId) {
|
||||
if ($note) {
|
||||
log_audit_event('note_delete', $_SESSION['user_id'], 'note', $noteId);
|
||||
|
||||
// Now, delete the note
|
||||
@ -33,17 +41,16 @@ if ($noteId) {
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
} else {
|
||||
// Note not found or no client_id associated
|
||||
echo json_encode(['success' => false, 'message' => 'Note not found.']);
|
||||
echo json_encode(['success' => false, 'message' => 'Note not found or you do not have permission to delete it.']);
|
||||
exit;
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
// Optional: Log error
|
||||
error_log("Error deleting note: " . $e->getMessage());
|
||||
echo json_encode(['success' => false, 'message' => 'Database error.']);
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
// Redirect if note_id is missing
|
||||
echo json_encode(['success' => false, 'message' => 'Note ID is required.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
140
edit-client.php
Normal file
140
edit-client.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
require_once __DIR__ . '/includes/audit.php';
|
||||
|
||||
// If user is not logged in, redirect to login page
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$displayName = $_SESSION['user_display_name'] ?? 'User';
|
||||
$clientId = $_GET['client_id'] ?? null;
|
||||
$client = null;
|
||||
$errors = [];
|
||||
|
||||
if (!$clientId) {
|
||||
header('Location: dashboard.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Fetch client data
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT * FROM clients WHERE client_id = ? AND user_id = ?");
|
||||
$stmt->execute([$clientId, $_SESSION['user_id']]);
|
||||
$client = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$client) {
|
||||
// If client not found or doesn't belong to the user, redirect.
|
||||
header('Location: dashboard.php');
|
||||
exit;
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$errors[] = "Error fetching client data: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$status = trim($_POST['status'] ?? '');
|
||||
|
||||
if (empty($name)) {
|
||||
$errors[] = 'Client name is required.';
|
||||
}
|
||||
if (!in_array($status, ['active', 'inactive'])) {
|
||||
$errors[] = 'Invalid status value.';
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE clients SET name = ?, status = ? WHERE client_id = ? AND user_id = ?");
|
||||
$stmt->execute([$name, $status, $clientId, $_SESSION['user_id']]);
|
||||
log_audit_event('client_edit', $_SESSION['user_id'], "Client '{$name}' (ID: {$clientId}) updated.");
|
||||
header('Location: dashboard.php?client_id=' . $clientId . '&status=client_updated');
|
||||
exit;
|
||||
} catch (PDOException $e) {
|
||||
$errors[] = "Error updating client: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Edit Client - ClientManager</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="dashboard.php">ClientManager</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 me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="dashboard.php">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="audit-log.php">Audit Log</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-person-circle"></i> <?php echo htmlspecialchars($displayName); ?>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
<li><a class="dropdown-item" href="logout.php">Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-4">
|
||||
<h2>Edit Client</h2>
|
||||
|
||||
<?php if (!empty($errors)): ?>
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<li><?php echo htmlspecialchars($error); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($client): ?>
|
||||
<form action="edit-client.php?client_id=<?php echo htmlspecialchars($clientId); ?>" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($client['name']); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="status" class="form-label">Status</label>
|
||||
<select class="form-select" id="status" name="status">
|
||||
<option value="active" <?php echo ($client['status'] === 'active') ? 'selected' : ''; ?>>Active</option>
|
||||
<option value="inactive" <?php echo ($client['status'] === 'inactive') ? 'selected' : ''; ?>>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||
<a href="dashboard.php?client_id=<?php echo htmlspecialchars($clientId); ?>" class="btn btn-secondary">Cancel</a>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<p>Client not found or you do not have permission to view it.</p>
|
||||
<a href="dashboard.php" class="btn btn-primary">Back to Dashboard</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user