This commit is contained in:
Vaica committed 2026-06-22 14:59:24 +08:00
1 parent 4ab47a3e47
commit ba016efbe8
21 files changed
+921 -72

No files matched your search

+71
View File
@@ -0,0 +1,71 @@
import fs from "fs";
import path from "path";
import { createHash, randomBytes } from "crypto";
interface StoredUser {
username: string;
passwordHash: string;
salt: string;
name: string;
role: "admin" | "user";
}
interface User {
username: string;
name: string;
role: "admin" | "user";
}
// 密码哈希
export function hashPassword(password: string, salt: string): string {
return createHash("sha256").update(salt + password).digest("hex");
}
// 生成密码哈希(用于创建用户)
export function generatePasswordHash(password: string): { hash: string; salt: string } {
const salt = randomBytes(16).toString("hex");
const hash = hashPassword(password, salt);
return { hash, salt };
}
// 从请求头获取用户信息
export function getAuthFromRequest(request: Request): User | null {
const authHeader = request.headers.get("X-Auth-User");
if (!authHeader) return null;
const stored = findStoredUser(authHeader);
if (!stored) return null;
return { username: stored.username, name: stored.name, role: stored.role };
}
// 查找用户
function findStoredUser(username: string): StoredUser | null {
const users = loadStoredUsers();
return users.find(u => u.username === username) || null;
}
// 认证用户
export function authenticateUser(username: string, password: string): User | null {
const stored = findStoredUser(username);
if (!stored) return null;
const hash = hashPassword(password, stored.salt);
if (hash !== stored.passwordHash) return null;
return { username: stored.username, name: stored.name, role: stored.role };
}
// 加载用户列表
function loadStoredUsers(): StoredUser[] {
try {
const usersPath = path.join(process.cwd(), "users.json");
if (!fs.existsSync(usersPath)) return [];
const data = JSON.parse(fs.readFileSync(usersPath, "utf-8"));
return data.users || [];
} catch {
return [];
}
}
// 是否是管理员
export function isAdmin(request: Request): boolean {
const user = getAuthFromRequest(request);
return user?.role === "admin";
}
+5 -1
View File
@@ -76,8 +76,9 @@ export function listPosts(options?: {
page?: number;
perPage?: number;
includeDrafts?: boolean;
author?: string;
}): { posts: PostListItem[]; total: number; totalPages: number } {
const { search = "", page = 1, perPage = ITEMS_PER_PAGE, includeDrafts = true } = options || {};
const { search = "", page = 1, perPage = ITEMS_PER_PAGE, includeDrafts = true, author } = options || {};
const dirs = findPostDirectories();
const allPosts: PostListItem[] = [];
@@ -102,6 +103,9 @@ export function listPosts(options?: {
if (!includeDrafts && post.draft) continue;
// 按作者过滤
if (author && post.author !== author) continue;
if (search) {
const q = search.toLowerCase();
const match =
+2 -4
View File
@@ -1,8 +1,6 @@
import { DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL } from "@/lib/config";
// 语音转文字:使用 OpenAI Whisper API 或其他兼容服务
const WHISPER_API_KEY = process.env.WHISPER_API_KEY || DEEPSEEK_API_KEY || "";
const WHISPER_API_BASE = process.env.WHISPER_API_BASE || (DEEPSEEK_API_KEY ? DEEPSEEK_BASE_URL : "https://api.openai.com/v1");
const WHISPER_API_KEY = process.env.WHISPER_API_KEY || process.env.DEEPSEEK_API_KEY || "";
const WHISPER_API_BASE = process.env.WHISPER_API_BASE || process.env.DEEPSEEK_BASE_URL || "https://api.openai.com/v1";
const WHISPER_MODEL = process.env.WHISPER_MODEL || "whisper-1";
export async function transcribeAudio(audioBuffer: ArrayBuffer, filename: string): Promise<string> {