From b3295e136d66c41a38e12a4361e23a04b6db45b6 Mon Sep 17 00:00:00 2001 From: Yee Jia Wei Date: Thu, 19 Oct 2023 13:46:40 +0800 Subject: [PATCH 1/3] change login and register to form --- components/AuthSubmitButton.tsx | 35 ++++++++++ pages/login.tsx | 109 +++++++++++++++++--------------- pages/register.tsx | 15 +++-- 3 files changed, 102 insertions(+), 57 deletions(-) create mode 100644 components/AuthSubmitButton.tsx diff --git a/components/AuthSubmitButton.tsx b/components/AuthSubmitButton.tsx new file mode 100644 index 00000000..434d0afe --- /dev/null +++ b/components/AuthSubmitButton.tsx @@ -0,0 +1,35 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { IconProp } from "@fortawesome/fontawesome-svg-core"; + +type Props = { + onClick?: Function; + icon?: IconProp; + label: string; + loading: boolean; + className?: string; +}; + +export default function AuthSubmitButton({ + onClick, + icon, + label, + loading, + className, +}: Props) { + return ( + + ); +} diff --git a/pages/login.tsx b/pages/login.tsx index f6968ccf..3c392845 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -3,8 +3,9 @@ import TextInput from "@/components/TextInput"; import CenteredForm from "@/layouts/CenteredForm"; import { signIn } from "next-auth/react"; import Link from "next/link"; -import { useState } from "react"; +import { useState, FormEvent } from "react"; import { toast } from "react-hot-toast"; +import AuthSubmitButton from "@/components/AuthSubmitButton"; interface FormData { username: string; @@ -21,7 +22,9 @@ export default function Login() { password: "", }); - async function loginUser() { + async function loginUser(event: FormEvent) { + event.preventDefault(); + if (form.username !== "" && form.password !== "") { setSubmitLoader(true); @@ -47,67 +50,69 @@ export default function Login() { return ( -
-

- Enter your credentials -

- -
-

- Username - {emailEnabled ? " or Email" : undefined} +

+
+

+ Enter your credentials

- setForm({ ...form, username: e.target.value })} - /> -
+
+

+ Username + {emailEnabled ? " or Email" : undefined} +

-
-

- Password -

+ setForm({ ...form, username: e.target.value })} + /> +
- setForm({ ...form, password: e.target.value })} +
+

+ Password +

+ + setForm({ ...form, password: e.target.value })} + /> + {emailEnabled && ( +
+ + Forgot Password? + +
+ )} +
+ + - {emailEnabled && ( -
+ {process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === "true" ? undefined : ( +
+

New here?

- Forgot Password? + Sign Up
)}
- - - {process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === "true" ? undefined : ( -
-

New here?

- - Sign Up - -
- )} -
+
); } diff --git a/pages/register.tsx b/pages/register.tsx index 75ba5251..a681c016 100644 --- a/pages/register.tsx +++ b/pages/register.tsx @@ -1,11 +1,12 @@ import Link from "next/link"; -import { useState } from "react"; +import { useState, FormEvent } from "react"; import { toast } from "react-hot-toast"; import SubmitButton from "@/components/SubmitButton"; import { signIn } from "next-auth/react"; import { useRouter } from "next/router"; import CenteredForm from "@/layouts/CenteredForm"; import TextInput from "@/components/TextInput"; +import AuthSubmitButton from "@/components/AuthSubmitButton"; const emailEnabled = process.env.NEXT_PUBLIC_EMAIL_PROVIDER; @@ -29,7 +30,9 @@ export default function Register() { passwordConfirmation: "", }); - async function registerUser() { + async function registerUser(event: FormEvent) { + event.preventDefault(); + const checkFields = () => { if (emailEnabled) { return ( @@ -107,7 +110,8 @@ export default function Register() {

) : ( -
+
+

Enter your details

@@ -117,6 +121,7 @@ export default function Register() {

) : undefined} -
+ )} ); From ec4bfa6ba9d61aaa2f394ed3ff77b25df0a5cd5f Mon Sep 17 00:00:00 2001 From: daniel31x13 Date: Mon, 23 Oct 2023 01:20:08 -0400 Subject: [PATCH 2/3] merged "AuthSubmitButton" with the "SubmitButton" + updated the other pages that needed this change --- components/AuthSubmitButton.tsx | 35 ------ components/SubmitButton.tsx | 15 ++- pages/choose-username.tsx | 87 +++++++------ pages/forgot.tsx | 87 +++++++------ pages/login.tsx | 11 +- pages/register.tsx | 216 ++++++++++++++++---------------- 6 files changed, 217 insertions(+), 234 deletions(-) delete mode 100644 components/AuthSubmitButton.tsx diff --git a/components/AuthSubmitButton.tsx b/components/AuthSubmitButton.tsx deleted file mode 100644 index 434d0afe..00000000 --- a/components/AuthSubmitButton.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { IconProp } from "@fortawesome/fontawesome-svg-core"; - -type Props = { - onClick?: Function; - icon?: IconProp; - label: string; - loading: boolean; - className?: string; -}; - -export default function AuthSubmitButton({ - onClick, - icon, - label, - loading, - className, -}: Props) { - return ( - - ); -} diff --git a/components/SubmitButton.tsx b/components/SubmitButton.tsx index 8a06eac9..6ee0a782 100644 --- a/components/SubmitButton.tsx +++ b/components/SubmitButton.tsx @@ -2,11 +2,12 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { IconProp } from "@fortawesome/fontawesome-svg-core"; type Props = { - onClick: Function; + onClick?: Function; icon?: IconProp; label: string; loading: boolean; className?: string; + type?: "button" | "submit" | "reset" | undefined; }; export default function SubmitButton({ @@ -15,20 +16,22 @@ export default function SubmitButton({ label, loading, className, + type, }: Props) { return ( -
{ - if (!loading) onClick(); + if (!loading && onClick) onClick(); }} > - {icon && } -

{label}

-
+ {icon && } +

{label}

+ ); } diff --git a/pages/choose-username.tsx b/pages/choose-username.tsx index 75d6aa01..1b4d9be8 100644 --- a/pages/choose-username.tsx +++ b/pages/choose-username.tsx @@ -1,6 +1,6 @@ import SubmitButton from "@/components/SubmitButton"; import { signOut } from "next-auth/react"; -import { useState } from "react"; +import { FormEvent, useState } from "react"; import { toast } from "react-hot-toast"; import { useSession } from "next-auth/react"; import useAccountStore from "@/store/account"; @@ -15,7 +15,9 @@ export default function ChooseUsername() { const { updateAccount, account } = useAccountStore(); - async function submitUsername() { + async function submitUsername(event: FormEvent) { + event.preventDefault(); + setSubmitLoader(true); const redirectionToast = toast.loading("Applying..."); @@ -38,50 +40,53 @@ export default function ChooseUsername() { return ( -
-

- Choose a Username (Last step) -

- -
-

- Username +

+
+

+ Choose a Username (Last step)

- setInputedUsername(e.target.value)} +
+

+ Username +

+ + setInputedUsername(e.target.value)} + /> +
+
+

+ Feel free to reach out to us at{" "} + + support@linkwarden.app + {" "} + in case of any issues. +

+
+ + -
-
-

- Feel free to reach out to us at{" "} - - support@linkwarden.app - {" "} - in case of any issues. -

-
- - -
signOut()} - className="w-fit mx-auto cursor-pointer text-gray-500 dark:text-gray-400 font-semibold " - > - Sign Out +
signOut()} + className="w-fit mx-auto cursor-pointer text-gray-500 dark:text-gray-400 font-semibold " + > + Sign Out +
-
+ ); } diff --git a/pages/forgot.tsx b/pages/forgot.tsx index eb60eb7f..d2fc8c72 100644 --- a/pages/forgot.tsx +++ b/pages/forgot.tsx @@ -3,7 +3,7 @@ import TextInput from "@/components/TextInput"; import CenteredForm from "@/layouts/CenteredForm"; import { signIn } from "next-auth/react"; import Link from "next/link"; -import { useState } from "react"; +import { FormEvent, useState } from "react"; import { toast } from "react-hot-toast"; interface FormData { @@ -17,7 +17,9 @@ export default function Forgot() { email: "", }); - async function loginUser() { + async function sendConfirmation(event: FormEvent) { + event.preventDefault(); + if (form.email !== "") { setSubmitLoader(true); @@ -40,49 +42,52 @@ export default function Forgot() { return ( -
-

- Password Recovery -

-
-

- Enter your Email so we can send you a link to recover your account. - Make sure to change your password in the profile settings - afterwards. -

-

- You wont get logged in if you haven't created an account yet. -

-
-
-

- Email +

+
+

+ Password Recovery

+
+

+ Enter your Email so we can send you a link to recover your + account. Make sure to change your password in the profile settings + afterwards. +

+

+ You wont get logged in if you haven't created an account yet. +

+
+
+

+ Email +

- setForm({ ...form, email: e.target.value })} + setForm({ ...form, email: e.target.value })} + /> +
+ + +
+ + Go back + +
- - -
- - Go back - -
-
+ ); } diff --git a/pages/login.tsx b/pages/login.tsx index 3c392845..6c9c4027 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -5,7 +5,6 @@ import { signIn } from "next-auth/react"; import Link from "next/link"; import { useState, FormEvent } from "react"; import { toast } from "react-hot-toast"; -import AuthSubmitButton from "@/components/AuthSubmitButton"; interface FormData { username: string; @@ -95,14 +94,18 @@ export default function Login() { )}
- - {process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === "true" ? undefined : ( + {process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === + "true" ? undefined : (
-

New here?

+

+ New here? +

-

- Enter your details -

-
-

- Display Name +

+ Enter your details

- - setForm({ ...form, name: e.target.value })} - /> -
- - {emailEnabled ? undefined : (

- Username + Display Name

setForm({ ...form, username: e.target.value })} + onChange={(e) => setForm({ ...form, name: e.target.value })} />
- )} - {emailEnabled ? ( -
-

- Email + {emailEnabled ? undefined : ( +

+

+ Username +

+ + + setForm({ ...form, username: e.target.value }) + } + /> +
+ )} + + {emailEnabled ? ( +
+

+ Email +

+ + setForm({ ...form, email: e.target.value })} + /> +
+ ) : undefined} + +
+

+ Password

setForm({ ...form, email: e.target.value })} + onChange={(e) => setForm({ ...form, password: e.target.value })} />
- ) : undefined} -
-

- Password -

- - setForm({ ...form, password: e.target.value })} - /> -
- -
-

- Confirm Password -

- - - setForm({ ...form, passwordConfirmation: e.target.value }) - } - /> -
- - {process.env.NEXT_PUBLIC_STRIPE_IS_ACTIVE ? ( -
-

- By signing up, you agree to our{" "} - - Terms of Service - {" "} - and{" "} - - Privacy Policy - - . -

-

- Need help?{" "} - - Get in touch - - . +

+

+ Confirm Password

+ + + setForm({ ...form, passwordConfirmation: e.target.value }) + } + />
- ) : undefined} - -
-

