@sqrzro/auth 4.0.0-alpha.6 → 4.0.0-alpha.8
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 +48 -18
- package/dist/components/Auth/index.d.ts +5 -1
- package/dist/components/Auth/index.js +5 -5
- package/dist/components/Password/index.d.ts +3 -2
- package/dist/components/Password/index.js +3 -3
- package/dist/forms/LoginForm/index.d.ts +2 -1
- package/dist/forms/LoginForm/index.js +2 -2
- package/dist/forms/PasswordForm/index.d.ts +2 -1
- package/dist/forms/PasswordForm/index.js +1 -1
- package/dist/forms/PasswordResetForm/index.d.ts +3 -2
- package/dist/forms/PasswordResetForm/index.js +1 -1
- package/dist/forms/PasswordResetForm/server.js +1 -1
- package/dist/get-auth-proxy.d.ts +6 -0
- package/dist/get-auth-proxy.js +17 -0
- package/dist/handle-auth-proxy.d.ts +5 -0
- package/dist/handle-auth-proxy.js +14 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/dist/interfaces.d.ts +6 -0
- package/package.json +2 -2
- package/src/components/Auth/index.tsx +20 -9
- package/src/components/Password/index.tsx +8 -4
- package/src/forms/LoginForm/index.tsx +9 -3
- package/src/forms/PasswordForm/index.tsx +3 -1
- package/src/forms/PasswordResetForm/index.tsx +7 -2
- package/src/forms/PasswordResetForm/server.ts +1 -1
- package/src/get-auth-proxy.ts +34 -0
- package/src/index.ts +5 -1
- package/src/interfaces.ts +9 -1
- package/src/handle-proxy.ts +0 -23
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-dev.log
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
|
|
2
|
-
> @sqrzro/auth@4.0.0-alpha.
|
|
2
|
+
> @sqrzro/auth@4.0.0-alpha.8 dev /Users/richard/Sites/@sqrzro/sqrzro/packages/auth
|
|
3
3
|
> tsc --watch
|
|
4
4
|
|
|
5
|
-
[2J[3J[H[[90m2:
|
|
5
|
+
[2J[3J[H[[90m2:49:05 PM[0m] Starting compilation in watch mode...
|
|
6
6
|
|
|
7
|
-
[[90m2:
|
|
7
|
+
[[90m2:49:08 PM[0m] Found 0 errors. Watching for file changes.
|
|
8
8
|
|
|
9
|
-
[2J[3J[H[[90m2:
|
|
9
|
+
[2J[3J[H[[90m2:49:11 PM[0m] File change detected. Starting incremental compilation...
|
|
10
10
|
|
|
11
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
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';`
|
|
@@ -62,32 +62,62 @@
|
|
|
62
62
|
[7m4[0m import { FormResponse, submitForm } from '@sqrzro/server/forms';
|
|
63
63
|
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~~[0m
|
|
64
64
|
|
|
65
|
-
[96msrc/
|
|
65
|
+
[96msrc/get-auth-proxy.ts[0m:[93m1[0m:[93m34[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.
|
|
66
66
|
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';`
|
|
67
67
|
|
|
68
|
-
[7m1[0m import {
|
|
69
|
-
[7m [0m [91m
|
|
68
|
+
[7m1[0m import type { AuthSession } from '@sqrzro/server/auth';
|
|
69
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~[0m
|
|
70
70
|
|
|
71
|
-
[[
|
|
71
|
+
[96msrc/get-auth-proxy.ts[0m:[93m2[0m:[93m36[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module '@sqrzro/server/proxy'. '/Users/richard/Sites/@sqrzro/sqrzro/packages/server/dist/proxy/index.js' implicitly has an 'any' type.
|
|
72
|
+
Try `npm i --save-dev @types/sqrzro__server` if it exists or add a new declaration (.d.ts) file containing `declare module '@sqrzro/server/proxy';`
|
|
72
73
|
|
|
73
|
-
[
|
|
74
|
+
[7m2[0m import type { ProxyRedirect } from '@sqrzro/server/proxy';
|
|
75
|
+
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~~[0m
|
|
74
76
|
|
|
75
|
-
[[90m2:
|
|
77
|
+
[[90m2:49:11 PM[0m] Found 11 errors. Watching for file changes.
|
|
76
78
|
|
|
77
|
-
[2J[3J[H[[90m2:
|
|
79
|
+
[2J[3J[H[[90m2:49:15 PM[0m] File change detected. Starting incremental compilation...
|
|
78
80
|
|
|
79
|
-
[[90m2:
|
|
81
|
+
[[90m2:49:15 PM[0m] Found 0 errors. Watching for file changes.
|
|
80
82
|
|
|
81
|
-
[2J[3J[H[[90m2:
|
|
83
|
+
[2J[3J[H[[90m2:49:47 PM[0m] File change detected. Starting incremental compilation...
|
|
82
84
|
|
|
83
|
-
[[90m2:
|
|
85
|
+
[[90m2:49:47 PM[0m] Found 0 errors. Watching for file changes.
|
|
84
86
|
|
|
85
|
-
[2J[3J[H[[90m2:
|
|
87
|
+
[2J[3J[H[[90m2:49:52 PM[0m] File change detected. Starting incremental compilation...
|
|
86
88
|
|
|
87
|
-
[[90m2:
|
|
89
|
+
[[90m2:49:52 PM[0m] Found 0 errors. Watching for file changes.
|
|
88
90
|
|
|
89
|
-
[2J[3J[H[[90m2:
|
|
91
|
+
[2J[3J[H[[90m2:50:44 PM[0m] File change detected. Starting incremental compilation...
|
|
90
92
|
|
|
91
|
-
[[90m2:
|
|
93
|
+
[[90m2:50:44 PM[0m] Found 0 errors. Watching for file changes.
|
|
94
|
+
|
|
95
|
+
[2J[3J[H[[90m2:50:48 PM[0m] File change detected. Starting incremental compilation...
|
|
96
|
+
|
|
97
|
+
[[90m2:50:48 PM[0m] Found 0 errors. Watching for file changes.
|
|
98
|
+
|
|
99
|
+
[2J[3J[H[[90m2:59:21 PM[0m] File change detected. Starting incremental compilation...
|
|
100
|
+
|
|
101
|
+
[[90m2:59:21 PM[0m] Found 0 errors. Watching for file changes.
|
|
102
|
+
|
|
103
|
+
[2J[3J[H[[90m2:59:25 PM[0m] File change detected. Starting incremental compilation...
|
|
104
|
+
|
|
105
|
+
[[90m2:59:25 PM[0m] Found 0 errors. Watching for file changes.
|
|
106
|
+
|
|
107
|
+
[2J[3J[H[[90m2:59:51 PM[0m] File change detected. Starting incremental compilation...
|
|
108
|
+
|
|
109
|
+
[[90m2:59:51 PM[0m] Found 0 errors. Watching for file changes.
|
|
110
|
+
|
|
111
|
+
[2J[3J[H[[90m3:00:13 PM[0m] File change detected. Starting incremental compilation...
|
|
112
|
+
|
|
113
|
+
[[90m3:00:13 PM[0m] Found 0 errors. Watching for file changes.
|
|
114
|
+
|
|
115
|
+
[2J[3J[H[[90m3:00:21 PM[0m] File change detected. Starting incremental compilation...
|
|
116
|
+
|
|
117
|
+
[[90m3:00:21 PM[0m] Found 0 errors. Watching for file changes.
|
|
118
|
+
|
|
119
|
+
[2J[3J[H[[90m3:04:21 PM[0m] File change detected. Starting incremental compilation...
|
|
120
|
+
|
|
121
|
+
[[90m3:04:21 PM[0m] Found 0 errors. Watching for file changes.
|
|
92
122
|
|
|
93
123
|
[41m[30m ELIFECYCLE [39m[49m [31mCommand failed.[39m
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import type { NextPageProps } from '@sqrzro/ui/utility';
|
|
2
|
-
|
|
2
|
+
import type { AuthClassNameProps } from '../../interfaces';
|
|
3
|
+
export interface AuthProps extends AuthClassNameProps, NextPageProps {
|
|
4
|
+
logo?: React.ReactElement;
|
|
5
|
+
}
|
|
6
|
+
declare function Auth({ classNames, logo, ...props }: AuthProps): React.ReactElement;
|
|
3
7
|
export default Auth;
|
|
@@ -3,23 +3,23 @@ import { Suspense } from 'react';
|
|
|
3
3
|
import { notFound } from 'next/navigation';
|
|
4
4
|
import LoginForm from '../../forms/LoginForm';
|
|
5
5
|
import Password from '../Password';
|
|
6
|
-
async function AuthComponent({ params, searchParams }) {
|
|
6
|
+
async function AuthComponent({ classNames, params, searchParams, }) {
|
|
7
7
|
const awaitedParams = await params;
|
|
8
8
|
if (!awaitedParams || !Array.isArray(awaitedParams.auth) || awaitedParams.auth.length !== 1) {
|
|
9
9
|
return notFound();
|
|
10
10
|
}
|
|
11
11
|
if (awaitedParams.auth[0] === 'login') {
|
|
12
|
-
return _jsx(LoginForm, {});
|
|
12
|
+
return _jsx(LoginForm, { classNames: classNames });
|
|
13
13
|
}
|
|
14
14
|
if (awaitedParams.auth[0] === 'mfa') {
|
|
15
15
|
return _jsx("div", { children: "[MFA NOT DONE]" });
|
|
16
16
|
}
|
|
17
17
|
if (awaitedParams.auth[0] === 'password') {
|
|
18
|
-
return _jsx(Password, { searchParams: searchParams });
|
|
18
|
+
return _jsx(Password, { classNames: classNames, searchParams: searchParams });
|
|
19
19
|
}
|
|
20
20
|
return notFound();
|
|
21
21
|
}
|
|
22
|
-
function Auth(props) {
|
|
23
|
-
return (_jsxs("div", { children: ["
|
|
22
|
+
function Auth({ classNames, logo, ...props }) {
|
|
23
|
+
return (_jsxs("div", { className: classNames?.root, children: [_jsx("div", { className: classNames?.logo, children: logo }), _jsx("div", { className: classNames?.panel, children: _jsx(Suspense, { children: _jsx(AuthComponent, { classNames: classNames, ...props }) }) })] }));
|
|
24
24
|
}
|
|
25
25
|
export default Auth;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AuthClassNameProps } from '../../interfaces';
|
|
2
|
+
interface PasswordProps extends AuthClassNameProps {
|
|
2
3
|
searchParams?: Promise<Record<string, string>> | null;
|
|
3
4
|
}
|
|
4
|
-
declare function Password({ searchParams }: Readonly<PasswordProps>): Promise<React.ReactElement>;
|
|
5
|
+
declare function Password({ classNames, searchParams, }: Readonly<PasswordProps>): Promise<React.ReactElement>;
|
|
5
6
|
export default Password;
|
|
@@ -2,17 +2,17 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { validateReset } from '@sqrzro/server/auth';
|
|
3
3
|
import PasswordForm from '../../forms/PasswordForm';
|
|
4
4
|
import PasswordResetForm from '../../forms/PasswordResetForm';
|
|
5
|
-
async function Password({ searchParams }) {
|
|
5
|
+
async function Password({ classNames, searchParams, }) {
|
|
6
6
|
const awaitedSearchParams = await searchParams;
|
|
7
7
|
if (awaitedSearchParams?.token) {
|
|
8
8
|
const validated = await validateReset('PASSWORD', awaitedSearchParams.token);
|
|
9
9
|
if (validated) {
|
|
10
|
-
return _jsx(PasswordResetForm, { token: awaitedSearchParams.token });
|
|
10
|
+
return _jsx(PasswordResetForm, { token: awaitedSearchParams.token, classNames: classNames });
|
|
11
11
|
}
|
|
12
12
|
else {
|
|
13
13
|
return _jsx("div", { children: "Invalid or Expired Token" });
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
return _jsx(PasswordForm, {});
|
|
16
|
+
return _jsx(PasswordForm, { classNames: classNames });
|
|
17
17
|
}
|
|
18
18
|
export default Password;
|
|
@@ -4,10 +4,10 @@ import { Fragment } from 'react';
|
|
|
4
4
|
import { Link } from '@sqrzro/ui/components';
|
|
5
5
|
import { Form, FormSubmit, PasswordFormField, TextFormField, useForm } from '@sqrzro/ui/forms';
|
|
6
6
|
import submit from './server';
|
|
7
|
-
function LoginForm() {
|
|
7
|
+
function LoginForm({ classNames }) {
|
|
8
8
|
const { fieldProps, formData, formProps } = useForm({
|
|
9
9
|
onSubmit: submit,
|
|
10
10
|
});
|
|
11
|
-
return (
|
|
11
|
+
return (_jsxs(Fragment, { children: [_jsx("h1", { className: classNames?.title, children: "Sign in to continue" }), _jsxs(Form, { ...formProps, children: [_jsx(TextFormField, { ...fieldProps('email'), hasAssistiveError: true }), _jsx(PasswordFormField, { ...fieldProps('password'), hasAssistiveError: true }), _jsx("div", { className: classNames?.actions, children: _jsx(FormSubmit, { isFullWidth: true, children: "Sign In" }) }), _jsx("footer", { className: classNames?.footer, children: _jsx(Link, { className: classNames?.link, href: `/auth/password${formData.email ? `?email=${formData.email}` : ''}`, children: "Forgot Password?" }) })] })] }));
|
|
12
12
|
}
|
|
13
13
|
export default LoginForm;
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { Fragment } from 'react';
|
|
4
4
|
import { Form, FormSubmit, TextFormField, useForm } from '@sqrzro/ui/forms';
|
|
5
5
|
import submit from './server';
|
|
6
|
-
function PasswordForm() {
|
|
6
|
+
function PasswordForm({ classNames }) {
|
|
7
7
|
const { fieldProps, formProps } = useForm({
|
|
8
8
|
onSubmit: submit,
|
|
9
9
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AuthClassNameProps } from '../../interfaces';
|
|
2
|
+
interface PasswordResetFormProps extends AuthClassNameProps {
|
|
2
3
|
token: string;
|
|
3
4
|
}
|
|
4
|
-
declare function PasswordResetForm({ token }: Readonly<PasswordResetFormProps>): React.ReactElement | null;
|
|
5
|
+
declare function PasswordResetForm({ classNames, token, }: Readonly<PasswordResetFormProps>): React.ReactElement | null;
|
|
5
6
|
export default PasswordResetForm;
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { Fragment } from 'react';
|
|
4
4
|
import { Form, FormSubmit, PasswordFormField, useForm } from '@sqrzro/ui/forms';
|
|
5
5
|
import submit from './server';
|
|
6
|
-
function PasswordResetForm({ token }) {
|
|
6
|
+
function PasswordResetForm({ classNames, token, }) {
|
|
7
7
|
const { fieldProps, formProps } = useForm({
|
|
8
8
|
defaults: { token },
|
|
9
9
|
onSubmit: submit,
|
|
@@ -10,7 +10,7 @@ const schema = z
|
|
|
10
10
|
})
|
|
11
11
|
.required({ password: true, token: true });
|
|
12
12
|
async function fn(data) {
|
|
13
|
-
await updatePasswordWithToken(data.token, data.password);
|
|
13
|
+
await updatePasswordWithToken('PASSWORD', data.token, data.password);
|
|
14
14
|
return redirect('/auth/login');
|
|
15
15
|
}
|
|
16
16
|
async function submit(formData) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AuthSession } from '@sqrzro/server/auth';
|
|
2
|
+
import type { ProxyRedirect } from '@sqrzro/server/proxy';
|
|
3
|
+
import type { NextRequest } from 'next/server';
|
|
4
|
+
import type { AuthConfigObject } from './interfaces';
|
|
5
|
+
declare function getAuthProxy(config?: AuthConfigObject): (session: AuthSession | null, request: NextRequest) => Promise<ProxyRedirect | null>;
|
|
6
|
+
export default getAuthProxy;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
async function handleAuthProxy(session, request, config) {
|
|
2
|
+
const pathname = request.nextUrl.pathname;
|
|
3
|
+
if (session) {
|
|
4
|
+
if (pathname.startsWith('/auth')) {
|
|
5
|
+
return { redirect: '/' };
|
|
6
|
+
}
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
if (pathname.startsWith('/auth') || config?.allow?.includes(pathname)) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return { redirect: '/auth/login' };
|
|
13
|
+
}
|
|
14
|
+
function getAuthProxy(config) {
|
|
15
|
+
return (session, request) => handleAuthProxy(session, request, config);
|
|
16
|
+
}
|
|
17
|
+
export default getAuthProxy;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AuthSession } from '@sqrzro/server/auth';
|
|
2
|
+
import type { ProxyRedirect } from '@sqrzro/server/proxy';
|
|
3
|
+
import type { NextRequest } from 'next/server';
|
|
4
|
+
declare function handleAuthProxy(session: AuthSession | null, request: NextRequest): Promise<ProxyRedirect | null>;
|
|
5
|
+
export default handleAuthProxy;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
async function handleAuthProxy(session, request) {
|
|
2
|
+
const pathname = request.nextUrl.pathname;
|
|
3
|
+
if (session) {
|
|
4
|
+
if (pathname.startsWith('/auth')) {
|
|
5
|
+
return { redirect: '/' };
|
|
6
|
+
}
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
if (pathname.startsWith('/auth')) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return { redirect: '/auth/login' };
|
|
13
|
+
}
|
|
14
|
+
export default handleAuthProxy;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type { AuthClassNames, AuthConfigObject } from './interfaces';
|
|
2
|
+
export type { AuthProps } from './components/Auth';
|
|
1
3
|
export { default as Auth } from './components/Auth';
|
|
2
4
|
export { default as LogoutButton } from './components/LogoutButton';
|
|
3
|
-
export { default as
|
|
5
|
+
export { default as getAuthProxy } from './get-auth-proxy';
|
package/dist/index.js
CHANGED
package/dist/interfaces.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export interface AuthConfigObject {
|
|
2
|
+
allow?: string[];
|
|
3
|
+
}
|
|
1
4
|
export interface AuthClassNames {
|
|
2
5
|
actions: string;
|
|
3
6
|
footer: string;
|
|
@@ -8,3 +11,6 @@ export interface AuthClassNames {
|
|
|
8
11
|
panel: string;
|
|
9
12
|
title: string;
|
|
10
13
|
}
|
|
14
|
+
export interface AuthClassNameProps {
|
|
15
|
+
classNames?: Partial<AuthClassNames>;
|
|
16
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqrzro/auth",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.0.0-alpha.
|
|
4
|
+
"version": "4.0.0-alpha.8",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"zod": "^4.3.6",
|
|
9
|
-
"@sqrzro/server": "^4.0.0-alpha.
|
|
9
|
+
"@sqrzro/server": "^4.0.0-alpha.18",
|
|
10
10
|
"@sqrzro/ui": "^4.0.0-alpha.13"
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
@@ -4,10 +4,19 @@ import type { NextPageProps } from '@sqrzro/ui/utility';
|
|
|
4
4
|
import { notFound } from 'next/navigation';
|
|
5
5
|
|
|
6
6
|
import LoginForm from '../../forms/LoginForm';
|
|
7
|
+
import type { AuthClassNameProps } from '../../interfaces';
|
|
7
8
|
|
|
8
9
|
import Password from '../Password';
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
export interface AuthProps extends AuthClassNameProps, NextPageProps {
|
|
12
|
+
logo?: React.ReactElement;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function AuthComponent({
|
|
16
|
+
classNames,
|
|
17
|
+
params,
|
|
18
|
+
searchParams,
|
|
19
|
+
}: AuthProps): Promise<React.ReactElement> {
|
|
11
20
|
const awaitedParams = await params;
|
|
12
21
|
|
|
13
22
|
if (!awaitedParams || !Array.isArray(awaitedParams.auth) || awaitedParams.auth.length !== 1) {
|
|
@@ -15,7 +24,7 @@ async function AuthComponent({ params, searchParams }: NextPageProps): Promise<R
|
|
|
15
24
|
}
|
|
16
25
|
|
|
17
26
|
if (awaitedParams.auth[0] === 'login') {
|
|
18
|
-
return <LoginForm />;
|
|
27
|
+
return <LoginForm classNames={classNames} />;
|
|
19
28
|
}
|
|
20
29
|
|
|
21
30
|
if (awaitedParams.auth[0] === 'mfa') {
|
|
@@ -23,19 +32,21 @@ async function AuthComponent({ params, searchParams }: NextPageProps): Promise<R
|
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
if (awaitedParams.auth[0] === 'password') {
|
|
26
|
-
return <Password searchParams={searchParams} />;
|
|
35
|
+
return <Password classNames={classNames} searchParams={searchParams} />;
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
return notFound();
|
|
30
39
|
}
|
|
31
40
|
|
|
32
|
-
function Auth(props:
|
|
41
|
+
function Auth({ classNames, logo, ...props }: AuthProps): React.ReactElement {
|
|
33
42
|
return (
|
|
34
|
-
<div>
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
|
|
43
|
+
<div className={classNames?.root}>
|
|
44
|
+
<div className={classNames?.logo}>{logo}</div>
|
|
45
|
+
<div className={classNames?.panel}>
|
|
46
|
+
<Suspense>
|
|
47
|
+
<AuthComponent classNames={classNames} {...props} />
|
|
48
|
+
</Suspense>
|
|
49
|
+
</div>
|
|
39
50
|
</div>
|
|
40
51
|
);
|
|
41
52
|
}
|
|
@@ -2,25 +2,29 @@ import { validateReset } from '@sqrzro/server/auth';
|
|
|
2
2
|
|
|
3
3
|
import PasswordForm from '../../forms/PasswordForm';
|
|
4
4
|
import PasswordResetForm from '../../forms/PasswordResetForm';
|
|
5
|
+
import type { AuthClassNameProps } from '../../interfaces';
|
|
5
6
|
|
|
6
|
-
interface PasswordProps {
|
|
7
|
+
interface PasswordProps extends AuthClassNameProps {
|
|
7
8
|
searchParams?: Promise<Record<string, string>> | null;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
async function Password({
|
|
11
|
+
async function Password({
|
|
12
|
+
classNames,
|
|
13
|
+
searchParams,
|
|
14
|
+
}: Readonly<PasswordProps>): Promise<React.ReactElement> {
|
|
11
15
|
const awaitedSearchParams = await searchParams;
|
|
12
16
|
|
|
13
17
|
if (awaitedSearchParams?.token) {
|
|
14
18
|
const validated = await validateReset('PASSWORD', awaitedSearchParams.token);
|
|
15
19
|
|
|
16
20
|
if (validated) {
|
|
17
|
-
return <PasswordResetForm token={awaitedSearchParams.token} />;
|
|
21
|
+
return <PasswordResetForm token={awaitedSearchParams.token} classNames={classNames} />;
|
|
18
22
|
} else {
|
|
19
23
|
return <div>Invalid or Expired Token</div>;
|
|
20
24
|
}
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
return <PasswordForm />;
|
|
27
|
+
return <PasswordForm classNames={classNames} />;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
export default Password;
|
|
@@ -5,21 +5,27 @@ import { Fragment } from 'react';
|
|
|
5
5
|
import { Link } from '@sqrzro/ui/components';
|
|
6
6
|
import { Form, FormSubmit, PasswordFormField, TextFormField, useForm } from '@sqrzro/ui/forms';
|
|
7
7
|
|
|
8
|
+
import type { AuthClassNameProps } from '../../interfaces';
|
|
9
|
+
|
|
8
10
|
import submit from './server';
|
|
9
11
|
|
|
10
|
-
function LoginForm(): React.ReactElement | null {
|
|
12
|
+
function LoginForm({ classNames }: AuthClassNameProps): React.ReactElement | null {
|
|
11
13
|
const { fieldProps, formData, formProps } = useForm({
|
|
12
14
|
onSubmit: submit,
|
|
13
15
|
});
|
|
14
16
|
|
|
15
17
|
return (
|
|
16
18
|
<Fragment>
|
|
19
|
+
<h1 className={classNames?.title}>Sign in to continue</h1>
|
|
17
20
|
<Form {...formProps}>
|
|
18
21
|
<TextFormField {...fieldProps('email')} hasAssistiveError />
|
|
19
22
|
<PasswordFormField {...fieldProps('password')} hasAssistiveError />
|
|
20
|
-
<
|
|
21
|
-
|
|
23
|
+
<div className={classNames?.actions}>
|
|
24
|
+
<FormSubmit isFullWidth>Sign In</FormSubmit>
|
|
25
|
+
</div>
|
|
26
|
+
<footer className={classNames?.footer}>
|
|
22
27
|
<Link
|
|
28
|
+
className={classNames?.link}
|
|
23
29
|
href={`/auth/password${formData.email ? `?email=${formData.email}` : ''}`}
|
|
24
30
|
>
|
|
25
31
|
Forgot Password?
|
|
@@ -4,9 +4,11 @@ import { Fragment } from 'react';
|
|
|
4
4
|
|
|
5
5
|
import { Form, FormSubmit, TextFormField, useForm } from '@sqrzro/ui/forms';
|
|
6
6
|
|
|
7
|
+
import type { AuthClassNameProps } from '../../interfaces';
|
|
8
|
+
|
|
7
9
|
import submit from './server';
|
|
8
10
|
|
|
9
|
-
function PasswordForm(): React.ReactElement | null {
|
|
11
|
+
function PasswordForm({ classNames }: AuthClassNameProps): React.ReactElement | null {
|
|
10
12
|
const { fieldProps, formProps } = useForm({
|
|
11
13
|
onSubmit: submit,
|
|
12
14
|
});
|
|
@@ -4,13 +4,18 @@ import { Fragment } from 'react';
|
|
|
4
4
|
|
|
5
5
|
import { Form, FormSubmit, PasswordFormField, useForm } from '@sqrzro/ui/forms';
|
|
6
6
|
|
|
7
|
+
import type { AuthClassNameProps } from '../../interfaces';
|
|
8
|
+
|
|
7
9
|
import submit from './server';
|
|
8
10
|
|
|
9
|
-
interface PasswordResetFormProps {
|
|
11
|
+
interface PasswordResetFormProps extends AuthClassNameProps {
|
|
10
12
|
token: string;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
function PasswordResetForm({
|
|
15
|
+
function PasswordResetForm({
|
|
16
|
+
classNames,
|
|
17
|
+
token,
|
|
18
|
+
}: Readonly<PasswordResetFormProps>): React.ReactElement | null {
|
|
14
19
|
const { fieldProps, formProps } = useForm({
|
|
15
20
|
defaults: { token },
|
|
16
21
|
onSubmit: submit,
|
|
@@ -15,7 +15,7 @@ const schema = z
|
|
|
15
15
|
.required({ password: true, token: true });
|
|
16
16
|
|
|
17
17
|
async function fn(data: PasswordResetFormFields): Promise<void> {
|
|
18
|
-
await updatePasswordWithToken(data.token, data.password);
|
|
18
|
+
await updatePasswordWithToken('PASSWORD', data.token, data.password);
|
|
19
19
|
return redirect('/auth/login');
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AuthSession } from '@sqrzro/server/auth';
|
|
2
|
+
import type { ProxyRedirect } from '@sqrzro/server/proxy';
|
|
3
|
+
import type { NextRequest } from 'next/server';
|
|
4
|
+
|
|
5
|
+
import type { AuthConfigObject } from './interfaces';
|
|
6
|
+
|
|
7
|
+
async function handleAuthProxy(
|
|
8
|
+
session: AuthSession | null,
|
|
9
|
+
request: NextRequest,
|
|
10
|
+
config?: AuthConfigObject
|
|
11
|
+
): Promise<ProxyRedirect | null> {
|
|
12
|
+
const pathname = request.nextUrl.pathname;
|
|
13
|
+
|
|
14
|
+
if (session) {
|
|
15
|
+
if (pathname.startsWith('/auth')) {
|
|
16
|
+
return { redirect: '/' };
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (pathname.startsWith('/auth') || config?.allow?.includes(pathname)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { redirect: '/auth/login' };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getAuthProxy(
|
|
29
|
+
config?: AuthConfigObject
|
|
30
|
+
): (session: AuthSession | null, request: NextRequest) => Promise<ProxyRedirect | null> {
|
|
31
|
+
return (session, request) => handleAuthProxy(session, request, config);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default getAuthProxy;
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
export type { AuthClassNames, AuthConfigObject } from './interfaces';
|
|
2
|
+
|
|
3
|
+
export type { AuthProps } from './components/Auth';
|
|
1
4
|
export { default as Auth } from './components/Auth';
|
|
5
|
+
|
|
2
6
|
export { default as LogoutButton } from './components/LogoutButton';
|
|
3
7
|
|
|
4
|
-
export { default as
|
|
8
|
+
export { default as getAuthProxy } from './get-auth-proxy';
|
package/src/interfaces.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export interface AuthConfigObject {
|
|
2
|
+
allow?: string[];
|
|
3
|
+
}
|
|
4
|
+
|
|
1
5
|
export interface AuthClassNames {
|
|
2
6
|
actions: string;
|
|
3
7
|
footer: string;
|
|
@@ -7,4 +11,8 @@ export interface AuthClassNames {
|
|
|
7
11
|
root: string;
|
|
8
12
|
panel: string;
|
|
9
13
|
title: string;
|
|
10
|
-
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AuthClassNameProps {
|
|
17
|
+
classNames?: Partial<AuthClassNames>;
|
|
18
|
+
}
|
package/src/handle-proxy.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { validateSession } from '@sqrzro/server/auth';
|
|
2
|
-
import { NextResponse } from 'next/server';
|
|
3
|
-
import type { NextRequest } from 'next/server';
|
|
4
|
-
|
|
5
|
-
async function handleProxy(request: NextRequest): Promise<NextResponse> {
|
|
6
|
-
const pathname = request.nextUrl.pathname;
|
|
7
|
-
const validated = await validateSession(request.cookies);
|
|
8
|
-
|
|
9
|
-
if (validated) {
|
|
10
|
-
if (pathname.startsWith('/auth')) {
|
|
11
|
-
return NextResponse.redirect(new URL('/', request.url));
|
|
12
|
-
}
|
|
13
|
-
return NextResponse.next();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (pathname.startsWith('/auth')) {
|
|
17
|
-
return NextResponse.next();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return NextResponse.redirect(new URL('/auth/login', request.url));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export default handleProxy;
|