ServerManager project files
This commit is contained in:
75
src/Models/CommandHistory.php
Executable file
75
src/Models/CommandHistory.php
Executable file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ServerManager\Models;
|
||||
|
||||
use ServerManager\Core\Database;
|
||||
|
||||
class CommandHistory
|
||||
{
|
||||
private Database $db;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
}
|
||||
|
||||
public function log(int $serverId, int $userId, string $command, ?string $output, int $exitStatus): int
|
||||
{
|
||||
return $this->db->insert('command_history', [
|
||||
'server_id' => $serverId,
|
||||
'user_id' => $userId,
|
||||
'command' => $command,
|
||||
'output' => mb_substr($output ?? '', 0, 65535),
|
||||
'exit_status' => $exitStatus,
|
||||
'executed_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getByServer(int $serverId, int $limit = 50): array
|
||||
{
|
||||
return $this->db->fetchAll(
|
||||
'SELECT ch.*, u.username
|
||||
FROM command_history ch
|
||||
LEFT JOIN users u ON ch.user_id = u.id
|
||||
WHERE ch.server_id = ?
|
||||
ORDER BY ch.executed_at DESC
|
||||
LIMIT ?',
|
||||
[$serverId, $limit]
|
||||
);
|
||||
}
|
||||
|
||||
public function getRecent(int $limit = 10): array
|
||||
{
|
||||
return $this->db->fetchAll(
|
||||
'SELECT ch.*, u.username, s.name as server_name
|
||||
FROM command_history ch
|
||||
LEFT JOIN users u ON ch.user_id = u.id
|
||||
LEFT JOIN servers s ON ch.server_id = s.id
|
||||
ORDER BY ch.executed_at DESC
|
||||
LIMIT ?',
|
||||
[$limit]
|
||||
);
|
||||
}
|
||||
|
||||
public function getById(int $id): ?array
|
||||
{
|
||||
return $this->db->fetch(
|
||||
'SELECT ch.*, u.username, s.name as server_name
|
||||
FROM command_history ch
|
||||
LEFT JOIN users u ON ch.user_id = u.id
|
||||
LEFT JOIN servers s ON ch.server_id = s.id
|
||||
WHERE ch.id = ?',
|
||||
[$id]
|
||||
);
|
||||
}
|
||||
|
||||
public function clearHistory(int $serverId = null): int
|
||||
{
|
||||
if ($serverId) {
|
||||
return $this->db->delete('command_history', 'server_id = ?', [$serverId]);
|
||||
}
|
||||
return $this->db->delete('command_history', '1=1');
|
||||
}
|
||||
}
|
||||
189
src/Models/Server.php
Executable file
189
src/Models/Server.php
Executable file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ServerManager\Models;
|
||||
|
||||
use ServerManager\Core\Database;
|
||||
use ServerManager\Core\App;
|
||||
use ServerManager\Core\Encryption;
|
||||
|
||||
class Server
|
||||
{
|
||||
private Database $db;
|
||||
private Encryption $encryption;
|
||||
private array $encryptedFields = ['ssh_password', 'ssh_key'];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->encryption = App::getEncryption();
|
||||
}
|
||||
|
||||
public function findById(int $id): ?array
|
||||
{
|
||||
$server = $this->db->fetch('SELECT * FROM servers WHERE id = ?', [$id]);
|
||||
if ($server) {
|
||||
$server = $this->encryption->decryptArray($server, $this->encryptedFields);
|
||||
}
|
||||
return $server;
|
||||
}
|
||||
|
||||
public function findAll(bool $activeOnly = false): array
|
||||
{
|
||||
$sql = 'SELECT * FROM servers';
|
||||
$params = [];
|
||||
|
||||
if ($activeOnly) {
|
||||
$sql .= ' WHERE is_active = 1';
|
||||
}
|
||||
|
||||
$sql .= ' ORDER BY name ASC';
|
||||
$servers = $this->db->fetchAll($sql, $params);
|
||||
|
||||
return array_map(function ($server) {
|
||||
return $this->encryption->decryptArray($server, $this->encryptedFields);
|
||||
}, $servers);
|
||||
}
|
||||
|
||||
public function getAll(int $page = 1, int $perPage = 20, array $filters = []): array
|
||||
{
|
||||
$where = [];
|
||||
$params = [];
|
||||
|
||||
if (!empty($filters['search'])) {
|
||||
$where[] = '(s.name LIKE ? OR s.ip_address LIKE ? OR s.description LIKE ?)';
|
||||
$search = '%' . $filters['search'] . '%';
|
||||
$params[] = $search;
|
||||
$params[] = $search;
|
||||
$params[] = $search;
|
||||
}
|
||||
|
||||
if (isset($filters['is_active']) && $filters['is_active'] !== '') {
|
||||
$where[] = 's.is_active = ?';
|
||||
$params[] = (int) $filters['is_active'];
|
||||
}
|
||||
|
||||
if (!empty($filters['group_name'])) {
|
||||
$where[] = 's.group_name = ?';
|
||||
$params[] = $filters['group_name'];
|
||||
}
|
||||
|
||||
if (!empty($filters['status'])) {
|
||||
$where[] = 's.current_status = ?';
|
||||
$params[] = $filters['status'];
|
||||
}
|
||||
|
||||
$whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$total = $this->db->fetch(
|
||||
"SELECT COUNT(*) as total FROM servers s {$whereClause}",
|
||||
$params
|
||||
);
|
||||
|
||||
$servers = $this->db->fetchAll(
|
||||
"SELECT s.* FROM servers s {$whereClause} ORDER BY s.name ASC LIMIT ? OFFSET ?",
|
||||
array_merge($params, [$perPage, $offset])
|
||||
);
|
||||
|
||||
$servers = array_map(function ($server) {
|
||||
return $this->encryption->decryptArray($server, $this->encryptedFields);
|
||||
}, $servers);
|
||||
|
||||
return [
|
||||
'data' => $servers,
|
||||
'total' => (int) ($total['total'] ?? 0),
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'total_pages' => ceil((int) ($total['total'] ?? 0) / $perPage),
|
||||
];
|
||||
}
|
||||
|
||||
public function create(array $data): int
|
||||
{
|
||||
if (!empty($data['ssh_password'])) {
|
||||
$data['ssh_password'] = $this->encryption->encrypt($data['ssh_password']);
|
||||
} else {
|
||||
$data['ssh_password'] = null;
|
||||
}
|
||||
|
||||
if (!empty($data['ssh_key'])) {
|
||||
$data['ssh_key'] = $this->encryption->encrypt($data['ssh_key']);
|
||||
} else {
|
||||
$data['ssh_key'] = null;
|
||||
}
|
||||
|
||||
$data['created_at'] = date('Y-m-d H:i:s');
|
||||
$data['updated_at'] = date('Y-m-d H:i:s');
|
||||
|
||||
if (empty($data['current_status'])) {
|
||||
$data['current_status'] = 'unknown';
|
||||
}
|
||||
|
||||
return $this->db->insert('servers', $data);
|
||||
}
|
||||
|
||||
public function update(int $id, array $data): bool
|
||||
{
|
||||
if (array_key_exists('ssh_password', $data)) {
|
||||
if (!empty($data['ssh_password'])) {
|
||||
$data['ssh_password'] = $this->encryption->encrypt($data['ssh_password']);
|
||||
} else {
|
||||
unset($data['ssh_password']);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('ssh_key', $data)) {
|
||||
if (!empty($data['ssh_key'])) {
|
||||
$data['ssh_key'] = $this->encryption->encrypt($data['ssh_key']);
|
||||
} else {
|
||||
unset($data['ssh_key']);
|
||||
}
|
||||
}
|
||||
|
||||
$data['updated_at'] = date('Y-m-d H:i:s');
|
||||
|
||||
return $this->db->update('servers', $data, 'id = ?', [$id]) > 0;
|
||||
}
|
||||
|
||||
public function delete(int $id): bool
|
||||
{
|
||||
return $this->db->delete('servers', 'id = ?', [$id]) > 0;
|
||||
}
|
||||
|
||||
public function toggleActive(int $id): ?bool
|
||||
{
|
||||
$server = $this->db->fetch('SELECT is_active FROM servers WHERE id = ?', [$id]);
|
||||
if (!$server) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$newState = $server['is_active'] ? 0 : 1;
|
||||
$this->db->update('servers', ['is_active' => $newState, 'updated_at' => date('Y-m-d H:i:s')], 'id = ?', [$id]);
|
||||
|
||||
return (bool) $newState;
|
||||
}
|
||||
|
||||
public function getGroups(): array
|
||||
{
|
||||
$groups = $this->db->fetchAll(
|
||||
'SELECT DISTINCT group_name FROM servers WHERE group_name IS NOT NULL AND group_name != "" ORDER BY group_name'
|
||||
);
|
||||
return array_column($groups, 'group_name');
|
||||
}
|
||||
|
||||
public function countAll(): int
|
||||
{
|
||||
$result = $this->db->fetch("SELECT COUNT(*) as total FROM servers");
|
||||
return (int) ($result['total'] ?? 0);
|
||||
}
|
||||
|
||||
public function countOnline(): int
|
||||
{
|
||||
$result = $this->db->fetch(
|
||||
"SELECT COUNT(*) as total FROM servers WHERE current_status = 'online' AND is_active = 1"
|
||||
);
|
||||
return (int) ($result['total'] ?? 0);
|
||||
}
|
||||
}
|
||||
124
src/Models/User.php
Executable file
124
src/Models/User.php
Executable file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ServerManager\Models;
|
||||
|
||||
use ServerManager\Core\Database;
|
||||
use ServerManager\Core\Security;
|
||||
|
||||
class User
|
||||
{
|
||||
private Database $db;
|
||||
private Security $security;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->security = new Security();
|
||||
}
|
||||
|
||||
public function findById(int $id): ?array
|
||||
{
|
||||
return $this->db->fetch('SELECT * FROM users WHERE id = ?', [$id]);
|
||||
}
|
||||
|
||||
public function findByUsername(string $username): ?array
|
||||
{
|
||||
return $this->db->fetch('SELECT * FROM users WHERE username = ?', [$username]);
|
||||
}
|
||||
|
||||
public function findByEmail(string $email): ?array
|
||||
{
|
||||
return $this->db->fetch('SELECT * FROM users WHERE email = ?', [$email]);
|
||||
}
|
||||
|
||||
public function authenticate(string $username, string $password): ?array
|
||||
{
|
||||
$user = $this->findByUsername($username);
|
||||
|
||||
if (!$user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$user['is_active']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$this->security->verifyPassword($password, $user['password_hash'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->updateLastLogin($user['id']);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function create(array $data): int
|
||||
{
|
||||
$data['password_hash'] = $this->security->hashPassword($data['password']);
|
||||
unset($data['password']);
|
||||
|
||||
$data['created_at'] = date('Y-m-d H:i:s');
|
||||
$data['updated_at'] = date('Y-m-d H:i:s');
|
||||
|
||||
if (empty($data['api_token'])) {
|
||||
$data['api_token'] = $this->security->generateApiToken();
|
||||
}
|
||||
|
||||
return $this->db->insert('users', $data);
|
||||
}
|
||||
|
||||
public function update(int $id, array $data): bool
|
||||
{
|
||||
if (isset($data['password'])) {
|
||||
$data['password_hash'] = $this->security->hashPassword($data['password']);
|
||||
unset($data['password']);
|
||||
}
|
||||
|
||||
$data['updated_at'] = date('Y-m-d H:i:s');
|
||||
|
||||
return $this->db->update('users', $data, 'id = ?', [$id]) > 0;
|
||||
}
|
||||
|
||||
public function delete(int $id): bool
|
||||
{
|
||||
return $this->db->delete('users', 'id = ?', [$id]) > 0;
|
||||
}
|
||||
|
||||
public function getAll(int $page = 1, int $perPage = 20): array
|
||||
{
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$total = $this->db->fetch("SELECT COUNT(*) as total FROM users");
|
||||
$users = $this->db->fetchAll(
|
||||
'SELECT id, username, email, role, is_active, last_login_at, created_at
|
||||
FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?',
|
||||
[$perPage, $offset]
|
||||
);
|
||||
|
||||
return [
|
||||
'data' => $users,
|
||||
'total' => (int) ($total['total'] ?? 0),
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'total_pages' => ceil((int) ($total['total'] ?? 0) / $perPage),
|
||||
];
|
||||
}
|
||||
|
||||
public function findByApiToken(string $token): ?array
|
||||
{
|
||||
return $this->db->fetch('SELECT * FROM users WHERE api_token = ? AND is_active = 1', [$token]);
|
||||
}
|
||||
|
||||
public function updateLastLogin(int $id): void
|
||||
{
|
||||
$this->db->update('users', ['last_login_at' => date('Y-m-d H:i:s')], 'id = ?', [$id]);
|
||||
}
|
||||
|
||||
public function countAll(): int
|
||||
{
|
||||
$result = $this->db->fetch("SELECT COUNT(*) as total FROM users");
|
||||
return (int) ($result['total'] ?? 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user