diff --git a/src/packages/com_mokowaas/admin/src/Controller/DisplayController.php b/src/packages/com_mokowaas/admin/src/Controller/DisplayController.php index 5d2f30ca..c9eaa008 100644 --- a/src/packages/com_mokowaas/admin/src/Controller/DisplayController.php +++ b/src/packages/com_mokowaas/admin/src/Controller/DisplayController.php @@ -63,6 +63,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('mokowaas.plugins.toggle')) { $this->jsonForbidden(); + return; } $app = Factory::getApplication(); @@ -87,6 +88,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('mokowaas.cache')) { $this->jsonForbidden(); + return; } $this->jsonResponse($this->getModel('Dashboard')->clearCache()); @@ -103,6 +105,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('mokowaas.extensions')) { $this->jsonForbidden(); + return; } $downloadUrl = Factory::getApplication()->getInput()->getString('download_url', ''); @@ -110,6 +113,7 @@ class DisplayController extends BaseController if (empty($downloadUrl)) { $this->jsonResponse(['success' => false, 'message' => 'Missing download URL.']); + return; } $this->jsonResponse($this->getModel('Extensions')->installFromUrl($downloadUrl)); @@ -126,6 +130,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('mokowaas.htaccess')) { $this->jsonForbidden(); + return; } $app = Factory::getApplication(); @@ -157,6 +162,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('mokowaas.htaccess')) { $this->jsonForbidden(); + return; } $model = $this->getModel('Htaccess'); @@ -184,6 +190,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('mokowaas.tickets.create')) { $this->jsonForbidden(); + return; } $input = Factory::getApplication()->getInput(); @@ -203,6 +210,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('mokowaas.tickets')) { $this->jsonForbidden(); + return; } $input = Factory::getApplication()->getInput(); @@ -221,6 +229,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('mokowaas.tickets')) { $this->jsonForbidden(); + return; } $input = Factory::getApplication()->getInput(); @@ -385,9 +394,12 @@ class DisplayController extends BaseController public function exportSettings() { + Session::checkToken('get') or die(Text::_('JINVALID_TOKEN')); + if (!$this->checkAcl('core.admin')) { $this->jsonForbidden(); + return; } $db = Factory::getDbo(); @@ -431,6 +443,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('core.admin')) { $this->jsonForbidden(); + return; } $json = Factory::getApplication()->getInput()->getRaw('settings_json', ''); @@ -439,6 +452,7 @@ class DisplayController extends BaseController if (empty($data) || empty($data['plugins'])) { $this->jsonResponse(['success' => false, 'message' => 'Invalid settings JSON.']); + return; } $db = Factory::getDbo(); @@ -488,6 +502,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('core.admin')) { $this->jsonForbidden(); + return; } $days = Factory::getApplication()->getInput()->getInt('days', 30); @@ -503,6 +518,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('core.admin')) { $this->jsonForbidden(); + return; } $ip = Factory::getApplication()->getInput()->getString('ip', ''); @@ -522,6 +538,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('core.admin')) { $this->jsonForbidden(); + return; } $input = Factory::getApplication()->getInput(); @@ -540,6 +557,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('core.admin')) { $this->jsonForbidden(); + return; } $model = new \Moko\Component\MokoWaaS\Administrator\Model\PrivacyModel(); @@ -560,6 +578,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('mokowaas.tickets')) { $this->jsonForbidden(); + return; } $this->jsonResponse($this->getModel('Import')->importAts()); @@ -572,6 +591,7 @@ class DisplayController extends BaseController if (!$this->checkAcl('core.admin')) { $this->jsonForbidden(); + return; } $this->jsonResponse($this->getModel('Import')->importAdminTools()); @@ -614,5 +634,6 @@ class DisplayController extends BaseController private function jsonForbidden(): void { $this->jsonResponse(['success' => false, 'message' => Text::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN')]); +return; } } diff --git a/src/packages/com_mokowaas/admin/src/Model/PrivacyModel.php b/src/packages/com_mokowaas/admin/src/Model/PrivacyModel.php index 9bb53564..3f91e084 100644 --- a/src/packages/com_mokowaas/admin/src/Model/PrivacyModel.php +++ b/src/packages/com_mokowaas/admin/src/Model/PrivacyModel.php @@ -321,6 +321,28 @@ class PrivacyModel extends BaseDatabaseModel } catch (\Throwable $e) {} + // Clear Joomla user profile fields (#7) + try + { + $db->setQuery( + $db->getQuery(true) + ->delete($db->quoteName('#__user_profiles')) + ->where($db->quoteName('user_id') . ' = ' . $userId) + )->execute(); + } + catch (\Throwable $e) {} + + // Clear contact details if linked + try + { + $db->setQuery( + $db->getQuery(true) + ->delete($db->quoteName('#__contact_details')) + ->where($db->quoteName('user_id') . ' = ' . $userId) + )->execute(); + } + catch (\Throwable $e) {} + // Log the anonymization $this->logConsent($userId, 'account_anonymized', 'granted'); diff --git a/src/packages/com_mokowaas/admin/src/Model/TicketsModel.php b/src/packages/com_mokowaas/admin/src/Model/TicketsModel.php index 47c0ea5c..34bfc928 100644 --- a/src/packages/com_mokowaas/admin/src/Model/TicketsModel.php +++ b/src/packages/com_mokowaas/admin/src/Model/TicketsModel.php @@ -207,15 +207,22 @@ class TicketsModel extends BaseDatabaseModel $db->insertObject('#__mokowaas_ticket_replies', $reply, 'id'); - // Mark SLA as responded if first staff reply - $db->setQuery( - $db->getQuery(true) - ->update($db->quoteName('#__mokowaas_tickets')) - ->set($db->quoteName('modified') . ' = ' . $db->quote($now)) - ->set($db->quoteName('sla_responded') . ' = 1') - ->where($db->quoteName('id') . ' = ' . $ticketId) - ->where($db->quoteName('sla_responded') . ' = 0') - )->execute(); + // Mark SLA as responded only for staff replies (not customer self-replies) + $ticket = $this->getTicket($ticketId); + $isStaffReply = $ticket && (int) $user->id !== (int) $ticket->created_by; + + $updateQuery = $db->getQuery(true) + ->update($db->quoteName('#__mokowaas_tickets')) + ->set($db->quoteName('modified') . ' = ' . $db->quote($now)) + ->where($db->quoteName('id') . ' = ' . $ticketId); + + if ($isStaffReply) + { + $updateQuery->set($db->quoteName('sla_responded') . ' = 1') + ->where($db->quoteName('sla_responded') . ' = 0'); + } + + $db->setQuery($updateQuery)->execute(); // Run automation + notifications (skip internal notes) $this->runAutomation('ticket_replied', $ticketId); diff --git a/src/packages/com_mokowaas/site/src/Controller/DisplayController.php b/src/packages/com_mokowaas/site/src/Controller/DisplayController.php index 4cecaf97..1018e9eb 100644 --- a/src/packages/com_mokowaas/site/src/Controller/DisplayController.php +++ b/src/packages/com_mokowaas/site/src/Controller/DisplayController.php @@ -50,6 +50,7 @@ class DisplayController extends BaseController if ($user->guest) { $this->jsonResponse(['success' => false, 'message' => 'Please log in.']); + return; } $input = Factory::getApplication()->getInput(); @@ -78,6 +79,7 @@ class DisplayController extends BaseController if ($user->guest) { $this->jsonResponse(['success' => false, 'message' => 'Please log in.']); + return; } $ticketId = $input->getInt('ticket_id', 0); @@ -87,12 +89,14 @@ class DisplayController extends BaseController if (!$ticket) { $this->jsonResponse(['success' => false, 'message' => 'Ticket not found.']); + return; } // Customers can only reply to their own tickets; staff can reply to any if ((int) $ticket->created_by !== $user->id && !$this->isStaff($user)) { $this->jsonResponse(['success' => false, 'message' => 'Access denied.']); + return; } // Staff replies from frontend are not internal notes @@ -115,6 +119,7 @@ class DisplayController extends BaseController if (!$this->isStaff($user)) { $this->jsonResponse(['success' => false, 'message' => 'Access denied.']); + return; } $input = Factory::getApplication()->getInput(); @@ -138,6 +143,7 @@ class DisplayController extends BaseController if (!$user->authorise('mokowaas.tickets.assign', 'com_mokowaas')) { $this->jsonResponse(['success' => false, 'message' => 'Access denied.']); + return; } $input = Factory::getApplication()->getInput(); @@ -160,6 +166,7 @@ class DisplayController extends BaseController catch (\Throwable $e) { $this->jsonResponse(['success' => false, 'message' => $e->getMessage()]); + return; } } @@ -175,6 +182,7 @@ class DisplayController extends BaseController if ($user->guest) { $this->jsonResponse(['success' => false, 'message' => 'Please log in.']); + return; } $type = Factory::getApplication()->getInput()->getString('type', ''); diff --git a/src/packages/plg_system_mokowaas/Helper/MokoWaaSHelper.php b/src/packages/plg_system_mokowaas/Helper/MokoWaaSHelper.php index 0cd42177..3e533f84 100644 --- a/src/packages/plg_system_mokowaas/Helper/MokoWaaSHelper.php +++ b/src/packages/plg_system_mokowaas/Helper/MokoWaaSHelper.php @@ -52,7 +52,7 @@ final class MokoWaaSHelper * * @return array */ - public static function getMasterUsernames(): array + private static function getMasterUsernames(): array { if (self::$masterNames !== null) { diff --git a/src/packages/plg_system_mokowaas_firewall/src/Extension/Firewall.php b/src/packages/plg_system_mokowaas_firewall/src/Extension/Firewall.php index f2aed66f..949e0998 100644 --- a/src/packages/plg_system_mokowaas_firewall/src/Extension/Firewall.php +++ b/src/packages/plg_system_mokowaas_firewall/src/Extension/Firewall.php @@ -503,7 +503,8 @@ class Firewall extends CMSPlugin implements SubscriberInterface, BootableExtensi } $value = (string) $value; - $decoded = urldecode($value); + // Double-decode to catch %25xx encoding tricks + $decoded = urldecode(urldecode($value)); if (preg_match($pattern, $value) || preg_match($pattern, $decoded)) {