Add token gate overlay, cap max machines at 2

Replace browser prompt() with full-screen auth overlay that blocks
access to the upload UI until a valid token is entered.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-13 17:41:57 -07:00
parent fa7e300424
commit f836948e6d

View File

@@ -299,10 +299,29 @@ app.get("/", (_req, res) => {
.drop input { display: none; } .drop input { display: none; }
.status { margin-top: 1rem; text-align: center; font-size: .9rem; color: #888; } .status { margin-top: 1rem; text-align: center; font-size: .9rem; color: #888; }
.status.error { color: #f66; } .status.error { color: #f66; }
.overlay { position: fixed; inset: 0; background: #111; display: flex;
align-items: center; justify-content: center; z-index: 10; }
.auth { max-width: 340px; width: 100%; padding: 2rem; text-align: center; }
.auth h2 { font-size: 1.1rem; margin-bottom: 1rem; }
.auth input { width: 100%; padding: .6rem .8rem; border: 1px solid #444; border-radius: 8px;
background: #222; color: #eee; font-size: .95rem; margin-bottom: .8rem; }
.auth input:focus { outline: none; border-color: #4a9eff; }
.auth button { width: 100%; padding: .6rem; border: none; border-radius: 8px;
background: #4a9eff; color: #fff; font-size: .95rem; cursor: pointer; }
.auth button:hover { background: #3a8eef; }
.auth .err { color: #f66; font-size: .85rem; margin-top: .5rem; }
</style> </style>
</head> </head>
<body> <body>
<div class="wrap"> <div class="overlay" id="auth-overlay" style="display:none">
<div class="auth">
<h2>Enter access token</h2>
<input type="password" id="token-input" placeholder="Token" autocomplete="off">
<button id="token-submit">Continue</button>
<div class="err" id="token-err"></div>
</div>
</div>
<div class="wrap" id="main" style="display:none">
<h1>Strip Photo Metadata</h1> <h1>Strip Photo Metadata</h1>
<div class="drop" id="drop"> <div class="drop" id="drop">
<p>Drop a photo here or tap to choose</p> <p>Drop a photo here or tap to choose</p>
@@ -313,25 +332,40 @@ app.get("/", (_req, res) => {
<script> <script>
(function() { (function() {
const KEY = "postconvert_token"; const KEY = "postconvert_token";
const overlay = document.getElementById("auth-overlay");
const main = document.getElementById("main");
const tokenInput = document.getElementById("token-input");
const tokenSubmit = document.getElementById("token-submit");
const tokenErr = document.getElementById("token-err");
const drop = document.getElementById("drop"); const drop = document.getElementById("drop");
const fileInput = document.getElementById("file"); const fileInput = document.getElementById("file");
const status = document.getElementById("status"); const status = document.getElementById("status");
function getToken() { function showApp() { overlay.style.display = "none"; main.style.display = ""; }
let t = localStorage.getItem(KEY); function showAuth() { overlay.style.display = ""; main.style.display = "none"; tokenErr.textContent = ""; }
if (t) return t;
t = prompt("Enter your access token:"); if (localStorage.getItem(KEY)) {
if (!t) return null; showApp();
localStorage.setItem(KEY, t.trim()); } else {
return t.trim(); showAuth();
} }
// Prompt immediately on page load tokenSubmit.addEventListener("click", () => {
if (!localStorage.getItem(KEY)) getToken(); const t = tokenInput.value.trim();
if (!t) { tokenErr.textContent = "Token required"; return; }
localStorage.setItem(KEY, t);
showApp();
});
tokenInput.addEventListener("keydown", (e) => {
if (e.key === "Enter") tokenSubmit.click();
});
function getToken() { return localStorage.getItem(KEY); }
async function strip(file) { async function strip(file) {
const token = getToken(); const token = getToken();
if (!token) return; if (!token) { showAuth(); return; }
status.className = "status"; status.className = "status";
status.textContent = "Stripping metadata…"; status.textContent = "Stripping metadata…";
@@ -348,8 +382,8 @@ app.get("/", (_req, res) => {
if (res.status === 401) { if (res.status === 401) {
localStorage.removeItem(KEY); localStorage.removeItem(KEY);
status.className = "status error"; showAuth();
status.textContent = "Bad token. Try again."; tokenErr.textContent = "Invalid token. Please try again.";
return; return;
} }