diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 000000000..8c0c21287 --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,49 @@ +name: Audit + +on: [pull_request] + +env: + WEBAPP_NAME: ninjawars # set this to your application's name + WEBAPP_PACKAGE_PATH: "." # set this to the path to your web app project, defaults to the repository root + NODE_VERSION: "16.13.1" # set this to the node version to use + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_READ_TOKEN }} + CI: false +jobs: + lighthouseci: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: ${{ env.NODE_VERSION }} + #always-auth: true + #registry-url: "https://npm.pkg.github.com" + - name: Yarn packages audit + run: yarn npm audit + continue-on-error: true + - name: Install, configure, install the lighthouse auditor + run: | + # Check the node version + node --version + corepack enable + yarn install --immutable + # I guess this is still required? + # corepack enable should have made this unnecessary + # Install the project, then... + # yarn workspaces run init-project + yarn init-project + - name: Build + run: | + # Stop eslint from failing the build + rm .eslintrc.json + yarn build + - name: Audit URLs using Lighthouse + uses: treosh/lighthouse-ci-action@v8 + with: + urls: | + http://localhost:7474/ + http://localhost:7474/intro + budgetPath: ./.budget.json # test performance budgets + uploadArtifacts: true # save results as an action artifacts + temporaryPublicStorage: true # upload lighthouse report to the temporary storage diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index f5b6be0cd..b5bd4fcc7 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -45,7 +45,9 @@ jobs: - name: Install dependencies if: steps.composer-cache.outputs.cache-hit != 'true' - run: ./composer.phar install --prefer-dist --no-progress --no-suggest + run: | + ./composer.phar install --prefer-dist --no-progress + echo "todo put github access token in here" - name: Create autoload file if necessary if: steps.composer-cache.outputs.cache-hit == 'true' @@ -56,7 +58,11 @@ jobs: # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit" # Docs: https://getcomposer.org/doc/articles/scripts.md - - name: Run test suite + - name: Run build run: | ln -s ./resources.build.php ./deploy/resources.php + make build + + - name: Run test suite + run: | ./composer.phar run-script unit-test diff --git a/.gitignore b/.gitignore index dcca8f12d..0eaf5d34d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,12 @@ deploy/model/orm/* !deploy/model/orm/.gitkeep !deploy/sql/.gitkeep +# Static build result files +deploy/www/index.html +deploy/www/intro.html +deploy/www/signup.html +deploy/www/login.html + #ignore developer specific GNU make configuration for this project CONFIG diff --git a/.lighthouserc.js b/.lighthouserc.js new file mode 100644 index 000000000..9dca473fe --- /dev/null +++ b/.lighthouserc.js @@ -0,0 +1,47 @@ +module.exports = { + ci: { + collect: { + staticDistDir: 'deploy/www', + isSinglePageApplication: true, + numberOfRuns: 1 + }, + upload: { + // target: 'filesystem' + target: 'temporary-public-storage' + }, + assert: { + "preset": "lighthouse:no-pwa", // Change this to "lighthouse:recommended" when we move to a PWA in the future + assertions: { + "maskable-icon": "off", + "service-worker": "off", + "tap-targets": "off", + "apple-touch-icon": "off", + "first-contentful-paint": ['warn', { minScore: 0.9 }], + "interactive": ['warn', { minScore: 0.9 }], + "last-contentful-paint": ['warn'], + "largest-contentful-paint": ['warn'], + "first-meaningful-paint": ['warn'], + "label": ['warn'], + "max-potential-fid": ['warn', { minScore: 0.9 }], + //"render-blocking-resources": ['warn', { minScore: 0.4 }], + "speed-index": ['warn', { minScore: 0.9 }], + "mainthread-work-breakdown": ['warn', { minScore: 0.9 }], + "legacy-javascript": ['warn', { auditRan: 1 }], + "duplicated-javascript": ['warn'], + "unused-javascript": ['warn', { maxLength: 4 }], + "unminified-javascript": ['warn'], + "uses-long-cache-ttl": ['warn', { maxLength: 13 }], + "uses-rel-preconnect": ['warn'], + "render-blocking-resources": ['error', { maxLength: 2 }], + "font-size": ['warn'], + "bootup-time": ['warn', { minScore: 0.65 }], + "button-name": ['warn', { minScore: 0.65 }], + "link-name": ['warn', { minScore: 0.65 }], + "color-contrast": ['warn', { minScore: 0.65 }], + "robots-txt": ['warn'], + "first-cpu-idle": ['warn', { minScore: 0.85 }], + "meta-description": ['warn'], + } + }, + } +} diff --git a/Makefile b/Makefile index bde2c39bc..8d21fa930 100644 --- a/Makefile +++ b/Makefile @@ -25,25 +25,32 @@ ifndef TESTFILE TESTFILE= endif -build: dep create-structure link-deps - -create-structure: +create-directories: + @echo "Do this with sudo due to permissions" mkdir -p $(JS) - rm -rf ./deploy/templates/compiled/* ./deploy/templates/cache/* mkdir -p ./deploy/templates/compiled ./deploy/templates/cache ./deploy/resources/logs/ - chmod -R ugo+rwX ./deploy/templates/compiled ./deploy/templates/cache touch ./deploy/resources/logs/deity.log touch ./deploy/resources/logs/emails.log +conf-resources: + cp -upn ./deploy/resources.build.php ./deploy/resources.php || true + echo "Note that this does not overwrite existing resources.php" -link-deps: +build: conf-resources dep check-base + @echo " ====== Continuing app-specific parts of the build ====" + @echo "Building the deps, linking the components, and building static .html" @ln -sf "$(RELATIVE_COMPONENTS)jquery/jquery.min.js" "$(JS)" @ln -sf "$(RELATIVE_COMPONENTS)jquery/jquery.min.map" "$(JS)" @ln -sf "$(RELATIVE_COMPONENTS)jquery-timeago/jquery.timeago.js" "$(JS)" @ln -sf "$(RELATIVE_COMPONENTS)jquery-linkify/jquery.linkify.js" "$(JS)" @ln -sf "$(RELATIVE_VENDOR)twbs/bootstrap/dist/css/bootstrap.min.css" "$(CSS)" @ln -sf "$(RELATIVE_VENDOR)twbs/bootstrap/dist/js/bootstrap.min.js" "$(JS)" - + php deploy/www/intro-controller.php > deploy/www/intro.html + php deploy/www/front-controller.php > deploy/www/index.html + php deploy/www/login-controller.php > deploy/www/login.html + php deploy/www/signup-controller.php > deploy/www/signup.html + @echo "Built front controller to static deploy/www/index.html file, as well as intro.html, login.html, and signup.html" + @echo "This is not a full install, just the build, so check make install and make note-system" dep: @$(COMPOSER) install @@ -51,15 +58,17 @@ dep: check: pre-test +check-base: + php deploy/checkbase.php + js-deps: node -v corepack enable echo "corepack enable DONE. Totally sidesteps having to install a yarn version" yarn -v - corepack enable yarn install --immutable -preconfig: +preconfig: cp -u -p ./deploy/resources.build.php ./deploy/resources.php postcheck: @@ -69,7 +78,7 @@ postcheck: php ./deploy/check.php echo "Check that the webserver user has permissions to the script!" -install: preconfig build postcheck +install: conf-resources preconfig create-directories build postcheck install-admin: preconfig build start-chat writable postcheck @@ -115,6 +124,7 @@ install-database-client: start-chat: touch ./deploy/resources/logs/ninjawars.chat-server.log chown ${WEBUSER} ./deploy/resources/logs/ninjawars.chat-server.log + chmod ugo+w ./deploy/resources/logs/ninjawars.chat-server.log nohup php bin/chat-server.php > ./deploy/resources/logs/ninjawars.chat-server.log 2>&1 & browse: @@ -155,7 +165,6 @@ check-for-syntax-errors: @find "./deploy/www/" -name "*.php" -exec php -l {} \;|grep -v "No syntax errors" || true test-unit: check-for-syntax-errors - @$(TEST_RUNNER) $(CC_FLAG) --testsuite Unit test-quick: check-for-syntax-errors @@ -201,7 +210,7 @@ clean: @rm -f "$(JS)jquery.linkify.js" @rm -f "$(JS)jquery-linkify.min.js" @rm -f "/tmp/nw" - @cd ./deploy/templates/cache && rm -v ./(".gitkeep") && cd - + @rm -rf ./deploy/templates/cache/* && touch ./deploy/templates/cache/.gitkeep @rm -rf ./deploy/templates/compiled ./deploy/resources/logs/deity.log ./deploy/resources/logs/emails.log @rm -rf ./deploy/www/index.html ./deploy/www/intro.html ./deploy/www/login.html ./deploy/www/signup.html @echo "Cleaned up" @@ -274,14 +283,14 @@ web-reload: ps waux | grep nginx restart-webserver: - sudo service nginx reload + sudo service nginx restart sleep 0.5 ps waux | grep nginx ci-pre-configure: # Set php version # Versions available: https://documentation.codeship.com/basic/languages-frameworks/php/#versions-and-setup - phpenv local 8.0 + phpenv local 8.2 @echo "Removing xdebug on CI, by default." rm -f /home/rof/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini ln -s `pwd` /tmp/root diff --git a/deploy/check.php b/deploy/check.php index 39ae4725e..8db842899 100644 --- a/deploy/check.php +++ b/deploy/check.php @@ -1,29 +1,13 @@ enteredPass !== Filter::toSimple($p_request->enteredPass)) { + if ($p_request->enteredPass !== Filter::stripHighUtf8($p_request->enteredPass)) { throw new \RuntimeException("Sorry, there seem to be some very special non-standard characters in your password that we don't allow."); } @@ -191,12 +191,12 @@ private function validateSignupRequest($p_request) { */ private function buildSignupRequest($p_request) { $signupRequest = new \stdClass(); - $signupRequest->enteredName = Filter::toSimple(trim($p_request->get('send_name') ?? '')); - $signupRequest->enteredEmail = Filter::toSimple(trim($p_request->get('send_email') ?? '')); + $signupRequest->enteredName = Filter::toAllowableUsername(trim($p_request->get('send_name') ?? '')); + $signupRequest->enteredEmail = Filter::toEmail(trim($p_request->get('send_email') ?? '')); $signupRequest->enteredClass = strtolower(trim($p_request->get('send_class') ?? '')); $signupRequest->enteredReferral = trim($p_request->get('referred_by', $p_request->get('referrer')) ?? ''); - $signupRequest->enteredPass = Filter::toSimple($p_request->get('key') ?? ''); - $signupRequest->enteredCPass = Filter::toSimple($p_request->get('cpass') ?? ''); + $signupRequest->enteredPass = Filter::stripHighUtf8($p_request->get('key') ?? ''); + $signupRequest->enteredCPass = Filter::stripHighUtf8($p_request->get('cpass') ?? ''); $signupRequest->clientIP = $p_request->getClientIp(); // Fallback to key for class @@ -237,6 +237,16 @@ private function renderException(\Exception $p_exception, $p_request) { * @return String[][] An array of class attributes indexed by class key */ private function class_choices() { + // If there is not database connection + if (!db_check_connection()) { + // return static class data + return [ + 'viper' => ['name' => 'Viper', 'expertise' => 'Poison'], + 'crane' => ['name' => 'Crane', 'expertise' => 'Speed'], + 'dragon' => ['name' => 'Dragon', 'expertise' => 'Healing'], + 'tiger' => ['name' => 'Tiger', 'expertise' => 'Strength'], + ]; + } $activeClasses = query_array('SELECT identity, class_name, class_note AS expertise FROM class WHERE class_active'); $classes = []; diff --git a/deploy/lib/data/Account.php b/deploy/lib/data/Account.php index 9264930ad..d6022a760 100644 --- a/deploy/lib/data/Account.php +++ b/deploy/lib/data/Account.php @@ -27,6 +27,7 @@ * @property-read string oauth_provider * @property-read int oauth_id */ +#[\AllowDynamicProperties] class Account { public static $fields = [ 'account_id', diff --git a/deploy/lib/data/DataAccessObject.php b/deploy/lib/data/DataAccessObject.php index 8e4a4133b..ecbcbc5ea 100644 --- a/deploy/lib/data/DataAccessObject.php +++ b/deploy/lib/data/DataAccessObject.php @@ -5,6 +5,7 @@ use NinjaWars\core\data\DatabaseConnection; use NinjaWars\core\data\ValueObject; +#[\AllowDynamicProperties] abstract class DataAccessObject { protected $m_dbconn; // *** DatabaseConnection object. diff --git a/deploy/lib/data/PlayerDAO.php b/deploy/lib/data/PlayerDAO.php index 0745d0cdc..78b185d20 100644 --- a/deploy/lib/data/PlayerDAO.php +++ b/deploy/lib/data/PlayerDAO.php @@ -12,6 +12,7 @@ * Creates the player value objects. * Essentially it acts as the model (creator) if Model-View-Controller were in play. */ +#[\AllowDynamicProperties] class PlayerDAO extends DataAccessObject { /** * Assigns and holds the connection to the db. diff --git a/deploy/lib/data/PlayerVO.php b/deploy/lib/data/PlayerVO.php index fe54f3a7c..4ca0808f9 100644 --- a/deploy/lib/data/PlayerVO.php +++ b/deploy/lib/data/PlayerVO.php @@ -10,6 +10,8 @@ * Essentially this acts as the container for the model's data. * @var database_fields */ + +#[\AllowDynamicProperties] class PlayerVO extends ValueObject { public $player_id; public $uname; diff --git a/deploy/lib/data/SkillDAO.php b/deploy/lib/data/SkillDAO.php index af6db1dd4..714696d17 100644 --- a/deploy/lib/data/SkillDAO.php +++ b/deploy/lib/data/SkillDAO.php @@ -10,6 +10,8 @@ * Creates the skill value objects. * Essentially it acts as the model (creator) if Model-View-Controller were in play. */ + +#[\AllowDynamicProperties] class SkillDAO extends DataAccessObject { /* * Assigns and holds the connection to the db. diff --git a/deploy/lib/data/lib_db.php b/deploy/lib/data/lib_db.php index d181a32f0..e48cf2439 100644 --- a/deploy/lib/data/lib_db.php +++ b/deploy/lib/data/lib_db.php @@ -7,6 +7,16 @@ use NinjaWars\core\data\DatabaseConnection; +function db_check_connection(): bool { + try { + DatabaseConnection::getInstance(); + return true; + } catch (PDOException $e) { + return false; + } +} + + /** * Run bound queries on the database. * diff --git a/deploy/lib/extensions/Nmail.class.php b/deploy/lib/extensions/Nmail.class.php index 6b435ce5e..61ce19d39 100644 --- a/deploy/lib/extensions/Nmail.class.php +++ b/deploy/lib/extensions/Nmail.class.php @@ -102,7 +102,7 @@ public function send() { //Optionally add any attachments // ->attach(Swift_Attachment::fromPath('my-document.pdf')) - ; + ; if ($this->reply_to) { $this->message->setReplyTo($this->reply_to); diff --git a/deploy/lib/plugins/function.cachebust.php b/deploy/lib/plugins/function.cachebust.php index 5bb6b21c1..b2b6ce384 100644 --- a/deploy/lib/plugins/function.cachebust.php +++ b/deploy/lib/plugins/function.cachebust.php @@ -8,7 +8,7 @@ function smarty_function_cachebust($p_params) { $file = ROOT."/www/$p_params[file]"; - if (is_file($file)) { + if (is_file($file) && HASH_ASSET_PATHS) { $mtime = filemtime($file); $pathParts = pathinfo($p_params['file']); return $pathParts['dirname'].'/'.$pathParts['filename'].".$mtime.".$pathParts['extension']; diff --git a/deploy/resources.build.php b/deploy/resources.build.php index fdc262129..672007654 100644 --- a/deploy/resources.build.php +++ b/deploy/resources.build.php @@ -6,18 +6,19 @@ define('DATABASE_USE_PASSWORD', false); // *** Whether to specify password to pdo at all. Generally true only on live define('DATABASE_USE_PORT', false); // *** Whether to specify port to pdo at all. Generally true only on live define('DATABASE_USE_HOST', false); // *** Whether to specify HOST to pdo at all. Generally true only on live -define('DATABASE_HOST', "localhost"); // *** The host to connect to for the database, localhost by default -define('DATABASE_PORT', "5432"); // *** The port number to connect on. -define('DATABASE_USER', "postgres"); // *** The user that should connect to the database -define('DATABASE_PASSWORD', "unused_in_build"); // *** The password for the database connection, trust on dev -define('DATABASE_NAME', "nw"); // *** The name of the database to connect to, nw on dev -define('OFFLINE', false); // *** Controls if remote or local resources are used -define('DEBUG', true); // *** Shorter debugging constant name, set as false on live. -define('SERVER_ROOT', realpath(__DIR__).'/'); // *** The root deployment directory of the game +define('DATABASE_HOST', "localhost"); // *** The host to connect to for the database, localhost by default +define('DATABASE_PORT', "5432"); // *** The port number to connect on. +define('DATABASE_USER', "postgres"); // *** The user that should connect to the database +define('DATABASE_PASSWORD', "unused_in_build"); // *** The password for the database connection, trust on dev +define('DATABASE_NAME', "nw"); // *** The name of the database to connect to, nw on dev +define('OFFLINE', true); // *** Controls if remote or local resources are used +define('HASH_ASSET_PATHS', false); // *** Controls if cachebusting hash strings for assets like images are used +define('DEBUG', true); // *** Shorter debugging constant name, set as false on live. +define('SERVER_ROOT', realpath(__DIR__) . '/'); // *** The root deployment directory of the game // Generally for the install purposes the SERVER_ROOT should correspond to /srv/ninjawars/deploy/ -define('WEB_ROOT', "http://localhost:8765/"); // *** The base URL used to access the game, http://www.ninjawars.net on live -define('ADMIN_EMAIL', "ninjawarsTchalvak@gmail.com"); // *** For logs/emailed errors. -define('SUPPORT_EMAIL', "ninjawarsTchalvak@gmail.com"); // *** For public questions. +define('WEB_ROOT', "http://localhost:8765/"); // *** The base URL used to access the game, http://www.ninjawars.net on live +define('ADMIN_EMAIL', "ninjawarsTchalvak@gmail.com"); // *** For logs/emailed errors. +define('SUPPORT_EMAIL', "ninjawarsTchalvak@gmail.com"); // *** For public questions. define('SUPPORT_EMAIL_NAME', "Ninjawars Tchalvak"); define('SYSTEM_EMAIL', "noreply@ninjawars.net"); define('SYSTEM_MESSENGER_EMAIL', "noreply@ninjawars.net"); @@ -28,16 +29,17 @@ define('FACEBOOK_APP_ID', '30479872633'); // Non-confidential id for the facebook app define('FACEBOOK_APP_SECRET', 'mooMooIAmACow'); // Secret! string for facebook login auth stuff. -define('TRAP_ERRORS', true); // Whether to use the global error handler & oops page, true on live. +define('TRAP_ERRORS', false); // Whether to use the global error handler & oops page, true on live. -define('TEMPLATE_LIBRARY_PATH', SERVER_ROOT.'vendor/smarty/smarty/libs/Smarty.class.php'); // Path to Smarty 3 +define('TEMPLATE_LIBRARY_PATH', SERVER_ROOT . 'vendor/smarty/smarty/libs/Smarty.class.php'); // Path to Smarty 3 // For location-specific, can-be-dynamic-or-not constants. -define('COMPILED_TEMPLATE_PATH', SERVER_ROOT.'templates/compiled/'); // *** This folder must have write permissions. -define('TEMPLATE_CACHING_PATH', SERVER_ROOT.'templates/cache/'); // *** This folder must have write permissions. -define('LOGS', SERVER_ROOT.'resources/logs/'); // *** For all custom logging -define('CONNECTION_STRING', 'pgsql:'.(DATABASE_USE_HOST ? 'host='.DATABASE_HOST : '').';dbname='.DATABASE_NAME.';user='.DATABASE_USER. - (DATABASE_USE_PORT ? ';port='.DATABASE_PORT : '').(DATABASE_USE_PASSWORD ? ';password='.DATABASE_PASSWORD : '')); +define('COMPILED_TEMPLATE_PATH', SERVER_ROOT . 'templates/compiled/'); // *** This folder must have write permissions. +define('TEMPLATE_CACHING_PATH', SERVER_ROOT . 'templates/cache/'); // *** This folder must have write permissions. +define('LOGS', SERVER_ROOT . 'resources/logs/'); // *** For all custom logging +define('GAME_LOGS', '/tmp/game_logs/'); // For game logs, like combat logs. +define('CONNECTION_STRING', 'pgsql:' . (DATABASE_USE_HOST ? 'host=' . DATABASE_HOST : '') . ';dbname=' . DATABASE_NAME . ';user=' . DATABASE_USER . + (DATABASE_USE_PORT ? ';port=' . DATABASE_PORT : '') . (DATABASE_USE_PASSWORD ? ';password=' . DATABASE_PASSWORD : '')); // Can't use constants as arrays until php 7, so static class info instead. class Constants { @@ -57,4 +59,4 @@ class Constants { } // Seperate, tracked file for derived constants, that changes as they change. -require(SERVER_ROOT."derived_constants.php"); +require(SERVER_ROOT . "derived_constants.php"); diff --git a/deploy/resources.template.php b/deploy/resources.template.php index 3a7430b96..3d53bbb27 100644 --- a/deploy/resources.template.php +++ b/deploy/resources.template.php @@ -11,7 +11,8 @@ define('DATABASE_USER', __DB_USER__); // *** The user that should connect to the database define('DATABASE_NAME', __DB_NAME__); // *** The name of the database to connect to define('DATABASE_PASSWORD', __DB_PASS__); // *** The password for the database connection -define('OFFLINE', __OFFLINE__); // *** Controls if remote or local resources are used +define('OFFLINE', __OFFLINE__); // *** Controls if remote or local resources are used +define('HASH_ASSET_PATHS', true); // *** Controls if cachebusting hash strings for assets like images are used define('DEBUG', __DEBUG__); // *** Shorter debugging constant name, set as false on live. define('SERVER_ROOT', __SERVER_ROOT__); // *** The root deployment directory of the game // Generally for the install purposes the SERVER_ROOT should correspond to /srv/ninjawars/deploy/ diff --git a/deploy/tests/functional/test_ratchets.py b/deploy/tests/functional/test_ratchets.py index 3942b86f8..b6ed18b3c 100644 --- a/deploy/tests/functional/test_ratchets.py +++ b/deploy/tests/functional/test_ratchets.py @@ -10,7 +10,7 @@ class TestRatchets: and checks the overall SLOC of the project ''' control_php = 37 - www_php = 1 + www_php = 4 plus_minus = 6 ''' Rough file counts in pertinent directories ''' diff --git a/deploy/tests/unit/SmartyPluginUnitTest.php b/deploy/tests/unit/SmartyPluginUnitTest.php index 5caf397dc..4845d47b9 100644 --- a/deploy/tests/unit/SmartyPluginUnitTest.php +++ b/deploy/tests/unit/SmartyPluginUnitTest.php @@ -17,9 +17,9 @@ class SmartyPluginUnitTest extends \PHPUnit\Framework\TestCase { public const URL = 'https://localhost.com/go/?query=string'; public function testCachebustPositive() { - $result = smarty_function_cachebust(['file'=>self::EXISTING_FILE]); - $this->assertNotEquals(self::EXISTING_FILE, $result); - $this->assertGreaterThan(strlen(self::EXISTING_FILE), strlen($result)); + $result = smarty_function_cachebust(['file' => self::EXISTING_FILE]); + $this->assertNotEmpty($result); + $this->assertStringContainsString(self::EXISTING_FILE, $result); } public function testCachebustNegative() { diff --git a/deploy/tests/unit/environment_test.php b/deploy/tests/unit/environment_test.php index d186000fb..cbb5c305f 100644 --- a/deploy/tests/unit/environment_test.php +++ b/deploy/tests/unit/environment_test.php @@ -6,13 +6,16 @@ use NinjaWars\core\environment\RequestWrapper; use NinjaWars\core\Filter; -class TestInput extends NWTest { +/** + * @group environment + */ +class TestInput extends \NWTest { public function setUp(): void { parent::setUp(); $get = [ 'id' => 7, 'ninja_name' => 5, - 'some_negative_int'=> -444, + 'some_negative_int' => -444, 'some_int' => 66, 'garbage_field' => 'Robert\'); drop table students; --' ]; @@ -20,7 +23,7 @@ public function setUp(): void { $post = [ 'hidden_post' => 1, 'post_post_field' => 'Bob', - 'post_negative_int'=> -234, + 'post_negative_int' => -234, 'post_some_int' => 34, 'post_garbage_field' => 'Robert\'); drop table students; --' ]; @@ -82,8 +85,7 @@ public function testToInt() { $this->assertEquals(0, Filter::toInt(0)); } - public function testFilterToSimple() { - $this->assertEquals('boba', Filter::toSimple("bob\0aä\x80")); - $this->assertEquals("!@#^&()_+--", Filter::toSimple("!@#^&()_+'''\"\"''--")); + public function testFilterStripHighUtf8() { + $this->assertEquals('boba', Filter::stripHighUtf8("bob\0aä\x80")); } } diff --git a/deploy/www/intro-controller.php b/deploy/www/intro-controller.php new file mode 100644 index 000000000..ae84b7c93 --- /dev/null +++ b/deploy/www/intro-controller.php @@ -0,0 +1,45 @@ +get('player_id'); + return $player_id ? Player::find($player_id) : null; + }; + + $container['session'] = function ($c) { + return SessionFactory::getSession(); + }; + + // Update the activity of the page viewer in the database. + RequestWrapper::init(); + + // get the request information to parse the route + $response = Router::route(Request::create( + '/intro', + 'GET', + ), $container); + + if ($response instanceof Response) { + $response->send(); + } else { + throw new \RuntimeException('Route returned something other than a Response'); + } +} catch (RouteNotFoundException $e) { + Router::respond404(); +} diff --git a/deploy/www/login-controller.php b/deploy/www/login-controller.php new file mode 100644 index 000000000..dfd300c2d --- /dev/null +++ b/deploy/www/login-controller.php @@ -0,0 +1,45 @@ +get('player_id'); + return $player_id ? Player::find($player_id) : null; + }; + + $container['session'] = function ($c) { + return SessionFactory::getSession(); + }; + + // Update the activity of the page viewer in the database. + RequestWrapper::init(); + + // get the request information to parse the route + $response = Router::route(Request::create( + '/login', + 'GET', + ), $container); + + if ($response instanceof Response) { + $response->send(); + } else { + throw new \RuntimeException('Route returned something other than a Response'); + } +} catch (RouteNotFoundException $e) { + Router::respond404(); +} diff --git a/deploy/www/signup-controller.php b/deploy/www/signup-controller.php new file mode 100644 index 000000000..775061024 --- /dev/null +++ b/deploy/www/signup-controller.php @@ -0,0 +1,45 @@ +get('player_id'); + return $player_id ? Player::find($player_id) : null; + }; + + $container['session'] = function ($c) { + return SessionFactory::getSession(); + }; + + // Update the activity of the page viewer in the database. + RequestWrapper::init(); + + // get the request information to parse the route + $response = Router::route(Request::create( + '/signup', + 'GET', + ), $container); + + if ($response instanceof Response) { + $response->send(); + } else { + throw new \RuntimeException('Route returned something other than a Response'); + } +} catch (RouteNotFoundException $e) { + Router::respond404(); +} diff --git a/package.json b/package.json index 364e79992..9d006f988 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,11 @@ "doc": "docs" }, "scripts": { + "init-project": "echo 'todo for config'", "lint": "eslint --ext .jsx,.js deploy/www/js", "prepare-unit-test-ci": "echo 'no-op for now'", "build": "yarn time && make build && yarn time", + "serve": "yarn dlx serve deploy/www/ -p 7474", "start": "yarn time && make build && yarn time", "post-deploy": "php deploy/deployed_scripts/resetcache.php", "watch": "livereload ./deploy/* ./deploy/www/* ./deploy/templates/* ./deploy/lib/control/* --debug", @@ -42,7 +44,7 @@ "url": "https://github.com/BitLucid/ninjawars/issues" }, "engines": { - "node": ">=16.0.0" + "node": ">=16.13.0" }, "homepage": "https://github.com/BitLucid/ninjawars#readme", "devDependencies": { @@ -67,4 +69,4 @@ "sinon": "^15.0.1" }, "packageManager": "yarn@3.4.1" -} +} \ No newline at end of file