File size: 1,986 Bytes
bc2ac28 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | import fs from "fs";
import path from "path";
import crypto from "crypto";
const DATA_DIR = path.join(process.cwd(), "data");
const KEYS_FILE = path.join(DATA_DIR, "api-keys.json");
export interface ApiKey {
key: string;
name: string;
createdAt: string;
active: boolean;
usageCount: number;
lastUsed: string | null;
}
function ensureDataDir() {
if (!fs.existsSync(DATA_DIR)) {
fs.mkdirSync(DATA_DIR, { recursive: true });
}
}
function readKeys(): ApiKey[] {
ensureDataDir();
if (!fs.existsSync(KEYS_FILE)) return [];
try {
return JSON.parse(fs.readFileSync(KEYS_FILE, "utf-8"));
} catch {
return [];
}
}
function writeKeys(keys: ApiKey[]) {
ensureDataDir();
fs.writeFileSync(KEYS_FILE, JSON.stringify(keys, null, 2), "utf-8");
}
export function generateKey(name: string): ApiKey {
const keys = readKeys();
const newKey: ApiKey = {
key: `neo1-${crypto.randomBytes(20).toString("hex")}`,
name,
createdAt: new Date().toISOString(),
active: true,
usageCount: 0,
lastUsed: null,
};
keys.push(newKey);
writeKeys(keys);
return newKey;
}
export function listKeys(): Omit<ApiKey, "key">[] {
return readKeys().map(({ key, ...rest }) => ({
...rest,
keyPreview: `${key.slice(0, 10)}...${key.slice(-4)}`,
})) as Omit<ApiKey, "key">[];
}
export function validateKey(key: string): ApiKey | null {
const keys = readKeys();
const found = keys.find((k) => k.key === key && k.active);
if (!found) return null;
found.usageCount += 1;
found.lastUsed = new Date().toISOString();
writeKeys(keys);
return found;
}
export function revokeKey(keyOrName: string): boolean {
const keys = readKeys();
const idx = keys.findIndex(
(k) => k.key === keyOrName || k.name === keyOrName
);
if (idx === -1) return false;
keys[idx].active = false;
writeKeys(keys);
return true;
}
export function getAdminSecret(): string {
return process.env["NEO_ADMIN_SECRET"] ?? "neo-admin-change-me";
}
|