diff --git a/apiserver/plane/authentication/provider/credentials/magic_code.py b/apiserver/plane/authentication/provider/credentials/magic_code.py
index 6686b5634..71451ef0d 100644
--- a/apiserver/plane/authentication/provider/credentials/magic_code.py
+++ b/apiserver/plane/authentication/provider/credentials/magic_code.py
@@ -120,7 +120,7 @@ class MagicCodeProvider(CredentialAdapter):
"INVALID_MAGIC_CODE"
],
error_message="INVALID_MAGIC_CODE",
- payload={"email": str(self.key)},
+ payload={"email": str(email)},
)
else:
raise AuthenticationException(
diff --git a/space/components/accounts/onboarding-form.tsx b/space/components/accounts/onboarding-form.tsx
index d1afe35c1..7a719d938 100644
--- a/space/components/accounts/onboarding-form.tsx
+++ b/space/components/accounts/onboarding-form.tsx
@@ -8,7 +8,7 @@ import { Button, Input, Spinner, TOAST_TYPE, setToast } from "@plane/ui";
// components
import { UserImageUploadModal } from "@/components/accounts";
// hooks
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
// services
import fileService from "@/services/file.service";
diff --git a/space/components/issues/board-views/kanban/block.tsx b/space/components/issues/board-views/kanban/block.tsx
index c5b12a9b6..6c2aa5279 100644
--- a/space/components/issues/board-views/kanban/block.tsx
+++ b/space/components/issues/board-views/kanban/block.tsx
@@ -6,7 +6,7 @@ import { useRouter } from "next/router";
import { IssueBlockDueDate } from "@/components/issues/board-views/block-due-date";
import { IssueBlockPriority } from "@/components/issues/board-views/block-priority";
import { IssueBlockState } from "@/components/issues/board-views/block-state";
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
// components
// interfaces
diff --git a/space/components/issues/board-views/kanban/header.tsx b/space/components/issues/board-views/kanban/header.tsx
index fc0ed274a..c08f89975 100644
--- a/space/components/issues/board-views/kanban/header.tsx
+++ b/space/components/issues/board-views/kanban/header.tsx
@@ -6,7 +6,7 @@ import { StateGroupIcon } from "@plane/ui";
import { issueGroupFilter } from "@/constants/data";
// ui
// mobx hook
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
import { RootStore } from "@/store/root.store";
import { IIssueState } from "types/issue";
diff --git a/space/components/issues/board-views/kanban/index.tsx b/space/components/issues/board-views/kanban/index.tsx
index ccfefd874..d1a9fe709 100644
--- a/space/components/issues/board-views/kanban/index.tsx
+++ b/space/components/issues/board-views/kanban/index.tsx
@@ -9,7 +9,7 @@ import { IssueKanBanHeader } from "@/components/issues/board-views/kanban/header
import { Icon } from "@/components/ui";
// interfaces
// mobx hook
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
import { RootStore } from "@/store/root.store";
import { IIssueState, IIssue } from "types/issue";
diff --git a/space/components/issues/board-views/list/block.tsx b/space/components/issues/board-views/list/block.tsx
index b761f5163..63b589066 100644
--- a/space/components/issues/board-views/list/block.tsx
+++ b/space/components/issues/board-views/list/block.tsx
@@ -7,7 +7,7 @@ import { IssueBlockLabels } from "@/components/issues/board-views/block-labels";
import { IssueBlockPriority } from "@/components/issues/board-views/block-priority";
import { IssueBlockState } from "@/components/issues/board-views/block-state";
// mobx hook
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
// interfaces
import { RootStore } from "@/store/root.store";
import { IIssue } from "types/issue";
diff --git a/space/components/issues/board-views/list/header.tsx b/space/components/issues/board-views/list/header.tsx
index f857158d9..6266c9cef 100644
--- a/space/components/issues/board-views/list/header.tsx
+++ b/space/components/issues/board-views/list/header.tsx
@@ -6,7 +6,7 @@ import { StateGroupIcon } from "@plane/ui";
// constants
import { issueGroupFilter } from "@/constants/data";
// mobx hook
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
import { RootStore } from "@/store/root.store";
import { IIssueState } from "types/issue";
diff --git a/space/components/issues/board-views/list/index.tsx b/space/components/issues/board-views/list/index.tsx
index a0da35522..03ca07998 100644
--- a/space/components/issues/board-views/list/index.tsx
+++ b/space/components/issues/board-views/list/index.tsx
@@ -4,7 +4,7 @@ import { IssueListBlock } from "@/components/issues/board-views/list/block";
import { IssueListHeader } from "@/components/issues/board-views/list/header";
// interfaces
// mobx hook
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
// store
import { RootStore } from "@/store/root.store";
import { IIssueState, IIssue } from "types/issue";
diff --git a/space/components/issues/filters/applied-filters/root.tsx b/space/components/issues/filters/applied-filters/root.tsx
index 432d187cf..7362e8787 100644
--- a/space/components/issues/filters/applied-filters/root.tsx
+++ b/space/components/issues/filters/applied-filters/root.tsx
@@ -3,7 +3,7 @@ import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
// components
// store
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
import { IIssueFilterOptions } from "@/store/issues/types";
import { RootStore } from "@/store/root.store";
import { AppliedFiltersList } from "./filters-list";
diff --git a/space/components/issues/filters/root.tsx b/space/components/issues/filters/root.tsx
index 2e9600774..e14412c32 100644
--- a/space/components/issues/filters/root.tsx
+++ b/space/components/issues/filters/root.tsx
@@ -2,7 +2,7 @@ import { FC, useCallback } from "react";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
// components
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/store/issues/helpers";
import { IIssueFilterOptions } from "@/store/issues/types";
import { RootStore } from "@/store/root.store";
diff --git a/space/components/issues/navbar/index.tsx b/space/components/issues/navbar/index.tsx
index ccd903a80..de8633100 100644
--- a/space/components/issues/navbar/index.tsx
+++ b/space/components/issues/navbar/index.tsx
@@ -8,8 +8,7 @@ import { Avatar, Button } from "@plane/ui";
import { ProjectLogo } from "@/components/common";
import { IssueFiltersDropdown } from "@/components/issues/filters";
// hooks
-import { useUser } from "@/hooks/store";
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore, useUser } from "@/hooks/store";
// store
import { RootStore } from "@/store/root.store";
import { TIssueBoardKeys } from "@/types/issue";
diff --git a/space/components/issues/navbar/issue-board-view.tsx b/space/components/issues/navbar/issue-board-view.tsx
index 3b81aaf68..12574bef8 100644
--- a/space/components/issues/navbar/issue-board-view.tsx
+++ b/space/components/issues/navbar/issue-board-view.tsx
@@ -3,7 +3,7 @@ import { useRouter } from "next/router";
// constants
import { issueViews } from "@/constants/data";
// mobx
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
import { RootStore } from "@/store/root.store";
import { TIssueBoardKeys } from "types/issue";
diff --git a/space/components/issues/peek-overview/comment/add-comment.tsx b/space/components/issues/peek-overview/comment/add-comment.tsx
index 059b224c3..dadcc1747 100644
--- a/space/components/issues/peek-overview/comment/add-comment.tsx
+++ b/space/components/issues/peek-overview/comment/add-comment.tsx
@@ -6,10 +6,8 @@ import { useForm, Controller } from "react-hook-form";
import { EditorRefApi } from "@plane/lite-text-editor";
import { LiteTextEditor } from "@/components/editor/lite-text-editor";
// hooks
-import { useUser } from "@/hooks/store";
+import { useMobxStore, useUser } from "@/hooks/store";
import useToast from "@/hooks/use-toast";
-// lib
-import { useMobxStore } from "@/lib/mobx/store-provider";
// types
import { Comment } from "@/types/issue";
diff --git a/space/components/issues/peek-overview/comment/comment-detail-card.tsx b/space/components/issues/peek-overview/comment/comment-detail-card.tsx
index 11f11849a..e3962c5e4 100644
--- a/space/components/issues/peek-overview/comment/comment-detail-card.tsx
+++ b/space/components/issues/peek-overview/comment/comment-detail-card.tsx
@@ -10,9 +10,7 @@ import { CommentReactions } from "@/components/issues/peek-overview";
// helpers
import { timeAgo } from "@/helpers/date-time.helper";
// hooks
-import { useUser } from "@/hooks/store";
-// mobx store
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore, useUser } from "@/hooks/store";
// store
import { RootStore } from "@/store/root.store";
// types
diff --git a/space/components/issues/peek-overview/comment/comment-reactions.tsx b/space/components/issues/peek-overview/comment/comment-reactions.tsx
index 09e725550..ca451f7b4 100644
--- a/space/components/issues/peek-overview/comment/comment-reactions.tsx
+++ b/space/components/issues/peek-overview/comment/comment-reactions.tsx
@@ -1,16 +1,13 @@
import React from "react";
-
-// mobx
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
-// ui
import { Tooltip } from "@plane/ui";
+// ui
import { ReactionSelector } from "@/components/ui";
// helpers
import { groupReactions, renderEmoji } from "@/helpers/emoji.helper";
// hooks
-import { useUser } from "@/hooks/store";
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore, useUser } from "@/hooks/store";
type Props = {
commentId: string;
diff --git a/space/components/issues/peek-overview/header.tsx b/space/components/issues/peek-overview/header.tsx
index 413b6ac2d..7aba40305 100644
--- a/space/components/issues/peek-overview/header.tsx
+++ b/space/components/issues/peek-overview/header.tsx
@@ -8,7 +8,7 @@ import { Icon } from "@/components/ui";
// helpers
import { copyTextToClipboard } from "@/helpers/string.helper";
// store
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
import { IPeekMode } from "@/store/issue_details";
import { RootStore } from "@/store/root.store";
// lib
diff --git a/space/components/issues/peek-overview/issue-activity.tsx b/space/components/issues/peek-overview/issue-activity.tsx
index 3a5477ac6..aaa7dc688 100644
--- a/space/components/issues/peek-overview/issue-activity.tsx
+++ b/space/components/issues/peek-overview/issue-activity.tsx
@@ -2,13 +2,12 @@ import React from "react";
import { observer } from "mobx-react-lite";
import Link from "next/link";
import { useRouter } from "next/router";
-// lib
import { Button } from "@plane/ui";
+// components
import { CommentCard, AddComment } from "@/components/issues/peek-overview";
import { Icon } from "@/components/ui";
// hooks
-import { useUser } from "@/hooks/store";
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore, useUser } from "@/hooks/store";
// types
import { IIssue } from "@/types/issue";
diff --git a/space/components/issues/peek-overview/issue-emoji-reactions.tsx b/space/components/issues/peek-overview/issue-emoji-reactions.tsx
index 207434100..7e568461b 100644
--- a/space/components/issues/peek-overview/issue-emoji-reactions.tsx
+++ b/space/components/issues/peek-overview/issue-emoji-reactions.tsx
@@ -4,12 +4,10 @@ import { useRouter } from "next/router";
// lib
import { Tooltip } from "@plane/ui";
import { ReactionSelector } from "@/components/ui";
+// helpers
import { groupReactions, renderEmoji } from "@/helpers/emoji.helper";
// hooks
-import { useUser } from "@/hooks/store";
-import { useMobxStore } from "@/lib/mobx/store-provider";
-// helpers
-// components
+import { useMobxStore, useUser } from "@/hooks/store";
export const IssueEmojiReactions: React.FC = observer(() => {
// router
diff --git a/space/components/issues/peek-overview/issue-reaction.tsx b/space/components/issues/peek-overview/issue-reaction.tsx
index eaa5bb8d5..5bc60cb34 100644
--- a/space/components/issues/peek-overview/issue-reaction.tsx
+++ b/space/components/issues/peek-overview/issue-reaction.tsx
@@ -1,5 +1,5 @@
import { IssueEmojiReactions, IssueVotes } from "@/components/issues/peek-overview";
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
export const IssueReactions: React.FC = () => {
const { project: projectStore } = useMobxStore();
diff --git a/space/components/issues/peek-overview/issue-vote-reactions.tsx b/space/components/issues/peek-overview/issue-vote-reactions.tsx
index b7d95a18a..64568f66c 100644
--- a/space/components/issues/peek-overview/issue-vote-reactions.tsx
+++ b/space/components/issues/peek-overview/issue-vote-reactions.tsx
@@ -1,15 +1,9 @@
import { useState, useEffect } from "react";
-
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
-
-// mobx
-// lib
import { Tooltip } from "@plane/ui";
// hooks
-import { useUser } from "@/hooks/store";
-import { useMobxStore } from "@/lib/mobx/store-provider";
-// ui
+import { useMobxStore, useUser } from "@/hooks/store";
export const IssueVotes: React.FC = observer(() => {
const [isSubmitting, setIsSubmitting] = useState(false);
diff --git a/space/components/issues/peek-overview/layout.tsx b/space/components/issues/peek-overview/layout.tsx
index 6662288ce..01183fb2d 100644
--- a/space/components/issues/peek-overview/layout.tsx
+++ b/space/components/issues/peek-overview/layout.tsx
@@ -9,7 +9,7 @@ import { Dialog, Transition } from "@headlessui/react";
// components
import { FullScreenPeekView, SidePeekView } from "@/components/issues/peek-overview";
// lib
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
export const IssuePeekOverview: React.FC = observer(() => {
// states
diff --git a/space/components/views/auth.tsx b/space/components/views/auth.tsx
index 0594cb045..cb36a6146 100644
--- a/space/components/views/auth.tsx
+++ b/space/components/views/auth.tsx
@@ -20,14 +20,14 @@ export const AuthView = observer(() => {
const { data: currentUser, fetchCurrentUser, isLoading } = useUser();
// fetching user information
- useSWR("CURRENT_USER_DETAILS", () => fetchCurrentUser(), {
+ const { isLoading: isSWRLoading } = useSWR("CURRENT_USER_DETAILS", () => fetchCurrentUser(), {
shouldRetryOnError: false,
revalidateOnFocus: false,
});
return (
<>
- {isLoading ? (
+ {isLoading || isSWRLoading ? (
diff --git a/space/components/views/project-details.tsx b/space/components/views/project-details.tsx
index 2233edc0e..ef51a4512 100644
--- a/space/components/views/project-details.tsx
+++ b/space/components/views/project-details.tsx
@@ -11,8 +11,7 @@ import { IssueSpreadsheetView } from "@/components/issues/board-views/spreadshee
import { IssueAppliedFilters } from "@/components/issues/filters/applied-filters/root";
import { IssuePeekOverview } from "@/components/issues/peek-overview";
// mobx store
-import { useUser } from "@/hooks/store";
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore, useUser } from "@/hooks/store";
import { RootStore } from "@/store/root.store";
// assets
import SomethingWentWrongImage from "public/something-went-wrong.svg";
diff --git a/space/helpers/authentication.helper.tsx b/space/helpers/authentication.helper.tsx
new file mode 100644
index 000000000..f60f694b5
--- /dev/null
+++ b/space/helpers/authentication.helper.tsx
@@ -0,0 +1,291 @@
+import { ReactNode } from "react";
+import Link from "next/link";
+
+export enum EPageTypes {
+ "INIT" = "INIT",
+ "PUBLIC" = "PUBLIC",
+ "NON_AUTHENTICATED" = "NON_AUTHENTICATED",
+ "ONBOARDING" = "ONBOARDING",
+ "AUTHENTICATED" = "AUTHENTICATED",
+}
+
+export enum EAuthModes {
+ SIGN_IN = "SIGN_IN",
+ SIGN_UP = "SIGN_UP",
+}
+
+export enum EAuthSteps {
+ EMAIL = "EMAIL",
+ PASSWORD = "PASSWORD",
+ UNIQUE_CODE = "UNIQUE_CODE",
+}
+
+export enum EAuthenticationErrorCodes {
+ INSTANCE_NOT_CONFIGURED = "5000",
+ SIGNUP_DISABLED = "5001",
+ INVALID_PASSWORD = "5002",
+ USER_ALREADY_EXIST = "5003",
+ USER_DOES_NOT_EXIST = "5004",
+ AUTHENTICATION_FAILED_SIGN_IN = "5005",
+ AUTHENTICATION_FAILED_SIGN_UP = "5006",
+ SMTP_NOT_CONFIGURED = "5007",
+ INVALID_MAGIC_CODE = "5008",
+ EXPIRED_MAGIC_CODE = "5009",
+ GOOGLE_NOT_CONFIGURED = "5010",
+ GITHUB_NOT_CONFIGURED = "5011",
+ INVALID_EMAIL = "5012",
+ EMAIL_REQUIRED = "5013",
+ REQUIRED_EMAIL_PASSWORD_SIGN_IN = "5014",
+ INVALID_EMAIL_SIGN_IN = "5015",
+ INVALID_EMAIL_SIGN_UP = "5016",
+ INVALID_EMAIL_MAGIC_SIGN_IN = "5017",
+ INVALID_EMAIL_MAGIC_SIGN_UP = "5018",
+ GITHUB_OAUTH_PROVIDER_ERROR = "5019",
+ GOOGLE_OAUTH_PROVIDER_ERROR = "5020",
+ MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED = "5021",
+ MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED = "5022",
+ INVALID_PASSWORD_TOKEN = "5023",
+ EXPIRED_PASSWORD_TOKEN = "5024",
+ INCORRECT_OLD_PASSWORD = "5025",
+ INVALID_NEW_PASSWORD = "5026",
+ PASSWORD_ALREADY_SET = "5027",
+ ADMIN_ALREADY_EXIST = "5028",
+ REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME = "5029",
+ INVALID_ADMIN_EMAIL = "5030",
+ INVALID_ADMIN_PASSWORD = "5031",
+ REQUIRED_ADMIN_EMAIL_PASSWORD = "5032",
+ ADMIN_AUTHENTICATION_FAILED = "5034",
+}
+
+export enum EErrorAlertType {
+ BANNER_ALERT = "BANNER_ALERT",
+ TOAST_ALERT = "TOAST_ALERT",
+ INLINE_FIRST_NAME = "INLINE_FIRST_NAME",
+ INLINE_EMAIL = "INLINE_EMAIL",
+ INLINE_PASSWORD = "INLINE_PASSWORD",
+ INLINE_EMAIL_CODE = "INLINE_EMAIL_CODE",
+}
+
+export type TAuthErrorInfo = {
+ type: EErrorAlertType;
+ code: EAuthenticationErrorCodes;
+ title: string;
+ message: ReactNode;
+};
+
+const errorCodeMessages: { [key in EAuthenticationErrorCodes]: { title: string; message: ReactNode } } = {
+ [EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED]: {
+ title: `Instance not configured`,
+ message: `Instance not configured. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.SIGNUP_DISABLED]: {
+ title: `Sign up disabled`,
+ message: `Sign up disabled. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_PASSWORD]: {
+ title: `Invalid password`,
+ message: `Invalid password. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.USER_ALREADY_EXIST]: {
+ title: `User already exists`,
+ message: (
+
+ Your account is already registered.
+
+ Sign In
+
+ now.
+
+ ),
+ },
+ [EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
+ title: `User does not exist`,
+ message: (
+
+ No account found.
+
+ Create one
+
+ to get started.
+
+ ),
+ },
+ [EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN]: {
+ title: `Authentication failed`,
+ message: `Authentication failed. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP]: {
+ title: `Authentication failed`,
+ message: `Authentication failed. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED]: {
+ title: `SMTP not configured`,
+ message: `SMTP not configured. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_MAGIC_CODE]: {
+ title: `Authentication failed`,
+ message: `Invalid magic code. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE]: {
+ title: `Expired magic code`,
+ message: `Expired magic code. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED]: {
+ title: `Google not configured`,
+ message: `Google not configured. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED]: {
+ title: `GitHub not configured`,
+ message: `GitHub not configured. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.EMAIL_REQUIRED]: {
+ title: `Email required`,
+ message: `Email required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN]: {
+ title: `Email and password required`,
+ message: `Email and password required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR]: {
+ title: `GitHub OAuth provider error`,
+ message: `GitHub OAuth provider error. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR]: {
+ title: `Google OAuth provider error`,
+ message: `Google OAuth provider error. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED]: {
+ title: `Email and code required`,
+ message: `Email and code required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED]: {
+ title: `Email and code required`,
+ message: `Email and code required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN]: {
+ title: `Invalid password token`,
+ message: `Invalid password token. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN]: {
+ title: `Expired password token`,
+ message: `Expired password token. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD]: {
+ title: `Incorrect old password`,
+ message: `Incorrect old password. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_NEW_PASSWORD]: {
+ title: `Invalid new password`,
+ message: `Invalid new password. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.PASSWORD_ALREADY_SET]: {
+ title: `Password already set`,
+ message: `Password already set. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST]: {
+ title: `Admin already exists`,
+ message: `Admin already exists. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME]: {
+ title: `Email, password and first name required`,
+ message: `Email, password and first name required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD]: {
+ title: `Invalid password`,
+ message: `Invalid password. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD]: {
+ title: `Email and password required`,
+ message: `Email and password required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED]: {
+ title: `Authentication failed`,
+ message: `Authentication failed. Please try again.`,
+ },
+};
+
+export const authErrorHandler = (errorCode: EAuthenticationErrorCodes): TAuthErrorInfo | undefined => {
+ const toastAlertErrorCodes = [
+ EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED,
+ EAuthenticationErrorCodes.SIGNUP_DISABLED,
+ EAuthenticationErrorCodes.INVALID_PASSWORD,
+ EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN,
+ EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP,
+ EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED,
+ EAuthenticationErrorCodes.INVALID_MAGIC_CODE,
+ EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE,
+ EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED,
+ EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED,
+ EAuthenticationErrorCodes.INVALID_EMAIL,
+ EAuthenticationErrorCodes.EMAIL_REQUIRED,
+ EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN,
+ EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN,
+ EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP,
+ EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN,
+ EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP,
+ EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR,
+ EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR,
+ EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED,
+ EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED,
+ EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN,
+ EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN,
+ EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD,
+ EAuthenticationErrorCodes.INVALID_NEW_PASSWORD,
+ EAuthenticationErrorCodes.PASSWORD_ALREADY_SET,
+ EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST,
+ EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME,
+ EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL,
+ EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD,
+ EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD,
+ EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED,
+ ];
+ const bannerAlertErrorCodes = [
+ EAuthenticationErrorCodes.USER_ALREADY_EXIST,
+ EAuthenticationErrorCodes.USER_DOES_NOT_EXIST,
+ ];
+
+ if (toastAlertErrorCodes.includes(errorCode))
+ return {
+ type: EErrorAlertType.TOAST_ALERT,
+ code: errorCode,
+ title: errorCodeMessages[errorCode]?.title || "Error",
+ message: errorCodeMessages[errorCode]?.message || "Something went wrong. Please try again.",
+ };
+
+ if (bannerAlertErrorCodes.includes(errorCode))
+ return {
+ type: EErrorAlertType.BANNER_ALERT,
+ code: errorCode,
+ title: errorCodeMessages[errorCode]?.title || "Error",
+ message: errorCodeMessages[errorCode]?.message || "Something went wrong. Please try again.",
+ };
+
+ return undefined;
+};
diff --git a/space/hooks/store/index.ts b/space/hooks/store/index.ts
index 9a48d10f2..3b7ef07c9 100644
--- a/space/hooks/store/index.ts
+++ b/space/hooks/store/index.ts
@@ -1,2 +1,4 @@
+export * from "./user-mobx-provider";
+
export * from "./use-instance";
export * from "./user";
diff --git a/space/hooks/store/user-mobx-provider.ts b/space/hooks/store/user-mobx-provider.ts
new file mode 100644
index 000000000..4fbc5591f
--- /dev/null
+++ b/space/hooks/store/user-mobx-provider.ts
@@ -0,0 +1,10 @@
+import { useContext } from "react";
+// store
+import { StoreContext } from "@/lib/store-context";
+import { RootStore } from "@/store/root.store";
+
+export const useMobxStore = (): RootStore => {
+ const context = useContext(StoreContext);
+ if (context === undefined) throw new Error("useMobxStore must be used within StoreProvider");
+ return context;
+};
diff --git a/space/hooks/use-editor-suggestions.tsx b/space/hooks/use-editor-suggestions.tsx
index d16d310c2..937306f7b 100644
--- a/space/hooks/use-editor-suggestions.tsx
+++ b/space/hooks/use-editor-suggestions.tsx
@@ -1,4 +1,4 @@
-import { useMobxStore } from "@/lib/mobx/store-provider";
+import { useMobxStore } from "@/hooks/store";
import { RootStore } from "@/store/root.store";
const useEditorSuggestions = () => {
diff --git a/space/lib/mobx/store-provider.tsx b/space/lib/mobx/store-provider.tsx
deleted file mode 100644
index c982246f4..000000000
--- a/space/lib/mobx/store-provider.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-"use client";
-
-import { createContext, useContext } from "react";
-// mobx store
-import { RootStore } from "@/store/root.store";
-
-let rootStore: RootStore = new RootStore();
-
-export const MobxStoreContext = createContext(rootStore);
-
-const initializeStore = () => {
- const singletonRootStore: RootStore = rootStore ?? new RootStore();
- if (typeof window === "undefined") return singletonRootStore;
- if (!rootStore) rootStore = singletonRootStore;
- return singletonRootStore;
-};
-
-export const MobxStoreProvider = ({ children }: any) => {
- const store: RootStore = initializeStore();
- return {children};
-};
-
-// hook
-export const useMobxStore = () => {
- const context = useContext(MobxStoreContext);
- if (context === undefined) throw new Error("useMobxStore must be used within MobxStoreProvider");
- return context;
-};
diff --git a/space/lib/wrappers/auth-wrapper.tsx b/space/lib/wrappers/auth-wrapper.tsx
new file mode 100644
index 000000000..1dad8f337
--- /dev/null
+++ b/space/lib/wrappers/auth-wrapper.tsx
@@ -0,0 +1,86 @@
+import { FC, ReactNode } from "react";
+import { observer } from "mobx-react-lite";
+import { useRouter } from "next/router";
+import useSWR from "swr";
+import { Spinner } from "@plane/ui";
+// helpers
+import { EPageTypes } from "@/helpers/authentication.helper";
+// hooks
+import { useUser, useUserProfile } from "@/hooks/store";
+
+type TAuthWrapper = {
+ children: ReactNode;
+ pageType?: EPageTypes;
+};
+
+export const AuthWrapper: FC = observer((props) => {
+ const router = useRouter();
+ const { children, pageType = EPageTypes.AUTHENTICATED } = props;
+ // hooks
+ const { isLoading, data: currentUser, fetchCurrentUser } = useUser();
+ const { data: currentUserProfile } = useUserProfile();
+
+ console;
+
+ const { isLoading: isSWRLoading } = useSWR("INSTANCE_INFORMATION", () => fetchCurrentUser(), {
+ revalidateOnFocus: false,
+ });
+
+ if (isSWRLoading || isLoading)
+ return (
+
+
+
+ );
+
+ if (pageType === EPageTypes.PUBLIC) return <>{children}>;
+
+ if (pageType === EPageTypes.INIT) {
+ if (!currentUser?.id) return <>{children}>;
+ else {
+ if (currentUserProfile?.id && currentUserProfile?.onboarding_step?.profile_complete) return <>{children}>;
+ else {
+ router.push(`/onboarding`);
+ return <>>;
+ }
+ }
+ }
+
+ if (pageType === EPageTypes.NON_AUTHENTICATED) {
+ if (!currentUser?.id) return <>{children}>;
+ else {
+ if (currentUserProfile?.id && currentUserProfile?.onboarding_step?.profile_complete) {
+ router.push(`/`);
+ return <>>;
+ } else {
+ router.push(`/onboarding`);
+ return <>>;
+ }
+ }
+ }
+
+ if (pageType === EPageTypes.ONBOARDING) {
+ if (!currentUser?.id) {
+ router.push(`/`);
+ return <>>;
+ } else {
+ if (currentUserProfile?.id && currentUserProfile?.onboarding_step?.profile_complete) {
+ router.push(`/`);
+ return <>>;
+ } else return <>{children}>;
+ }
+ }
+
+ if (pageType === EPageTypes.AUTHENTICATED) {
+ if (!currentUser?.id) return <>{children}>;
+ else {
+ if (currentUserProfile?.id && currentUserProfile?.onboarding_step?.profile_complete) return <>{children}>;
+ else {
+ router.push(`/onboarding`);
+ return <>>;
+ }
+ }
+ }
+
+ return <>{children}>;
+});
diff --git a/space/lib/wrappers/index.ts b/space/lib/wrappers/index.ts
new file mode 100644
index 000000000..51fab70a6
--- /dev/null
+++ b/space/lib/wrappers/index.ts
@@ -0,0 +1,2 @@
+export * from "./instance-wrapper";
+export * from "./auth-wrapper";
diff --git a/space/layouts/instance-layout.tsx b/space/lib/wrappers/instance-wrapper.tsx
similarity index 73%
rename from space/layouts/instance-layout.tsx
rename to space/lib/wrappers/instance-wrapper.tsx
index 65e56d50f..05390fad8 100644
--- a/space/layouts/instance-layout.tsx
+++ b/space/lib/wrappers/instance-wrapper.tsx
@@ -8,20 +8,20 @@ import { InstanceNotReady } from "@/components/instance";
// hooks
import { useInstance } from "@/hooks/store";
-type TInstanceLayout = {
+type TInstanceWrapper = {
children: ReactNode;
};
-const InstanceLayout: FC = observer((props) => {
+export const InstanceWrapper: FC = observer((props) => {
const { children } = props;
- // store
+ // hooks
const { isLoading, instance, fetchInstanceInfo } = useInstance();
- useSWR("INSTANCE_INFORMATION", () => fetchInstanceInfo(), {
+ const { isLoading: isSWRLoading } = useSWR("INSTANCE_INFORMATION", () => fetchInstanceInfo(), {
revalidateOnFocus: false,
});
- if (isLoading)
+ if (isSWRLoading || isLoading)
return (
@@ -32,5 +32,3 @@ const InstanceLayout: FC
= observer((props) => {
return <>{children}>;
});
-
-export default InstanceLayout;
diff --git a/space/pages/[workspace_slug]/[project_slug]/index.tsx b/space/pages/[workspace_slug]/[project_slug]/index.tsx
index 9e8a6018d..aaec7672e 100644
--- a/space/pages/[workspace_slug]/[project_slug]/index.tsx
+++ b/space/pages/[workspace_slug]/[project_slug]/index.tsx
@@ -1,14 +1,16 @@
import Head from "next/head";
import { useRouter } from "next/router";
-
import useSWR from "swr";
-
-/// layouts
// components
import { ProjectDetailsView } from "@/components/views";
-// lib
-import { useMobxStore } from "@/lib/mobx/store-provider";
-import ProjectLayout from "layouts/project-layout";
+// helpers
+import { EPageTypes } from "@/helpers/authentication.helper";
+// hooks
+import { useMobxStore } from "@/hooks/store";
+// layouts
+import ProjectLayout from "@/layouts/project-layout";
+// wrappers
+import { AuthWrapper } from "@/lib/wrappers";
const WorkspaceProjectPage = (props: any) => {
const SITE_TITLE = props?.project_settings?.project_details?.name || "Plane | Deploy";
@@ -31,12 +33,14 @@ const WorkspaceProjectPage = (props: any) => {
});
return (
-
-
- {SITE_TITLE}
-
-
-
+
+
+
+ {SITE_TITLE}
+
+
+
+
);
};
diff --git a/space/pages/_app.tsx b/space/pages/_app.tsx
index ce206f49b..16f6e6efd 100644
--- a/space/pages/_app.tsx
+++ b/space/pages/_app.tsx
@@ -7,15 +7,15 @@ import "@/styles/globals.css";
import { SITE_NAME, SITE_DESCRIPTION, SITE_URL, TWITTER_USER_NAME, SITE_KEYWORDS, SITE_TITLE } from "@/constants/seo";
import { ToastContextProvider } from "@/contexts/toast.context";
// mobx store provider
-import InstanceLayout from "@/layouts/instance-layout";
-import { MobxStoreProvider } from "@/lib/mobx/store-provider";
-// constants
+import { StoreProvider } from "@/lib/store-context";
+// wrappers
+import { InstanceWrapper } from "@/lib/wrappers";
const prefix = parseInt(process.env.NEXT_PUBLIC_DEPLOY_WITH_NGINX || "0") === 0 ? "/" : "/spaces/";
function MyApp({ Component, pageProps }: AppProps) {
return (
-
+ <>
{SITE_TITLE}
@@ -31,14 +31,16 @@ function MyApp({ Component, pageProps }: AppProps) {
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ >
);
}
diff --git a/space/pages/accounts/forgot-password.tsx b/space/pages/accounts/forgot-password.tsx
index 0538df24a..494eae9d3 100644
--- a/space/pages/accounts/forgot-password.tsx
+++ b/space/pages/accounts/forgot-password.tsx
@@ -9,11 +9,13 @@ import { CircleCheck } from "lucide-react";
// ui
import { Button, Input, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui";
// helpers
+import { EPageTypes } from "@/helpers/authentication.helper";
import { cn } from "@/helpers/common.helper";
import { checkEmailValidity } from "@/helpers/string.helper";
// hooks
-// import useAuthRedirection from "@/hooks/use-auth-redirection";
import useTimer from "@/hooks/use-timer";
+// wrappers
+import { AuthWrapper } from "@/lib/wrappers";
// services
import { AuthService } from "@/services/authentication.service";
// images
@@ -77,85 +79,87 @@ const ForgotPasswordPage: NextPage = () => {
};
return (
-
-
-
-
-
-
-
-
- Plane
-
+
+
+
+
-
-
-
-
-
- Reset your password
-
-
- Enter your user account{"'"}s verified email address and we will send you a password reset link.
-
-
-
+
);
};
diff --git a/space/pages/accounts/reset-password.tsx b/space/pages/accounts/reset-password.tsx
index a8d232d97..773acb10e 100644
--- a/space/pages/accounts/reset-password.tsx
+++ b/space/pages/accounts/reset-password.tsx
@@ -10,9 +10,11 @@ import { Button, Input } from "@plane/ui";
// components
import { PasswordStrengthMeter } from "@/components/accounts";
// helpers
+import { EPageTypes } from "@/helpers/authentication.helper";
import { API_BASE_URL } from "@/helpers/common.helper";
import { getPasswordStrength } from "@/helpers/password.helper";
-// hooks
+// wrappers
+import { AuthWrapper } from "@/lib/wrappers";
// services
import { AuthService } from "@/services/authentication.service";
// images
@@ -75,98 +77,71 @@ const ResetPasswordPage: NextPage = () => {
);
return (
-
-
-
-
-
-
-
-
- Plane
-
+
+
+
+
-
-
-
-
-
- Set new password
-
-
Secure your account with a strong password
-
-
+
);
};
diff --git a/space/pages/index.tsx b/space/pages/index.tsx
index 0ab791c60..8bba85cca 100644
--- a/space/pages/index.tsx
+++ b/space/pages/index.tsx
@@ -2,8 +2,15 @@ import { observer } from "mobx-react-lite";
import { NextPage } from "next";
// components
import { AuthView } from "@/components/views";
-// store
+// helpers
+import { EPageTypes } from "@/helpers/authentication.helper";
+// wrapper
+import { AuthWrapper } from "@/lib/wrappers";
-const Index: NextPage = observer(() =>
);
+const Index: NextPage = observer(() => (
+
+
+
+));
export default Index;
diff --git a/space/pages/onboarding/index.tsx b/space/pages/onboarding/index.tsx
index acebd6b2c..6ba95126a 100644
--- a/space/pages/onboarding/index.tsx
+++ b/space/pages/onboarding/index.tsx
@@ -7,8 +7,12 @@ import { useTheme } from "next-themes";
import { Avatar } from "@plane/ui";
// components
import { OnBoardingForm } from "@/components/accounts/onboarding-form";
-// mobx
+// helpers
+import { EPageTypes } from "@/helpers/authentication.helper";
+// hooks
import { useUser, useUserProfile } from "@/hooks/store";
+// wrappers
+import { AuthWrapper } from "@/lib/wrappers";
// assets
import ProfileSetupDark from "public/onboarding/profile-setup-dark.svg";
import ProfileSetup from "public/onboarding/profile-setup.svg";
@@ -49,71 +53,78 @@ const OnBoardingPage = observer(() => {
};
return (
-
-
-
-
-
-
+
+
+
+
-
-
-
- {user?.avatar && (
-
- )}
-
- {user?.first_name ? `${user?.first_name} ${user?.last_name ?? ""}` : user?.email}
-
+
+
+
+ {user?.avatar && (
+
+ )}
+
+ {user?.first_name ? `${user?.first_name} ${user?.last_name ?? ""}` : user?.email}
+
+
-
-
-
-
Welcome to Plane!
-
- Let’s setup your profile, tell us a bit about yourself.
-
-
-
-
-
-
-
-
- {user?.avatar && (
-
- )}
-
- {user?.first_name ? `${user?.first_name} ${user?.last_name ?? ""}` : user?.email}
-
+
+
+
Welcome to Plane!
+
+ Let’s setup your profile, tell us a bit about yourself.
+
+
+
-
-
+
+
+
+ {user?.avatar && (
+
+ )}
+
+ {user?.first_name ? `${user?.first_name} ${user?.last_name ?? ""}` : user?.email}
+
+
+
+
+
+
-
+
);
});
diff --git a/space/pages/project-not-published/index.tsx b/space/pages/project-not-published/index.tsx
index acc638412..803ed3d03 100644
--- a/space/pages/project-not-published/index.tsx
+++ b/space/pages/project-not-published/index.tsx
@@ -1,32 +1,39 @@
// next imports
import Image from "next/image";
-import projectNotPublishedImage from "public/project-not-published.svg";
+// helpers
+import { EPageTypes } from "@/helpers/authentication.helper";
+// wrappers
+import { AuthWrapper } from "@/lib/wrappers";
+// images
+import projectNotPublishedImage from "@/public/project-not-published.svg";
const CustomProjectNotPublishedError = () => (
-
-
-
-
-
+
+
+
+
+
+
+
+
+ Oops! The page you{`'`}re looking for isn{`'`}t live at the moment.
+
+
+ If this is your project, login to your workspace to adjust its visibility settings and make it public.
+
-
- Oops! The page you{`'`}re looking for isn{`'`}t live at the moment.
-
-
- If this is your project, login to your workspace to adjust its visibility settings and make it public.
-
-
-
-
+
);
export default CustomProjectNotPublishedError;
diff --git a/space/services/api.service.ts b/space/services/api.service.ts
index 9ab4d56ed..26f8cc727 100644
--- a/space/services/api.service.ts
+++ b/space/services/api.service.ts
@@ -19,7 +19,7 @@ abstract class APIService {
this.axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
- if (error.response && error.response.status === 401) window.location.href = "/space/login";
+ if (error.response && error.response.status === 401) window.location.href = "/";
return Promise.reject(error.response?.data ?? error);
}
);
diff --git a/space/services/authentication.service.ts b/space/services/authentication.service.ts
index 698aaa31f..e18205479 100644
--- a/space/services/authentication.service.ts
+++ b/space/services/authentication.service.ts
@@ -26,7 +26,7 @@ export class AuthService extends APIService {
});
}
- async sendResetPasswordLink(data: { email: string }): Promise
{
+ async sendResetPasswordLink(data: { email: string }): Promise {
return this.post(`/auth/forgot-password/`, data)
.then((response) => response?.data)
.catch((error) => {
@@ -34,7 +34,7 @@ export class AuthService extends APIService {
});
}
- async generateUniqueCode(data: { email: string }): Promise {
+ async generateUniqueCode(data: { email: string }): Promise {
return this.post("/auth/spaces/magic-generate/", data, { headers: {} })
.then((response) => response?.data)
.catch((error) => {
diff --git a/space/services/user.service.ts b/space/services/user.service.ts
index a08ccf837..72500a048 100644
--- a/space/services/user.service.ts
+++ b/space/services/user.service.ts
@@ -18,7 +18,7 @@ export class UserService extends APIService {
});
}
- async updateUser(data: Partial): Promise {
+ async updateUser(data: Partial): Promise {
return this.patch("/api/users/me/", data)
.then((response) => response?.data)
.catch((error) => {
@@ -33,7 +33,7 @@ export class UserService extends APIService {
throw error?.response;
});
}
- async updateCurrentUserProfile(data: any): Promise {
+ async updateCurrentUserProfile(data: Partial): Promise {
return this.patch("/api/users/me/profile/", data)
.then((response) => response?.data)
.catch((error) => {
diff --git a/web/components/account/auth-forms/sign-in-root.tsx b/web/components/account/auth-forms/auth-root.tsx
similarity index 66%
rename from web/components/account/auth-forms/sign-in-root.tsx
rename to web/components/account/auth-forms/auth-root.tsx
index 78a65a63d..a451994d8 100644
--- a/web/components/account/auth-forms/sign-in-root.tsx
+++ b/web/components/account/auth-forms/auth-root.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from "react";
+import React, { FC, useEffect, useState } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { IEmailCheckData } from "@plane/types";
@@ -29,26 +29,42 @@ import { AuthService } from "@/services/auth.service";
const authService = new AuthService();
-export const SignInAuthRoot = observer(() => {
+type TAuthRoot = {
+ authMode: EAuthModes;
+};
+
+export const AuthRoot: FC = observer((props) => {
//router
const router = useRouter();
- const { email: emailParam, invitation_id, slug: workspaceSlug, error_code, error_message } = router.query;
+ const { email: emailParam, invitation_id, slug: workspaceSlug, error_code } = router.query;
+ // props
+ const { authMode } = props;
// states
const [authStep, setAuthStep] = useState(EAuthSteps.EMAIL);
const [email, setEmail] = useState(emailParam ? emailParam.toString() : "");
const [errorInfo, setErrorInfo] = useState(undefined);
// hooks
const { instance } = useInstance();
- // derived values
- const authMode = EAuthModes.SIGN_IN;
useEffect(() => {
- if (error_code && error_message) {
- const errorhandler = authErrorHandler(
- error_code?.toString() as EAuthenticationErrorCodes,
- error_message?.toString()
- );
+ if (error_code) {
+ const errorhandler = authErrorHandler(error_code?.toString() as EAuthenticationErrorCodes);
if (errorhandler) {
+ if (
+ [
+ EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN,
+ EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP,
+ ].includes(errorhandler.code)
+ )
+ setAuthStep(EAuthSteps.PASSWORD);
+ if (
+ [EAuthenticationErrorCodes.INVALID_MAGIC_CODE, EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE].includes(
+ errorhandler.code
+ )
+ )
+ setAuthStep(EAuthSteps.UNIQUE_CODE);
+
+ // validating wheather to show alert to banner
if (errorhandler?.type === EErrorAlertType.TOAST_ALERT) {
setToast({
type: TOAST_TYPE.ERROR,
@@ -58,23 +74,30 @@ export const SignInAuthRoot = observer(() => {
} else setErrorInfo(errorhandler);
}
}
- }, [error_code, error_message]);
+ }, [error_code, authMode]);
// step 1 submit handler- email verification
const handleEmailVerification = async (data: IEmailCheckData) => {
setEmail(data.email);
- await authService
- .signInEmailCheck(data)
+ const emailCheckRequest =
+ authMode === EAuthModes.SIGN_IN ? authService.signInEmailCheck(data) : authService.signUpEmailCheck(data);
+
+ await emailCheckRequest
.then(() => {
setAuthStep(EAuthSteps.PASSWORD);
})
- .catch((err) => {
- setToast({
- type: TOAST_TYPE.ERROR,
- title: "Error!",
- message: err?.error_message ?? "Something went wrong. Please try again.",
- });
+ .catch((error) => {
+ const errorhandler = authErrorHandler(error?.error_code.toString());
+ if (errorhandler?.type === EErrorAlertType.BANNER_ALERT) {
+ setErrorInfo(errorhandler);
+ return;
+ } else if (errorhandler?.type === EErrorAlertType.TOAST_ALERT)
+ setToast({
+ type: TOAST_TYPE.ERROR,
+ title: errorhandler?.title,
+ message: (errorhandler?.message as string) || "Something went wrong. Please try again.",
+ });
});
};
@@ -87,7 +110,7 @@ export const SignInAuthRoot = observer(() => {
workspaceSlug={workspaceSlug?.toString() || undefined}
invitationId={invitation_id?.toString() || undefined}
invitationEmail={email || undefined}
- authMode={EAuthModes.SIGN_IN}
+ authMode={authMode}
currentAuthStep={authStep}
>
{errorInfo && errorInfo?.type === EErrorAlertType.BANNER_ALERT && (
diff --git a/web/components/account/auth-forms/index.ts b/web/components/account/auth-forms/index.ts
index e5d77069c..604c4b5c6 100644
--- a/web/components/account/auth-forms/index.ts
+++ b/web/components/account/auth-forms/index.ts
@@ -1,5 +1,4 @@
-export * from "./sign-up-root";
-export * from "./sign-in-root";
+export * from "./auth-root";
export * from "./auth-header";
export * from "./auth-banner";
diff --git a/web/components/account/auth-forms/sign-up-root.tsx b/web/components/account/auth-forms/sign-up-root.tsx
deleted file mode 100644
index 0ea698674..000000000
--- a/web/components/account/auth-forms/sign-up-root.tsx
+++ /dev/null
@@ -1,133 +0,0 @@
-import { FC, useEffect, useState } from "react";
-import { observer } from "mobx-react";
-import { useRouter } from "next/router";
-// types
-import { IEmailCheckData } from "@plane/types";
-// ui
-import { TOAST_TYPE, setToast } from "@plane/ui";
-// components
-import {
- AuthHeader,
- AuthBanner,
- AuthEmailForm,
- AuthUniqueCodeForm,
- AuthPasswordForm,
- OAuthOptions,
- TermsAndConditions,
-} from "@/components/account";
-// helpers
-import {
- EAuthModes,
- EAuthSteps,
- EAuthenticationErrorCodes,
- EErrorAlertType,
- TAuthErrorInfo,
- authErrorHandler,
-} from "@/helpers/authentication.helper";
-// hooks
-import { useInstance } from "@/hooks/store";
-// services
-import { AuthService } from "@/services/auth.service";
-
-// service initialization
-const authService = new AuthService();
-
-export const SignUpAuthRoot: FC = observer(() => {
- //router
- const router = useRouter();
- const { email: emailParam, invitation_id, slug: workspaceSlug, error_code, error_message } = router.query;
- // states
- const [authStep, setAuthStep] = useState(EAuthSteps.EMAIL);
- const [email, setEmail] = useState(emailParam ? emailParam.toString() : "");
- const [errorInfo, setErrorInfo] = useState(undefined);
- // hooks
- const { instance } = useInstance();
- // derived values
- const authMode = EAuthModes.SIGN_UP;
- const isSmtpConfigured = instance?.config?.is_smtp_configured;
-
- useEffect(() => {
- if (error_code && error_message) {
- const errorhandler = authErrorHandler(
- error_code?.toString() as EAuthenticationErrorCodes,
- error_message?.toString()
- );
- if (errorhandler) {
- if (errorhandler?.type === EErrorAlertType.TOAST_ALERT) {
- setToast({
- type: TOAST_TYPE.ERROR,
- title: errorhandler?.title,
- message: errorhandler?.message as string,
- });
- } else setErrorInfo(errorhandler);
- }
- }
- }, [error_code, error_message]);
-
- // email verification
- const handleEmailVerification = async (data: IEmailCheckData) => {
- setEmail(data.email);
- await authService
- .signUpEmailCheck(data)
- .then(() => {
- if (isSmtpConfigured) setAuthStep(EAuthSteps.UNIQUE_CODE);
- else setAuthStep(EAuthSteps.PASSWORD);
- })
- .catch((error) => {
- const errorhandler = authErrorHandler(error?.error_code, error?.error_message);
- if (errorhandler) {
- setErrorInfo(errorhandler);
- return;
- }
- setToast({
- type: TOAST_TYPE.ERROR,
- title: "Error!",
- message: error?.error_message ?? "Something went wrong. Please try again.",
- });
- });
- };
-
- const isOAuthEnabled =
- instance?.config && (instance?.config?.is_google_enabled || instance?.config?.is_github_enabled);
-
- return (
-
-
- {errorInfo && errorInfo?.type === EErrorAlertType.BANNER_ALERT && (
- setErrorInfo(value)} />
- )}
- {authStep === EAuthSteps.EMAIL && }
- {authStep === EAuthSteps.UNIQUE_CODE && (
- {
- setEmail("");
- setAuthStep(EAuthSteps.EMAIL);
- }}
- submitButtonText="Continue"
- mode={authMode}
- />
- )}
- {authStep === EAuthSteps.PASSWORD && (
- {
- setEmail("");
- setAuthStep(EAuthSteps.EMAIL);
- }}
- handleStepChange={(step) => setAuthStep(step)}
- mode={authMode}
- />
- )}
- {isOAuthEnabled && }
-
-
-
- );
-});
diff --git a/web/helpers/authentication.helper.ts b/web/helpers/authentication.helper.ts
deleted file mode 100644
index 375d2a9fa..000000000
--- a/web/helpers/authentication.helper.ts
+++ /dev/null
@@ -1,149 +0,0 @@
-import { ReactNode } from "react";
-
-export enum EPageTypes {
- "PUBLIC" = "PUBLIC",
- "NON_AUTHENTICATED" = "NON_AUTHENTICATED",
- "ONBOARDING" = "ONBOARDING",
- "AUTHENTICATED" = "AUTHENTICATED",
-}
-
-export enum EAuthModes {
- SIGN_IN = "SIGN_IN",
- SIGN_UP = "SIGN_UP",
-}
-
-export enum EAuthSteps {
- EMAIL = "EMAIL",
- PASSWORD = "PASSWORD",
- UNIQUE_CODE = "UNIQUE_CODE",
-}
-
-export enum EAuthenticationErrorCodes {
- // alert errors
- INSTANCE_NOT_CONFIGURED = "INSTANCE_NOT_CONFIGURED",
- SMTP_NOT_CONFIGURED = "SMTP_NOT_CONFIGURED",
- AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED",
- INVALID_TOKEN = "INVALID_TOKEN",
- EXPIRED_TOKEN = "EXPIRED_TOKEN",
- IMPROPERLY_CONFIGURED = "IMPROPERLY_CONFIGURED",
- OAUTH_PROVIDER_ERROR = "OAUTH_PROVIDER_ERROR",
- // banner errors
- INVALID_EMAIL = "INVALID_EMAIL",
- INVALID_PASSWORD = "INVALID_PASSWORD",
- USER_DOES_NOT_EXIST = "USER_DOES_NOT_EXIST",
- ADMIN_ALREADY_EXIST = "ADMIN_ALREADY_EXIST",
- USER_ALREADY_EXIST = "USER_ALREADY_EXIST",
- // inline errors from backend
- REQUIRED_EMAIL_PASSWORD_FIRST_NAME = "REQUIRED_EMAIL_PASSWORD_FIRST_NAME",
- REQUIRED_EMAIL_PASSWORD = "REQUIRED_EMAIL_PASSWORD",
- EMAIL_CODE_REQUIRED = "EMAIL_CODE_REQUIRED",
-}
-
-export enum EErrorAlertType {
- BANNER_ALERT = "BANNER_ALERT",
- TOAST_ALERT = "TOAST_ALERT",
- INLINE_FIRST_NAME = "INLINE_FIRST_NAME",
- INLINE_EMAIL = "INLINE_EMAIL",
- INLINE_PASSWORD = "INLINE_PASSWORD",
- INLINE_EMAIL_CODE = "INLINE_EMAIL_CODE",
-}
-
-export type TAuthErrorInfo = { type: EErrorAlertType; title: string; message: ReactNode };
-
-const errorCodeMessages: { [key in EAuthenticationErrorCodes]: { title: string; message: ReactNode } } = {
- [EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED]: {
- title: `Instance not configured`,
- message: `Instance not configured. Please contact your administrator.`,
- },
- [EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED]: {
- title: `SMTP not configured`,
- message: `SMTP not configured. Please contact your administrator.`,
- },
- [EAuthenticationErrorCodes.AUTHENTICATION_FAILED]: {
- title: `Authentication failed.`,
- message: `Authentication failed. Please try again.`,
- },
- [EAuthenticationErrorCodes.INVALID_TOKEN]: { title: `Invalid token.`, message: `Invalid token. Please try again.` },
- [EAuthenticationErrorCodes.EXPIRED_TOKEN]: { title: `Expired token.`, message: `Expired token. Please try again.` },
- [EAuthenticationErrorCodes.IMPROPERLY_CONFIGURED]: {
- title: `Improperly configured.`,
- message: `Improperly configured. Please contact your administrator.`,
- },
- [EAuthenticationErrorCodes.OAUTH_PROVIDER_ERROR]: {
- title: `OAuth provider error.`,
- message: `OAuth provider error. Please try again.`,
- },
- [EAuthenticationErrorCodes.INVALID_EMAIL]: {
- title: `Invalid email.`,
- message: `Invalid email. Please try again.`,
- },
- [EAuthenticationErrorCodes.INVALID_PASSWORD]: {
- title: `Invalid password.`,
- message: `Invalid password. Please try again.`,
- },
- [EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
- title: `User does not exist.`,
- message: `User does not exist. Please try again.`,
- },
- [EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST]: {
- title: `Admin already exists.`,
- message: `Admin already exists. Please try again.`,
- },
- [EAuthenticationErrorCodes.USER_ALREADY_EXIST]: {
- title: `User already exists.`,
- message: `User already exists. Please try again.`,
- },
- [EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_FIRST_NAME]: {
- title: `Missing fields.`,
- message: `Email, password, and first name are required.`,
- },
- [EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD]: {
- title: `Missing fields.`,
- message: `Email and password are required.`,
- },
- [EAuthenticationErrorCodes.EMAIL_CODE_REQUIRED]: {
- title: `Missing fields.`,
- message: `Email and code are required.`,
- },
-};
-
-export const authErrorHandler = (
- errorCode: EAuthenticationErrorCodes,
- errorMessage: string | undefined
-): TAuthErrorInfo | undefined => {
- const toastAlertErrorCodes = [
- EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED,
- EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED,
- EAuthenticationErrorCodes.AUTHENTICATION_FAILED,
- EAuthenticationErrorCodes.INVALID_TOKEN,
- EAuthenticationErrorCodes.EXPIRED_TOKEN,
- EAuthenticationErrorCodes.IMPROPERLY_CONFIGURED,
- EAuthenticationErrorCodes.OAUTH_PROVIDER_ERROR,
- ];
- const bannerAlertErrorCodes = [
- EAuthenticationErrorCodes.INVALID_EMAIL,
- EAuthenticationErrorCodes.INVALID_PASSWORD,
- EAuthenticationErrorCodes.USER_DOES_NOT_EXIST,
- EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST,
- EAuthenticationErrorCodes.USER_ALREADY_EXIST,
- EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_FIRST_NAME,
- EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD,
- EAuthenticationErrorCodes.EMAIL_CODE_REQUIRED,
- ];
-
- if (toastAlertErrorCodes.includes(errorCode))
- return {
- type: EErrorAlertType.TOAST_ALERT,
- title: errorCodeMessages[errorCode]?.title || "Error",
- message: errorMessage || errorCodeMessages[errorCode]?.message || "Something went wrong. Please try again.",
- };
-
- if (bannerAlertErrorCodes.includes(errorCode))
- return {
- type: EErrorAlertType.BANNER_ALERT,
- title: errorCodeMessages[errorCode]?.title || "Error",
- message: errorMessage || errorCodeMessages[errorCode]?.message || "Something went wrong. Please try again.",
- };
-
- return undefined;
-};
diff --git a/web/helpers/authentication.helper.tsx b/web/helpers/authentication.helper.tsx
new file mode 100644
index 000000000..7bd61eb83
--- /dev/null
+++ b/web/helpers/authentication.helper.tsx
@@ -0,0 +1,290 @@
+import { ReactNode } from "react";
+import Link from "next/link";
+
+export enum EPageTypes {
+ "PUBLIC" = "PUBLIC",
+ "NON_AUTHENTICATED" = "NON_AUTHENTICATED",
+ "ONBOARDING" = "ONBOARDING",
+ "AUTHENTICATED" = "AUTHENTICATED",
+}
+
+export enum EAuthModes {
+ SIGN_IN = "SIGN_IN",
+ SIGN_UP = "SIGN_UP",
+}
+
+export enum EAuthSteps {
+ EMAIL = "EMAIL",
+ PASSWORD = "PASSWORD",
+ UNIQUE_CODE = "UNIQUE_CODE",
+}
+
+export enum EAuthenticationErrorCodes {
+ INSTANCE_NOT_CONFIGURED = "5000",
+ SIGNUP_DISABLED = "5001",
+ INVALID_PASSWORD = "5002",
+ USER_ALREADY_EXIST = "5003",
+ USER_DOES_NOT_EXIST = "5004",
+ AUTHENTICATION_FAILED_SIGN_IN = "5005",
+ AUTHENTICATION_FAILED_SIGN_UP = "5006",
+ SMTP_NOT_CONFIGURED = "5007",
+ INVALID_MAGIC_CODE = "5008",
+ EXPIRED_MAGIC_CODE = "5009",
+ GOOGLE_NOT_CONFIGURED = "5010",
+ GITHUB_NOT_CONFIGURED = "5011",
+ INVALID_EMAIL = "5012",
+ EMAIL_REQUIRED = "5013",
+ REQUIRED_EMAIL_PASSWORD_SIGN_IN = "5014",
+ INVALID_EMAIL_SIGN_IN = "5015",
+ INVALID_EMAIL_SIGN_UP = "5016",
+ INVALID_EMAIL_MAGIC_SIGN_IN = "5017",
+ INVALID_EMAIL_MAGIC_SIGN_UP = "5018",
+ GITHUB_OAUTH_PROVIDER_ERROR = "5019",
+ GOOGLE_OAUTH_PROVIDER_ERROR = "5020",
+ MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED = "5021",
+ MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED = "5022",
+ INVALID_PASSWORD_TOKEN = "5023",
+ EXPIRED_PASSWORD_TOKEN = "5024",
+ INCORRECT_OLD_PASSWORD = "5025",
+ INVALID_NEW_PASSWORD = "5026",
+ PASSWORD_ALREADY_SET = "5027",
+ ADMIN_ALREADY_EXIST = "5028",
+ REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME = "5029",
+ INVALID_ADMIN_EMAIL = "5030",
+ INVALID_ADMIN_PASSWORD = "5031",
+ REQUIRED_ADMIN_EMAIL_PASSWORD = "5032",
+ ADMIN_AUTHENTICATION_FAILED = "5034",
+}
+
+export enum EErrorAlertType {
+ BANNER_ALERT = "BANNER_ALERT",
+ TOAST_ALERT = "TOAST_ALERT",
+ INLINE_FIRST_NAME = "INLINE_FIRST_NAME",
+ INLINE_EMAIL = "INLINE_EMAIL",
+ INLINE_PASSWORD = "INLINE_PASSWORD",
+ INLINE_EMAIL_CODE = "INLINE_EMAIL_CODE",
+}
+
+export type TAuthErrorInfo = {
+ type: EErrorAlertType;
+ code: EAuthenticationErrorCodes;
+ title: string;
+ message: ReactNode;
+};
+
+const errorCodeMessages: { [key in EAuthenticationErrorCodes]: { title: string; message: ReactNode } } = {
+ [EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED]: {
+ title: `Instance not configured`,
+ message: `Instance not configured. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.SIGNUP_DISABLED]: {
+ title: `Sign up disabled`,
+ message: `Sign up disabled. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_PASSWORD]: {
+ title: `Invalid password`,
+ message: `Invalid password. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.USER_ALREADY_EXIST]: {
+ title: `User already exists`,
+ message: (
+
+ Your account is already registered.
+
+ Sign In
+
+ now.
+
+ ),
+ },
+ [EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
+ title: `User does not exist`,
+ message: (
+
+ No account found.
+
+ Create one
+
+ to get started.
+
+ ),
+ },
+ [EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN]: {
+ title: `Authentication failed`,
+ message: `Authentication failed. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP]: {
+ title: `Authentication failed`,
+ message: `Authentication failed. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED]: {
+ title: `SMTP not configured`,
+ message: `SMTP not configured. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_MAGIC_CODE]: {
+ title: `Authentication failed`,
+ message: `Invalid magic code. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE]: {
+ title: `Expired magic code`,
+ message: `Expired magic code. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED]: {
+ title: `Google not configured`,
+ message: `Google not configured. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED]: {
+ title: `GitHub not configured`,
+ message: `GitHub not configured. Please contact your administrator.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.EMAIL_REQUIRED]: {
+ title: `Email required`,
+ message: `Email required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN]: {
+ title: `Email and password required`,
+ message: `Email and password required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR]: {
+ title: `GitHub OAuth provider error`,
+ message: `GitHub OAuth provider error. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR]: {
+ title: `Google OAuth provider error`,
+ message: `Google OAuth provider error. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED]: {
+ title: `Email and code required`,
+ message: `Email and code required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED]: {
+ title: `Email and code required`,
+ message: `Email and code required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN]: {
+ title: `Invalid password token`,
+ message: `Invalid password token. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN]: {
+ title: `Expired password token`,
+ message: `Expired password token. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD]: {
+ title: `Incorrect old password`,
+ message: `Incorrect old password. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_NEW_PASSWORD]: {
+ title: `Invalid new password`,
+ message: `Invalid new password. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.PASSWORD_ALREADY_SET]: {
+ title: `Password already set`,
+ message: `Password already set. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST]: {
+ title: `Admin already exists`,
+ message: `Admin already exists. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME]: {
+ title: `Email, password and first name required`,
+ message: `Email, password and first name required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL]: {
+ title: `Invalid email`,
+ message: `Invalid email. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD]: {
+ title: `Invalid password`,
+ message: `Invalid password. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD]: {
+ title: `Email and password required`,
+ message: `Email and password required. Please try again.`,
+ },
+ [EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED]: {
+ title: `Authentication failed`,
+ message: `Authentication failed. Please try again.`,
+ },
+};
+
+export const authErrorHandler = (errorCode: EAuthenticationErrorCodes): TAuthErrorInfo | undefined => {
+ const toastAlertErrorCodes = [
+ EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED,
+ EAuthenticationErrorCodes.SIGNUP_DISABLED,
+ EAuthenticationErrorCodes.INVALID_PASSWORD,
+ EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN,
+ EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP,
+ EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED,
+ EAuthenticationErrorCodes.INVALID_MAGIC_CODE,
+ EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE,
+ EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED,
+ EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED,
+ EAuthenticationErrorCodes.INVALID_EMAIL,
+ EAuthenticationErrorCodes.EMAIL_REQUIRED,
+ EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN,
+ EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN,
+ EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP,
+ EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN,
+ EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP,
+ EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR,
+ EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR,
+ EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED,
+ EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED,
+ EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN,
+ EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN,
+ EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD,
+ EAuthenticationErrorCodes.INVALID_NEW_PASSWORD,
+ EAuthenticationErrorCodes.PASSWORD_ALREADY_SET,
+ EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST,
+ EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME,
+ EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL,
+ EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD,
+ EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD,
+ EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED,
+ ];
+ const bannerAlertErrorCodes = [
+ EAuthenticationErrorCodes.USER_ALREADY_EXIST,
+ EAuthenticationErrorCodes.USER_DOES_NOT_EXIST,
+ ];
+
+ if (toastAlertErrorCodes.includes(errorCode))
+ return {
+ type: EErrorAlertType.TOAST_ALERT,
+ code: errorCode,
+ title: errorCodeMessages[errorCode]?.title || "Error",
+ message: errorCodeMessages[errorCode]?.message || "Something went wrong. Please try again.",
+ };
+
+ if (bannerAlertErrorCodes.includes(errorCode))
+ return {
+ type: EErrorAlertType.BANNER_ALERT,
+ code: errorCode,
+ title: errorCodeMessages[errorCode]?.title || "Error",
+ message: errorCodeMessages[errorCode]?.message || "Something went wrong. Please try again.",
+ };
+
+ return undefined;
+};
diff --git a/web/lib/wrappers/instance-wrapper.tsx b/web/lib/wrappers/instance-wrapper.tsx
index 25ca7c424..a9d114dbc 100644
--- a/web/lib/wrappers/instance-wrapper.tsx
+++ b/web/lib/wrappers/instance-wrapper.tsx
@@ -30,12 +30,7 @@ export const InstanceWrapper: FC = observer((props) => {
);
// something went wrong while in the request
- if (error && error?.status === "error")
- return (
-
- Something went wrong. please try again later
-
- );
+ if (error && error?.status === "error") return <>{children}>;
// instance is not ready and setup is not done
if (instance?.instance?.is_setup_done === false) return ;
diff --git a/web/pages/accounts/forgot-password.tsx b/web/pages/accounts/forgot-password.tsx
index 57debc226..cb1df8504 100644
--- a/web/pages/accounts/forgot-password.tsx
+++ b/web/pages/accounts/forgot-password.tsx
@@ -122,7 +122,7 @@ const ForgotPasswordPage: NextPageWithLayout = () => {
-
+
@@ -176,7 +176,7 @@ const ForgotPasswordPage: NextPageWithLayout = () => {
>
{resendTimerCode > 0 ? `Resend in ${resendTimerCode} seconds` : "Send reset link"}
-
+
Back to sign in
diff --git a/web/pages/accounts/reset-password.tsx b/web/pages/accounts/reset-password.tsx
index 433689bf4..f7c9acf37 100644
--- a/web/pages/accounts/reset-password.tsx
+++ b/web/pages/accounts/reset-password.tsx
@@ -90,7 +90,7 @@ const ResetPasswordPage: NextPageWithLayout = () => {
Plane
-
+
diff --git a/web/pages/accounts/set-password.tsx b/web/pages/accounts/set-password.tsx
index 86f98b272..7437f8ea9 100644
--- a/web/pages/accounts/set-password.tsx
+++ b/web/pages/accounts/set-password.tsx
@@ -111,7 +111,7 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
Plane
-
+
diff --git a/web/pages/accounts/sign-in.tsx b/web/pages/accounts/sign-in.tsx
index 30a5b96cb..11f7cc478 100644
--- a/web/pages/accounts/sign-in.tsx
+++ b/web/pages/accounts/sign-in.tsx
@@ -4,12 +4,12 @@ import Link from "next/link";
// ui
import { useTheme } from "next-themes";
// components
-import { SignInAuthRoot } from "@/components/account";
+import { AuthRoot } from "@/components/account";
import { PageHead } from "@/components/core";
// constants
import { NAVIGATE_TO_SIGNUP } from "@/constants/event-tracker";
// helpers
-import { EPageTypes } from "@/helpers/authentication.helper";
+import { EAuthModes, EPageTypes } from "@/helpers/authentication.helper";
// hooks
import { useEventTracker } from "@/hooks/store";
// layouts
@@ -58,8 +58,8 @@ const SignInPage: NextPageWithLayout = observer(() => {
-
diff --git a/web/pages/index.tsx b/web/pages/index.tsx
index 5b23b618e..6b085ffd3 100644
--- a/web/pages/index.tsx
+++ b/web/pages/index.tsx
@@ -5,12 +5,12 @@ import Link from "next/link";
// ui
import { useTheme } from "next-themes";
// components
-import { SignUpAuthRoot } from "@/components/account";
+import { AuthRoot } from "@/components/account";
import { PageHead } from "@/components/core";
// constants
import { NAVIGATE_TO_SIGNIN } from "@/constants/event-tracker";
// helpers
-import { EPageTypes } from "@/helpers/authentication.helper";
+import { EAuthModes, EPageTypes } from "@/helpers/authentication.helper";
// hooks
import { useEventTracker } from "@/hooks/store";
// layouts
@@ -56,8 +56,8 @@ const HomePage: NextPageWithLayout = observer(() => {
-