Add server ownership, team access, role-based UI, and default admin role
- New migration 002_server_access.sql: created_by column + server_user table - Server model: ownership, permission checks, team management methods - Routes: /team routes, RoleMiddleware on /servers/create and /admin - ServerController: permission checks via server_user, team CRUD methods - TerminalController: server access checks - DashboardController: filter servers by accessible ones - ApiController: server access checks - Views: team.php, team_server.php, sidebar Team link, hide actions by role - Default user role changed from operator to admin on registration - Admin user form defaults to admin role
This commit is contained in:
@@ -7,6 +7,7 @@ namespace ServerManager\Models;
|
||||
use ServerManager\Core\Database;
|
||||
use ServerManager\Core\App;
|
||||
use ServerManager\Core\Encryption;
|
||||
use ServerManager\Core\Session;
|
||||
|
||||
class Server
|
||||
{
|
||||
@@ -74,6 +75,13 @@ class Server
|
||||
$params[] = $filters['status'];
|
||||
}
|
||||
|
||||
if (!empty($filters['accessible_ids'])) {
|
||||
$ids = array_map('intval', $filters['accessible_ids']);
|
||||
$placeholders = implode(',', array_fill(0, count($ids), '?'));
|
||||
$where[] = "s.id IN ({$placeholders})";
|
||||
$params = array_merge($params, $ids);
|
||||
}
|
||||
|
||||
$whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
@@ -121,6 +129,11 @@ class Server
|
||||
$data['current_status'] = 'unknown';
|
||||
}
|
||||
|
||||
$userId = Session::get('user_id');
|
||||
if ($userId && empty($data['created_by'])) {
|
||||
$data['created_by'] = $userId;
|
||||
}
|
||||
|
||||
return $this->db->insert('servers', $data);
|
||||
}
|
||||
|
||||
@@ -186,4 +199,155 @@ class Server
|
||||
);
|
||||
return (int) ($result['total'] ?? 0);
|
||||
}
|
||||
|
||||
public function getUserRole(int $serverId, int $userId): ?string
|
||||
{
|
||||
$server = $this->db->fetch('SELECT created_by FROM servers WHERE id = ?', [$serverId]);
|
||||
if (!$server) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((int) $server['created_by'] === $userId) {
|
||||
return 'owner';
|
||||
}
|
||||
|
||||
$assignment = $this->db->fetch(
|
||||
'SELECT role FROM server_user WHERE server_id = ? AND user_id = ?',
|
||||
[$serverId, $userId]
|
||||
);
|
||||
|
||||
return $assignment ? $assignment['role'] : null;
|
||||
}
|
||||
|
||||
public function getAccessibleServerIds(int $userId): array
|
||||
{
|
||||
$owned = $this->db->fetchAll(
|
||||
'SELECT id FROM servers WHERE created_by = ?',
|
||||
[$userId]
|
||||
);
|
||||
|
||||
$assigned = $this->db->fetchAll(
|
||||
'SELECT server_id FROM server_user WHERE user_id = ?',
|
||||
[$userId]
|
||||
);
|
||||
|
||||
$ids = [];
|
||||
foreach ($owned as $row) {
|
||||
$ids[] = (int) $row['id'];
|
||||
}
|
||||
foreach ($assigned as $row) {
|
||||
$ids[] = (int) $row['server_id'];
|
||||
}
|
||||
|
||||
return array_unique($ids);
|
||||
}
|
||||
|
||||
public function isOwner(int $serverId, int $userId): bool
|
||||
{
|
||||
$server = $this->db->fetch('SELECT created_by FROM servers WHERE id = ?', [$serverId]);
|
||||
return $server && (int) $server['created_by'] === $userId;
|
||||
}
|
||||
|
||||
public function canManage(int $serverId, int $userId): bool
|
||||
{
|
||||
$role = $this->getUserRole($serverId, $userId);
|
||||
return $role === 'owner' || $role === 'manager';
|
||||
}
|
||||
|
||||
public function canView(int $serverId, int $userId): bool
|
||||
{
|
||||
return $this->getUserRole($serverId, $userId) !== null;
|
||||
}
|
||||
|
||||
public function getTeam(int $serverId): array
|
||||
{
|
||||
$members = $this->db->fetchAll(
|
||||
'SELECT su.*, u.username, u.email
|
||||
FROM server_user su
|
||||
JOIN users u ON su.user_id = u.id
|
||||
WHERE su.server_id = ?
|
||||
ORDER BY su.created_at ASC',
|
||||
[$serverId]
|
||||
);
|
||||
|
||||
$owner = $this->db->fetch(
|
||||
'SELECT u.id, u.username, u.email
|
||||
FROM servers s
|
||||
JOIN users u ON s.created_by = u.id
|
||||
WHERE s.id = ?',
|
||||
[$serverId]
|
||||
);
|
||||
|
||||
$result = [];
|
||||
if ($owner) {
|
||||
$result[] = [
|
||||
'user_id' => (int) $owner['id'],
|
||||
'username' => $owner['username'],
|
||||
'email' => $owner['email'],
|
||||
'role' => 'owner',
|
||||
];
|
||||
}
|
||||
foreach ($members as $m) {
|
||||
$result[] = [
|
||||
'user_id' => (int) $m['user_id'],
|
||||
'username' => $m['username'],
|
||||
'email' => $m['email'],
|
||||
'role' => $m['role'],
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function addUser(int $serverId, int $userId, string $role): bool
|
||||
{
|
||||
if (!in_array($role, ['viewer', 'manager'], true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$existing = $this->db->fetch(
|
||||
'SELECT id FROM server_user WHERE server_id = ? AND user_id = ?',
|
||||
[$serverId, $userId]
|
||||
);
|
||||
if ($existing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->db->insert('server_user', [
|
||||
'server_id' => $serverId,
|
||||
'user_id' => $userId,
|
||||
'role' => $role,
|
||||
]);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function removeUser(int $serverId, int $userId): bool
|
||||
{
|
||||
return $this->db->delete(
|
||||
'server_user',
|
||||
'server_id = ? AND user_id = ?',
|
||||
[$serverId, $userId]
|
||||
) > 0;
|
||||
}
|
||||
|
||||
public function updateUserRole(int $serverId, int $userId, string $role): bool
|
||||
{
|
||||
if (!in_array($role, ['viewer', 'manager'], true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->db->update(
|
||||
'server_user',
|
||||
['role' => $role],
|
||||
'server_id = ? AND user_id = ?',
|
||||
[$serverId, $userId]
|
||||
) > 0;
|
||||
}
|
||||
|
||||
public function getOwnedServers(int $userId): array
|
||||
{
|
||||
return $this->db->fetchAll(
|
||||
'SELECT * FROM servers WHERE created_by = ? ORDER BY name ASC',
|
||||
[$userId]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user