用户组增加权限控制

This commit is contained in:
mtvpls
2026-04-22 16:22:17 +08:00
parent 2734de0c85
commit 0916e4ff08
61 changed files with 617 additions and 165 deletions
+3
View File
@@ -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');
+9
View File
@@ -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) {
+7
View File
@@ -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) {
+3
View File
@@ -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
View File
@@ -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,