Implement RFID tag dump PWA with REST API, auth, and CI (#1)

Add Next.js app with SQLite/Drizzle storage for sites and LF/HF tag
dumps, multi-user Auth.js (credentials + optional OIDC), personal API
tokens in Settings, versioned /api/v1 for UI and future CLI use,
MCT/Proxmark/JSON import-export, PWA offline shell, Vitest tests, and
GitHub Actions CI.

Co-authored-by: Cursor Agent <[email protected]>
This commit is contained in:
Nick Trochalakis
2026-08-23 15:24:12 -07:00
committed by GitHub
co-authored by Cursor Agent
parent 5029945cc2
commit 8500d2f673
65 changed files with 13689 additions and 1 deletions
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env tsx
/**
* Create a local user account.
* Usage: npm run create-user -- --email [email protected] --password 'secret' [--name "You"]
*/
import { hash } from "bcryptjs";
import { eq } from "drizzle-orm";
import { getDb, resetDbConnection } from "../src/db/client";
import { users } from "../src/db/schema";
function arg(name: string): string | undefined {
const idx = process.argv.indexOf(`--${name}`);
if (idx === -1) return undefined;
return process.argv[idx + 1];
}
async function main() {
const email = arg("email")?.trim().toLowerCase();
const password = arg("password");
const name = arg("name") || email?.split("@")[0] || "User";
if (!email || !password) {
console.error(
"Usage: npm run create-user -- --email [email protected] --password 'secret' [--name Name]"
);
process.exit(1);
}
const db = getDb();
const existing = db.select().from(users).where(eq(users.email, email)).get();
if (existing) {
console.error(`User already exists: ${email}`);
process.exit(1);
}
const passwordHash = await hash(password, 12);
const id = crypto.randomUUID();
db.insert(users)
.values({
id,
email,
name,
passwordHash,
createdAt: new Date(),
})
.run();
console.log(`Created user ${email} (${id})`);
resetDbConnection();
}
main().catch((err) => {
console.error(err);
process.exit(1);
});