@explita/cloud-auth-client 0.0.1 → 0.1.0

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.
Files changed (48) hide show
  1. package/README.md +25 -2
  2. package/dist/components/change-password.js +13 -11
  3. package/dist/components/icons/lock.d.ts +4 -0
  4. package/dist/components/icons/lock.js +15 -0
  5. package/dist/components/icons/logout.d.ts +4 -0
  6. package/dist/components/icons/logout.js +11 -0
  7. package/dist/components/icons/setting.d.ts +4 -0
  8. package/dist/components/icons/setting.js +12 -0
  9. package/dist/components/login-form.js +3 -4
  10. package/dist/components/optional-otp.js +2 -2
  11. package/dist/components/reset-password.js +15 -16
  12. package/dist/components/settings.js +4 -1
  13. package/dist/components/signup-form.d.ts +3 -3
  14. package/dist/components/signup-form.js +20 -21
  15. package/dist/components/toggle-2fa.js +3 -3
  16. package/dist/components/toggle-account-status.js +18 -11
  17. package/dist/components/ui/dialog.js +1 -1
  18. package/dist/components/user-card.js +22 -9
  19. package/dist/contexts/auth-provider.js +23 -18
  20. package/dist/hooks/use-token-refresher.js +11 -11
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +3 -1
  23. package/dist/lib/api-client.js +39 -24
  24. package/dist/lib/api-server.js +5 -4
  25. package/dist/lib/constants.d.ts +10 -0
  26. package/dist/lib/constants.js +13 -0
  27. package/dist/lib/error.js +1 -1
  28. package/dist/lib/refresh-helper.d.ts +0 -6
  29. package/dist/lib/refresh-helper.js +12 -22
  30. package/dist/lib/utils.d.ts +3 -1
  31. package/dist/lib/utils.js +19 -14
  32. package/dist/server/index.d.ts +3 -2
  33. package/dist/server/index.js +5 -2
  34. package/dist/server/{cookie.js → next-cookie-override.js} +3 -3
  35. package/dist/server/reset-password.js +7 -0
  36. package/dist/server/role.d.ts +2 -4
  37. package/dist/server/role.js +13 -1
  38. package/dist/server/server-session.js +5 -0
  39. package/dist/server/server-token.js +5 -5
  40. package/dist/server/toggle-2fa.js +4 -0
  41. package/dist/server/{users-accounts.d.ts → user.d.ts} +3 -5
  42. package/dist/server/{users-accounts.js → user.js} +16 -4
  43. package/dist/styles.css +7 -1
  44. package/dist/types.d.ts +21 -87
  45. package/package.json +9 -9
  46. /package/dist/components/{x-icon.d.ts → icons/x-icon.d.ts} +0 -0
  47. /package/dist/components/{x-icon.js → icons/x-icon.js} +0 -0
  48. /package/dist/server/{cookie.d.ts → next-cookie-override.d.ts} +0 -0
package/README.md CHANGED
@@ -78,7 +78,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
78
78
  loginPath: "/login", //default is /login
79
79
  signupPath: "/signup", //default is /signup
80
80
  resetPasswordPath: "/reset-password", //default is /reset-password
81
- cookieOverride: cookieOverrideHandler, //included in the server-side functions and only needed if your app runs on localhost subdomain eg: http://console.localhost:3000
81
+ cookieOverride: cookieOverrideHandler, //included in the server-side functions and only needed if your app needs to use anything from @explita/cloud-auth-client/server, e.g: getServerSession() - only in Next.js
82
82
  disableLoading: true, //default is false
83
83
  excludedPaths: [], //array of strings of relative paths, all the paths mentioned above are already excluded.
84
84
  }}
