@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.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-dev.log +32 -0
- package/dist/components/Auth/index.d.ts +2 -1
- package/dist/components/Auth/index.js +4 -4
- package/dist/components/LogoutButton/index.js +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/server.d.ts +5 -1
- package/dist/server.js +9 -6
- package/package.json +3 -2
- package/src/components/Auth/index.tsx +7 -10
- package/src/components/LogoutButton/index.tsx +3 -0
- package/src/index.ts +1 -1
- package/src/server.ts +14 -6
package/.turbo/turbo-build.log
CHANGED
|
@@ -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[[90m7:55:29 AM[0m] Starting compilation in watch mode...
|
|
6
|
+
|
|
7
|
+
[[90m7:55:31 AM[0m] Found 0 errors. Watching for file changes.
|
|
8
|
+
|
|
9
|
+
c[[90m7:55:34 AM[0m] File change detected. Starting incremental compilation...
|
|
10
|
+
|
|
11
|
+
[[90m7:55:34 AM[0m] Found 0 errors. Watching for file changes.
|
|
12
|
+
|
|
13
|
+
c[[90m7:55:38 AM[0m] File change detected. Starting incremental compilation...
|
|
14
|
+
|
|
15
|
+
[[90m7:55:38 AM[0m] Found 0 errors. Watching for file changes.
|
|
16
|
+
|
|
17
|
+
c[[90m11:04:28 AM[0m] File change detected. Starting incremental compilation...
|
|
18
|
+
|
|
19
|
+
[[90m11:04:28 AM[0m] Found 0 errors. Watching for file changes.
|
|
20
|
+
|
|
21
|
+
c[[90m11:04:35 AM[0m] File change detected. Starting incremental compilation...
|
|
22
|
+
|
|
23
|
+
[[90m11:04:35 AM[0m] Found 0 errors. Watching for file changes.
|
|
24
|
+
|
|
25
|
+
c[[90m11:04:43 AM[0m] File change detected. Starting incremental compilation...
|
|
26
|
+
|
|
27
|
+
[[90m11:04:43 AM[0m] Found 0 errors. Watching for file changes.
|
|
28
|
+
|
|
29
|
+
c[[90m11:04:52 AM[0m] File change detected. Starting incremental compilation...
|
|
30
|
+
|
|
31
|
+
[[90m11:04:52 AM[0m] 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 {
|
|
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
|
|
41
|
-
return (_jsxs("div", { className: tw(
|
|
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
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
|
-
|
|
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
|
-
|
|
4
|
-
export async function
|
|
5
|
-
if (
|
|
6
|
-
|
|
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,
|
|
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
|
|
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.
|
|
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 {
|
|
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
|
|
77
|
+
await registerAuthEvents({ login: onLogin, password: onPassword });
|
|
76
78
|
|
|
77
79
|
return (
|
|
78
|
-
<div
|
|
79
|
-
className={tw(
|
|
80
|
-
|
|
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
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
|
-
|
|
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
|
|
22
|
-
if (
|
|
23
|
-
|
|
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,
|
|
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
|
|
78
|
+
return authEvents.password?.(email, token) || false;
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
export async function submitPasswordForm(
|