@sqrzro/auth 2.0.0-bz.4 → 2.0.0-bz.5

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,8 +1,5 @@
1
1
  /// <reference types="react" />
2
- import type { AuthClassNames } from '../Auth';
3
2
  export interface MFAFormProps {
4
- classNames?: Partial<AuthClassNames>;
5
- hasAssistiveSubmit?: boolean;
6
3
  }
7
- declare function MFAForm({ hasAssistiveSubmit }: Readonly<MFAFormProps>): React.ReactElement;
4
+ declare function MFAForm(): React.ReactElement;
8
5
  export default MFAForm;
@@ -1,29 +1,10 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useEffect, useState } from 'react';
4
- import { CodeFormField, Form, FormSubmit, tw } from '@sqrzro/components';
5
- import { useForm } from '@sqrzro/hooks';
6
- import { useRouter } from 'next/navigation';
3
+ import { CodeFormField, Form, FormSubmit } from '@sqrzro/components';
4
+ import useMFAForm from '../../hooks/useMFAForm';
7
5
  import { submitMFAForm } from '../../server';
8
- function MFAForm({ hasAssistiveSubmit }) {
9
- const router = useRouter();
10
- const [errorCount, setErrorCount] = useState(0);
11
- const { fieldProps, formProps, resetForm, submitForm } = useForm({
12
- onSubmit: submitMFAForm,
13
- onSuccess: () => {
14
- router.push('/');
15
- },
16
- onValidationError: () => {
17
- setErrorCount((count) => count + 1);
18
- },
19
- toasts: {
20
- success: false,
21
- validation: "There seems to be an issue with the code you've entered. Please try again.",
22
- },
23
- });
24
- useEffect(() => {
25
- resetForm();
26
- }, [errorCount]);
27
- return (_jsxs(Form, { ...formProps, children: [_jsx(CodeFormField, { ...fieldProps('token'), onFinalChange: submitForm, hasAssistiveLabel: true, isAutoFocus: true }, errorCount), _jsx("div", { className: tw(hasAssistiveSubmit ? 'sr-only' : ''), children: _jsx(FormSubmit, { children: "Verify" }) })] }));
6
+ function MFAForm() {
7
+ const { formProps, fieldProps, key, submitForm } = useMFAForm({ onSubmit: submitMFAForm });
8
+ return (_jsxs(Form, { ...formProps, children: [_jsx(CodeFormField, { ...fieldProps('token'), onFinalChange: submitForm, hasAssistiveLabel: true, isAutoFocus: true }, key), _jsx(FormSubmit, { children: "Verify" })] }));
28
9
  }
29
10
  export default MFAForm;
@@ -16,6 +16,6 @@ async function MFAPage({ classNames }) {
16
16
  if (!userHasMFA) {
17
17
  return _jsx(MFASetup, { classNames: classNames });
18
18
  }
19
- return (_jsxs("div", { children: [_jsx("h1", { className: tw('text-center', classNames?.title), children: "Multi-Factor Authentication" }), _jsx("p", { className: "mb-6 text-center", children: "Enter the 6-digit code listed in your authentication app:" }), _jsx(MFAForm, { classNames: classNames, hasAssistiveSubmit: true })] }));
19
+ return (_jsxs("div", { children: [_jsx("h1", { className: tw('text-center', classNames?.title), children: "Multi-Factor Authentication" }), _jsx("p", { className: "mb-6 text-center", children: "Enter the 6-digit code listed in your authentication app:" }), _jsx(MFAForm, {})] }));
20
20
  }
21
21
  export default MFAPage;
@@ -1,8 +1,8 @@
1
1
  /// <reference types="react" />
2
2
  import type { AuthClassNames } from '../Auth';
3
- export interface MFASetupProps {
3
+ export interface MFASetupFormProps {
4
4
  classNames?: Partial<AuthClassNames>;
5
5
  url: string;
6
6
  }
7
- declare function MFASetupForm({ classNames, url }: Readonly<MFASetupProps>): React.ReactElement;
7
+ declare function MFASetupForm({ classNames, url }: Readonly<MFASetupFormProps>): React.ReactElement;
8
8
  export default MFASetupForm;
@@ -12,9 +12,6 @@ function MFASetupForm({ classNames, url }) {
12
12
  event.preventDefault();
13
13
  setStep(1);
14
14
  }
15
- if (step === 1) {
16
- return (_jsxs(Fragment, { children: [_jsx("p", { className: "mb-4", children: "You'll need to setup an additional authentication step before you can continue." }), _jsx("figure", { className: "flex justify-center rounded border p-2", children: _jsx("img", { alt: "qrcode", src: url }) }), _jsxs("p", { className: "mb-4", children: [_jsx("strong", { children: "Step 1:" }), " Scan the QR code, or enter the secret below, in the Google Authentictor app."] }), _jsx(Button, { onClick: nextStep, variant: "primary", isFullWidth: true, children: "Continue" })] }));
17
- }
18
- return (_jsxs(Fragment, { children: [_jsxs("p", { className: "mb-4", children: [_jsx("strong", { children: "Step 2:" }), " Enter the 6-digit code listed in the Google Authenticator app:"] }), _jsx(MFAForm, {}), _jsx(Link, { className: classNames?.link, onClick: previousStep, children: "Scan QRcode again" })] }));
15
+ return (_jsxs(Fragment, { children: [_jsxs("div", { className: step === 1 ? null : 'sr-only', children: [_jsx("p", { className: "mb-4", children: "You'll need to setup an additional authentication step before you can continue." }), _jsx("figure", { className: "flex justify-center rounded border p-2", children: _jsx("img", { alt: "qrcode", src: url }) }), _jsxs("p", { className: "mb-4", children: [_jsx("strong", { children: "Step 1:" }), " Scan the QR code, or enter the secret below, in the Google Authentictor app."] }), _jsx(Button, { onClick: nextStep, variant: "primary", isFullWidth: true, children: "Continue" })] }), _jsxs("div", { className: step === 2 ? null : 'sr-only', children: [_jsxs("p", { className: "mb-4", children: [_jsx("strong", { children: "Step 2:" }), " Enter the 6-digit code listed in the Google Authenticator app:"] }), _jsx(MFAForm, {}), _jsx(Link, { className: classNames?.link, onClick: previousStep, children: "Scan QRcode again" })] })] }));
19
16
  }
20
17
  export default MFASetupForm;
@@ -0,0 +1,10 @@
1
+ import type { UseFormArgs, UseFormReturn } from '@sqrzro/hooks';
2
+ import type { MFAFormFields } from '../server';
3
+ export interface UseMFAFormArgs {
4
+ onSubmit: UseFormArgs<MFAFormFields, boolean>['onSubmit'];
5
+ }
6
+ export interface UseMFAFormReturn extends UseFormReturn<MFAFormFields> {
7
+ key: number;
8
+ }
9
+ declare function useMFAForm({ onSubmit }: UseMFAFormArgs): UseMFAFormReturn;
10
+ export default useMFAForm;
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+ import { useEffect, useState } from 'react';
3
+ import { useForm } from '@sqrzro/hooks';
4
+ import { useRouter } from 'next/navigation';
5
+ function useMFAForm({ onSubmit }) {
6
+ const router = useRouter();
7
+ const [errorCount, setErrorCount] = useState(0);
8
+ const form = useForm({
9
+ onSubmit,
10
+ onSuccess: () => {
11
+ router.push('/');
12
+ },
13
+ onValidationError: () => {
14
+ setErrorCount((count) => count + 1);
15
+ },
16
+ toasts: {
17
+ success: false,
18
+ validation: "There seems to be an issue with the code you've entered. Please try again.",
19
+ },
20
+ });
21
+ useEffect(() => {
22
+ form.resetForm();
23
+ }, [errorCount]);
24
+ return { ...form, key: errorCount };
25
+ }
26
+ export default useMFAForm;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,7 @@
1
1
  export { default as Auth } from './components/Auth';
2
2
  export type { AuthClassNames, AuthProps } from './components/Auth';
3
+ export type { MFASetupProps } from './components/MFASetup';
4
+ export { default as MFASetup } from './components/MFASetup';
3
5
  export { default as LogoutButton } from './components/LogoutButton';
6
+ export type { UseMFAFormArgs, UseMFAFormReturn } from './hooks/useMFAForm';
7
+ export { default as useMFAForm } from './hooks/useMFAForm';
package/dist/index.js CHANGED
@@ -1,2 +1,4 @@
1
1
  export { default as Auth } from './components/Auth';
2
+ export { default as MFASetup } from './components/MFASetup';
2
3
  export { default as LogoutButton } from './components/LogoutButton';
4
+ export { default as useMFAForm } from './hooks/useMFAForm';
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",
4
+ "version": "2.0.0-bz.5",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "dependencies": {
@@ -1,57 +1,25 @@
1
1
  'use client';
2
2
 
3
- import { useEffect, useState } from 'react';
4
-
5
- import { CodeFormField, Form, FormSubmit, tw } from '@sqrzro/components';
6
- import { useForm } from '@sqrzro/hooks';
7
- import { useRouter } from 'next/navigation';
3
+ import { CodeFormField, Form, FormSubmit } from '@sqrzro/components';
8
4
 
5
+ import useMFAForm from '../../hooks/useMFAForm';
9
6
  import { submitMFAForm } from '../../server';
10
- import type { MFAFormFields } from '../../server';
11
-
12
- import type { AuthClassNames } from '../Auth';
13
-
14
- export interface MFAFormProps {
15
- classNames?: Partial<AuthClassNames>;
16
- hasAssistiveSubmit?: boolean;
17
- }
18
-
19
- function MFAForm({ hasAssistiveSubmit }: Readonly<MFAFormProps>): React.ReactElement {
20
- const router = useRouter();
21
-
22
- const [errorCount, setErrorCount] = useState(0);
23
7
 
24
- const { fieldProps, formProps, resetForm, submitForm } = useForm<MFAFormFields, boolean>({
25
- onSubmit: submitMFAForm,
26
- onSuccess: () => {
27
- router.push('/');
28
- },
29
- onValidationError: () => {
30
- setErrorCount((count) => count + 1);
31
- },
32
- toasts: {
33
- success: false,
34
- validation:
35
- "There seems to be an issue with the code you've entered. Please try again.",
36
- },
37
- });
8
+ export interface MFAFormProps {}
38
9
 
39
- useEffect(() => {
40
- resetForm();
41
- }, [errorCount]);
10
+ function MFAForm(): React.ReactElement {
11
+ const { formProps, fieldProps, key, submitForm } = useMFAForm({ onSubmit: submitMFAForm });
42
12
 
43
13
  return (
44
14
  <Form {...formProps}>
45
15
  <CodeFormField
46
- key={errorCount}
16
+ key={key}
47
17
  {...fieldProps('token')}
48
18
  onFinalChange={submitForm}
49
19
  hasAssistiveLabel
50
20
  isAutoFocus
51
21
  />
52
- <div className={tw(hasAssistiveSubmit ? 'sr-only' : '')}>
53
- <FormSubmit>Verify</FormSubmit>
54
- </div>
22
+ <FormSubmit>Verify</FormSubmit>
55
23
  </Form>
56
24
  );
57
25
  }
@@ -34,7 +34,7 @@ async function MFAPage({ classNames }: Readonly<MFAPageProps>): Promise<React.Re
34
34
  <p className="mb-6 text-center">
35
35
  Enter the 6-digit code listed in your authentication app:
36
36
  </p>
37
- <MFAForm classNames={classNames} hasAssistiveSubmit />
37
+ <MFAForm />
38
38
  </div>
39
39
  );
40
40
  }
@@ -7,12 +7,12 @@ import { Button, Link } from '@sqrzro/components';
7
7
  import type { AuthClassNames } from '../Auth';
8
8
  import MFAForm from '../MFAForm';
9
9
 
10
- export interface MFASetupProps {
10
+ export interface MFASetupFormProps {
11
11
  classNames?: Partial<AuthClassNames>;
12
12
  url: string;
13
13
  }
14
14
 
15
- function MFASetupForm({ classNames, url }: Readonly<MFASetupProps>): React.ReactElement {
15
+ function MFASetupForm({ classNames, url }: Readonly<MFASetupFormProps>): React.ReactElement {
16
16
  const [step, setStep] = useState(1);
17
17
 
18
18
  function nextStep(): void {
@@ -24,9 +24,9 @@ function MFASetupForm({ classNames, url }: Readonly<MFASetupProps>): React.React
24
24
  setStep(1);
25
25
  }
26
26
 
27
- if (step === 1) {
28
- return (
29
- <Fragment>
27
+ return (
28
+ <Fragment>
29
+ <div className={step === 1 ? null : 'sr-only'}>
30
30
  <p className="mb-4">
31
31
  You&#39;ll need to setup an additional authentication step before you can
32
32
  continue.
@@ -36,25 +36,22 @@ function MFASetupForm({ classNames, url }: Readonly<MFASetupProps>): React.React
36
36
  </figure>
37
37
  <p className="mb-4">
38
38
  <strong>Step 1:</strong> Scan the QR code, or enter the secret below, in the
39
- Google Authentictor app.
39
+ Google Authenticator app.
40
40
  </p>
41
41
  <Button onClick={nextStep} variant="primary" isFullWidth>
42
42
  Continue
43
43
  </Button>
44
- </Fragment>
45
- );
46
- }
47
-
48
- return (
49
- <Fragment>
50
- <p className="mb-4">
51
- <strong>Step 2:</strong> Enter the 6-digit code listed in the Google Authenticator
52
- app:
53
- </p>
54
- <MFAForm />
55
- <Link className={classNames?.link} onClick={previousStep}>
56
- Scan QRcode again
57
- </Link>
44
+ </div>
45
+ <div className={step === 2 ? null : 'sr-only'}>
46
+ <p className="mb-4">
47
+ <strong>Step 2:</strong> Enter the 6-digit code listed in the Google
48
+ Authenticator app:
49
+ </p>
50
+ <MFAForm />
51
+ <Link className={classNames?.link} onClick={previousStep}>
52
+ Scan QRcode again
53
+ </Link>
54
+ </div>
58
55
  </Fragment>
59
56
  );
60
57
  }
@@ -0,0 +1,46 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState } from 'react';
4
+
5
+ import { useForm } from '@sqrzro/hooks';
6
+ import type { UseFormArgs, UseFormReturn } from '@sqrzro/hooks';
7
+ import { useRouter } from 'next/navigation';
8
+
9
+ import type { MFAFormFields } from '../server';
10
+
11
+ export interface UseMFAFormArgs {
12
+ onSubmit: UseFormArgs<MFAFormFields, boolean>['onSubmit'];
13
+ }
14
+
15
+ export interface UseMFAFormReturn extends UseFormReturn<MFAFormFields> {
16
+ key: number;
17
+ }
18
+
19
+ function useMFAForm({ onSubmit }: UseMFAFormArgs): UseMFAFormReturn {
20
+ const router = useRouter();
21
+
22
+ const [errorCount, setErrorCount] = useState(0);
23
+
24
+ const form = useForm<MFAFormFields, boolean>({
25
+ onSubmit,
26
+ onSuccess: () => {
27
+ router.push('/');
28
+ },
29
+ onValidationError: () => {
30
+ setErrorCount((count) => count + 1);
31
+ },
32
+ toasts: {
33
+ success: false,
34
+ validation:
35
+ "There seems to be an issue with the code you've entered. Please try again.",
36
+ },
37
+ });
38
+
39
+ useEffect(() => {
40
+ form.resetForm();
41
+ }, [errorCount]);
42
+
43
+ return { ...form, key: errorCount };
44
+ }
45
+
46
+ export default useMFAForm;
package/src/index.ts CHANGED
@@ -1,3 +1,10 @@
1
1
  export { default as Auth } from './components/Auth';
2
2
  export type { AuthClassNames, AuthProps } from './components/Auth';
3
+
4
+ export type { MFASetupProps } from './components/MFASetup';
5
+ export { default as MFASetup } from './components/MFASetup';
6
+
3
7
  export { default as LogoutButton } from './components/LogoutButton';
8
+
9
+ export type { UseMFAFormArgs, UseMFAFormReturn } from './hooks/useMFAForm';
10
+ export { default as useMFAForm } from './hooks/useMFAForm';
@@ -1,78 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- var components_1 = require("@sqrzro/components");
40
- var navigation_1 = require("next/navigation");
41
- var MFAForm_1 = require("../MFAForm");
42
- var MFASetup_1 = require("../MFASetup");
43
- var server_1 = require("../../server");
44
- function MFAPage(_a) {
45
- return __awaiter(this, arguments, void 0, function (_b) {
46
- var user, userHasMFA;
47
- var classNames = _b.classNames;
48
- return __generator(this, function (_c) {
49
- switch (_c.label) {
50
- case 0: return [4 /*yield*/, (0, server_1.checkMFAEnabled)()];
51
- case 1:
52
- if (!(_c.sent())) {
53
- return [2 /*return*/, (0, navigation_1.notFound)()];
54
- }
55
- return [4 /*yield*/, (0, server_1.getSessionUser)()];
56
- case 2:
57
- user = _c.sent();
58
- if (!user) {
59
- return [2 /*return*/, <div>Error</div>];
60
- }
61
- return [4 /*yield*/, (0, server_1.checkUserHasMFA)(user)];
62
- case 3:
63
- userHasMFA = _c.sent();
64
- if (!userHasMFA) {
65
- return [2 /*return*/, <MFASetup_1.default classNames={classNames}/>];
66
- }
67
- return [2 /*return*/, (<div>
68
- <h1 className={(0, components_1.tw)('text-center', classNames === null || classNames === void 0 ? void 0 : classNames.title)}>Multi-Factor Authentication</h1>
69
- <p className="mb-6 text-center">
70
- Enter the 6-digit code listed in your authentication app:
71
- </p>
72
- <MFAForm_1.default classNames={classNames} hasAssistiveSubmit/>
73
- </div>)];
74
- }
75
- });
76
- });
77
- }
78
- exports.default = MFAPage;