@@ -165,7 +165,7 @@ LoggedOut; //check if user is logged out
165
165
  ```typescript
166
166
  "use server";
167
167
 
168
- import {
168
+ import type {
169
169
  NewRole,
170
170
  ResetPasswordWithToken,
171
171
  ResetPasswordWithUserId,
@@ -227,6 +227,29 @@ export async function assignPermissions(roleId: string, permissions: string[]) {
227
227
 
228
228
  ---
229
229
 
230
+ ### Using Node/Express Backend
231
+
232
+ If you're using a Node.js/Express backend and need to authenticate requests between your frontend and backend, use [cloud-auth-express](https://www.npmjs.com/package/@explita/cloud-auth-express) to verify tokens server-side.
233
+
234
+ Make sure your frontend sends the token along in each request:
235
+
236
+ ```typescript
237
+ import { getToken } from "@explita/cloud-auth-client";
238
+
239
+ const response = await fetch("/api/your-route", {
240
+ method: "POST",
241
+ headers: {
242
+ Authorization: `Bearer ${getToken()}`,
243
+ },
244
+ body: JSON.stringify(data),
245
+ });
246
+ ```
247
+
248
+ > ⚠️ **Note:** This section only applies if you're doing separate frontend/backend communication.
249
+ > If you're building a fullstack app (e.g. with Next.js using Server Actions or API routes), you don't need to handle this manually — it's already managed internally by cloud-auth-client.
250
+
251
+ ---
252
+
230
253
  ### Getting started
231
254
 
232
255
  Sign up for an account at [Explita Cloud](https://cloud.explita.ng), create a project, add auth service and get your API key from the dashboard and add it to your environment variables.
@@ -44,7 +44,6 @@ const message_1 = require("./message");
44
44
  const must_login_1 = require("./must-login");
45
45
  const utils_1 = require("../lib/utils");
46
46
  function ChangePassword({ user, open, onOpenChange, onSubmit, onSuccess, }) {
47
- var _a, _b;
48
47
  const { user: loggedInUser } = (0, auth_provider_1.useAuth)();
49
48
  const [state, handleSubmit, isPending] = (0, react_1.useActionState)(async function (prevState, formData) {
50
49
  if (!onSubmit || typeof onSubmit !== "function") {
@@ -55,11 +54,11 @@ function ChangePassword({ user, open, onOpenChange, onSubmit, onSuccess, }) {
55
54
  }
56
55
  try {
57
56
  const result = await onSubmit({
58
- userId: (user === null || user === void 0 ? void 0 : user.id) || loggedInUser.id,
57
+ userId: user?.id || loggedInUser.id,
59
58
  password: formData.get("password"),
60
59
  confirmPassword: formData.get("confirmPassword"),
61
60
  });
62
- onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess();
61
+ onSuccess?.();
63
62
  return result;
64
63
  }
65
64
  catch (error) {
@@ -70,7 +69,10 @@ function ChangePassword({ user, open, onOpenChange, onSubmit, onSuccess, }) {
70
69
  onOpenChange(state);
71
70
  (0, utils_1.unstuckPointerEvents)();
72
71
  } },
73
- react_1.default.createElement(dialog_1.DialogContent, null, !loggedInUser ? (react_1.default.createElement(must_login_1.MustLogin, { onOpenChange: onOpenChange })) : (react_1.default.createElement("form", { action: handleSubmit },
72
+ react_1.default.createElement(dialog_1.DialogContent, null, !loggedInUser ? (react_1.default.createElement(must_login_1.MustLogin, { onOpenChange: (state) => {
73
+ onOpenChange(state);
74
+ (0, utils_1.unstuckPointerEvents)();
75
+ } })) : (react_1.default.createElement("form", { action: handleSubmit },
74
76
  react_1.default.createElement(dialog_1.DialogHeader, null,
75
77
  !user || loggedInUser.id === user.id ? (react_1.default.createElement(dialog_1.DialogTitle, null, "Change your password")) : (react_1.default.createElement(dialog_1.DialogTitle, null,
76
78
  "Change password for ",
@@ -78,22 +80,22 @@ function ChangePassword({ user, open, onOpenChange, onSubmit, onSuccess, }) {
78
80
  " ",
79
81
  user.lastName)),
80
82
  react_1.default.createElement(dialog_1.DialogDescription, null, "Please enter the new password"),
81
- user && loggedInUser.id !== (user === null || user === void 0 ? void 0 : user.id) && (react_1.default.createElement(dialog_1.DialogDescription, { className: "ecpauth:mt-2 ecpauth:text-base" },
83
+ user && loggedInUser.id !== user?.id && (react_1.default.createElement(dialog_1.DialogDescription, { className: "ecpauth:mt-2 ecpauth:text-base" },
82
84
  "Username: ",
83
- (user === null || user === void 0 ? void 0 : user.username) || (user === null || user === void 0 ? void 0 : user.email)))),
84
- (state === null || state === void 0 ? void 0 : state.status) === "success" ? (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:mt-2 ecpauth:font-semibold ecpauth:text-base", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:mt-2" })),
85
+ user?.username || user?.email))),
86
+ state?.status === "success" ? (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:mt-2 ecpauth:font-semibold ecpauth:text-base", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:mt-2" })),
85
87
  react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:flex-col ecpauth:gap-6 ecpauth:my-5" },
86
88
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
87
89
  react_1.default.createElement(label_1.Label, { htmlFor: "password" }, "New Password"),
88
90
  react_1.default.createElement(input_1.Input, { id: "password", type: "password", name: "password" }),
89
- react_1.default.createElement(message_1.Message, { message: (state === null || state === void 0 ? void 0 : state.status) === "validation-error"
90
- ? (_a = state === null || state === void 0 ? void 0 : state.errors) === null || _a === void 0 ? void 0 : _a.password
91
+ react_1.default.createElement(message_1.Message, { message: state?.status === "validation-error"
92
+ ? state?.errors?.password
91
93
  : "" })),
92
94
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
93
95
  react_1.default.createElement(label_1.Label, { htmlFor: "confirmPassword" }, "Confirm New Password"),
94
96
  react_1.default.createElement(input_1.Input, { id: "confirmPassword", type: "password", name: "confirmPassword" }),
95
- react_1.default.createElement(message_1.Message, { message: (state === null || state === void 0 ? void 0 : state.status) === "validation-error"
96
- ? (_b = state === null || state === void 0 ? void 0 : state.errors) === null || _b === void 0 ? void 0 : _b.confirmPassword
97
+ react_1.default.createElement(message_1.Message, { message: state?.status === "validation-error"
98
+ ? state?.errors?.confirmPassword
97
99
  : "" }))),
98
100
  react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:justify-end ecpauth:gap-2" },
99
101
  react_1.default.createElement(button_1.Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false) }, "Cancel"),
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ export declare function LockIcon({ size }: {
3
+ size?: number;
4
+ }): React.JSX.Element;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LockIcon = LockIcon;
7
+ const react_1 = __importDefault(require("react"));
8
+ function LockIcon({ size = 24 }) {
9
+ return (react_1.default.createElement("svg", { stroke: "currentColor", fill: "none", strokeWidth: "2", viewBox: "0 0 24 24", strokeLinecap: "round", strokeLinejoin: "round", height: `${size}px`, width: `${size}px`, xmlns: "http://www.w3.org/2000/svg" },
10
+ react_1.default.createElement("path", { d: "M15 21h-8a2 2 0 0 1 -2 -2v-6a2 2 0 0 1 2 -2h10c.265 0 .518 .052 .75 .145" }),
11
+ react_1.default.createElement("path", { d: "M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0" }),
12
+ react_1.default.createElement("path", { d: "M8 11v-4a4 4 0 1 1 8 0v4" }),
13
+ react_1.default.createElement("path", { d: "M19 22v.01" }),
14
+ react_1.default.createElement("path", { d: "M19 19a2.003 2.003 0 0 0 .914 -3.782a1.98 1.98 0 0 0 -2.414 .483" })));
15
+ }
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ export declare function LogoutIcon({ size }: {
3
+ size?: number;
4
+ }): React.JSX.Element;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LogoutIcon = LogoutIcon;
7
+ const react_1 = __importDefault(require("react"));
8
+ function LogoutIcon({ size = 24 }) {
9
+ return (react_1.default.createElement("svg", { stroke: "currentColor", fill: "currentColor", strokeWidth: "0", viewBox: "0 0 20 20", "aria-hidden": "true", height: `${size}px`, width: `${size}px`, xmlns: "http://www.w3.org/2000/svg" },
10
+ react_1.default.createElement("path", { fillRule: "evenodd", d: "M3 3a1 1 0 00-1 1v12a1 1 0 102 0V4a1 1 0 00-1-1zm10.293 9.293a1 1 0 001.414 1.414l3-3a1 1 0 000-1.414l-3-3a1 1 0 10-1.414 1.414L14.586 9H7a1 1 0 100 2h7.586l-1.293 1.293z", clipRule: "evenodd" })));
11
+ }
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ export declare function SettingIcon({ size }: {
3
+ size?: number;
4
+ }): React.JSX.Element;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SettingIcon = SettingIcon;
7
+ const react_1 = __importDefault(require("react"));
8
+ function SettingIcon({ size = 24 }) {
9
+ return (react_1.default.createElement("svg", { stroke: "currentColor", fill: "currentColor", strokeWidth: "0", viewBox: "0 0 24 24", height: `${size}px`, width: `${size}px`, xmlns: "http://www.w3.org/2000/svg" },
10
+ react_1.default.createElement("path", { fill: "none", d: "M0 0h24v24H0z" }),
11
+ react_1.default.createElement("path", { d: "M17.41 6.59 15 5.5l2.41-1.09L18.5 2l1.09 2.41L22 5.5l-2.41 1.09L18.5 9l-1.09-2.41zm3.87 6.13L20.5 11l-.78 1.72-1.72.78 1.72.78.78 1.72.78-1.72L23 13.5l-1.72-.78zm-5.04 1.65 1.94 1.47-2.5 4.33-2.24-.94c-.2.13-.42.26-.64.37l-.3 2.4h-5l-.3-2.41c-.22-.11-.43-.23-.64-.37l-2.24.94-2.5-4.33 1.94-1.47c-.01-.11-.01-.24-.01-.36s0-.25.01-.37l-1.94-1.47 2.5-4.33 2.24.94c.2-.13.42-.26.64-.37L7.5 6h5l.3 2.41c.22.11.43.23.64.37l2.24-.94 2.5 4.33-1.94 1.47c.01.12.01.24.01.37s0 .24-.01.36zM13 14c0-1.66-1.34-3-3-3s-3 1.34-3 3 1.34 3 3 3 3-1.34 3-3z" })));
12
+ }
@@ -45,7 +45,6 @@ const auth_provider_1 = require("../contexts/auth-provider");
45
45
  const loader_1 = require("./loader");
46
46
  const message_1 = require("./message");
47
47
  function Login({ className, ...props }) {
48
- var _a, _b;
49
48
  const { login, error, computedRouteContext, isAuthenticated } = (0, auth_provider_1.useAuth)();
50
49
  const [authToken, setAuthToken] = react_1.default.useState(null);
51
50
  const { resetPasswordUrl, signupUrl, loginUrl } = computedRouteContext;
@@ -86,14 +85,14 @@ function Login({ className, ...props }) {
86
85
  react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:flex-col ecpauth:gap-6" },
87
86
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
88
87
  react_1.default.createElement(label_1.Label, { htmlFor: "email" }, "Email/Username"),
89
- react_1.default.createElement(input_1.Input, { id: "email", type: "text", placeholder: "email@example.com", name: "email", defaultValue: state === null || state === void 0 ? void 0 : state.email }),
90
- react_1.default.createElement(message_1.Message, { message: (_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.email })),
88
+ react_1.default.createElement(input_1.Input, { id: "email", type: "text", placeholder: "email@example.com", name: "email", defaultValue: state?.email }),
89
+ react_1.default.createElement(message_1.Message, { message: error?.errors?.email })),
91
90
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
92
91
  react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:items-center" },
93
92
  react_1.default.createElement(label_1.Label, { htmlFor: "password" }, "Password"),
94
93
  resetPasswordUrl && (react_1.default.createElement("a", { href: resetPasswordUrl, className: "ecpauth:ml-auto ecpauth:inline-block ecpauth:text-sm ecpauth:underline-offset-4 ecpauth:hover:underline" }, "Forgot your password?"))),
95
94
  react_1.default.createElement(input_1.Input, { id: "password", type: "password", name: "password" }),
96
- react_1.default.createElement(message_1.Message, { message: (_b = error === null || error === void 0 ? void 0 : error.errors) === null || _b === void 0 ? void 0 : _b.password })),
95
+ react_1.default.createElement(message_1.Message, { message: error?.errors?.password })),
97
96
  react_1.default.createElement(button_1.Button, { type: "submit", className: "ecpauth:w-full ecpauth:cursor-pointer", disabled: isPending }, isPending ? "Logging in..." : "Login")),
98
97
  signupUrl && (react_1.default.createElement("div", { className: "ecpauth:mt-4 ecpauth:text-center ecpauth:text-sm" },
99
98
  "Don't have an account?",
@@ -55,10 +55,10 @@ function OptionalOTPInner({ user, onVerified, onCanceled }) {
55
55
  return null; // or a fallback UI
56
56
  }
57
57
  const otp = useOTP({
58
- referenceId: user === null || user === void 0 ? void 0 : user.id,
58
+ referenceId: user?.id,
59
59
  onVerified,
60
60
  onCanceled,
61
- sentTo: user === null || user === void 0 ? void 0 : user.email,
61
+ sentTo: user?.email,
62
62
  channel: "email",
63
63
  });
64
64
  (0, react_1.useEffect)(() => {
@@ -44,7 +44,6 @@ const label_1 = require("./ui/label");
44
44
  const message_1 = require("./message");
45
45
  const auth_provider_1 = require("../contexts/auth-provider");
46
46
  function ResetPassword({ className, onChangePassword, ...props }) {
47
- var _a;
48
47
  const { sendPasswordResetRequest, computedRouteContext } = (0, auth_provider_1.useAuth)();
49
48
  const [token, setToken] = (0, react_1.useState)(null);
50
49
  const { loginUrl } = computedRouteContext;
@@ -75,33 +74,33 @@ function ResetPassword({ className, onChangePassword, ...props }) {
75
74
  console.log(error);
76
75
  }
77
76
  }, undefined);
78
- (0, react_1.useEffect)(() => {
79
- let timer;
80
- if ((state === null || state === void 0 ? void 0 : state.status) === "success") {
81
- if (loginUrl) {
82
- timer = setTimeout(() => {
83
- window.location.href = loginUrl;
84
- }, 2000);
85
- }
86
- }
87
- return () => {
88
- clearTimeout(timer);
89
- };
90
- }, [state === null || state === void 0 ? void 0 : state.status]);
77
+ // useEffect(() => {
78
+ // let timer: NodeJS.Timeout;
79
+ // if (state?.status === "success") {
80
+ // if (loginUrl) {
81
+ // timer = setTimeout(() => {
82
+ // window.location.href = loginUrl;
83
+ // }, 2000);
84
+ // }
85
+ // }
86
+ // return () => {
87
+ // clearTimeout(timer);
88
+ // };
89
+ // }, [state?.status]);
91
90
  return (react_1.default.createElement("div", { className: (0, utils_1.cn)("ecpauth:flex ecpauth:flex-col ecpauth:gap-6 ecpauth:w-full ecpauth:max-w-sm", className), ...props },
92
91
  react_1.default.createElement(card_1.Card, null,
93
92
  react_1.default.createElement(card_1.CardHeader, null,
94
93
  react_1.default.createElement(card_1.CardTitle, { className: "ecpauth:text-2xl" }, "Reset Password"),
95
94
  react_1.default.createElement(card_1.CardDescription, null, "Provide your details to reset your password.")),
96
95
  react_1.default.createElement(card_1.CardContent, null,
97
- (state === null || state === void 0 ? void 0 : state.status) === "success" ? (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:mb-4 ecpauth:font-semibold ecpauth:text-base", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:mb-4" })),
96
+ state?.status === "success" ? (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:mb-4 ecpauth:font-semibold ecpauth:text-base", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:mb-4" })),
98
97
  !token ? (react_1.default.createElement("form", { action: handleSubmit },
99
98
  react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:flex-col ecpauth:gap-6" },
100
99
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
101
100
  react_1.default.createElement(label_1.Label, { htmlFor: "email" }, "Email"),
102
101
  react_1.default.createElement(input_1.Input, { id: "email", type: "email", placeholder: "email@example.com", name: "email", defaultValue:
103
102
  //@ts-ignore
104
- (_a = state === null || state === void 0 ? void 0 : state.form) === null || _a === void 0 ? void 0 : _a.email })),
103
+ state?.form?.email })),
105
104
  react_1.default.createElement(button_1.Button, { type: "submit", className: "ecpauth:w-full ecpauth:cursor-pointer", disabled: isPending }, "Send Reset Password Link")))) : (react_1.default.createElement("form", { action: handleSubmit },
106
105
  react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:flex-col ecpauth:gap-6" },
107
106
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
@@ -16,7 +16,10 @@ function Settings({ open, onOpenChange, onToggle2FA }) {
16
16
  onOpenChange(state);
17
17
  (0, utils_1.unstuckPointerEvents)();
18
18
  } },
19
- react_1.default.createElement(dialog_1.DialogContent, null, !user ? (react_1.default.createElement(must_login_1.MustLogin, { onOpenChange: onOpenChange })) : (react_1.default.createElement("div", { className: "ecpauth:relative" },
19
+ react_1.default.createElement(dialog_1.DialogContent, null, !user ? (react_1.default.createElement(must_login_1.MustLogin, { onOpenChange: (state) => {
20
+ onOpenChange(state);
21
+ (0, utils_1.unstuckPointerEvents)();
22
+ } })) : (react_1.default.createElement("div", { className: "ecpauth:relative" },
20
23
  react_1.default.createElement(dialog_1.DialogHeader, { className: "ecpauth:border-b ecpauth:border-gray-200 ecpauth:dark:border-gray-800 ecpauth:pb-2" },
21
24
  react_1.default.createElement(dialog_1.DialogTitle, { className: "ecpauth:flex ecpauth:items-center ecpauth:justify-between" },
22
25
  react_1.default.createElement("span", { className: "ecpauth:text-stone-800 ecpauth:dark:text-stone-50" }, "Account Settings")),
@@ -1,9 +1,9 @@
1
1
  import React from "react";
2
- import { Signup, FormResponse, User } from "../types";
2
+ import { CreateUser, FormResponse, User } from "../types";
3
3
  type Props = {
4
4
  className?: string;
5
- onSubmit: (data: Signup) => Promise<FormResponse<User>>;
6
- groupId?: string;
5
+ onSubmit: (data: CreateUser) => Promise<FormResponse<User>>;
6
+ groupId?: string | null;
7
7
  metaData?: Record<string, string>;
8
8
  acceptUsername?: boolean;
9
9
  };
@@ -44,7 +44,6 @@ const label_1 = require("./ui/label");
44
44
  const message_1 = require("./message");
45
45
  const auth_provider_1 = require("../contexts/auth-provider");
46
46
  function Signup({ className, onSubmit, groupId, metaData, acceptUsername = true, ...props }) {
47
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
48
47
  const { computedRouteContext } = (0, auth_provider_1.useAuth)();
49
48
  const { loginUrl } = computedRouteContext;
50
49
  const [state, handleSubmit, isPending] = (0, react_1.useActionState)(async function (prevState, formData) {
@@ -76,59 +75,59 @@ function Signup({ className, onSubmit, groupId, metaData, acceptUsername = true,
76
75
  }, undefined);
77
76
  (0, react_1.useEffect)(() => {
78
77
  let timer;
79
- if ((state === null || state === void 0 ? void 0 : state.status) === "success" && loginUrl) {
78
+ if (state?.status === "success" && loginUrl) {
80
79
  timer = setTimeout(() => {
81
- window.location.href = `${loginUrl}?authToken=${state === null || state === void 0 ? void 0 : state.authToken}`;
80
+ window.location.href = `${loginUrl}?authToken=${state?.authToken}`;
82
81
  }, 2000);
83
82
  }
84
83
  return () => {
85
84
  clearTimeout(timer);
86
85
  };
87
- }, [state === null || state === void 0 ? void 0 : state.status, loginUrl]);
86
+ }, [state?.status, loginUrl]);
88
87
  return (react_1.default.createElement("div", { className: (0, utils_1.cn)("ecpauth:flex ecpauth:flex-col ecpauth:gap-6 ecpauth:w-full ecpauth:max-w-sm", className), ...props },
89
88
  react_1.default.createElement(card_1.Card, null,
90
89
  react_1.default.createElement(card_1.CardHeader, null,
91
90
  react_1.default.createElement(card_1.CardTitle, { className: "ecpauth:text-2xl" }, "Sign Up"),
92
91
  react_1.default.createElement(card_1.CardDescription, null, "Provide your details to sign up from your account.")),
93
92
  react_1.default.createElement(card_1.CardContent, null,
94
- (state === null || state === void 0 ? void 0 : state.status) === "success" ? (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:mb-4 ecpauth:font-semibold ecpauth:text-lg", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:mb-4" })),
93
+ state?.status === "success" ? (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:mb-4 ecpauth:font-semibold ecpauth:text-lg", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:mb-4" })),
95
94
  react_1.default.createElement("form", { action: handleSubmit },
96
95
  react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:flex-col ecpauth:gap-6" },
97
96
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
98
97
  react_1.default.createElement(label_1.Label, { htmlFor: "firstName" }, "First Name"),
99
- react_1.default.createElement(input_1.Input, { id: "firstName", type: "text", placeholder: "First Name", name: "firstName", defaultValue: (_a = state === null || state === void 0 ? void 0 : state.form) === null || _a === void 0 ? void 0 : _a.firstName }),
100
- react_1.default.createElement(message_1.Message, { message: (state === null || state === void 0 ? void 0 : state.status) === "validation-error"
101
- ? (_b = state === null || state === void 0 ? void 0 : state.errors) === null || _b === void 0 ? void 0 : _b.firstName
98
+ react_1.default.createElement(input_1.Input, { id: "firstName", type: "text", placeholder: "First Name", name: "firstName", defaultValue: state?.form?.firstName }),
99
+ react_1.default.createElement(message_1.Message, { message: state?.status === "validation-error"
100
+ ? state?.errors?.firstName
102
101
  : "" })),
103
102
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
104
103
  react_1.default.createElement(label_1.Label, { htmlFor: "lastName" }, "Last Name"),
105
- react_1.default.createElement(input_1.Input, { id: "lastName", type: "text", placeholder: "Last Name", name: "lastName", defaultValue: (_c = state === null || state === void 0 ? void 0 : state.form) === null || _c === void 0 ? void 0 : _c.lastName }),
106
- react_1.default.createElement(message_1.Message, { message: (state === null || state === void 0 ? void 0 : state.status) === "validation-error"
107
- ? (_d = state === null || state === void 0 ? void 0 : state.errors) === null || _d === void 0 ? void 0 : _d.lastName
104
+ react_1.default.createElement(input_1.Input, { id: "lastName", type: "text", placeholder: "Last Name", name: "lastName", defaultValue: state?.form?.lastName }),
105
+ react_1.default.createElement(message_1.Message, { message: state?.status === "validation-error"
106
+ ? state?.errors?.lastName
108
107
  : "" })),
109
108
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
110
109
  react_1.default.createElement(label_1.Label, { htmlFor: "email" }, "Email"),
111
- react_1.default.createElement(input_1.Input, { id: "email", type: "email", placeholder: "email@example.com", name: "email", defaultValue: (_e = state === null || state === void 0 ? void 0 : state.form) === null || _e === void 0 ? void 0 : _e.email }),
112
- react_1.default.createElement(message_1.Message, { message: (state === null || state === void 0 ? void 0 : state.status) === "validation-error"
113
- ? (_f = state === null || state === void 0 ? void 0 : state.errors) === null || _f === void 0 ? void 0 : _f.email
110
+ react_1.default.createElement(input_1.Input, { id: "email", type: "email", placeholder: "email@example.com", name: "email", defaultValue: state?.form?.email }),
111
+ react_1.default.createElement(message_1.Message, { message: state?.status === "validation-error"
112
+ ? state?.errors?.email
114
113
  : "" })),
115
114
  acceptUsername && (react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
116
115
  react_1.default.createElement(label_1.Label, { htmlFor: "username" }, "Username"),
117
- react_1.default.createElement(input_1.Input, { id: "username", type: "text", placeholder: "Username", name: "username", defaultValue: (_g = state === null || state === void 0 ? void 0 : state.form) === null || _g === void 0 ? void 0 : _g.username }),
118
- react_1.default.createElement(message_1.Message, { message: (state === null || state === void 0 ? void 0 : state.status) === "validation-error"
119
- ? (_h = state === null || state === void 0 ? void 0 : state.errors) === null || _h === void 0 ? void 0 : _h.username
116
+ react_1.default.createElement(input_1.Input, { id: "username", type: "text", placeholder: "Username", name: "username", defaultValue: state?.form?.username }),
117
+ react_1.default.createElement(message_1.Message, { message: state?.status === "validation-error"
118
+ ? state?.errors?.username
120
119
  : "" }))),
121
120
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
122
121
  react_1.default.createElement(label_1.Label, { htmlFor: "password" }, "Password"),
123
122
  react_1.default.createElement(input_1.Input, { id: "password", type: "password", name: "password" }),
124
- react_1.default.createElement(message_1.Message, { message: (state === null || state === void 0 ? void 0 : state.status) === "validation-error"
125
- ? (_j = state === null || state === void 0 ? void 0 : state.errors) === null || _j === void 0 ? void 0 : _j.password
123
+ react_1.default.createElement(message_1.Message, { message: state?.status === "validation-error"
124
+ ? state?.errors?.password
126
125
  : "" })),
127
126
  react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:gap-2" },
128
127
  react_1.default.createElement(label_1.Label, { htmlFor: "confirmPassword" }, "Confirm Password"),
129
128
  react_1.default.createElement(input_1.Input, { id: "confirmPassword", type: "password", name: "confirmPassword" }),
130
- react_1.default.createElement(message_1.Message, { message: (state === null || state === void 0 ? void 0 : state.status) === "validation-error"
131
- ? (_k = state === null || state === void 0 ? void 0 : state.errors) === null || _k === void 0 ? void 0 : _k.confirmPassword
129
+ react_1.default.createElement(message_1.Message, { message: state?.status === "validation-error"
130
+ ? state?.errors?.confirmPassword
132
131
  : "" })),
133
132
  react_1.default.createElement(button_1.Button, { type: "submit", className: "ecpauth:w-full ecpauth:cursor-pointer", disabled: isPending }, isPending ? "Signing up..." : "Sign Up")),
134
133
  loginUrl && (react_1.default.createElement("div", { className: "ecpauth:mt-4 ecpauth:text-center ecpauth:text-sm" },
@@ -64,15 +64,15 @@ function Toggle2FA({ onSubmit }) {
64
64
  return (react_1.default.createElement("div", { className: "ecpauth:text-stone-800 ecpauth:dark:text-stone-50" },
65
65
  isPending && react_1.default.createElement(loader_1.Loader, null),
66
66
  react_1.default.createElement("p", { className: "ecpauth:font-semibold ecpauth:text-lg ecpauth:mb-2" }, "Toggle Two Factor Authentication"),
67
- (state === null || state === void 0 ? void 0 : state.status) === "success" ? (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:my-2 ecpauth:font-semibold ecpauth:text-base", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:my-2" })),
67
+ state?.status === "success" ? (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:my-2 ecpauth:font-semibold ecpauth:text-base", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:my-2" })),
68
68
  react_1.default.createElement("p", null,
69
69
  "This action will enable or disable 2FA on your account. If enabled, you\u2019ll be asked for a code sent to ",
70
- react_1.default.createElement("strong", null, user === null || user === void 0 ? void 0 : user.email),
70
+ react_1.default.createElement("strong", null, user?.email),
71
71
  " during login."),
72
72
  react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:items-center ecpauth:justify-between ecpauth:py-3 ecpauth:my-3 ecpauth:border-y ecpauth:border-gray-200 ecpauth:dark:border-gray-800" },
73
73
  react_1.default.createElement("p", { className: "ecpauth:flex-1 ecpauth:mb-0" }, "You can enable or disable your Two Factor Authentication"),
74
74
  react_1.default.createElement("div", { className: "ecpauth:w-40 ecpauth:flex ecpauth:justify-end ecpauth:pe-3" },
75
- react_1.default.createElement(switch_1.Switch, { checked: !!(user === null || user === void 0 ? void 0 : user.with2fa), onCheckedChange: () => startTransition(handleSubmit), disabled: !canUseOtp }))),
75
+ react_1.default.createElement(switch_1.Switch, { checked: !!user?.with2fa, onCheckedChange: () => startTransition(handleSubmit), disabled: !canUseOtp }))),
76
76
  !canUseOtp && (react_1.default.createElement("p", { className: "ecpauth:text-red-500 ecpauth:my-2 ecpauth:text-sm" },
77
77
  "2FA is not available. Please install",
78
78
  " ",
@@ -40,6 +40,7 @@ const button_1 = require("./ui/button");
40
40
  const auth_provider_1 = require("../contexts/auth-provider");
41
41
  const message_1 = require("./message");
42
42
  const must_login_1 = require("./must-login");
43
+ const utils_1 = require("../lib/utils");
43
44
  function ToggleAccountStatus({ user, open, onOpenChange, onSuccess, onSubmit, }) {
44
45
  const { user: loggedInUser } = (0, auth_provider_1.useAuth)();
45
46
  const [state, handleSubmit, isPending] = (0, react_1.useActionState)(async function () {
@@ -57,35 +58,41 @@ function ToggleAccountStatus({ user, open, onOpenChange, onSuccess, onSubmit, })
57
58
  }
58
59
  try {
59
60
  const result = await onSubmit(user.id);
60
- onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess();
61
+ onSuccess?.();
61
62
  return result;
62
63
  }
63
64
  catch (error) {
64
65
  console.log(error);
65
66
  }
66
67
  }, undefined);
67
- return (react_1.default.createElement(dialog_1.Dialog, { open: open, onOpenChange: onOpenChange },
68
- react_1.default.createElement(dialog_1.DialogContent, null, !loggedInUser ? (react_1.default.createElement(must_login_1.MustLogin, { onOpenChange: onOpenChange })) : (react_1.default.createElement("form", { action: handleSubmit },
68
+ return (react_1.default.createElement(dialog_1.Dialog, { open: open, onOpenChange: (state) => {
69
+ onOpenChange(state);
70
+ (0, utils_1.unstuckPointerEvents)();
71
+ } },
72
+ react_1.default.createElement(dialog_1.DialogContent, null, !loggedInUser ? (react_1.default.createElement(must_login_1.MustLogin, { onOpenChange: (state) => {
73
+ onOpenChange(state);
74
+ (0, utils_1.unstuckPointerEvents)();
75
+ } })) : (react_1.default.createElement("form", { action: handleSubmit },
69
76
  react_1.default.createElement(dialog_1.DialogHeader, null,
70
77
  react_1.default.createElement(dialog_1.DialogTitle, null,
71
- "Toggle account status (", user === null || user === void 0 ? void 0 :
72
- user.firstName,
73
- " ", user === null || user === void 0 ? void 0 :
74
- user.lastName,
78
+ "Toggle account status (",
79
+ user?.firstName,
80
+ " ",
81
+ user?.lastName,
75
82
  ")"),
76
- (state === null || state === void 0 ? void 0 : state.status) === "success" ? (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:my-2 ecpauth:font-semibold ecpauth:text-base", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state === null || state === void 0 ? void 0 : state.message, className: "ecpauth:my-2" }))),
83
+ state?.status === "success" ? (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:my-2 ecpauth:font-semibold ecpauth:text-base", variant: "success" })) : (react_1.default.createElement(message_1.Message, { message: state?.message, className: "ecpauth:my-2" }))),
77
84
  react_1.default.createElement(dialog_1.DialogDescription, { className: "ecpauth:flex ecpauth:flex-col ecpauth:gap-2 ecpauth:text-gray-700 ecpauth:dark:text-gray-50 ecpauth:mt-4" },
78
85
  react_1.default.createElement("span", null,
79
86
  "This action will",
80
87
  " ",
81
- react_1.default.createElement("strong", null, (user === null || user === void 0 ? void 0 : user.isActive) ? "suspend" : "unsuspend"),
88
+ react_1.default.createElement("strong", null, user?.isActive ? "suspend" : "unsuspend"),
82
89
  " the user."),
83
90
  react_1.default.createElement("span", null,
84
91
  "You can always",
85
92
  " ",
86
- react_1.default.createElement("strong", null, (user === null || user === void 0 ? void 0 : user.isActive) ? "unsuspend" : "suspend"),
93
+ react_1.default.createElement("strong", null, user?.isActive ? "unsuspend" : "suspend"),
87
94
  " the user if you change your mind.")),
88
95
  react_1.default.createElement(dialog_1.DialogFooter, { className: "ecpauth:flex ecpauth:justify-center ecpauth:gap-2 ecpauth:mt-4" },
89
96
  react_1.default.createElement(button_1.Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false) }, "Cancel"),
90
- react_1.default.createElement(button_1.Button, { disabled: isPending, type: "submit" }, (user === null || user === void 0 ? void 0 : user.isActive) ? "Suspend" : "Unsuspend")))))));
97
+ react_1.default.createElement(button_1.Button, { disabled: isPending, type: "submit" }, user?.isActive ? "Suspend" : "Unsuspend")))))));
91
98
  }
@@ -47,7 +47,7 @@ exports.DialogTrigger = DialogTrigger;
47
47
  const React = __importStar(require("react"));
48
48
  const DialogPrimitive = __importStar(require("@radix-ui/react-dialog"));
49
49
  const utils_1 = require("../../lib/utils");
50
- const x_icon_1 = require("../x-icon");
50
+ const x_icon_1 = require("../icons/x-icon");
51
51
  function Dialog({ ...props }) {
52
52
  return React.createElement(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
53
53
  }
@@ -39,8 +39,11 @@ const dropdown_menu_1 = require("./ui/dropdown-menu");
39
39
  const change_password_1 = require("./change-password");
40
40
  const auth_provider_1 = require("../contexts/auth-provider");
41
41
  const settings_1 = require("./settings");
42
+ const setting_1 = require("./icons/setting");
43
+ const lock_1 = require("./icons/lock");
44
+ const logout_1 = require("./icons/logout");
42
45
  function UserCard({ align = "start", onChangePassword, onToggle2FA, trigger, }) {
43
- const { logout } = (0, auth_provider_1.useAuth)();
46
+ const { logout, user } = (0, auth_provider_1.useAuth)();
44
47
  const [passwordOpen, setPasswordOpen] = (0, react_1.useState)(false);
45
48
  const [settingsOpen, setSettingsOpen] = (0, react_1.useState)(false);
46
49
  return (react_1.default.createElement(react_1.default.Fragment, null,
@@ -49,19 +52,29 @@ function UserCard({ align = "start", onChangePassword, onToggle2FA, trigger, })
49
52
  react_1.default.createElement(dropdown_menu_1.DropdownMenu, null,
50
53
  trigger ? (react_1.default.createElement(dropdown_menu_1.DropdownMenuTrigger, null, trigger)) : (react_1.default.createElement(Trigger, null)),
51
54
  react_1.default.createElement(dropdown_menu_1.DropdownMenuContent, { className: "ecpauth:w-56 ecpauth:border-gray-200 ecpauth:dark:border-gray-800", align: align },
52
- react_1.default.createElement(dropdown_menu_1.DropdownMenuItem, { onClick: () => setSettingsOpen(true) }, "Settings"),
53
- react_1.default.createElement(dropdown_menu_1.DropdownMenuItem, { onClick: () => setPasswordOpen(true) }, "Change Password"),
55
+ react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:flex-col ecpauth:items-center ecpauth:justify-center ecpauth:py-4" },
56
+ react_1.default.createElement("h2", { className: "ecpauth:text-lg ecpauth:font-semibold" }, `${user?.fullName}`),
57
+ react_1.default.createElement("p", { className: "ecpauth:text-sm ecpauth:text-muted-foreground" }, user?.role?.label ?? "-Global-")),
54
58
  react_1.default.createElement(dropdown_menu_1.DropdownMenuSeparator, null),
55
- react_1.default.createElement(dropdown_menu_1.DropdownMenuItem, { onClick: () => logout() }, "Logout")))));
59
+ react_1.default.createElement(dropdown_menu_1.DropdownMenuItem, { onClick: () => setSettingsOpen(true) },
60
+ react_1.default.createElement(setting_1.SettingIcon, null),
61
+ "Settings"),
62
+ react_1.default.createElement(dropdown_menu_1.DropdownMenuItem, { onClick: () => setPasswordOpen(true) },
63
+ react_1.default.createElement(lock_1.LockIcon, null),
64
+ "Change Password"),
65
+ react_1.default.createElement(dropdown_menu_1.DropdownMenuSeparator, null),
66
+ react_1.default.createElement(dropdown_menu_1.DropdownMenuItem, { onClick: () => logout() },
67
+ react_1.default.createElement(logout_1.LogoutIcon, null),
68
+ "Logout")))));
56
69
  }
57
70
  function Trigger() {
58
71
  const { user, authLoading } = (0, auth_provider_1.useAuth)();
59
72
  return (react_1.default.createElement(dropdown_menu_1.DropdownMenuTrigger, { className: "ecpauth:flex ecpauth:items-center ecpauth:gap-2 ecpauth:p-1 ecpauth:pe-4 ecpauth:rounded-lg ecpauth:border ecpauth:border-gray-200 ecpauth:dark:border-gray-800 ecpauth:cursor-pointer ecpauth:bg-white ecpauth:hover:bg-gray-100 ecpauth:dark:bg-gray-800 ecpauth:dark:hover:bg-gray-800/80 ecpauth:dark:hover:text-white ecpauth:outline-none ecpauth:focus:outline-none" }, authLoading ? ("Please wait...") : (react_1.default.createElement(react_1.default.Fragment, null,
60
73
  react_1.default.createElement("div", { className: "ecpauth:size-12 ecpauth:rounded-full ecpauth:bg-gray-200" }),
61
74
  react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:flex-col ecpauth:text-left" },
62
- react_1.default.createElement("span", { className: "ecpauth:font-semibold ecpauth:text-stone-800 ecpauth:dark:text-stone-50" }, user === null || user === void 0 ? void 0 :
63
- user.firstName,
64
- " ", user === null || user === void 0 ? void 0 :
65
- user.lastName),
66
- react_1.default.createElement("span", { className: "ecpauth:text-sm ecpauth:text-gray-500" }, user === null || user === void 0 ? void 0 : user.email))))));
75
+ react_1.default.createElement("span", { className: "ecpauth:font-semibold ecpauth:text-stone-800 ecpauth:dark:text-stone-50" },
76
+ user?.firstName,
77
+ " ",
78
+ user?.lastName),
79
+ react_1.default.createElement("span", { className: "ecpauth:text-sm ecpauth:text-gray-500" }, user?.email))))));
67
80
  }