From 4451fc59828d88b752633b2af29ddf50deb1d21b Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Mon, 26 Dec 2022 12:34:23 -0800 Subject: [PATCH] Clean up password forms. --- components/forms/PasswordEditForm.js | 68 -------------- components/forms/PasswordResetForm.js | 52 ----------- components/forms/ProfilePasswordForm.js | 69 -------------- components/forms/UserPasswordForm.js | 93 +++++++++++-------- .../{ProfileDetails.js => ProfileSettings.js} | 10 +- .../pages/{UserDetails.js => UserSettings.js} | 2 +- .../{ProfileSettings.js => ProfileDetails.js} | 2 +- pages/api/users/[id]/index.ts | 3 +- pages/profile/index.js | 4 +- pages/users/[...id].js | 4 +- 10 files changed, 69 insertions(+), 238 deletions(-) delete mode 100644 components/forms/PasswordEditForm.js delete mode 100644 components/forms/PasswordResetForm.js delete mode 100644 components/forms/ProfilePasswordForm.js rename components/pages/{ProfileDetails.js => ProfileSettings.js} (71%) rename components/pages/{UserDetails.js => UserSettings.js} (98%) rename components/settings/{ProfileSettings.js => ProfileDetails.js} (96%) diff --git a/components/forms/PasswordEditForm.js b/components/forms/PasswordEditForm.js deleted file mode 100644 index f4480393..00000000 --- a/components/forms/PasswordEditForm.js +++ /dev/null @@ -1,68 +0,0 @@ -import { useRef } from 'react'; -import { Form, FormInput, FormButtons, PasswordField, Button } from 'react-basics'; -import { useApi } from 'next-basics'; -import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; -import styles from './Form.module.css'; - -export default function PasswordEditForm({ onSave, onClose }) { - const { post } = useApi(getAuthToken()); - const { mutate, error, isLoading } = useMutation(data => post('/account/change-password', data)); - const ref = useRef(null); - - const handleSubmit = async data => { - mutate(data, { - onSuccess: async () => { - onSave(); - }, - }); - }; - - const samePassword = value => { - if (value !== ref?.current?.getValues('new_password')) { - return "Passwords don't match"; - } - return true; - }; - - return ( - <> -
- - - - - - - - - - - - - -
- - ); -} diff --git a/components/forms/PasswordResetForm.js b/components/forms/PasswordResetForm.js deleted file mode 100644 index ac5df2f2..00000000 --- a/components/forms/PasswordResetForm.js +++ /dev/null @@ -1,52 +0,0 @@ -import { useRef } from 'react'; -import { Form, FormInput, FormButtons, PasswordField, Button } from 'react-basics'; -import { useApi } from 'next-basics'; -import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; -import styles from './Form.module.css'; - -export default function PasswordResetForm({ token, onSave }) { - const { post } = useApi(getAuthToken()); - const { mutate, error, isLoading } = useMutation(data => - post('/account/reset-password', { ...data, token }), - ); - const ref = useRef(null); - - const handleSubmit = async data => { - mutate(data, { - onSuccess: async () => { - onSave(); - }, - }); - }; - - const samePassword = value => { - if (value !== ref?.current?.getValues('new_password')) { - return "Passwords don't match"; - } - return true; - }; - - return ( - <> -
-

Reset your password

- - - - - - - - - -
- - ); -} diff --git a/components/forms/ProfilePasswordForm.js b/components/forms/ProfilePasswordForm.js deleted file mode 100644 index a713342f..00000000 --- a/components/forms/ProfilePasswordForm.js +++ /dev/null @@ -1,69 +0,0 @@ -import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; -import { useApi } from 'next-basics'; -import { useRef } from 'react'; -import { SubmitButton, Form, FormButtons, FormInput, PasswordField } from 'react-basics'; -import styles from './UserForm.module.css'; -import useUser from 'hooks/useUser'; - -export default function UserPasswordForm({ onSave }) { - const { - user: { id }, - } = useUser(); - const { post } = useApi(getAuthToken()); - const { mutate, error } = useMutation(data => post(`/users/${id}/password`, data)); - const ref = useRef(null); - - const handleSubmit = async data => { - mutate(data, { - onSuccess: async () => { - onSave(); - }, - }); - }; - - const samePassword = value => { - if (value !== ref?.current?.getValues('new_password')) { - return "Passwords don't match"; - } - return true; - }; - - return ( - <> -
- - - - - - - - - - - Save - -
- - ); -} diff --git a/components/forms/UserPasswordForm.js b/components/forms/UserPasswordForm.js index b8fe4d1f..a5543352 100644 --- a/components/forms/UserPasswordForm.js +++ b/components/forms/UserPasswordForm.js @@ -1,25 +1,35 @@ +import { useRef } from 'react'; +import { Form, FormInput, FormButtons, PasswordField, Button } from 'react-basics'; +import { useApi } from 'next-basics'; import { useMutation } from '@tanstack/react-query'; import { getAuthToken } from 'lib/client'; -import { useApi } from 'next-basics'; -import { useRef } from 'react'; -import { SubmitButton, Form, FormButtons, FormInput, PasswordField } from 'react-basics'; import styles from './UserForm.module.css'; +import useUser from 'hooks/useUser'; -export default function UserPasswordForm({ data, onSave }) { - const { id } = data; +export default function UserPasswordForm({ onSave, userId }) { + const { + user: { id }, + } = useUser(); + + const isCurrentUser = !userId || id === userId; + const url = isCurrentUser ? `/users/${id}/password` : `/users/${id}`; const { post } = useApi(getAuthToken()); - const { mutate, error } = useMutation(({ password }) => post(`/users/${id}`, { password })); + const { mutate, error, isLoading } = useMutation(data => post(url, data)); const ref = useRef(null); const handleSubmit = async data => { - mutate( - { password: data.new_password }, - { - onSuccess: async () => { - onSave(); - }, + const payload = isCurrentUser + ? data + : { + password: data.new_password, + }; + + mutate(payload, { + onSuccess: async () => { + onSave(); + ref.current.reset(); }, - ); + }); }; const samePassword = value => { @@ -30,33 +40,42 @@ export default function UserPasswordForm({ data, onSave }) { }; return ( - <> -
+ + {isCurrentUser && ( - - - - - Save - -
- + )} + + + + + + + + + + ); } diff --git a/components/pages/ProfileDetails.js b/components/pages/ProfileSettings.js similarity index 71% rename from components/pages/ProfileDetails.js rename to components/pages/ProfileSettings.js index a9d64718..ab6dbb8a 100644 --- a/components/pages/ProfileDetails.js +++ b/components/pages/ProfileSettings.js @@ -1,11 +1,11 @@ import Page from 'components/layout/Page'; import PageHeader from 'components/layout/PageHeader'; -import ProfileSettings from 'components/settings/ProfileSettings'; +import ProfileDetails from 'components/settings/ProfileDetails'; import { useState } from 'react'; import { Breadcrumbs, Item, Tabs, useToast } from 'react-basics'; -import ProfilePasswordForm from 'components/forms/ProfilePasswordForm'; +import UserPasswordForm from 'components/forms/UserPasswordForm'; -export default function ProfileDetails() { +export default function ProfileSettings() { const [tab, setTab] = useState('general'); const { toast, showToast } = useToast(); @@ -25,8 +25,8 @@ export default function ProfileDetails() { General Password - {tab === 'general' && } - {tab === 'password' && } + {tab === 'general' && } + {tab === 'password' && } ); } diff --git a/components/pages/UserDetails.js b/components/pages/UserSettings.js similarity index 98% rename from components/pages/UserDetails.js rename to components/pages/UserSettings.js index 56c23bfb..1f6dbdc8 100644 --- a/components/pages/UserDetails.js +++ b/components/pages/UserSettings.js @@ -53,7 +53,7 @@ export default function UserDetails({ userId }) { Users - {values?.name} + {values?.username} diff --git a/components/settings/ProfileSettings.js b/components/settings/ProfileDetails.js similarity index 96% rename from components/settings/ProfileSettings.js rename to components/settings/ProfileDetails.js index bddbcd7b..c77b946b 100644 --- a/components/settings/ProfileSettings.js +++ b/components/settings/ProfileDetails.js @@ -7,7 +7,7 @@ import LanguageSetting from './LanguageSetting'; import styles from './ProfileSettings.module.css'; import ThemeSetting from './ThemeSetting'; -export default function ProfileSettings() { +export default function ProfileDetails() { const { user } = useUser(); if (!user) { diff --git a/pages/api/users/[id]/index.ts b/pages/api/users/[id]/index.ts index d7a238c7..d31039f1 100644 --- a/pages/api/users/[id]/index.ts +++ b/pages/api/users/[id]/index.ts @@ -46,7 +46,8 @@ export default async ( const data: any = {}; - if (password) { + // Only admin can change these fields + if (password && isAdmin) { data.password = hashPassword(password); } diff --git a/pages/profile/index.js b/pages/profile/index.js index ab1db48e..46287b0d 100644 --- a/pages/profile/index.js +++ b/pages/profile/index.js @@ -1,5 +1,5 @@ import Settings from 'components/pages/Settings'; -import ProfileDetails from 'components/pages/ProfileDetails'; +import ProfileSettings from 'components/pages/ProfileSettings'; import useRequireLogin from 'hooks/useRequireLogin'; import React from 'react'; @@ -12,7 +12,7 @@ export default function TeamsPage() { return ( - + ); } diff --git a/pages/users/[...id].js b/pages/users/[...id].js index a020fa72..a8023b06 100644 --- a/pages/users/[...id].js +++ b/pages/users/[...id].js @@ -1,5 +1,5 @@ import Settings from 'components/pages/Settings'; -import UserDetails from 'components/pages/UserDetails'; +import UserSettings from 'components/pages/UserSettings'; import useRequireLogin from 'hooks/useRequireLogin'; import { useRouter } from 'next/router'; import React from 'react'; @@ -15,7 +15,7 @@ export default function TeamDetailPage() { return ( - + ); }