diff --git a/tests/wizard.php b/tests/wizard.php index 6d86cd6..9222ba3 100644 --- a/tests/wizard.php +++ b/tests/wizard.php @@ -75,4 +75,43 @@ ''); is_same ('an empty state emits nothing', state_block([]), ''); +group('Confirm email / password (typo protection)'); +$ok = ['org'=>'A','email'=>'me@example.com','email2'=>'me@example.com','username'=>'', + 'password'=>'correct-horse','password2'=>'correct-horse','agent'=>'']; +is_same ('a matching pair passes', admin_errors($ok), ''); +is_same ('missing email is caught', admin_errors(['email'=>'']+$ok), 'Enter an admin email address.'); +is_true ('mismatched email is caught', admin_errors(['email2'=>'you@example.com']+$ok) !== ''); +// cPanel users retype with different capitalisation constantly; that is not a typo. +is_same ('email match is case-insensitive', admin_errors(['email2'=>'ME@Example.com']+$ok), ''); +is_same ('missing password is caught', admin_errors(['password'=>'']+$ok), 'Choose a password.'); +is_true ('mismatched password is caught', admin_errors(['password2'=>'correct-horse ']+$ok) !== ''); +is_true ('password match is EXACT', admin_errors(['password2'=>'Correct-Horse']+$ok) !== ''); + +group('The admin form asks for both confirmations'); +$af = admin_form($ok); +is_true ('confirm email field', (bool) preg_match('/name="email2"/', $af)); +is_true ('confirm password field', (bool) preg_match('/name="password2"/', $af)); +is_false('neither rides in the hidden bag', + (bool) preg_match('/type="hidden" name="(email2|password2)"/', $af)); + +group('The credentials backup file'); +$bag = $ok + ['db_host'=>'localhost','db_name'=>'cp_tiger','db_user'=>'cp_tiger','db_pass'=>'dbsecret', + 'app_dir'=>'/home/u/site/tiger-app','docroot'=>'/home/u/public_html']; +$plain = credentials_file($bag, 'https://example.com', ['ok'=>false]); +foreach ([['the admin email','me@example.com'], ['the admin password','correct-horse'], + ['the db name','cp_tiger'], ['the db password','dbsecret'], + ['the app dir','/home/u/site/tiger-app'], ['the config path','local.ini'], + ['a keep-it-safe warning','CONTAINS PASSWORDS']] as $c) { + is_true('carries ' . $c[0], strpos($plain, $c[1]) !== false); +} +is_false('no agent section when it was not enabled', strpos($plain, 'AGENT ACCESS') !== false); + +$withAgent = credentials_file($bag, 'https://example.com', + ['ok'=>true, 'token'=>'tgr_abc', 'modules'=>['cms','media']]); +is_true ('agent section when enabled', strpos($withAgent, 'AGENT ACCESS') !== false); +is_true ('carries the access key', strpos($withAgent, 'tgr_abc') !== false); +is_true ('says it cannot be retrieved later', stripos($withAgent, 'shown once') !== false); +is_true ('says where to revoke', strpos($withAgent, '/mcp/admin') !== false); + + done(); diff --git a/tiger-install.php b/tiger-install.php index 0290cc6..448ef57 100644 --- a/tiger-install.php +++ b/tiger-install.php @@ -29,7 +29,7 @@ @ini_set('display_errors', '1'); @set_time_limit(0); -const INSTALLER_VERSION = '1.1.0'; +const INSTALLER_VERSION = '1.2.0'; const RELEASE_REPO = 'webtigers/tiger'; // the skeleton repo whose releases host the full-app bundle const MIN_PHP = '8.1.0'; const GH_API = 'https://api.github.com'; @@ -410,12 +410,14 @@ function db_form($bag, $errNote = '') { function admin_form($bag, $errNote = '') { return '

Create your admin account

' . ($errNote !== '' ? '
' . h($errNote) . '
' : '
Database installed and ready.
') - . '
' . hidden_bag($bag, ['org', 'email', 'username', 'password', 'agent']) + . '' . hidden_bag($bag, ['org', 'email', 'email2', 'username', 'password', 'password2', 'agent']) . '
' . field('Organization name', 'org', 'text', $bag['org'], 'My Company') . field('Admin email', 'email', 'email', $bag['email']) + . field('Confirm email', 'email2', 'email', $bag['email2']) . field('Username (optional)', 'username', 'text', $bag['username']) . field('Password (min 8)', 'password', 'password', $bag['password']) + . field('Confirm password', 'password2', 'password', $bag['password2']) . '
'; } + // One file with everything, generated in-page so no secret is ever written to the server. + $credText = credentials_file($bag, $base, $agentWanted ? $agent : ['ok' => false]); + $credName = 'tiger-credentials-' . preg_replace('/[^a-z0-9.-]/i', '-', $domain) . '-' . gmdate('Ymd') . '.txt'; + $body .= '

💾 Save your credentials

' + . '

One file with your admin login, database details, paths' + . ($agentWanted && !empty($agent['ok']) ? ' and the agent access key' : '') + . '. This installer deletes itself, so this is the only time these appear together.

' + . '
Download credentials' + . '
It contains passwords. Put it in a password manager, not your Downloads folder.
' + . '
'; + page('Done', $body, [ 'installer' => INSTALLER_VERSION, 'step' => 'finish',