@sqrzro/auth 2.0.0-r19.8 → 4.0.0-alpha.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.
- package/.turbo/turbo-build.log +2 -2
- package/.turbo/turbo-dev.log +71 -0
- package/dist/components/Auth/index.d.ts +4 -32
- package/dist/components/Auth/index.js +19 -40
- package/dist/components/AuthComponent/index.d.ts +6 -0
- package/dist/components/AuthComponent/index.js +21 -0
- package/dist/components/LoginForm/index.d.ts +2 -1
- package/dist/components/LoginForm/index.js +22 -3
- package/dist/components/LogoutButton/index.d.ts +1 -2
- package/dist/components/LogoutButton/index.js +5 -11
- package/dist/components/LogoutButton/server.d.ts +2 -0
- package/dist/components/LogoutButton/server.js +8 -0
- package/dist/components/MFAForm/index.js +1 -1
- package/dist/components/Password/index.d.ts +5 -0
- package/dist/components/Password/index.js +18 -0
- package/dist/components/PasswordForm/index.js +1 -1
- package/dist/components/PasswordResetForm/index.js +1 -1
- package/dist/forms/LoginForm/client.d.ts +2 -0
- package/dist/forms/LoginForm/client.js +13 -0
- package/dist/forms/LoginForm/index.d.ts +2 -0
- package/dist/forms/LoginForm/index.js +13 -0
- package/dist/forms/LoginForm/interfaces.d.ts +5 -0
- package/dist/forms/LoginForm/interfaces.js +1 -0
- package/dist/forms/LoginForm/server.d.ts +4 -0
- package/dist/forms/LoginForm/server.js +25 -0
- package/dist/forms/PasswordForm/client.d.ts +2 -0
- package/dist/forms/PasswordForm/client.js +13 -0
- package/dist/forms/PasswordForm/index.d.ts +2 -0
- package/dist/forms/PasswordForm/index.js +12 -0
- package/dist/forms/PasswordForm/interfaces.d.ts +3 -0
- package/dist/forms/PasswordForm/interfaces.js +1 -0
- package/dist/forms/PasswordForm/server.d.ts +4 -0
- package/dist/forms/PasswordForm/server.js +21 -0
- package/dist/forms/PasswordResetForm/client.d.ts +5 -0
- package/dist/forms/PasswordResetForm/client.js +14 -0
- package/dist/forms/PasswordResetForm/index.d.ts +5 -0
- package/dist/forms/PasswordResetForm/index.js +13 -0
- package/dist/forms/PasswordResetForm/interfaces.d.ts +4 -0
- package/dist/forms/PasswordResetForm/interfaces.js +1 -0
- package/dist/forms/PasswordResetForm/server.d.ts +4 -0
- package/dist/forms/PasswordResetForm/server.js +23 -0
- package/dist/handle-proxy.d.ts +4 -0
- package/dist/handle-proxy.js +17 -0
- package/dist/hooks/useLoginForm.js +3 -0
- package/dist/index.d.ts +1 -5
- package/dist/index.js +1 -2
- package/dist/interfaces.d.ts +10 -0
- package/dist/interfaces.js +1 -0
- package/dist/proxy.d.ts +0 -0
- package/dist/proxy.js +1 -0
- package/dist/server.d.ts +6 -1
- package/dist/server.js +12 -3
- package/package.json +14 -11
- package/src/components/Auth/index.tsx +31 -75
- package/src/components/LogoutButton/index.tsx +7 -19
- package/src/components/LogoutButton/server.ts +11 -0
- package/src/components/Password/index.tsx +26 -0
- package/src/forms/LoginForm/index.tsx +33 -0
- package/src/forms/LoginForm/interfaces.ts +5 -0
- package/src/forms/LoginForm/server.ts +33 -0
- package/src/forms/PasswordForm/index.tsx +24 -0
- package/src/forms/PasswordForm/interfaces.ts +3 -0
- package/src/forms/PasswordForm/server.ts +28 -0
- package/src/forms/PasswordResetForm/index.tsx +29 -0
- package/src/forms/PasswordResetForm/interfaces.ts +4 -0
- package/src/forms/PasswordResetForm/server.ts +30 -0
- package/src/handle-proxy.ts +23 -0
- package/src/index.ts +1 -7
- package/src/interfaces.ts +10 -0
- package/tsconfig.json +6 -5
- package/src/components/LoginForm/index.tsx +0 -44
- package/src/components/MFAForm/index.tsx +0 -47
- package/src/components/MFAPage/index.tsx +0 -54
- package/src/components/MFASetup/index.tsx +0 -43
- package/src/components/MFASetupForm/index.tsx +0 -78
- package/src/components/PasswordForm/index.tsx +0 -113
- package/src/components/PasswordPage/index.tsx +0 -20
- package/src/components/PasswordResetForm/index.tsx +0 -45
- package/src/hooks/useLoginForm.ts +0 -33
- package/src/hooks/useMFAForm.ts +0 -56
- package/src/server.ts +0 -100
package/.turbo/turbo-build.log
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
> @sqrzro/auth@2.0.0-r19.14 dev /Users/richard/Sites/@sqrzro/sqrzro/packages/auth
|
|
3
|
+
> tsc --watch
|
|
4
|
+
|
|
5
|
+
[2J[3J[H[[90m10:06:07 AM[0m] Starting compilation in watch mode...
|
|
6
|
+
|
|
7
|
+
[[90m10:06:11 AM[0m] Found 0 errors. Watching for file changes.
|
|
8
|
+
|
|
9
|
+
[2J[3J[H[[90m10:06:14 AM[0m] File change detected. Starting incremental compilation...
|
|
10
|
+
|
|
11
|
+
[96msrc/components/LogoutButton/server.ts[0m:[93m3[0m:[93m31[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/auth'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/auth/index.js' implicitly has an 'any' type.
|
|
12
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/auth';`
|
|
13
|
+
|
|
14
|
+
[7m3[0m import { deleteSession } from '@sqrzro/server/auth';
|
|
15
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~[0m
|
|
16
|
+
|
|
17
|
+
[96msrc/components/Password/index.tsx[0m:[93m1[0m:[93m31[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/auth'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/auth/index.js' implicitly has an 'any' type.
|
|
18
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/auth';`
|
|
19
|
+
|
|
20
|
+
[7m1[0m import { validateReset } from '@sqrzro/server/auth';
|
|
21
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~[0m
|
|
22
|
+
|
|
23
|
+
[96msrc/forms/LoginForm/server.ts[0m:[93m3[0m:[93m45[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/auth'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/auth/index.js' implicitly has an 'any' type.
|
|
24
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/auth';`
|
|
25
|
+
|
|
26
|
+
[7m3[0m import { createSession, validateUser } from '@sqrzro/server/auth';
|
|
27
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~[0m
|
|
28
|
+
|
|
29
|
+
[96msrc/forms/LoginForm/server.ts[0m:[93m4[0m:[93m42[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/forms'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/forms/index.js' implicitly has an 'any' type.
|
|
30
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/forms';`
|
|
31
|
+
|
|
32
|
+
[7m4[0m import { FormResponse, submitForm } from '@sqrzro/server/forms';
|
|
33
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~~[0m
|
|
34
|
+
|
|
35
|
+
[96msrc/forms/PasswordForm/server.ts[0m:[93m3[0m:[93m29[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/auth'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/auth/index.js' implicitly has an 'any' type.
|
|
36
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/auth';`
|
|
37
|
+
|
|
38
|
+
[7m3[0m import { createReset } from '@sqrzro/server/auth';
|
|
39
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~[0m
|
|
40
|
+
|
|
41
|
+
[96msrc/forms/PasswordForm/server.ts[0m:[93m4[0m:[93m42[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/forms'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/forms/index.js' implicitly has an 'any' type.
|
|
42
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/forms';`
|
|
43
|
+
|
|
44
|
+
[7m4[0m import { FormResponse, submitForm } from '@sqrzro/server/forms';
|
|
45
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~~[0m
|
|
46
|
+
|
|
47
|
+
[96msrc/forms/PasswordResetForm/server.ts[0m:[93m3[0m:[93m41[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/auth'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/auth/index.js' implicitly has an 'any' type.
|
|
48
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/auth';`
|
|
49
|
+
|
|
50
|
+
[7m3[0m import { updatePasswordWithToken } from '@sqrzro/server/auth';
|
|
51
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~[0m
|
|
52
|
+
|
|
53
|
+
[96msrc/forms/PasswordResetForm/server.ts[0m:[93m4[0m:[93m42[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/forms'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/forms/index.js' implicitly has an 'any' type.
|
|
54
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/forms';`
|
|
55
|
+
|
|
56
|
+
[7m4[0m import { FormResponse, submitForm } from '@sqrzro/server/forms';
|
|
57
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~~[0m
|
|
58
|
+
|
|
59
|
+
[96msrc/handle-proxy.ts[0m:[93m1[0m:[93m33[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/auth'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/auth/index.js' implicitly has an 'any' type.
|
|
60
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/auth';`
|
|
61
|
+
|
|
62
|
+
[7m1[0m import { validateSession } from '@sqrzro/server/auth';
|
|
63
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~[0m
|
|
64
|
+
|
|
65
|
+
[[90m10:06:14 AM[0m] Found 9 errors. Watching for file changes.
|
|
66
|
+
|
|
67
|
+
[2J[3J[H[[90m10:06:16 AM[0m] File change detected. Starting incremental compilation...
|
|
68
|
+
|
|
69
|
+
[[90m10:06:17 AM[0m] Found 0 errors. Watching for file changes.
|
|
70
|
+
|
|
71
|
+
[41m[30m ELIFECYCLE [39m[49m [31mCommand failed.[39m
|
|
@@ -1,34 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
actions: string;
|
|
5
|
-
footer: string;
|
|
6
|
-
form: string;
|
|
7
|
-
link: string;
|
|
8
|
-
logo: string;
|
|
9
|
-
root: string;
|
|
10
|
-
panel: string;
|
|
11
|
-
title: string;
|
|
1
|
+
interface AuthProps {
|
|
2
|
+
params: Promise<Record<string, string>>;
|
|
3
|
+
searchParams: Promise<Record<string, string>>;
|
|
12
4
|
}
|
|
13
|
-
|
|
14
|
-
logo?: React.ReactElement;
|
|
15
|
-
onLogin?: () => Promise<void>;
|
|
16
|
-
onPassword?: (email: string, token: string) => Promise<boolean>;
|
|
17
|
-
params: {
|
|
18
|
-
auth: string[];
|
|
19
|
-
};
|
|
20
|
-
scopes?: Partial<ScopeObject>;
|
|
21
|
-
searchParams: {
|
|
22
|
-
email?: string;
|
|
23
|
-
r?: string;
|
|
24
|
-
token?: string;
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
*
|
|
29
|
-
* A note on `classNames`: As `Auth` needs to run on the server (as some of its children require
|
|
30
|
-
* sessions etc), using the `getClassNames` pattern won't work, as it currently only works for
|
|
31
|
-
* client components. So we have to pass the classNames directly to the component.
|
|
32
|
-
*/
|
|
33
|
-
declare function Auth({ classNames, logo, onLogin, onPassword, params: { auth }, searchParams, }: Readonly<AuthProps>): Promise<React.ReactElement>;
|
|
5
|
+
declare function Auth({ params, searchParams }: Readonly<AuthProps>): React.ReactElement;
|
|
34
6
|
export default Auth;
|
|
@@ -1,46 +1,25 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { Suspense } from 'react';
|
|
3
3
|
import { notFound } from 'next/navigation';
|
|
4
|
-
import LoginForm from '
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* To make it easier for consumers to use Auth in their projects, this auth component uses a
|
|
10
|
-
* Catch-All Segment to handle the rendering of all Auth pages. This function is used to determine
|
|
11
|
-
* which page to render based on the route.
|
|
12
|
-
*
|
|
13
|
-
* More information on Catch-All Segments can be found here:
|
|
14
|
-
* https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes#catch-all-segments
|
|
15
|
-
*
|
|
16
|
-
* @param route
|
|
17
|
-
* @param props
|
|
18
|
-
* @returns
|
|
19
|
-
*/
|
|
20
|
-
function getPage(route, props) {
|
|
21
|
-
switch (route) {
|
|
22
|
-
case 'mfa':
|
|
23
|
-
return _jsx(MFAPage, { ...props });
|
|
24
|
-
case 'password':
|
|
25
|
-
return _jsx(PasswordPage, { ...props });
|
|
26
|
-
default:
|
|
27
|
-
return _jsx(LoginForm, { ...props });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
*
|
|
32
|
-
* A note on `classNames`: As `Auth` needs to run on the server (as some of its children require
|
|
33
|
-
* sessions etc), using the `getClassNames` pattern won't work, as it currently only works for
|
|
34
|
-
* client components. So we have to pass the classNames directly to the component.
|
|
35
|
-
*/
|
|
36
|
-
async function Auth({ classNames, logo, onLogin, onPassword, params: { auth }, searchParams, }) {
|
|
37
|
-
if (auth.length > 1) {
|
|
4
|
+
import LoginForm from '../../forms/LoginForm';
|
|
5
|
+
import Password from '../Password';
|
|
6
|
+
async function AuthComponent({ params, searchParams, }) {
|
|
7
|
+
const awaitedParams = await params;
|
|
8
|
+
if (!Array.isArray(awaitedParams.auth) || awaitedParams.auth.length !== 1) {
|
|
38
9
|
return notFound();
|
|
39
10
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
11
|
+
if (awaitedParams.auth[0] === 'login') {
|
|
12
|
+
return _jsx(LoginForm, {});
|
|
13
|
+
}
|
|
14
|
+
if (awaitedParams.auth[0] === 'mfa') {
|
|
15
|
+
return _jsx("div", { children: "[MFA NOT DONE]" });
|
|
16
|
+
}
|
|
17
|
+
if (awaitedParams.auth[0] === 'password') {
|
|
18
|
+
return _jsx(Password, { searchParams: searchParams });
|
|
19
|
+
}
|
|
20
|
+
return notFound();
|
|
21
|
+
}
|
|
22
|
+
function Auth({ params, searchParams }) {
|
|
23
|
+
return (_jsxs("div", { children: ["AUTH PAGE HEADER", _jsx(Suspense, { children: _jsx(AuthComponent, { params: params, searchParams: searchParams }) })] }));
|
|
45
24
|
}
|
|
46
25
|
export default Auth;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
interface AuthComponentProps {
|
|
2
|
+
params: Promise<Record<string, string>>;
|
|
3
|
+
searchParams: Promise<Record<string, string>>;
|
|
4
|
+
}
|
|
5
|
+
declare function AuthComponent({ params, searchParams, }: Readonly<AuthComponentProps>): Promise<React.ReactElement>;
|
|
6
|
+
export default AuthComponent;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { notFound } from 'next/navigation';
|
|
3
|
+
import LoginForm from '../../forms/LoginForm';
|
|
4
|
+
import Password from '../Password';
|
|
5
|
+
async function AuthComponent({ params, searchParams, }) {
|
|
6
|
+
const awaitedParams = await params;
|
|
7
|
+
if (!Array.isArray(awaitedParams.auth) || awaitedParams.auth.length !== 1) {
|
|
8
|
+
return notFound();
|
|
9
|
+
}
|
|
10
|
+
if (awaitedParams.auth[0] === 'login') {
|
|
11
|
+
return _jsx(LoginForm, {});
|
|
12
|
+
}
|
|
13
|
+
if (awaitedParams.auth[0] === 'mfa') {
|
|
14
|
+
return _jsx("div", { children: "[MFA NOT DONE]" });
|
|
15
|
+
}
|
|
16
|
+
if (awaitedParams.auth[0] === 'password') {
|
|
17
|
+
return _jsx(Password, { searchParams: searchParams });
|
|
18
|
+
}
|
|
19
|
+
return notFound();
|
|
20
|
+
}
|
|
21
|
+
export default AuthComponent;
|
|
@@ -3,7 +3,8 @@ export interface LoginFormProps {
|
|
|
3
3
|
classNames?: Partial<AuthClassNames>;
|
|
4
4
|
searchParams: {
|
|
5
5
|
r?: string;
|
|
6
|
+
session?: string;
|
|
6
7
|
};
|
|
7
8
|
}
|
|
8
|
-
declare function LoginForm({ classNames, searchParams }: Readonly<LoginFormProps>): React.ReactElement;
|
|
9
|
+
declare function LoginForm({ classNames, searchParams }: Readonly<LoginFormProps>): React.ReactElement | null;
|
|
9
10
|
export default LoginForm;
|
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Fragment } from 'react';
|
|
3
|
+
import { Fragment, useEffect } from 'react';
|
|
4
|
+
import { usePathname } from 'next/navigation';
|
|
4
5
|
import { Form, FormSubmit, Link, PasswordFormField, TextFormField, tw } from '@sqrzro/components';
|
|
5
6
|
import useLoginForm from '../../hooks/useLoginForm';
|
|
6
|
-
import { submitLoginForm } from '../../server';
|
|
7
|
+
import { setUserSession, submitLoginForm } from '../../server';
|
|
7
8
|
function LoginForm({ classNames, searchParams }) {
|
|
9
|
+
const pathname = usePathname();
|
|
8
10
|
const { fieldProps, formData, formProps, isLoading } = useLoginForm(submitLoginForm, {
|
|
9
11
|
redirect: searchParams.r,
|
|
10
12
|
});
|
|
11
|
-
|
|
13
|
+
async function handleSession() {
|
|
14
|
+
if (searchParams.session) {
|
|
15
|
+
void setUserSession(searchParams.session);
|
|
16
|
+
setTimeout(() => {
|
|
17
|
+
window.location.href = pathname;
|
|
18
|
+
}, 500);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (searchParams.session) {
|
|
23
|
+
void handleSession();
|
|
24
|
+
}
|
|
25
|
+
}, []);
|
|
26
|
+
// If a session is provided, show a loading page while the session is being redirected
|
|
27
|
+
if (searchParams.session) {
|
|
28
|
+
return _jsx("h1", { className: tw('text-center', classNames?.title), children: "Authenticating..." });
|
|
29
|
+
}
|
|
30
|
+
return (_jsxs(Fragment, { children: [_jsx("h1", { className: tw('text-center', classNames?.title), children: "Sign in to continue" }), _jsxs(Form, { ...formProps, classNames: { root: classNames?.form }, children: [_jsx(TextFormField, { ...fieldProps('email'), hasAssistiveError: true }), _jsx(PasswordFormField, { ...fieldProps('password'), hasAssistiveError: true }), _jsx("div", { className: tw(classNames?.actions), children: _jsx(FormSubmit, { isFullWidth: true, isLoading: isLoading, children: "Sign In" }) }), _jsx("footer", { className: tw('text-center', classNames?.footer), children: _jsx(Link, { className: classNames?.link, href: `/auth/password${formData.email ? `?email=${formData.email}` : ''}`, children: "Forgot Password?" }) })] })] }));
|
|
12
31
|
}
|
|
13
32
|
export default LoginForm;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export interface LogoutButtonProps {
|
|
2
2
|
children?: React.ReactElement | string;
|
|
3
|
-
redirectTo?: string;
|
|
4
3
|
}
|
|
5
|
-
declare function LogoutButton({ children
|
|
4
|
+
declare function LogoutButton({ children }: Readonly<LogoutButtonProps>): React.ReactElement;
|
|
6
5
|
export default LogoutButton;
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
function LogoutButton({ children = 'Log out'
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
await logout();
|
|
9
|
-
router.push(redirectTo || '/');
|
|
10
|
-
// It seems necessary to refresh to ensure the user is redirected to the login page
|
|
11
|
-
router.refresh();
|
|
12
|
-
}
|
|
13
|
-
return (_jsx("form", { action: handleLogout, className: "contents", children: _jsx("button", { type: "submit", children: children }) }));
|
|
3
|
+
import { useTransition } from 'react';
|
|
4
|
+
import handle from './server';
|
|
5
|
+
function LogoutButton({ children = 'Log out' }) {
|
|
6
|
+
const [isLoading, startTransition] = useTransition();
|
|
7
|
+
return (_jsx("button", { disabled: isLoading, onClick: () => startTransition(handle), children: children }));
|
|
14
8
|
}
|
|
15
9
|
export default LogoutButton;
|
|
@@ -14,6 +14,6 @@ function MFAForm({ classNames, searchParams }) {
|
|
|
14
14
|
setDelayedKey(key);
|
|
15
15
|
}
|
|
16
16
|
}, [isLoading, key]);
|
|
17
|
-
return (_jsxs(Form, { ...formProps, classNames: { root: classNames?.form }, children: [_jsx(CodeFormField, { ...fieldProps('token'), isDisabled: isLoading, onFinalChange: submitForm, hasAssistiveError: true, hasAssistiveLabel: true, isAutoFocus: true }, delayedKey), _jsx("div", { className: "sr-only", children: _jsx(FormSubmit, { children: "Verify" }) })] }));
|
|
17
|
+
return (_jsxs(Form, { ...formProps, classNames: { root: classNames?.form }, children: [_jsx(CodeFormField, { ...fieldProps('token'), isDisabled: isLoading, onFinalChange: submitForm, hasAssistiveError: true, hasAssistiveLabel: true, isAutoFocus: true }, delayedKey), _jsx("div", { className: "sr-only", children: _jsx(FormSubmit, { isFullWidth: true, children: "Verify" }) })] }));
|
|
18
18
|
}
|
|
19
19
|
export default MFAForm;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { validateReset } from '@sqrzro/server/auth';
|
|
3
|
+
import PasswordForm from '../../forms/PasswordForm';
|
|
4
|
+
import PasswordResetForm from '../../forms/PasswordResetForm';
|
|
5
|
+
async function Password({ searchParams }) {
|
|
6
|
+
const awaitedSearchParams = await searchParams;
|
|
7
|
+
if (awaitedSearchParams.token) {
|
|
8
|
+
const validated = await validateReset('PASSWORD', awaitedSearchParams.token);
|
|
9
|
+
if (validated) {
|
|
10
|
+
return _jsx(PasswordResetForm, { token: awaitedSearchParams.token });
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
return _jsx("div", { children: "Invalid or Expired Token" });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return _jsx(PasswordForm, {});
|
|
17
|
+
}
|
|
18
|
+
export default Password;
|
|
@@ -23,6 +23,6 @@ function PasswordForm({ classNames, email }) {
|
|
|
23
23
|
setFormData('email', '');
|
|
24
24
|
setSentCount(0);
|
|
25
25
|
}
|
|
26
|
-
return (_jsxs(Fragment, { children: [_jsx("div", { className: tw(sentCount === 0 ? 'block' : 'hidden'), children: _jsxs(Form, { ...formProps, classNames: { root: classNames?.form }, children: [_jsx("h1", { className: classNames?.title, children: "Reset Your Password" }), _jsx("p", { className: "text-sm", children: "Enter the email address associated with your account and we'll send you a link to reset your password." }), _jsx(TextFormField, { ...fieldProps('email'), type: "email", hasAssistiveLabel: true }), _jsx("div", { className: tw(classNames?.actions), children: _jsx(FormSubmit, { isLoading: isLoading, children: "Send Email" }) }), _jsx("footer", { className: tw('text-center', classNames?.footer), children: _jsx(Link, { className: classNames?.link, href: "/auth/login", children: "Back" }) })] }) }), _jsx("div", { className: tw(sentCount > 0 ? 'flex' : 'hidden'), children: _jsxs("div", { className: tw(classNames?.form), children: [_jsx("h1", { className: classNames?.title, children: "Check Your Email" }), sentCount === 1 ? (_jsxs(Fragment, { children: [_jsxs("p", { className: "text-sm", children: ["If ", _jsx("strong", { children: formData.email }), " matches an email we have on file, then we've sent you an email containing further instructions for resetting your password."] }), _jsxs("p", { className: "text-sm", children: ["If you haven't received an email in 5 minutes, check your spam,", ' ', _jsx(Link, { className: classNames?.link, onClick: handleResend, children: "resend" }), ", or", ' ', _jsx(Link, { className: classNames?.link, onClick: handleReset, children: "try a different email address" }), "."] })] })) : (_jsxs(Fragment, { children: [_jsxs("p", { className: "text-sm", children: ["We've resent password reset instructions to", ' ', _jsx("strong", { children: formData.email }), ", if it is an email we have on file."] }), _jsxs("p", { className: "text-sm", children: ["Please check again. If you still haven't received an email,", ' ', _jsx(Link, { className: classNames?.link, onClick: handleReset, children: "try a different email address" }), "."] })] }))] }) })] }));
|
|
26
|
+
return (_jsxs(Fragment, { children: [_jsx("div", { className: tw(sentCount === 0 ? 'block' : 'hidden'), children: _jsxs(Form, { ...formProps, classNames: { root: classNames?.form }, children: [_jsx("h1", { className: classNames?.title, children: "Reset Your Password" }), _jsx("p", { className: "text-sm", children: "Enter the email address associated with your account and we'll send you a link to reset your password." }), _jsx(TextFormField, { ...fieldProps('email'), type: "email", hasAssistiveLabel: true }), _jsx("div", { className: tw(classNames?.actions), children: _jsx(FormSubmit, { isFullWidth: true, isLoading: isLoading, children: "Send Email" }) }), _jsx("footer", { className: tw('text-center', classNames?.footer), children: _jsx(Link, { className: classNames?.link, href: "/auth/login", children: "Back" }) })] }) }), _jsx("div", { className: tw(sentCount > 0 ? 'flex' : 'hidden'), children: _jsxs("div", { className: tw(classNames?.form), children: [_jsx("h1", { className: classNames?.title, children: "Check Your Email" }), sentCount === 1 ? (_jsxs(Fragment, { children: [_jsxs("p", { className: "text-sm", children: ["If ", _jsx("strong", { children: formData.email }), " matches an email we have on file, then we've sent you an email containing further instructions for resetting your password."] }), _jsxs("p", { className: "text-sm", children: ["If you haven't received an email in 5 minutes, check your spam,", ' ', _jsx(Link, { className: classNames?.link, onClick: handleResend, children: "resend" }), ", or", ' ', _jsx(Link, { className: classNames?.link, onClick: handleReset, children: "try a different email address" }), "."] })] })) : (_jsxs(Fragment, { children: [_jsxs("p", { className: "text-sm", children: ["We've resent password reset instructions to", ' ', _jsx("strong", { children: formData.email }), ", if it is an email we have on file."] }), _jsxs("p", { className: "text-sm", children: ["Please check again. If you still haven't received an email,", ' ', _jsx(Link, { className: classNames?.link, onClick: handleReset, children: "try a different email address" }), "."] })] }))] }) })] }));
|
|
27
27
|
}
|
|
28
28
|
export default PasswordForm;
|
|
@@ -15,6 +15,6 @@ function PasswordResetForm({ classNames, token, }) {
|
|
|
15
15
|
},
|
|
16
16
|
toasts: { success: false },
|
|
17
17
|
});
|
|
18
|
-
return (_jsxs(Form, { ...formProps, classNames: { root: classNames?.form }, children: [_jsx("h1", { className: classNames?.title, children: "Reset Your Password" }), _jsx("div", { className: "relative", children: _jsx(PasswordFormField, { ...fieldProps('password', 'New Password') }) }), _jsx("div", { className: "mt-8", children: _jsx(FormSubmit, { isLoading: isLoading, children: "Reset Password" }) })] }));
|
|
18
|
+
return (_jsxs(Form, { ...formProps, classNames: { root: classNames?.form }, children: [_jsx("h1", { className: classNames?.title, children: "Reset Your Password" }), _jsx("div", { className: "relative", children: _jsx(PasswordFormField, { ...fieldProps('password', 'New Password') }) }), _jsx("div", { className: "mt-8", children: _jsx(FormSubmit, { isFullWidth: true, isLoading: isLoading, children: "Reset Password" }) })] }));
|
|
19
19
|
}
|
|
20
20
|
export default PasswordResetForm;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment } from 'react';
|
|
4
|
+
import { Form, FormSubmit, Link, PasswordFormField, TextFormField } from '@sqrzro/components';
|
|
5
|
+
import { useForm } from '@sqrzro/hooks';
|
|
6
|
+
import { handleSubmit } from './server';
|
|
7
|
+
function LoginForm() {
|
|
8
|
+
const { fieldProps, formData, formProps } = useForm({
|
|
9
|
+
onSubmit: handleSubmit,
|
|
10
|
+
});
|
|
11
|
+
return (_jsx(Fragment, { children: _jsxs(Form, { ...formProps, children: [_jsx(TextFormField, { ...fieldProps('email'), hasAssistiveError: true }), _jsx(PasswordFormField, { ...fieldProps('password'), hasAssistiveError: true }), _jsx(FormSubmit, { isFullWidth: true, children: "Sign In" }), _jsx("footer", { children: _jsx(Link, { href: `/auth/password${formData.email ? `?email=${formData.email}` : ''}`, children: "Forgot Password?" }) })] }) }));
|
|
12
|
+
}
|
|
13
|
+
export default LoginForm;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment } from 'react';
|
|
4
|
+
import { Link } from '@sqrzro/ui/components';
|
|
5
|
+
import { Form, FormSubmit, PasswordFormField, TextFormField, useForm } from '@sqrzro/ui/forms';
|
|
6
|
+
import submit from './server';
|
|
7
|
+
function LoginForm() {
|
|
8
|
+
const { fieldProps, formData, formProps } = useForm({
|
|
9
|
+
onSubmit: submit,
|
|
10
|
+
});
|
|
11
|
+
return (_jsx(Fragment, { children: _jsxs(Form, { ...formProps, children: [_jsx(TextFormField, { ...fieldProps('email'), hasAssistiveError: true }), _jsx(PasswordFormField, { ...fieldProps('password'), hasAssistiveError: true }), _jsx(FormSubmit, { children: "Sign In" }), _jsx("footer", { children: _jsx(Link, { href: `/auth/password${formData.email ? `?email=${formData.email}` : ''}`, children: "Forgot Password?" }) })] }) }));
|
|
12
|
+
}
|
|
13
|
+
export default LoginForm;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
import { createSession, validateUser } from '@sqrzro/server/auth';
|
|
3
|
+
import { submitForm } from '@sqrzro/server/forms';
|
|
4
|
+
import { redirect } from 'next/navigation';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
const schema = z
|
|
7
|
+
.object({
|
|
8
|
+
email: z.email(),
|
|
9
|
+
password: z.string(),
|
|
10
|
+
redirect: z.string().optional(),
|
|
11
|
+
})
|
|
12
|
+
.required({ email: true, password: true });
|
|
13
|
+
async function fn(data) {
|
|
14
|
+
const userID = await validateUser(data.email, data.password);
|
|
15
|
+
await createSession(userID);
|
|
16
|
+
redirect('/');
|
|
17
|
+
}
|
|
18
|
+
async function submit(formData) {
|
|
19
|
+
return submitForm({
|
|
20
|
+
fn,
|
|
21
|
+
formData,
|
|
22
|
+
schema,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export default submit;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment } from 'react';
|
|
4
|
+
import { Form, FormSubmit, TextFormField } from '@sqrzro/components';
|
|
5
|
+
import { useForm } from '@sqrzro/hooks';
|
|
6
|
+
import { handleSubmit } from './server';
|
|
7
|
+
function PasswordForm() {
|
|
8
|
+
const { fieldProps, formProps } = useForm({
|
|
9
|
+
onSubmit: handleSubmit,
|
|
10
|
+
});
|
|
11
|
+
return (_jsx(Fragment, { children: _jsxs(Form, { ...formProps, children: [_jsx(TextFormField, { ...fieldProps('email'), hasAssistiveError: true }), _jsx(FormSubmit, { isFullWidth: true, children: "Send Email" })] }) }));
|
|
12
|
+
}
|
|
13
|
+
export default PasswordForm;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment } from 'react';
|
|
4
|
+
import { Form, FormSubmit, TextFormField, useForm } from '@sqrzro/ui/forms';
|
|
5
|
+
import submit from './server';
|
|
6
|
+
function PasswordForm() {
|
|
7
|
+
const { fieldProps, formProps } = useForm({
|
|
8
|
+
onSubmit: submit,
|
|
9
|
+
});
|
|
10
|
+
return (_jsx(Fragment, { children: _jsxs(Form, { ...formProps, children: [_jsx(TextFormField, { ...fieldProps('email'), hasAssistiveError: true }), _jsx(FormSubmit, { isFullWidth: true, children: "Send Email" })] }) }));
|
|
11
|
+
}
|
|
12
|
+
export default PasswordForm;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
import { createReset } from '@sqrzro/server/auth';
|
|
3
|
+
import { submitForm } from '@sqrzro/server/forms';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
const schema = z
|
|
6
|
+
.object({
|
|
7
|
+
email: z.email(),
|
|
8
|
+
})
|
|
9
|
+
.required({ email: true });
|
|
10
|
+
async function fn(data) {
|
|
11
|
+
const token = await createReset('PASSWORD', data.email);
|
|
12
|
+
console.log(token);
|
|
13
|
+
}
|
|
14
|
+
async function submit(formData) {
|
|
15
|
+
return submitForm({
|
|
16
|
+
fn,
|
|
17
|
+
formData,
|
|
18
|
+
schema,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export default submit;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment } from 'react';
|
|
4
|
+
import { Form, FormSubmit, TextFormField } from '@sqrzro/components';
|
|
5
|
+
import { useForm } from '@sqrzro/hooks';
|
|
6
|
+
import { handleSubmit } from './server';
|
|
7
|
+
function PasswordResetForm({ token }) {
|
|
8
|
+
const { fieldProps, formProps } = useForm({
|
|
9
|
+
defaults: { token },
|
|
10
|
+
onSubmit: handleSubmit,
|
|
11
|
+
});
|
|
12
|
+
return (_jsx(Fragment, { children: _jsxs(Form, { ...formProps, children: [_jsx(TextFormField, { ...fieldProps('password'), hasAssistiveError: true }), _jsx(FormSubmit, { isFullWidth: true, children: "Reset Password" })] }) }));
|
|
13
|
+
}
|
|
14
|
+
export default PasswordResetForm;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment } from 'react';
|
|
4
|
+
import { Form, FormSubmit, PasswordFormField, useForm } from '@sqrzro/ui/forms';
|
|
5
|
+
import submit from './server';
|
|
6
|
+
function PasswordResetForm({ token }) {
|
|
7
|
+
const { fieldProps, formProps } = useForm({
|
|
8
|
+
defaults: { token },
|
|
9
|
+
onSubmit: submit,
|
|
10
|
+
});
|
|
11
|
+
return (_jsx(Fragment, { children: _jsxs(Form, { ...formProps, children: [_jsx(PasswordFormField, { ...fieldProps('password') }), _jsx(FormSubmit, { isFullWidth: true, children: "Reset Password" })] }) }));
|
|
12
|
+
}
|
|
13
|
+
export default PasswordResetForm;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
import { updatePasswordWithToken } from '@sqrzro/server/auth';
|
|
3
|
+
import { submitForm } from '@sqrzro/server/forms';
|
|
4
|
+
import { redirect } from 'next/navigation';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
const schema = z
|
|
7
|
+
.object({
|
|
8
|
+
password: z.string(),
|
|
9
|
+
token: z.string().regex(/[A-Za-z0-9]{48}/u),
|
|
10
|
+
})
|
|
11
|
+
.required({ password: true, token: true });
|
|
12
|
+
async function fn(data) {
|
|
13
|
+
await updatePasswordWithToken(data.token, data.password);
|
|
14
|
+
return redirect('/auth/login');
|
|
15
|
+
}
|
|
16
|
+
async function submit(formData) {
|
|
17
|
+
return submitForm({
|
|
18
|
+
fn,
|
|
19
|
+
formData,
|
|
20
|
+
schema,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export default submit;
|