From a1211ae81534758e41321474dc111535509558ad Mon Sep 17 00:00:00 2001 From: Hosteroid Date: Mon, 20 Oct 2025 19:02:56 +0300 Subject: [PATCH] Add isolation checks and logging for domains and groups Implemented validation to restrict domain assignment to notification groups owned by the user when isolation mode is enabled. Added logging for domain creation, bulk domain addition, and notification group creation, update, and deletion to improve auditability and traceability. --- app/Controllers/DomainController.php | 100 +++++++++++++++++- .../NotificationGroupController.php | 25 +++++ 2 files changed, 123 insertions(+), 2 deletions(-) diff --git a/app/Controllers/DomainController.php b/app/Controllers/DomainController.php index ccfcd60..935b35c 100644 --- a/app/Controllers/DomainController.php +++ b/app/Controllers/DomainController.php @@ -145,6 +145,22 @@ class DomainController extends Controller } $tags = $tagValidation['tags']; + // Validate notification group in isolation mode + if ($groupId) { + $userId = \Core\Auth::id(); + $settingModel = new \App\Models\Setting(); + $isolationMode = $settingModel->getValue('user_isolation_mode', 'shared'); + + if ($isolationMode === 'isolated') { + $group = $this->groupModel->find($groupId); + if (!$group || $group['user_id'] != $userId) { + $_SESSION['error'] = 'You can only assign domains to your own notification groups'; + $this->redirect('/domains/create'); + return; + } + } + } + // Check if domain already exists if ($this->domainModel->existsByDomain($domainName)) { $_SESSION['error'] = 'Domain already exists'; @@ -181,7 +197,19 @@ class DomainController extends Controller 'last_checked' => date('Y-m-d H:i:s'), 'status' => $status, 'whois_data' => json_encode($whoisData), - 'is_active' => 1 + 'is_active' => 1, + 'user_id' => $userId + ]); + + // Log domain creation + $logger = new \App\Services\Logger(); + $logger->info('Domain created', [ + 'domain_id' => $id, + 'domain_name' => $domainName, + 'user_id' => $userId, + 'status' => $status, + 'expiration_date' => $whoisData['expiration_date'], + 'notification_group_id' => $groupId ]); if ($status !== 'available') { @@ -250,6 +278,22 @@ class DomainController extends Controller return; } $tags = $tagValidation['tags']; + + // Validate notification group in isolation mode + if ($groupId) { + $userId = \Core\Auth::id(); + $settingModel = new \App\Models\Setting(); + $isolationMode = $settingModel->getValue('user_isolation_mode', 'shared'); + + if ($isolationMode === 'isolated') { + $group = $this->groupModel->find($groupId); + if (!$group || $group['user_id'] != $userId) { + $_SESSION['error'] = 'You can only assign domains to your own notification groups'; + $this->redirect('/domains/' . $id . '/edit'); + return; + } + } + } // Check if monitoring status changed $statusChanged = ($domain['is_active'] != $isActive); @@ -452,6 +496,22 @@ class DomainController extends Controller } $tags = $tagValidation['tags']; + // Validate notification group in isolation mode + if ($groupId) { + $userId = \Core\Auth::id(); + $settingModel = new \App\Models\Setting(); + $isolationMode = $settingModel->getValue('user_isolation_mode', 'shared'); + + if ($isolationMode === 'isolated') { + $group = $this->groupModel->find($groupId); + if (!$group || $group['user_id'] != $userId) { + $_SESSION['error'] = 'You can only assign domains to your own notification groups'; + $this->redirect('/domains/bulk-add'); + return; + } + } + } + // Split by new lines and clean $domainNames = array_filter(array_map('trim', explode("\n", $domainsText))); @@ -459,6 +519,16 @@ class DomainController extends Controller $skipped = 0; $availableCount = 0; $errors = []; + $userId = \Core\Auth::id(); + + // Log bulk add start + $logger = new \App\Services\Logger(); + $logger->info('Bulk domain add started', [ + 'user_id' => $userId, + 'domain_count' => count($domainNames), + 'notification_group_id' => $groupId, + 'tags' => $tags + ]); foreach ($domainNames as $domainName) { // Skip if already exists @@ -494,12 +564,22 @@ class DomainController extends Controller 'last_checked' => date('Y-m-d H:i:s'), 'status' => $status, 'whois_data' => json_encode($whoisData), - 'is_active' => 1 + 'is_active' => 1, + 'user_id' => \Core\Auth::id() ]); $added++; } + // Log bulk add completion + $logger->info('Bulk domain add completed', [ + 'user_id' => $userId, + 'added' => $added, + 'skipped' => $skipped, + 'errors' => count($errors), + 'available_count' => $availableCount + ]); + $message = "Added $added domain(s)"; if ($skipped > 0) $message .= ", skipped $skipped duplicate(s)"; if (count($errors) > 0) $message .= ", failed to add " . count($errors) . " domain(s)"; @@ -636,6 +716,22 @@ class DomainController extends Controller return; } + // Validate notification group in isolation mode + if ($groupId) { + $userId = \Core\Auth::id(); + $settingModel = new \App\Models\Setting(); + $isolationMode = $settingModel->getValue('user_isolation_mode', 'shared'); + + if ($isolationMode === 'isolated') { + $group = $this->groupModel->find($groupId); + if (!$group || $group['user_id'] != $userId) { + $_SESSION['error'] = 'You can only assign domains to your own notification groups'; + $this->redirect('/domains'); + return; + } + } + } + $updated = 0; foreach ($domainIds as $id) { if ($this->domainModel->update($id, ['notification_group_id' => $groupId])) { diff --git a/app/Controllers/NotificationGroupController.php b/app/Controllers/NotificationGroupController.php index 5d379f4..d3e9938 100644 --- a/app/Controllers/NotificationGroupController.php +++ b/app/Controllers/NotificationGroupController.php @@ -104,6 +104,15 @@ class NotificationGroupController extends Controller $id = $this->groupModel->create($groupData); + // Log group creation + $logger = new \App\Services\Logger(); + $logger->info('Notification group created', [ + 'group_id' => $id, + 'group_name' => $name, + 'user_id' => $userId, + 'isolation_mode' => $isolationMode + ]); + $_SESSION['success'] = "Group '$name' created successfully"; $this->redirect("/groups/edit?id=$id"); } catch (\Exception $e) { @@ -174,6 +183,14 @@ class NotificationGroupController extends Controller 'description' => $description ]); + // Log group update + $logger = new \App\Services\Logger(); + $logger->info('Notification group updated', [ + 'group_id' => $id, + 'group_name' => $name, + 'user_id' => \Core\Auth::id() + ]); + $_SESSION['success'] = 'Group updated successfully'; $this->redirect("/groups/edit?id=$id"); } catch (\Exception $e) { @@ -198,6 +215,14 @@ class NotificationGroupController extends Controller } try { + // Log group deletion + $logger = new \App\Services\Logger(); + $logger->info('Notification group deleted', [ + 'group_id' => $id, + 'group_name' => $group['name'], + 'user_id' => \Core\Auth::id() + ]); + $this->groupModel->deleteWithRelations($id); $_SESSION['success'] = 'Group deleted successfully'; $this->redirect('/groups');