Files
hotel/docker/harden-test-server.php
DanielS 1e9daa8858 Add Windows test-server setup behind nginx
- docker-compose.server.yml: app on APP_BIND for an existing nginx proxy,
  QLO_SSL passed to the container
- docker/setup-testserver.ps1: one-shot setup for Docker Desktop/WSL
  (random .env secrets, CLI install that never reinstalls over an
  existing shop, German texts, optional demo content, hardening)
- docker/harden-test-server.php: delete demo customer pub@qloapps.com,
  disable webservice API keys, set SSL mode, deny module log folders
- docker/nginx-qloapps.conf: HTTPS + basic auth + X-Forwarded-Proto
- apache: deny /modules/*/logs/ (qlocmconnector logs API secrets)
- docker/TESTSERVER.md: Windows Server guide (German)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 00:45:15 +01:00

68 lines
2.4 KiB
PHP

<?php
/**
* Clean up demo leftovers before a QloApps install is reachable from the network.
* Idempotent; safe to run again.
* docker compose exec -u www-data app php docker/harden-test-server.php
*
* - deletes the demo customer pub@qloapps.com (its password is public in the QloApps fixtures)
* - disables the webservice API and every API key (the installer creates an active key)
* - makes sure developer mode is off and the shop runs in the expected SSL mode
* - protects module log folders (qlocmconnector logs API secrets) with a deny file
* QLO_SSL=1 in the environment (docker-compose.server.yml) switches the shop to HTTPS.
*/
if (PHP_SAPI !== 'cli') {
exit("CLI only\n");
}
define('_PS_ADMIN_DIR_', __DIR__);
require __DIR__.'/../config/config.inc.php';
$ok = function ($msg) { echo ' [ok] '.$msg.PHP_EOL; };
$warn = function ($msg) { echo ' [!!] '.$msg.PHP_EOL; };
echo "Demo customer\n";
$ids = Db::getInstance()->executeS('SELECT id_customer FROM '._DB_PREFIX_."customer WHERE email = 'pub@qloapps.com'");
foreach ($ids as $row) {
$c = new Customer((int)$row['id_customer']);
$c->delete();
}
$ok(count($ids) ? 'pub@qloapps.com deleted' : 'no demo customer present');
echo "Webservice API\n";
Configuration::updateValue('PS_WEBSERVICE', 0);
Db::getInstance()->update('webservice_account', array('active' => 0));
$ok('API disabled, all keys deactivated');
echo "Developer mode\n";
if (_PS_MODE_DEV_) {
$warn('_PS_MODE_DEV_ is on: set it to false in config/defines.inc.php');
} else {
$ok('off');
}
echo "SSL\n";
$ssl = getenv('QLO_SSL') === '1';
Configuration::updateValue('PS_SSL_ENABLED', (int)$ssl);
Configuration::updateValue('PS_SSL_ENABLED_EVERYWHERE', (int)$ssl);
$ok($ssl ? 'HTTPS everywhere' : 'HTTP (LAN test, no certificate)');
echo "Module log folders\n";
$deny = "<IfModule mod_authz_core.c>\n Require all denied\n</IfModule>\n";
foreach (glob(_PS_MODULE_DIR_.'*', GLOB_ONLYDIR) as $dir) {
$logs = $dir.'/logs';
if (basename($dir) === 'qlocmconnector' && !is_dir($logs)) {
@mkdir($logs, 0755, true);
}
if (is_dir($logs) && !is_file($logs.'/.htaccess')) {
file_put_contents($logs.'/.htaccess', $deny);
$ok(basename($dir).'/logs protected');
}
}
echo "Admin accounts\n";
foreach (Db::getInstance()->executeS('SELECT email, active FROM '._DB_PREFIX_.'employee') as $e) {
echo ' - '.$e['email'].($e['active'] ? '' : ' (inactive)').PHP_EOL;
}
Tools::clearSmartyCache();
echo "Done.\n";