All files / middleware usageLimit.ts

0% Statements 0/45
0% Branches 0/1
0% Functions 0/1
0% Lines 0/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66                                                                                                                                   
import { Context, Next } from 'koa';
import { prisma } from '../models';
import { QuotaExceededError, ForbiddenError } from './errorHandler';
import { MEMBER_QUOTA, MemberLevel } from '../types';
 
// 检查使用次数限制
export async function usageLimitMiddleware(ctx: Context, next: Next): Promise<void> {
  const userId = ctx.state.user?.userId;
 
  // 测试模式:无需登录即可使用
  if (!userId) {
    ctx.state.userQuota = { dailyLimit: -1, wordLimit: -1 };
    await next();
    return;
  }
 
  const user = await prisma.user.findUnique({ where: { id: parseInt(userId) } });
  if (!user) {
    throw new ForbiddenError('用户不存在');
  }
 
  const today = new Date().toISOString().slice(0, 10);
  const memberLevel = user.memberLevel;
  const quota = MEMBER_QUOTA[memberLevel as MemberLevel];
 
  // 重置每日使用次数
  if (user.lastUsageDate !== today) {
    await prisma.user.update({
      where: { id: parseInt(userId) },
      data: {
        dailyUsage: 0,
        lastUsageDate: today,
      },
    });
    user.dailyUsage = 0;
    user.lastUsageDate = today;
  }
 
  // 检查次数限制 (-1 表示无限制)
  if (quota.dailyLimit !== -1 && user.dailyUsage >= quota.dailyLimit) {
    throw new QuotaExceededError(`今日使用次数已达上限(${quota.dailyLimit}次),请升级会员`);
  }
 
  // 将用户信息和配额存入 state
  ctx.state.userQuota = quota;
  ctx.state.userInfo = user;
 
  await next();
}
 
// 检查字数限制
export function checkWordLimit(wordCount: number): (ctx: Context, next: Next) => Promise<void> {
  return async (ctx: Context, next: Next) => {
    const quota = ctx.state.userQuota;
    if (!quota) {
      throw new ForbiddenError('请先检查使用限制');
    }
 
    // -1 表示无限制
    if (quota.wordLimit !== -1 && wordCount > quota.wordLimit) {
      throw new QuotaExceededError(`文本字数超出限制(${quota.wordLimit}字),请升级会员或缩短文本`);
    }
 
    await next();
  };
}