diff --git a/backend/services/user-service/user-service.ts b/backend/services/user-service/user-service.ts index 3c00f3f..be6560a 100644 --- a/backend/services/user-service/user-service.ts +++ b/backend/services/user-service/user-service.ts @@ -203,6 +203,10 @@ class UserService { }; sendPasswordReset = async (email: string) => { + if (env.emailVerification !== "true") { + throw new ForbiddenError("Email Verification Not Enabled"); + } + const user = await User.findOne({ email }); if (!user) throw new NotFoundError("User Not Found Password Reset Email"); diff --git a/src/components/DownloadPage/DownloadPage.tsx b/src/components/DownloadPage/DownloadPage.tsx index d8fda5e..9c17657 100644 --- a/src/components/DownloadPage/DownloadPage.tsx +++ b/src/components/DownloadPage/DownloadPage.tsx @@ -10,6 +10,12 @@ import dayjs from "dayjs"; import { getFileColor, getFileExtension } from "../../utils/files"; import { FileInterface } from "../../types/file"; import bytes from "bytes"; +import LockIcon from "../../icons/LockIcon"; +import OneIcon from "../../icons/OneIcon"; +import StorageIcon from "../../icons/StorageIcon"; +import CalendarIcon from "../../icons/CalendarIcon"; +import DownloadIcon from "../../icons/DownloadIcon"; +import PublicIcon from "../../icons/PublicIcon"; const PublicDownloadPage = () => { const [file, setFile] = useState(null); @@ -33,6 +39,22 @@ const PublicDownloadPage = () => { downloadPublicFileAPI(id, tempToken); }; + const permissionText = (() => { + if (!file) return ""; + if (file.metadata.linkType === "one") { + return `Temporary`; + } else if (file.metadata.linkType === "public") { + return "Public"; + } else { + return "Private"; + } + })(); + + const copyName = () => { + navigator.clipboard.writeText(file!.filename); + toast.success("Filename Copied"); + }; + useEffect(() => { getFile(); }, [getFile]); @@ -77,32 +99,48 @@ const PublicDownloadPage = () => {

-
-
- Type - {fileExtension} -
-
- Size - {fileSize} -
-
- Created - {formattedDate} -
-
- Access - - {file.metadata.link ? "Public" : "Private"} - -
-
- +
+ + +
+

File details

+
+
+ {!file.metadata.linkType && } + {file.metadata.linkType === "one" && ( + + )} + {file.metadata.linkType === "public" && ( + + )} +

{permissionText}

+
+
+ +

{fileSize}

+
+
+ +

{formattedDate}

+
+
+ +
diff --git a/src/components/LoginPage/LoginPage.tsx b/src/components/LoginPage/LoginPage.tsx index 9fc0e98..28cf20b 100755 --- a/src/components/LoginPage/LoginPage.tsx +++ b/src/components/LoginPage/LoginPage.tsx @@ -123,7 +123,13 @@ const LoginPage = () => { } catch (e) { console.log("Create Account Error", e); setLoadingLogin(false); - setError("Create Account Failed"); + if (e instanceof AxiosError && e.response?.status === 404) { + setError("Email does not exist"); + } else if (e instanceof AxiosError && e.response?.status === 403) { + setError("Email Verification Not Enabled"); + } else { + setError("Create Account Failed"); + } } }; diff --git a/src/components/ResetPasswordPage/ResetPasswordPage.tsx b/src/components/ResetPasswordPage/ResetPasswordPage.tsx index 2769b75..9f16947 100644 --- a/src/components/ResetPasswordPage/ResetPasswordPage.tsx +++ b/src/components/ResetPasswordPage/ResetPasswordPage.tsx @@ -4,6 +4,7 @@ import { ToastContainer, toast } from "react-toastify"; import { useState } from "react"; import { resetPasswordAPI } from "../../api/userAPI"; import AlertIcon from "../../icons/AlertIcon"; +import { AxiosError } from "axios"; const ResetPasswordPage = () => { const token = useParams().token!; @@ -13,7 +14,30 @@ const ResetPasswordPage = () => { const [error, setError] = useState(""); const navigate = useNavigate(); - const isSubmitDisabled = password !== verifyPassword; + const errorMessage = (() => { + if (password.length === 0) { + return ""; + } + + if (password.length < 6) { + return "Password must be at least 6 characters"; + } else if (password.length > 256) { + return "Password must be less than 256 characters"; + } + + if ( + password.length && + verifyPassword.length && + password !== verifyPassword + ) { + return "Passwords do not match"; + } + + return ""; + })(); + + const isSubmitDisabled = + !password.length || password !== verifyPassword || errorMessage; const onSubmit = async (e: any) => { try { @@ -22,15 +46,18 @@ const ResetPasswordPage = () => { await toast.promise(resetPasswordAPI(password, token), { pending: "Resetting password...", success: "Password Reset", - error: "Error Resetting Password", }); setTimeout(() => { navigate("/"); }, 1500); } catch (e) { + if (e instanceof AxiosError && e.response?.status === 401) { + setError("Invalid token error"); + } else { + setError("Reset Password Failed"); + } console.log("Reset Password Error", e); setLoadingLogin(false); - setError("Reset Password Failed"); } }; @@ -70,17 +97,17 @@ const ResetPasswordPage = () => { - {(isSubmitDisabled || error) && ( + {(error || errorMessage) && (

- {isSubmitDisabled ? "Passwords do not match" : error} + {error ? error : errorMessage}

diff --git a/src/components/SettingsPage/SettingsChangePasswordPopup.tsx b/src/components/SettingsPage/SettingsChangePasswordPopup.tsx index cadbcfa..77e4325 100644 --- a/src/components/SettingsPage/SettingsChangePasswordPopup.tsx +++ b/src/components/SettingsPage/SettingsChangePasswordPopup.tsx @@ -3,6 +3,7 @@ import CloseIcon from "../../icons/CloseIcon"; import classNames from "classnames"; import { toast } from "react-toastify"; import { changePasswordAPI } from "../../api/userAPI"; +import { AxiosError } from "axios"; interface SettingsChangePasswordPopupProps { closePopup: () => void; @@ -44,9 +45,15 @@ const SettingsChangePasswordPopup: React.FC< if (newPassword.length < 6) { return "Password must be at least 6 characters"; + } else if (newPassword.length > 256) { + return "Password must be less than 256 characters"; } - if (verifyNewPassword.length !== 0 && newPassword !== verifyNewPassword) { + if ( + newPassword.length && + verifyNewPassword.length && + newPassword !== verifyNewPassword + ) { return "Passwords do not match"; } @@ -60,10 +67,14 @@ const SettingsChangePasswordPopup: React.FC< await toast.promise(changePasswordAPI(currentPassword, newPassword), { pending: "Changing password...", success: "Password Changed", - error: "Error Changing Password", }); closePopup(); } catch (e) { + if (e instanceof AxiosError && e.response?.status === 401) { + toast.error("Incorrect password"); + } else { + toast.error("Error changing password"); + } console.log("Error changing password", e); } finally { setLoadingChangePassword(false);