asd
This commit is contained in:
commit
3e4a056b14
67 files changed
+13926
No files matched your search
+151
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require __DIR__ . '/../includes/auth.php';
|
||||
require __DIR__ . '/../includes/captcha.php';
|
||||
send_security_headers(true);
|
||||
|
||||
if (current_admin()) {
|
||||
redirect(base_url('admin/'));
|
||||
}
|
||||
if (pending_login()) {
|
||||
redirect(base_url('admin/2fa.php'));
|
||||
}
|
||||
|
||||
$setup = admin_count() === 0; // first run: create the first admin account
|
||||
// The first-admin form is only usable with the setup key from config.php
|
||||
// (or create the admin from the server console). Never open to the internet.
|
||||
$setupKey = (string)security_config()['setup_key'];
|
||||
$setupAllowed = $setup && strlen($setupKey) >= 16;
|
||||
$error = null;
|
||||
// Why the previous session ended (whitelisted values only).
|
||||
$notices = [
|
||||
'elsewhere' => 'Akun Anda masuk dari perangkat atau browser lain, sehingga sesi ini diakhiri. Masuk lagi untuk melanjutkan.',
|
||||
'password' => 'Password akun ini telah diganti. Silakan masuk dengan password baru.',
|
||||
'inactive' => 'Sesi diakhiri karena akun tidak aktif.',
|
||||
'expired' => 'Waktu verifikasi habis. Silakan masuk lagi.',
|
||||
'otp' => 'Terlalu banyak kode OTP salah. Silakan masuk lagi dalam ' . LOGIN_WINDOW_MIN . ' menit.',
|
||||
];
|
||||
$notice = $notices[input_str($_GET['reason'] ?? '')] ?? null;
|
||||
$username = '';
|
||||
$name = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
csrf_check();
|
||||
$username = strtolower(trim(input_str($_POST['username'] ?? '')));
|
||||
$password = input_str($_POST['password'] ?? '');
|
||||
// The CAPTCHA is checked first, before any password is verified.
|
||||
$captchaOk = captcha_check(input_str($_POST['captcha'] ?? ''));
|
||||
if (login_locked()) {
|
||||
$error = 'Terlalu banyak percobaan gagal dari jaringan ini. Coba lagi dalam ' . LOGIN_WINDOW_MIN . ' menit.';
|
||||
} elseif (!$captchaOk) {
|
||||
$error = 'Kode keamanan (CAPTCHA) salah atau kedaluwarsa. Ketik kode pada gambar yang baru.';
|
||||
} elseif ($setup) {
|
||||
$name = trim(input_str($_POST['full_name'] ?? ''));
|
||||
$sentKey = input_str($_POST['setup_key'] ?? '');
|
||||
if (!$setupAllowed) {
|
||||
$error = 'Pembuatan admin pertama tidak diizinkan dari sini.';
|
||||
} elseif (!hash_equals($setupKey, $sentKey)) {
|
||||
db()->prepare('INSERT INTO login_attempts (ip, username, success) VALUES (?,?,0)')->execute([client_ip(), 'setup']);
|
||||
$error = 'Kode setup salah.';
|
||||
} else {
|
||||
$error = validate_new_admin($username, $name, $password, input_str($_POST['password_confirm'] ?? ''));
|
||||
}
|
||||
if (!$error && admin_count() === 0) {
|
||||
// The first admin is the super admin; the authenticator is set up next.
|
||||
db()->prepare("INSERT INTO admins (username, full_name, role, password_hash) VALUES (?,?,'super_admin',?)")
|
||||
->execute([$username, $name, password_hash($password, PASSWORD_DEFAULT)]);
|
||||
db()->prepare("INSERT INTO audit_log (action, summary, ip) VALUES ('user.create', ?, ?)")
|
||||
->execute(["Membuat akun admin pertama: $username", client_ip()]);
|
||||
begin_second_factor(verify_credentials($username, $password));
|
||||
redirect(base_url('admin/2fa.php'));
|
||||
}
|
||||
} elseif ($row = verify_credentials($username, $password)) {
|
||||
begin_second_factor($row);
|
||||
redirect(base_url('admin/2fa.php'));
|
||||
} else {
|
||||
$error = 'Username atau password salah.';
|
||||
}
|
||||
}
|
||||
captcha_new(); // every rendered form gets a fresh challenge
|
||||
$captchaQuestion = captcha_question();
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="robots" content="noindex">
|
||||
<title><?= $setup ? 'Buat Akun Admin' : 'Masuk Admin' ?> · SERUBI</title>
|
||||
<?= theme_boot_script() ?>
|
||||
<link rel="icon" href="<?= e(asset('assets/favicon.svg')) ?>" type="image/svg+xml">
|
||||
<link rel="stylesheet" href="<?= e(asset('assets/css/base.css')) ?>">
|
||||
<link rel="stylesheet" href="<?= e(asset('assets/css/admin.css')) ?>">
|
||||
</head>
|
||||
<body class="page-login">
|
||||
<main class="login">
|
||||
<a class="brand" href="<?= e(base_url()) ?>" aria-label="Bank Papua SERUBI, kembali ke kalkulator"><?= bank_logo('auto', 'logo-lg') ?><span class="brand-prog">SERUBI</span></a>
|
||||
<form class="login-card" method="post" novalidate>
|
||||
<?= csrf_field() ?>
|
||||
<h1><?= $setup ? 'Buat akun admin pertama' : 'Masuk ke admin parameter' ?></h1>
|
||||
<p class="muted"><?= $setup
|
||||
? 'Belum ada admin. Akun ini dapat mengubah parameter perhitungan dan menambah admin lain.'
|
||||
: 'Ubah rate ALCO dan parameter perhitungan kalkulator cashback.' ?></p>
|
||||
|
||||
<?php if ($setup && !$setupAllowed): ?>
|
||||
<p class="alert alert-info" role="status"><?= icon('info') ?><span>Belum ada admin. Buat admin pertama dari konsol server:<br><code>php database/migrate.php --create-admin</code><br>atau isi <code>security.setup_key</code> (minimal 16 karakter) di config.php.</span></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($notice && !$error): ?>
|
||||
<p class="alert alert-info" role="status"><?= icon('info') ?><span><?= e($notice) ?></span></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($error): ?>
|
||||
<p class="alert alert-error" role="alert"><?= icon('alert') ?><span><?= e($error) ?></span></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="form-field">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" name="username" autocomplete="username" required autocapitalize="none" spellcheck="false"
|
||||
value="<?= e($username) ?>" <?= $username === '' ? 'autofocus' : '' ?>>
|
||||
</div>
|
||||
<?php if ($setupAllowed): ?>
|
||||
<div class="form-field">
|
||||
<label for="setup_key">Kode setup</label>
|
||||
<input id="setup_key" name="setup_key" type="password" required autocomplete="off">
|
||||
<p class="hint">Kode dari <code>security.setup_key</code> di config.php.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($setup): ?>
|
||||
<div class="form-field">
|
||||
<label for="full_name">Nama lengkap</label>
|
||||
<input id="full_name" name="full_name" autocomplete="name" required value="<?= e($name) ?>">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="form-field">
|
||||
<label for="password">Password</label>
|
||||
<input id="password" name="password" type="password" required autocomplete="<?= $setup ? 'new-password' : 'current-password' ?>" <?= $username !== '' ? 'autofocus' : '' ?>>
|
||||
<?php if ($setup): ?><p class="hint">Minimal 10 karakter, berisi huruf, angka, dan simbol.</p><?php endif; ?>
|
||||
</div>
|
||||
<?php if ($setup): ?>
|
||||
<div class="form-field">
|
||||
<label for="password_confirm">Ulangi password</label>
|
||||
<input id="password_confirm" name="password_confirm" type="password" required autocomplete="new-password">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!$setup || $setupAllowed): ?>
|
||||
<div class="form-field">
|
||||
<label for="captcha">Kode keamanan</label>
|
||||
<?php if ($captchaQuestion): ?>
|
||||
<p class="hint"><?= e($captchaQuestion) ?></p>
|
||||
<?php else: ?>
|
||||
<img class="captcha-img" src="<?= e(base_url('admin/captcha.php') . '?r=' . bin2hex(random_bytes(4))) ?>" width="200" height="64" alt="Kode keamanan berupa gambar 5 karakter">
|
||||
<p class="hint">Ketik 5 karakter pada gambar. <a href="<?= e(base_url('admin/login.php')) ?>">Ganti gambar</a></p>
|
||||
<?php endif; ?>
|
||||
<input id="captcha" name="captcha" required autocomplete="off" autocapitalize="characters" spellcheck="false" inputmode="<?= $captchaQuestion ? 'numeric' : 'text' ?>" maxlength="8">
|
||||
</div>
|
||||
<button class="btn btn-primary btn-block" type="submit"><?= icon($setup ? 'check' : 'lock') ?><span><?= $setup ? 'Buat akun & masuk' : 'Masuk' ?></span></button>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
<a class="back-link" href="<?= e(base_url()) ?>"><?= icon('calc') ?><span>Kembali ke kalkulator</span></a>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user