From 59b47da7e5a9e9fafa23e2485740f89beb529f1f Mon Sep 17 00:00:00 2001 From: Matej Kminek Date: Wed, 20 Nov 2019 22:42:40 +0100 Subject: [PATCH 1/6] Specify last_output as TEXT field - to prevent DB failure when output is actually greater than 255 chars. This issue prohibited updating server database, therefore sending emails over and over --- src/psm/Util/Install/Installer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index 633b8b99..7420c367 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -253,7 +253,7 @@ class Installer { `website_password` varchar(255) DEFAULT NULL, `last_error` varchar(255) DEFAULT NULL, `last_error_output` varchar(255) DEFAULT NULL, - `last_output` varchar(255) DEFAULT NULL, + `last_output` TEXT NULL DEFAULT NULL, PRIMARY KEY (`server_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX.'servers_uptime' => "CREATE TABLE IF NOT EXISTS `".PSM_DB_PREFIX."servers_uptime` ( From a5312265f8ce267451a52a81572aff7b0512bc24 Mon Sep 17 00:00:00 2001 From: Matej Kminek Date: Wed, 20 Nov 2019 23:03:58 +0100 Subject: [PATCH 2/6] Use native php function to load information about curl response. Obtain from it HTTP status code, so get rid of regexing. Also used for rediret checks. Better usability in the future. Removed logging of status message - some HTTP servers (like Tomcat, from version 9 I guess) do not return status message at all (and its not such a big deal to log it) --- src/includes/functions.inc.php | 8 +-- src/psm/Util/Server/Updater/StatusUpdater.php | 49 ++++++++----------- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index ebadaa30..15b44abf 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -351,7 +351,7 @@ function psm_parse_msg($status, $type, $vars, $combi = false) { * @param string|bool $website_password Password website * @param string|null $request_method Request method like GET, POST etc. * @param string|null $post_field POST data - * @return string cURL result + * @return array ["result" => cURL result, "info" => cURL info array] */ function psm_curl_get($href, $header = false, $body = true, $timeout = null, $add_agent = true, $website_username = false, $website_password = false, $request_method = null, $post_field = null) { ($timeout === null || $timeout > 0) ? PSM_CURL_TIMEOUT : intval($timeout); @@ -401,6 +401,8 @@ function psm_curl_get($href, $header = false, $body = true, $timeout = null, $ad } $result = curl_exec($ch); + $info = curl_getinfo($ch); + curl_close($ch); if(defined('PSM_DEBUG') && PSM_DEBUG === true && psm_is_cli()) { @@ -409,7 +411,7 @@ function psm_curl_get($href, $header = false, $body = true, $timeout = null, $ad echo PHP_EOL.'==============END cURL Resul for: '.$href.'==========================================='.PHP_EOL; } - return $result; + return ["result" => $result, "info" => $info]; } /** @@ -477,7 +479,7 @@ function psm_update_available() { // been more than a week since update, lets go // update last check date psm_update_conf('last_update_check', time()); - $latest = psm_curl_get(PSM_UPDATE_URL); + $latest = psm_curl_get(PSM_UPDATE_URL)["result"]; // extract latest version from Github. preg_match('/"tag_name":"[v](([\d][.][\d][.][\d])(-?\w*))"/', $latest, $latest); // add latest version to database diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 2b1f26b8..2ee3faf8 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -246,30 +246,22 @@ class StatusUpdater { $this->server['request_method'], $this->server['post_field'] ); - $this->header = $curl_result; + $this->header = $curl_result["result"]; + $code = $curl_result["info"]["http_code"]; + $redirectUrl = $curl_result["info"]["redirect_url"]; $this->rtime = (microtime(true) - $starttime); - // the first line would be the status code.. - $status_code = strtok($curl_result, "\r\n"); - // keep it general - // $code[2][0] = status code - // $code[3][0] = name of status code - $code_matches = array(); - preg_match_all("/[A-Z]{2,5}\/\d(\.\d)?\s(\d{3})\s?(.*)/", $status_code, $code_matches); - - if(empty($code_matches[0])) { + if(empty($code)) { // somehow we dont have a proper response. $this->error = 'TIMEOUT ERROR: no response from server'; $result = false; } else { - $code = $code_matches[2][0]; - $msg = $code_matches[3][0]; $allow_http_status = explode("|", $this->server['allow_http_status']); // All status codes starting with a 4 or higher mean trouble! if (substr($code, 0, 1) >= '4' && !in_array($code ,$allow_http_status)) { - $this->error = "HTTP STATUS ERROR: ".$code.' '.$msg; + $this->error = "HTTP STATUS ERROR: ".$code; $result = false; } else { $result = true; @@ -278,7 +270,7 @@ class StatusUpdater { if ($this->server['pattern'] != '') { // Check to see if the body should not contain specified pattern // Check to see if the pattern was [not] found. - if (($this->server['pattern_online'] == 'yes') == !preg_match("/{$this->server['pattern']}/i", $curl_result)) { + if (($this->server['pattern_online'] == 'yes') == !preg_match("/{$this->server['pattern']}/i", $this->header)) { $this->error = "TEXT ERROR : Pattern '{$this->server['pattern']}' ". ($this->server['pattern_online'] == 'yes' ? 'not' : 'was'). ' found.'; @@ -286,24 +278,23 @@ class StatusUpdater { } } - // Check if the website redirects to another domain - if ($this->server['redirect_check'] == 'bad'){ - $location_matches = array(); - preg_match('/([Ll]ocation: )(https*:\/\/)(www.)?([a-zA-Z.:0-9]*)([\/][[:alnum:][:punct:]]*)/', $curl_result, $location_matches); - if(!empty($location_matches)) { - $ip_matches = array(); - preg_match('/(https*:\/\/)(www.)?([a-zA-Z.:0-9]*)([\/][[:alnum:][:punct:]]*)?/', $this->server['ip'], $ip_matches); - if (strtolower($location_matches[4]) !== strtolower($ip_matches[3])) { - $this->error = "The IP/URL redirects to another domain."; - $result = false; - } - } - } + // Check if the website redirects to another domain + if ($this->server['redirect_check'] == 'bad') { + if (!empty($redirectUrl)) { + $redirectPieces = parse_url($redirectUrl); + $ipPieces = parse_url($this->server['ip']); + + if (strtolower($redirectPieces['host']) !== strtolower($ipPieces['host'])) { + $this->error = "The IP/URL redirects to another domain."; + $result = false; + } + } + } - // Should we check a header ? + // Should we check a header ? if ($this->server['header_name'] != '' && $this->server['header_value'] != '') { $header_flag = false; - $header_text = substr($curl_result, 0, strpos($curl_result, "\r\n\r\n")); // Only get the header text if the result also includes the body + $header_text = substr($this->header, 0, strpos($this->header, "\r\n\r\n")); // Only get the header text if the result also includes the body foreach (explode("\r\n", $header_text) as $i => $line) { if ($i === 0 || strpos($line, ':') == false) { continue; // We skip the status code & other non-header lines. Needed for proxy or redirects From b7c1c4a29ec2a3dcb9ceb5dd8e11629281c6dc81 Mon Sep 17 00:00:00 2001 From: Matej Kminek Date: Sun, 24 Nov 2019 21:48:19 +0100 Subject: [PATCH 3/6] API interface and first basic API request: https://phpservermonitor.com/api/?&mod=server_status&key=123456789 https://phpservermonitor.com/api/?&mod=server_status&key=123456789&action=detail&id=14 Created api folder and booter. User database row enhanced by api_auth field, to store user hashcode. Updated router, to hold information whether this is an api request and if is, load specific controller. Then use standard executeMethod to get proper JsonResponse. First implemented API to get list of servers / one server detail --- api/index.php | 43 ++ .../Server/Controller/ApiStatusController.php | 87 ++++ src/psm/Module/Server/ServerModule.php | 1 + src/psm/Router.php | 376 ++++++++++-------- src/psm/Service/User.php | 38 ++ src/psm/Util/Install/Installer.php | 1 + 6 files changed, 381 insertions(+), 165 deletions(-) create mode 100644 api/index.php create mode 100644 src/psm/Module/Server/Controller/ApiStatusController.php diff --git a/api/index.php b/api/index.php new file mode 100644 index 00000000..ac5333bb --- /dev/null +++ b/api/index.php @@ -0,0 +1,43 @@ +. + * + * @package phpservermon + * @author Pepijn Over + * @copyright Copyright (c) 2008-2017 Pepijn Over + * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 + * @version Release: @package_version@ + * @link http://www.phpservermonitor.org/ + **/ + +require __DIR__.'/../src/bootstrap.php'; + +$router->setIsApi(true); + +psm_no_cache(); + +$mod = psm_GET('mod'); + +try { + $router->run($mod); +} catch (\InvalidArgumentException $e) { + // invalid module, try the default one + // it that somehow also doesnt exist, we have a bit of an issue + // and we really have no reason catch it + $router->run(PSM_MODULE_DEFAULT); +} \ No newline at end of file diff --git a/src/psm/Module/Server/Controller/ApiStatusController.php b/src/psm/Module/Server/Controller/ApiStatusController.php new file mode 100644 index 00000000..cf910623 --- /dev/null +++ b/src/psm/Module/Server/Controller/ApiStatusController.php @@ -0,0 +1,87 @@ +. + * + * @package phpservermon + * @author Pepijn Over + * @copyright Copyright (c) 2008-2017 Pepijn Over + * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 + * @version Release: @package_version@ + * @link http://www.phpservermonitor.org/ + * */ +/** + * Server module. List all servers, return list as JSON. + */ + +namespace psm\Module\Server\Controller; + +use psm\Service\Database; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; +use Twig_Environment; + +/** + * Description of ApiStatusController + * + * @author Matej Kminek , 24. 11. 2019 + */ +class ApiStatusController extends AbstractServerController { + + /** + * Current server id + * @var int|\PDOStatement $server_id + */ + protected $server_id; + + function __construct(Database $db, Twig_Environment $twig) { + parent::__construct($db, $twig); + + $this->server_id = isset($_GET['id']) ? intval($_GET['id']) : 0; + + $this->setActions(array('detail', 'list'), 'list'); + } + + /** + * Prepare the view template + */ + protected function executeList() { + $server = $this->getServers(); + + return new JsonResponse($server, Response::HTTP_OK); + } + + /** + * Prepare the view template + */ + protected function executeDetail() { + var_dump($this->server_id); + if(empty($this->server_id)){ + return new JsonResponse("Not found", Response::HTTP_NOT_FOUND); + } + + $server = $this->getServers($this->server_id); + + if (empty($server)) { + return $this->runAction('index'); + } + + return new JsonResponse($server, Response::HTTP_OK); + } + +} diff --git a/src/psm/Module/Server/ServerModule.php b/src/psm/Module/Server/ServerModule.php index 44a5b06e..d78a156a 100644 --- a/src/psm/Module/Server/ServerModule.php +++ b/src/psm/Module/Server/ServerModule.php @@ -43,6 +43,7 @@ class ServerModule implements ModuleInterface { 'log' => __NAMESPACE__.'\Controller\LogController', 'status' => __NAMESPACE__.'\Controller\StatusController', 'update' => __NAMESPACE__.'\Controller\UpdateController', + 'api.status' => __NAMESPACE__.'\Controller\ApiStatusController', ); } diff --git a/src/psm/Router.php b/src/psm/Router.php index 140d95fb..c732aaee 100644 --- a/src/psm/Router.php +++ b/src/psm/Router.php @@ -44,194 +44,240 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; */ class Router { - /** - * Service container - * @var \Symfony\Component\DependencyInjection\ContainerBuilder $container - */ - protected $container; + /** + * Service container + * @var \Symfony\Component\DependencyInjection\ContainerBuilder $container + */ + protected $container; - public function __construct() { - $this->container = $this->buildServiceContainer(); + /** + * Indication whether this request comes from API + * @var boolean + */ + private $isApi = false; - $mods = $this->container->getParameter('modules'); + public function __construct() { + $this->container = $this->buildServiceContainer(); - foreach ($mods as $mod) { - $mod_loader = $this->container->get($mod); - $mod_loader->load($this->container); - } - } + $mods = $this->container->getParameter('modules'); - /** - * Run a module. - * - * The $mod param is in the format $module_$controller. - * If the "_$controller" part is omitted, it will attempt to load - * the controller with the same name as the module. - * - * @param string $mod - * @throws \InvalidArgumentException - * @throws \LogicException - */ - public function run($mod) { - if (strpos($mod, '_') !== false) { - list($mod, $controller) = explode('_', $mod); - } else { - $controller = $mod; - } - $this->buildTwigEnvironment(); + foreach ($mods as $mod) { + $mod_loader = $this->container->get($mod); + $mod_loader->load($this->container); + } + } - $controller = $this->getController($mod, $controller); - $action = null; + /** + * Run a module. + * + * The $mod param is in the format $module_$controller. + * If the "_$controller" part is omitted, it will attempt to load + * the controller with the same name as the module. + * + * @param string $mod + * @throws \InvalidArgumentException + * @throws \LogicException + */ + public function run($mod) { + if (strpos($mod, '_') !== false) { + list($mod, $controller) = explode('_', $mod); + } else { + $controller = $mod; + } + $this->buildTwigEnvironment(); - try { - $this->validateRequest($controller); - } catch (\InvalidArgumentException $ex) { - switch ($ex->getMessage()) { - case 'login_required': - $controller = $this->getController('user', 'login'); - break; - case 'invalid_csrf_token': - case 'invalid_user_level': - default: - $controller = $this->getController('error'); - $action = '401'; - break; - } - } + $controller = $this->isApi ? $this->getController($mod, $controller, true) : $this->getController($mod, $controller); + $action = null; - $response = $controller->run($action); + try { + $this->validateRequest($controller); + } catch (\InvalidArgumentException $ex) { + switch ($ex->getMessage()) { + case 'invalid_api_key': + $controller = $this->getController('error'); + $action = '403'; + break; + case 'login_required': + $controller = $this->getController('user', 'login'); + break; + case 'invalid_csrf_token': + case 'invalid_user_level': + default: + $controller = $this->getController('error'); + $action = '401'; + break; + } + } - if (!($response instanceof Response)) { - throw new \LogicException('Controller did not return a Response object.'); - } - $response->send(); - } + $response = $controller->run($action); - /** - * Get an instance of the requested controller. - * @param string $module_id - * @param string $controller_id if NULL, default controller will be used - * @return \psm\Module\ControllerInterface - * @throws \InvalidArgumentException - */ - public function getController($module_id, $controller_id = null) { - if ($controller_id === null) { - // by default, we use the controller with the same id as the module. - $controller_id = $module_id; - } + if (!($response instanceof Response)) { + throw new \LogicException('Controller did not return a Response object.'); + } + $response->send(); + } + + /** + * Get an instance of the requested controller. + * @param string $module_id + * @param string $controller_id if NULL, default controller will be used + * @return \psm\Module\ControllerInterface + * @throws \InvalidArgumentException + */ + public function getController($module_id, $controller_id = null, $isApi = false) { + if ($controller_id === null) { + // by default, we use the controller with the same id as the module. + $controller_id = $module_id; + } + + if ($isApi) { + // if this is an api request, serve api.controller + $controller_id = "api." . $controller_id; + } $module = $this->container->get('module.'.$module_id); - $controllers = $module->getControllers(); - if (!isset($controllers[$controller_id]) || !class_exists($controllers[$controller_id])) { + $controllers = $module->getControllers(); + if (!isset($controllers[$controller_id]) || !class_exists($controllers[$controller_id])) { throw new \InvalidArgumentException('Controller "'.$controller_id.'" is not registered or does not exist.'); - } - $controller = new $controllers[$controller_id]( - $this->container->get('db'), - $this->container->get('twig') - ); + } + $controller = new $controllers[$controller_id]( + $this->container->get('db'), + $this->container->get('twig') + ); - if (!$controller instanceof \psm\Module\ControllerInterface) { - throw new \Exception('Controller does not implement ControllerInterface'); - } - $controller->setContainer($this->container); + if (!$controller instanceof \psm\Module\ControllerInterface) { + throw new \Exception('Controller does not implement ControllerInterface'); + } + $controller->setContainer($this->container); - return $controller; - } + return $controller; + } - /** - * Get service from container - * @param string $id - * @return mixed FALSE on failure, service otherwise - * @throws \InvalidArgumentException - */ - public function getService($id) { - return $this->container->get($id); - } + /** + * Get service from container + * @param string $id + * @return mixed FALSE on failure, service otherwise + * @throws \InvalidArgumentException + */ + public function getService($id) { + return $this->container->get($id); + } - /** - * Validate requets before heading to a controller - * @param \psm\Module\ControllerInterface $controller - * @throws \InvalidArgumentException - */ - protected function validateRequest(\psm\Module\ControllerInterface $controller) { - $request = Request::createFromGlobals(); + /** + * Validate requets before heading to a controller + * @param \psm\Module\ControllerInterface $controller + * @throws \InvalidArgumentException + */ + protected function validateRequest(\psm\Module\ControllerInterface $controller) { + $request = Request::createFromGlobals(); + + if($this->isApi){ + return $this->validateApiRequest($controller, $request); + } - if ($request->getMethod() == 'POST') { - // require CSRF token for all POST calls - $session = $this->container->get('user')->getSession(); - $token_in = $request->request->get('csrf', ''); - $csrf_key = $controller->getCSRFKey(); + if ($request->getMethod() == 'POST') { + // require CSRF token for all POST calls + $session = $this->container->get('user')->getSession(); + $token_in = $request->request->get('csrf', ''); + $csrf_key = $controller->getCSRFKey(); - if (empty($csrf_key)) { - if (!hash_equals($session->get('csrf_token'), $token_in)) { - throw new \InvalidArgumentException('invalid_csrf_token'); - } - } else { - if (!hash_equals( - hash_hmac('sha256', $csrf_key, $session->get('csrf_token2')), - $token_in - )) { - throw new \InvalidArgumentException('invalid_csrf_token'); - } - } - } + if (empty($csrf_key)) { + if (!hash_equals($session->get('csrf_token'), $token_in)) { + throw new \InvalidArgumentException('invalid_csrf_token'); + } + } else { + if (!hash_equals( + hash_hmac('sha256', $csrf_key, $session->get('csrf_token2')), + $token_in + )) { + throw new \InvalidArgumentException('invalid_csrf_token'); + } + } + } - // get min required level for this controller and make sure the user matches - $min_lvl = $controller->getMinUserLevelRequired(); + // get min required level for this controller and make sure the user matches + $min_lvl = $controller->getMinUserLevelRequired(); - if ($min_lvl < PSM_USER_ANONYMOUS) { - // if user is not logged in, load login module - if (!$this->container->get('user')->isUserLoggedIn()) { - throw new \InvalidArgumentException('login_required'); - } elseif ($this->container->get('user')->getUserLevel() > $min_lvl) { - throw new \InvalidArgumentException('invalid_user_level'); - } - } - } + if ($min_lvl < PSM_USER_ANONYMOUS) { + // if user is not logged in, load login module + if (!$this->container->get('user')->isUserLoggedIn()) { + throw new \InvalidArgumentException('login_required'); + } elseif ($this->container->get('user')->getUserLevel() > $min_lvl) { + throw new \InvalidArgumentException('invalid_user_level'); + } + } + } + + private function validateApiRequest(\psm\Module\ControllerInterface $controller, Request $request) { + $result = $controller->getUser()->loginWithApiKey($request->query->get("key")); + + if (!$result) { + throw new \InvalidArgumentException('invalid_api_key'); + } + + // get min required level for this controller and make sure the user matches + $min_lvl = $controller->getMinUserLevelRequired(); + if ($min_lvl < PSM_USER_ANONYMOUS) { + // if user is not logged in, load login module + if ($this->container->get('user')->getUserLevel() > $min_lvl) { + throw new \InvalidArgumentException('invalid_user_level'); + } + } + } - /** - * Build a new service container - * @return \Symfony\Component\DependencyInjection\ContainerBuilder - * @throws \InvalidArgumentException - */ - protected function buildServiceContainer() { - $builder = new ContainerBuilder(); - $loader = new XmlFileLoader($builder, new FileLocator(PSM_PATH_CONFIG)); - $loader->load('services.xml'); + /** + * Build a new service container + * @return \Symfony\Component\DependencyInjection\ContainerBuilder + * @throws \InvalidArgumentException + */ + protected function buildServiceContainer() { + $builder = new ContainerBuilder(); + $loader = new XmlFileLoader($builder, new FileLocator(PSM_PATH_CONFIG)); + $loader->load('services.xml'); - return $builder; - } + return $builder; + } - /** - * Prepare twig environment - * @return \Twig_Environment - */ - protected function buildTwigEnvironment() { - $twig = $this->container->get('twig'); - $session = $this->container->get('user')->getSession(); - if (!$session->has('csrf_token')) { - $session->set('csrf_token', bin2hex(random_bytes(32))); - } - if (!$session->has('csrf_token2')) { - $session->set('csrf_token2', random_bytes(32)); - } + /** + * Prepare twig environment + * @return \Twig_Environment + */ + protected function buildTwigEnvironment() { + $twig = $this->container->get('twig'); + $session = $this->container->get('user')->getSession(); + if (!$session->has('csrf_token')) { + $session->set('csrf_token', bin2hex(random_bytes(32))); + } + if (!$session->has('csrf_token2')) { + $session->set('csrf_token2', random_bytes(32)); + } - $twig->addFunction( - new \Twig_SimpleFunction( - 'csrf_token', - function($lock_to = null) use ($session) { - if (empty($lock_to)) { - return $session->get('csrf_token'); - } - return hash_hmac('sha256', $lock_to, $session->get('csrf_token2')); - } - ) - ); - $twig->addGlobal('direction_current', psm_get_lang('locale_dir')); - $twig->addGlobal('language_current', psm_get_lang('locale_tag')); - $twig->addGlobal('language', psm_get_lang('locale')[1]); + $twig->addFunction( + new \Twig_SimpleFunction( + 'csrf_token', + function($lock_to = null) use ($session) { + if (empty($lock_to)) { + return $session->get('csrf_token'); + } + return hash_hmac('sha256', $lock_to, $session->get('csrf_token2')); + } + ) + ); + $twig->addGlobal('direction_current', psm_get_lang('locale_dir')); + $twig->addGlobal('language_current', psm_get_lang('locale_tag')); + $twig->addGlobal('language', psm_get_lang('locale')[1]); - return $twig; - } -} \ No newline at end of file + return $twig; + } + + public function getIsApi() { + return $this->isApi; + } + + public function setIsApi($isApi) { + $this->isApi = $isApi; + return $this; + } + +} diff --git a/src/psm/Service/User.php b/src/psm/Service/User.php index 6906fd93..7a85e73f 100644 --- a/src/psm/Service/User.php +++ b/src/psm/Service/User.php @@ -147,6 +147,23 @@ class User { return $query_user->fetchObject(); } + /** + * Search into database for the user data of api key specified as parameter + * @return object|boolean user data as an object if existing user + */ + public function getUserByApiKey($key) { + if(empty($key)){ + return null; + } + + // database query, getting all the info of the selected user + $query_user = $this->db_connection->prepare('SELECT * FROM '.PSM_DB_PREFIX.'users WHERE api_hash = :api_hash'); + $query_user->bindValue(':api_hash', $key, \PDO::PARAM_STR); + $query_user->execute(); + // get result row (as an object) + return $query_user->fetchObject(); + } + /** * Logs in with SESSION data. * @@ -169,6 +186,27 @@ class User { } } + /** + * Logs in via the api key + * @return bool success state of cookie login + */ + public function loginWithApiKey($key) { + $apiKey = trim($key); + + if (empty($apiKey)) { + return false; + } + $user = $this->getUserByApiKey($apiKey); + + if (empty($user)) { + return false; + } + + $this->setUserLoggedIn($user->user_id, true); + + return true; + } + /** * Logs in via the Cookie * @return bool success state of cookie login diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index 7420c367..9de3ec6f 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -186,6 +186,7 @@ class Installer { `password_reset_hash` char(40) DEFAULT NULL COMMENT 'user''s password reset code', `password_reset_timestamp` bigint(20) DEFAULT NULL COMMENT 'timestamp of the password reset request', `rememberme_token` varchar(64) DEFAULT NULL COMMENT 'user''s remember-me cookie token', + `api_hash` varchar(255) DEFAULT NULL COMMENT 'user''s hash key to validate API requests', `level` tinyint(2) unsigned NOT NULL DEFAULT '20', `name` varchar(255) NOT NULL, `mobile` varchar(15) NOT NULL, From 32303299f74ec74b659f71b3e7815adedd99f122 Mon Sep 17 00:00:00 2001 From: Matej Kminek Date: Sun, 24 Nov 2019 21:52:31 +0100 Subject: [PATCH 4/6] Removed bloat dump --- src/psm/Module/Server/Controller/ApiStatusController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/psm/Module/Server/Controller/ApiStatusController.php b/src/psm/Module/Server/Controller/ApiStatusController.php index cf910623..27120ec2 100644 --- a/src/psm/Module/Server/Controller/ApiStatusController.php +++ b/src/psm/Module/Server/Controller/ApiStatusController.php @@ -70,7 +70,6 @@ class ApiStatusController extends AbstractServerController { * Prepare the view template */ protected function executeDetail() { - var_dump($this->server_id); if(empty($this->server_id)){ return new JsonResponse("Not found", Response::HTTP_NOT_FOUND); } From 2e2e2e109e6c559148b078c45cb315b857a6bf56 Mon Sep 17 00:00:00 2001 From: Matej Kminek Date: Sun, 24 Nov 2019 22:13:43 +0100 Subject: [PATCH 5/6] GUI to edit API hash on user --- src/lang/cs_CZ.lang.php | 1 + src/lang/en_US.lang.php | 1 + src/psm/Module/User/Controller/UserController.php | 5 +++-- src/templates/default/module/user/user/update.tpl.html | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lang/cs_CZ.lang.php b/src/lang/cs_CZ.lang.php index 881c1942..854f4211 100644 --- a/src/lang/cs_CZ.lang.php +++ b/src/lang/cs_CZ.lang.php @@ -89,6 +89,7 @@ $sm_lang = array( 'user_name' => 'Uživatelské jméno', 'password' => 'Heslo', 'password_repeat' => 'Stejné heslo (pro kontrolu)', + 'api_hash' => 'API hash', 'password_leave_blank' => 'Ponechte prázdné pro ponechání beze změn.', 'level' => 'Oprávnění', 'level_10' => 'Administrátor', diff --git a/src/lang/en_US.lang.php b/src/lang/en_US.lang.php index d59d8bfa..19b25271 100644 --- a/src/lang/en_US.lang.php +++ b/src/lang/en_US.lang.php @@ -95,6 +95,7 @@ $sm_lang = array( 'user_name' => 'Username', 'password' => 'Password', 'password_repeat' => 'Password repeat', + 'api_hash' => 'API hash', 'password_leave_blank' => 'Leave blank to keep unchanged', 'level' => 'Level', 'level_10' => 'Administrator', diff --git a/src/psm/Module/User/Controller/UserController.php b/src/psm/Module/User/Controller/UserController.php index 2fdd788e..d147a234 100644 --- a/src/psm/Module/User/Controller/UserController.php +++ b/src/psm/Module/User/Controller/UserController.php @@ -139,7 +139,7 @@ class UserController extends AbstractController { */ protected function executeEdit() { $user_id = isset($_GET['id']) ? intval($_GET['id']) : 0; - $fields_prefill = array('name', 'user_name', 'mobile', 'pushover_key', 'pushover_device', 'telegram_id', 'email'); + $fields_prefill = array('name', 'user_name', 'mobile', 'pushover_key', 'pushover_device', 'telegram_id', 'email', 'api_hash'); if ($user_id == 0) { // insert mode @@ -223,7 +223,7 @@ class UserController extends AbstractController { } $user_id = (isset($_GET['id'])) ? intval($_GET['id']) : 0; - $fields = array('name', 'user_name', 'password', 'password_repeat', 'level', 'mobile', 'pushover_key', 'pushover_device', 'telegram_id', 'email'); + $fields = array('name', 'user_name', 'password', 'password_repeat', 'level', 'mobile', 'pushover_key', 'pushover_device', 'telegram_id', 'email', 'api_hash'); $clean = array(); foreach ($fields as $field) { if (isset($_POST[$field])) { @@ -342,6 +342,7 @@ class UserController extends AbstractController { 'label_user_name' => psm_get_lang('users', 'user_name'), 'label_password' => psm_get_lang('users', 'password'), 'label_password_repeat' => psm_get_lang('users', 'password_repeat'), + 'label_api_hash' => psm_get_lang('users', 'api_hash'), 'label_level' => psm_get_lang('users', 'level'), 'label_level_description' => psm_get_lang('users', 'level_description'), 'label_mobile' => psm_get_lang('users', 'mobile'), diff --git a/src/templates/default/module/user/user/update.tpl.html b/src/templates/default/module/user/user/update.tpl.html index 79661850..46df2d04 100644 --- a/src/templates/default/module/user/user/update.tpl.html +++ b/src/templates/default/module/user/user/update.tpl.html @@ -13,6 +13,8 @@ {{ macro.input_field("password", "password", null, "password", label_password, edit_value_password, placeholder_password, "255") }} {{ macro.input_field("password", "password_repeat", null, "password_repeat", label_password_repeat, edit_value_password_repeat, placeholder_password, "255") }} + + {{ macro.input_field("text", "api_hash", null, "api_hash", label_api_hash, edit_value_api_hash, placeholder_api_hash, "255") }} {{ macro.input_field("email", "email", null, "email", label_email, edit_value_email, null, "255") }} From 054095cdbe42f795fa3087689dbf0365ae1fbec4 Mon Sep 17 00:00:00 2001 From: Matej Kminek Date: Tue, 26 Nov 2019 09:56:52 +0100 Subject: [PATCH 6/6] Changed fields log.message and servers.last_error_output to TEXT to prevent failure on modern mysql databases --- src/psm/Util/Install/Installer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index 9de3ec6f..f966cd23 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -212,7 +212,7 @@ class Installer { `log_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `server_id` int(11) unsigned NOT NULL, `type` enum('status','email','sms','pushover','telegram') NOT NULL, - `message` varchar(255) NOT NULL, + `message` TEXT NOT NULL, `datetime` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`log_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", @@ -253,7 +253,7 @@ class Installer { `website_username` varchar(255) DEFAULT NULL, `website_password` varchar(255) DEFAULT NULL, `last_error` varchar(255) DEFAULT NULL, - `last_error_output` varchar(255) DEFAULT NULL, + `last_error_output` TEXT NULL DEFAULT NULL, `last_output` TEXT NULL DEFAULT NULL, PRIMARY KEY (`server_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;",