mirror of
https://github.com/JetSprow/J-Board-Lite.git
synced 2026-05-01 01:14:10 +05:30
merge main into dev
This commit is contained in:
@@ -9,6 +9,7 @@ import { actorFromSession, recordAuditLog } from "@/services/audit";
|
||||
import { getAppConfig } from "@/services/app-config";
|
||||
import { normalizeSiteUrl } from "@/services/site-url";
|
||||
import { encrypt } from "@/lib/crypto";
|
||||
import { getErrorMessage } from "@/lib/errors";
|
||||
import { sendSmtpTestEmail } from "@/services/email";
|
||||
|
||||
const settingsSchema = z.object({
|
||||
@@ -65,15 +66,10 @@ type SmtpTestActionResult =
|
||||
|
||||
function formatActionError(error: unknown, fallback: string) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return error.issues[0]?.message ?? fallback;
|
||||
const details = error.issues.map((issue) => issue.message).filter(Boolean).join(";");
|
||||
return details || getErrorMessage(error, fallback);
|
||||
}
|
||||
if (error instanceof Error && error.message.trim()) {
|
||||
return error.message.trim();
|
||||
}
|
||||
if (typeof error === "string" && error.trim()) {
|
||||
return error.trim();
|
||||
}
|
||||
return fallback;
|
||||
return getErrorMessage(error, fallback);
|
||||
}
|
||||
|
||||
async function assertSmtpTestRateLimit(userId: string) {
|
||||
|
||||
@@ -26,7 +26,7 @@ export async function createUser(formData: FormData) {
|
||||
const data = createUserSchema.parse(Object.fromEntries(formData));
|
||||
const hashed = await bcrypt.hash(data.password, 12);
|
||||
const user = await prisma.user.create({
|
||||
data: { email: data.email, password: hashed, name: data.name || null, role: data.role },
|
||||
data: { email: data.email, emailVerifiedAt: new Date(), password: hashed, name: data.name || null, role: data.role },
|
||||
});
|
||||
await recordAuditLog({
|
||||
actor: actorFromSession(session),
|
||||
|
||||
@@ -58,7 +58,7 @@ async function generateUniqueInviteCode(): Promise<string> {
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("邀请码生成失败,请稍后重试");
|
||||
throw new Error("邀请码生成失败:连续 10 次生成的随机码都已存在,请稍后重试");
|
||||
}
|
||||
|
||||
export async function updateAccountProfile(formData: FormData) {
|
||||
|
||||
@@ -33,8 +33,8 @@ async function getProxyPlanForCart(planId: string) {
|
||||
},
|
||||
});
|
||||
|
||||
if (plan.type !== "PROXY") throw new Error("套餐类型错误");
|
||||
if (!plan.isActive) throw new Error("套餐已下架");
|
||||
if (plan.type !== "PROXY") throw new Error(`套餐类型不匹配:${plan.name} 是 ${plan.type},不能作为代理套餐加入购物车`);
|
||||
if (!plan.isActive) throw new Error(`套餐已下架:${plan.name} 当前不可购买`);
|
||||
return plan;
|
||||
}
|
||||
|
||||
@@ -115,8 +115,8 @@ export async function addProxyPlanToCart(
|
||||
export async function addStreamingPlanToCart(planId: string) {
|
||||
const session = await requireAuth();
|
||||
const plan = await prisma.subscriptionPlan.findUniqueOrThrow({ where: { id: planId } });
|
||||
if (plan.type !== "STREAMING") throw new Error("套餐类型错误");
|
||||
if (!plan.isActive) throw new Error("套餐已下架");
|
||||
if (plan.type !== "STREAMING") throw new Error(`套餐类型不匹配:${plan.name} 是 ${plan.type},不能作为流媒体套餐加入购物车`);
|
||||
if (!plan.isActive) throw new Error(`套餐已下架:${plan.name} 当前不可购买`);
|
||||
|
||||
const availability = await getPlanAvailability(plan, { userId: session.user.id });
|
||||
if (!availability.available) {
|
||||
|
||||
@@ -135,8 +135,8 @@ export async function purchaseProxy(
|
||||
},
|
||||
});
|
||||
|
||||
if (plan.type !== "PROXY") throw new Error("套餐类型错误");
|
||||
if (!plan.isActive) throw new Error("套餐已下架");
|
||||
if (plan.type !== "PROXY") throw new Error(`套餐类型不匹配:${plan.name} 是 ${plan.type},不能作为代理套餐购买`);
|
||||
if (!plan.isActive) throw new Error(`套餐已下架:${plan.name} 当前不可购买`);
|
||||
|
||||
const price = getPlanPurchasePrice(plan, trafficGb);
|
||||
|
||||
@@ -216,8 +216,8 @@ export async function purchaseStreaming(planId: string): Promise<string> {
|
||||
where: { id: planId },
|
||||
});
|
||||
|
||||
if (plan.type !== "STREAMING") throw new Error("套餐类型错误");
|
||||
if (!plan.isActive) throw new Error("套餐已下架");
|
||||
if (plan.type !== "STREAMING") throw new Error(`套餐类型不匹配:${plan.name} 是 ${plan.type},不能作为流媒体套餐购买`);
|
||||
if (!plan.isActive) throw new Error(`套餐已下架:${plan.name} 当前不可购买`);
|
||||
|
||||
const availability = await getPlanAvailability(plan, { userId: session.user.id });
|
||||
if (!availability.available) {
|
||||
|
||||
Reference in New Issue
Block a user