v1.0.0.0
StocketBase
- <?php
-
- declare(strict_types=1);
-
- require_once __DIR__ . '/includes/config.php';
- require_once __DIR__ . '/includes/database.php';
- require_once __DIR__ . '/includes/auth.php';
- require_once __DIR__ . '/includes/csrf.php';
- require_once __DIR__ . '/includes/asset.php';
- require_once __DIR__ . '/includes/site-front.php';
- require_once __DIR__ . '/includes/antibot.php';
- require_once __DIR__ . '/includes/login-throttle.php';
- require_once __DIR__ . '/includes/two-factor.php';
-
- Auth::boot();
- AntiBot::boot('team');
- if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- AntiBot::refresh('team');
- }
-
- if (isset($_GET['logout'])) {
- Auth::logout();
- header('Location: team-login.php');
- exit;
- }
-
- if (isset($_GET['cancel'])) {
- Auth::cancelTwoFactor();
- header('Location: team-login.php');
- exit;
- }
-
- if (Auth::check()) {
- header('Location: dashboard.php');
- exit;
- }
-
- $error = null;
- $pending = Auth::pendingTwoFactorAccount();
-
- if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- if (!Csrf::verify($_POST['csrf_token'] ?? null)) {
- $error = 'Security check failed, please try again.';
- } elseif ($pending !== null) {
- $identifier = (string) $pending['id'];
- $wait = LoginThrottle::secondsUntilAllowed('2fa', $identifier);
-
- if ($wait > 0) {
- $error = LoginThrottle::message($wait);
- } elseif (TwoFactor::verify($pending, (string) ($_POST['code'] ?? ''))) {
- LoginThrottle::clear('2fa', $identifier);
- Auth::completeLogin($pending);
- header('Location: dashboard.php');
- exit;
- } else {
- LoginThrottle::recordFailure('2fa', $identifier);
- $error = 'Invalid code.';
- }
- } elseif (!AntiBot::verify('team', $_POST['antibot_answer'] ?? null, $_POST['antibot_started'] ?? null, $_POST['website'] ?? null)) {
- $error = 'Security verification failed, please try again.';
- } else {
- $username = trim((string) ($_POST['username'] ?? ''));
- $password = (string) ($_POST['password'] ?? '');
-
- if ($username === '' || $password === '') {
- $error = 'Please enter your username and password.';
- } else {
- $wait = LoginThrottle::secondsUntilAllowed('team', $username);
-
- if ($wait > 0) {
- $error = LoginThrottle::message($wait);
- } else {
- $account = Auth::verifyCredentials($username, $password);
-
- if ($account === null) {
- LoginThrottle::recordFailure('team', $username);
- $error = 'Invalid credentials.';
- } else {
- LoginThrottle::clear('team', $username);
-
- if (TwoFactor::isEnabled($account)) {
- Auth::startTwoFactor($account);
- header('Location: team-login.php');
- exit;
- }
-
- Auth::completeLogin($account);
- header('Location: dashboard.php');
- exit;
- }
- }
- }
- }
- }
-
- $siteName = Config::get('APP_NAME', 'StocketBase');
-
- ?>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Team login - <?= htmlspecialchars($siteName) ?></title>
- <?= Asset::favicon() ?>
- <?= Asset::css('assets/site.css') ?>
- <style>
- <?= SiteFront::renderFontFaces() ?><?= SiteFront::fontVariablesCss() ?>
- </style>
- </head>
- <body class="auth-page" data-theme="light">
- <script>
- (function() {
- try {
- var t = localStorage.getItem('stocketbase_theme');
- if (t === 'dark' || t === 'light') {
- document.body.setAttribute('data-theme', t);
- } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
- document.body.setAttribute('data-theme', 'dark');
- }
- } catch (e) {}
- })();
- </script>
- <div class="auth-card">
- <h1>Team login</h1>
- <p class="auth-subtitle"><?= htmlspecialchars($siteName) ?> editorial access</p>
-
- <?php if ($error !== null): ?>
- <div class="auth-error"><?= htmlspecialchars($error) ?></div>
- <?php endif; ?>
-
- <?php if ($pending !== null): ?>
- <form method="post">
- <?= Csrf::field() ?>
- <label>Authentication code (or a recovery code)</label>
- <input type="text" name="code" required autofocus autocomplete="one-time-code" inputmode="text" maxlength="16" spellcheck="false">
- <button type="submit">Verify</button>
- <p style="margin-top:14px;font-size:13px;"><a href="team-login.php?cancel=1">Back to login</a></p>
- </form>
- <?php else: ?>
- <form method="post">
- <?= Csrf::field() ?>
- <?= AntiBot::field('team') ?>
- <label>Username or email</label>
- <input type="text" name="username" required autofocus>
- <label>Password</label>
- <input type="password" name="password" required>
- <div class="antibot-box">
- <div class="antibot-image"><?= AntiBot::image('team') ?></div>
- <label for="team-antibot-answer">Security code</label>
- <input id="team-antibot-answer" type="text" name="antibot_answer" required inputmode="text" autocomplete="off" maxlength="6" spellcheck="false">
- </div>
- <button type="submit">Log in</button>
- </form>
- <?php endif; ?>
- </div>
- </body>
- </html>
-