feat: enhance user form password
This commit is contained in:
@@ -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")}{" "}
|
||||
|
||||
@@ -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", {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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("更新用户时发生未知错误");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user