feat: add local auth billing and usage management
This commit is contained in:
1 parent
f642b5e71f
commit
196fdde83f
119 files changed
+15695
-2650
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import { jsonError, jsonOk, readJsonBody } from "@/lib/server/api";
|
||||
import { requireAdminSession } from "@/lib/server/auth/current-user";
|
||||
import { getOrganizationApiConfig, resetPlatformUserPassword } from "@/lib/server/organization-client";
|
||||
import { AccountStoreError, getPlatformUserById, updatePlatformUser } from "@/lib/server/account-store";
|
||||
import { hasSuperAdminAccess } from "@/lib/auth/permissions";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const dynamic = "force-dynamic";
|
||||
@@ -8,53 +9,23 @@ export const dynamic = "force-dynamic";
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const session = await requireAdminSession();
|
||||
const context = { accessToken: session.accessToken };
|
||||
const config = getOrganizationApiConfig(context.accessToken);
|
||||
if (!config.staffConfigured) {
|
||||
throw Object.assign(new Error(`企业端用户接口配置不完整:${config.staffMissing.join(", ")}`), { status: 503 });
|
||||
}
|
||||
const body = await readJsonBody<Record<string, unknown>>(request);
|
||||
await resetPlatformUserPassword({
|
||||
tenantId: tenantIdNumber(config.tenantId),
|
||||
userId: requiredNumber(body.userId, "用户 ID"),
|
||||
newPassword: requiredString(body, "newPassword", "新密码"),
|
||||
mustChangePassword: booleanValue(body.mustChangePassword, true)
|
||||
}, context);
|
||||
return jsonOk({ ok: true });
|
||||
const userId = requiredString(body.userId, "账号 ID");
|
||||
const target = await getPlatformUserById(userId, { includeDisabled: true });
|
||||
if (!target) throw new AccountStoreError("账号不存在。", 404);
|
||||
if (!hasSuperAdminAccess(session.user) && (session.user.role !== "organization_admin" || target.role !== "user" || target.organizationId !== session.user.organizationId)) {
|
||||
throw new AccountStoreError("组织管理员只能重置本组织普通用户密码。", 403);
|
||||
}
|
||||
const newPassword = requiredString(body.newPassword, "新密码");
|
||||
if (newPassword.length < 8) throw new AccountStoreError("新密码至少需要 8 位。", 400);
|
||||
const user = await updatePlatformUser(userId, { password: newPassword, clearLoginLock: true });
|
||||
return jsonOk({ ok: true, userId: user.id });
|
||||
} catch (error) {
|
||||
return jsonError(error, 500, { request, source: "api.admin.accounts.password", logClientErrors: true });
|
||||
}
|
||||
}
|
||||
|
||||
function requiredString(body: Record<string, unknown>, key: string, label: string): string {
|
||||
const value = body[key];
|
||||
function requiredString(value: unknown, label: string): string {
|
||||
if (typeof value === "string" && value.trim()) return value.trim();
|
||||
throw badRequest(`${label}不能为空。`);
|
||||
}
|
||||
|
||||
function requiredNumber(value: unknown, label: string): number {
|
||||
const parsed = typeof value === "number" ? value : Number(value);
|
||||
if (Number.isFinite(parsed)) return parsed;
|
||||
throw badRequest(`${label}必须是数字。`);
|
||||
}
|
||||
|
||||
function tenantIdNumber(value: string): number {
|
||||
const tenantId = Number(value);
|
||||
if (!Number.isFinite(tenantId)) throw badRequest("租户 ID 必须是数字。");
|
||||
return tenantId;
|
||||
}
|
||||
|
||||
function booleanValue(value: unknown, fallback: boolean): boolean {
|
||||
if (typeof value === "boolean") return value;
|
||||
if (typeof value === "string") {
|
||||
if (value === "true") return true;
|
||||
if (value === "false") return false;
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
function badRequest(message: string): Error & { status: number } {
|
||||
const error = new Error(message) as Error & { status: number };
|
||||
error.status = 400;
|
||||
return error;
|
||||
throw new AccountStoreError(`${label}不能为空。`, 400);
|
||||
}
|
||||
Reference in new issue
Block a user