fix: user state after logout (#2849)

* fix: user state after logout

* chore: user state handle with mobx

* chore: signout update for profile setting

* fix: minor fixes

---------

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
Lakhan Baheti 2023-11-25 23:04:56 +05:30 committed by GitHub
parent e89f152779
commit 51dff31926
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 45 additions and 35 deletions

View File

@ -10,16 +10,12 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { Button } from "@plane/ui"; import { Button } from "@plane/ui";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// services
import { AuthService } from "services/auth.service";
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
}; };
const authService = new AuthService();
export const DeactivateAccountModal: React.FC<Props> = (props) => { export const DeactivateAccountModal: React.FC<Props> = (props) => {
const { isOpen, onClose } = props; const { isOpen, onClose } = props;
@ -28,7 +24,7 @@ export const DeactivateAccountModal: React.FC<Props> = (props) => {
const [isDeactivating, setIsDeactivating] = useState(false); const [isDeactivating, setIsDeactivating] = useState(false);
const { const {
user: { deactivateAccount }, user: { deactivateAccount, signOut },
} = useMobxStore(); } = useMobxStore();
const router = useRouter(); const router = useRouter();
@ -46,8 +42,7 @@ export const DeactivateAccountModal: React.FC<Props> = (props) => {
const handleSwitchAccount = async () => { const handleSwitchAccount = async () => {
setSwitchingAccount(true); setSwitchingAccount(true);
await authService await signOut()
.signOut()
.then(() => { .then(() => {
mutate("CURRENT_USER_DETAILS", null); mutate("CURRENT_USER_DETAILS", null);
setTheme("system"); setTheme("system");

View File

@ -12,8 +12,6 @@ import { LogIn, LogOut, Settings, UserCog2 } from "lucide-react";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// services
import { AuthService } from "services/auth.service";
// ui // ui
import { Avatar, Tooltip } from "@plane/ui"; import { Avatar, Tooltip } from "@plane/ui";
@ -27,15 +25,13 @@ const PROFILE_LINKS = [
}, },
]; ];
const authService = new AuthService();
export const InstanceSidebarDropdown = observer(() => { export const InstanceSidebarDropdown = observer(() => {
const router = useRouter(); const router = useRouter();
// store // store
const { const {
theme: { sidebarCollapsed }, theme: { sidebarCollapsed },
workspace: { workspaceSlug }, workspace: { workspaceSlug },
user: { currentUser, currentUserSettings }, user: { signOut, currentUser, currentUserSettings },
} = useMobxStore(); } = useMobxStore();
// hooks // hooks
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
@ -49,8 +45,7 @@ export const InstanceSidebarDropdown = observer(() => {
""; "";
const handleSignOut = async () => { const handleSignOut = async () => {
await authService await signOut()
.signOut()
.then(() => { .then(() => {
mutate("CURRENT_USER_DETAILS", null); mutate("CURRENT_USER_DETAILS", null);
setTheme("system"); setTheme("system");

View File

@ -10,8 +10,6 @@ import { Check, ChevronDown, LogOut, Plus, Settings, UserCircle2 } from "lucide-
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// services
import { AuthService } from "services/auth.service";
// ui // ui
import { Avatar, Loader } from "@plane/ui"; import { Avatar, Loader } from "@plane/ui";
// types // types
@ -46,8 +44,6 @@ const profileLinks = (workspaceSlug: string, userId: string) => [
}, },
]; ];
const authService = new AuthService();
export const WorkspaceSidebarDropdown = observer(() => { export const WorkspaceSidebarDropdown = observer(() => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug } = router.query; const { workspaceSlug } = router.query;
@ -55,8 +51,8 @@ export const WorkspaceSidebarDropdown = observer(() => {
const { const {
theme: { sidebarCollapsed }, theme: { sidebarCollapsed },
workspace: { workspaces, currentWorkspace: activeWorkspace }, workspace: { workspaces, currentWorkspace: activeWorkspace },
user: { currentUser, updateCurrentUser, isUserInstanceAdmin }, user: { currentUser, updateCurrentUser, isUserInstanceAdmin, signOut },
trackEvent: { setTrackElement } trackEvent: { setTrackElement },
} = useMobxStore(); } = useMobxStore();
// hooks // hooks
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
@ -79,8 +75,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
}; };
const handleSignOut = async () => { const handleSignOut = async () => {
await authService await signOut()
.signOut()
.then(() => { .then(() => {
mutate("CURRENT_USER_DETAILS", null); mutate("CURRENT_USER_DETAILS", null);
setTheme("system"); setTheme("system");

View File

@ -5,22 +5,30 @@ import useSWR from "swr";
import { Spinner } from "@plane/ui"; import { Spinner } from "@plane/ui";
// store // store
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
import { observer } from "mobx-react-lite";
export interface IUserAuthWrapper { export interface IUserAuthWrapper {
children: ReactNode; children: ReactNode;
} }
export const UserAuthWrapper: FC<IUserAuthWrapper> = (props) => { export const UserAuthWrapper: FC<IUserAuthWrapper> = observer((props) => {
const { children } = props; const { children } = props;
// store // store
const { const {
user: { fetchCurrentUser, fetchCurrentUserInstanceAdminStatus, fetchCurrentUserSettings }, user: {
currentUser,
currentUserError,
fetchCurrentUser,
fetchCurrentUserInstanceAdminStatus,
fetchCurrentUserSettings,
},
workspace: { fetchWorkspaces }, workspace: { fetchWorkspaces },
} = useMobxStore(); } = useMobxStore();
// router // router
const router = useRouter(); const router = useRouter();
// fetching user information // fetching user information
const { data: currentUser, error } = useSWR("CURRENT_USER_DETAILS", () => fetchCurrentUser(), { useSWR("CURRENT_USER_DETAILS", () => fetchCurrentUser(), {
shouldRetryOnError: false, shouldRetryOnError: false,
}); });
// fetching current user instance admin status // fetching current user instance admin status
@ -36,7 +44,7 @@ export const UserAuthWrapper: FC<IUserAuthWrapper> = (props) => {
shouldRetryOnError: false, shouldRetryOnError: false,
}); });
if (!currentUser && !error) { if (!currentUser && !currentUserError) {
return ( return (
<div className="h-screen grid place-items-center p-4 bg-custom-background-100"> <div className="h-screen grid place-items-center p-4 bg-custom-background-100">
<div className="flex flex-col items-center gap-3 text-center"> <div className="flex flex-col items-center gap-3 text-center">
@ -46,11 +54,11 @@ export const UserAuthWrapper: FC<IUserAuthWrapper> = (props) => {
); );
} }
if (error) { if (currentUserError) {
const redirectTo = router.asPath; const redirectTo = router.asPath;
router.push(`/?next=${redirectTo}`); router.push(`/?next=${redirectTo}`);
return null; return null;
} }
return <>{children}</>; return <>{children}</>;
}; });

View File

@ -4,8 +4,6 @@ import { Menu, Transition } from "@headlessui/react";
import { LogIn, LogOut, MoveLeft, Plus, User, UserPlus } from "lucide-react"; import { LogIn, LogOut, MoveLeft, Plus, User, UserPlus } from "lucide-react";
// mobx store // mobx store
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// services
import { AuthService } from "services/auth.service";
// ui // ui
import { Avatar, Tooltip } from "@plane/ui"; import { Avatar, Tooltip } from "@plane/ui";
import { Fragment } from "react"; import { Fragment } from "react";
@ -29,8 +27,6 @@ const SIDEBAR_LINKS = [
}, },
]; ];
const authService = new AuthService();
export const ProfileLayoutSidebar = observer(() => { export const ProfileLayoutSidebar = observer(() => {
const router = useRouter(); const router = useRouter();
@ -41,7 +37,7 @@ export const ProfileLayoutSidebar = observer(() => {
const { const {
theme: { sidebarCollapsed, toggleSidebar }, theme: { sidebarCollapsed, toggleSidebar },
workspace: { workspaces }, workspace: { workspaces },
user: { currentUser, currentUserSettings, isUserInstanceAdmin }, user: { currentUser, currentUserSettings, isUserInstanceAdmin, signOut },
} = useMobxStore(); } = useMobxStore();
// redirect url for normal mode // redirect url for normal mode
@ -51,8 +47,7 @@ export const ProfileLayoutSidebar = observer(() => {
""; "";
const handleSignOut = async () => { const handleSignOut = async () => {
await authService await signOut()
.signOut()
.then(() => { .then(() => {
mutate("CURRENT_USER_DETAILS", null); mutate("CURRENT_USER_DETAILS", null);
setTheme("system"); setTheme("system");

View File

@ -4,6 +4,7 @@ import { action, observable, runInAction, makeObservable, computed } from "mobx"
import { ProjectMemberService, ProjectService } from "services/project"; import { ProjectMemberService, ProjectService } from "services/project";
import { UserService } from "services/user.service"; import { UserService } from "services/user.service";
import { WorkspaceService } from "services/workspace.service"; import { WorkspaceService } from "services/workspace.service";
import { AuthService } from "services/auth.service";
// interfaces // interfaces
import { IUser, IUserSettings } from "types/users"; import { IUser, IUserSettings } from "types/users";
import { IWorkspaceMemberMe, IProjectMember, TUserProjectRole, TUserWorkspaceRole } from "types"; import { IWorkspaceMemberMe, IProjectMember, TUserProjectRole, TUserWorkspaceRole } from "types";
@ -11,6 +12,7 @@ import { RootStore } from "./root";
export interface IUserStore { export interface IUserStore {
loader: boolean; loader: boolean;
currentUserError: any;
isUserLoggedIn: boolean | null; isUserLoggedIn: boolean | null;
currentUser: IUser | null; currentUser: IUser | null;
@ -55,6 +57,7 @@ export interface IUserStore {
updateCurrentUserTheme: (theme: string) => Promise<IUser>; updateCurrentUserTheme: (theme: string) => Promise<IUser>;
deactivateAccount: () => Promise<void>; deactivateAccount: () => Promise<void>;
signOut: () => Promise<void>;
leaveWorkspace: (workspaceSlug: string) => Promise<void>; leaveWorkspace: (workspaceSlug: string) => Promise<void>;
@ -64,6 +67,7 @@ export interface IUserStore {
class UserStore implements IUserStore { class UserStore implements IUserStore {
loader: boolean = false; loader: boolean = false;
currentUserError: any = null;
isUserLoggedIn: boolean | null = null; isUserLoggedIn: boolean | null = null;
currentUser: IUser | null = null; currentUser: IUser | null = null;
@ -92,6 +96,7 @@ class UserStore implements IUserStore {
workspaceService; workspaceService;
projectService; projectService;
projectMemberService; projectMemberService;
authService;
constructor(_rootStore: RootStore) { constructor(_rootStore: RootStore) {
makeObservable(this, { makeObservable(this, {
@ -121,6 +126,7 @@ class UserStore implements IUserStore {
leaveWorkspace: action, leaveWorkspace: action,
joinProject: action, joinProject: action,
leaveProject: action, leaveProject: action,
signOut: action,
// computed // computed
currentProjectMemberInfo: computed, currentProjectMemberInfo: computed,
currentWorkspaceMemberInfo: computed, currentWorkspaceMemberInfo: computed,
@ -134,6 +140,7 @@ class UserStore implements IUserStore {
this.workspaceService = new WorkspaceService(); this.workspaceService = new WorkspaceService();
this.projectService = new ProjectService(); this.projectService = new ProjectService();
this.projectMemberService = new ProjectMemberService(); this.projectMemberService = new ProjectMemberService();
this.authService = new AuthService();
} }
get currentWorkspaceMemberInfo() { get currentWorkspaceMemberInfo() {
@ -171,6 +178,7 @@ class UserStore implements IUserStore {
const response = await this.userService.currentUser(); const response = await this.userService.currentUser();
if (response) { if (response) {
runInAction(() => { runInAction(() => {
this.currentUserError = null;
this.currentUser = response; this.currentUser = response;
this.isUserLoggedIn = true; this.isUserLoggedIn = true;
}); });
@ -178,6 +186,7 @@ class UserStore implements IUserStore {
return response; return response;
} catch (error) { } catch (error) {
runInAction(() => { runInAction(() => {
this.currentUserError = error;
this.isUserLoggedIn = false; this.isUserLoggedIn = false;
}); });
throw error; throw error;
@ -422,6 +431,19 @@ class UserStore implements IUserStore {
throw error; throw error;
} }
}; };
signOut = async () => {
try {
await this.authService.signOut();
runInAction(() => {
this.currentUserError = null;
this.currentUser = null;
this.isUserLoggedIn = false;
});
} catch (error) {
throw error;
}
};
} }
export default UserStore; export default UserStore;