@burdenoff/microfe-auth 2026.514.1 → 2026.514.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/components/profile/UserProfileMenu.d.ts.map +1 -1
- package/dist/auth/components/profile/UserProfileMenu.js +63 -52
- package/dist/auth/components/profile/UserProfileMenu.js.map +1 -1
- package/dist/auth/hooks/useAuthOperations.d.ts.map +1 -1
- package/dist/auth/hooks/useAuthOperations.js +78 -70
- package/dist/auth/hooks/useAuthOperations.js.map +1 -1
- package/dist/auth/hooks/useSessionOperations.d.ts.map +1 -1
- package/dist/auth/hooks/useSessionOperations.js +2 -1
- package/dist/auth/hooks/useSessionOperations.js.map +1 -1
- package/dist/auth/pages/LoginPage.d.ts.map +1 -1
- package/dist/auth/pages/LoginPage.js +214 -246
- package/dist/auth/pages/LoginPage.js.map +1 -1
- package/dist/auth/pages/PasswordResetPage.d.ts.map +1 -1
- package/dist/auth/pages/PasswordResetPage.js +54 -53
- package/dist/auth/pages/PasswordResetPage.js.map +1 -1
- package/dist/auth/pages/RegisterPage.d.ts.map +1 -1
- package/dist/auth/pages/RegisterPage.js +206 -189
- package/dist/auth/pages/RegisterPage.js.map +1 -1
- package/dist/auth/pages/SecurityPage.d.ts.map +1 -1
- package/dist/auth/pages/SecurityPage.js +229 -248
- package/dist/auth/pages/SecurityPage.js.map +1 -1
- package/dist/auth/utils/validation.js +1 -1
- package/dist/auth/utils/validation.js.map +1 -1
- package/dist/dev/main.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserProfileMenu.d.ts","sourceRoot":"","sources":["../../../../src/auth/components/profile/UserProfileMenu.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UserProfileMenu.d.ts","sourceRoot":"","sources":["../../../../src/auth/components/profile/UserProfileMenu.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAE/B;;;OAGG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IAErB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,iBAAiB,EACjB,QAAQ,EACR,QAAkB,GACnB,EAAE,oBAAoB,kDA2JtB"}
|
|
@@ -1,91 +1,102 @@
|
|
|
1
1
|
import { useAuthStore as e } from "../../store/authStore.js";
|
|
2
2
|
import { useEffect as t, useRef as n, useState as r } from "react";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { useNavigate as i } from "react-router-dom";
|
|
4
|
+
import { Building2 as a, ChevronDown as o, LogOut as s, UserPlus as c } from "lucide-react";
|
|
5
|
+
import { useI18n as l } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
6
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
6
7
|
//#region src/auth/components/profile/UserProfileMenu.tsx
|
|
7
|
-
function
|
|
8
|
-
let { t:
|
|
9
|
-
let n =
|
|
8
|
+
function f({ onSwitchWorkspace: f, onLogout: p, position: m = "right" }) {
|
|
9
|
+
let { t: h } = l(), g = (e, t) => {
|
|
10
|
+
let n = h(e);
|
|
10
11
|
return n === e ? t : n;
|
|
11
|
-
}, [
|
|
12
|
+
}, [_, v] = r(!1), y = n(null), b = i(), x = e((e) => e.user), S = e((e) => e.currentWorkspaceId);
|
|
12
13
|
t(() => {
|
|
13
14
|
function e(e) {
|
|
14
|
-
|
|
15
|
+
y.current && !y.current.contains(e.target) && v(!1);
|
|
15
16
|
}
|
|
16
|
-
if (
|
|
17
|
-
}, [
|
|
18
|
-
let
|
|
19
|
-
|
|
20
|
-
},
|
|
21
|
-
|
|
17
|
+
if (_) return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
18
|
+
}, [_]);
|
|
19
|
+
let C = () => {
|
|
20
|
+
v(!1), p();
|
|
21
|
+
}, w = () => {
|
|
22
|
+
v(!1), f?.();
|
|
22
23
|
};
|
|
23
|
-
if (!
|
|
24
|
-
let
|
|
25
|
-
if (
|
|
26
|
-
if (
|
|
27
|
-
let e =
|
|
28
|
-
return e.length >= 2 ? `${e[0][0]}${e[1][0]}`.toUpperCase() :
|
|
24
|
+
if (!x) return null;
|
|
25
|
+
let T = () => {
|
|
26
|
+
if (x.firstName && x.lastName) return `${x.firstName[0]}${x.lastName[0]}`.toUpperCase();
|
|
27
|
+
if (x.name) {
|
|
28
|
+
let e = x.name.split(" ");
|
|
29
|
+
return e.length >= 2 ? `${e[0][0]}${e[1][0]}`.toUpperCase() : x.name.substring(0, 2).toUpperCase();
|
|
29
30
|
}
|
|
30
|
-
return
|
|
31
|
-
},
|
|
32
|
-
return /* @__PURE__ */
|
|
31
|
+
return x.username ? x.username.substring(0, 2).toUpperCase() : x.email.substring(0, 2).toUpperCase();
|
|
32
|
+
}, E = x.name || `${x.firstName || ""} ${x.lastName || ""}`.trim() || x.username;
|
|
33
|
+
return /* @__PURE__ */ d("div", {
|
|
33
34
|
className: "relative",
|
|
34
|
-
ref:
|
|
35
|
-
children: [/* @__PURE__ */
|
|
36
|
-
onClick: () =>
|
|
35
|
+
ref: y,
|
|
36
|
+
children: [/* @__PURE__ */ d("button", {
|
|
37
|
+
onClick: () => v(!_),
|
|
37
38
|
className: "flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-bg-sunken transition-colors",
|
|
38
39
|
"aria-label": "User menu",
|
|
39
|
-
"aria-expanded":
|
|
40
|
+
"aria-expanded": _,
|
|
40
41
|
children: [
|
|
41
|
-
/* @__PURE__ */
|
|
42
|
+
/* @__PURE__ */ u("div", {
|
|
42
43
|
className: "w-8 h-8 rounded-full bg-accent-blue flex items-center justify-center text-white text-sm font-medium",
|
|
43
|
-
children:
|
|
44
|
+
children: T()
|
|
44
45
|
}),
|
|
45
|
-
/* @__PURE__ */
|
|
46
|
+
/* @__PURE__ */ u("span", {
|
|
46
47
|
className: "hidden sm:block text-sm font-medium text-text-secondary",
|
|
47
|
-
children:
|
|
48
|
+
children: E
|
|
48
49
|
}),
|
|
49
|
-
/* @__PURE__ */
|
|
50
|
+
/* @__PURE__ */ u(o, { className: `w-4 h-4 text-text-secondary transition-transform ${_ ? "rotate-180" : ""}` })
|
|
50
51
|
]
|
|
51
|
-
}),
|
|
52
|
-
className: `absolute top-full mt-2 w-64 bg-bg-surface rounded-lg shadow-lg border border-border-subtle py-2 z-50 ${
|
|
53
|
-
children: [/* @__PURE__ */
|
|
52
|
+
}), _ && /* @__PURE__ */ d("div", {
|
|
53
|
+
className: `absolute top-full mt-2 w-64 bg-bg-surface rounded-lg shadow-lg border border-border-subtle py-2 z-50 ${m === "right" ? "right-0" : "left-0"}`,
|
|
54
|
+
children: [/* @__PURE__ */ d("div", {
|
|
54
55
|
className: "px-4 py-3 border-b border-border-subtle",
|
|
55
56
|
children: [
|
|
56
|
-
/* @__PURE__ */
|
|
57
|
+
/* @__PURE__ */ u("p", {
|
|
57
58
|
className: "text-sm font-medium text-foreground truncate",
|
|
58
|
-
children:
|
|
59
|
+
children: E
|
|
59
60
|
}),
|
|
60
|
-
/* @__PURE__ */
|
|
61
|
+
/* @__PURE__ */ u("p", {
|
|
61
62
|
className: "text-xs text-text-secondary truncate",
|
|
62
|
-
children:
|
|
63
|
+
children: x.email
|
|
63
64
|
}),
|
|
64
|
-
|
|
65
|
+
S && /* @__PURE__ */ d("p", {
|
|
65
66
|
className: "text-xs text-text-tertiary mt-1 truncate",
|
|
66
67
|
children: [
|
|
67
68
|
"Workspace: ",
|
|
68
|
-
|
|
69
|
+
S.substring(0, 8),
|
|
69
70
|
"..."
|
|
70
71
|
]
|
|
71
72
|
})
|
|
72
73
|
]
|
|
73
|
-
}), /* @__PURE__ */
|
|
74
|
+
}), /* @__PURE__ */ d("div", {
|
|
74
75
|
className: "py-1",
|
|
75
|
-
children: [
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
children: [
|
|
77
|
+
f && /* @__PURE__ */ d("button", {
|
|
78
|
+
onClick: w,
|
|
79
|
+
className: "w-full flex items-center gap-3 px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken transition-colors",
|
|
80
|
+
children: [/* @__PURE__ */ u(a, { className: "w-4 h-4" }), /* @__PURE__ */ u("span", { children: g("auth.profileMenu.switchWorkspace", "Switch Workspace") })]
|
|
81
|
+
}),
|
|
82
|
+
/* @__PURE__ */ d("button", {
|
|
83
|
+
onClick: () => {
|
|
84
|
+
v(!1), b(`/auth/login?mode=add-account&returnTo=${encodeURIComponent(window.location.pathname + window.location.search)}`);
|
|
85
|
+
},
|
|
86
|
+
className: "w-full flex items-center gap-3 px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken transition-colors",
|
|
87
|
+
children: [/* @__PURE__ */ u(c, { className: "w-4 h-4" }), /* @__PURE__ */ u("span", { children: g("auth.profileMenu.addAccount", "Add account") })]
|
|
88
|
+
}),
|
|
89
|
+
/* @__PURE__ */ d("button", {
|
|
90
|
+
onClick: C,
|
|
91
|
+
className: "w-full flex items-center gap-3 px-4 py-2 text-sm text-status-error-text hover:bg-status-error-bg-subtle transition-colors",
|
|
92
|
+
children: [/* @__PURE__ */ u(s, { className: "w-4 h-4" }), /* @__PURE__ */ u("span", { children: g("auth.profileMenu.logout", "Logout") })]
|
|
93
|
+
})
|
|
94
|
+
]
|
|
84
95
|
})]
|
|
85
96
|
})]
|
|
86
97
|
});
|
|
87
98
|
}
|
|
88
99
|
//#endregion
|
|
89
|
-
export {
|
|
100
|
+
export { f as UserProfileMenu };
|
|
90
101
|
|
|
91
102
|
//# sourceMappingURL=UserProfileMenu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserProfileMenu.js","names":[],"sources":["../../../../src/auth/components/profile/UserProfileMenu.tsx"],"sourcesContent":["import { useState, useRef, useEffect } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport { LogOut, ChevronDown, Building2 } from \"lucide-react\";\nimport { useAuthStore } from \"../../store/authStore\";\n\nexport interface UserProfileMenuProps {\n /**\n * Callback when workspace switcher should be shown\n */\n onSwitchWorkspace?: () => void;\n\n /**\n * Logout handler (REQUIRED)\n * Should clear auth state and redirect to login\n */\n onLogout: () => void;\n\n /**\n * Position of the dropdown menu\n * @default 'right'\n */\n position?: \"left\" | \"right\";\n}\n\n/**\n * User Profile Menu Component\n *\n * Displays user avatar/icon with dropdown menu containing:\n * - User information\n * - Switch Workspace option\n * - Logout button\n *\n * @example\n * ```tsx\n * import { UserProfileMenu } from '@burdenoff/microfe-auth';\n *\n * function AppHeader() {\n * return (\n * <div className=\"header\">\n * <UserProfileMenu\n * onSwitchWorkspace={() => setShowWorkspaceSwitcher(true)}\n * position=\"right\"\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function UserProfileMenu({\n onSwitchWorkspace,\n onLogout,\n position = \"right\",\n}: UserProfileMenuProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const [isOpen, setIsOpen] = useState(false);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const user = useAuthStore((state) => state.user);\n const currentWorkspaceId = useAuthStore((state) => state.currentWorkspaceId);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n }\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () =>\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }\n }, [isOpen]);\n\n const handleLogout = () => {\n setIsOpen(false);\n onLogout();\n };\n\n const handleSwitchWorkspace = () => {\n setIsOpen(false);\n onSwitchWorkspace?.();\n };\n\n if (!user) {\n return null;\n }\n\n // Get user initials for avatar\n const getInitials = () => {\n if (user.firstName && user.lastName) {\n return `${user.firstName[0]}${user.lastName[0]}`.toUpperCase();\n }\n if (user.name) {\n const parts = user.name.split(\" \");\n if (parts.length >= 2) {\n return `${parts[0][0]}${parts[1][0]}`.toUpperCase();\n }\n return user.name.substring(0, 2).toUpperCase();\n }\n if (user.username) {\n return user.username.substring(0, 2).toUpperCase();\n }\n return user.email.substring(0, 2).toUpperCase();\n };\n\n const displayName =\n user.name ||\n `${user.firstName || \"\"} ${user.lastName || \"\"}`.trim() ||\n user.username;\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {/* Profile Button */}\n <button\n onClick={() => setIsOpen(!isOpen)}\n className=\"flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-bg-sunken transition-colors\"\n aria-label=\"User menu\"\n aria-expanded={isOpen}\n >\n {/* Avatar */}\n <div className=\"w-8 h-8 rounded-full bg-accent-blue flex items-center justify-center text-white text-sm font-medium\">\n {getInitials()}\n </div>\n\n {/* User Name (optional, hide on small screens) */}\n <span className=\"hidden sm:block text-sm font-medium text-text-secondary\">\n {displayName}\n </span>\n\n {/* Chevron */}\n <ChevronDown\n className={`w-4 h-4 text-text-secondary transition-transform ${\n isOpen ? \"rotate-180\" : \"\"\n }`}\n />\n </button>\n\n {/* Dropdown Menu */}\n {isOpen && (\n <div\n className={`absolute top-full mt-2 w-64 bg-bg-surface rounded-lg shadow-lg border border-border-subtle py-2 z-50 ${\n position === \"right\" ? \"right-0\" : \"left-0\"\n }`}\n >\n {/* User Info Section */}\n <div className=\"px-4 py-3 border-b border-border-subtle\">\n <p className=\"text-sm font-medium text-foreground truncate\">\n {displayName}\n </p>\n <p className=\"text-xs text-text-secondary truncate\">{user.email}</p>\n {currentWorkspaceId && (\n <p className=\"text-xs text-text-tertiary mt-1 truncate\">\n Workspace: {currentWorkspaceId.substring(0, 8)}...\n </p>\n )}\n </div>\n\n {/* Menu Items */}\n <div className=\"py-1\">\n {/* Switch Workspace */}\n {onSwitchWorkspace && (\n <button\n onClick={handleSwitchWorkspace}\n className=\"w-full flex items-center gap-3 px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken transition-colors\"\n >\n <Building2 className=\"w-4 h-4\" />\n <span>\n {tr(\"auth.profileMenu.switchWorkspace\", \"Switch Workspace\")}\n </span>\n </button>\n )}\n\n {/* Logout */}\n <button\n onClick={handleLogout}\n className=\"w-full flex items-center gap-3 px-4 py-2 text-sm text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <LogOut className=\"w-4 h-4\" />\n <span>{tr(\"auth.profileMenu.logout\", \"Logout\")}</span>\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"UserProfileMenu.js","names":[],"sources":["../../../../src/auth/components/profile/UserProfileMenu.tsx"],"sourcesContent":["import { useState, useRef, useEffect } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport { LogOut, ChevronDown, Building2, UserPlus } from \"lucide-react\";\nimport { useNavigate } from \"react-router-dom\";\nimport { useAuthStore } from \"../../store/authStore\";\n\nexport interface UserProfileMenuProps {\n /**\n * Callback when workspace switcher should be shown\n */\n onSwitchWorkspace?: () => void;\n\n /**\n * Logout handler (REQUIRED)\n * Should clear auth state and redirect to login\n */\n onLogout: () => void;\n\n /**\n * Position of the dropdown menu\n * @default 'right'\n */\n position?: \"left\" | \"right\";\n}\n\n/**\n * User Profile Menu Component\n *\n * Displays user avatar/icon with dropdown menu containing:\n * - User information\n * - Switch Workspace option\n * - Logout button\n *\n * @example\n * ```tsx\n * import { UserProfileMenu } from '@burdenoff/microfe-auth';\n *\n * function AppHeader() {\n * return (\n * <div className=\"header\">\n * <UserProfileMenu\n * onSwitchWorkspace={() => setShowWorkspaceSwitcher(true)}\n * position=\"right\"\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function UserProfileMenu({\n onSwitchWorkspace,\n onLogout,\n position = \"right\",\n}: UserProfileMenuProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const [isOpen, setIsOpen] = useState(false);\n const menuRef = useRef<HTMLDivElement>(null);\n const navigate = useNavigate();\n\n const user = useAuthStore((state) => state.user);\n const currentWorkspaceId = useAuthStore((state) => state.currentWorkspaceId);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n }\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () =>\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }\n }, [isOpen]);\n\n const handleLogout = () => {\n setIsOpen(false);\n onLogout();\n };\n\n const handleSwitchWorkspace = () => {\n setIsOpen(false);\n onSwitchWorkspace?.();\n };\n\n if (!user) {\n return null;\n }\n\n // Get user initials for avatar\n const getInitials = () => {\n if (user.firstName && user.lastName) {\n return `${user.firstName[0]}${user.lastName[0]}`.toUpperCase();\n }\n if (user.name) {\n const parts = user.name.split(\" \");\n if (parts.length >= 2) {\n return `${parts[0][0]}${parts[1][0]}`.toUpperCase();\n }\n return user.name.substring(0, 2).toUpperCase();\n }\n if (user.username) {\n return user.username.substring(0, 2).toUpperCase();\n }\n return user.email.substring(0, 2).toUpperCase();\n };\n\n const displayName =\n user.name ||\n `${user.firstName || \"\"} ${user.lastName || \"\"}`.trim() ||\n user.username;\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {/* Profile Button */}\n <button\n onClick={() => setIsOpen(!isOpen)}\n className=\"flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-bg-sunken transition-colors\"\n aria-label=\"User menu\"\n aria-expanded={isOpen}\n >\n {/* Avatar */}\n <div className=\"w-8 h-8 rounded-full bg-accent-blue flex items-center justify-center text-white text-sm font-medium\">\n {getInitials()}\n </div>\n\n {/* User Name (optional, hide on small screens) */}\n <span className=\"hidden sm:block text-sm font-medium text-text-secondary\">\n {displayName}\n </span>\n\n {/* Chevron */}\n <ChevronDown\n className={`w-4 h-4 text-text-secondary transition-transform ${\n isOpen ? \"rotate-180\" : \"\"\n }`}\n />\n </button>\n\n {/* Dropdown Menu */}\n {isOpen && (\n <div\n className={`absolute top-full mt-2 w-64 bg-bg-surface rounded-lg shadow-lg border border-border-subtle py-2 z-50 ${\n position === \"right\" ? \"right-0\" : \"left-0\"\n }`}\n >\n {/* User Info Section */}\n <div className=\"px-4 py-3 border-b border-border-subtle\">\n <p className=\"text-sm font-medium text-foreground truncate\">\n {displayName}\n </p>\n <p className=\"text-xs text-text-secondary truncate\">{user.email}</p>\n {currentWorkspaceId && (\n <p className=\"text-xs text-text-tertiary mt-1 truncate\">\n Workspace: {currentWorkspaceId.substring(0, 8)}...\n </p>\n )}\n </div>\n\n {/* Menu Items */}\n <div className=\"py-1\">\n {/* Switch Workspace */}\n {onSwitchWorkspace && (\n <button\n onClick={handleSwitchWorkspace}\n className=\"w-full flex items-center gap-3 px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken transition-colors\"\n >\n <Building2 className=\"w-4 h-4\" />\n <span>\n {tr(\"auth.profileMenu.switchWorkspace\", \"Switch Workspace\")}\n </span>\n </button>\n )}\n\n {/* Add Account */}\n <button\n onClick={() => {\n setIsOpen(false);\n const returnTo = encodeURIComponent(\n window.location.pathname + window.location.search,\n );\n navigate(`/auth/login?mode=add-account&returnTo=${returnTo}`);\n }}\n className=\"w-full flex items-center gap-3 px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken transition-colors\"\n >\n <UserPlus className=\"w-4 h-4\" />\n <span>{tr(\"auth.profileMenu.addAccount\", \"Add account\")}</span>\n </button>\n\n {/* Logout */}\n <button\n onClick={handleLogout}\n className=\"w-full flex items-center gap-3 px-4 py-2 text-sm text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <LogOut className=\"w-4 h-4\" />\n <span>{tr(\"auth.profileMenu.logout\", \"Logout\")}</span>\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAuthOperations.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useAuthOperations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useAuthOperations.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useAuthOperations.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,IAAI,EACJ,WAAW,EACX,UAAU,EACX,MAAM,UAAU,CAAC;AA6IlB,UAAU,mBAAmB;IAC3B,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;CAC1B;AAED,UAAU,wBAAwB;IAChC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AA4BD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B;oBAyCzC,WAAW,KAAG,OAAO,CAAC,UAAU,CAAC;oBAkJjC,WAAW;;;;;;;;;;;;yBAsP/B,MAAM,KACZ,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;gCAyBxB,MAAM;iBA5dpC,OAAO;iBACP,MAAM;;;mBAyDY,WAAW,KAAG,OAAO,CAAC,UAAU,CAAC;sBAkJjC,WAAW;;;;;;;;;;;;;;;;;EAsTzC"}
|
|
@@ -2,14 +2,14 @@ import { useAuth as e } from "../providers/AuthProvider.js";
|
|
|
2
2
|
import { useAuthStore as t } from "../store/authStore.js";
|
|
3
3
|
import { CurrentUserDocument as n, RefreshTokenDocument as r, ResendVerificationEmailDocument as i, SignInDocument as a, SignOutDocument as o, SignUpDocument as s, VerifyEmailDocument as c } from "../../generated/global-operations.js";
|
|
4
4
|
import { useEffect as l, useRef as u } from "react";
|
|
5
|
-
import {
|
|
6
|
-
import { useApolloClient as
|
|
7
|
-
import { useEventBus as
|
|
5
|
+
import { getProfileTokens as d, getProfileUser as f, getProfiles as p, loginProfile as m } from "@burdenoff/fe-libs/shared/providers/shell/ProfileStorageManager";
|
|
6
|
+
import { useApolloClient as h, useMutation as g, useQuery as _ } from "@apollo/client/react";
|
|
7
|
+
import { useEventBus as v } from "@burdenoff/fe-libs/shared/events";
|
|
8
8
|
//#region src/auth/hooks/useAuthOperations.ts
|
|
9
|
-
function
|
|
9
|
+
function y(e, t) {
|
|
10
10
|
return e.includes("email or username already exists") || t === "BAD_USER_INPUT" ? "An account with this email or username already exists. Please sign in or use a different email." : t === "TENANT_CREATION_FAILED" ? "We couldn't finish setting up your account. Please try again in a few moments. If this persists, contact support." : e.includes("Failed to fetch") || e.includes("NetworkError") || e.includes("Load failed") ? "Unable to reach the server. Please check your internet connection and try again." : e.includes("CORS") || e.includes("cross-origin") ? "Unable to reach the server. Please try again or contact support." : t === "INTERNAL_SERVER_ERROR" ? "Something went wrong on our end. Please try again in a few moments." : e && e !== "Sign up failed" ? e : "Sign up failed. Please try again.";
|
|
11
11
|
}
|
|
12
|
-
function
|
|
12
|
+
function b(e) {
|
|
13
13
|
try {
|
|
14
14
|
let t = window.location.hostname.endsWith(".local.burdenoff.com") ? ".local.burdenoff.com" : void 0, n = t ? `; domain=${t}` : "", r = window.location.protocol === "https:" ? "; secure" : "", i = JSON.stringify({
|
|
15
15
|
id: e,
|
|
@@ -18,33 +18,33 @@ function _(e) {
|
|
|
18
18
|
document.cookie = `bf-sso=${encodeURIComponent(i)}${n}; path=/; samesite=lax${r}; max-age=86400`, document.cookie = `bf-sso-profile=${encodeURIComponent(i)}${n}; path=/; samesite=lax${r}; max-age=86400`;
|
|
19
19
|
} catch {}
|
|
20
20
|
}
|
|
21
|
-
function
|
|
21
|
+
function x(e) {
|
|
22
22
|
return { ...e };
|
|
23
23
|
}
|
|
24
|
-
function
|
|
24
|
+
function S(e) {
|
|
25
25
|
return typeof e == "object" && !!e;
|
|
26
26
|
}
|
|
27
|
-
function
|
|
28
|
-
return Array.isArray(e) ? e.filter((e) =>
|
|
27
|
+
function C(e) {
|
|
28
|
+
return Array.isArray(e) ? e.filter((e) => S(e)) : [];
|
|
29
29
|
}
|
|
30
|
-
function
|
|
31
|
-
if (!
|
|
32
|
-
let t =
|
|
33
|
-
return t.length > 0 ? t :
|
|
30
|
+
function w(e) {
|
|
31
|
+
if (!S(e)) return [];
|
|
32
|
+
let t = C(e.errors);
|
|
33
|
+
return t.length > 0 ? t : C(e.graphQLErrors);
|
|
34
34
|
}
|
|
35
|
-
function
|
|
36
|
-
if (e instanceof Error ||
|
|
35
|
+
function T(e) {
|
|
36
|
+
if (e instanceof Error || S(e) && typeof e.message == "string") return e.message;
|
|
37
37
|
}
|
|
38
|
-
function
|
|
38
|
+
function E(e) {
|
|
39
39
|
let t = e?.extensions?.code;
|
|
40
40
|
return typeof t == "string" ? t : null;
|
|
41
41
|
}
|
|
42
|
-
function
|
|
43
|
-
let
|
|
42
|
+
function D(S = {}) {
|
|
43
|
+
let C = t((e) => e.isLoading), D = t((e) => e.error), O = t((e) => e.errorCode), k = t((e) => e.isAuthenticated), A = t((e) => e.user), j = t((e) => e.accessToken), M = S.disableCurrentUserQuery ?? !1, N = u(!1), P = e(), F = v(), I = h(), [L] = g(a), [R] = g(s), [z] = g(o), [B] = g(r), [V] = g(c), [H] = g(i), U = async (e) => {
|
|
44
44
|
let n = t.getState();
|
|
45
45
|
try {
|
|
46
46
|
n.setLoading(!0), n.setError(null);
|
|
47
|
-
let t = await
|
|
47
|
+
let t = await L({
|
|
48
48
|
variables: { input: e },
|
|
49
49
|
errorPolicy: "none"
|
|
50
50
|
});
|
|
@@ -63,19 +63,19 @@ function w(y = {}) {
|
|
|
63
63
|
metadata: { mfaMethod: r.mfaMethod }
|
|
64
64
|
};
|
|
65
65
|
if (r.user && r.accessToken && r.refreshToken) {
|
|
66
|
-
|
|
66
|
+
N.current = !0, n.setUser(r.user), n.setAuthTokens(r.accessToken, r.refreshToken), n.setAuthenticated(!0), n.setMfaRequired(!1);
|
|
67
67
|
let e = r.expiresIn ? Date.now() + r.expiresIn * 1e3 : void 0;
|
|
68
|
-
return
|
|
68
|
+
return m(x(r.user), {
|
|
69
69
|
accessToken: r.accessToken,
|
|
70
70
|
refreshToken: r.refreshToken,
|
|
71
71
|
expiresAt: e
|
|
72
|
-
}),
|
|
72
|
+
}), b(r.user.id), F.emit("auth.signed_in", {
|
|
73
73
|
userId: r.user.id,
|
|
74
74
|
tenantId: r.user.tenantId,
|
|
75
75
|
workspaceId: r.user.defaultWorkspaceId,
|
|
76
76
|
mfaEnabled: r.user.mfaEnabled,
|
|
77
77
|
emailVerified: r.user.emailVerified
|
|
78
|
-
}, { component: "useAuthOperations" }),
|
|
78
|
+
}, { component: "useAuthOperations" }), P.onAuthSuccess?.(r.user, r.accessToken, r.refreshToken), {
|
|
79
79
|
success: !0,
|
|
80
80
|
user: r.user,
|
|
81
81
|
token: r.accessToken,
|
|
@@ -91,11 +91,11 @@ function w(y = {}) {
|
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
93
|
} catch (e) {
|
|
94
|
-
let t = "Sign in failed", r = null, i =
|
|
94
|
+
let t = "Sign in failed", r = null, i = w(e);
|
|
95
95
|
if (i.length > 0) {
|
|
96
96
|
let e = i[0];
|
|
97
|
-
t = e.message || t, r =
|
|
98
|
-
} else t =
|
|
97
|
+
t = e.message || t, r = E(e);
|
|
98
|
+
} else t = T(e) ?? t;
|
|
99
99
|
return console.error("[SignIn] Error:", t, r ? `(${r})` : ""), n.setError(t, r), {
|
|
100
100
|
success: !1,
|
|
101
101
|
error: t
|
|
@@ -103,11 +103,11 @@ function w(y = {}) {
|
|
|
103
103
|
} finally {
|
|
104
104
|
n.setLoading(!1);
|
|
105
105
|
}
|
|
106
|
-
},
|
|
106
|
+
}, W = async (e) => {
|
|
107
107
|
let n = t.getState();
|
|
108
108
|
try {
|
|
109
109
|
n.setLoading(!0), n.setError(null);
|
|
110
|
-
let t = await
|
|
110
|
+
let t = await R({ variables: { input: e } }), r = w(t);
|
|
111
111
|
if (r.length > 0) {
|
|
112
112
|
let e = r[0].message ?? "Sign up failed";
|
|
113
113
|
throw console.error("[SignUp] GraphQL error:", e), n.setError(e), Error(e);
|
|
@@ -121,47 +121,55 @@ function w(y = {}) {
|
|
|
121
121
|
return !i.accessToken || !i.refreshToken || i.accessToken === "" || i.refreshToken === "" ? (n.setUser(i.user), n.setAuthenticated(!1), {
|
|
122
122
|
...i,
|
|
123
123
|
requiresEmailVerification: !0
|
|
124
|
-
}) : (n.setUser(i.user), n.setAuthTokens(i.accessToken, i.refreshToken), n.setAuthenticated(!0),
|
|
124
|
+
}) : (n.setUser(i.user), n.setAuthTokens(i.accessToken, i.refreshToken), n.setAuthenticated(!0), F.emit("auth.signed_up", {
|
|
125
125
|
userId: i.user.id,
|
|
126
126
|
tenantId: i.user.tenantId,
|
|
127
127
|
workspaceId: i.user.defaultWorkspaceId,
|
|
128
128
|
mfaEnabled: i.user.mfaEnabled,
|
|
129
129
|
emailVerified: i.user.emailVerified
|
|
130
|
-
}, { component: "useAuthOperations" }),
|
|
130
|
+
}, { component: "useAuthOperations" }), P.onAuthSuccess?.(i.user, i.accessToken, i.refreshToken), i);
|
|
131
131
|
} catch (e) {
|
|
132
|
-
let t = "Sign up failed. Please try again.", r, i =
|
|
132
|
+
let t = "Sign up failed. Please try again.", r, i = w(e);
|
|
133
133
|
if (i.length > 0) {
|
|
134
134
|
let e = i[0];
|
|
135
|
-
r =
|
|
135
|
+
r = E(e) ?? void 0, t = y(e.message ?? "", r);
|
|
136
136
|
} else {
|
|
137
|
-
let n =
|
|
138
|
-
n && (t =
|
|
137
|
+
let n = T(e);
|
|
138
|
+
n && (t = y(n));
|
|
139
139
|
}
|
|
140
140
|
throw n.setError(t, r ?? null), Error(t);
|
|
141
141
|
} finally {
|
|
142
142
|
n.setLoading(!1);
|
|
143
143
|
}
|
|
144
|
-
},
|
|
144
|
+
}, G = async () => {
|
|
145
145
|
let e = t.getState(), n = e.user;
|
|
146
146
|
try {
|
|
147
|
-
await
|
|
147
|
+
await z();
|
|
148
148
|
} catch (e) {
|
|
149
149
|
console.error("Sign out failed:", e);
|
|
150
|
-
} finally {
|
|
151
|
-
await N.clearStore(), e.clearAuth(), M.emit("auth.signed_out", {
|
|
152
|
-
userId: n?.id,
|
|
153
|
-
tenantId: n?.tenantId,
|
|
154
|
-
workspaceId: n?.defaultWorkspaceId
|
|
155
|
-
}, { component: "useAuthOperations" }), j.onLogout?.();
|
|
156
150
|
}
|
|
157
|
-
|
|
151
|
+
await I.clearStore(), e.clearAuth(), F.emit("auth.signed_out", {
|
|
152
|
+
userId: n?.id,
|
|
153
|
+
tenantId: n?.tenantId,
|
|
154
|
+
workspaceId: n?.defaultWorkspaceId
|
|
155
|
+
}, { component: "useAuthOperations" });
|
|
156
|
+
let r = p().filter((e) => e.id !== n?.id);
|
|
157
|
+
if (r.length > 0) {
|
|
158
|
+
let t = r[0], n = d(t.id), i = f(t.id);
|
|
159
|
+
if (n?.accessToken && i) {
|
|
160
|
+
e.loadFromProfile(t.id);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
P.onLogout?.();
|
|
165
|
+
}, K = async () => {
|
|
158
166
|
let e = t.getState();
|
|
159
167
|
try {
|
|
160
168
|
let t = e.refreshToken;
|
|
161
169
|
if (!t) throw Error("No refresh token available");
|
|
162
|
-
let { data: n } = await
|
|
170
|
+
let { data: n } = await B({ variables: { token: t } }), r = n.refreshToken;
|
|
163
171
|
if (!r.accessToken || !r.refreshToken || !r.user) throw Error("Token refresh failed: Invalid response from server");
|
|
164
|
-
return e.setAuthTokens(r.accessToken, r.refreshToken), e.setUser(r.user),
|
|
172
|
+
return e.setAuthTokens(r.accessToken, r.refreshToken), e.setUser(r.user), F.emit("auth.token_refreshed", {
|
|
165
173
|
userId: r.user.id,
|
|
166
174
|
tenantId: r.user.tenantId,
|
|
167
175
|
workspaceId: r.user.defaultWorkspaceId,
|
|
@@ -169,36 +177,36 @@ function w(y = {}) {
|
|
|
169
177
|
emailVerified: r.user.emailVerified
|
|
170
178
|
}, { component: "useAuthOperations" }), r;
|
|
171
179
|
} catch (t) {
|
|
172
|
-
throw
|
|
180
|
+
throw F.emit("auth.token_refresh_failed", {
|
|
173
181
|
userId: e.user?.id,
|
|
174
182
|
tenantId: e.user?.tenantId,
|
|
175
183
|
workspaceId: e.user?.defaultWorkspaceId,
|
|
176
184
|
reason: t instanceof Error ? t.message : "Token refresh failed"
|
|
177
185
|
}, { component: "useAuthOperations" }), e.clearAuth(), t;
|
|
178
186
|
}
|
|
179
|
-
}, { data:
|
|
180
|
-
skip:
|
|
187
|
+
}, { data: q, refetch: J } = _(n, {
|
|
188
|
+
skip: M || !k || N.current,
|
|
181
189
|
fetchPolicy: "network-only"
|
|
182
190
|
});
|
|
183
191
|
return l(() => {
|
|
184
|
-
|
|
185
|
-
}, [
|
|
186
|
-
if (
|
|
192
|
+
q?.currentUser && t.getState().setUser(q.currentUser);
|
|
193
|
+
}, [q]), l(() => {
|
|
194
|
+
if (N.current && k) {
|
|
187
195
|
let e = setTimeout(() => {
|
|
188
|
-
|
|
196
|
+
N.current = !1;
|
|
189
197
|
}, 2e3);
|
|
190
198
|
return () => clearTimeout(e);
|
|
191
199
|
}
|
|
192
|
-
}, [
|
|
193
|
-
signIn:
|
|
194
|
-
signUp:
|
|
195
|
-
signOut:
|
|
196
|
-
refreshToken:
|
|
200
|
+
}, [k]), {
|
|
201
|
+
signIn: U,
|
|
202
|
+
signUp: W,
|
|
203
|
+
signOut: G,
|
|
204
|
+
refreshToken: K,
|
|
197
205
|
verifyEmail: async (e) => {
|
|
198
206
|
let n = t.getState();
|
|
199
207
|
try {
|
|
200
208
|
n.setLoading(!0);
|
|
201
|
-
let { data: t } = await
|
|
209
|
+
let { data: t } = await V({ variables: { token: e } });
|
|
202
210
|
return t.verifyEmail.success && n.user && n.setUser({
|
|
203
211
|
...n.user,
|
|
204
212
|
emailVerified: !0
|
|
@@ -212,25 +220,25 @@ function w(y = {}) {
|
|
|
212
220
|
},
|
|
213
221
|
resendVerification: async (e) => {
|
|
214
222
|
try {
|
|
215
|
-
let { data: t } = await
|
|
223
|
+
let { data: t } = await H({ variables: { email: e } });
|
|
216
224
|
return t.resendVerificationEmail;
|
|
217
225
|
} catch (e) {
|
|
218
226
|
throw console.error("Failed to resend verification email:", e), e;
|
|
219
227
|
}
|
|
220
228
|
},
|
|
221
|
-
refetchCurrentUser:
|
|
222
|
-
login:
|
|
223
|
-
register:
|
|
224
|
-
logout:
|
|
225
|
-
isLoading:
|
|
226
|
-
error:
|
|
227
|
-
errorCode:
|
|
228
|
-
isAuthenticated:
|
|
229
|
-
user:
|
|
230
|
-
accessToken:
|
|
229
|
+
refetchCurrentUser: J,
|
|
230
|
+
login: U,
|
|
231
|
+
register: W,
|
|
232
|
+
logout: G,
|
|
233
|
+
isLoading: C,
|
|
234
|
+
error: D,
|
|
235
|
+
errorCode: O,
|
|
236
|
+
isAuthenticated: k,
|
|
237
|
+
user: A,
|
|
238
|
+
accessToken: j
|
|
231
239
|
};
|
|
232
240
|
}
|
|
233
241
|
//#endregion
|
|
234
|
-
export {
|
|
242
|
+
export { D as useAuthOperations };
|
|
235
243
|
|
|
236
244
|
//# sourceMappingURL=useAuthOperations.js.map
|