107 lines
4.4 KiB
PHP
107 lines
4.4 KiB
PHP
<?php
|
|
// CLI helper (never reachable over HTTP).
|
|
// php database/migrate.php create database, tables and seed (if empty)
|
|
// php database/migrate.php --reseed reset all parameters to the workbook defaults
|
|
// php database/migrate.php --dump-params print the active parameters as JSON
|
|
// php database/migrate.php --create-admin create an admin account interactively
|
|
// php database/migrate.php --create-db-user create a least-privilege MySQL user for the app
|
|
declare(strict_types=1);
|
|
|
|
if (PHP_SAPI !== 'cli') {
|
|
http_response_code(404);
|
|
exit;
|
|
}
|
|
require __DIR__ . '/../includes/auth.php';
|
|
|
|
function ask(string $label, bool $secret = false): string
|
|
{
|
|
fwrite(STDOUT, $label . ': ');
|
|
if ($secret && DIRECTORY_SEPARATOR === '/') {
|
|
shell_exec('stty -echo');
|
|
$v = (string)fgets(STDIN);
|
|
shell_exec('stty echo');
|
|
fwrite(STDOUT, "\n");
|
|
} else {
|
|
$v = (string)fgets(STDIN);
|
|
}
|
|
return rtrim($v, "\r\n");
|
|
}
|
|
|
|
try {
|
|
$pdo = db();
|
|
} catch (PDOException $e) {
|
|
if ((int)($e->errorInfo[1] ?? $e->getCode()) !== 1049) { // 1049 = unknown database
|
|
throw $e;
|
|
}
|
|
// First install with a privileged account: create the database.
|
|
$name = str_replace('`', '', app_config()['db']['name']);
|
|
db_connect(app_config()['db'], false)
|
|
->exec("CREATE DATABASE IF NOT EXISTS `$name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
|
$pdo = db();
|
|
}
|
|
db_migrate($pdo);
|
|
|
|
if (in_array('--reseed', $argv, true)) {
|
|
db_seed($pdo, true);
|
|
fwrite(STDERR, "Parameters reset to workbook defaults.\n");
|
|
}
|
|
|
|
if (in_array('--dump-params', $argv, true)) {
|
|
echo json_encode(load_params(), JSON_PRETTY_PRINT), "\n";
|
|
exit;
|
|
}
|
|
|
|
if (in_array('--dump-public-model', $argv, true)) {
|
|
require __DIR__ . '/../includes/engine.php';
|
|
echo json_encode(engine_client_model(load_params_db()), JSON_PRETTY_PRINT | JSON_PRESERVE_ZERO_FRACTION), "\n";
|
|
exit;
|
|
}
|
|
|
|
if (in_array('--create-admin', $argv, true)) {
|
|
$username = strtolower(trim(ask('Username')));
|
|
$name = trim(ask('Nama lengkap'));
|
|
$password = ask('Password (min 10, huruf+angka+simbol)', true);
|
|
$confirm = ask('Ulangi password', true);
|
|
if ($err = validate_new_admin($username, $name, $password, $confirm)) {
|
|
fwrite(STDERR, "Gagal: $err\n");
|
|
exit(1);
|
|
}
|
|
$st = $pdo->prepare('SELECT COUNT(*) FROM admins WHERE username = ?');
|
|
$st->execute([$username]);
|
|
if ((int)$st->fetchColumn() > 0) {
|
|
fwrite(STDERR, "Gagal: username sudah dipakai.\n");
|
|
exit(1);
|
|
}
|
|
// The first super admin is created here; later admins are added from the admin page.
|
|
$role = (int)$pdo->query("SELECT COUNT(*) FROM admins WHERE role = 'super_admin' AND is_active = 1")->fetchColumn() === 0 ? 'super_admin' : 'admin';
|
|
$pdo->prepare('INSERT INTO admins (username, full_name, role, password_hash) VALUES (?,?,?,?)')
|
|
->execute([$username, $name, $role, password_hash($password, PASSWORD_DEFAULT)]);
|
|
$pdo->prepare("INSERT INTO audit_log (action, summary, ip) VALUES ('user.create', ?, 'cli')")
|
|
->execute(["Membuat admin $username dari konsol server"]);
|
|
fwrite(STDOUT, "Admin $username dibuat.\n");
|
|
exit;
|
|
}
|
|
|
|
if (in_array('--create-db-user', $argv, true)) {
|
|
// Run once with the privileged account currently in config.php.
|
|
$c = app_config()['db'];
|
|
$user = 'serubi_app';
|
|
$pass = rtrim(strtr(base64_encode(random_bytes(24)), '+/', 'Aa'), '=');
|
|
// Local DB server: allow only local connections. Remote DB: the web server connects from elsewhere.
|
|
$hosts = in_array($c['host'], ['127.0.0.1', 'localhost'], true) ? ['localhost', '127.0.0.1'] : ['%'];
|
|
$db = str_replace('`', '', $c['name']);
|
|
foreach ($hosts as $h) {
|
|
$account = "'$user'@'$h'";
|
|
$pdo->exec("CREATE USER IF NOT EXISTS $account IDENTIFIED BY " . $pdo->quote($pass));
|
|
$pdo->exec("ALTER USER $account IDENTIFIED BY " . $pdo->quote($pass));
|
|
$pdo->exec("GRANT SELECT, INSERT, UPDATE, DELETE ON `$db`.* TO $account");
|
|
}
|
|
$pdo->exec('FLUSH PRIVILEGES');
|
|
fwrite(STDOUT, "User MySQL '$user' dibuat dengan hak SELECT/INSERT/UPDATE/DELETE pada `$db` saja.\n");
|
|
fwrite(STDOUT, "Ganti di config.php (atau environment variable):\n 'user' => '$user',\n 'password' => '$pass',\n");
|
|
exit;
|
|
}
|
|
|
|
$c = app_config()['db'];
|
|
fwrite(STDERR, sprintf("Database `%s` ready on %s:%d.\n", $c['name'], $c['host'], $c['port']));
|