Refactor routes and controllers for RESTful resource access
Updated controllers and routes to use RESTful resource-based URLs and parameter passing for groups, users, and notification channels. Added user isolation checks for domain and group access, ensuring proper data filtering based on isolation mode. Adjusted views to match new route structure and improved security and maintainability by removing reliance on query parameters for resource identification.
This commit is contained in:
@@ -20,6 +20,22 @@ class DomainController extends Controller
|
|||||||
$this->whoisService = new WhoisService();
|
$this->whoisService = new WhoisService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check domain access based on isolation mode
|
||||||
|
*/
|
||||||
|
private function checkDomainAccess(int $id): ?array
|
||||||
|
{
|
||||||
|
$userId = \Core\Auth::id();
|
||||||
|
$settingModel = new \App\Models\Setting();
|
||||||
|
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
|
||||||
|
|
||||||
|
if ($isolationMode === 'isolated') {
|
||||||
|
return $this->domainModel->findWithIsolation($id, $userId);
|
||||||
|
} else {
|
||||||
|
return $this->domainModel->find($id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
// Get current user and isolation mode
|
// Get current user and isolation mode
|
||||||
@@ -221,7 +237,7 @@ class DomainController extends Controller
|
|||||||
public function edit($params = [])
|
public function edit($params = [])
|
||||||
{
|
{
|
||||||
$id = $params['id'] ?? 0;
|
$id = $params['id'] ?? 0;
|
||||||
$domain = $this->domainModel->find($id);
|
$domain = $this->checkDomainAccess($id);
|
||||||
|
|
||||||
if (!$domain) {
|
if (!$domain) {
|
||||||
$_SESSION['error'] = 'Domain not found';
|
$_SESSION['error'] = 'Domain not found';
|
||||||
@@ -258,7 +274,7 @@ class DomainController extends Controller
|
|||||||
$this->verifyCsrf('/domains');
|
$this->verifyCsrf('/domains');
|
||||||
|
|
||||||
$id = (int)($params['id'] ?? 0);
|
$id = (int)($params['id'] ?? 0);
|
||||||
$domain = $this->domainModel->find($id);
|
$domain = $this->checkDomainAccess($id);
|
||||||
|
|
||||||
if (!$domain) {
|
if (!$domain) {
|
||||||
$_SESSION['error'] = 'Domain not found';
|
$_SESSION['error'] = 'Domain not found';
|
||||||
@@ -269,7 +285,6 @@ class DomainController extends Controller
|
|||||||
$groupId = !empty($_POST['notification_group_id']) ? (int)$_POST['notification_group_id'] : null;
|
$groupId = !empty($_POST['notification_group_id']) ? (int)$_POST['notification_group_id'] : null;
|
||||||
$isActive = isset($_POST['is_active']) ? 1 : 0;
|
$isActive = isset($_POST['is_active']) ? 1 : 0;
|
||||||
$tagsInput = trim($_POST['tags'] ?? '');
|
$tagsInput = trim($_POST['tags'] ?? '');
|
||||||
$userId = \Core\Auth::id();
|
|
||||||
|
|
||||||
// Validate tags
|
// Validate tags
|
||||||
$tagValidation = \App\Helpers\InputValidator::validateTags($tagsInput);
|
$tagValidation = \App\Helpers\InputValidator::validateTags($tagsInput);
|
||||||
@@ -350,7 +365,7 @@ class DomainController extends Controller
|
|||||||
public function refresh($params = [])
|
public function refresh($params = [])
|
||||||
{
|
{
|
||||||
$id = $params['id'] ?? 0;
|
$id = $params['id'] ?? 0;
|
||||||
$domain = $this->domainModel->find($id);
|
$domain = $this->checkDomainAccess($id);
|
||||||
|
|
||||||
if (!$domain) {
|
if (!$domain) {
|
||||||
$_SESSION['error'] = 'Domain not found';
|
$_SESSION['error'] = 'Domain not found';
|
||||||
@@ -402,7 +417,7 @@ class DomainController extends Controller
|
|||||||
public function delete($params = [])
|
public function delete($params = [])
|
||||||
{
|
{
|
||||||
$id = $params['id'] ?? 0;
|
$id = $params['id'] ?? 0;
|
||||||
$domain = $this->domainModel->find($id);
|
$domain = $this->checkDomainAccess($id);
|
||||||
|
|
||||||
if (!$domain) {
|
if (!$domain) {
|
||||||
$_SESSION['error'] = 'Domain not found';
|
$_SESSION['error'] = 'Domain not found';
|
||||||
@@ -418,7 +433,18 @@ class DomainController extends Controller
|
|||||||
public function show($params = [])
|
public function show($params = [])
|
||||||
{
|
{
|
||||||
$id = $params['id'] ?? 0;
|
$id = $params['id'] ?? 0;
|
||||||
|
|
||||||
|
// Get current user and isolation mode
|
||||||
|
$userId = \Core\Auth::id();
|
||||||
|
$settingModel = new \App\Models\Setting();
|
||||||
|
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
|
||||||
|
|
||||||
|
// Check domain access based on isolation mode
|
||||||
|
if ($isolationMode === 'isolated') {
|
||||||
|
$domain = $this->domainModel->getWithChannels($id, $userId);
|
||||||
|
} else {
|
||||||
$domain = $this->domainModel->getWithChannels($id);
|
$domain = $this->domainModel->getWithChannels($id);
|
||||||
|
}
|
||||||
|
|
||||||
if (!$domain) {
|
if (!$domain) {
|
||||||
$_SESSION['error'] = 'Domain not found';
|
$_SESSION['error'] = 'Domain not found';
|
||||||
@@ -618,11 +644,21 @@ class DomainController extends Controller
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get current user and isolation mode
|
||||||
|
$userId = \Core\Auth::id();
|
||||||
|
$settingModel = new \App\Models\Setting();
|
||||||
|
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
|
||||||
|
|
||||||
$refreshed = 0;
|
$refreshed = 0;
|
||||||
$failed = 0;
|
$failed = 0;
|
||||||
|
|
||||||
foreach ($domainIds as $id) {
|
foreach ($domainIds as $id) {
|
||||||
|
// Check domain access based on isolation mode
|
||||||
|
if ($isolationMode === 'isolated') {
|
||||||
|
$domain = $this->domainModel->findWithIsolation($id, $userId);
|
||||||
|
} else {
|
||||||
$domain = $this->domainModel->find($id);
|
$domain = $this->domainModel->find($id);
|
||||||
|
}
|
||||||
if (!$domain) continue;
|
if (!$domain) continue;
|
||||||
|
|
||||||
$whoisData = $this->whoisService->getDomainInfo($domain['domain_name']);
|
$whoisData = $this->whoisService->getDomainInfo($domain['domain_name']);
|
||||||
@@ -770,9 +806,21 @@ class DomainController extends Controller
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get current user and isolation mode
|
||||||
|
$userId = \Core\Auth::id();
|
||||||
|
$settingModel = new \App\Models\Setting();
|
||||||
|
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
|
||||||
|
|
||||||
$updated = 0;
|
$updated = 0;
|
||||||
foreach ($domainIds as $id) {
|
foreach ($domainIds as $id) {
|
||||||
if ($this->domainModel->update($id, ['is_active' => $isActive])) {
|
// Check domain access based on isolation mode
|
||||||
|
if ($isolationMode === 'isolated') {
|
||||||
|
$domain = $this->domainModel->findWithIsolation($id, $userId);
|
||||||
|
} else {
|
||||||
|
$domain = $this->domainModel->find($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($domain && $this->domainModel->update($id, ['is_active' => $isActive])) {
|
||||||
$updated++;
|
$updated++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -793,7 +841,7 @@ class DomainController extends Controller
|
|||||||
$this->verifyCsrf('/domains');
|
$this->verifyCsrf('/domains');
|
||||||
|
|
||||||
$id = (int)($params['id'] ?? 0);
|
$id = (int)($params['id'] ?? 0);
|
||||||
$domain = $this->domainModel->find($id);
|
$domain = $this->checkDomainAccess($id);
|
||||||
|
|
||||||
if (!$domain) {
|
if (!$domain) {
|
||||||
$_SESSION['error'] = 'Domain not found';
|
$_SESSION['error'] = 'Domain not found';
|
||||||
@@ -845,9 +893,19 @@ class DomainController extends Controller
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get current user and isolation mode
|
||||||
|
$userId = \Core\Auth::id();
|
||||||
|
$settingModel = new \App\Models\Setting();
|
||||||
|
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
|
||||||
|
|
||||||
$updated = 0;
|
$updated = 0;
|
||||||
foreach ($domainIds as $id) {
|
foreach ($domainIds as $id) {
|
||||||
|
// Check domain access based on isolation mode
|
||||||
|
if ($isolationMode === 'isolated') {
|
||||||
|
$domain = $this->domainModel->findWithIsolation($id, $userId);
|
||||||
|
} else {
|
||||||
$domain = $this->domainModel->find($id);
|
$domain = $this->domainModel->find($id);
|
||||||
|
}
|
||||||
if (!$domain) continue;
|
if (!$domain) continue;
|
||||||
|
|
||||||
// Get existing tags
|
// Get existing tags
|
||||||
@@ -886,9 +944,21 @@ class DomainController extends Controller
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get current user and isolation mode
|
||||||
|
$userId = \Core\Auth::id();
|
||||||
|
$settingModel = new \App\Models\Setting();
|
||||||
|
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
|
||||||
|
|
||||||
$updated = 0;
|
$updated = 0;
|
||||||
foreach ($domainIds as $id) {
|
foreach ($domainIds as $id) {
|
||||||
if ($this->domainModel->update($id, ['tags' => ''])) {
|
// Check domain access based on isolation mode
|
||||||
|
if ($isolationMode === 'isolated') {
|
||||||
|
$domain = $this->domainModel->findWithIsolation($id, $userId);
|
||||||
|
} else {
|
||||||
|
$domain = $this->domainModel->find($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($domain && $this->domainModel->update($id, ['tags' => ''])) {
|
||||||
$updated++;
|
$updated++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,22 @@ class NotificationGroupController extends Controller
|
|||||||
$this->channelModel = new NotificationChannel();
|
$this->channelModel = new NotificationChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check group access based on isolation mode
|
||||||
|
*/
|
||||||
|
private function checkGroupAccess(int $id): ?array
|
||||||
|
{
|
||||||
|
$userId = \Core\Auth::id();
|
||||||
|
$settingModel = new \App\Models\Setting();
|
||||||
|
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
|
||||||
|
|
||||||
|
if ($isolationMode === 'isolated') {
|
||||||
|
return $this->groupModel->getWithDetails($id, $userId);
|
||||||
|
} else {
|
||||||
|
return $this->groupModel->getWithDetails($id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
// Get current user and isolation mode
|
// Get current user and isolation mode
|
||||||
@@ -114,7 +130,7 @@ class NotificationGroupController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$_SESSION['success'] = "Group '$name' created successfully";
|
$_SESSION['success'] = "Group '$name' created successfully";
|
||||||
$this->redirect("/groups/edit?id=$id");
|
$this->redirect("/groups/$id/edit");
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// Log the error using the ErrorHandler service
|
// Log the error using the ErrorHandler service
|
||||||
$errorHandler = new \App\Services\ErrorHandler();
|
$errorHandler = new \App\Services\ErrorHandler();
|
||||||
@@ -125,10 +141,10 @@ class NotificationGroupController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit()
|
public function edit($params = [])
|
||||||
{
|
{
|
||||||
$id = (int)($_GET['id'] ?? 0);
|
$id = $params['id'] ?? 0;
|
||||||
$group = $this->groupModel->getWithDetails($id);
|
$group = $this->checkGroupAccess($id);
|
||||||
|
|
||||||
if (!$group) {
|
if (!$group) {
|
||||||
$_SESSION['error'] = 'Group not found';
|
$_SESSION['error'] = 'Group not found';
|
||||||
@@ -142,7 +158,7 @@ class NotificationGroupController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update()
|
public function update($params = [])
|
||||||
{
|
{
|
||||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
$this->redirect('/groups');
|
$this->redirect('/groups');
|
||||||
@@ -152,13 +168,21 @@ class NotificationGroupController extends Controller
|
|||||||
// CSRF Protection
|
// CSRF Protection
|
||||||
$this->verifyCsrf('/groups');
|
$this->verifyCsrf('/groups');
|
||||||
|
|
||||||
$id = (int)$_POST['id'];
|
$id = $params['id'] ?? 0;
|
||||||
|
$group = $this->checkGroupAccess($id);
|
||||||
|
|
||||||
|
if (!$group) {
|
||||||
|
$_SESSION['error'] = 'Group not found';
|
||||||
|
$this->redirect('/groups');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$name = trim($_POST['name'] ?? '');
|
$name = trim($_POST['name'] ?? '');
|
||||||
$description = trim($_POST['description'] ?? '');
|
$description = trim($_POST['description'] ?? '');
|
||||||
|
|
||||||
if (empty($name)) {
|
if (empty($name)) {
|
||||||
$_SESSION['error'] = 'Group name is required';
|
$_SESSION['error'] = 'Group name is required';
|
||||||
$this->redirect("/groups/edit?id=$id");
|
$this->redirect("/groups/$id/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,14 +190,14 @@ class NotificationGroupController extends Controller
|
|||||||
$nameError = \App\Helpers\InputValidator::validateLength($name, 255, 'Group name');
|
$nameError = \App\Helpers\InputValidator::validateLength($name, 255, 'Group name');
|
||||||
if ($nameError) {
|
if ($nameError) {
|
||||||
$_SESSION['error'] = $nameError;
|
$_SESSION['error'] = $nameError;
|
||||||
$this->redirect("/groups/edit?id=$id");
|
$this->redirect("/groups/$id/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$descError = \App\Helpers\InputValidator::validateLength($description, 1000, 'Description');
|
$descError = \App\Helpers\InputValidator::validateLength($description, 1000, 'Description');
|
||||||
if ($descError) {
|
if ($descError) {
|
||||||
$_SESSION['error'] = $descError;
|
$_SESSION['error'] = $descError;
|
||||||
$this->redirect("/groups/edit?id=$id");
|
$this->redirect("/groups/$id/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,21 +216,21 @@ class NotificationGroupController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$_SESSION['success'] = 'Group updated successfully';
|
$_SESSION['success'] = 'Group updated successfully';
|
||||||
$this->redirect("/groups/edit?id=$id");
|
$this->redirect("/groups/$id/edit");
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// Log the error using the ErrorHandler service
|
// Log the error using the ErrorHandler service
|
||||||
$errorHandler = new \App\Services\ErrorHandler();
|
$errorHandler = new \App\Services\ErrorHandler();
|
||||||
$errorHandler->handleException($e);
|
$errorHandler->handleException($e);
|
||||||
|
|
||||||
$_SESSION['error'] = 'Failed to update notification group. Please try again.';
|
$_SESSION['error'] = 'Failed to update notification group. Please try again.';
|
||||||
$this->redirect("/groups/edit?id=$id");
|
$this->redirect("/groups/$id/edit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete()
|
public function delete($params = [])
|
||||||
{
|
{
|
||||||
$id = (int)($_GET['id'] ?? 0);
|
$id = $params['id'] ?? 0;
|
||||||
$group = $this->groupModel->find($id);
|
$group = $this->checkGroupAccess($id);
|
||||||
|
|
||||||
if (!$group) {
|
if (!$group) {
|
||||||
$_SESSION['error'] = 'Group not found';
|
$_SESSION['error'] = 'Group not found';
|
||||||
@@ -236,7 +260,7 @@ class NotificationGroupController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addChannel()
|
public function addChannel($params = [])
|
||||||
{
|
{
|
||||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
$this->redirect('/groups');
|
$this->redirect('/groups');
|
||||||
@@ -246,13 +270,22 @@ class NotificationGroupController extends Controller
|
|||||||
// CSRF Protection
|
// CSRF Protection
|
||||||
$this->verifyCsrf('/groups');
|
$this->verifyCsrf('/groups');
|
||||||
|
|
||||||
$groupId = (int)$_POST['group_id'];
|
$groupId = $params['group_id'] ?? 0;
|
||||||
|
|
||||||
|
// Check group access
|
||||||
|
$group = $this->checkGroupAccess($groupId);
|
||||||
|
if (!$group) {
|
||||||
|
$_SESSION['error'] = 'Group not found';
|
||||||
|
$this->redirect('/groups');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$channelType = $_POST['channel_type'] ?? '';
|
$channelType = $_POST['channel_type'] ?? '';
|
||||||
|
|
||||||
// Validate channel type
|
// Validate channel type
|
||||||
if (empty($channelType)) {
|
if (empty($channelType)) {
|
||||||
$_SESSION['error'] = 'Please select a channel type';
|
$_SESSION['error'] = 'Please select a channel type';
|
||||||
$this->redirect("/groups/edit?id=$groupId");
|
$this->redirect("/groups/$groupId/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,59 +308,75 @@ class NotificationGroupController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['error'] = "Invalid channel configuration: Missing {$missingField}";
|
$_SESSION['error'] = "Invalid channel configuration: Missing {$missingField}";
|
||||||
$this->redirect("/groups/edit?id=$groupId");
|
$this->redirect("/groups/$groupId/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->channelModel->createChannel($groupId, $channelType, $config);
|
$this->channelModel->createChannel($groupId, $channelType, $config);
|
||||||
$_SESSION['success'] = 'Channel added successfully';
|
$_SESSION['success'] = 'Channel added successfully';
|
||||||
$this->redirect("/groups/edit?id=$groupId");
|
$this->redirect("/groups/$groupId/edit");
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// Log the error using the ErrorHandler service
|
// Log the error using the ErrorHandler service
|
||||||
$errorHandler = new \App\Services\ErrorHandler();
|
$errorHandler = new \App\Services\ErrorHandler();
|
||||||
$errorHandler->handleException($e);
|
$errorHandler->handleException($e);
|
||||||
|
|
||||||
$_SESSION['error'] = 'Failed to add notification channel. Please try again.';
|
$_SESSION['error'] = 'Failed to add notification channel. Please try again.';
|
||||||
$this->redirect("/groups/edit?id=$groupId");
|
$this->redirect("/groups/$groupId/edit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteChannel()
|
public function deleteChannel($params = [])
|
||||||
{
|
{
|
||||||
$id = (int)($_GET['id'] ?? 0);
|
$id = $params['id'] ?? 0;
|
||||||
$groupId = (int)($_GET['group_id'] ?? 0);
|
$groupId = $params['group_id'] ?? 0;
|
||||||
|
|
||||||
|
// Check group access
|
||||||
|
$group = $this->checkGroupAccess($groupId);
|
||||||
|
if (!$group) {
|
||||||
|
$_SESSION['error'] = 'Group not found';
|
||||||
|
$this->redirect('/groups');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->channelModel->delete($id);
|
$this->channelModel->delete($id);
|
||||||
$_SESSION['success'] = 'Channel deleted successfully';
|
$_SESSION['success'] = 'Channel deleted successfully';
|
||||||
$this->redirect("/groups/edit?id=$groupId");
|
$this->redirect("/groups/$groupId/edit");
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// Log the error using the ErrorHandler service
|
// Log the error using the ErrorHandler service
|
||||||
$errorHandler = new \App\Services\ErrorHandler();
|
$errorHandler = new \App\Services\ErrorHandler();
|
||||||
$errorHandler->handleException($e);
|
$errorHandler->handleException($e);
|
||||||
|
|
||||||
$_SESSION['error'] = 'Failed to delete notification channel. Please try again.';
|
$_SESSION['error'] = 'Failed to delete notification channel. Please try again.';
|
||||||
$this->redirect("/groups/edit?id=$groupId");
|
$this->redirect("/groups/$groupId/edit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toggleChannel()
|
public function toggleChannel($params = [])
|
||||||
{
|
{
|
||||||
$id = (int)($_GET['id'] ?? 0);
|
$id = $params['id'] ?? 0;
|
||||||
$groupId = (int)($_GET['group_id'] ?? 0);
|
$groupId = $params['group_id'] ?? 0;
|
||||||
|
|
||||||
|
// Check group access
|
||||||
|
$group = $this->checkGroupAccess($groupId);
|
||||||
|
if (!$group) {
|
||||||
|
$_SESSION['error'] = 'Group not found';
|
||||||
|
$this->redirect('/groups');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->channelModel->toggleActive($id);
|
$this->channelModel->toggleActive($id);
|
||||||
$_SESSION['success'] = 'Channel status updated';
|
$_SESSION['success'] = 'Channel status updated';
|
||||||
$this->redirect("/groups/edit?id=$groupId");
|
$this->redirect("/groups/$groupId/edit");
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// Log the error using the ErrorHandler service
|
// Log the error using the ErrorHandler service
|
||||||
$errorHandler = new \App\Services\ErrorHandler();
|
$errorHandler = new \App\Services\ErrorHandler();
|
||||||
$errorHandler->handleException($e);
|
$errorHandler->handleException($e);
|
||||||
|
|
||||||
$_SESSION['error'] = 'Failed to update channel status. Please try again.';
|
$_SESSION['error'] = 'Failed to update channel status. Please try again.';
|
||||||
$this->redirect("/groups/edit?id=$groupId");
|
$this->redirect("/groups/$groupId/edit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +404,7 @@ class NotificationGroupController extends Controller
|
|||||||
} else {
|
} else {
|
||||||
$_SESSION['error'] = 'Invalid channel configuration for testing';
|
$_SESSION['error'] = 'Invalid channel configuration for testing';
|
||||||
$groupId = $_POST['group_id'] ?? 0;
|
$groupId = $_POST['group_id'] ?? 0;
|
||||||
$this->redirect($groupId ? "/groups/edit?id=$groupId" : '/groups');
|
$this->redirect($groupId ? "/groups/$groupId/edit" : '/groups');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -404,7 +453,7 @@ class NotificationGroupController extends Controller
|
|||||||
// Only redirect if not AJAX
|
// Only redirect if not AJAX
|
||||||
if (!$isAjax) {
|
if (!$isAjax) {
|
||||||
$groupId = $_POST['group_id'] ?? 0;
|
$groupId = $_POST['group_id'] ?? 0;
|
||||||
$this->redirect("/groups/edit?id=$groupId");
|
$this->redirect("/groups/$groupId/edit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,13 +569,27 @@ class NotificationGroupController extends Controller
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get current user and isolation mode
|
||||||
|
$userId = \Core\Auth::id();
|
||||||
|
$settingModel = new \App\Models\Setting();
|
||||||
|
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
|
||||||
|
|
||||||
$deletedCount = 0;
|
$deletedCount = 0;
|
||||||
$errors = [];
|
$errors = [];
|
||||||
|
|
||||||
foreach ($groupIds as $groupId) {
|
foreach ($groupIds as $groupId) {
|
||||||
try {
|
try {
|
||||||
|
// Check group access based on isolation mode
|
||||||
|
if ($isolationMode === 'isolated') {
|
||||||
|
$group = $this->groupModel->getWithDetails((int)$groupId, $userId);
|
||||||
|
} else {
|
||||||
|
$group = $this->groupModel->getWithDetails((int)$groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($group) {
|
||||||
$this->groupModel->deleteWithRelations((int)$groupId);
|
$this->groupModel->deleteWithRelations((int)$groupId);
|
||||||
$deletedCount++;
|
$deletedCount++;
|
||||||
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// Log individual errors but continue processing
|
// Log individual errors but continue processing
|
||||||
$errorHandler = new \App\Services\ErrorHandler();
|
$errorHandler = new \App\Services\ErrorHandler();
|
||||||
|
|||||||
@@ -98,8 +98,13 @@ class SearchController extends Controller
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get current user and isolation mode
|
||||||
|
$userId = \Core\Auth::id();
|
||||||
|
$settingModel = new \App\Models\Setting();
|
||||||
|
$isolationMode = $settingModel->getValue('user_isolation_mode', 'shared');
|
||||||
|
|
||||||
// Search existing domains (limit to 5 for quick results)
|
// Search existing domains (limit to 5 for quick results)
|
||||||
$results = $this->domainModel->searchSuggestions($query, 5);
|
$results = $this->domainModel->searchSuggestions($query, 5, $isolationMode === 'isolated' ? $userId : null);
|
||||||
|
|
||||||
// Calculate days left for each domain
|
// Calculate days left for each domain
|
||||||
foreach ($results as &$domain) {
|
foreach ($results as &$domain) {
|
||||||
|
|||||||
@@ -194,9 +194,9 @@ class UserController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Show edit user form
|
* Show edit user form
|
||||||
*/
|
*/
|
||||||
public function edit()
|
public function edit($params = [])
|
||||||
{
|
{
|
||||||
$userId = (int)($_GET['id'] ?? 0);
|
$userId = $params['id'] ?? 0;
|
||||||
$user = $this->userModel->find($userId);
|
$user = $this->userModel->find($userId);
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
@@ -214,7 +214,7 @@ class UserController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Update user
|
* Update user
|
||||||
*/
|
*/
|
||||||
public function update()
|
public function update($params = [])
|
||||||
{
|
{
|
||||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
$this->redirect('/users');
|
$this->redirect('/users');
|
||||||
@@ -224,7 +224,7 @@ class UserController extends Controller
|
|||||||
// CSRF Protection
|
// CSRF Protection
|
||||||
$this->verifyCsrf('/users');
|
$this->verifyCsrf('/users');
|
||||||
|
|
||||||
$userId = (int)($_POST['id'] ?? 0);
|
$userId = $params['id'] ?? 0;
|
||||||
$user = $this->userModel->find($userId);
|
$user = $this->userModel->find($userId);
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
@@ -242,13 +242,13 @@ class UserController extends Controller
|
|||||||
// Validation
|
// Validation
|
||||||
if (empty($email) || empty($fullName)) {
|
if (empty($email) || empty($fullName)) {
|
||||||
$_SESSION['error'] = 'Email and full name are required';
|
$_SESSION['error'] = 'Email and full name are required';
|
||||||
$this->redirect('/users/edit?id=' . $userId);
|
$this->redirect("/users/$userId/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
$_SESSION['error'] = 'Invalid email address';
|
$_SESSION['error'] = 'Invalid email address';
|
||||||
$this->redirect('/users/edit?id=' . $userId);
|
$this->redirect("/users/$userId/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ class UserController extends Controller
|
|||||||
$nameError = \App\Helpers\InputValidator::validateLength($fullName, 255, 'Full name');
|
$nameError = \App\Helpers\InputValidator::validateLength($fullName, 255, 'Full name');
|
||||||
if ($nameError) {
|
if ($nameError) {
|
||||||
$_SESSION['error'] = $nameError;
|
$_SESSION['error'] = $nameError;
|
||||||
$this->redirect('/users/edit?id=' . $userId);
|
$this->redirect("/users/$userId/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ class UserController extends Controller
|
|||||||
$existingUsers = $this->userModel->where('email', $email);
|
$existingUsers = $this->userModel->where('email', $email);
|
||||||
if (!empty($existingUsers) && $existingUsers[0]['id'] != $userId) {
|
if (!empty($existingUsers) && $existingUsers[0]['id'] != $userId) {
|
||||||
$_SESSION['error'] = 'Email already in use by another user';
|
$_SESSION['error'] = 'Email already in use by another user';
|
||||||
$this->redirect('/users/edit?id=' . $userId);
|
$this->redirect("/users/$userId/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +282,7 @@ class UserController extends Controller
|
|||||||
if (!empty($password)) {
|
if (!empty($password)) {
|
||||||
if (strlen($password) < 8) {
|
if (strlen($password) < 8) {
|
||||||
$_SESSION['error'] = 'Password must be at least 8 characters';
|
$_SESSION['error'] = 'Password must be at least 8 characters';
|
||||||
$this->redirect('/users/edit?id=' . $userId);
|
$this->redirect("/users/$userId/edit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->userModel->changePassword($userId, $password);
|
$this->userModel->changePassword($userId, $password);
|
||||||
@@ -293,16 +293,16 @@ class UserController extends Controller
|
|||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$_SESSION['error'] = 'Failed to update user: ' . $e->getMessage();
|
$_SESSION['error'] = 'Failed to update user: ' . $e->getMessage();
|
||||||
$this->redirect('/users/edit?id=' . $userId);
|
$this->redirect("/users/$userId/edit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete user
|
* Delete user
|
||||||
*/
|
*/
|
||||||
public function delete()
|
public function delete($params = [])
|
||||||
{
|
{
|
||||||
$userId = (int)($_GET['id'] ?? 0);
|
$userId = $params['id'] ?? 0;
|
||||||
$user = $this->userModel->find($userId);
|
$user = $this->userModel->find($userId);
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
@@ -342,9 +342,9 @@ class UserController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Toggle user active status
|
* Toggle user active status
|
||||||
*/
|
*/
|
||||||
public function toggleStatus()
|
public function toggleStatus($params = [])
|
||||||
{
|
{
|
||||||
$userId = (int)($_GET['id'] ?? 0);
|
$userId = $params['id'] ?? 0;
|
||||||
$user = $this->userModel->find($userId);
|
$user = $this->userModel->find($userId);
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
|
|||||||
@@ -91,15 +91,22 @@ class Domain extends Model
|
|||||||
/**
|
/**
|
||||||
* Get domain with notification channels
|
* Get domain with notification channels
|
||||||
*/
|
*/
|
||||||
public function getWithChannels(int $id): ?array
|
public function getWithChannels(int $id, ?int $userId = null): ?array
|
||||||
{
|
{
|
||||||
$sql = "SELECT d.*, ng.name as group_name, ng.id as group_id
|
$sql = "SELECT d.*, ng.name as group_name, ng.id as group_id
|
||||||
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
|
||||||
WHERE d.id = ?";
|
WHERE d.id = ?";
|
||||||
|
|
||||||
|
$params = [$id];
|
||||||
|
|
||||||
|
if ($userId) {
|
||||||
|
$sql .= " AND d.user_id = ?";
|
||||||
|
$params[] = $userId;
|
||||||
|
}
|
||||||
|
|
||||||
$stmt = $this->db->prepare($sql);
|
$stmt = $this->db->prepare($sql);
|
||||||
$stmt->execute([$id]);
|
$stmt->execute($params);
|
||||||
$domain = $stmt->fetch();
|
$domain = $stmt->fetch();
|
||||||
|
|
||||||
if (!$domain) {
|
if (!$domain) {
|
||||||
@@ -117,6 +124,25 @@ class Domain extends Model
|
|||||||
return $domain;
|
return $domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find domain by ID with user isolation support
|
||||||
|
*/
|
||||||
|
public function findWithIsolation(int $id, ?int $userId = null): ?array
|
||||||
|
{
|
||||||
|
$sql = "SELECT * FROM domains WHERE id = ?";
|
||||||
|
$params = [$id];
|
||||||
|
|
||||||
|
if ($userId) {
|
||||||
|
$sql .= " AND user_id = ?";
|
||||||
|
$params[] = $userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $this->db->prepare($sql);
|
||||||
|
$stmt->execute($params);
|
||||||
|
$result = $stmt->fetch();
|
||||||
|
return $result ?: null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if domain exists
|
* Check if domain exists
|
||||||
*/
|
*/
|
||||||
@@ -362,19 +388,26 @@ class Domain extends Model
|
|||||||
/**
|
/**
|
||||||
* Search domains for suggestions (quick search)
|
* Search domains for suggestions (quick search)
|
||||||
*/
|
*/
|
||||||
public function searchSuggestions(string $query, int $limit = 5): array
|
public function searchSuggestions(string $query, int $limit = 5, ?int $userId = null): array
|
||||||
{
|
{
|
||||||
$sql = "SELECT d.id, d.domain_name, d.registrar, d.expiration_date, d.status, ng.name as group_name
|
$sql = "SELECT d.id, d.domain_name, d.registrar, d.expiration_date, d.status, ng.name as group_name
|
||||||
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
|
||||||
WHERE d.domain_name LIKE ?
|
WHERE (d.domain_name LIKE ?
|
||||||
OR d.registrar LIKE ?
|
OR d.registrar LIKE ?)";
|
||||||
ORDER BY d.domain_name ASC
|
|
||||||
LIMIT ?";
|
$params = ['%' . $query . '%', '%' . $query . '%'];
|
||||||
|
|
||||||
|
if ($userId) {
|
||||||
|
$sql .= " AND d.user_id = ?";
|
||||||
|
$params[] = $userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql .= " ORDER BY d.domain_name ASC LIMIT ?";
|
||||||
|
$params[] = $limit;
|
||||||
|
|
||||||
$searchTerm = '%' . $query . '%';
|
|
||||||
$stmt = $this->db->prepare($sql);
|
$stmt = $this->db->prepare($sql);
|
||||||
$stmt->execute([$searchTerm, $searchTerm, $limit]);
|
$stmt->execute($params);
|
||||||
return $stmt->fetchAll();
|
return $stmt->fetchAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,10 @@ 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) {
|
if ($userId) {
|
||||||
$group['domains'] = $domainModel->where('notification_group_id', $id, $userId);
|
$sql = "SELECT * FROM domains WHERE notification_group_id = ? AND user_id = ?";
|
||||||
|
$stmt = $this->db->prepare($sql);
|
||||||
|
$stmt->execute([$id, $userId]);
|
||||||
|
$group['domains'] = $stmt->fetchAll();
|
||||||
} else {
|
} else {
|
||||||
$group['domains'] = $domainModel->where('notification_group_id', $id);
|
$group['domains'] = $domainModel->where('notification_group_id', $id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,8 @@ ob_start();
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-6">
|
<div class="p-6">
|
||||||
<form method="POST" action="/groups/update" class="space-y-5">
|
<form method="POST" action="/groups/<?= $group['id'] ?>/update" class="space-y-5">
|
||||||
<?= csrf_field() ?>
|
<?= csrf_field() ?>
|
||||||
<input type="hidden" name="id" value="<?= $group['id'] ?>">
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-5">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||||
<!-- Group Name -->
|
<!-- Group Name -->
|
||||||
@@ -112,12 +111,12 @@ ob_start();
|
|||||||
<i class="fas fa-paper-plane mr-1"></i>
|
<i class="fas fa-paper-plane mr-1"></i>
|
||||||
Test
|
Test
|
||||||
</button>
|
</button>
|
||||||
<a href="/channels/toggle?id=<?= $channel['id'] ?>&group_id=<?= $group['id'] ?>"
|
<a href="/groups/<?= $group['id'] ?>/channels/<?= $channel['id'] ?>/toggle"
|
||||||
class="flex-1 px-3 py-2 bg-yellow-50 text-yellow-700 rounded text-center text-sm hover:bg-yellow-100 transition-colors duration-150">
|
class="flex-1 px-3 py-2 bg-yellow-50 text-yellow-700 rounded text-center text-sm hover:bg-yellow-100 transition-colors duration-150">
|
||||||
<i class="fas fa-<?= $channel['is_active'] ? 'pause' : 'play' ?> mr-1"></i>
|
<i class="fas fa-<?= $channel['is_active'] ? 'pause' : 'play' ?> mr-1"></i>
|
||||||
<?= $channel['is_active'] ? 'Disable' : 'Enable' ?>
|
<?= $channel['is_active'] ? 'Disable' : 'Enable' ?>
|
||||||
</a>
|
</a>
|
||||||
<a href="/channels/delete?id=<?= $channel['id'] ?>&group_id=<?= $group['id'] ?>"
|
<a href="/groups/<?= $group['id'] ?>/channels/<?= $channel['id'] ?>/delete"
|
||||||
class="flex-1 px-3 py-2 bg-red-50 text-red-700 rounded text-center text-sm hover:bg-red-100 transition-colors duration-150"
|
class="flex-1 px-3 py-2 bg-red-50 text-red-700 rounded text-center text-sm hover:bg-red-100 transition-colors duration-150"
|
||||||
onclick="return confirm('Delete this channel?')">
|
onclick="return confirm('Delete this channel?')">
|
||||||
<i class="fas fa-trash mr-1"></i>
|
<i class="fas fa-trash mr-1"></i>
|
||||||
@@ -136,9 +135,8 @@ ob_start();
|
|||||||
Add New Channel
|
Add New Channel
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<form method="POST" action="/channels/add" id="channelForm" class="space-y-5">
|
<form method="POST" action="/groups/<?= $group['id'] ?>/channels" id="channelForm" class="space-y-5">
|
||||||
<?= csrf_field() ?>
|
<?= csrf_field() ?>
|
||||||
<input type="hidden" name="group_id" value="<?= $group['id'] ?>">
|
|
||||||
|
|
||||||
<!-- Channel Type -->
|
<!-- Channel Type -->
|
||||||
<div>
|
<div>
|
||||||
@@ -388,7 +386,7 @@ function toggleChannelFields() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Form validation before submit
|
// Form validation before submit
|
||||||
const addChannelForm = document.querySelector('form[action="/channels/add"]');
|
const addChannelForm = document.querySelector('form[action="/groups/<?= $group['id'] ?>/channels"]');
|
||||||
if (addChannelForm) {
|
if (addChannelForm) {
|
||||||
addChannelForm.addEventListener('submit', function(e) {
|
addChannelForm.addEventListener('submit', function(e) {
|
||||||
const channelType = document.getElementById('channel_type').value;
|
const channelType = document.getElementById('channel_type').value;
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ ob_start();
|
|||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||||
<div class="flex items-center justify-end space-x-2">
|
<div class="flex items-center justify-end space-x-2">
|
||||||
<a href="/groups/edit?id=<?= $group['id'] ?>" class="text-blue-600 hover:text-blue-800" title="Manage">
|
<a href="/groups/<?= $group['id'] ?>/edit" class="text-blue-600 hover:text-blue-800" title="Manage">
|
||||||
<i class="fas fa-cog"></i>
|
<i class="fas fa-cog"></i>
|
||||||
</a>
|
</a>
|
||||||
<?php if (\Core\Auth::isAdmin()): ?>
|
<?php if (\Core\Auth::isAdmin()): ?>
|
||||||
@@ -120,7 +120,7 @@ ob_start();
|
|||||||
<i class="fas fa-exchange-alt"></i>
|
<i class="fas fa-exchange-alt"></i>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<a href="/groups/delete?id=<?= $group['id'] ?>"
|
<a href="/groups/<?= $group['id'] ?>/delete"
|
||||||
class="text-red-600 hover:text-red-800"
|
class="text-red-600 hover:text-red-800"
|
||||||
title="Delete"
|
title="Delete"
|
||||||
onclick="return confirm('Are you sure? Domains will be unassigned from this group.')">
|
onclick="return confirm('Are you sure? Domains will be unassigned from this group.')">
|
||||||
@@ -162,10 +162,10 @@ ob_start();
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex space-x-2">
|
<div class="flex space-x-2">
|
||||||
<a href="/groups/edit?id=<?= $group['id'] ?>" class="flex-1 px-3 py-1.5 bg-blue-50 text-blue-600 rounded text-center text-sm hover:bg-blue-100 transition-colors">
|
<a href="/groups/<?= $group['id'] ?>/edit" class="flex-1 px-3 py-1.5 bg-blue-50 text-blue-600 rounded text-center text-sm hover:bg-blue-100 transition-colors">
|
||||||
<i class="fas fa-cog mr-1"></i> Manage
|
<i class="fas fa-cog mr-1"></i> Manage
|
||||||
</a>
|
</a>
|
||||||
<a href="/groups/delete?id=<?= $group['id'] ?>"
|
<a href="/groups/<?= $group['id'] ?>/delete"
|
||||||
class="flex-1 px-3 py-1.5 bg-red-50 text-red-600 rounded text-center text-sm hover:bg-red-100 transition-colors"
|
class="flex-1 px-3 py-1.5 bg-red-50 text-red-600 rounded text-center text-sm hover:bg-red-100 transition-colors"
|
||||||
onclick="return confirm('Are you sure? Domains will be unassigned from this group.')">
|
onclick="return confirm('Are you sure? Domains will be unassigned from this group.')">
|
||||||
<i class="fas fa-trash mr-1"></i> Delete
|
<i class="fas fa-trash mr-1"></i> Delete
|
||||||
|
|||||||
@@ -258,16 +258,16 @@ $pagination = $pagination ?? [
|
|||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||||
<div class="flex items-center justify-end space-x-2">
|
<div class="flex items-center justify-end space-x-2">
|
||||||
<a href="/users/edit?id=<?= $user['id'] ?>" class="text-blue-600 hover:text-blue-800" title="Edit">
|
<a href="/users/<?= $user['id'] ?>/edit" class="text-blue-600 hover:text-blue-800" title="Edit">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
<?php if ($user['id'] != \Core\Auth::id()): ?>
|
<?php if ($user['id'] != \Core\Auth::id()): ?>
|
||||||
<a href="/users/toggle-status?id=<?= $user['id'] ?>"
|
<a href="/users/<?= $user['id'] ?>/toggle-status"
|
||||||
class="text-orange-600 hover:text-orange-800"
|
class="text-orange-600 hover:text-orange-800"
|
||||||
title="<?= $user['is_active'] ? 'Deactivate' : 'Activate' ?>">
|
title="<?= $user['is_active'] ? 'Deactivate' : 'Activate' ?>">
|
||||||
<i class="fas fa-<?= $user['is_active'] ? 'user-slash' : 'user-check' ?>"></i>
|
<i class="fas fa-<?= $user['is_active'] ? 'user-slash' : 'user-check' ?>"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="/users/delete?id=<?= $user['id'] ?>"
|
<a href="/users/<?= $user['id'] ?>/delete"
|
||||||
class="text-red-600 hover:text-red-800"
|
class="text-red-600 hover:text-red-800"
|
||||||
title="Delete"
|
title="Delete"
|
||||||
onclick="return confirm('Are you sure you want to delete this user?')">
|
onclick="return confirm('Are you sure you want to delete this user?')">
|
||||||
|
|||||||
@@ -84,17 +84,17 @@ $router->post('/domains/{id}/delete', [DomainController::class, 'delete']);
|
|||||||
$router->get('/groups', [NotificationGroupController::class, 'index']);
|
$router->get('/groups', [NotificationGroupController::class, 'index']);
|
||||||
$router->get('/groups/create', [NotificationGroupController::class, 'create']);
|
$router->get('/groups/create', [NotificationGroupController::class, 'create']);
|
||||||
$router->post('/groups/store', [NotificationGroupController::class, 'store']);
|
$router->post('/groups/store', [NotificationGroupController::class, 'store']);
|
||||||
$router->get('/groups/edit', [NotificationGroupController::class, 'edit']);
|
$router->get('/groups/{id}/edit', [NotificationGroupController::class, 'edit']);
|
||||||
$router->post('/groups/update', [NotificationGroupController::class, 'update']);
|
$router->post('/groups/{id}/update', [NotificationGroupController::class, 'update']);
|
||||||
$router->get('/groups/delete', [NotificationGroupController::class, 'delete']);
|
$router->post('/groups/{id}/delete', [NotificationGroupController::class, 'delete']);
|
||||||
$router->post('/groups/bulk-delete', [NotificationGroupController::class, 'bulkDelete']);
|
$router->post('/groups/bulk-delete', [NotificationGroupController::class, 'bulkDelete']);
|
||||||
$router->post('/groups/transfer', [NotificationGroupController::class, 'transfer']);
|
$router->post('/groups/transfer', [NotificationGroupController::class, 'transfer']);
|
||||||
$router->post('/groups/bulk-transfer', [NotificationGroupController::class, 'bulkTransfer']);
|
$router->post('/groups/bulk-transfer', [NotificationGroupController::class, 'bulkTransfer']);
|
||||||
|
|
||||||
// Notification Channels
|
// Notification Channels
|
||||||
$router->post('/channels/add', [NotificationGroupController::class, 'addChannel']);
|
$router->post('/groups/{group_id}/channels', [NotificationGroupController::class, 'addChannel']);
|
||||||
$router->get('/channels/delete', [NotificationGroupController::class, 'deleteChannel']);
|
$router->post('/groups/{group_id}/channels/{id}/delete', [NotificationGroupController::class, 'deleteChannel']);
|
||||||
$router->get('/channels/toggle', [NotificationGroupController::class, 'toggleChannel']);
|
$router->post('/groups/{group_id}/channels/{id}/toggle', [NotificationGroupController::class, 'toggleChannel']);
|
||||||
$router->post('/channels/test', [NotificationGroupController::class, 'testChannel']);
|
$router->post('/channels/test', [NotificationGroupController::class, 'testChannel']);
|
||||||
|
|
||||||
// TLD Registry
|
// TLD Registry
|
||||||
@@ -155,10 +155,10 @@ $router->get('/api/notifications/recent', [NotificationController::class, 'getRe
|
|||||||
$router->get('/users', [UserController::class, 'index']);
|
$router->get('/users', [UserController::class, 'index']);
|
||||||
$router->get('/users/create', [UserController::class, 'create']);
|
$router->get('/users/create', [UserController::class, 'create']);
|
||||||
$router->post('/users/store', [UserController::class, 'store']);
|
$router->post('/users/store', [UserController::class, 'store']);
|
||||||
$router->get('/users/edit', [UserController::class, 'edit']);
|
$router->get('/users/{id}/edit', [UserController::class, 'edit']);
|
||||||
$router->post('/users/update', [UserController::class, 'update']);
|
$router->post('/users/{id}/update', [UserController::class, 'update']);
|
||||||
$router->get('/users/delete', [UserController::class, 'delete']);
|
$router->post('/users/{id}/delete', [UserController::class, 'delete']);
|
||||||
$router->get('/users/toggle-status', [UserController::class, 'toggleStatus']);
|
$router->post('/users/{id}/toggle-status', [UserController::class, 'toggleStatus']);
|
||||||
$router->post('/users/bulk-toggle-status', [UserController::class, 'bulkToggleStatus']);
|
$router->post('/users/bulk-toggle-status', [UserController::class, 'bulkToggleStatus']);
|
||||||
$router->post('/users/bulk-delete', [UserController::class, 'bulkDelete']);
|
$router->post('/users/bulk-delete', [UserController::class, 'bulkDelete']);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user