feat: enhance user form password

This commit is contained in:
oiov
2025-06-18 11:08:58 +08:00
parent 858b02fa0c
commit 4573373544
7 changed files with 111 additions and 17 deletions
-4
View File
@@ -46,10 +46,6 @@ export default function LoginPage() {
<Suspense>
<UserAuthForm />
</Suspense>
{/* <p className="mt-4 break-all rounded-md border border-dashed bg-neutral-50 p-2 text-left text-sm text-gray-600 dark:border-neutral-600 dark:bg-neutral-800 dark:text-zinc-400">
📢 To keep our free resources accessible to all, we're allowing only
200 new account sign-ups each day.
</p> */}
<p className="px-2 text-center text-sm text-muted-foreground">
{t("By clicking continue, you agree to our")}{" "}
+1
View File
@@ -22,6 +22,7 @@ export async function POST(req: Request) {
team: data.team,
image: data.image,
apiKey: data.apiKey,
password: data.password,
});
if (!res?.id) {
return Response.json("An error occurred", {
+3 -1
View File
@@ -155,6 +155,7 @@ export function UserAuthForm({ className, type, ...props }: UserAuthFormProps) {
)}
</div>
<Button
className="my-2"
disabled={
!loginMethod.registration ||
isLoading ||
@@ -219,6 +220,7 @@ export function UserAuthForm({ className, type, ...props }: UserAuthFormProps) {
</div>
<Button
className="my-2"
disabled={
!loginMethod.registration ||
isLoading ||
@@ -332,7 +334,7 @@ export function UserAuthForm({ className, type, ...props }: UserAuthFormProps) {
{loginMethod["resend"] && loginMethod["credentials"] ? (
<Tabs defaultValue="resend">
<TabsList className="w-full justify-center">
<TabsList className="mb-2 w-full justify-center">
<TabsTrigger value="resend">{t("Email Code")}</TabsTrigger>
<TabsTrigger value="password">{t("Password")}</TabsTrigger>
</TabsList>
+18 -1
View File
@@ -52,7 +52,6 @@ export function UserForm({
handleSubmit,
register,
formState: { errors },
getValues,
setValue,
} = useForm<FormData>({
resolver: zodResolver(updateUserSchema),
@@ -64,6 +63,7 @@ export function UserForm({
image: initData?.image || "",
role: initData?.role || "USER",
team: initData?.team || "free",
password: "",
},
});
@@ -215,6 +215,23 @@ export function UserForm({
</FormSectionColumns>
</div>
<div className="items-center justify-start gap-4 md:flex">
<FormSectionColumns title="Password">
<Label className="sr-only" htmlFor="password">
Password
</Label>
<Input
id="password"
className="flex-1 shadow-inner"
size={20}
type="password"
{...register("password")}
/>
{errors?.password && (
<p className="p-1 text-[13px] text-red-600">
{errors.password.message}
</p>
)}
</FormSectionColumns>
<FormSectionColumns title="Active">
<div className="flex w-full items-center gap-2">
<Label className="sr-only" htmlFor="active">
+87 -10
View File
@@ -2,11 +2,10 @@ import { User, UserRole } from "@prisma/client";
import { prisma } from "@/lib/db";
import { hashPassword, verifyPassword } from "../utils";
export interface UpdateUserForm
extends Omit<
User,
"id" | "createdAt" | "updatedAt" | "emailVerified" | "password"
> {}
extends Omit<User, "id" | "createdAt" | "updatedAt" | "emailVerified"> {}
export const getUserByEmail = async (email: string) => {
try {
@@ -109,15 +108,93 @@ export async function getAllUsersActiveApiKeyCount() {
export const updateUser = async (userId: string, data: UpdateUserForm) => {
try {
const session = await prisma.user.update({
where: {
id: userId,
// 1. 验证用户是否存在
const existingUser = await prisma.user.findUnique({
where: { id: userId },
select: {
id: true,
password: true,
email: true,
},
data,
});
return session;
if (!existingUser) {
throw new Error("用户不存在");
}
// 2. 准备更新数据
const updateData: Partial<UpdateUserForm> = {};
// 3. 处理基础字段
if (data.name !== undefined) updateData.name = data.name;
if (data.email !== undefined) {
// 检查邮箱是否已被其他用户使用
if (data.email !== existingUser.email) {
const emailExists = await prisma.user.findFirst({
where: {
email: data.email,
id: { not: userId },
},
});
if (emailExists) {
throw new Error("邮箱已被使用");
}
}
updateData.email = data.email;
}
if (data.role !== undefined) updateData.role = data.role;
if (data.active !== undefined) updateData.active = data.active;
if (data.team !== undefined) updateData.team = data.team;
if (data.image !== undefined) updateData.image = data.image;
if (data.apiKey !== undefined) updateData.apiKey = data.apiKey;
// 4. 处理密码更新
if (data.password) {
const trimmedPassword = data.password.trim();
// 检查新密码是否与当前密码相同
const isSamePassword = verifyPassword(
trimmedPassword,
existingUser.password || "",
);
if (!isSamePassword) {
updateData.password = hashPassword(trimmedPassword);
}
}
if (Object.keys(updateData).length === 0) {
return existingUser;
}
const updatedUser = await prisma.user.update({
where: { id: userId },
data: {
...updateData,
updatedAt: new Date(),
},
select: {
id: true,
name: true,
email: true,
role: true,
active: true,
team: true,
image: true,
apiKey: true,
createdAt: true,
updatedAt: true,
},
});
return updatedUser;
} catch (error) {
return null;
console.error("更新用户失败:", error);
if (error instanceof Error) {
throw error;
}
throw new Error("更新用户时发生未知错误");
}
};
+1
View File
@@ -18,4 +18,5 @@ export const updateUserSchema = z.object({
active: z.number().default(1),
team: z.string(),
role: z.nativeEnum(UserRole),
password: z.string().optional(),
});
+1 -1
View File
File diff suppressed because one or more lines are too long