diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx
index 5816a48..d564984 100644
--- a/src/app/admin/page.tsx
+++ b/src/app/admin/page.tsx
@@ -135,9 +135,6 @@ interface UserConfigProps {
}
const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => {
- const [userSettings, setUserSettings] = useState({
- enableRegistration: false,
- });
const [showAddUserForm, setShowAddUserForm] = useState(false);
const [showChangePasswordForm, setShowChangePasswordForm] = useState(false);
const [newUser, setNewUser] = useState({
@@ -152,41 +149,9 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => {
// 当前登录用户名
const currentUsername = getAuthInfoFromBrowserCookie()?.username || null;
- useEffect(() => {
- if (config?.UserConfig) {
- setUserSettings({
- enableRegistration: config.UserConfig.AllowRegister,
- });
- }
- }, [config]);
- // 切换允许注册设置
- const toggleAllowRegister = async (value: boolean) => {
- try {
- // 先更新本地 UI
- setUserSettings((prev) => ({ ...prev, enableRegistration: value }));
- const res = await fetch('/api/admin/user', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- action: 'setAllowRegister',
- allowRegister: value,
- }),
- });
- if (!res.ok) {
- const data = await res.json().catch(() => ({}));
- throw new Error(data.error || `操作失败: ${res.status}`);
- }
-
- await refreshConfig();
- } catch (err) {
- showError(err instanceof Error ? err.message : '操作失败');
- // revert toggle UI
- setUserSettings((prev) => ({ ...prev, enableRegistration: !value }));
- }
- };
const handleBanUser = async (uname: string) => {
await handleUserAction('ban', uname);
@@ -305,36 +270,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => {
- {/* 注册设置 */}
-
diff --git a/src/app/api/admin/user/route.ts b/src/app/api/admin/user/route.ts
index a926c16..aaa012e 100644
--- a/src/app/api/admin/user/route.ts
+++ b/src/app/api/admin/user/route.ts
@@ -15,7 +15,6 @@ const ACTIONS = [
'unban',
'setAdmin',
'cancelAdmin',
- 'setAllowRegister',
'changePassword',
'deleteUser',
] as const;
@@ -43,12 +42,10 @@ export async function POST(request: NextRequest) {
const {
targetUsername, // 目标用户名
targetPassword, // 目标用户密码(仅在添加用户时需要)
- allowRegister,
action,
} = body as {
targetUsername?: string;
targetPassword?: string;
- allowRegister?: boolean;
action?: (typeof ACTIONS)[number];
};
@@ -56,12 +53,11 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ error: '参数格式错误' }, { status: 400 });
}
- if (action !== 'setAllowRegister' && !targetUsername) {
+ if (!targetUsername) {
return NextResponse.json({ error: '缺少目标用户名' }, { status: 400 });
}
if (
- action !== 'setAllowRegister' &&
action !== 'changePassword' &&
action !== 'deleteUser' &&
username === targetUsername
@@ -105,188 +101,180 @@ export async function POST(request: NextRequest) {
// 权限校验逻辑
const isTargetAdmin = targetEntry?.role === 'admin';
- if (action === 'setAllowRegister') {
- if (typeof allowRegister !== 'boolean') {
- return NextResponse.json({ error: '参数格式错误' }, { status: 400 });
- }
- adminConfig.UserConfig.AllowRegister = allowRegister;
- // 保存后直接返回成功(走后面的统一保存逻辑)
- } else {
- switch (action) {
- case 'add': {
- if (targetEntry) {
- return NextResponse.json({ error: '用户已存在' }, { status: 400 });
- }
- if (!targetPassword) {
- return NextResponse.json(
- { error: '缺少目标用户密码' },
- { status: 400 }
- );
- }
- await db.registerUser(targetUsername!, targetPassword);
- // 更新配置
- adminConfig.UserConfig.Users.push({
- username: targetUsername!,
- role: 'user',
- });
- targetEntry =
- adminConfig.UserConfig.Users[
- adminConfig.UserConfig.Users.length - 1
- ];
- break;
+ switch (action) {
+ case 'add': {
+ if (targetEntry) {
+ return NextResponse.json({ error: '用户已存在' }, { status: 400 });
}
- case 'ban': {
- if (!targetEntry) {
- return NextResponse.json(
- { error: '目标用户不存在' },
- { status: 404 }
- );
- }
- if (isTargetAdmin) {
- // 目标是管理员
- if (operatorRole !== 'owner') {
- return NextResponse.json(
- { error: '仅站长可封禁管理员' },
- { status: 401 }
- );
- }
- }
- targetEntry.banned = true;
- break;
- }
- case 'unban': {
- if (!targetEntry) {
- return NextResponse.json(
- { error: '目标用户不存在' },
- { status: 404 }
- );
- }
- if (isTargetAdmin) {
- if (operatorRole !== 'owner') {
- return NextResponse.json(
- { error: '仅站长可操作管理员' },
- { status: 401 }
- );
- }
- }
- targetEntry.banned = false;
- break;
- }
- case 'setAdmin': {
- if (!targetEntry) {
- return NextResponse.json(
- { error: '目标用户不存在' },
- { status: 404 }
- );
- }
- if (targetEntry.role === 'admin') {
- return NextResponse.json(
- { error: '该用户已是管理员' },
- { status: 400 }
- );
- }
- if (operatorRole !== 'owner') {
- return NextResponse.json(
- { error: '仅站长可设置管理员' },
- { status: 401 }
- );
- }
- targetEntry.role = 'admin';
- break;
- }
- case 'cancelAdmin': {
- if (!targetEntry) {
- return NextResponse.json(
- { error: '目标用户不存在' },
- { status: 404 }
- );
- }
- if (targetEntry.role !== 'admin') {
- return NextResponse.json(
- { error: '目标用户不是管理员' },
- { status: 400 }
- );
- }
- if (operatorRole !== 'owner') {
- return NextResponse.json(
- { error: '仅站长可取消管理员' },
- { status: 401 }
- );
- }
- targetEntry.role = 'user';
- break;
- }
- case 'changePassword': {
- if (!targetEntry) {
- return NextResponse.json(
- { error: '目标用户不存在' },
- { status: 404 }
- );
- }
- if (!targetPassword) {
- return NextResponse.json({ error: '缺少新密码' }, { status: 400 });
- }
-
- // 权限检查:不允许修改站长密码
- if (targetEntry.role === 'owner') {
- return NextResponse.json(
- { error: '无法修改站长密码' },
- { status: 401 }
- );
- }
-
- if (
- isTargetAdmin &&
- operatorRole !== 'owner' &&
- username !== targetUsername
- ) {
- return NextResponse.json(
- { error: '仅站长可修改其他管理员密码' },
- { status: 401 }
- );
- }
-
- await db.changePassword(targetUsername!, targetPassword);
- break;
- }
- case 'deleteUser': {
- if (!targetEntry) {
- return NextResponse.json(
- { error: '目标用户不存在' },
- { status: 404 }
- );
- }
-
- // 权限检查:站长可删除所有用户(除了自己),管理员可删除普通用户
- if (username === targetUsername) {
- return NextResponse.json(
- { error: '不能删除自己' },
- { status: 400 }
- );
- }
-
- if (isTargetAdmin && operatorRole !== 'owner') {
- return NextResponse.json(
- { error: '仅站长可删除管理员' },
- { status: 401 }
- );
- }
-
- await db.deleteUser(targetUsername!);
-
- // 从配置中移除用户
- const userIndex = adminConfig.UserConfig.Users.findIndex(
- (u) => u.username === targetUsername
+ if (!targetPassword) {
+ return NextResponse.json(
+ { error: '缺少目标用户密码' },
+ { status: 400 }
);
- if (userIndex > -1) {
- adminConfig.UserConfig.Users.splice(userIndex, 1);
- }
-
- break;
}
- default:
- return NextResponse.json({ error: '未知操作' }, { status: 400 });
+ await db.registerUser(targetUsername!, targetPassword);
+ // 更新配置
+ adminConfig.UserConfig.Users.push({
+ username: targetUsername!,
+ role: 'user',
+ });
+ targetEntry =
+ adminConfig.UserConfig.Users[
+ adminConfig.UserConfig.Users.length - 1
+ ];
+ break;
}
+ case 'ban': {
+ if (!targetEntry) {
+ return NextResponse.json(
+ { error: '目标用户不存在' },
+ { status: 404 }
+ );
+ }
+ if (isTargetAdmin) {
+ // 目标是管理员
+ if (operatorRole !== 'owner') {
+ return NextResponse.json(
+ { error: '仅站长可封禁管理员' },
+ { status: 401 }
+ );
+ }
+ }
+ targetEntry.banned = true;
+ break;
+ }
+ case 'unban': {
+ if (!targetEntry) {
+ return NextResponse.json(
+ { error: '目标用户不存在' },
+ { status: 404 }
+ );
+ }
+ if (isTargetAdmin) {
+ if (operatorRole !== 'owner') {
+ return NextResponse.json(
+ { error: '仅站长可操作管理员' },
+ { status: 401 }
+ );
+ }
+ }
+ targetEntry.banned = false;
+ break;
+ }
+ case 'setAdmin': {
+ if (!targetEntry) {
+ return NextResponse.json(
+ { error: '目标用户不存在' },
+ { status: 404 }
+ );
+ }
+ if (targetEntry.role === 'admin') {
+ return NextResponse.json(
+ { error: '该用户已是管理员' },
+ { status: 400 }
+ );
+ }
+ if (operatorRole !== 'owner') {
+ return NextResponse.json(
+ { error: '仅站长可设置管理员' },
+ { status: 401 }
+ );
+ }
+ targetEntry.role = 'admin';
+ break;
+ }
+ case 'cancelAdmin': {
+ if (!targetEntry) {
+ return NextResponse.json(
+ { error: '目标用户不存在' },
+ { status: 404 }
+ );
+ }
+ if (targetEntry.role !== 'admin') {
+ return NextResponse.json(
+ { error: '目标用户不是管理员' },
+ { status: 400 }
+ );
+ }
+ if (operatorRole !== 'owner') {
+ return NextResponse.json(
+ { error: '仅站长可取消管理员' },
+ { status: 401 }
+ );
+ }
+ targetEntry.role = 'user';
+ break;
+ }
+ case 'changePassword': {
+ if (!targetEntry) {
+ return NextResponse.json(
+ { error: '目标用户不存在' },
+ { status: 404 }
+ );
+ }
+ if (!targetPassword) {
+ return NextResponse.json({ error: '缺少新密码' }, { status: 400 });
+ }
+
+ // 权限检查:不允许修改站长密码
+ if (targetEntry.role === 'owner') {
+ return NextResponse.json(
+ { error: '无法修改站长密码' },
+ { status: 401 }
+ );
+ }
+
+ if (
+ isTargetAdmin &&
+ operatorRole !== 'owner' &&
+ username !== targetUsername
+ ) {
+ return NextResponse.json(
+ { error: '仅站长可修改其他管理员密码' },
+ { status: 401 }
+ );
+ }
+
+ await db.changePassword(targetUsername!, targetPassword);
+ break;
+ }
+ case 'deleteUser': {
+ if (!targetEntry) {
+ return NextResponse.json(
+ { error: '目标用户不存在' },
+ { status: 404 }
+ );
+ }
+
+ // 权限检查:站长可删除所有用户(除了自己),管理员可删除普通用户
+ if (username === targetUsername) {
+ return NextResponse.json(
+ { error: '不能删除自己' },
+ { status: 400 }
+ );
+ }
+
+ if (isTargetAdmin && operatorRole !== 'owner') {
+ return NextResponse.json(
+ { error: '仅站长可删除管理员' },
+ { status: 401 }
+ );
+ }
+
+ await db.deleteUser(targetUsername!);
+
+ // 从配置中移除用户
+ const userIndex = adminConfig.UserConfig.Users.findIndex(
+ (u) => u.username === targetUsername
+ );
+ if (userIndex > -1) {
+ adminConfig.UserConfig.Users.splice(userIndex, 1);
+ }
+
+ break;
+ }
+ default:
+ return NextResponse.json({ error: '未知操作' }, { status: 400 });
}
// 将更新后的配置写入数据库
diff --git a/src/app/api/register/route.ts b/src/app/api/register/route.ts
deleted file mode 100644
index 79ef281..0000000
--- a/src/app/api/register/route.ts
+++ /dev/null
@@ -1,130 +0,0 @@
-/* eslint-disable no-console,@typescript-eslint/no-explicit-any */
-import { NextRequest, NextResponse } from 'next/server';
-
-import { getConfig } from '@/lib/config';
-import { db } from '@/lib/db';
-
-export const runtime = 'nodejs';
-
-// 读取存储类型环境变量,默认 localstorage
-const STORAGE_TYPE =
- (process.env.NEXT_PUBLIC_STORAGE_TYPE as
- | 'localstorage'
- | 'redis'
- | 'upstash'
- | 'kvrocks'
- | undefined) || 'localstorage';
-
-// 生成签名
-async function generateSignature(
- data: string,
- secret: string
-): Promise
{
- const encoder = new TextEncoder();
- const keyData = encoder.encode(secret);
- const messageData = encoder.encode(data);
-
- // 导入密钥
- const key = await crypto.subtle.importKey(
- 'raw',
- keyData,
- { name: 'HMAC', hash: 'SHA-256' },
- false,
- ['sign']
- );
-
- // 生成签名
- const signature = await crypto.subtle.sign('HMAC', key, messageData);
-
- // 转换为十六进制字符串
- return Array.from(new Uint8Array(signature))
- .map((b) => b.toString(16).padStart(2, '0'))
- .join('');
-}
-
-// 生成认证Cookie(带签名)
-async function generateAuthCookie(username: string): Promise {
- const authData: any = {
- role: 'user',
- username,
- timestamp: Date.now(),
- };
-
- // 使用process.env.PASSWORD作为签名密钥,而不是用户密码
- const signingKey = process.env.PASSWORD || '';
- const signature = await generateSignature(username, signingKey);
- authData.signature = signature;
-
- return encodeURIComponent(JSON.stringify(authData));
-}
-
-export async function POST(req: NextRequest) {
- try {
- // localstorage 模式下不支持注册
- if (STORAGE_TYPE === 'localstorage') {
- return NextResponse.json(
- { error: '当前模式不支持注册' },
- { status: 400 }
- );
- }
-
- const config = await getConfig();
- // 校验是否开放注册
- if (!config.UserConfig.AllowRegister) {
- return NextResponse.json({ error: '当前未开放注册' }, { status: 400 });
- }
-
- const { username, password } = await req.json();
-
- if (!username || typeof username !== 'string') {
- return NextResponse.json({ error: '用户名不能为空' }, { status: 400 });
- }
- if (!password || typeof password !== 'string') {
- return NextResponse.json({ error: '密码不能为空' }, { status: 400 });
- }
-
- // 检查是否和管理员重复
- if (username === process.env.USERNAME) {
- return NextResponse.json({ error: '用户已存在' }, { status: 400 });
- }
-
- try {
- // 检查用户是否已存在
- const exist = await db.checkUserExist(username);
- if (exist) {
- return NextResponse.json({ error: '用户已存在' }, { status: 400 });
- }
-
- await db.registerUser(username, password);
-
- // 添加到配置中并保存
- config.UserConfig.Users.push({
- username,
- role: 'user',
- });
- await db.saveAdminConfig(config);
-
- // 注册成功,设置认证cookie
- const response = NextResponse.json({ ok: true });
- const cookieValue = await generateAuthCookie(username);
- const expires = new Date();
- expires.setDate(expires.getDate() + 7); // 7天过期
-
- response.cookies.set('auth', cookieValue, {
- path: '/',
- expires,
- sameSite: 'lax', // 改为 lax 以支持 PWA
- httpOnly: false, // PWA 需要客户端可访问
- secure: false, // 根据协议自动设置
- });
-
- return response;
- } catch (err) {
- console.error('数据库注册失败', err);
- return NextResponse.json({ error: '数据库错误' }, { status: 500 });
- }
- } catch (error) {
- console.error('注册接口异常', error);
- return NextResponse.json({ error: '服务器错误' }, { status: 500 });
- }
-}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index e56f085..ace6098 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -46,7 +46,7 @@ export default async function RootLayout({
let announcement =
process.env.ANNOUNCEMENT ||
'本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。';
- let enableRegister = process.env.NEXT_PUBLIC_ENABLE_REGISTER === 'true';
+
let doubanProxyType = process.env.NEXT_PUBLIC_DOUBAN_PROXY_TYPE || 'melody-cdn-sharon';
let doubanProxy = process.env.NEXT_PUBLIC_DOUBAN_PROXY || '';
let doubanImageProxyType =
@@ -64,7 +64,7 @@ export default async function RootLayout({
const config = await getConfig();
siteName = config.SiteConfig.SiteName;
announcement = config.SiteConfig.Announcement;
- enableRegister = config.UserConfig.AllowRegister;
+
doubanProxyType = config.SiteConfig.DoubanProxyType;
doubanProxy = config.SiteConfig.DoubanProxy;
doubanImageProxyType = config.SiteConfig.DoubanImageProxyType;
@@ -83,7 +83,6 @@ export default async function RootLayout({
// 将运行时配置注入到全局 window 对象,供客户端在运行时读取
const runtimeConfig = {
STORAGE_TYPE: process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage',
- ENABLE_REGISTER: enableRegister,
DOUBAN_PROXY_TYPE: doubanProxyType,
DOUBAN_PROXY: doubanProxy,
DOUBAN_IMAGE_PROXY_TYPE: doubanImageProxyType,
diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx
index 85ddf5d..a0f2e72 100644
--- a/src/app/login/page.tsx
+++ b/src/app/login/page.tsx
@@ -75,7 +75,7 @@ function LoginPageClient() {
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const [shouldAskUsername, setShouldAskUsername] = useState(false);
- const [enableRegister, setEnableRegister] = useState(false);
+
const { siteName } = useSite();
// 在客户端挂载后设置配置
@@ -83,9 +83,6 @@ function LoginPageClient() {
if (typeof window !== 'undefined') {
const storageType = (window as any).RUNTIME_CONFIG?.STORAGE_TYPE;
setShouldAskUsername(storageType && storageType !== 'localstorage');
- setEnableRegister(
- Boolean((window as any).RUNTIME_CONFIG?.ENABLE_REGISTER)
- );
}
}, []);
@@ -122,32 +119,7 @@ function LoginPageClient() {
}
};
- // 处理注册逻辑
- const handleRegister = async () => {
- setError(null);
- if (!password || !username) return;
- try {
- setLoading(true);
- const res = await fetch('/api/register', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username, password }),
- });
-
- if (res.ok) {
- const redirect = searchParams.get('redirect') || '/';
- router.replace(redirect);
- } else {
- const data = await res.json().catch(() => ({}));
- setError(data.error ?? '服务器错误');
- }
- } catch (error) {
- setError('网络错误,请稍后重试');
- } finally {
- setLoading(false);
- }
- };
return (
@@ -195,38 +167,16 @@ function LoginPageClient() {
{error}
)}
- {/* 登录 / 注册按钮 */}
- {shouldAskUsername && enableRegister ? (
-
-
-
-
- ) : (
-
- )}
+ {/* 登录按钮 */}
+
diff --git a/src/lib/admin.types.ts b/src/lib/admin.types.ts
index 8cddf28..0179294 100644
--- a/src/lib/admin.types.ts
+++ b/src/lib/admin.types.ts
@@ -18,7 +18,6 @@ export interface AdminConfig {
FluidSearch: boolean;
};
UserConfig: {
- AllowRegister: boolean;
Users: {
username: string;
role: 'user' | 'admin' | 'owner';
diff --git a/src/lib/config.ts b/src/lib/config.ts
index 521981b..be70cb6 100644
--- a/src/lib/config.ts
+++ b/src/lib/config.ts
@@ -172,7 +172,6 @@ async function getInitConfig(configFile: string, subConfig: {
process.env.NEXT_PUBLIC_FLUID_SEARCH !== 'false',
},
UserConfig: {
- AllowRegister: process.env.NEXT_PUBLIC_ENABLE_REGISTER === 'true',
Users: [],
},
SourceConfig: [],
@@ -251,7 +250,7 @@ export async function getConfig(): Promise {
export function configSelfCheck(adminConfig: AdminConfig): AdminConfig {
// 确保必要的属性存在和初始化
if (!adminConfig.UserConfig) {
- adminConfig.UserConfig = { AllowRegister: false, Users: [] };
+ adminConfig.UserConfig = { Users: [] };
}
if (!adminConfig.UserConfig.Users || !Array.isArray(adminConfig.UserConfig.Users)) {
adminConfig.UserConfig.Users = [];
diff --git a/src/lib/downstream.ts b/src/lib/downstream.ts
index 6cef046..25f0e4a 100644
--- a/src/lib/downstream.ts
+++ b/src/lib/downstream.ts
@@ -58,9 +58,6 @@ async function searchWithCache(
}
const data = await response.json();
- if (apiSite.key === 'xiaomaomi') {
- console.log(data);
- }
if (
!data ||
!data.list ||