- Already have an account? -

- - Login - + {process.env.NEXT_PUBLIC_STRIPE_IS_ACTIVE ? ( +
+

+ By signing up, you agree to our{" "} + + Terms of Service + {" "} + and{" "} + + Privacy Policy + + . +

+

+ Need help?{" "} + + Get in touch + + . +

+
+ ) : undefined} + + +
+

+ Already have an account? +

+ + Login + +
-
)} From bcae97a296bf7ecf43fb004db9a32881c658f080 Mon Sep 17 00:00:00 2001 From: daniel31x13 Date: Mon, 23 Oct 2023 01:45:31 -0400 Subject: [PATCH 3/3] bug fixed --- lib/api/controllers/users/postUser.ts | 8 ++--- .../users/userId/updateUserById.ts | 29 +++++++++++++++++-- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/api/controllers/users/postUser.ts b/lib/api/controllers/users/postUser.ts index 5025d4e9..d9f24f94 100644 --- a/lib/api/controllers/users/postUser.ts +++ b/lib/api/controllers/users/postUser.ts @@ -54,10 +54,10 @@ export default async function postUser( const checkIfUserExists = await prisma.user.findFirst({ where: emailEnabled ? { - email: body.email?.toLowerCase(), + email: body.email?.toLowerCase().trim(), } : { - username: (body.username as string).toLowerCase(), + username: (body.username as string).toLowerCase().trim(), }, }); @@ -71,8 +71,8 @@ export default async function postUser( name: body.name, username: emailEnabled ? undefined - : (body.username as string).toLowerCase(), - email: emailEnabled ? body.email?.toLowerCase() : undefined, + : (body.username as string).toLowerCase().trim(), + email: emailEnabled ? body.email?.toLowerCase().trim() : undefined, password: hashedPassword, }, }); diff --git a/lib/api/controllers/users/userId/updateUserById.ts b/lib/api/controllers/users/userId/updateUserById.ts index b2229e36..c7ac3e88 100644 --- a/lib/api/controllers/users/userId/updateUserById.ts +++ b/lib/api/controllers/users/userId/updateUserById.ts @@ -29,6 +29,15 @@ export default async function updateUser( status: 400, }; + // Check email (if enabled) + const checkEmail = + /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + if (emailEnabled && !checkEmail.test(data.email?.toLowerCase() || "")) + return { + response: "Please enter a valid email.", + status: 400, + }; + const checkUsername = RegExp("^[a-z0-9_-]{3,31}$"); if (!checkUsername.test(data.username.toLowerCase())) @@ -58,11 +67,25 @@ export default async function updateUser( }, }); - if (userIsTaken) + if (userIsTaken) { + if (data.email?.toLowerCase().trim() === userIsTaken.email?.trim()) + return { + response: "Email is taken.", + status: 400, + }; + else if ( + data.username?.toLowerCase().trim() === userIsTaken.username?.trim() + ) + return { + response: "Username is taken.", + status: 400, + }; + return { response: "Username/Email is taken.", status: 400, }; + } // Avatar Settings @@ -105,8 +128,8 @@ export default async function updateUser( }, data: { name: data.name, - username: data.username.toLowerCase(), - email: data.email?.toLowerCase(), + username: data.username.toLowerCase().trim(), + email: data.email?.toLowerCase().trim(), isPrivate: data.isPrivate, archiveAsScreenshot: data.archiveAsScreenshot, archiveAsPDF: data.archiveAsPDF,