diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000..6415b91 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,74 @@ +language: "en" + +early_access: false + +reviews: + request_changes_workflow: true + high_level_summary: true + poem: false + review_status: true + collapse_walkthrough: false + path_filters: + # Exclude XML files for manifest and configuration + - "!**/*.xml" + # Exclude language files (translations) + - "!**/language/**/*.ini" + # Exclude asset files that don’t need review + - "!**/*.svg" + - "!**/*.png" + - "!**/*.jpg" + - "!**/*.jpeg" + - "!**/*.gif" + - "!**/*.ico" + # Exclude compiled and minified files + - "!**/*.min.js" + - "!**/*.min.css" + # Exclude SCSS files if they are intermediate and do not need review + - "!**/templates/**/*.scss" + # Exclude libraries and vendor code (third-party dependencies) + - "!**/node_modules/**" + - "!**/vendor/**" + # Exclude build files + - "!**/build/**" + # Exclude configuration files that are environment-specific + - "!**/configuration.php" + path_instructions: + # JavaScript files: front-end interactivity and functionality + - path: "**/*.js" + instructions: | + "Review JavaScript code to ensure: + - Adherence to Google JavaScript style guide. + - Efficient DOM manipulation suitable for Joomla’s frontend. + - Use of Joomla’s core JavaScript libraries where applicable (e.g., jQuery compatibility). + - Best practices for asynchronous requests if AJAX is used." + - path: "**/*.php" + instructions: | + "Review the PHP code for Joomla coding standards compliance, ensuring: + - Code follows Joomla's coding standards, validated using PHPCS with the Joomla standard. + - Adherence to Joomla’s MVC structure for extensions. + - Proper use of Joomla’s built-in functions (e.g., Input, Factory). + - SQL queries use Joomla’s database API to prevent SQL injection. + - Code is well-documented, with clear function and class descriptions." + - path: "**/*.ts" + instructions: | + "Review the JavaScript code for conformity with the Google JavaScript style guide, highlighting any deviations. Ensure that: + - The code adheres to best practices associated with nodejs. + - The code adheres to best practices associated with nestjs framework. + - The code adheres to best practices recommended for performance. + - The code adheres to similar naming conventions for controllers, models, services, methods, variables." + auto_review: + enabled: true + ignore_title_keywords: + - "WIP" + - "DO NOT MERGE" + drafts: false + base_branches: + - "master" + - "dev" + - "j4x" + - "feat/*" + - "feat-*" + - "release-*" + +chat: + auto_reply: true diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..5fd4d21 --- /dev/null +++ b/changelog.md @@ -0,0 +1,17 @@ +# Changelog + +#### Legend + +- Bug Fix (-) +- Feature Addition (+) + +### com_api v4.0.0 + +##### - Bug fixes: +- #194540 - API Rate Limit Exceeded,403 - Issue #122 +- Drop support to accept token as 'Key' parameter from GET/POST request - Tokens should not be accepted via request variables + + +##### + Features Added: +- #175851 - Joomla 4 & PHP 8.0 compatible +- #194541 - Added IP based restrictions to access the APIs, Issue #63 \ No newline at end of file diff --git a/code/admin/assets/css/api.css b/code/admin/assets/css/api.css index 6d63500..b413833 100644 --- a/code/admin/assets/css/api.css +++ b/code/admin/assets/css/api.css @@ -12,3 +12,21 @@ background-image: url(../images/l_logs.png); padding-left:60px!important; } +.api-filter { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} +.js-stools-container-bar-api-filter { + -webkit-margin-start: auto; + margin-inline-start: auto; +} +.js-stools-container-bar-api-filter .btn-toolbar>*+* { + -webkit-margin-start: 8px; + margin-inline-start: 8px; +} +.js-stools-container-bar-api-filter .btn-toolbar>* { + margin: 5px; +} \ No newline at end of file diff --git a/code/admin/config.xml b/code/admin/config.xml index fed8ecc..e1c7239 100755 --- a/code/admin/config.xml +++ b/code/admin/config.xml @@ -3,13 +3,20 @@
+ + + + + - - + + @@ -19,10 +26,12 @@ - - - + + + + true)); @@ -52,8 +53,8 @@ public function saveOrderAjax() $order = $input->post->get('order', array(), 'array'); // Sanitize the input - JArrayHelper::toInteger($pks); - JArrayHelper::toInteger($order); + ArrayHelper::toInteger($pks); + ArrayHelper::toInteger($order); // Get the model $model = $this->getModel(); diff --git a/code/admin/helpers/api.php b/code/admin/helpers/api.php index e9a0eee..43012c5 100644 --- a/code/admin/helpers/api.php +++ b/code/admin/helpers/api.php @@ -8,9 +8,9 @@ // No direct access. defined('_JEXEC') or die(); +use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Factory; diff --git a/code/admin/language/en-GB/en-GB.com_api.ini b/code/admin/language/en-GB/en-GB.com_api.ini index d75df97..52fb7de 100644 --- a/code/admin/language/en-GB/en-GB.com_api.ini +++ b/code/admin/language/en-GB/en-GB.com_api.ini @@ -86,7 +86,7 @@ COM_API_CONFIG_ALLOW_CORS_LBL="Allow Cross Origin Requests" COM_API_CONFIG_ALLOW_CORS_DESC="This configuration enables CORS support. Choose if you wish to enable CORS for only GET method or for all methods." COM_API_CONFIG_CORS_LBL="CORS URLs / Domains" COM_API_CONFIG_CORS_DESC="List of URLs for which to allow CORS requests. Put an asterisk (*) to allow CORS requests from all domains. Alternately put a comma separated list of URL's. Ex. https://techjoomla.com, http://example.com" -COM_API_FORM_LBL_RATE_LIMIT="Hourly Rate Limit for Requests" +COM_API_FORM_LBL_RATE_LIMIT="Rate Limit for Requests" COM_API_FORM_LBL_RATE_LIMIT_DESC="Put a number if you want to limit the number of requests made by a token in an hour to the configured value. An empty or 0 value allows unlimited requests" COM_API_EXCLD_WORDS="Exclude request variables from log" COM_API_EXCLD_WORDS_DESC="A comma separated list of request variables that will be redacted before being added to the API Request log" @@ -97,6 +97,15 @@ COM_API_CONFIG_ALLOW_HEADER_DESC="Add comma separated values for Access-Control- COM_API_FILTER_DESC="Searches in User name, hash, Request URL, POST Data.
uid:number searches logs for a particular user" UNASSIGNED_HASH="No user for this API Key" +COM_API_CONFIG_IPS_DESC="List of IPs for which to allow API access. Put an asterisk (*) to allow API access from all IPs. Alternately put a comma separated list of IPs Ex. 192.168.1.1, 192.168.1.10 or IP Range Ex. 192.168.1.1-192.168.1.10 or CIDR Block Ex. 192.168.1.1/24" +COM_API_CONFIG_IPS_LBL="IP Address/IP Range/CIDR Block" +COM_API_CONFIG_REQ_LT_LBL="Rate Frequency" +COM_API_CONFIG_REQ_LT_DESC="Request limit frequency" +COM_API_CONFIG_RLT_HOUR="Hour" +COM_API_CONFIG_RLT_MINUTE="Minute" +COM_API_CONFIG_RLT_DAY="Day" +COM_API_CONFIG_GET_CORS="Get" + ; Permissions JACTION_MANAGELOGS="Manage Logs" JACTION_MANAGELOGS_DESC="Allows users in this group to manage API logs." diff --git a/code/admin/language/en-GB/en-GB.com_api.sys.ini b/code/admin/language/en-GB/en-GB.com_api.sys.ini index 70b5066..875e132 100644 --- a/code/admin/language/en-GB/en-GB.com_api.sys.ini +++ b/code/admin/language/en-GB/en-GB.com_api.sys.ini @@ -9,6 +9,7 @@ COM_API_XML_DESCRIPTION="Multi" COM_API_TEST_LABEL="Test label" COM_API_TITLE_KEYS="API Keys" +COM_API_TITLE_LOGS="Request Logs" COM_API_SHOW_TABLES_SQL_STATEMENT="SHOW FULL TABLES WHERE tables_in_%s LIKE %s" diff --git a/code/admin/models/fields/createdby.php b/code/admin/models/fields/createdby.php index 6fc3548..1a072c7 100644 --- a/code/admin/models/fields/createdby.php +++ b/code/admin/models/fields/createdby.php @@ -7,7 +7,6 @@ */ defined('JPATH_BASE') or die(); - use Joomla\CMS\Form\FormField; use Joomla\CMS\Factory; diff --git a/code/admin/tables/log.php b/code/admin/tables/log.php index 765abb9..6561339 100644 --- a/code/admin/tables/log.php +++ b/code/admin/tables/log.php @@ -14,6 +14,7 @@ use Joomla\CMS\Factory; use Joomla\Registry\Registry; use Joomla\CMS\Access\Access; +use Joomla\Utilities\ArrayHelper; /** * Log Table class @@ -138,7 +139,7 @@ public function store($updateNulls = false) { if (is_array($this->post_data)) { - $this->post_data = JArrayHelper::toString($this->post_data, '=', '&'); + $this->post_data = ArrayHelper::toString($this->post_data, '=', '&'); } return parent::store($updateNulls = false); diff --git a/code/admin/views/cpanel/view.html.php b/code/admin/views/cpanel/view.html.php index 3bd7bdf..f016609 100644 --- a/code/admin/views/cpanel/view.html.php +++ b/code/admin/views/cpanel/view.html.php @@ -7,9 +7,9 @@ */ defined('_JEXEC') or die(); - -use Joomla\CMS\MVC\View\HtmlView; + use Joomla\CMS\Language\Text; +use Joomla\CMS\Toolbar\ToolbarHelper; /** * Cpanel class @@ -54,7 +54,7 @@ public function display($tpl = null) */ private function generateToolbar() { - JToolBarHelper::title(Text::_('COM_API') . ': ' . Text::_('COM_API_CONTROL_PANEL')); - JToolBarHelper::preferences('com_api', 500, 500); + ToolbarHelper::title(Text::_('COM_API') . ': ' . Text::_('COM_API_CONTROL_PANEL')); + ToolbarHelper::preferences('com_api', 500, 500); } } diff --git a/code/admin/views/key/tmpl/edit.php b/code/admin/views/key/tmpl/edit.php index b9f46b6..e28a88c 100644 --- a/code/admin/views/key/tmpl/edit.php +++ b/code/admin/views/key/tmpl/edit.php @@ -28,36 +28,36 @@ HTMLHelper::_('behavior.keepalive'); // Import CSS -$document = Factory::getDocument(); -$document->addStyleSheet('components/com_api/assets/css/api.css'); -?> +HTMLHelper::_('stylesheet','components/com_api/assets/css/api.css'); - + "); + ?>
diff --git a/code/admin/views/key/view.html.php b/code/admin/views/key/view.html.php index 0cdb813..66e5809 100644 --- a/code/admin/views/key/view.html.php +++ b/code/admin/views/key/view.html.php @@ -14,6 +14,8 @@ use Joomla\CMS\Form\Form; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; +use Joomla\CMS\Toolbar\ToolbarHelper; + /** * View class key form. @@ -95,11 +97,11 @@ protected function addToolbar() if (JVERSION >= '3.0') { - JToolBarHelper::title($viewTitle, 'pencil-2'); + ToolBarHelper::title($viewTitle, 'pencil-2'); } else { - JToolBarHelper::title($viewTitle, 'key.png'); + ToolBarHelper::title($viewTitle, 'key.png'); } if (isset($this->item->checked_out)) @@ -116,28 +118,28 @@ protected function addToolbar() // If not checked out, can save the item. if (! $checkedOut && ($canDo->get('core.edit') || ($canDo->get('core.create')))) { - JToolBarHelper::apply('key.apply', 'JTOOLBAR_APPLY'); - JToolBarHelper::save('key.save', 'JTOOLBAR_SAVE'); + ToolBarHelper::apply('key.apply', 'JTOOLBAR_APPLY'); + ToolBarHelper::save('key.save', 'JTOOLBAR_SAVE'); } if (! $checkedOut && ($canDo->get('core.create'))) { - JToolBarHelper::custom('key.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + ToolBarHelper::custom('key.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); } // If an existing item, can save to a copy. if (! $isNew && $canDo->get('core.create')) { - JToolBarHelper::custom('key.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + ToolBarHelper::custom('key.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); } if (empty($this->item->id)) { - JToolBarHelper::cancel('key.cancel', 'JTOOLBAR_CANCEL'); + ToolBarHelper::cancel('key.cancel', 'JTOOLBAR_CANCEL'); } else { - JToolBarHelper::cancel('key.cancel', 'JTOOLBAR_CLOSE'); + ToolBarHelper::cancel('key.cancel', 'JTOOLBAR_CLOSE'); } } } diff --git a/code/admin/views/keys/tmpl/default.php b/code/admin/views/keys/tmpl/default.php index 0087608..b8ba9f5 100644 --- a/code/admin/views/keys/tmpl/default.php +++ b/code/admin/views/keys/tmpl/default.php @@ -19,10 +19,10 @@ use Joomla\CMS\Language\Text; HTMLHelper::addIncludePath(JPATH_COMPONENT . '/helpers/html'); +HTMLHelper::stylesheet('administrator/components/com_api/assets/css/api.css'); // Import CSS -$document = Factory::getDocument(); -$document->addStyleSheet('components/com_api/assets/css/api.css'); +HTMLHelper::_('stylesheet','components/com_api/assets/css/api.css'); $user = Factory::getUser(); $userId = $user->get('id'); @@ -38,29 +38,26 @@ } $sortFields = $this->getSortFields(); -?> - +'); -extra_sidebar)) { $this->sidebar .= $this->extra_sidebar; @@ -73,30 +70,31 @@ method="post" name="adminForm" id="adminForm"> sidebar)): ?> -
+
sidebar; ?>
-
+
- +
+
+ +
diff --git a/code/admin/views/keys/view.html.php b/code/admin/views/keys/view.html.php index a33e3aa..54ca1fc 100644 --- a/code/admin/views/keys/view.html.php +++ b/code/admin/views/keys/view.html.php @@ -7,13 +7,12 @@ */ // No direct access. -defined('_JEXEC') or die(); - +defined('_JEXEC') or die(); use Joomla\CMS\MVC\View\HtmlView; use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Pagination\Pagination; use Joomla\CMS\Language\Text; -use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Toolbar\ToolbarHelper; /** * View class for list of keys @@ -97,11 +96,11 @@ protected function addToolbar() if (JVERSION >= '3.0') { - JToolBarHelper::title(Text::_('COM_API_TITLE_KEYS'), 'key'); + ToolBarHelper::title(Text::_('COM_API_TITLE_KEYS'), 'key'); } else { - JToolBarHelper::title(Text::_('COM_API_TITLE_KEYS'), 'keys.png'); + ToolBarHelper::title(Text::_('COM_API_TITLE_KEYS'), 'keys.png'); } // Check if the form exists before showing the add/edit buttons @@ -111,12 +110,12 @@ protected function addToolbar() { if ($canDo->get('core.create')) { - JToolBarHelper::addNew('key.add', 'JTOOLBAR_NEW'); + ToolBarHelper::addNew('key.add', 'JTOOLBAR_NEW'); } if ($canDo->get('core.edit') && isset($this->items[0])) { - JToolBarHelper::editList('key.edit', 'JTOOLBAR_EDIT'); + ToolBarHelper::editList('key.edit', 'JTOOLBAR_EDIT'); } } @@ -124,9 +123,9 @@ protected function addToolbar() { if (isset($this->items[0]->state)) { - JToolBarHelper::divider(); - JToolBarHelper::custom('keys.publish', 'publish.png', 'publish_f2.png', 'JTOOLBAR_PUBLISH', true); - JToolBarHelper::custom('keys.unpublish', 'unpublish.png', 'unpublish_f2.png', 'JTOOLBAR_UNPUBLISH', true); + ToolBarHelper::divider(); + ToolBarHelper::custom('keys.publish', 'publish.png', 'publish_f2.png', 'JTOOLBAR_PUBLISH', true); + ToolBarHelper::custom('keys.unpublish', 'unpublish.png', 'unpublish_f2.png', 'JTOOLBAR_UNPUBLISH', true); } } @@ -135,14 +134,14 @@ protected function addToolbar() { if ($canDo->get('core.delete')) { - JToolBarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'keys.delete', 'JTOOLBAR_DELETE'); - JToolBarHelper::divider(); + ToolBarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'keys.delete', 'JTOOLBAR_DELETE'); + ToolBarHelper::divider(); } } if ($canDo->get('core.admin')) { - JToolBarHelper::preferences('com_api'); + ToolBarHelper::preferences('com_api'); } // Set sidebar action - New in 3.0 diff --git a/code/admin/views/logs/tmpl/default.php b/code/admin/views/logs/tmpl/default.php index 607498b..16b6d9f 100644 --- a/code/admin/views/logs/tmpl/default.php +++ b/code/admin/views/logs/tmpl/default.php @@ -19,8 +19,7 @@ HTMLHelper::addIncludePath(JPATH_COMPONENT.'/helpers/html'); // Import CSS -$document = Factory::getDocument(); -$document->addStyleSheet('components/com_api/assets/css/api.css'); +HTMLHelper::_('stylesheet','components/com_api/assets/css/api.css'); $user = Factory::getUser(); $userId = $user->get('id'); @@ -36,29 +35,27 @@ } $sortFields = $this->getSortFields(); -?> - +'); -extra_sidebar)) { $this->sidebar .= $this->extra_sidebar; diff --git a/code/admin/views/logs/view.html.php b/code/admin/views/logs/view.html.php index 3b81ad6..a0bcfc3 100644 --- a/code/admin/views/logs/view.html.php +++ b/code/admin/views/logs/view.html.php @@ -7,13 +7,12 @@ */ // No direct access. -defined('_JEXEC') or die(); - +defined('_JEXEC') or die(); use Joomla\CMS\MVC\View\HtmlView; use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Pagination\Pagination; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; +use Joomla\CMS\Toolbar\ToolbarHelper; /** @@ -94,17 +93,17 @@ protected function addToolbar() if (JVERSION >= '3.0') { - JToolBarHelper::title(Text::_('COM_API_TITLE_LOGS'), 'list'); + ToolBarHelper::title(Text::_('COM_API_TITLE_LOGS'), 'list'); } else { - JToolBarHelper::title(Text::_('COM_API_TITLE_LOGS'), 'logs.png'); + ToolBarHelper::title(Text::_('COM_API_TITLE_LOGS'), 'logs.png'); } if ($canDo->get('core.edit.state')) { // If this component does not use state then show a direct delete button as we can not trash - JToolBarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'logs.delete', 'JTOOLBAR_DELETE'); + ToolBarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'logs.delete', 'JTOOLBAR_DELETE'); } // Show trash and delete for components that uses the state field @@ -112,19 +111,19 @@ protected function addToolbar() { if ($state->get('filter.state') == - 2 && $canDo->get('core.delete')) { - JToolBarHelper::deleteList('', 'logs.delete', 'JTOOLBAR_EMPTY_TRASH'); - JToolBarHelper::divider(); + ToolBarHelper::deleteList('', 'logs.delete', 'JTOOLBAR_EMPTY_TRASH'); + ToolBarHelper::divider(); } elseif ($canDo->get('core.edit.state')) { - JToolBarHelper::trash('logs.trash', 'JTOOLBAR_TRASH'); - JToolBarHelper::divider(); + ToolBarHelper::trash('logs.trash', 'JTOOLBAR_TRASH'); + ToolBarHelper::divider(); } } if ($canDo->get('core.admin')) { - JToolBarHelper::preferences('com_api'); + ToolBarHelper::preferences('com_api'); } if (JVERSION >= '3.0') diff --git a/code/api.xml b/code/api.xml index 1201912..2fb033c 100644 --- a/code/api.xml +++ b/code/api.xml @@ -1,13 +1,13 @@ - + com_api - 11th Oct 2022 + 06th MAR 2023 Copyright (C) 2009 - 2019 Techjoomla. All rights reserved. http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL Techjoomla extensions@techjoomla.com https://techjoomla.com - 3.0.2 + 4.0.0 Multi-purpose REST API framework for Joomla @@ -47,7 +47,9 @@ COM_API COM_API_TITLE_KEYS + COM_API_TITLE_LOGS + access.xml config.xml diff --git a/code/script.api.php b/code/script.api.php index 107470b..45e53c4 100644 --- a/code/script.api.php +++ b/code/script.api.php @@ -254,7 +254,7 @@ private function installSubextensions($parent) } $db->setQuery($sql); - $db->query(); + $db->execute(); // B. Change the ordering of back-end modules to 1 + max ordering if ($folder == 'admin') @@ -272,7 +272,7 @@ private function installSubextensions($parent) ->set($db->qn('ordering') . ' = ' . $db->q($position)) ->where($db->qn('module') . ' = ' . $db->q('mod_' . $module)); $db->setQuery($query); - $db->query(); + $db->execute(); } // C. Link to all pages @@ -364,7 +364,7 @@ private function installSubextensions($parent) ) ->where($db->qn('folder') . ' = ' . $db->q($folder)); $db->setQuery($query); - $db->query(); + $db->execute(); } } } @@ -401,7 +401,7 @@ private function installSubextensions($parent) ->where('( ' . ($db->qn('name') . ' = ' . $db->q($folder)) . ' OR ' . ($db->qn('element') . ' = ' . $db->q($folder)) . ' )') ->where($db->qn('folder') . ' = ' . $db->q($folder)); $db->setQuery($query); - $db->query(); + $db->execute(); } } } diff --git a/code/site/api.php b/code/site/api.php index 9cb22b2..6301213 100755 --- a/code/site/api.php +++ b/code/site/api.php @@ -10,8 +10,8 @@ * and the com_api extension by Brian Edgerton (http://www.edgewebworks.com) */ defined('_JEXEC') or die('Restricted access'); - use Joomla\CMS\Table\Table; + use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; diff --git a/code/site/controllers/http.php b/code/site/controllers/http.php index 5afb853..d29b12b 100644 --- a/code/site/controllers/http.php +++ b/code/site/controllers/http.php @@ -179,7 +179,13 @@ private function resetDocumentType() { foreach (headers_list() as $header) { - header_remove($header); + $headerParts = explode(":", $header); + + if (is_array($headerParts) && isset($headerParts[0])) + { + $headerToRemove = trim($headerParts[0]); + header_remove($headerToRemove); + } } } //JResponse::clearHeaders(); diff --git a/code/site/language/en-GB/en-GB.com_api.ini b/code/site/language/en-GB/en-GB.com_api.ini index 29b2c4b..1a81a62 100644 --- a/code/site/language/en-GB/en-GB.com_api.ini +++ b/code/site/language/en-GB/en-GB.com_api.ini @@ -40,6 +40,7 @@ COM_API_NOT_AUTH_MSG="You are not authorized to view this resource." COM_API_RATE_LIMIT_EXCEEDED="API Rate Limit Exceeded" COM_API_UNAUTHORIZED_REGISTER="You are not authorized to create a key." COM_API_PLUGIN_NO_ENCODER="Content type cannot be encoded." +COM_API_IP_RISRICTED="API Access Is Not Allowed from your IP." COM_API_PUBLISHED="Published" COM_API_UNPUBLISHED="Unpublished" diff --git a/code/site/libraries/authentication.php b/code/site/libraries/authentication.php index b6198f6..99ea2c4 100644 --- a/code/site/libraries/authentication.php +++ b/code/site/libraries/authentication.php @@ -191,7 +191,7 @@ private static function getAuthMethod() { $app = Factory::getApplication(); $key = $app->input->get('key'); - + if (isset($_SERVER['HTTP_X_AUTH']) && $_SERVER['HTTP_X_AUTH']) { $authMethod = $_SERVER['HTTP_X_AUTH']; diff --git a/code/site/libraries/authentication/key.php b/code/site/libraries/authentication/key.php old mode 100755 new mode 100644 index 55faa91..2cd1b00 --- a/code/site/libraries/authentication/key.php +++ b/code/site/libraries/authentication/key.php @@ -31,12 +31,16 @@ class ApiAuthenticationKey extends ApiAuthentication * @return int|boolean User id of the user or false */ public function authenticate() - { - $app = Factory::getApplication(); - $query_token = $app->input->get('key', '', 'STRING'); - $header_token = $this->getBearerToken(); - $key = $header_token ? $header_token : $query_token; - $token = $this->loadTokenByHash($key); + { + $header_token = $this->getBearerToken(); + + if (!$header_token) + { + $app = Factory::getApplication(); + $header_token = $app->input->get('key'); + } + + $token = $this->loadTokenByHash($header_token); if (isset($token->state) && $token->state == 1) { diff --git a/code/site/libraries/authentication/user.php b/code/site/libraries/authentication/user.php index b7c0841..a74ec0e 100755 --- a/code/site/libraries/authentication/user.php +++ b/code/site/libraries/authentication/user.php @@ -13,6 +13,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Authentication\Authentication; use Joomla\CMS\User\User; +use Joomla\CMS\Uri\Uri; class ApiAuthenticationUser extends ApiAuthentication { @@ -29,10 +30,10 @@ public function authenticate() //$username = Factory::getApplication()->input->get( 'username' ); //$password = Factory::getApplication()->input->get( 'password' ); - $user = $this->loadUserByCredentials( $username, $password ); - + $user = $this->loadUserByCredentials( $username, $password ); + // Remove username and password from request for when it gets logged - $uri = Factory::getURI(); + $uri = Uri::getInstance(); $uri->delVar('username'); $uri->delVar('password'); diff --git a/code/site/libraries/plugin.php b/code/site/libraries/plugin.php index 393e68b..89c1a0b 100755 --- a/code/site/libraries/plugin.php +++ b/code/site/libraries/plugin.php @@ -22,6 +22,7 @@ use Joomla\CMS\User\User; use Joomla\Registry\Registry; use Joomla\CMS\Uri\Uri; +use Joomla\Utilities\IpHelper; /** * API_plugin base class @@ -279,8 +280,10 @@ final public function getResourceAccess($resource, $method = 'GET', $returnParam */ final public function fetchResource($resource_name = null) { + $app = Factory::getApplication(); + $this->log(); - + if ($resource_name == null) { $resource_name = $this->get('resource'); @@ -311,6 +314,16 @@ final public function fetchResource($resource_name = null) ApiError::raiseError(403, Text::_('COM_API_RATE_LIMIT_EXCEEDED'), 'APIUnauthorisedException'); } + $ip_address = $app->input->server->get('REMOTE_ADDR', '', 'STRING'); + $ips = $this->params->get('ip_address', ''); + + if ($ips === ""){}else{ + if (!IpHelper::IPinList($ip_address,$ips)) + { + ApiError::raiseError(403, Text::_('COM_API_IP_RISRICTED'), 'APIUnauthorisedException'); + } + } + $this->lastUsed(); if ($resource_obj !== false) @@ -334,7 +347,7 @@ final public function fetchResource($resource_name = null) * * @since 1.0 */ - final private function checkInternally($resource_name) + final function checkInternally($resource_name) { if (! method_exists($this, $resource_name)) { @@ -356,9 +369,8 @@ final private function checkInternally($resource_name) * * @since 1.0 */ - final private function checkRequestLimit() + final function checkRequestLimit() { - $app = Factory::getApplication(); $limit = $this->params->get('request_limit', 0); if ($limit == 0) @@ -366,29 +378,26 @@ final private function checkRequestLimit() return true; } - $hash = $app->input->get('key', '', 'STRING'); - $ip_address = $app->input->server->get('REMOTE_ADDR', '', 'STRING'); - + $hash = APIAuthentication::getBearerToken(); $time = $this->params->get('request_limit_time', 'hour'); - + $now = Factory::getDate(); switch ($time) { - case 'day': - $offset = 60 * 60 * 24; + case 'day': + $now->modify('-1 day'); break; - case 'minute': - $offset = 60; + case 'minute': + $now->modify('-1 minute'); break; case 'hour': - default: - $offset = 60 * 60; + default: + $now->modify('-1 hour'); break; } - $query_time = time() - $offset; - + $query_time = $now->toSql(); $db = Factory::getDBO(); $query = $db->getQuery(true); $query->select('COUNT(*)'); @@ -415,7 +424,7 @@ final private function checkRequestLimit() * * @since 1.0 */ - final private function log() + final function log() { if (! $this->params->get('log_requests')) { @@ -431,7 +440,7 @@ final private function log() $excludes = $params->get('exclude_log'); $raw_post = file_get_contents('php://input'); $redactions = explode(",", $excludes); - $req_url = Uri::current() . '?' . Factory::getURI()->getQuery(); + $req_url = Uri::current() . '?' . Uri::getInstance()->getQuery(); switch ($app->input->server->get('CONTENT_TYPE')) { @@ -459,7 +468,7 @@ final private function log() $table = Table::getInstance('Log', 'ApiTable'); $date = Factory::getDate(); - $table->hash = $app->input->get('key', '', 'STRING'); + $table->hash = APIAuthentication::getBearerToken(); $table->ip_address = $app->input->server->get('REMOTE_ADDR', '', 'STRING'); $table->time = $date->toSql(); $table->request = $req_url; @@ -476,12 +485,11 @@ final private function log() * * @since 1.0 */ - final private function lastUsed() + final function lastUsed() { - $app = Factory::getApplication(); $table = Table::getInstance('Key', 'ApiTable'); - $hash = $app->input->get('key', '', 'STRING'); + $hash = APIAuthentication::getBearerToken(); $table->setLastUsed($hash); }