Enforce user-specific data access for all users

Refactored controllers and models to always filter data by user ID, removing admin bypass logic. This ensures all statistics, groups, domains, and tags are user-specific regardless of isolation mode, improving data isolation and security.
This commit is contained in:
Hosteroid
2025-10-20 18:03:16 +03:00
parent 011fab095e
commit c387e90a19
5 changed files with 22 additions and 41 deletions

View File

@@ -27,27 +27,17 @@ class DashboardController extends Controller
$settingModel = new \App\Models\Setting(); $settingModel = new \App\Models\Setting();
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared'); $isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
// Get user-specific or global statistics // Get user-specific statistics (always user-specific)
if ($isolationMode === 'isolated') { $stats = $this->domainModel->getStatistics($userId);
$stats = $this->domainModel->getStatistics($userId); $recentDomains = $this->domainModel->getRecent(5, $userId);
$recentDomains = $this->domainModel->getRecent(5, $userId); $groups = $this->groupModel->getAllWithChannelCount($userId);
$groups = $this->groupModel->getAllWithChannelCount($userId);
} else {
$stats = $this->domainModel->getStatistics();
$recentDomains = $this->domainModel->getRecent(5);
$groups = $this->groupModel->getAllWithChannelCount();
}
// Get expiring threshold from settings // Get expiring threshold from settings
$notificationDays = $settingModel->getNotificationDays(); $notificationDays = $settingModel->getNotificationDays();
$expiringThreshold = !empty($notificationDays) ? max($notificationDays) : 30; $expiringThreshold = !empty($notificationDays) ? max($notificationDays) : 30;
// Get expiring domains limited to top 5 // Get expiring domains limited to top 5
if ($isolationMode === 'isolated') { $allExpiringDomains = $this->domainModel->getExpiringDomains($expiringThreshold, $userId);
$allExpiringDomains = $this->domainModel->getExpiringDomains($expiringThreshold, $userId);
} else {
$allExpiringDomains = $this->domainModel->getExpiringDomains($expiringThreshold);
}
$expiringThisMonth = array_slice($allExpiringDomains, 0, 5); $expiringThisMonth = array_slice($allExpiringDomains, 0, 5);
$recentLogs = $this->logModel->getRecent(10); $recentLogs = $this->logModel->getRecent(10);

View File

@@ -50,16 +50,11 @@ class DomainController extends Controller
]; ];
// Get filtered and paginated domains using model // Get filtered and paginated domains using model
$result = $this->domainModel->getFilteredPaginated($filters, $sortBy, $sortOrder, $page, $perPage, $expiringThreshold, $isolationMode === 'isolated' ? $userId : null); $result = $this->domainModel->getFilteredPaginated($filters, $sortBy, $sortOrder, $page, $perPage, $expiringThreshold, $userId);
// Get groups and tags based on isolation mode // Get groups and tags (always user-specific)
if ($isolationMode === 'isolated') { $groups = $this->groupModel->getAllWithChannelCount($userId);
$groups = $this->groupModel->getAllWithChannelCount($userId); $allTags = $this->domainModel->getAllTags($userId);
$allTags = $this->domainModel->getAllTags($userId);
} else {
$groups = $this->groupModel->getAllWithChannelCount();
$allTags = $this->domainModel->getAllTags();
}
// Format domains for display // Format domains for display
$formattedDomains = \App\Helpers\DomainHelper::formatMultiple($result['domains']); $formattedDomains = \App\Helpers\DomainHelper::formatMultiple($result['domains']);

View File

@@ -24,12 +24,8 @@ class NotificationGroupController extends Controller
$settingModel = new \App\Models\Setting(); $settingModel = new \App\Models\Setting();
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared'); $isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
// Get groups based on isolation mode // Get groups (always user-specific)
if ($isolationMode === 'isolated') { $groups = $this->groupModel->getAllWithChannelCount($userId);
$groups = $this->groupModel->getAllWithChannelCount($userId);
} else {
$groups = $this->groupModel->getAllWithChannelCount();
}
// Get users for transfer functionality (admin only) // Get users for transfer functionality (admin only)
$users = []; $users = [];

View File

