Initial commit of the Asset Management System, including project structure, Docker configuration, database migrations, and core application files. Added user authentication, asset management features, and basic UI components.

This commit is contained in:
2025-08-22 21:41:02 +02:00
parent b43a98f0ec
commit 677f70a19c
52 changed files with 5186 additions and 2 deletions

204
app/Models/User.php Normal file
View File

@@ -0,0 +1,204 @@
<?php
namespace App\Models;
use App\Core\Database;
class User
{
private Database $database;
public function __construct(Database $database)
{
$this->database = $database;
}
public function find(int $id): ?array
{
return $this->database->fetch(
"SELECT * FROM users WHERE id = :id",
['id' => $id]
);
}
public function findByEmail(string $email): ?array
{
return $this->database->fetch(
"SELECT * FROM users WHERE email = :email",
['email' => $email]
);
}
public function findAll(array $filters = [], int $limit = null, int $offset = 0): array
{
$sql = "SELECT * FROM users WHERE 1=1";
$params = [];
if (!empty($filters['role'])) {
$sql .= " AND role = :role";
$params['role'] = $filters['role'];
}
if (isset($filters['active'])) {
$sql .= " AND active = :active";
$params['active'] = $filters['active'];
}
if (!empty($filters['search'])) {
$sql .= " AND (name LIKE :search OR email LIKE :search)";
$params['search'] = '%' . $filters['search'] . '%';
}
$sql .= " ORDER BY name ASC";
if ($limit) {
$sql .= " LIMIT :limit OFFSET :offset";
$params['limit'] = $limit;
$params['offset'] = $offset;
}
return $this->database->fetchAll($sql, $params);
}
public function create(array $data): int
{
$data['passhash'] = password_hash($data['password'], PASSWORD_ARGON2ID);
unset($data['password']);
$data['created_at'] = date('Y-m-d H:i:s');
$data['updated_at'] = date('Y-m-d H:i:s');
return $this->database->insert('users', $data);
}
public function update(int $id, array $data): bool
{
if (isset($data['password']) && !empty($data['password'])) {
$data['passhash'] = password_hash($data['password'], PASSWORD_ARGON2ID);
unset($data['password']);
}
$data['updated_at'] = date('Y-m-d H:i:s');
return $this->database->update('users', $data, 'id = :id', ['id' => $id]) > 0;
}
public function delete(int $id): bool
{
return $this->database->delete('users', 'id = :id', ['id' => $id]) > 0;
}
public function toggleStatus(int $id): bool
{
$user = $this->find($id);
if (!$user) {
return false;
}
$newStatus = !$user['active'];
return $this->update($id, ['active' => $newStatus]);
}
public function count(array $filters = []): int
{
$sql = "SELECT COUNT(*) as total FROM users WHERE 1=1";
$params = [];
if (!empty($filters['role'])) {
$sql .= " AND role = :role";
$params['role'] = $filters['role'];
}
if (isset($filters['active'])) {
$sql .= " AND active = :active";
$params['active'] = $filters['active'];
}
$result = $this->database->fetch($sql, $params);
return $result['total'] ?? 0;
}
public function getActiveUsers(): array
{
return $this->findAll(['active' => true]);
}
public function getUsersByRole(string $role): array
{
return $this->findAll(['role' => $role]);
}
public function searchUsers(string $search): array
{
return $this->findAll(['search' => $search]);
}
public function updateLastLogin(int $id): bool
{
return $this->update($id, ['last_login' => date('Y-m-d H:i:s')]);
}
public function changePassword(int $id, string $newPassword): bool
{
return $this->update($id, ['password' => $newPassword]);
}
public function getUsersWithStats(): array
{
$sql = "SELECT
u.*,
COUNT(DISTINCT a.id) as asset_count,
COUNT(DISTINCT al.id) as audit_count
FROM users u
LEFT JOIN assets a ON u.id = a.created_by
LEFT JOIN audit_log al ON u.id = al.user_id
GROUP BY u.id
ORDER BY u.name ASC";
return $this->database->fetchAll($sql);
}
public function getRecentActivity(int $userId, int $limit = 10): array
{
$sql = "SELECT al.*, a.inventarnummer, a.bezeichnung
FROM audit_log al
LEFT JOIN assets a ON al.table_name = 'assets' AND al.record_id = a.id
WHERE al.user_id = :user_id
ORDER BY al.created_at DESC
LIMIT :limit";
return $this->database->fetchAll($sql, [
'user_id' => $userId,
'limit' => $limit
]);
}
public function validateEmail(string $email, int $excludeId = null): bool
{
$sql = "SELECT COUNT(*) as total FROM users WHERE email = :email";
$params = ['email' => $email];
if ($excludeId) {
$sql .= " AND id != :exclude_id";
$params['exclude_id'] = $excludeId;
}
$result = $this->database->fetch($sql, $params);
return ($result['total'] ?? 0) === 0;
}
public function getRoles(): array
{
return [
'admin' => 'Administrator',
'auditor' => 'Auditor',
'employee' => 'Mitarbeiter'
];
}
public function getRoleName(string $role): string
{
$roles = $this->getRoles();
return $roles[$role] ?? $role;
}
}