From c387e90a19cc9076e53464694910c725d5ad7479 Mon Sep 17 00:00:00 2001 From: Hosteroid Date: Mon, 20 Oct 2025 18:03:16 +0300 Subject: [PATCH] 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. --- app/Controllers/DashboardController.php | 20 +++++-------------- app/Controllers/DomainController.php | 13 ++++-------- .../NotificationGroupController.php | 8 ++------ app/Models/Domain.php | 16 +++++++-------- app/Models/NotificationGroup.php | 6 +++--- 5 files changed, 22 insertions(+), 41 deletions(-) diff --git a/app/Controllers/DashboardController.php b/app/Controllers/DashboardController.php index 6b5e55e..1c9d32d 100644 --- a/app/Controllers/DashboardController.php +++ b/app/Controllers/DashboardController.php @@ -27,27 +27,17 @@ class DashboardController extends Controller $settingModel = new \App\Models\Setting(); $isolationMode = $settingModel->getValue('user_isolation_mode', 'shared'); - // Get user-specific or global statistics - if ($isolationMode === 'isolated') { - $stats = $this->domainModel->getStatistics($userId); - $recentDomains = $this->domainModel->getRecent(5, $userId); - $groups = $this->groupModel->getAllWithChannelCount($userId); - } else { - $stats = $this->domainModel->getStatistics(); - $recentDomains = $this->domainModel->getRecent(5); - $groups = $this->groupModel->getAllWithChannelCount(); - } + // Get user-specific statistics (always user-specific) + $stats = $this->domainModel->getStatistics($userId); + $recentDomains = $this->domainModel->getRecent(5, $userId); + $groups = $this->groupModel->getAllWithChannelCount($userId); // Get expiring threshold from settings $notificationDays = $settingModel->getNotificationDays(); $expiringThreshold = !empty($notificationDays) ? max($notificationDays) : 30; // Get expiring domains limited to top 5 - if ($isolationMode === 'isolated') { - $allExpiringDomains = $this->domainModel->getExpiringDomains($expiringThreshold, $userId); - } else { - $allExpiringDomains = $this->domainModel->getExpiringDomains($expiringThreshold); - } + $allExpiringDomains = $this->domainModel->getExpiringDomains($expiringThreshold, $userId); $expiringThisMonth = array_slice($allExpiringDomains, 0, 5); $recentLogs = $this->logModel->getRecent(10); diff --git a/app/Controllers/DomainController.php b/app/Controllers/DomainController.php index cb8be91..7b3c73b 100644 --- a/app/Controllers/DomainController.php +++ b/app/Controllers/DomainController.php @@ -50,16 +50,11 @@ class DomainController extends Controller ]; // 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 - if ($isolationMode === 'isolated') { - $groups = $this->groupModel->getAllWithChannelCount($userId); - $allTags = $this->domainModel->getAllTags($userId); - } else { - $groups = $this->groupModel->getAllWithChannelCount(); - $allTags = $this->domainModel->getAllTags(); - } + // Get groups and tags (always user-specific) + $groups = $this->groupModel->getAllWithChannelCount($userId); + $allTags = $this->domainModel->getAllTags($userId); // Format domains for display $formattedDomains = \App\Helpers\DomainHelper::formatMultiple($result['domains']); diff --git a/app/Controllers/NotificationGroupController.php b/app/Controllers/NotificationGroupController.php index 5d379f4..5f5f684 100644 --- a/app/Controllers/NotificationGroupController.php +++ b/app/Controllers/NotificationGroupController.php @@ -24,12 +24,8 @@ class NotificationGroupController extends Controller $settingModel = new \App\Models\Setting(); $isolationMode = $settingModel->getValue('user_isolation_mode', 'shared'); - // Get groups based on isolation mode - if ($isolationMode === 'isolated') { - $groups = $this->groupModel->getAllWithChannelCount($userId); - } else { - $groups = $this->groupModel->getAllWithChannelCount(); - } + // Get groups (always user-specific) + $groups = $this->groupModel->getAllWithChannelCount($userId); // Get users for transfer functionality (admin only) $users = []; diff --git a/app/Models/Domain.php b/app/Models/Domain.php index b78fdb9..c20210c 100644 --- a/app/Models/Domain.php +++ b/app/Models/Domain.php @@ -25,8 +25,8 @@ class Domain extends Model FROM domains d LEFT JOIN notification_groups ng ON d.notification_group_id = ng.id"; - if ($userId && !$this->getUserModel()->isAdmin($userId)) { - $sql .= " WHERE d.user_id = ?"; + if ($userId) { + $sql .= " WHERE d.user_id = ? ORDER BY d.status DESC, d.expiration_date ASC"; $stmt = $this->db->prepare($sql); $stmt->execute([$userId]); } else { @@ -52,7 +52,7 @@ class Domain extends Model $params = [$days]; - if ($userId && !$this->getUserModel()->isAdmin($userId)) { + if ($userId) { $sql .= " AND d.user_id = ?"; $params[] = $userId; } @@ -76,7 +76,7 @@ class Domain extends Model $params = [$status]; - if ($userId && !$this->getUserModel()->isAdmin($userId)) { + if ($userId) { $sql .= " AND d.user_id = ?"; $params[] = $userId; } @@ -140,7 +140,7 @@ class Domain extends Model $params = []; - if ($userId && !$this->getUserModel()->isAdmin($userId)) { + if ($userId) { $sql .= " AND d.user_id = ?"; $params[] = $userId; } @@ -170,7 +170,7 @@ class Domain extends Model $whereClause = "WHERE is_active = 1"; $params = []; - if ($userId && !$this->getUserModel()->isAdmin($userId)) { + if ($userId) { $whereClause .= " AND user_id = ?"; $params[] = $userId; } @@ -191,7 +191,7 @@ class Domain extends Model $inactiveWhereClause = "WHERE is_active = 0"; $inactiveParams = []; - if ($userId && !$this->getUserModel()->isAdmin($userId)) { + if ($userId) { $inactiveWhereClause .= " AND user_id = ?"; $inactiveParams[] = $userId; } @@ -372,7 +372,7 @@ class Domain extends Model $params = ['%' . $query . '%', '%' . $query . '%', '%' . $query . '%']; - if ($userId && !$this->getUserModel()->isAdmin($userId)) { + if ($userId) { $sql .= " AND d.user_id = ?"; $params[] = $userId; } diff --git a/app/Models/NotificationGroup.php b/app/Models/NotificationGroup.php index 50f438b..9403e62 100644 --- a/app/Models/NotificationGroup.php +++ b/app/Models/NotificationGroup.php @@ -28,7 +28,7 @@ class NotificationGroup extends Model LEFT JOIN notification_channels nc ON ng.id = nc.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"; $stmt = $this->db->prepare($sql); $stmt->execute([$userId]); @@ -52,7 +52,7 @@ class NotificationGroup extends Model } // 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; } @@ -62,7 +62,7 @@ class NotificationGroup extends Model // Get domains (filtered by user if needed) $domainModel = new Domain(); - if ($userId && !$this->getUserModel()->isAdmin($userId)) { + if ($userId) { $group['domains'] = $domainModel->where('notification_group_id', $id, $userId); } else { $group['domains'] = $domainModel->where('notification_group_id', $id);