From 7a56680935d04f83e7cee5553a7105efa4a659df Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Fri, 28 Jul 2023 10:33:45 +0800 Subject: [PATCH] update password --- client/public/locales/en/common.json | 6 +- client/public/locales/zh/common.json | 6 +- client/src/api/user.ts | 18 ++- .../icons/outlink/iframe.svg:Zone.Identifier | 0 client/src/hooks/useRequest.tsx | 8 +- client/src/pages/account/components/Info.tsx | 110 ++++++++++++------ .../account/components/UpdatePswModal.tsx | 58 +++++++++ .../api/user/{ => account}/loginByPassword.ts | 0 .../pages/api/user/{ => account}/loginout.ts | 0 .../pages/api/user/{ => account}/register.ts | 0 .../api/user/{ => account}/tokenLogin.ts | 0 .../pages/api/user/{ => account}/update.ts | 0 .../{ => account}/updatePasswordByCode.ts | 0 .../api/user/account/updatePasswordByOld.ts | 49 ++++++++ .../pages/app/detail/components/OutLink.tsx | 16 +-- 15 files changed, 217 insertions(+), 54 deletions(-) delete mode 100644 client/src/components/Icon/icons/outlink/iframe.svg:Zone.Identifier create mode 100644 client/src/pages/account/components/UpdatePswModal.tsx rename client/src/pages/api/user/{ => account}/loginByPassword.ts (100%) rename client/src/pages/api/user/{ => account}/loginout.ts (100%) rename client/src/pages/api/user/{ => account}/register.ts (100%) rename client/src/pages/api/user/{ => account}/tokenLogin.ts (100%) rename client/src/pages/api/user/{ => account}/update.ts (100%) rename client/src/pages/api/user/{ => account}/updatePasswordByCode.ts (100%) create mode 100644 client/src/pages/api/user/account/updatePasswordByOld.ts diff --git a/client/public/locales/en/common.json b/client/public/locales/en/common.json index 485124f8e..2aa1112cb 100644 --- a/client/public/locales/en/common.json +++ b/client/public/locales/en/common.json @@ -33,6 +33,10 @@ }, "user": { "Bill Detail": "Bill Detail", - "Pay": "Pay" + "Pay": "Pay", + "Update Password": "Update Password", + "Update password failed": "Update password failed", + "Update password succseful": "Update password succseful", + "Old password is error": "Old password is error" } } diff --git a/client/public/locales/zh/common.json b/client/public/locales/zh/common.json index c70c2d81e..14b4636c9 100644 --- a/client/public/locales/zh/common.json +++ b/client/public/locales/zh/common.json @@ -33,6 +33,10 @@ }, "user": { "Bill Detail": "账单详情", - "Pay": "充值" + "Pay": "充值", + "Update Password": "修改密码", + "Update password failed": "修改密码异常", + "Update password succseful": "修改密码成功", + "Old password is error": "旧密码错误" } } diff --git a/client/src/api/user.ts b/client/src/api/user.ts index 55feedebe..79acbe5ef 100644 --- a/client/src/api/user.ts +++ b/client/src/api/user.ts @@ -12,7 +12,7 @@ export const sendAuthCode = (data: { googleToken: string; }) => POST('/user/sendAuthCode', data); -export const getTokenLogin = () => GET('/user/tokenLogin'); +export const getTokenLogin = () => GET('/user/account/tokenLogin'); export const postRegister = ({ username, @@ -25,7 +25,7 @@ export const postRegister = ({ password: string; inviterId: string; }) => - POST('/user/register', { + POST('/user/account/register', { username, code, inviterId, @@ -41,21 +41,27 @@ export const postFindPassword = ({ code: string; password: string; }) => - POST('/user/updatePasswordByCode', { + POST('/user/account/updatePasswordByCode', { username, code, password: createHashPassword(password) }); +export const updatePasswordByOld = ({ oldPsw, newPsw }: { oldPsw: string; newPsw: string }) => + POST('/user/account/updatePasswordByOld', { + oldPsw: createHashPassword(oldPsw), + newPsw: createHashPassword(newPsw) + }); + export const postLogin = ({ username, password }: { username: string; password: string }) => - POST('/user/loginByPassword', { + POST('/user/account/loginByPassword', { username, password: createHashPassword(password) }); -export const loginOut = () => GET('/user/loginout'); +export const loginOut = () => GET('/user/account/loginout'); -export const putUserInfo = (data: UserUpdateParams) => PUT('/user/update', data); +export const putUserInfo = (data: UserUpdateParams) => PUT('/user/account/update', data); export const getUserBills = (data: RequestPaging) => POST>(`/user/getBill`, data); diff --git a/client/src/components/Icon/icons/outlink/iframe.svg:Zone.Identifier b/client/src/components/Icon/icons/outlink/iframe.svg:Zone.Identifier deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/src/hooks/useRequest.tsx b/client/src/hooks/useRequest.tsx index 29775a1ed..b491a1abf 100644 --- a/client/src/hooks/useRequest.tsx +++ b/client/src/hooks/useRequest.tsx @@ -2,14 +2,16 @@ import { useToast } from '@/hooks/useToast'; import { useMutation } from '@tanstack/react-query'; import type { UseMutationOptions } from '@tanstack/react-query'; import { getErrText } from '@/utils/tools'; +import { useTranslation } from 'react-i18next'; interface Props extends UseMutationOptions { - successToast?: string; - errorToast?: string; + successToast?: string | null; + errorToast?: string | null; } export const useRequest = ({ successToast, errorToast, onSuccess, onError, ...props }: Props) => { const { toast } = useToast(); + const { t } = useTranslation(); const mutation = useMutation({ ...props, onSuccess(res, variables: void, context: unknown) { @@ -24,7 +26,7 @@ export const useRequest = ({ successToast, errorToast, onSuccess, onError, ...pr onError?.(err, variables, context); errorToast && toast({ - title: getErrText(err, errorToast), + title: t(getErrText(err, errorToast)), status: 'error' }); } diff --git a/client/src/pages/account/components/Info.tsx b/client/src/pages/account/components/Info.tsx index ae1dcc3de..bb45dcea7 100644 --- a/client/src/pages/account/components/Info.tsx +++ b/client/src/pages/account/components/Info.tsx @@ -1,5 +1,5 @@ import React, { useCallback } from 'react'; -import { Box, Flex, Button, useDisclosure } from '@chakra-ui/react'; +import { Box, Flex, Button, useDisclosure, useTheme, ModalBody } from '@chakra-ui/react'; import { useForm } from 'react-hook-form'; import { UserUpdateParams } from '@/types/user'; import { putUserInfo } from '@/api/user'; @@ -7,35 +7,48 @@ import { useToast } from '@/hooks/useToast'; import { useGlobalStore } from '@/store/global'; import { useUserStore } from '@/store/user'; import { UserType } from '@/types/user'; -import { useRouter } from 'next/router'; import { useQuery } from '@tanstack/react-query'; import dynamic from 'next/dynamic'; import { useSelectFile } from '@/hooks/useSelectFile'; import { compressImg } from '@/utils/file'; import { getErrText } from '@/utils/tools'; import { feConfigs } from '@/store/static'; +import { useTranslation } from 'react-i18next'; import Loading from '@/components/Loading'; import Avatar from '@/components/Avatar'; +import MyIcon from '@/components/Icon'; +import MyTooltip from '@/components/MyTooltip'; const PayModal = dynamic(() => import('./PayModal'), { loading: () => , ssr: false }); +const UpdatePswModal = dynamic(() => import('./UpdatePswModal'), { + loading: () => , + ssr: false +}); const UserInfo = () => { - const router = useRouter(); + const theme = useTheme(); + const { t } = useTranslation(); const { userInfo, updateUserInfo, initUserInfo } = useUserStore(); const { setLoading } = useGlobalStore(); - const { reset } = useForm({ + const { reset, register } = useForm({ defaultValues: userInfo as UserType }); + const { toast } = useToast(); const { isOpen: isOpenPayModal, onClose: onClosePayModal, onOpen: onOpenPayModal } = useDisclosure(); + const { + isOpen: isOpenUpdatePsw, + onClose: onCloseUpdatePsw, + onOpen: onOpenUpdatePsw + } = useDisclosure(); const { File, onOpen: onOpenSelectFile } = useSelectFile({ fileType: '.jpg,.png', multiple: false @@ -98,41 +111,68 @@ const UserInfo = () => { } }); return ( - - - 头像: - - - + + + + + + + + + + + 更换 + - - 账号: - {userInfo?.username} - - {feConfigs?.show_userDetail && ( - - - 余额: - - {userInfo?.balance.toFixed(3)} 元 - - - - - )} + + + 账号: + {userInfo?.username} + + + 密码: + ***** + + + {feConfigs?.show_userDetail && ( + + + 余额: + + {userInfo?.balance.toFixed(3)} 元 + + + + + )} + {isOpenPayModal && } + {isOpenUpdatePsw && } - + ); }; diff --git a/client/src/pages/account/components/UpdatePswModal.tsx b/client/src/pages/account/components/UpdatePswModal.tsx new file mode 100644 index 000000000..c66a5c7b2 --- /dev/null +++ b/client/src/pages/account/components/UpdatePswModal.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { ModalBody, Box, Flex, Input, ModalFooter, Button } from '@chakra-ui/react'; +import MyModal from '@/components/MyModal'; +import { useTranslation } from 'react-i18next'; +import { useForm } from 'react-hook-form'; +import { useRequest } from '@/hooks/useRequest'; +import { updatePasswordByOld } from '@/api/user'; + +const UpdatePswModal = ({ onClose }: { onClose: () => void }) => { + const { t } = useTranslation(); + const { register, handleSubmit } = useForm({ + defaultValues: { + oldPsw: '', + newPsw: '', + confirmPsw: '' + } + }); + + const { mutate: onSubmit, isLoading } = useRequest({ + mutationFn: (data) => { + return updatePasswordByOld(data); + }, + onSuccess() { + onClose(); + }, + successToast: t('user.Update password succseful'), + errorToast: t('user.Update password failed') + }); + + return ( + + + + 旧密码: + + + + 新密码: + + + + 确认密码: + + + + + + + + + ); +}; + +export default UpdatePswModal; diff --git a/client/src/pages/api/user/loginByPassword.ts b/client/src/pages/api/user/account/loginByPassword.ts similarity index 100% rename from client/src/pages/api/user/loginByPassword.ts rename to client/src/pages/api/user/account/loginByPassword.ts diff --git a/client/src/pages/api/user/loginout.ts b/client/src/pages/api/user/account/loginout.ts similarity index 100% rename from client/src/pages/api/user/loginout.ts rename to client/src/pages/api/user/account/loginout.ts diff --git a/client/src/pages/api/user/register.ts b/client/src/pages/api/user/account/register.ts similarity index 100% rename from client/src/pages/api/user/register.ts rename to client/src/pages/api/user/account/register.ts diff --git a/client/src/pages/api/user/tokenLogin.ts b/client/src/pages/api/user/account/tokenLogin.ts similarity index 100% rename from client/src/pages/api/user/tokenLogin.ts rename to client/src/pages/api/user/account/tokenLogin.ts diff --git a/client/src/pages/api/user/update.ts b/client/src/pages/api/user/account/update.ts similarity index 100% rename from client/src/pages/api/user/update.ts rename to client/src/pages/api/user/account/update.ts diff --git a/client/src/pages/api/user/updatePasswordByCode.ts b/client/src/pages/api/user/account/updatePasswordByCode.ts similarity index 100% rename from client/src/pages/api/user/updatePasswordByCode.ts rename to client/src/pages/api/user/account/updatePasswordByCode.ts diff --git a/client/src/pages/api/user/account/updatePasswordByOld.ts b/client/src/pages/api/user/account/updatePasswordByOld.ts new file mode 100644 index 000000000..cec9cfeb0 --- /dev/null +++ b/client/src/pages/api/user/account/updatePasswordByOld.ts @@ -0,0 +1,49 @@ +// Next.js API route support: https://nextjs.org/docs/api-routes/introduction +import type { NextApiRequest, NextApiResponse } from 'next'; +import { jsonRes } from '@/service/response'; +import { User } from '@/service/models/user'; +import { AuthCode } from '@/service/models/authCode'; +import { connectToDatabase } from '@/service/mongo'; +import { UserAuthTypeEnum } from '@/constants/common'; +import { setCookie } from '@/service/utils/tools'; +import { authUser } from '@/service/utils/auth'; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + try { + const { oldPsw, newPsw } = req.body as { oldPsw: string; newPsw: string }; + + if (!oldPsw || !newPsw) { + throw new Error('Params is missing'); + } + + await connectToDatabase(); + + const { userId } = await authUser({ req, authToken: true }); + + // auth old password + const user = await User.findOne({ + _id: userId, + password: oldPsw + }); + + if (!user) { + throw new Error('user.Old password is error'); + } + + // 更新对应的记录 + await User.findByIdAndUpdate(userId, { + password: newPsw + }); + + jsonRes(res, { + data: { + user + } + }); + } catch (err) { + jsonRes(res, { + code: 500, + error: err + }); + } +} diff --git a/client/src/pages/app/detail/components/OutLink.tsx b/client/src/pages/app/detail/components/OutLink.tsx index fe774d4d7..26b3393ee 100644 --- a/client/src/pages/app/detail/components/OutLink.tsx +++ b/client/src/pages/app/detail/components/OutLink.tsx @@ -74,7 +74,7 @@ const Share = ({ appId }: { appId: string }) => { }); return ( - + 免登录窗口 @@ -222,7 +222,7 @@ const OutLink = ({ appId }: { appId: string }) => { { title: '免登录窗口', desc: '分享链接给其他用户,无需登录即可直接进行使用', value: LinkTypeEnum.share + }, + { + icon: 'outlink_iframe', + title: '网页嵌入', + desc: '嵌入到已有网页中,右下角会生成对话按键', + value: LinkTypeEnum.iframe } - // { - // icon: 'outlink_iframe', - // title: '网页嵌入', - // desc: '嵌入到已有网页中,右下角会生成对话按键', - // value: LinkTypeEnum.iframe - // } ]} value={linkType} onChange={(e) => setLinkType(e as `${LinkTypeEnum}`)}