Some checks failed
Lint / build (20) (push) Has been cancelled
- Remove hardcoded admin password, use env var or auto-generate - Fix trustHost to be conditional (Vercel-only by default) - Add HTTP security headers (CSP, X-Frame-Options, HSTS) - Create middleware.ts to activate existing rate limiting - Implement structured logging system - Rewrite error handling in ai-cad service - Update security documentation
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import crypto from "node:crypto";
|
||
import fs from "node:fs";
|
||
import postgres from "postgres";
|
||
import { drizzle } from "drizzle-orm/postgres-js";
|
||
import { user } from "./lib/db/schema";
|
||
import { generateHashedPassword } from "./lib/db/utils";
|
||
|
||
function generateSecurePassword(length = 16): string {
|
||
const charset =
|
||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*";
|
||
const bytes = crypto.randomBytes(length);
|
||
let password = "";
|
||
for (let i = 0; i < length; i++) {
|
||
password += charset[bytes[i] % charset.length];
|
||
}
|
||
return password;
|
||
}
|
||
|
||
async function main() {
|
||
let connectionString = process.env.POSTGRES_URL;
|
||
|
||
// 如果环境变量中没有 POSTGRES_URL,则尝试从 .env.local 中读取
|
||
if (!connectionString && fs.existsSync(".env.local")) {
|
||
const envContent = fs.readFileSync(".env.local", "utf8");
|
||
for (const line of envContent.split("\n")) {
|
||
const trimmed = line.trim();
|
||
if (!trimmed || trimmed.startsWith("#")) continue;
|
||
const [key, ...rest] = trimmed.split("=");
|
||
if (key === "POSTGRES_URL") {
|
||
connectionString = rest.join("=").trim();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!connectionString) {
|
||
throw new Error("POSTGRES_URL is not set");
|
||
}
|
||
|
||
const client = postgres(connectionString);
|
||
const db = drizzle(client);
|
||
|
||
// 从环境变量读取管理员邮箱和密码,避免硬编码凭据
|
||
const email =
|
||
process.env.ADMIN_EMAIL ||
|
||
process.env.INIT_ADMIN_EMAIL ||
|
||
"admin@example.com";
|
||
const password =
|
||
process.env.ADMIN_PASSWORD ||
|
||
process.env.INIT_ADMIN_PASSWORD ||
|
||
generateSecurePassword();
|
||
|
||
const hashedPassword = generateHashedPassword(password);
|
||
try {
|
||
await db.insert(user).values({
|
||
email,
|
||
password: hashedPassword,
|
||
role: "admin",
|
||
isActive: true,
|
||
});
|
||
|
||
// biome-ignore lint/style/noConsole: 仅用于一次性脚本
|
||
console.log("Admin user created:", email);
|
||
if (!process.env.ADMIN_PASSWORD && !process.env.INIT_ADMIN_PASSWORD) {
|
||
console.log(
|
||
"Auto-generated password (save this - it will not be shown again):",
|
||
password
|
||
);
|
||
}
|
||
} catch (error: unknown) {
|
||
const message =
|
||
error instanceof Error ? error.message : String(error);
|
||
// 如果已存在则忽略错误
|
||
// biome-ignore lint/style/noConsole: 仅用于一次性脚本
|
||
console.log("Admin user may already exist:", email, "-", message);
|
||
}
|
||
|
||
await client.end();
|
||
}
|
||
|
||
main().catch((error) => {
|
||
// biome-ignore lint/style/noConsole: 仅用于一次性脚本
|
||
console.error("Failed to create admin user:", error);
|
||
process.exit(1);
|
||
});
|
||
|
||
|