用户组增加权限控制
This commit is contained in:
@@ -5,6 +5,7 @@ import { parseStringPromise } from 'xml2js';
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { getMagnetBaseUrl, universalMagnetFetch } from '@/lib/magnet.client';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -16,7 +17,7 @@ export async function POST(req: NextRequest) {
|
||||
try {
|
||||
// 检查权限
|
||||
const authInfo = getAuthInfoFromCookie(req);
|
||||
if (!authInfo || (authInfo.role !== 'admin' && authInfo.role !== 'owner')) {
|
||||
if (!authInfo?.username || !(await hasFeaturePermission(authInfo.username, 'magnet_search'))) {
|
||||
return NextResponse.json(
|
||||
{ error: '无权限访问' },
|
||||
{ status: 403 }
|
||||
|
||||
@@ -5,6 +5,7 @@ import { parseStringPromise } from 'xml2js';
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { getMagnetBaseUrl, universalMagnetFetch } from '@/lib/magnet.client';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -17,7 +18,7 @@ export const runtime = 'nodejs';
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const authInfo = getAuthInfoFromCookie(req);
|
||||
if (!authInfo || (authInfo.role !== 'admin' && authInfo.role !== 'owner')) {
|
||||
if (!authInfo?.username || !(await hasFeaturePermission(authInfo.username, 'magnet_search'))) {
|
||||
return NextResponse.json(
|
||||
{ error: '无权限访问' },
|
||||
{ status: 403 }
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -15,7 +16,7 @@ export async function POST(req: NextRequest) {
|
||||
try {
|
||||
// 检查权限
|
||||
const authInfo = getAuthInfoFromCookie(req);
|
||||
if (!authInfo || (authInfo.role !== 'admin' && authInfo.role !== 'owner')) {
|
||||
if (!authInfo?.username || !(await hasFeaturePermission(authInfo.username, 'magnet_save_private_library'))) {
|
||||
return NextResponse.json(
|
||||
{ error: '无权限访问' },
|
||||
{ status: 403 }
|
||||
|
||||
@@ -5,6 +5,7 @@ import { parseStringPromise } from 'xml2js';
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { getMagnetBaseUrl, universalMagnetFetch } from '@/lib/magnet.client';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -22,7 +23,7 @@ export async function POST(req: NextRequest) {
|
||||
try {
|
||||
// 检查权限
|
||||
const authInfo = getAuthInfoFromCookie(req);
|
||||
if (!authInfo || (authInfo.role !== 'admin' && authInfo.role !== 'owner')) {
|
||||
if (!authInfo?.username || !(await hasFeaturePermission(authInfo.username, 'magnet_search'))) {
|
||||
return NextResponse.json(
|
||||
{ error: '无权限访问' },
|
||||
{ status: 403 }
|
||||
|
||||
@@ -58,7 +58,6 @@ export async function POST(request: NextRequest) {
|
||||
EnableVideoCardEntry,
|
||||
EnablePlayPageEntry,
|
||||
EnableAIComments,
|
||||
AllowRegularUsers,
|
||||
Temperature,
|
||||
MaxTokens,
|
||||
SystemPrompt,
|
||||
@@ -95,7 +94,6 @@ export async function POST(request: NextRequest) {
|
||||
EnableVideoCardEntry: boolean;
|
||||
EnablePlayPageEntry: boolean;
|
||||
EnableAIComments: boolean;
|
||||
AllowRegularUsers: boolean;
|
||||
Temperature?: number;
|
||||
MaxTokens?: number;
|
||||
SystemPrompt?: string;
|
||||
@@ -135,7 +133,6 @@ export async function POST(request: NextRequest) {
|
||||
typeof EnableVideoCardEntry !== 'boolean' ||
|
||||
typeof EnablePlayPageEntry !== 'boolean' ||
|
||||
typeof EnableAIComments !== 'boolean' ||
|
||||
typeof AllowRegularUsers !== 'boolean' ||
|
||||
(Temperature !== undefined && typeof Temperature !== 'number') ||
|
||||
(MaxTokens !== undefined && typeof MaxTokens !== 'number') ||
|
||||
(SystemPrompt !== undefined && typeof SystemPrompt !== 'string') ||
|
||||
@@ -185,7 +182,6 @@ export async function POST(request: NextRequest) {
|
||||
EnableVideoCardEntry,
|
||||
EnablePlayPageEntry,
|
||||
EnableAIComments,
|
||||
AllowRegularUsers,
|
||||
Temperature,
|
||||
MaxTokens,
|
||||
SystemPrompt,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { db } from '@/lib/db';
|
||||
import { sanitizeFeaturePermissions } from '@/lib/feature-permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -356,11 +357,13 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
case 'userGroup': {
|
||||
// 用户组管理操作
|
||||
const { groupAction, groupName, enabledApis } = body as {
|
||||
const { groupAction, groupName, enabledApis, permissions } = body as {
|
||||
groupAction: 'add' | 'edit' | 'delete';
|
||||
groupName: string;
|
||||
enabledApis?: string[];
|
||||
permissions?: string[];
|
||||
};
|
||||
const normalizedPermissions = sanitizeFeaturePermissions(permissions);
|
||||
|
||||
if (!adminConfig.UserConfig.Tags) {
|
||||
adminConfig.UserConfig.Tags = [];
|
||||
@@ -375,6 +378,7 @@ export async function POST(request: NextRequest) {
|
||||
adminConfig.UserConfig.Tags.push({
|
||||
name: groupName,
|
||||
enabledApis: enabledApis || [],
|
||||
permissions: normalizedPermissions,
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -384,6 +388,7 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({ error: '用户组不存在' }, { status: 404 });
|
||||
}
|
||||
adminConfig.UserConfig.Tags[groupIndex].enabledApis = enabledApis || [];
|
||||
adminConfig.UserConfig.Tags[groupIndex].permissions = normalizedPermissions;
|
||||
break;
|
||||
}
|
||||
case 'delete': {
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from '@/lib/ai-orchestrator';
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { db } from '@/lib/db';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -212,6 +212,10 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
if (!(await hasFeaturePermission(authInfo.username, 'ai_ask'))) {
|
||||
return NextResponse.json({ error: '无权限使用 AI 问片功能' }, { status: 403 });
|
||||
}
|
||||
|
||||
// 2. 获取AI配置
|
||||
const adminConfig = await getConfig();
|
||||
const aiConfig = adminConfig.AIConfig;
|
||||
@@ -223,23 +227,7 @@ export async function POST(request: NextRequest) {
|
||||
);
|
||||
}
|
||||
|
||||
// 3. 权限检查:如果不允许普通用户使用,检查用户角色
|
||||
if (!aiConfig.AllowRegularUsers) {
|
||||
const username = authInfo.username;
|
||||
// 站长始终有权限
|
||||
if (username !== process.env.USERNAME) {
|
||||
// 检查是否为管理员
|
||||
const userInfo = await db.getUserInfoV2(username);
|
||||
if (!userInfo || (userInfo.role !== 'admin' && userInfo.role !== 'owner') || userInfo.banned) {
|
||||
return NextResponse.json(
|
||||
{ error: '该功能仅限站长和管理员使用' },
|
||||
{ status: 403 }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 解析请求参数
|
||||
// 3. 解析请求参数
|
||||
const body = (await request.json()) as ChatRequest;
|
||||
const { message, context, history = [] } = body;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { EmbyClient } from '@/lib/emby.client';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -45,7 +46,8 @@ export async function GET(
|
||||
if (username) {
|
||||
// 检查用户是否被封禁
|
||||
const userInfo = await db.getUserInfoV2(username);
|
||||
if (userInfo && !userInfo.banned) {
|
||||
const allowed = await hasFeaturePermission(username, 'emby');
|
||||
if (userInfo && !userInfo.banned && allowed) {
|
||||
isValidToken = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { embyManager } from '@/lib/emby-manager';
|
||||
import { getProxyToken } from '@/lib/emby-token';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -17,6 +18,8 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'emby', '无权限访问 Emby');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 获取Emby客户端
|
||||
const client = await embyManager.getClient(embyKey);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -54,14 +55,18 @@ export async function GET(
|
||||
if (username) {
|
||||
// 检查用户是否被封禁
|
||||
const userInfo = await db.getUserInfoV2(username);
|
||||
if (userInfo && !userInfo.banned) {
|
||||
const allowed = await hasFeaturePermission(username, 'emby');
|
||||
if (userInfo && !userInfo.banned && allowed) {
|
||||
hasValidToken = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 验证用户登录
|
||||
const hasValidAuth = authInfo && authInfo.username;
|
||||
const hasValidAuth = !!(
|
||||
authInfo?.username &&
|
||||
(await hasFeaturePermission(authInfo.username, 'emby'))
|
||||
);
|
||||
|
||||
// 两者至少满足其一
|
||||
if (!hasValidToken && !hasValidAuth) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getCachedEmbyList, setCachedEmbyList } from '@/lib/emby-cache';
|
||||
import { embyManager } from '@/lib/emby-manager';
|
||||
import { getProxyToken } from '@/lib/emby-token';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -18,6 +19,8 @@ export async function GET(request: NextRequest) {
|
||||
const sortOrder = searchParams.get('sortOrder') || 'Ascending';
|
||||
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'emby', '无权限访问 Emby');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 判断是否是默认排序(只有默认排序才使用缓存)
|
||||
const isDefaultSort = sortBy === 'SortName' && sortOrder === 'Ascending';
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -55,14 +56,18 @@ export async function GET(
|
||||
if (username) {
|
||||
// 检查用户是否被封禁
|
||||
const userInfo = await db.getUserInfoV2(username);
|
||||
if (userInfo && !userInfo.banned) {
|
||||
const allowed = await hasFeaturePermission(username, 'emby');
|
||||
if (userInfo && !userInfo.banned && allowed) {
|
||||
hasValidToken = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 验证用户登录
|
||||
const hasValidAuth = authInfo && authInfo.username;
|
||||
const hasValidAuth = !!(
|
||||
authInfo?.username &&
|
||||
(await hasFeaturePermission(authInfo.username, 'emby'))
|
||||
);
|
||||
|
||||
// 两者至少满足其一
|
||||
if (!hasValidToken && !hasValidAuth) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { embyManager } from '@/lib/emby-manager';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
export const dynamic = 'force-dynamic'; // 禁用缓存
|
||||
@@ -8,8 +9,10 @@ export const dynamic = 'force-dynamic'; // 禁用缓存
|
||||
/**
|
||||
* 获取所有启用的Emby源列表
|
||||
*/
|
||||
export async function GET() {
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'emby', '无权限访问 Emby');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const sources = await embyManager.getEnabledSources();
|
||||
|
||||
return NextResponse.json({
|
||||
|
||||
@@ -4,11 +4,14 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getCachedEmbyViews, setCachedEmbyViews } from '@/lib/emby-cache';
|
||||
import { embyManager } from '@/lib/emby-manager';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'emby', '无权限访问 Emby');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { searchParams } = new URL(request.url);
|
||||
const embyKey = searchParams.get('embyKey') || undefined;
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getCachedLiveChannels } from '@/lib/live';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'live', '无权限访问电视直播');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { searchParams } = new URL(request.url);
|
||||
const sourceKey = searchParams.get('source');
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getCachedLiveChannels } from '@/lib/live';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'live', '无权限访问电视直播');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { searchParams } = new URL(request.url);
|
||||
const sourceKey = searchParams.get('source');
|
||||
const tvgId = searchParams.get('tvgId');
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const authResult = await requireFeaturePermission(request, 'live', '无权限访问电视直播');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { searchParams } = new URL(request.url);
|
||||
const url = searchParams.get('url');
|
||||
const source = searchParams.get('moontv-source');
|
||||
@@ -51,4 +54,4 @@ export async function GET(request: NextRequest) {
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error: 'Failed to fetch', message: error }, { status: 500 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
console.log(request.url)
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'live', '无权限访问电视直播');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const config = await getConfig();
|
||||
|
||||
if (!config) {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { db } from '@/lib/db';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export async function getAuthorizedUsername(request: NextRequest): Promise<string | NextResponse> {
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
@@ -19,5 +20,10 @@ export async function getAuthorizedUsername(request: NextRequest): Promise<strin
|
||||
}
|
||||
}
|
||||
|
||||
const allowed = await hasFeaturePermission(authInfo.username, 'manga');
|
||||
if (!allowed) {
|
||||
return NextResponse.json({ error: '无权限访问漫画功能' }, { status: 403 });
|
||||
}
|
||||
|
||||
return authInfo.username;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -30,6 +31,8 @@ async function getOpenListClient(): Promise<OpenListClient | null> {
|
||||
// 代理OpenList缓存的音频文件
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { searchParams } = new URL(request.url);
|
||||
const platform = searchParams.get('platform');
|
||||
const id = searchParams.get('id');
|
||||
|
||||
@@ -5,12 +5,15 @@ import { randomUUID } from 'crypto';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { db } from '@/lib/db';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
// GET - 获取用户的所有歌单
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
@@ -43,6 +46,8 @@ export async function GET(request: NextRequest) {
|
||||
// POST - 创建新歌单
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
@@ -93,6 +98,8 @@ export async function POST(request: NextRequest) {
|
||||
// PUT - 更新歌单信息
|
||||
export async function PUT(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
@@ -151,6 +158,8 @@ export async function PUT(request: NextRequest) {
|
||||
// DELETE - 删除歌单
|
||||
export async function DELETE(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
|
||||
@@ -4,12 +4,15 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { db } from '@/lib/db';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
// GET - 获取歌单中的所有歌曲
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
@@ -61,6 +64,8 @@ export async function GET(request: NextRequest) {
|
||||
// POST - 添加歌曲到歌单
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
@@ -136,6 +141,8 @@ export async function POST(request: NextRequest) {
|
||||
// DELETE - 从歌单中移除歌曲
|
||||
export async function DELETE(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { db } from '@/lib/db';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { MusicPlayRecord } from '@/lib/db.client';
|
||||
import { getCachedSongs, setCachedSong } from '@/lib/music-song-cache';
|
||||
|
||||
@@ -11,6 +12,8 @@ export const runtime = 'nodejs';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
@@ -63,6 +66,8 @@ export async function GET(request: NextRequest) {
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
@@ -181,6 +186,8 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
export async function DELETE(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 从 cookie 获取用户信息
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
// 代理音频流
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { searchParams } = new URL(request.url);
|
||||
const url = searchParams.get('url');
|
||||
|
||||
|
||||
+25
-20
@@ -3,6 +3,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -20,19 +21,19 @@ const serverCache = {
|
||||
// 正在下载的音频任务追踪(防止重复下载)
|
||||
const downloadingTasks = new Map<string, Promise<void>>();
|
||||
|
||||
// 获取 TuneHub 配置
|
||||
async function getTuneHubConfig() {
|
||||
// 获取音乐服务配置
|
||||
async function getMusicServiceConfig() {
|
||||
const config = await getConfig();
|
||||
const musicConfig = config?.MusicConfig;
|
||||
|
||||
const enabled = musicConfig?.TuneHubEnabled ?? false;
|
||||
const enabled = musicConfig?.Enabled ?? false;
|
||||
const baseUrl =
|
||||
musicConfig?.TuneHubBaseUrl ||
|
||||
process.env.TUNEHUB_BASE_URL ||
|
||||
'https://tunehub.sayqz.com/api';
|
||||
const apiKey = musicConfig?.TuneHubApiKey || process.env.TUNEHUB_API_KEY || '';
|
||||
musicConfig?.BaseUrl ||
|
||||
process.env.MUSIC_V2_BASE_URL ||
|
||||
'';
|
||||
const token = musicConfig?.Token || process.env.MUSIC_V2_TOKEN || '';
|
||||
|
||||
return { enabled, baseUrl, apiKey, musicConfig };
|
||||
return { enabled, baseUrl, token, musicConfig };
|
||||
}
|
||||
|
||||
// 获取 OpenList 客户端
|
||||
@@ -135,7 +136,7 @@ async function replaceAudioUrlsWithOpenList(
|
||||
return data;
|
||||
}
|
||||
|
||||
// TuneHub 返回的数据结构是 { code: 0, data: { data: [...], total: 1 } }
|
||||
// 音乐服务返回的数据结构是 { code: 0, data: { data: [...], total: 1 } }
|
||||
// 需要提取内层的 data 数组
|
||||
const songsData = data.data.data || data.data;
|
||||
const songs = Array.isArray(songsData) ? songsData : [songsData];
|
||||
@@ -205,7 +206,7 @@ async function proxyRequest(
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('TuneHub API 请求失败:', error);
|
||||
console.error('Music API 请求失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -394,7 +395,9 @@ async function executeMethod(
|
||||
// GET 请求处理
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { enabled, baseUrl } = await getTuneHubConfig();
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { enabled, baseUrl } = await getMusicServiceConfig();
|
||||
|
||||
if (!enabled) {
|
||||
return NextResponse.json(
|
||||
@@ -544,7 +547,9 @@ export async function GET(request: NextRequest) {
|
||||
// POST 请求处理(用于解析歌曲)
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const { enabled, baseUrl, apiKey } = await getTuneHubConfig();
|
||||
const authResult = await requireFeaturePermission(request, 'music', '无权限访问音乐功能');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { enabled, baseUrl, token } = await getMusicServiceConfig();
|
||||
|
||||
if (!enabled) {
|
||||
return NextResponse.json(
|
||||
@@ -565,13 +570,13 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
switch (action) {
|
||||
case 'parse': {
|
||||
// 解析歌曲(需要 API Key)
|
||||
if (!apiKey) {
|
||||
// 解析歌曲(需要 Token)
|
||||
if (!token) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: -1,
|
||||
error: '未配置 TuneHub API Key',
|
||||
message: '未配置 TuneHub API Key'
|
||||
error: '未配置音乐服务 Token',
|
||||
message: '未配置音乐服务 Token'
|
||||
},
|
||||
{ status: 403 }
|
||||
);
|
||||
@@ -650,17 +655,17 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// OpenList 缓存未命中,继续调用 TuneHub
|
||||
// OpenList 缓存未命中,继续调用音乐服务
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 调用 TuneHub API 解析
|
||||
// 4. 调用音乐服务解析
|
||||
try {
|
||||
const response = await proxyRequest(`${baseUrl}/v1/parse`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': apiKey,
|
||||
'X-API-Key': token,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
platform,
|
||||
@@ -671,7 +676,7 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// 如果 TuneHub 返回错误,包装成统一格式
|
||||
// 如果音乐服务返回错误,包装成统一格式
|
||||
if (!response.ok || data.code !== 0) {
|
||||
return NextResponse.json({
|
||||
code: data.code || -1,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { createQuarkInstantPlayFolder } from '@/lib/netdisk/quark.client';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
import { base58Encode } from '@/lib/utils';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -21,6 +22,9 @@ export async function POST(request: NextRequest) {
|
||||
if (!authInfo?.username) {
|
||||
return NextResponse.json({ error: '未登录' }, { status: 401 });
|
||||
}
|
||||
if (!(await hasFeaturePermission(authInfo.username, 'netdisk_temp_play'))) {
|
||||
return NextResponse.json({ error: '无权限使用临时播放' }, { status: 403 });
|
||||
}
|
||||
|
||||
const { shareUrl, passcode, title } = await request.json();
|
||||
if (!shareUrl) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { transferQuarkShare } from '@/lib/netdisk/quark.client';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -12,6 +13,9 @@ export async function POST(request: NextRequest) {
|
||||
if (!authInfo?.username) {
|
||||
return NextResponse.json({ error: '未登录' }, { status: 401 });
|
||||
}
|
||||
if (!(await hasFeaturePermission(authInfo.username, 'netdisk_transfer'))) {
|
||||
return NextResponse.json({ error: '无权限使用网盘转存' }, { status: 403 });
|
||||
}
|
||||
|
||||
const { shareUrl, passcode } = await request.json();
|
||||
if (!shareUrl) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -13,6 +14,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'private_library', '无权限访问私人影库');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 权限检查
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -44,7 +45,8 @@ export async function GET(
|
||||
if (username) {
|
||||
// 检查用户是否被封禁
|
||||
const userInfo = await db.getUserInfoV2(username);
|
||||
if (userInfo && !userInfo.banned) {
|
||||
const allowed = await hasFeaturePermission(username, 'private_library');
|
||||
if (userInfo && !userInfo.banned && allowed) {
|
||||
isValidToken = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { db } from '@/lib/db';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
import {
|
||||
@@ -21,6 +22,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'private_library', '无权限访问私人影库');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { db } from '@/lib/db';
|
||||
import {
|
||||
invalidateMetaInfoCache,
|
||||
@@ -19,6 +20,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'private_library', '无权限访问私人影库');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 权限检查
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
import {
|
||||
getCachedVideoInfo,
|
||||
@@ -20,6 +21,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'private_library', '无权限访问私人影库');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { db } from '@/lib/db';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
import {
|
||||
@@ -21,6 +22,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'private_library', '无权限访问私人影库');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -39,14 +40,18 @@ export async function GET(
|
||||
if (username) {
|
||||
// 检查用户是否被封禁
|
||||
const userInfo = await db.getUserInfoV2(username);
|
||||
if (userInfo && !userInfo.banned) {
|
||||
const allowed = await hasFeaturePermission(username, 'private_library');
|
||||
if (userInfo && !userInfo.banned && allowed) {
|
||||
hasValidToken = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 验证用户登录
|
||||
const hasValidAuth = authInfo && authInfo.username;
|
||||
const hasValidAuth = !!(
|
||||
authInfo?.username &&
|
||||
(await hasFeaturePermission(authInfo.username, 'private_library'))
|
||||
);
|
||||
|
||||
// 两者至少满足其一
|
||||
if (!hasValidToken && !hasValidAuth) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -65,6 +66,8 @@ async function getFinalUrl(url: string, maxRedirects = 5): Promise<string> {
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'private_library', '无权限访问私人影库');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { OpenListClient } from '@/lib/openlist.client';
|
||||
import { invalidateVideoInfoCache } from '@/lib/openlist-cache';
|
||||
|
||||
@@ -15,6 +16,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'private_library', '无权限访问私人影库');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { startOpenListRefresh } from '@/lib/openlist-refresh';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -14,6 +15,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'private_library', '无权限访问私人影库');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
// 权限检查
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { getScanTask } from '@/lib/scan-task';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -13,6 +14,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'private_library', '无权限访问私人影库');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { PansouLink, searchPansou } from '@/lib/pansou.client';
|
||||
|
||||
@@ -9,6 +10,13 @@ export const runtime = 'nodejs';
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(
|
||||
request,
|
||||
'netdisk_search',
|
||||
'无权限使用网盘搜索'
|
||||
);
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
|
||||
const body = await request.json();
|
||||
const { keyword } = body;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getAvailableApiSites, getConfig } from '@/lib/config';
|
||||
import { db } from '@/lib/db';
|
||||
import { getCachedLiveChannels } from '@/lib/live';
|
||||
import { hasFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -76,7 +77,12 @@ export async function GET(request: NextRequest) {
|
||||
const apiSites = await getAvailableApiSites(username);
|
||||
|
||||
// 获取直播源
|
||||
const liveConfig = config.LiveConfig?.filter(live => !live.disabled) || [];
|
||||
const canAccessLive = isGlobalToken || !username
|
||||
? true
|
||||
: await hasFeaturePermission(username, 'live');
|
||||
const liveConfig = canAccessLive
|
||||
? config.LiveConfig?.filter(live => !live.disabled) || []
|
||||
: [];
|
||||
|
||||
// 获取当前请求的 origin,用于构建代理链接
|
||||
// 优先级:SITE_BASE 环境变量 > origin 参数 > 从请求头构建
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
function getBaseUrl(url: string): string {
|
||||
const urlObj = new URL(url);
|
||||
const pathParts = urlObj.pathname.split('/');
|
||||
@@ -38,6 +40,8 @@ function processM3u8Content(content: string, baseUrl: string): string {
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'web_live', '无权限访问网络直播');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { searchParams } = new URL(request.url);
|
||||
const url = searchParams.get('url');
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const dynamic = 'force-dynamic'; // 禁用缓存
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'web_live', '无权限访问网络直播');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const config = await getConfig();
|
||||
if (!config?.WebLiveConfig) {
|
||||
return NextResponse.json([]);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import crypto from 'crypto';
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
function getAntiCode(oldAntiCode: string, streamName: string): string {
|
||||
const paramsT = 100;
|
||||
const sdkVersion = 2403051612;
|
||||
@@ -206,6 +208,8 @@ async function getDouyinStream(roomId: string) {
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'web_live', '无权限访问网络直播');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const { searchParams } = new URL(request.url);
|
||||
const platform = searchParams.get('platform');
|
||||
const roomId = searchParams.get('roomId');
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { XiaoyaClient } from '@/lib/xiaoya.client';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -14,6 +15,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'xiaoya', '无权限访问小雅');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
import { XiaoyaClient } from '@/lib/xiaoya.client';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -66,6 +67,8 @@ async function getFinalUrl(url: string, maxRedirects = 5): Promise<string> {
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'xiaoya', '无权限访问小雅');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { requireFeaturePermission } from '@/lib/permissions';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -13,6 +14,8 @@ export const runtime = 'nodejs';
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await requireFeaturePermission(request, 'xiaoya', '无权限访问小雅');
|
||||
if (authResult instanceof NextResponse) return authResult;
|
||||
const authInfo = getAuthInfoFromCookie(request);
|
||||
if (!authInfo || !authInfo.username) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
|
||||
Reference in New Issue
Block a user