@sqrzro/auth 2.0.0-bz.0 → 2.0.0-bz.2

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @sqrzro/auth@2.0.0-bz.0 build /Users/richard/Sites/@sqrzro/sqrzro/packages/auth
2
+ > @sqrzro/auth@2.0.0-bz.2 build /Users/richard/Sites/@sqrzro/sqrzro/packages/auth
3
3
  > tsc -p tsconfig.json
4
4
 
@@ -0,0 +1,32 @@
1
+
2
+ > @sqrzro/auth@2.0.0-bz.1 dev /Users/richard/Sites/@sqrzro/sqrzro/packages/auth
3
+ > tsc -p tsconfig.json --watch
4
+
5
+ c[7:55:29 AM] Starting compilation in watch mode...
6
+
7
+ [7:55:31 AM] Found 0 errors. Watching for file changes.
8
+
9
+ c[7:55:34 AM] File change detected. Starting incremental compilation...
10
+
11
+ [7:55:34 AM] Found 0 errors. Watching for file changes.
12
+
13
+ c[7:55:38 AM] File change detected. Starting incremental compilation...
14
+
15
+ [7:55:38 AM] Found 0 errors. Watching for file changes.
16
+
17
+ c[11:04:28 AM] File change detected. Starting incremental compilation...
18
+
19
+ [11:04:28 AM] Found 0 errors. Watching for file changes.
20
+
21
+ c[11:04:35 AM] File change detected. Starting incremental compilation...
22
+
23
+ [11:04:35 AM] Found 0 errors. Watching for file changes.
24
+
25
+ c[11:04:43 AM] File change detected. Starting incremental compilation...
26
+
27
+ [11:04:43 AM] Found 0 errors. Watching for file changes.
28
+
29
+ c[11:04:52 AM] File change detected. Starting incremental compilation...
30
+
31
+ [11:04:52 AM] Found 0 errors. Watching for file changes.
32
+
@@ -13,6 +13,7 @@ export interface AuthClassNames {
13
13
  export interface AuthProps extends ClassNameProps<AuthClassNames> {
14
14
  logo?: React.ReactElement;
15
15
  onLogin?: () => Promise<void>;
16
+ onPassword?: (email: string, token: string) => Promise<boolean>;
16
17
  params: {
17
18
  auth: string[];
18
19
  };
@@ -29,5 +30,5 @@ export interface AuthProps extends ClassNameProps<AuthClassNames> {
29
30
  * sessions etc), using the `getClassNames` pattern won't work, as it currently only works for
30
31
  * client components. So we have to pass the classNames directly to the component.
31
32
  */
32
- declare function Auth({ classNames, logo, onLogin, params: { auth }, searchParams, }: Readonly<AuthProps>): Promise<React.ReactElement>;
33
+ declare function Auth({ classNames, logo, onLogin, onPassword, params: { auth }, searchParams, }: Readonly<AuthProps>): Promise<React.ReactElement>;
33
34
  export default Auth;
@@ -4,7 +4,7 @@ import { notFound } from 'next/navigation';
4
4
  import LoginForm from '../LoginForm';
5
5
  import MFAPage from '../MFAPage';
6
6
  import PasswordPage from '../PasswordPage';
7
- import { registerAuthEvent } from '../../server';
7
+ import { registerAuthEvents } from '../../server';
8
8
  /**
9
9
  * To make it easier for consumers to use Auth in their projects, this auth component uses a
10
10
  * Catch-All Segment to handle the rendering of all Auth pages. This function is used to determine
@@ -33,12 +33,12 @@ function getPage(route, props) {
33
33
  * sessions etc), using the `getClassNames` pattern won't work, as it currently only works for
34
34
  * client components. So we have to pass the classNames directly to the component.
35
35
  */
36
- async function Auth({ classNames, logo, onLogin, params: { auth }, searchParams, }) {
36
+ async function Auth({ classNames, logo, onLogin, onPassword, params: { auth }, searchParams, }) {
37
37
  if (auth.length > 1) {
38
38
  return notFound();
39
39
  }
40
- await registerAuthEvent(onLogin);
41
- return (_jsxs("div", { className: tw('grid h-screen grid-rows-[1fr_auto_auto_2fr] justify-center', classNames?.root), children: [_jsx("div", { className: tw('row-start-2', classNames?.logo), children: logo }), _jsx("div", { className: tw('row-start-3 w-screen max-w-sm', classNames?.panel), children: getPage(auth[0], {
40
+ await registerAuthEvents({ login: onLogin, password: onPassword });
41
+ return (_jsxs("div", { className: tw(classNames?.root), children: [_jsx("div", { className: tw(classNames?.logo), children: logo }), _jsx("div", { className: tw(classNames?.panel), children: getPage(auth[0], {
42
42
  classNames,
43
43
  searchParams,
44
44
  }) })] }));
@@ -7,6 +7,8 @@ function LogoutButton({ children = 'Log out', redirectTo, }) {
7
7
  async function handleLogout() {
8
8
  await logout();
9
9
  router.push(redirectTo || '/');
10
+ // It seems necessary to refresh to ensure the user is redirected to the login page
11
+ router.refresh();
10
12
  }
11
13
  return (_jsx("form", { action: handleLogout, className: "contents", children: _jsx("button", { type: "submit", children: children }) }));
12
14
  }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { default as Auth } from './components/Auth';
2
- export type { AuthProps } from './components/Auth';
2
+ export type { AuthClassNames, AuthProps } from './components/Auth';
3
3
  export { default as LogoutButton } from './components/LogoutButton';
package/dist/server.d.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import type { LoginFormFields, MFAFormFields, UserObject } from '@sqrzro/server/auth';
2
2
  import type { Errorable } from '@sqrzro/interfaces';
3
3
  export type { MFAFormFields, ScopeObject } from '@sqrzro/server/auth';
4
- export declare function registerAuthEvent(fn?: () => Promise<void>): Promise<void>;
4
+ interface AuthEventObject {
5
+ login?: () => Promise<void>;
6
+ password?: (email: string, token: string) => Promise<boolean>;
7
+ }
8
+ export declare function registerAuthEvents(events: AuthEventObject): Promise<void>;
5
9
  export declare function checkUserHasMFA(user: UserObject): Promise<boolean>;
6
10
  export declare function generateMFA(name: string, email?: string): Promise<string | null>;
7
11
  export declare function getSessionUser(): Promise<UserObject | null>;
package/dist/server.js CHANGED
@@ -1,9 +1,12 @@
1
1
  'use server';
2
2
  import { handleLoginForm, handleLogout, handleMFAForm, handlePasswordForm, handlePasswordResetForm, checkUserHasMFA as serverCheckUserHasMFA, generateMFA as serverGenerateMFA, getSessionUser as serverGetSessionUser, checkMFAEnabled as syncCheckMFAEnabled, } from '@sqrzro/server/auth';
3
- let authEvent; // eslint-disable-line @typescript-eslint/init-declarations
4
- export async function registerAuthEvent(fn) {
5
- if (fn) {
6
- authEvent = fn;
3
+ const authEvents = {};
4
+ export async function registerAuthEvents(events) {
5
+ if (events.login) {
6
+ authEvents.login = events.login;
7
+ }
8
+ if (events.password) {
9
+ authEvents.password = events.password;
7
10
  }
8
11
  return Promise.resolve();
9
12
  }
@@ -27,13 +30,13 @@ export async function checkMFAEnabled() {
27
30
  return Promise.resolve(syncCheckMFAEnabled());
28
31
  }
29
32
  export async function submitLoginForm(formData) {
30
- return handleLoginForm(formData, authEvent);
33
+ return handleLoginForm(formData, authEvents.login);
31
34
  }
32
35
  export async function submitMFAForm(formData) {
33
36
  return handleMFAForm(formData);
34
37
  }
35
38
  async function sendPasswordResetMail(email, token) {
36
- return true;
39
+ return authEvents.password?.(email, token) || false;
37
40
  }
38
41
  export async function submitPasswordForm(formData) {
39
42
  return handlePasswordForm(formData, sendPasswordResetMail);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sqrzro/auth",
3
3
  "type": "module",
4
- "version": "2.0.0-bz.0",
4
+ "version": "2.0.0-bz.2",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "dependencies": {
@@ -17,6 +17,7 @@
17
17
  "typescript": "^5.4.4"
18
18
  },
19
19
  "scripts": {
20
- "build": "tsc -p tsconfig.json"
20
+ "build": "tsc -p tsconfig.json",
21
+ "dev": "tsc -p tsconfig.json --watch"
21
22
  }
22
23
  }
@@ -6,7 +6,7 @@ import LoginForm from '../LoginForm';
6
6
  import MFAPage from '../MFAPage';
7
7
  import PasswordPage from '../PasswordPage';
8
8
 
9
- import { registerAuthEvent } from '../../server';
9
+ import { registerAuthEvents } from '../../server';
10
10
  import type { ScopeObject } from '../../server';
11
11
 
12
12
  export interface AuthClassNames {
@@ -22,6 +22,7 @@ export interface AuthClassNames {
22
22
  export interface AuthProps extends ClassNameProps<AuthClassNames> {
23
23
  logo?: React.ReactElement;
24
24
  onLogin?: () => Promise<void>;
25
+ onPassword?: (email: string, token: string) => Promise<boolean>;
25
26
  params: { auth: string[] };
26
27
  scopes?: Partial<ScopeObject>;
27
28
  searchParams: { email?: string; r?: string; token?: string };
@@ -65,6 +66,7 @@ async function Auth({
65
66
  classNames,
66
67
  logo,
67
68
  onLogin,
69
+ onPassword,
68
70
  params: { auth },
69
71
  searchParams,
70
72
  }: Readonly<AuthProps>): Promise<React.ReactElement> {
@@ -72,17 +74,12 @@ async function Auth({
72
74
  return notFound();
73
75
  }
74
76
 
75
- await registerAuthEvent(onLogin);
77
+ await registerAuthEvents({ login: onLogin, password: onPassword });
76
78
 
77
79
  return (
78
- <div
79
- className={tw(
80
- 'grid h-screen grid-rows-[1fr_auto_auto_2fr] justify-center',
81
- classNames?.root
82
- )}
83
- >
84
- <div className={tw('row-start-2', classNames?.logo)}>{logo}</div>
85
- <div className={tw('row-start-3 w-screen max-w-sm', classNames?.panel)}>
80
+ <div className={tw(classNames?.root)}>
81
+ <div className={tw(classNames?.logo)}>{logo}</div>
82
+ <div className={tw(classNames?.panel)}>
86
83
  {getPage(auth[0], {
87
84
  classNames,
88
85
  searchParams,
@@ -18,6 +18,9 @@ function LogoutButton({
18
18
  async function handleLogout(): Promise<void> {
19
19
  await logout();
20
20
  router.push(redirectTo || '/');
21
+
22
+ // It seems necessary to refresh to ensure the user is redirected to the login page
23
+ router.refresh();
21
24
  }
22
25
 
23
26
  return (
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { default as Auth } from './components/Auth';
2
- export type { AuthProps } from './components/Auth';
2
+ export type { AuthClassNames, AuthProps } from './components/Auth';
3
3
  export { default as LogoutButton } from './components/LogoutButton';
package/src/server.ts CHANGED
@@ -16,11 +16,19 @@ import type { Errorable } from '@sqrzro/interfaces';
16
16
 
17
17
  export type { MFAFormFields, ScopeObject } from '@sqrzro/server/auth';
18
18
 
19
- let authEvent: () => Promise<void>; // eslint-disable-line @typescript-eslint/init-declarations
19
+ interface AuthEventObject {
20
+ login?: () => Promise<void>;
21
+ password?: (email: string, token: string) => Promise<boolean>;
22
+ }
23
+
24
+ const authEvents: AuthEventObject = {};
20
25
 
21
- export async function registerAuthEvent(fn?: () => Promise<void>): Promise<void> {
22
- if (fn) {
23
- authEvent = fn;
26
+ export async function registerAuthEvents(events: AuthEventObject): Promise<void> {
27
+ if (events.login) {
28
+ authEvents.login = events.login;
29
+ }
30
+ if (events.password) {
31
+ authEvents.password = events.password;
24
32
  }
25
33
  return Promise.resolve();
26
34
  }
@@ -59,7 +67,7 @@ interface PasswordResetFormFields {
59
67
  }
60
68
 
61
69
  export async function submitLoginForm(formData: LoginFormFields): Promise<Errorable<string>> {
62
- return handleLoginForm(formData, authEvent);
70
+ return handleLoginForm(formData, authEvents.login);
63
71
  }
64
72
 
65
73
  export async function submitMFAForm(formData: MFAFormFields): Promise<Errorable<boolean>> {
@@ -67,7 +75,7 @@ export async function submitMFAForm(formData: MFAFormFields): Promise<Errorable<
67
75
  }
68
76
 
69
77
  async function sendPasswordResetMail(email: string, token: string): Promise<boolean> {
70
- return true;
78
+ return authEvents.password?.(email, token) || false;
71
79
  }
72
80
 
73
81
  export async function submitPasswordForm(