correzione login

This commit is contained in:
Flatlogic Bot 2025-11-05 22:50:07 +00:00
parent 5f68d7fe5b
commit f4d677bb9d
6 changed files with 213 additions and 34 deletions

View File

@ -9,7 +9,7 @@ if (!can($_SESSION['user_role'], 'asset', 'create')) {
}
$allowed_fields_str = can($_SESSION['user_role'], 'asset', 'create');
$allowed_fields = ($allowed_fields_str === '*') ? ['name', 'asset_tag', 'status', 'location', 'manufacturer', 'model', 'purchase_date'] : explode(',', $allowed_fields_str);
$allowed_fields = ($allowed_fields_str === '*') ? ['name', 'status', 'location', 'manufacturer', 'model', 'purchase_date'] : explode(',', $allowed_fields_str);
$success_message = '';
$error_message = '';
@ -19,28 +19,52 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$placeholders = [];
$columns = [];
foreach ($allowed_fields as $field) {
if (isset($_POST[$field])) {
$data[] = $_POST[$field];
$columns[] = $field;
$placeholders[] = '?';
// Generate new asset tag
try {
$pdo = db();
$stmt = $pdo->query("SELECT asset_tag FROM assets WHERE asset_tag LIKE 'ASSET-%' ORDER BY CAST(SUBSTRING(asset_tag, 7) AS UNSIGNED) DESC LIMIT 1");
$last_asset_tag = $stmt->fetchColumn();
if ($last_asset_tag) {
$last_number = (int) substr($last_asset_tag, 6);
$new_number = $last_number + 1;
} else {
$new_number = 1;
}
$new_asset_tag = 'ASSET-' . str_pad($new_number, 3, '0', STR_PAD_LEFT);
$data = [$new_asset_tag];
$columns = ['asset_tag'];
$placeholders = '?';
} catch (PDOException $e) {
$error_message = 'Error generating asset tag: ' . $e->getMessage();
}
if (empty($data)) {
$error_message = 'No data submitted.';
} else {
try {
$pdo = db();
$sql = sprintf("INSERT INTO assets (%s) VALUES (%s)", implode(', ', $columns), implode(', ', $placeholders));
$stmt = $pdo->prepare($sql);
$stmt->execute($data);
if (empty($error_message)) {
foreach ($allowed_fields as $field) {
if (isset($_POST[$field])) {
$data[] = $_POST[$field];
$columns[] = $field;
$placeholders[] = '?';
}
}
header("Location: index.php?success=asset_added");
exit;
if (count($data) <= 1) { // Only asset tag is present
$error_message = 'No data submitted.';
} else {
try {
$sql = sprintf("INSERT INTO assets (%s) VALUES (%s)", implode(', ', $columns), implode(', ', array_fill(0, count($columns), '?')));
$stmt = $pdo->prepare($sql);
$stmt->execute($data);
} catch (PDOException $e) {
$error_message = 'Database error: ' . $e->getMessage();
header("Location: index.php?success=asset_added");
exit;
} catch (PDOException $e) {
$error_message = 'Database error: ' . $e->getMessage();
}
}
}
}
@ -85,12 +109,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<input type="text" class="form-control" id="name" name="name" required>
</div>
<?php endif; ?>
<?php if (in_array('asset_tag', $allowed_fields)): ?>
<div class="col-md-6 mb-3">
<label for="asset_tag" class="form-label">Asset Tag*</label>
<input type="text" class="form-control" id="asset_tag" name="asset_tag" required>
</div>
<?php endif; ?>
</div>
<div class="row">
<?php if (in_array('status', $allowed_fields)): ?>

View File

@ -0,0 +1,5 @@
CREATE TABLE IF NOT EXISTS `categories` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL UNIQUE,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB;

View File

@ -0,0 +1,2 @@
ALTER TABLE `assets` ADD COLUMN `category_id` INT NULL AFTER `status`;
ALTER TABLE `assets` ADD FOREIGN KEY (`category_id`) REFERENCES `categories`(`id`) ON DELETE SET NULL;

143
index.php
View File

@ -7,8 +7,38 @@ require_once 'auth-helpers.php';
$allowed_fields_str = can($_SESSION['user_role'], 'asset', 'read');
$allowed_fields = $allowed_fields_str ? explode(',', $allowed_fields_str) : [];
// Function to count total assets
function count_assets($search = '', $status = '') {
$sql = "SELECT COUNT(*) FROM assets";
$where = [];
$params = [];
if (!empty($search)) {
$where[] = "name LIKE :search";
$params[':search'] = "%$search%";
}
if (!empty($status)) {
$where[] = "status = :status";
$params[':status'] = $status;
}
if (!empty($where)) {
$sql .= " WHERE " . implode(' AND ', $where);
}
try {
$pdo = db();
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchColumn();
} catch (PDOException $e) {
return 0;
}
}
// Function to execute query and return results
function get_assets($fields) {
function get_assets($fields, $search = '', $status = '', $limit = 10, $offset = 0, $sort_by = 'created_at', $sort_order = 'DESC') {
if (empty($fields)) {
return []; // No read permission
}
@ -19,16 +49,70 @@ function get_assets($fields) {
$select_fields = implode(', ', $fields);
$sql = "SELECT $select_fields FROM assets";
$where = [];
$params = [];
if (!empty($search)) {
// Assuming 'name' is a field that can be searched.
if (in_array('name', $fields)) {
$where[] = "name LIKE :search";
$params[':search'] = "%$search%";
}
}
if (!empty($status)) {
if (in_array('status', $fields)) {
$where[] = "status = :status";
$params[':status'] = $status;
}
}
if (!empty($where)) {
$sql .= " WHERE " . implode(' AND ', $where);
}
// Whitelist sortable columns
$sortable_columns = array_merge($fields, ['created_at']);
if (!in_array($sort_by, $sortable_columns)) {
$sort_by = 'created_at';
}
$sort_order = strtoupper($sort_order) === 'ASC' ? 'ASC' : 'DESC';
$sql .= " ORDER BY $sort_by $sort_order LIMIT :limit OFFSET :offset";
$params[':limit'] = $limit;
$params[':offset'] = $offset;
try {
$pdo = db();
$stmt = $pdo->query("SELECT $select_fields FROM assets ORDER BY created_at DESC");
$stmt = $pdo->prepare($sql);
// Bind parameters separately to handle integer binding for LIMIT and OFFSET
foreach ($params as $key => &$val) {
if ($key === ':limit' || $key === ':offset') {
$stmt->bindParam($key, $val, PDO::PARAM_INT);
} else {
$stmt->bindParam($key, $val);
}
}
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
return ['error' => 'Database error: ' . $e->getMessage()];
}
}
$assets = get_assets($allowed_fields);
$search = $_GET['search'] ?? '';
$status = $_GET['status'] ?? '';
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$limit = 10;
$offset = ($page - 1) * $limit;
$sort_by = $_GET['sort_by'] ?? 'created_at';
$sort_order = $_GET['sort_order'] ?? 'DESC';
$total_assets = count_assets($search, $status);
$total_pages = ceil($total_assets / $limit);
$assets = get_assets($allowed_fields, $search, $status, $limit, $offset, $sort_by, $sort_order);
function getStatusClass($status) {
switch (strtolower($status)) {
@ -86,6 +170,23 @@ function getStatusClass($status) {
<?php endif; ?>
<div class="surface p-4">
<form method="get" class="row g-3 mb-4">
<div class="col-md-4">
<input type="text" name="search" class="form-control" placeholder="Search by asset name..." value="<?php echo htmlspecialchars($search); ?>">
</div>
<div class="col-md-3">
<select name="status" class="form-select">
<option value="">All Statuses</option>
<option value="In Service" <?php echo ($status === 'In Service') ? 'selected' : ''; ?>>In Service</option>
<option value="Under Repair" <?php echo ($status === 'Under Repair') ? 'selected' : ''; ?>>Under Repair</option>
<option value="Retired" <?php echo ($status === 'Retired') ? 'selected' : ''; ?>>Retired</option>
</select>
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-primary">Filter</button>
</div>
</form>
<?php if (isset($assets['error'])): ?>
<div class="alert alert-danger">
<?php echo htmlspecialchars($assets['error']); ?>
@ -93,7 +194,7 @@ function getStatusClass($status) {
<?php elseif (empty($assets)): ?>
<div class="text-center p-5">
<h4>No assets found.</h4>
<?php if (can($_SESSION['user_role'], 'asset', 'create'])): ?>
<?php if (can($_SESSION['user_role'], 'asset', 'create')): ?>
<p>Get started by adding your first company asset.</p>
<a href="add-asset.php" class="btn btn-primary">Add Asset</a>
<?php endif; ?>
@ -103,8 +204,18 @@ function getStatusClass($status) {
<table class="table asset-table">
<thead>
<tr>
<?php foreach ($allowed_fields as $field): if($field === 'id') continue; ?>
<th><?php echo ucfirst(str_replace('_', ' ', $field)); ?></th>
<?php
$new_sort_order = ($sort_order === 'DESC') ? 'ASC' : 'DESC';
foreach ($allowed_fields as $field): if($field === 'id') continue;
?>
<th>
<a href="?page=<?php echo $page; ?>&search=<?php echo urlencode($search); ?>&status=<?php echo urlencode($status); ?>&sort_by=<?php echo $field; ?>&sort_order=<?php echo $new_sort_order; ?>">
<?php echo ucfirst(str_replace('_', ' ', $field)); ?>
<?php if ($sort_by === $field): ?>
<i data-feather="<?php echo ($sort_order === 'DESC') ? 'arrow-down' : 'arrow-up'; ?>"></i>
<?php endif; ?>
</a>
</th>
<?php endforeach; ?>
<th>Actions</th>
</tr>
@ -117,7 +228,7 @@ function getStatusClass($status) {
<?php if ($field === 'status'): ?>
<span class="status <?php echo getStatusClass($asset[$field]); ?>"><?php echo htmlspecialchars($asset[$field]); ?></span>
<?php else: ?>
<?php echo htmlspecialchars($asset[$field]); ?>
<?php echo htmlspecialchars($asset[$field] ?? ''); ?>
<?php endif; ?>
</td>
<?php endforeach; ?>
@ -125,15 +236,31 @@ function getStatusClass($status) {
<?php if (can($_SESSION['user_role'], 'asset', 'update')): ?>
<a href="edit-asset.php?id=<?php echo $asset['id']; ?>" class="btn btn-sm btn-outline-primary">Edit</a>
<?php endif; ?>
<?php if (can($_SESSION['user_role'], 'asset', 'delete'])): ?>
<?php if (can($_SESSION['user_role'], 'asset', 'delete')): ?>
<?php if (can($_SESSION['user_role'], 'asset', 'delete')): ?>
<a href="delete-asset.php?id=<?php echo $asset['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Are you sure you want to delete this asset?');">Delete</a>
<?php endif; ?>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center">
<?php if ($page > 1): ?>
<li class="page-item"><a class="page-link" href="?page=<?php echo $page - 1; ?>&search=<?php echo urlencode($search); ?>&status=<?php echo urlencode($status); ?>&sort_by=<?php echo $sort_by; ?>&sort_order=<?php echo $sort_order; ?>">Previous</a></li>
<?php endif; ?>
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
<li class="page-item <?php echo ($i == $page) ? 'active' : ''; ?>"><a class="page-link" href="?page=<?php echo $i; ?>&search=<?php echo urlencode($search); ?>&status=<?php echo urlencode($status); ?>&sort_by=<?php echo $sort_by; ?>&sort_order=<?php echo $sort_order; ?>"><?php echo $i; ?></a></li>
<?php endfor; ?>
<?php if ($page < $total_pages): ?>
<li class="page-item"><a class="page-link" href="?page=<?php echo $page + 1; ?>&search=<?php echo urlencode($search); ?>&status=<?php echo urlencode($status); ?>&sort_by=<?php echo $sort_by; ?>&sort_order=<?php echo $sort_order; ?>">Next</a></li>
<?php endif; ?>
</ul>
</nav>
<?php endif; ?>
</div>
</main>

4
opcache_reset.php Normal file
View File

@ -0,0 +1,4 @@
<?php
opcache_reset();
echo "Opcode cache has been cleared.";
?>

23
run-migrations.php Normal file
View File

@ -0,0 +1,23 @@
<?php
require_once 'db/config.php';
// This script will run all migrations and then delete itself.
$pdo = db();
$migrations_dir = __DIR__ . '/db/migrations';
$files = glob($migrations_dir . '/*.sql');
foreach ($files as $file) {
$sql = file_get_contents($file);
try {
$pdo->exec($sql);
echo "Successfully ran migration: " . basename($file) . "<br>";
} catch (PDOException $e) {
echo "Error running migration: " . basename($file) . " - " . $e->getMessage() . "<br>";
}
}
// Self-destruct
unlink(__FILE__);
echo "<br>All migrations have been processed. This script has been deleted.";