From d61d7b06ede7ba22b0a1e05b34166d2a2bacf609 Mon Sep 17 00:00:00 2001 From: Jim Mason Date: Mon, 30 Aug 2021 17:30:45 +0100 Subject: [PATCH] added new 'validate' controller and hooked it into CI Partly satisfies #81 --- .travis.yml | 2 +- config/controller_config.php | 1 + controllers/Validate.php | 145 +++++++++++++++++++++++++++++++++++ engine/IUser.php | 1 + engine/impl/User.php | 22 ++++++ 5 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 controllers/Validate.php diff --git a/.travis.yml b/.travis.yml index 46854ff3c..3c7719a82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,4 +40,4 @@ before_script: - export HTTP_ACCEPT="application/json" - export HTTP_USER_AGENT="Travis CI" -script: php zk test action=test subaction=test +script: php zk validate diff --git a/config/controller_config.php b/config/controller_config.php index e7ae66ee4..690803fd1 100644 --- a/config/controller_config.php +++ b/config/controller_config.php @@ -16,4 +16,5 @@ 'api' => ZK\Controllers\API::class, 'sso' => ZK\Controllers\SSOLogin::class, 'push' => ZK\Controllers\PushServer::class, + 'validate' => ZK\Controllers\Validate::class, ]; diff --git a/controllers/Validate.php b/controllers/Validate.php new file mode 100644 index 000000000..43f201973 --- /dev/null +++ b/controllers/Validate.php @@ -0,0 +1,145 @@ + + * @copyright Copyright (C) 1997-2021 Jim Mason + * @link https://zookeeper.ibinx.com/ + * @license GPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License, + * version 3, along with this program. If not, see + * http://www.gnu.org/licenses/ + * + */ + +namespace ZK\Controllers; + +use ZK\Engine\Engine; +use ZK\Engine\IChart; +use ZK\Engine\IPlaylist; +use ZK\Engine\IUser; + +use ZK\UI\UICommon as UI; + +class Validate implements IController { + private $success = true; + private $session; + private $testPass; + + private const TEST_USER = "__test_u"; + private const TEST_NAME = "Test User"; + private const TEST_ACCESS = "qr"; // some unused roles for safety + + private const FAIL = "\033[0;31m"; + private const OK = "\033[0;32m"; + private const NORMAL = "\033[0m"; + + private function showSuccess($success) { + $this->success &= $success; + if($success) + echo self::OK."OK"; + else + echo self::FAIL."FAILED!"; + echo self::NORMAL."\n"; + } + + public function processRequest() { + if(php_sapi_name() != "cli") { + http_response_code(400); + return; + } + + $this->session = Engine::session(); + echo "\nStarting Validation...\n\n"; + try { + if($this->validateCreateUser() && + $this->validateSignon() && + $this->validateCategories() && + $this->validateDeleteUser()); + } catch (\Exception $e) { + // if there is a db configuration issue (wrong db name + // or password, etc.), we'll get an exception. + echo self::FAIL."\nFATAL: ".$e->getMessage().self::NORMAL."\n"; + $this->success = false; + } + echo "\nDone.\n"; + exit($this->success?0:1); + } + + public function validateCreateUser() { + $api = Engine::api(IUser::class); + + // clear test user, if any + // + // we don't want to show any errors from the attempted deletion; + // if there is a database configuration problem, it will show up below. + error_reporting(0); + $api->deleteUser(self::TEST_USER); + error_reporting(E_ALL & ~E_NOTICE); + + echo "\tcreate user: "; + $this->testPass = md5(uniqid(rand())); + $success = $api->insertUser(self::TEST_USER, $this->testPass, + self::TEST_NAME, self::TEST_ACCESS, ""); + $this->showSuccess($success); + if($success) { + echo "\tvalidate user: "; + $user = $api->getUser(self::TEST_USER); + $success = $user['realname'] == self::TEST_NAME; + $this->showSuccess($success); + } + return $success; + } + + public function validateSignon() { + echo "\tvalidate signon: "; + if(Engine::api(IUser::class)->validatePassword(self::TEST_USER, + $this->testPass, 1, $access)) { + $this->showSuccess(true); + echo "\tvalidate session: "; + // Create a session + // + // Suppress warnings from session cookie creation + error_reporting(E_ERROR); + $sessionID = md5(uniqid(rand())); + $this->session->create($sessionID, self::TEST_USER, $access); + + // Validate session + $this->session->validate($sessionID); + $success = $this->session->isAuth(substr(self::TEST_ACCESS, 1, 1)); + $this->showSuccess($success); + + // Resume normal error reporting + error_reporting(E_ALL & ~E_NOTICE); + } else { + $this->showSuccess(false); + $success = false; + } + return $success; + } + + public function validateCategories() { + echo "\tvalidate categories: "; + $cats = Engine::api(IChart::class)->getCategories(); + $success = sizeof($cats) == 16; + $this->showSuccess($success); + return true; // continue even if this test fails + } + + public function validateDeleteUser() { + echo "\tdelete user: "; + $success = Engine::api(IUser::class)->deleteUser(self::TEST_USER); + $this->showSuccess($success); + return $success; + } +} diff --git a/engine/IUser.php b/engine/IUser.php index 8837a5b35..bbdf832e7 100644 --- a/engine/IUser.php +++ b/engine/IUser.php @@ -43,4 +43,5 @@ function createNewAccount($fullname, $account); function validatePassword($user, $password, $updateTimestamp, &$groups=0); function updateUser($user, $password, $realname="XXZZ", $groups="XXZZ", $expiration="XXZZ"); function insertUser($user, $password, $realname, $groups, $expiration); + function deleteUser($user); } diff --git a/engine/impl/User.php b/engine/impl/User.php index 0a37cf19d..5d9b4b887 100644 --- a/engine/impl/User.php +++ b/engine/impl/User.php @@ -253,4 +253,26 @@ public function insertUser($user, $password, $realname, $groups, $expiration) { $stmt->execute(); return ($stmt->rowCount() > 0); } + + public function deleteUser($user) { + // validate this user has no playlists nor reviews + $query = "SELECT COUNT(*) c FROM lists WHERE dj = ?"; + $stmt = $this->prepare($query); + $stmt->bindValue(1, $user); + $result = $stmt->executeAndFetch(); + if($result['c']) + return false; + + $query = "SELECT COUNT(*) c FROM reviews WHERE user = ?"; + $stmt = $this->prepare($query); + $stmt->bindValue(1, $user); + $result = $stmt->executeAndFetch(); + if($result['c']) + return false; + + $query = "DELETE FROM users WHERE name = ?"; + $stmt = $this->prepare($query); + $stmt->bindValue(1, $user); + return $stmt->execute(); + } }