mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 08:09:18 +02:00
- Skip required-field validation for orientation/ap/finality/licence/jury in admin add+edit
102 lines
3.3 KiB
PHP
102 lines
3.3 KiB
PHP
#!/usr/bin/env php
|
|
<?php
|
|
/**
|
|
* Re-encrypt the SMTP password after rotating APP_KEY.
|
|
*
|
|
* Usage:
|
|
* php scripts/reencrypt-smtp-password.php <new_base64_key> [DB_PATH]
|
|
*
|
|
* Steps performed:
|
|
* 1. Read old APP_KEY from the .env file adjacent to this script's app root.
|
|
* 2. Decrypt the current password from smtp_settings using the old key.
|
|
* 3. Encrypt it with the new key.
|
|
* 4. Write the new ciphertext back to the DB.
|
|
* 5. Update app/.env with the new APP_KEY.
|
|
*
|
|
* After running this script, redeploy or manually update app/.env on every
|
|
* environment that shares the same database.
|
|
*/
|
|
|
|
$newKeyB64 = $argv[1] ?? '';
|
|
$dbPath = $argv[2] ?? null;
|
|
|
|
if ($newKeyB64 === '') {
|
|
fwrite(STDERR, "Usage: php reencrypt-smtp-password.php <new_base64_key> [DB_PATH]\n");
|
|
fwrite(STDERR, "Generate a key: php -r \"echo base64_encode(random_bytes(32));\"\n");
|
|
exit(1);
|
|
}
|
|
|
|
$newKeyRaw = base64_decode($newKeyB64, strict: true);
|
|
if ($newKeyRaw === false || strlen($newKeyRaw) !== 32) {
|
|
fwrite(STDERR, "ERROR: new key must be a base64-encoded 32-byte value.\n");
|
|
exit(1);
|
|
}
|
|
|
|
// Locate app root (script lives in app/scripts/ or scripts/ next to app/)
|
|
$candidates = [
|
|
__DIR__ . '/../app', // repo root / scripts/
|
|
__DIR__ . '/..', // app / scripts/
|
|
];
|
|
$appRoot = null;
|
|
foreach ($candidates as $c) {
|
|
if (file_exists(realpath($c) . '/src/Crypto.php')) {
|
|
$appRoot = realpath($c);
|
|
break;
|
|
}
|
|
}
|
|
if ($appRoot === null) {
|
|
fwrite(STDERR, "ERROR: could not locate app root (looking for src/Crypto.php).\n");
|
|
exit(1);
|
|
}
|
|
|
|
define('APP_ROOT', $appRoot);
|
|
require_once $appRoot . '/src/Crypto.php';
|
|
|
|
$dbPath = $dbPath ?? $appRoot . '/storage/xamxam.db';
|
|
if (!file_exists($dbPath)) {
|
|
fwrite(STDERR, "ERROR: database not found: $dbPath\n");
|
|
exit(1);
|
|
}
|
|
|
|
$pdo = new PDO('sqlite:' . $dbPath);
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
|
$row = $pdo->query("SELECT password FROM smtp_settings WHERE id = 1")->fetch(PDO::FETCH_ASSOC);
|
|
if (!$row) {
|
|
fwrite(STDERR, "ERROR: no smtp_settings row found.\n");
|
|
exit(1);
|
|
}
|
|
|
|
// Decrypt with the old key (read from existing .env via Crypto::decrypt)
|
|
$plaintext = Crypto::decrypt($row['password']);
|
|
if ($plaintext === '') {
|
|
echo "Password is empty — nothing to re-encrypt.\n";
|
|
exit(0);
|
|
}
|
|
|
|
// Encrypt with the new key directly (bypass the singleton so we can supply a different key)
|
|
$iv = random_bytes(12);
|
|
$tag = '';
|
|
$cipher = openssl_encrypt($plaintext, 'aes-256-gcm', $newKeyRaw, OPENSSL_RAW_DATA, $iv, $tag, '', 16);
|
|
if ($cipher === false) {
|
|
fwrite(STDERR, "ERROR: encryption failed: " . openssl_error_string() . "\n");
|
|
exit(1);
|
|
}
|
|
$newBlob = base64_encode($iv . $tag . $cipher);
|
|
|
|
// Write new ciphertext to DB
|
|
$pdo->prepare("UPDATE smtp_settings SET password = ? WHERE id = 1")->execute([$newBlob]);
|
|
echo "DB updated with new ciphertext.\n";
|
|
|
|
// Update .env
|
|
$envFile = $appRoot . '/.env';
|
|
$envContent = file_exists($envFile) ? file_get_contents($envFile) : '';
|
|
if (preg_match('/^APP_KEY=.*/m', $envContent)) {
|
|
$envContent = preg_replace('/^APP_KEY=.*/m', 'APP_KEY=' . $newKeyB64, $envContent);
|
|
} else {
|
|
$envContent .= "APP_KEY={$newKeyB64}\n";
|
|
}
|
|
file_put_contents($envFile, $envContent);
|
|
echo ".env updated with new APP_KEY.\n";
|
|
echo "Done. Redeploy app/.env to all environments: just deploy-env\n";
|