Connector Open-Source Code

Browse connector files locally. Exchange API keys stay on your device.

ui/login.php

<?php
declare(strict_types=1);

require_once __DIR__ . '/common.php';

$action = (string)($_GET['action'] ?? '');
if ($action === 'logout') {
    nv_ui_logout();
    header('Location: /login.php');
    exit;
}

if (nv_ui_is_logged_in()) {
    header('Location: /index.php');
    exit;
}

if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
    $password = (string)($_POST['password'] ?? '');
    if (nv_ui_auth_verify($password)) {
        nv_ui_mark_logged_in();
        header('Location: /index.php');
        exit;
    }
    nv_toast_set('err', 'Invalid password.');
    header('Location: /login.php');
    exit;
}

render_header('Connector Login', 'Login', false);
?>
<style>
  .auth-wrap{
    min-height:calc(100vh - 220px);
    display:flex;
    align-items:center;
  }
  .auth-grid{
    width:100%;
    display:grid;
    grid-template-columns: minmax(260px, 1fr) minmax(320px, 440px);
    gap:1.2rem;
    align-items:stretch;
  }
  .auth-hero{
    border:1px solid rgba(130,179,255,.26);
    border-radius:18px;
    padding:1.2rem 1.15rem;
    background:
      radial-gradient(700px 180px at 10% 0%, rgba(122,219,255,.2), transparent 58%),
      linear-gradient(140deg, rgba(16,36,74,.82), rgba(11,22,48,.86));
    box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 18px 36px rgba(3,11,27,.36);
  }
  .auth-kicker{
    display:inline-flex;
    align-items:center;
    gap:.4rem;
    border:1px solid rgba(133,205,255,.38);
    border-radius:999px;
    padding:.2rem .58rem;
    background:rgba(14,53,97,.45);
    color:#d8efff;
    font-size:.84rem;
    font-weight:700;
  }
  .auth-title{
    margin:.9rem 0 .55rem 0;
    font-size:2rem;
    line-height:1.08;
    font-weight:900;
    color:#f4f8ff;
  }
  .auth-sub{
    margin:0;
    color:#b8c8ea;
    max-width:68ch;
    line-height:1.45;
  }
  .auth-points{
    margin-top:1rem;
    display:grid;
    gap:.5rem;
  }
  .auth-points span{
    color:#dce7ff;
    font-weight:600;
    font-size:.95rem;
  }
  .auth-card{
    border:1px solid rgba(134,183,255,.3);
    border-radius:18px;
    background:linear-gradient(155deg, rgba(15,27,55,.9), rgba(9,20,44,.92));
    box-shadow:0 18px 38px rgba(4,12,28,.44), inset 0 1px 0 rgba(255,255,255,.1);
    overflow:hidden;
  }
  .auth-head{
    border-bottom:1px solid rgba(134,183,255,.24);
    padding:.9rem 1rem;
    font-weight:800;
    font-size:1.1rem;
    color:#eef5ff;
  }
  .auth-body{ padding:1rem; }
  .auth-body .form-label{
    font-weight:700;
    color:#e8f1ff;
  }
  .auth-body .form-control{
    min-height:46px;
    border-color:rgba(123,173,247,.35);
    background:rgba(7,17,37,.62);
    color:#f1f6ff;
  }
  .auth-body .form-control:focus{
    border-color:rgba(121,190,255,.58);
    box-shadow:0 0 0 .2rem rgba(78,150,255,.2);
  }
  .auth-body .btn{ min-height:46px; font-weight:800; }
  @media (max-width: 992px){
    .auth-wrap{ min-height:unset; }
    .auth-grid{ grid-template-columns:1fr; }
    .auth-hero{ display:none; }
  }
</style>

<section class="auth-wrap">
  <div class="auth-grid">
    <aside class="auth-hero">
      <span class="auth-kicker"><i class="bi bi-shield-lock"></i>Secure Access</span>
      <h1 class="auth-title">NuxVision Connector</h1>
      <p class="auth-sub">Manage local instances, monitor runner/tracker status, and keep your connector up to date from one private interface.</p>
      <div class="auth-points">
        <span><i class="bi bi-check2-circle me-2"></i>Local-first configuration</span>
        <span><i class="bi bi-check2-circle me-2"></i>Per-instance service control</span>
        <span><i class="bi bi-check2-circle me-2"></i>Integrated update workflow</span>
      </div>
    </aside>

    <div class="auth-card">
      <div class="auth-head">Connector Login</div>
      <div class="auth-body">
        <p class="nv-muted mb-3">Enter the UI password to continue.</p>
        <form method="post" autocomplete="off">
          <label class="form-label">Password</label>
          <input type="password" name="password" class="form-control mb-3" required autofocus>
          <button class="btn btn-accent w-100" type="submit">
            <i class="bi bi-box-arrow-in-right me-1"></i>Sign in
          </button>
        </form>
        <a class="btn btn-soft w-100 mt-2" href="/forgot_password.php">
          <i class="bi bi-key me-1"></i>Forgot password
        </a>
      </div>
    </div>
  </div>
</section>
<?php render_footer(); ?>