mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-10-01 23:56:39 +08:00
update login
This commit is contained in:
parent
714ad21b74
commit
ef5638e427
@ -1,6 +1,5 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import prisma from "@/lib/prisma";
|
import prisma from "@/lib/prisma";
|
||||||
import { insertUser } from "@/lib/auth";
|
|
||||||
import { getTokenLength } from "@/lib/utils";
|
import { getTokenLength } from "@/lib/utils";
|
||||||
|
|
||||||
async function handle(
|
async function handle(
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
input {
|
|
||||||
text-align: left !important
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.ant-input {
|
|
||||||
text-align: left !important
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import "./users-table.modules.scss";
|
|
||||||
import React, { Dispatch, SetStateAction, useEffect, useState } from "react";
|
import React, { Dispatch, SetStateAction, useEffect, useState } from "react";
|
||||||
import { User } from "@prisma/client";
|
import { User } from "@prisma/client";
|
||||||
import {
|
import {
|
||||||
|
@ -3,17 +3,79 @@
|
|||||||
import { signIn } from "next-auth/react";
|
import { signIn } from "next-auth/react";
|
||||||
import React, { useState, useEffect, useRef, use } from "react";
|
import React, { useState, useEffect, useRef, use } from "react";
|
||||||
import { isName } from "@/lib/auth_list";
|
import { isName } from "@/lib/auth_list";
|
||||||
|
import { Form, Input, InputRef } from "antd";
|
||||||
|
import { UserOutlined, MailOutlined } from "@ant-design/icons";
|
||||||
|
import type { FormProps } from "antd";
|
||||||
|
import { SignInOptions } from "next-auth/react";
|
||||||
|
|
||||||
export default function UserLoginButton() {
|
export default function UserLoginButton() {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [loginForm] = Form.useForm();
|
||||||
const nameInput = useRef<HTMLInputElement>(null);
|
const nameInput = useRef<InputRef>(null);
|
||||||
const passwordInput = useRef<HTMLInputElement>(null);
|
const passwordInput = useRef<InputRef>(null);
|
||||||
const emailInput = useRef<HTMLInputElement>(null);
|
const emailInput = useRef<HTMLInputElement>(null);
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
|
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
|
type FieldType = {
|
||||||
|
username?: string;
|
||||||
|
password?: string;
|
||||||
|
email?: string;
|
||||||
|
};
|
||||||
|
const onFinish: FormProps<FieldType>["onFinish"] = (values) => {
|
||||||
|
setLoading(true);
|
||||||
|
let signInOptions: SignInOptions = {
|
||||||
|
redirect: false,
|
||||||
|
};
|
||||||
|
let loginProvider = "";
|
||||||
|
|
||||||
|
if (values.email) {
|
||||||
|
loginProvider = "email";
|
||||||
|
signInOptions = { ...signInOptions, email: values.email };
|
||||||
|
} else {
|
||||||
|
loginProvider = "credentials";
|
||||||
|
signInOptions = {
|
||||||
|
...signInOptions,
|
||||||
|
username: values.username,
|
||||||
|
password: values.password ?? "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
signIn(loginProvider, signInOptions).then((result) => {
|
||||||
|
setLoading(false);
|
||||||
|
if (!result?.error) {
|
||||||
|
window.location.href =
|
||||||
|
result?.url && result.url.includes("verify") ? result.url : "/";
|
||||||
|
} else {
|
||||||
|
const errorParts = result.error.split(",");
|
||||||
|
if (errorParts.length > 1) {
|
||||||
|
loginForm.setFields([
|
||||||
|
{
|
||||||
|
name: errorParts[0],
|
||||||
|
errors: [errorParts[1]],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
loginForm.setFields([
|
||||||
|
{
|
||||||
|
name: "password",
|
||||||
|
errors: [result.error],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log("response,", result);
|
||||||
|
});
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
console.log("Success:", values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFinishFailed: FormProps<FieldType>["onFinishFailed"] = (
|
||||||
|
errorInfo,
|
||||||
|
) => {
|
||||||
|
console.log("Failed:", errorInfo);
|
||||||
|
};
|
||||||
|
|
||||||
const handleNameComposition = (
|
const handleNameComposition = (
|
||||||
e: React.CompositionEvent<HTMLInputElement>,
|
e: React.CompositionEvent<HTMLInputElement>,
|
||||||
@ -68,10 +130,11 @@ export default function UserLoginButton() {
|
|||||||
if (nameInput.current) {
|
if (nameInput.current) {
|
||||||
if (!isName(username)) {
|
if (!isName(username)) {
|
||||||
setError(true);
|
setError(true);
|
||||||
nameInput.current.setCustomValidity("用户名校验失败");
|
// nameInput
|
||||||
|
// nameInput.current.setCustomValidity("用户名校验失败");
|
||||||
} else {
|
} else {
|
||||||
setError(false);
|
setError(false);
|
||||||
nameInput.current.setCustomValidity("");
|
// nameInput.current.setCustomValidity("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log("username:", username);
|
// console.log("username:", username);
|
||||||
@ -79,102 +142,176 @@ export default function UserLoginButton() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/*
|
<div className="mt-6 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
This example requires updating your template:
|
<Form
|
||||||
|
|
||||||
```
|
|
||||||
<html class="h-full bg-white">
|
|
||||||
<body class="h-full">
|
|
||||||
```
|
|
||||||
*/}
|
|
||||||
|
|
||||||
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
|
||||||
<form
|
|
||||||
className="space-y-6"
|
className="space-y-6"
|
||||||
action="#"
|
// action="#"
|
||||||
method="POST"
|
// method="POST"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
onSubmit={onSubmitHandler}
|
onFinish={onFinish}
|
||||||
|
onFinishFailed={onFinishFailed}
|
||||||
|
size="large"
|
||||||
|
form={loginForm}
|
||||||
|
id="login-form"
|
||||||
|
// onSubmit={onSubmitHandler}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div className="mt-2">
|
<Form.Item
|
||||||
<input
|
name="username"
|
||||||
id="username"
|
rules={[
|
||||||
name="username"
|
{
|
||||||
type="username"
|
validator: async (_, value) => {
|
||||||
ref={nameInput}
|
if (value && !isName(value)) {
|
||||||
// value={username}
|
return Promise.reject(
|
||||||
onCompositionStart={(e) => e.preventDefault()}
|
new Error("Invalid username format!"),
|
||||||
onCompositionEnd={handleNameComposition}
|
);
|
||||||
onChange={onNameChange}
|
}
|
||||||
// required
|
const email_value = loginForm.getFieldValue("email");
|
||||||
placeholder="输入姓名、拼音或邮箱"
|
if (!value && !email_value) {
|
||||||
className={`${
|
return Promise.reject(
|
||||||
loading
|
new Error("Please input your username!"),
|
||||||
? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
);
|
||||||
: "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
}
|
||||||
} group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
if (value && email_value) {
|
||||||
${
|
return Promise.reject(new Error("Field must be unique!"));
|
||||||
error
|
}
|
||||||
? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
const password_value = loginForm.getFieldValue("password");
|
||||||
: ""
|
if (!value && password_value) {
|
||||||
}
|
return Promise.reject(
|
||||||
`}
|
new Error("Please input your username!"),
|
||||||
/>
|
);
|
||||||
<input
|
}
|
||||||
id="password"
|
},
|
||||||
name="password"
|
},
|
||||||
type="password"
|
]}
|
||||||
ref={passwordInput}
|
>
|
||||||
value={password}
|
<Input
|
||||||
|
// id="basic_username"
|
||||||
|
// name="username"
|
||||||
|
// type="username"
|
||||||
|
// ref={nameInput}
|
||||||
|
// // value={username}
|
||||||
// onCompositionStart={(e) => e.preventDefault()}
|
// onCompositionStart={(e) => e.preventDefault()}
|
||||||
// onCompositionEnd={handleComposition}
|
// onCompositionEnd={handleNameComposition}
|
||||||
onChange={onPasswordChange}
|
// onChange={onNameChange}
|
||||||
// required
|
// required
|
||||||
placeholder="密码验证,测试阶段"
|
autoComplete="off"
|
||||||
className={`${
|
prefix={<UserOutlined style={{ color: "rgba(0,0,0,.25)" }} />}
|
||||||
loading
|
placeholder="输入姓名、拼音或邮箱"
|
||||||
? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
className={
|
||||||
: "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
"text-sm font-medium text-stone-600 dark:text-stone-400"
|
||||||
} group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
}
|
||||||
${
|
// className={`${
|
||||||
error
|
// loading
|
||||||
? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
// ? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
||||||
: ""
|
// : "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
||||||
}
|
// } group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
||||||
`}
|
// ${
|
||||||
|
// error
|
||||||
|
// ? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
||||||
|
// : ""
|
||||||
|
// }
|
||||||
|
// `}
|
||||||
/>
|
/>
|
||||||
<input
|
</Form.Item>
|
||||||
id="email"
|
|
||||||
name="email"
|
<Form.Item<FieldType>
|
||||||
type="email"
|
// label="Password"
|
||||||
ref={emailInput}
|
name="password"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
validator: async (_, value) => {
|
||||||
|
if (value) {
|
||||||
|
if (value.length < 6) {
|
||||||
|
return Promise.reject(
|
||||||
|
new Error("Password must be at least 6 characters!"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input.Password
|
||||||
|
// id="basic_password"
|
||||||
|
// name="password"
|
||||||
|
// type="password"
|
||||||
|
// status={error ? "error" : ""}
|
||||||
|
// ref={passwordInput}
|
||||||
|
// value={password}
|
||||||
|
// // onCompositionStart={(e) => e.preventDefault()}
|
||||||
|
// // onCompositionEnd={handleComposition}
|
||||||
|
// onChange={onPasswordChange}
|
||||||
|
autoComplete="off"
|
||||||
|
// // required
|
||||||
|
placeholder="密码验证,测试阶段"
|
||||||
|
className={
|
||||||
|
"text-sm font-medium text-stone-600 dark:text-stone-400"
|
||||||
|
}
|
||||||
|
// className={`${
|
||||||
|
// loading
|
||||||
|
// ? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
||||||
|
// : "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
||||||
|
// } group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
||||||
|
// ${
|
||||||
|
// error
|
||||||
|
// ? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
||||||
|
// : ""
|
||||||
|
// }
|
||||||
|
// `}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="email"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
type: "email",
|
||||||
|
message: "The input is not valid E-mail!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: async (_, value) => {
|
||||||
|
const username_value = loginForm.getFieldValue("username");
|
||||||
|
if (value && username_value) {
|
||||||
|
return Promise.reject(new Error("Field must be unique!"));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
// id="email"
|
||||||
|
// name="email"
|
||||||
|
// type="email"
|
||||||
|
// ref={emailInput}
|
||||||
// value={username}
|
// value={username}
|
||||||
onCompositionStart={(e) => e.preventDefault()}
|
// onCompositionStart={(e) => e.preventDefault()}
|
||||||
// onCompositionEnd={handleComposition}
|
// onCompositionEnd={handleComposition}
|
||||||
// onChange={onNameChange}
|
// onChange={onNameChange}
|
||||||
// required
|
// required
|
||||||
|
prefix={<MailOutlined style={{ color: "rgba(0,0,0,.25)" }} />}
|
||||||
placeholder="邮箱验证,测试阶段"
|
placeholder="邮箱验证,测试阶段"
|
||||||
className={`${
|
className={
|
||||||
loading
|
"text-sm font-medium text-stone-600 dark:text-stone-400"
|
||||||
? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
}
|
||||||
: "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
// className={`${
|
||||||
} group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
// loading
|
||||||
${
|
// ? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
||||||
error
|
// : "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
||||||
? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
// } group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
||||||
: ""
|
// ${
|
||||||
}
|
// error
|
||||||
`}
|
// ? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
||||||
|
// : ""
|
||||||
|
// }
|
||||||
|
// `}
|
||||||
/>
|
/>
|
||||||
{/*{error && <p className="mt-2 text-pink-600 text-sm">{error}</p>}*/}
|
</Form.Item>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<Form.Item>
|
||||||
<button
|
<button
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
// onClick={(e) => handleSubmit(e)}
|
// onClick={() => loginForm.submit()}
|
||||||
type="submit"
|
type="submit"
|
||||||
className={`${
|
className={`${
|
||||||
loading
|
loading
|
||||||
@ -184,8 +321,8 @@ export default function UserLoginButton() {
|
|||||||
>
|
>
|
||||||
Sign in
|
Sign in
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</Form.Item>
|
||||||
</form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
{/*</div>*/}
|
{/*</div>*/}
|
||||||
</>
|
</>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
border: 0;
|
border: 0;
|
||||||
border-top: 1px solid var(--color-separator);
|
border-top: 1px solid var(--color-separator);
|
||||||
display: block;
|
display: block;
|
||||||
margin: 2rem auto 1rem;
|
margin: 1rem auto 1rem;
|
||||||
overflow: visible
|
overflow: visible
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.signin form input[type],.signin>div input[type] {
|
.signin form input[type],.signin>div input[type] {
|
||||||
margin-bottom: .5rem
|
//margin-bottom: .5rem
|
||||||
}
|
}
|
||||||
|
|
||||||
.signin form button,.signin>div button {
|
.signin form button,.signin>div button {
|
||||||
@ -73,7 +73,7 @@ html {
|
|||||||
.login-form {
|
.login-form {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
width: 350px;
|
width: 350px;
|
||||||
height: 500px;
|
height: 550px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
|
|
||||||
/* 定位到中心 */
|
/* 定位到中心 */
|
||||||
@ -86,4 +86,12 @@ html {
|
|||||||
/* 毛玻璃 */
|
/* 毛玻璃 */
|
||||||
backdrop-filter: blur(10px); /* 应用模糊效果 */
|
backdrop-filter: blur(10px); /* 应用模糊效果 */
|
||||||
background-color: rgba(255, 255, 255, 0.5); /* 半透明的白色背景 */
|
background-color: rgba(255, 255, 255, 0.5); /* 半透明的白色背景 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
text-align: left !important
|
||||||
|
}
|
||||||
|
|
||||||
|
#login-form input:-webkit-autofill {
|
||||||
|
transition: background-color 5000s ease-in-out 0s;
|
||||||
|
}
|
||||||
|
65
lib/auth.ts
65
lib/auth.ts
@ -80,7 +80,7 @@ export const authOptions: NextAuthOptions = {
|
|||||||
const username = cleanUpString(`${credential?.username}`);
|
const username = cleanUpString(`${credential?.username}`);
|
||||||
const password = cleanPassword(`${credential?.password}`);
|
const password = cleanPassword(`${credential?.password}`);
|
||||||
// 验证用户名
|
// 验证用户名
|
||||||
console.log(credential, 'p', password, '==============3')
|
// console.log(credential, 'p', password, '==============3')
|
||||||
// 判断姓名格式是否符合要求,不符合则拒绝
|
// 判断姓名格式是否符合要求,不符合则拒绝
|
||||||
if (username && isName(username)) {
|
if (username && isName(username)) {
|
||||||
// Any object returned will be saved in `user` property of the JWT
|
// Any object returned will be saved in `user` property of the JWT
|
||||||
@ -90,17 +90,21 @@ export const authOptions: NextAuthOptions = {
|
|||||||
} else {
|
} else {
|
||||||
user['name'] = username;
|
user['name'] = username;
|
||||||
}
|
}
|
||||||
if (password) {
|
// 目前用户不存在,则会创建新用户。
|
||||||
user['password'] = password;
|
let existingUser = await existUser(user); // await insertUser(user)
|
||||||
// 如果有密码,则启用密码验证,查询数据库,否则失败
|
if (!existingUser) {
|
||||||
return await validatePassword(user);
|
// 如果不存在,则报错
|
||||||
|
// throw new Error("用户查询失败")
|
||||||
|
// 如果不存在,则创建
|
||||||
|
existingUser = await insertUser(user);
|
||||||
}
|
}
|
||||||
|
// 有密码就校验密码,没有就直接返回用户
|
||||||
return await insertUser(user) ?? user
|
password && validatePassword(password, existingUser.password);
|
||||||
|
return existingUser;
|
||||||
} else {
|
} else {
|
||||||
// If you return null then an error will be displayed advising the user to check their details.
|
// If you return null then an error will be displayed advising the user to check their details.
|
||||||
// return null
|
// return null
|
||||||
throw new Error("用户名校验失败")
|
throw new Error("username,用户名校验失败")
|
||||||
// You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter
|
// You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,21 +194,15 @@ export async function VerifiedAdminUser() {
|
|||||||
return !!(name && ADMIN_LIST.includes(name));
|
return !!(name && ADMIN_LIST.includes(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function validatePassword(user: {[key: string]: string}): Promise<User | void> {
|
export function validatePassword(password: string, hashPassword: string | null | undefined ): boolean | void {
|
||||||
|
if (!hashPassword) {
|
||||||
const existingUser = await existUser(user);
|
throw new Error("password,未设置密码");
|
||||||
console.log('------', 'existUser', existUser)
|
|
||||||
|
|
||||||
if (!existingUser) {
|
|
||||||
throw new Error("用户名或密码不正确");
|
|
||||||
}
|
}
|
||||||
if (existingUser.password == null) {
|
|
||||||
throw new Error("未设置密码");
|
if (!comparePassword(password, hashPassword)) {
|
||||||
}
|
throw new Error("password,用户名或密码不正确")
|
||||||
if (!comparePassword(user.passowrd, existingUser.password)) {
|
|
||||||
throw new Error("用户名或密码不正确")
|
|
||||||
} else {
|
} else {
|
||||||
return existingUser;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,19 +223,20 @@ async function existUser(user: {[key: string]: string} | User ) {
|
|||||||
|
|
||||||
export async function insertUser(user: {[key: string]: string}) {
|
export async function insertUser(user: {[key: string]: string}) {
|
||||||
try {
|
try {
|
||||||
const existingUser = await existUser(user);
|
return await prisma.user.create({
|
||||||
// console.log('[LOG]', existingUser, user, '=======')
|
data: user
|
||||||
if (!existingUser) {
|
})
|
||||||
return await prisma.user.create({
|
// const existingUser = await existUser(user);
|
||||||
data: user
|
// // console.log('[LOG]', existingUser, user, '=======')
|
||||||
})
|
// if (!existingUser) {
|
||||||
} else {
|
//
|
||||||
// console.log('user==========', existingUser)
|
// } else {
|
||||||
return existingUser;
|
// // console.log('user==========', existingUser)
|
||||||
}
|
// return existingUser;
|
||||||
|
// }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('[Prisma Error]', e);
|
throw new Error("username,用户创建失败");
|
||||||
return false;
|
// return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user