@@ -25,8 +25,8 @@ class Domain extends Model
FROM domains d FROM domains d
LEFT JOIN notification_groups ng ON d.notification_group_id = ng.id"; LEFT JOIN notification_groups ng ON d.notification_group_id = ng.id";
if ($userId && !$this->getUserModel()->isAdmin($userId)) { if ($userId) {
$sql .= " WHERE d.user_id = ?"; $sql .= " WHERE d.user_id = ? ORDER BY d.status DESC, d.expiration_date ASC";
$stmt = $this->db->prepare($sql); $stmt = $this->db->prepare($sql);
$stmt->execute([$userId]); $stmt->execute([$userId]);
} else { } else {
@@ -52,7 +52,7 @@ class Domain extends Model
$params = [$days]; $params = [$days];
if ($userId && !$this->getUserModel()->isAdmin($userId)) { if ($userId) {
$sql .= " AND d.user_id = ?"; $sql .= " AND d.user_id = ?";
$params[] = $userId; $params[] = $userId;
} }
@@ -76,7 +76,7 @@ class Domain extends Model
$params = [$status]; $params = [$status];
if ($userId && !$this->getUserModel()->isAdmin($userId)) { if ($userId) {
$sql .= " AND d.user_id = ?"; $sql .= " AND d.user_id = ?";
$params[] = $userId; $params[] = $userId;
} }
@@ -140,7 +140,7 @@ class Domain extends Model
$params = []; $params = [];
if ($userId && !$this->getUserModel()->isAdmin($userId)) { if ($userId) {
$sql .= " AND d.user_id = ?"; $sql .= " AND d.user_id = ?";
$params[] = $userId; $params[] = $userId;
} }
@@ -170,7 +170,7 @@ class Domain extends Model
$whereClause = "WHERE is_active = 1"; $whereClause = "WHERE is_active = 1";
$params = []; $params = [];
if ($userId && !$this->getUserModel()->isAdmin($userId)) { if ($userId) {
$whereClause .= " AND user_id = ?"; $whereClause .= " AND user_id = ?";
$params[] = $userId; $params[] = $userId;
} }
@@ -191,7 +191,7 @@ class Domain extends Model
$inactiveWhereClause = "WHERE is_active = 0"; $inactiveWhereClause = "WHERE is_active = 0";
$inactiveParams = []; $inactiveParams = [];
if ($userId && !$this->getUserModel()->isAdmin($userId)) { if ($userId) {
$inactiveWhereClause .= " AND user_id = ?"; $inactiveWhereClause .= " AND user_id = ?";
$inactiveParams[] = $userId; $inactiveParams[] = $userId;
} }
@@ -372,7 +372,7 @@ class Domain extends Model
$params = ['%' . $query . '%', '%' . $query . '%', '%' . $query . '%']; $params = ['%' . $query . '%', '%' . $query . '%', '%' . $query . '%'];
if ($userId && !$this->getUserModel()->isAdmin($userId)) { if ($userId) {
$sql .= " AND d.user_id = ?"; $sql .= " AND d.user_id = ?";
$params[] = $userId; $params[] = $userId;
} }

View File

@@ -28,7 +28,7 @@ class NotificationGroup extends Model
LEFT JOIN notification_channels nc ON ng.id = nc.notification_group_id LEFT JOIN notification_channels nc ON ng.id = nc.notification_group_id
LEFT JOIN domains d ON ng.id = d.notification_group_id"; LEFT JOIN domains d ON ng.id = d.notification_group_id";
if ($userId && !$this->getUserModel()->isAdmin($userId)) { if ($userId) {
$sql .= " WHERE ng.user_id = ? GROUP BY ng.id ORDER BY ng.name ASC"; $sql .= " WHERE ng.user_id = ? GROUP BY ng.id ORDER BY ng.name ASC";
$stmt = $this->db->prepare($sql); $stmt = $this->db->prepare($sql);
$stmt->execute([$userId]); $stmt->execute([$userId]);
@@ -52,7 +52,7 @@ class NotificationGroup extends Model
} }
// Check if user has access to this group // Check if user has access to this group
if ($userId && !$this->getUserModel()->isAdmin($userId) && $group['user_id'] != $userId) { if ($userId && $group['user_id'] != $userId) {
return null; return null;
} }
@@ -62,7 +62,7 @@ class NotificationGroup extends Model
// Get domains (filtered by user if needed) // Get domains (filtered by user if needed)
$domainModel = new Domain(); $domainModel = new Domain();
if ($userId && !$this->getUserModel()->isAdmin($userId)) { if ($userId) {
$group['domains'] = $domainModel->where('notification_group_id', $id, $userId); $group['domains'] = $domainModel->where('notification_group_id', $id, $userId);
} else { } else {
$group['domains'] = $domainModel->where('notification_group_id', $id); $group['domains'] = $domainModel->where('notification_group_id', $id);