@ttoss/react-auth 1.1.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/README.md +146 -0
- package/dist/esm/index.js +529 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +564 -0
- package/i18n/lang/en.json +74 -0
- package/package.json +53 -0
- package/src/Auth.tsx +199 -0
- package/src/AuthCard.tsx +85 -0
- package/src/AuthConfirmSignUp.tsx +70 -0
- package/src/AuthContainer.tsx +21 -0
- package/src/AuthProvider.tsx +84 -0
- package/src/AuthSignIn.tsx +111 -0
- package/src/AuthSignUp.tsx +97 -0
- package/src/index.ts +4 -0
- package/src/types.ts +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# @ttoss/react-auth
|
|
2
|
+
|
|
3
|
+
## About
|
|
4
|
+
|
|
5
|
+
This module handles auth in your applications and other ttoss modules.
|
|
6
|
+
|
|
7
|
+
This module is intended to use with AWS Cognito. It uses [AWS Amplify](https://docs.amplify.aws/lib/auth/getting-started/q/platform/js) under the hood.
|
|
8
|
+
|
|
9
|
+
[Amplify Auth configuration](https://docs.amplify.aws/lib/auth/start/q/platform/js#re-use-existing-authentication-resource) must be provided in your App to make Auth Module works properly.
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
### Install
|
|
14
|
+
|
|
15
|
+
```shell
|
|
16
|
+
$ yarn add @ttoss/auth @ttoss/react-notifications
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Examples of use
|
|
20
|
+
|
|
21
|
+
### Amplify config
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import Amplify from 'aws-amplify';
|
|
25
|
+
|
|
26
|
+
Amplify.configure({
|
|
27
|
+
Auth: {
|
|
28
|
+
// REQUIRED only for Federated Authentication - Amazon Cognito Identity Pool ID
|
|
29
|
+
identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX-1234-abcd-1234567890ab',
|
|
30
|
+
|
|
31
|
+
// REQUIRED - Amazon Cognito Region
|
|
32
|
+
region: 'XX-XXXX-X',
|
|
33
|
+
|
|
34
|
+
// OPTIONAL - Amazon Cognito Federated Identity Pool Region
|
|
35
|
+
// Required only if it's different from Amazon Cognito Region
|
|
36
|
+
identityPoolRegion: 'XX-XXXX-X',
|
|
37
|
+
|
|
38
|
+
// OPTIONAL - Amazon Cognito User Pool ID
|
|
39
|
+
userPoolId: 'XX-XXXX-X_abcd1234',
|
|
40
|
+
|
|
41
|
+
// OPTIONAL - Amazon Cognito Web Client ID (26-char alphanumeric string)
|
|
42
|
+
userPoolWebClientId: 'a1b2c3d4e5f6g7h8i9j0k1l2m3',
|
|
43
|
+
|
|
44
|
+
// OPTIONAL - Enforce user authentication prior to accessing AWS resources or not
|
|
45
|
+
mandatorySignIn: false,
|
|
46
|
+
|
|
47
|
+
// OPTIONAL - Configuration for cookie storage
|
|
48
|
+
// Note: if the secure flag is set to true, then the cookie transmission requires a secure protocol
|
|
49
|
+
cookieStorage: {
|
|
50
|
+
// REQUIRED - Cookie domain (only required if cookieStorage is provided)
|
|
51
|
+
domain: '.yourdomain.com',
|
|
52
|
+
// OPTIONAL - Cookie path
|
|
53
|
+
path: '/',
|
|
54
|
+
// OPTIONAL - Cookie expiration in days
|
|
55
|
+
expires: 365,
|
|
56
|
+
// OPTIONAL - See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
|
|
57
|
+
sameSite: 'strict' | 'lax',
|
|
58
|
+
// OPTIONAL - Cookie secure flag
|
|
59
|
+
// Either true or false, indicating if the cookie transmission requires a secure protocol (https).
|
|
60
|
+
secure: true,
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
// OPTIONAL - customized storage object
|
|
64
|
+
storage: MyStorage,
|
|
65
|
+
|
|
66
|
+
// OPTIONAL - Manually set the authentication flow type. Default is 'USER_SRP_AUTH'
|
|
67
|
+
authenticationFlowType: 'USER_PASSWORD_AUTH',
|
|
68
|
+
|
|
69
|
+
// OPTIONAL - Manually set key value pairs that can be passed to Cognito Lambda Triggers
|
|
70
|
+
clientMetadata: { myCustomKey: 'myCustomValue' },
|
|
71
|
+
|
|
72
|
+
// OPTIONAL - Hosted UI configuration
|
|
73
|
+
oauth: {
|
|
74
|
+
domain: 'your_cognito_domain',
|
|
75
|
+
scope: [
|
|
76
|
+
'phone',
|
|
77
|
+
'email',
|
|
78
|
+
'profile',
|
|
79
|
+
'openid',
|
|
80
|
+
'aws.cognito.signin.user.admin',
|
|
81
|
+
],
|
|
82
|
+
redirectSignIn: 'http://localhost:3000/',
|
|
83
|
+
redirectSignOut: 'http://localhost:3000/',
|
|
84
|
+
responseType: 'code', // or 'token', note that REFRESH token will only be generated when the responseType is code
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### PrivateRoute component
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { useAuth } from '@ttoss/react-auth';
|
|
94
|
+
|
|
95
|
+
const PrivateRoute = (props: any) => {
|
|
96
|
+
const { isAuthenticated } = useAuth();
|
|
97
|
+
|
|
98
|
+
if (!isAuthenticated) {
|
|
99
|
+
return <Navigate to="/login" state={{ redirectTo: props.path || '/' }} />;
|
|
100
|
+
}
|
|
101
|
+
return <Route {...props} />;
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Login Page
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { Auth, useAuth } from '@ttoss/react-auth';
|
|
109
|
+
|
|
110
|
+
const Login = () => {
|
|
111
|
+
const auth = useAuth();
|
|
112
|
+
|
|
113
|
+
const onSuccess = () => {
|
|
114
|
+
// Navigate to logged-area
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<div>
|
|
119
|
+
<h1>Login Page</h1>
|
|
120
|
+
|
|
121
|
+
<Auth onSignIn={onSuccess} />
|
|
122
|
+
|
|
123
|
+
<button onClick={auth.signOut}>Logout</button>
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
export default Login;
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Auth with Progressbar
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { AuthProvider } from '@ttoss/react-auth';
|
|
134
|
+
import { NotificationsProvider } from '@ttoss/react-notifications';
|
|
135
|
+
|
|
136
|
+
ReactDOM.render(
|
|
137
|
+
<React.StrictMode>
|
|
138
|
+
<NotificationsProvider>
|
|
139
|
+
<AuthProvider>
|
|
140
|
+
<App />
|
|
141
|
+
</AuthProvider>
|
|
142
|
+
</NotificationsProvider>
|
|
143
|
+
</React.StrictMode>,
|
|
144
|
+
document.getElementById('root')
|
|
145
|
+
);
|
|
146
|
+
```
|
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
|
|
3
|
+
// src/AuthProvider.tsx
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { Auth, Hub } from "aws-amplify";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
var signOut = () => {
|
|
8
|
+
return Auth.signOut();
|
|
9
|
+
};
|
|
10
|
+
var AuthContext = React.createContext({
|
|
11
|
+
signOut,
|
|
12
|
+
isAuthenticated: false,
|
|
13
|
+
user: null,
|
|
14
|
+
tokens: null
|
|
15
|
+
});
|
|
16
|
+
var AuthProvider = ({ children }) => {
|
|
17
|
+
const [user, setUser] = React.useState(null);
|
|
18
|
+
const [tokens, setTokens] = React.useState(null);
|
|
19
|
+
React.useEffect(() => {
|
|
20
|
+
const updateUser = () => {
|
|
21
|
+
Auth.currentAuthenticatedUser().then(({ attributes, signInUserSession }) => {
|
|
22
|
+
setUser({
|
|
23
|
+
id: attributes.sub,
|
|
24
|
+
email: attributes.email,
|
|
25
|
+
emailVerified: attributes["email_verified"]
|
|
26
|
+
});
|
|
27
|
+
setTokens({
|
|
28
|
+
idToken: signInUserSession.idToken.jwtToken,
|
|
29
|
+
accessToken: signInUserSession.accessToken.jwtToken,
|
|
30
|
+
refreshToken: signInUserSession.refreshToken.token
|
|
31
|
+
});
|
|
32
|
+
}).catch(() => {
|
|
33
|
+
setUser(null);
|
|
34
|
+
setTokens(null);
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
const updateUserListener = Hub.listen("auth", updateUser);
|
|
38
|
+
updateUser();
|
|
39
|
+
return () => {
|
|
40
|
+
updateUserListener();
|
|
41
|
+
};
|
|
42
|
+
}, []);
|
|
43
|
+
const isAuthenticated = !!user;
|
|
44
|
+
return /* @__PURE__ */ jsx(AuthContext.Provider, { value: { signOut, isAuthenticated, user, tokens }, children });
|
|
45
|
+
};
|
|
46
|
+
var useAuth = () => {
|
|
47
|
+
return React.useContext(AuthContext);
|
|
48
|
+
};
|
|
49
|
+
var AuthProvider_default = AuthProvider;
|
|
50
|
+
|
|
51
|
+
// src/Auth.tsx
|
|
52
|
+
import * as React3 from "react";
|
|
53
|
+
import { Auth as AmplifyAuth } from "aws-amplify";
|
|
54
|
+
|
|
55
|
+
// src/AuthCard.tsx
|
|
56
|
+
import * as React2 from "react";
|
|
57
|
+
import { Button, Card, Flex, Link, Text } from "@ttoss/ui";
|
|
58
|
+
import { useNotifications } from "@ttoss/react-notifications";
|
|
59
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
60
|
+
var LogoContext = React2.createContext({});
|
|
61
|
+
var LogoProvider = ({ children, ...values }) => {
|
|
62
|
+
return /* @__PURE__ */ jsx2(LogoContext.Provider, { value: values, children });
|
|
63
|
+
};
|
|
64
|
+
var AuthCard = ({
|
|
65
|
+
children,
|
|
66
|
+
title,
|
|
67
|
+
buttonLabel,
|
|
68
|
+
links = []
|
|
69
|
+
}) => {
|
|
70
|
+
const { logo } = React2.useContext(LogoContext);
|
|
71
|
+
const { isLoading } = useNotifications();
|
|
72
|
+
return /* @__PURE__ */ jsx2(Card, { sx: { maxWidth: "564px" }, children: /* @__PURE__ */ jsxs(Flex, { sx: { flexDirection: "column", gap: 3 }, children: [
|
|
73
|
+
logo && /* @__PURE__ */ jsx2(Flex, { sx: { width: "100%", justifyContent: "center" }, children: logo }),
|
|
74
|
+
/* @__PURE__ */ jsx2(
|
|
75
|
+
Text,
|
|
76
|
+
{
|
|
77
|
+
variant: "title",
|
|
78
|
+
sx: { alignSelf: "center", marginY: 4, fontSize: 5 },
|
|
79
|
+
children: title
|
|
80
|
+
}
|
|
81
|
+
),
|
|
82
|
+
children,
|
|
83
|
+
/* @__PURE__ */ jsx2(Flex, { sx: { justifyContent: "space-between", marginTop: 3 }, children: /* @__PURE__ */ jsx2(
|
|
84
|
+
Button,
|
|
85
|
+
{
|
|
86
|
+
type: "submit",
|
|
87
|
+
"aria-label": "submit-login",
|
|
88
|
+
variant: "cta",
|
|
89
|
+
disabled: isLoading,
|
|
90
|
+
sx: { width: "100%" },
|
|
91
|
+
children: buttonLabel
|
|
92
|
+
}
|
|
93
|
+
) }),
|
|
94
|
+
/* @__PURE__ */ jsx2(
|
|
95
|
+
Flex,
|
|
96
|
+
{
|
|
97
|
+
sx: {
|
|
98
|
+
justifyContent: "space-between",
|
|
99
|
+
flexDirection: "column",
|
|
100
|
+
gap: 3,
|
|
101
|
+
marginTop: 4,
|
|
102
|
+
color: "text"
|
|
103
|
+
},
|
|
104
|
+
children: links.map((link) => {
|
|
105
|
+
return link && /* @__PURE__ */ jsx2(Link, { onClick: link.onClick, children: link.label }, link.label);
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
] }) });
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// src/AuthConfirmSignUp.tsx
|
|
113
|
+
import { Form, FormFieldInput, useForm, yup, yupResolver } from "@ttoss/forms";
|
|
114
|
+
import { useI18n } from "@ttoss/react-i18n";
|
|
115
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
116
|
+
var AuthConfirmSignUp = ({
|
|
117
|
+
email,
|
|
118
|
+
onConfirmSignUp
|
|
119
|
+
}) => {
|
|
120
|
+
const { intl } = useI18n();
|
|
121
|
+
const schema = yup.object().shape({
|
|
122
|
+
code: yup.string().required(
|
|
123
|
+
intl.formatMessage({
|
|
124
|
+
description: "Required field.",
|
|
125
|
+
defaultMessage: "Required field"
|
|
126
|
+
})
|
|
127
|
+
).max(
|
|
128
|
+
6,
|
|
129
|
+
intl.formatMessage(
|
|
130
|
+
{
|
|
131
|
+
description: "Minimum {value} characters.",
|
|
132
|
+
defaultMessage: "Minimum {value} characters"
|
|
133
|
+
},
|
|
134
|
+
{ value: 6 }
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
}).required();
|
|
138
|
+
const formMethods = useForm({
|
|
139
|
+
resolver: yupResolver(schema)
|
|
140
|
+
});
|
|
141
|
+
return /* @__PURE__ */ jsx3(
|
|
142
|
+
Form,
|
|
143
|
+
{
|
|
144
|
+
...formMethods,
|
|
145
|
+
onSubmit: ({ code }) => {
|
|
146
|
+
return onConfirmSignUp({ code, email });
|
|
147
|
+
},
|
|
148
|
+
children: /* @__PURE__ */ jsx3(
|
|
149
|
+
AuthCard,
|
|
150
|
+
{
|
|
151
|
+
buttonLabel: intl.formatMessage({
|
|
152
|
+
description: "Confirm",
|
|
153
|
+
defaultMessage: "Confirm"
|
|
154
|
+
}),
|
|
155
|
+
title: intl.formatMessage({
|
|
156
|
+
description: "Confirmation",
|
|
157
|
+
defaultMessage: "Confirmation"
|
|
158
|
+
}),
|
|
159
|
+
children: /* @__PURE__ */ jsx3(
|
|
160
|
+
FormFieldInput,
|
|
161
|
+
{
|
|
162
|
+
name: "code",
|
|
163
|
+
label: intl.formatMessage({
|
|
164
|
+
description: "Sign up confirmation code",
|
|
165
|
+
defaultMessage: "Code"
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// src/AuthSignIn.tsx
|
|
176
|
+
import { Form as Form2, FormFieldInput as FormFieldInput2, useForm as useForm2, yup as yup2, yupResolver as yupResolver2 } from "@ttoss/forms";
|
|
177
|
+
|
|
178
|
+
// ../cloud-auth/dist/esm/index.js
|
|
179
|
+
var PASSWORD_MINIMUM_LENGTH = 8;
|
|
180
|
+
|
|
181
|
+
// src/AuthSignIn.tsx
|
|
182
|
+
import { useI18n as useI18n2 } from "@ttoss/react-i18n";
|
|
183
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
184
|
+
var AuthSignIn = ({
|
|
185
|
+
onSignIn,
|
|
186
|
+
onSignUp,
|
|
187
|
+
defaultValues
|
|
188
|
+
}) => {
|
|
189
|
+
const { intl } = useI18n2();
|
|
190
|
+
const schema = yup2.object().shape({
|
|
191
|
+
email: yup2.string().required(
|
|
192
|
+
intl.formatMessage({
|
|
193
|
+
description: "Email is a required field.",
|
|
194
|
+
defaultMessage: "Email field is required"
|
|
195
|
+
})
|
|
196
|
+
).email(
|
|
197
|
+
intl.formatMessage({
|
|
198
|
+
description: "Invalid email.",
|
|
199
|
+
defaultMessage: "Invalid email"
|
|
200
|
+
})
|
|
201
|
+
),
|
|
202
|
+
password: yup2.string().required(
|
|
203
|
+
intl.formatMessage({
|
|
204
|
+
description: "Password is required.",
|
|
205
|
+
defaultMessage: "Password field is required"
|
|
206
|
+
})
|
|
207
|
+
).min(
|
|
208
|
+
PASSWORD_MINIMUM_LENGTH,
|
|
209
|
+
intl.formatMessage(
|
|
210
|
+
{
|
|
211
|
+
description: "Password must be at least {value} characters long.",
|
|
212
|
+
defaultMessage: "Password requires {value} characters"
|
|
213
|
+
},
|
|
214
|
+
{ value: PASSWORD_MINIMUM_LENGTH }
|
|
215
|
+
)
|
|
216
|
+
).trim()
|
|
217
|
+
});
|
|
218
|
+
const formMethods = useForm2({
|
|
219
|
+
defaultValues,
|
|
220
|
+
resolver: yupResolver2(schema)
|
|
221
|
+
});
|
|
222
|
+
const onSubmitForm = (data) => {
|
|
223
|
+
return onSignIn(data);
|
|
224
|
+
};
|
|
225
|
+
return /* @__PURE__ */ jsx4(Form2, { ...formMethods, onSubmit: onSubmitForm, children: /* @__PURE__ */ jsxs2(
|
|
226
|
+
AuthCard,
|
|
227
|
+
{
|
|
228
|
+
title: intl.formatMessage({
|
|
229
|
+
description: "Sign in title.",
|
|
230
|
+
defaultMessage: "Login"
|
|
231
|
+
}),
|
|
232
|
+
buttonLabel: intl.formatMessage({
|
|
233
|
+
description: "Button label.",
|
|
234
|
+
defaultMessage: "Login"
|
|
235
|
+
}),
|
|
236
|
+
links: [
|
|
237
|
+
{
|
|
238
|
+
onClick: onSignUp,
|
|
239
|
+
label: intl.formatMessage({
|
|
240
|
+
description: "Link to retrieve password.",
|
|
241
|
+
defaultMessage: "Do you forgot your password?"
|
|
242
|
+
})
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
onClick: onSignUp,
|
|
246
|
+
label: intl.formatMessage({
|
|
247
|
+
description: "Link to sign up.",
|
|
248
|
+
defaultMessage: "Don't have an account? Sign up"
|
|
249
|
+
})
|
|
250
|
+
}
|
|
251
|
+
],
|
|
252
|
+
children: [
|
|
253
|
+
/* @__PURE__ */ jsx4(
|
|
254
|
+
FormFieldInput2,
|
|
255
|
+
{
|
|
256
|
+
name: "email",
|
|
257
|
+
label: intl.formatMessage({
|
|
258
|
+
description: "Email label.",
|
|
259
|
+
defaultMessage: "Email"
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
),
|
|
263
|
+
/* @__PURE__ */ jsx4(
|
|
264
|
+
FormFieldInput2,
|
|
265
|
+
{
|
|
266
|
+
name: "password",
|
|
267
|
+
label: intl.formatMessage({
|
|
268
|
+
description: "Password label.",
|
|
269
|
+
defaultMessage: "Password"
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
)
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
) });
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// src/AuthSignUp.tsx
|
|
279
|
+
import { Form as Form3, FormFieldInput as FormFieldInput3, useForm as useForm3, yup as yup3, yupResolver as yupResolver3 } from "@ttoss/forms";
|
|
280
|
+
import { useI18n as useI18n3 } from "@ttoss/react-i18n";
|
|
281
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
282
|
+
var AuthSignUp = ({ onSignUp, onReturnToSignIn }) => {
|
|
283
|
+
const { intl } = useI18n3();
|
|
284
|
+
const schema = yup3.object().shape({
|
|
285
|
+
email: yup3.string().required(
|
|
286
|
+
intl.formatMessage({
|
|
287
|
+
description: "Email is a required field.",
|
|
288
|
+
defaultMessage: "Email field is required"
|
|
289
|
+
})
|
|
290
|
+
).email(
|
|
291
|
+
intl.formatMessage({
|
|
292
|
+
description: "Invalid email.",
|
|
293
|
+
defaultMessage: "Invalid email"
|
|
294
|
+
})
|
|
295
|
+
),
|
|
296
|
+
password: yup3.string().required(
|
|
297
|
+
intl.formatMessage({
|
|
298
|
+
description: "Password is required.",
|
|
299
|
+
defaultMessage: "Password field is required"
|
|
300
|
+
})
|
|
301
|
+
).min(
|
|
302
|
+
PASSWORD_MINIMUM_LENGTH,
|
|
303
|
+
intl.formatMessage(
|
|
304
|
+
{
|
|
305
|
+
description: "Password must be at least {value} characters long.",
|
|
306
|
+
defaultMessage: "Password requires {value} characters"
|
|
307
|
+
},
|
|
308
|
+
{ value: PASSWORD_MINIMUM_LENGTH }
|
|
309
|
+
)
|
|
310
|
+
).trim()
|
|
311
|
+
});
|
|
312
|
+
const formMethods = useForm3({
|
|
313
|
+
resolver: yupResolver3(schema)
|
|
314
|
+
});
|
|
315
|
+
const onSubmitForm = (data) => {
|
|
316
|
+
return onSignUp(data);
|
|
317
|
+
};
|
|
318
|
+
return /* @__PURE__ */ jsx5(Form3, { ...formMethods, onSubmit: onSubmitForm, children: /* @__PURE__ */ jsxs3(
|
|
319
|
+
AuthCard,
|
|
320
|
+
{
|
|
321
|
+
buttonLabel: intl.formatMessage({
|
|
322
|
+
description: "Create account.",
|
|
323
|
+
defaultMessage: "Create account"
|
|
324
|
+
}),
|
|
325
|
+
title: intl.formatMessage({
|
|
326
|
+
description: "Title on sign up.",
|
|
327
|
+
defaultMessage: "Register"
|
|
328
|
+
}),
|
|
329
|
+
links: [
|
|
330
|
+
{
|
|
331
|
+
label: intl.formatMessage({
|
|
332
|
+
description: "Link to sign in on sign up.",
|
|
333
|
+
defaultMessage: "Do you already have an account? Sign in"
|
|
334
|
+
}),
|
|
335
|
+
onClick: onReturnToSignIn
|
|
336
|
+
}
|
|
337
|
+
],
|
|
338
|
+
children: [
|
|
339
|
+
/* @__PURE__ */ jsx5(
|
|
340
|
+
FormFieldInput3,
|
|
341
|
+
{
|
|
342
|
+
name: "email",
|
|
343
|
+
label: intl.formatMessage({
|
|
344
|
+
description: "Email label.",
|
|
345
|
+
defaultMessage: "Email"
|
|
346
|
+
})
|
|
347
|
+
}
|
|
348
|
+
),
|
|
349
|
+
/* @__PURE__ */ jsx5(
|
|
350
|
+
FormFieldInput3,
|
|
351
|
+
{
|
|
352
|
+
name: "password",
|
|
353
|
+
label: intl.formatMessage({
|
|
354
|
+
description: "Password label.",
|
|
355
|
+
defaultMessage: "Password"
|
|
356
|
+
})
|
|
357
|
+
}
|
|
358
|
+
)
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
) });
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// src/Auth.tsx
|
|
365
|
+
import { assign, createMachine } from "xstate";
|
|
366
|
+
import { useMachine } from "@xstate/react";
|
|
367
|
+
import { useNotifications as useNotifications2 } from "@ttoss/react-notifications";
|
|
368
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
369
|
+
var authMachine = createMachine(
|
|
370
|
+
{
|
|
371
|
+
predictableActionArguments: true,
|
|
372
|
+
initial: "signIn",
|
|
373
|
+
states: {
|
|
374
|
+
signIn: {
|
|
375
|
+
on: {
|
|
376
|
+
SIGN_UP: { target: "signUp" },
|
|
377
|
+
SIGN_UP_RESEND_CONFIRMATION: {
|
|
378
|
+
actions: ["assignEmail"],
|
|
379
|
+
target: "signUpConfirm"
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
signUp: {
|
|
384
|
+
on: {
|
|
385
|
+
SIGN_UP_CONFIRM: {
|
|
386
|
+
actions: ["assignEmail"],
|
|
387
|
+
target: "signUpConfirm"
|
|
388
|
+
},
|
|
389
|
+
RETURN_TO_SIGN_IN: { target: "signIn" }
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
signUpConfirm: {
|
|
393
|
+
on: {
|
|
394
|
+
SIGN_UP_CONFIRMED: {
|
|
395
|
+
actions: ["assignEmail"],
|
|
396
|
+
target: "signIn"
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
actions: {
|
|
404
|
+
assignEmail: assign({
|
|
405
|
+
email: (_, event) => {
|
|
406
|
+
return event.email;
|
|
407
|
+
}
|
|
408
|
+
})
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
);
|
|
412
|
+
var AuthWithoutLogo = () => {
|
|
413
|
+
const { isAuthenticated } = useAuth();
|
|
414
|
+
const [state, send] = useMachine(authMachine);
|
|
415
|
+
const { setLoading } = useNotifications2();
|
|
416
|
+
const onSignIn = React3.useCallback(
|
|
417
|
+
async ({ email, password }) => {
|
|
418
|
+
try {
|
|
419
|
+
setLoading(true);
|
|
420
|
+
await AmplifyAuth.signIn(email, password);
|
|
421
|
+
} catch (error) {
|
|
422
|
+
switch (error.code) {
|
|
423
|
+
case "UserNotConfirmedException":
|
|
424
|
+
await AmplifyAuth.resendSignUp(email);
|
|
425
|
+
send({ type: "SIGN_UP_RESEND_CONFIRMATION", email });
|
|
426
|
+
break;
|
|
427
|
+
default:
|
|
428
|
+
}
|
|
429
|
+
} finally {
|
|
430
|
+
setLoading(false);
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
[send, setLoading]
|
|
434
|
+
);
|
|
435
|
+
const onSignUp = React3.useCallback(
|
|
436
|
+
async ({ email, password }) => {
|
|
437
|
+
try {
|
|
438
|
+
setLoading(true);
|
|
439
|
+
await AmplifyAuth.signUp({
|
|
440
|
+
username: email,
|
|
441
|
+
password,
|
|
442
|
+
attributes: { email }
|
|
443
|
+
});
|
|
444
|
+
send({ type: "SIGN_UP_CONFIRM", email });
|
|
445
|
+
} catch (error) {
|
|
446
|
+
} finally {
|
|
447
|
+
setLoading(false);
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
[send, setLoading]
|
|
451
|
+
);
|
|
452
|
+
const onConfirmSignUp = React3.useCallback(
|
|
453
|
+
async ({ email, code }) => {
|
|
454
|
+
try {
|
|
455
|
+
setLoading(true);
|
|
456
|
+
await AmplifyAuth.confirmSignUp(email, code);
|
|
457
|
+
send({ type: "SIGN_UP_CONFIRMED", email });
|
|
458
|
+
} catch (error) {
|
|
459
|
+
} finally {
|
|
460
|
+
setLoading(false);
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
[send, setLoading]
|
|
464
|
+
);
|
|
465
|
+
const onReturnToSignIn = React3.useCallback(() => {
|
|
466
|
+
send({ type: "RETURN_TO_SIGN_IN" });
|
|
467
|
+
}, [send]);
|
|
468
|
+
if (isAuthenticated) {
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
471
|
+
if (state.matches("signUp")) {
|
|
472
|
+
return /* @__PURE__ */ jsx6(AuthSignUp, { onSignUp, onReturnToSignIn });
|
|
473
|
+
}
|
|
474
|
+
if (state.matches("signUpConfirm")) {
|
|
475
|
+
return /* @__PURE__ */ jsx6(
|
|
476
|
+
AuthConfirmSignUp,
|
|
477
|
+
{
|
|
478
|
+
onConfirmSignUp,
|
|
479
|
+
email: state.context.email
|
|
480
|
+
}
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
return /* @__PURE__ */ jsx6(
|
|
484
|
+
AuthSignIn,
|
|
485
|
+
{
|
|
486
|
+
onSignIn,
|
|
487
|
+
onSignUp: () => {
|
|
488
|
+
return send("SIGN_UP");
|
|
489
|
+
},
|
|
490
|
+
defaultValues: { email: state.context.email }
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
};
|
|
494
|
+
var withLogo = (Component) => {
|
|
495
|
+
const WithLogo = ({ logo, ...componentProps }) => {
|
|
496
|
+
return /* @__PURE__ */ jsx6(LogoProvider, { logo, children: /* @__PURE__ */ jsx6(Component, { ...componentProps }) });
|
|
497
|
+
};
|
|
498
|
+
WithLogo.displayName = "WithLogo";
|
|
499
|
+
return WithLogo;
|
|
500
|
+
};
|
|
501
|
+
var Auth2 = withLogo(AuthWithoutLogo);
|
|
502
|
+
|
|
503
|
+
// src/AuthContainer.tsx
|
|
504
|
+
import { Flex as Flex2 } from "@ttoss/ui";
|
|
505
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
506
|
+
var AuthContainer = ({ sx, ...props }) => {
|
|
507
|
+
return /* @__PURE__ */ jsx7(
|
|
508
|
+
Flex2,
|
|
509
|
+
{
|
|
510
|
+
...props,
|
|
511
|
+
sx: {
|
|
512
|
+
height: "100vh",
|
|
513
|
+
justifyContent: "center",
|
|
514
|
+
alignItems: "center",
|
|
515
|
+
margin: 0,
|
|
516
|
+
backgroundPosition: "center",
|
|
517
|
+
backgroundRepeat: "no-repeat",
|
|
518
|
+
backgroundSize: "cover",
|
|
519
|
+
...sx
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
);
|
|
523
|
+
};
|
|
524
|
+
export {
|
|
525
|
+
Auth2 as Auth,
|
|
526
|
+
AuthContainer,
|
|
527
|
+
AuthProvider_default as AuthProvider,
|
|
528
|
+
useAuth
|
|
529
|
+
};
|