@ttoss/react-auth 2.0.9 → 2.1.1

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/src/AuthCard.tsx DELETED
@@ -1,95 +0,0 @@
1
- import * as React from 'react';
2
- import { Box, Button, Flex, Heading } from '@ttoss/ui';
3
- import { useNotifications } from '@ttoss/react-notifications';
4
-
5
- export type LogoContextProps = {
6
- logo?: React.ReactNode;
7
- children?: React.ReactNode;
8
- };
9
-
10
- const LogoContext = React.createContext<LogoContextProps>({});
11
-
12
- export const LogoProvider = ({ children, ...values }: LogoContextProps) => {
13
- return <LogoContext.Provider value={values}>{children}</LogoContext.Provider>;
14
- };
15
-
16
- type AuthCardProps = {
17
- children: React.ReactNode;
18
- title: string;
19
- buttonLabel: string;
20
- extraButton?: React.ReactNode;
21
- isValidForm?: boolean;
22
- };
23
-
24
- export const AuthCard = ({
25
- children,
26
- title,
27
- buttonLabel,
28
- extraButton,
29
- isValidForm,
30
- }: AuthCardProps) => {
31
- const { logo } = React.useContext(LogoContext);
32
-
33
- const { isLoading } = useNotifications();
34
-
35
- return (
36
- <Box
37
- sx={{
38
- width: '100%',
39
- border: 'default',
40
- borderColor: 'primary',
41
- paddingX: '2xl',
42
- paddingY: '3xl',
43
- backgroundColor: 'surface',
44
- }}
45
- >
46
- {logo && (
47
- <Flex
48
- sx={{
49
- width: '100%',
50
- maxHeight: '90px',
51
- justifyContent: 'center',
52
- marginBottom: '2xl',
53
- }}
54
- >
55
- {logo}
56
- </Flex>
57
- )}
58
- <Flex sx={{ flexDirection: 'column' }}>
59
- <Heading
60
- as="h2"
61
- variant="h2"
62
- sx={{
63
- marginBottom: '2xl',
64
- }}
65
- >
66
- {title}
67
- </Heading>
68
-
69
- {children}
70
-
71
- <Flex
72
- sx={{
73
- flexDirection: 'column',
74
- width: '100%',
75
- gap: 'xl',
76
- marginTop: '2xl',
77
- }}
78
- >
79
- <Button
80
- type="submit"
81
- aria-label="submit-button"
82
- variant="accent"
83
- disabled={isLoading || !isValidForm}
84
- sx={{ textAlign: 'center', display: 'initial' }}
85
- loading={isLoading}
86
- >
87
- {buttonLabel}
88
- </Button>
89
-
90
- {extraButton}
91
- </Flex>
92
- </Flex>
93
- </Box>
94
- );
95
- };
@@ -1,73 +0,0 @@
1
- import { AuthCard } from './AuthCard';
2
- import { Form, FormFieldInput, useForm, yup, yupResolver } from '@ttoss/forms';
3
- import { useI18n } from '@ttoss/react-i18n';
4
- import type { OnConfirmSignUp } from './types';
5
-
6
- export type AuthConfirmSignUpProps = {
7
- email: string;
8
- onConfirmSignUp: OnConfirmSignUp;
9
- };
10
-
11
- export const AuthConfirmSignUp = ({
12
- email,
13
- onConfirmSignUp,
14
- }: AuthConfirmSignUpProps) => {
15
- const { intl } = useI18n();
16
-
17
- const schema = yup
18
- .object()
19
- .shape({
20
- code: yup
21
- .string()
22
- .required(
23
- intl.formatMessage({
24
- description: 'Required field.',
25
- defaultMessage: 'Required field',
26
- })
27
- )
28
- .max(
29
- 6,
30
- intl.formatMessage(
31
- {
32
- description: 'Minimum {value} characters.',
33
- defaultMessage: 'Minimum {value} characters',
34
- },
35
- { value: 6 }
36
- )
37
- ),
38
- })
39
- .required();
40
-
41
- const formMethods = useForm<yup.InferType<typeof schema>>({
42
- resolver: yupResolver(schema),
43
- });
44
-
45
- return (
46
- <Form
47
- {...formMethods}
48
- onSubmit={({ code }) => {
49
- return onConfirmSignUp({ code, email });
50
- }}
51
- >
52
- <AuthCard
53
- buttonLabel={intl.formatMessage({
54
- description: 'Confirm',
55
- defaultMessage: 'Confirm',
56
- })}
57
- isValidForm={formMethods.formState.isValid}
58
- title={intl.formatMessage({
59
- description: 'Confirmation',
60
- defaultMessage: 'Confirmation',
61
- })}
62
- >
63
- <FormFieldInput
64
- name="code"
65
- label={intl.formatMessage({
66
- description: 'Sign up confirmation code',
67
- defaultMessage: 'Code',
68
- })}
69
- />
70
- </AuthCard>
71
- </Form>
72
- );
73
- };
@@ -1,102 +0,0 @@
1
- import { AuthCard } from './AuthCard';
2
- import { Button, Link, Text } from '@ttoss/ui';
3
- import { Form, FormFieldInput, useForm, yup, yupResolver } from '@ttoss/forms';
4
- import { NotificationsBox } from '@ttoss/react-notifications';
5
- import { useI18n } from '@ttoss/react-i18n';
6
- import type { OnForgotPassword } from './types';
7
-
8
- export type AuthForgotPasswordProps = {
9
- onForgotPassword: OnForgotPassword;
10
- onCancel: () => void;
11
- onSignUp: () => void;
12
- };
13
-
14
- export const AuthForgotPassword = ({
15
- onForgotPassword,
16
- onCancel,
17
- onSignUp,
18
- }: AuthForgotPasswordProps) => {
19
- const { intl } = useI18n();
20
-
21
- const schema = yup
22
- .object()
23
- .shape({
24
- email: yup
25
- .string()
26
- .required(
27
- intl.formatMessage({
28
- description: 'Required field.',
29
- defaultMessage: 'Enter your email address',
30
- })
31
- )
32
- .email(
33
- intl.formatMessage({
34
- description: 'Please, insert a valid e-mail',
35
- defaultMessage: 'Please, insert a valid e-mail',
36
- })
37
- ),
38
- })
39
- .required();
40
-
41
- const formMethods = useForm<yup.InferType<typeof schema>>({
42
- resolver: yupResolver(schema),
43
- mode: 'onBlur',
44
- });
45
-
46
- return (
47
- <Form
48
- {...formMethods}
49
- sx={{
50
- maxWidth: '390px',
51
- }}
52
- onSubmit={({ email }) => {
53
- return onForgotPassword({ email });
54
- }}
55
- >
56
- <AuthCard
57
- buttonLabel={intl.formatMessage({
58
- description: 'Recover Password',
59
- defaultMessage: 'Recover Password',
60
- })}
61
- isValidForm={formMethods.formState.isValid}
62
- title={intl.formatMessage({
63
- description: 'Recovering Password',
64
- defaultMessage: 'Recovering Password',
65
- })}
66
- extraButton={
67
- <Button
68
- sx={{ textAlign: 'center', display: 'initial' }}
69
- variant="secondary"
70
- onClick={onCancel}
71
- >
72
- {intl.formatMessage({
73
- description: 'Cancel',
74
- defaultMessage: 'Cancel',
75
- })}
76
- </Button>
77
- }
78
- >
79
- <FormFieldInput
80
- name="email"
81
- label={intl.formatMessage({
82
- description: 'Registered Email',
83
- defaultMessage: 'Registered Email',
84
- })}
85
- />
86
-
87
- <NotificationsBox />
88
-
89
- <Text
90
- sx={{ marginTop: 'xl', cursor: 'pointer' }}
91
- as={Link}
92
- onClick={onSignUp}
93
- >
94
- {intl.formatMessage({
95
- description: 'Sign up now',
96
- defaultMessage: 'Sign up now',
97
- })}
98
- </Text>
99
- </AuthCard>
100
- </Form>
101
- );
102
- };
@@ -1,158 +0,0 @@
1
- import * as React from 'react';
2
- import { AuthCard } from './AuthCard';
3
- import { Button } from '@ttoss/ui';
4
- import {
5
- Form,
6
- FormFieldInput,
7
- FormFieldPassword,
8
- useForm,
9
- yup,
10
- yupResolver,
11
- } from '@ttoss/forms';
12
- import { NotificationsBox } from '@ttoss/react-notifications';
13
- import { PASSWORD_MINIMUM_LENGTH } from '@ttoss/cloud-auth';
14
- import { useI18n } from '@ttoss/react-i18n';
15
- import type { OnForgotPasswordResetPassword } from './types';
16
-
17
- export type AuthForgotPasswordResetPasswordProps = {
18
- email: string;
19
- onForgotPasswordResetPassword: OnForgotPasswordResetPassword;
20
- onCancel: () => void;
21
- };
22
-
23
- export const AuthForgotPasswordResetPassword = ({
24
- email,
25
- onForgotPasswordResetPassword,
26
- onCancel,
27
- }: AuthForgotPasswordResetPasswordProps) => {
28
- const { intl } = useI18n();
29
-
30
- const schema = React.useMemo(() => {
31
- return yup
32
- .object()
33
- .shape({
34
- code: yup
35
- .string()
36
- .required(
37
- intl.formatMessage({
38
- description: 'Required field.',
39
- defaultMessage: 'Required field',
40
- })
41
- )
42
- .max(
43
- 6,
44
- intl.formatMessage(
45
- {
46
- description: 'Minimum {value} characters.',
47
- defaultMessage: 'Minimum {value} characters',
48
- },
49
- { value: 6 }
50
- )
51
- ),
52
- password: yup
53
- .string()
54
- .required(
55
- intl.formatMessage({
56
- description: 'Password is required.',
57
- defaultMessage: 'Password field is required',
58
- })
59
- )
60
- .min(
61
- PASSWORD_MINIMUM_LENGTH,
62
- intl.formatMessage(
63
- {
64
- description:
65
- 'Password must be at least {value} characters long.',
66
- defaultMessage: 'Password requires {value} characters',
67
- },
68
- { value: PASSWORD_MINIMUM_LENGTH }
69
- )
70
- )
71
- .trim(),
72
- confirmPassword: yup
73
- .string()
74
- .required(
75
- intl.formatMessage({
76
- description: 'Confirm Password is required.',
77
- defaultMessage: 'Confirm password field is required',
78
- })
79
- )
80
- .oneOf(
81
- [yup.ref('password')],
82
- intl.formatMessage({
83
- description: 'Passwords are not the same',
84
- defaultMessage: 'Passwords are not the same',
85
- })
86
- ),
87
- })
88
- .required();
89
- }, [intl]);
90
-
91
- const formMethods = useForm<yup.InferType<typeof schema>>({
92
- resolver: yupResolver(schema),
93
- mode: 'onBlur',
94
- });
95
-
96
- return (
97
- <Form
98
- {...formMethods}
99
- sx={{
100
- maxWidth: '390px',
101
- }}
102
- onSubmit={({ code, password }) => {
103
- return onForgotPasswordResetPassword({
104
- email,
105
- code,
106
- newPassword: password,
107
- });
108
- }}
109
- >
110
- <AuthCard
111
- buttonLabel={intl.formatMessage({
112
- description: 'Recover Password',
113
- defaultMessage: 'Recover Password',
114
- })}
115
- isValidForm={formMethods.formState.isValid}
116
- title={intl.formatMessage({
117
- description: 'Recovering Password',
118
- defaultMessage: 'Recovering Password',
119
- })}
120
- extraButton={
121
- <Button
122
- sx={{ textAlign: 'center', display: 'initial' }}
123
- variant="secondary"
124
- onClick={onCancel}
125
- >
126
- {intl.formatMessage({
127
- description: 'Cancel',
128
- defaultMessage: 'Cancel',
129
- })}
130
- </Button>
131
- }
132
- >
133
- <FormFieldInput
134
- name="code"
135
- label={intl.formatMessage({
136
- description: 'Code',
137
- defaultMessage: 'Code',
138
- })}
139
- />
140
- <FormFieldPassword
141
- name="password"
142
- label={intl.formatMessage({
143
- description: 'Password label.',
144
- defaultMessage: 'Password',
145
- })}
146
- />
147
- <FormFieldPassword
148
- name="confirmPassword"
149
- label={intl.formatMessage({
150
- description: 'Confirm Password label.',
151
- defaultMessage: 'Confirm password',
152
- })}
153
- />
154
- <NotificationsBox />
155
- </AuthCard>
156
- </Form>
157
- );
158
- };
@@ -1,25 +0,0 @@
1
- import { Flex } from '@ttoss/ui';
2
-
3
- export type AuthFullScreenProps = {
4
- backgroundImageUrl?: string;
5
- children: React.ReactNode;
6
- };
7
-
8
- export const AuthFullScreen = ({ children }: AuthFullScreenProps) => {
9
- return (
10
- <Flex
11
- sx={{
12
- height: '100vh',
13
- width: '100vw',
14
- justifyContent: 'center',
15
- alignItems: 'center',
16
- margin: 0,
17
- backgroundPosition: 'center',
18
- backgroundRepeat: 'no-repeat',
19
- backgroundSize: 'cover',
20
- }}
21
- >
22
- {children}
23
- </Flex>
24
- );
25
- };
@@ -1,119 +0,0 @@
1
- import * as React from 'react';
2
- import { Hub } from 'aws-amplify/utils';
3
- import {
4
- signOut as awsSignOut,
5
- fetchAuthSession,
6
- fetchUserAttributes,
7
- getCurrentUser,
8
- } from 'aws-amplify/auth';
9
-
10
- type User = {
11
- id: string;
12
- email: string;
13
- emailVerified: string;
14
- } | null;
15
-
16
- type Tokens = {
17
- idToken: string;
18
- accessToken: string;
19
- refreshToken: string;
20
- } | null;
21
-
22
- const signOut = () => {
23
- return awsSignOut();
24
- };
25
-
26
- const AuthContext = React.createContext<{
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- signOut: () => Promise<any>;
29
- isAuthenticated: boolean;
30
- user: User;
31
- tokens: Tokens;
32
- }>({
33
- signOut,
34
- isAuthenticated: false,
35
- user: null,
36
- tokens: null,
37
- });
38
-
39
- export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
40
- const [{ user, tokens, isAuthenticated }, setAuthState] = React.useState<{
41
- user: User;
42
- tokens: Tokens;
43
- isAuthenticated: boolean | undefined;
44
- }>({
45
- user: null,
46
- tokens: null,
47
- isAuthenticated: undefined,
48
- });
49
-
50
- React.useEffect(() => {
51
- const updateUser = () => {
52
- getCurrentUser()
53
- .then(async ({ userId }) => {
54
- const [session, user] = await Promise.all([
55
- fetchAuthSession(),
56
- fetchUserAttributes(),
57
- ]);
58
-
59
- const idToken = session.tokens?.idToken?.toString() ?? '';
60
- const accessToken = session.tokens?.accessToken.toString() ?? '';
61
-
62
- setAuthState({
63
- user: {
64
- id: userId,
65
- email: user.email ?? '',
66
- emailVerified: user.email_verified ?? '',
67
- },
68
- tokens: {
69
- idToken,
70
- accessToken,
71
- refreshToken: '',
72
- },
73
- isAuthenticated: true,
74
- });
75
- })
76
- .catch((e) => {
77
- // eslint-disable-next-line no-console
78
- console.error(e);
79
- setAuthState({
80
- user: null,
81
- tokens: null,
82
- isAuthenticated: false,
83
- });
84
- });
85
- };
86
-
87
- const updateUserListener = Hub.listen('auth', updateUser);
88
-
89
- /**
90
- * Check manually the first time.
91
- */
92
- updateUser();
93
-
94
- return () => {
95
- updateUserListener();
96
- };
97
- }, []);
98
-
99
- if (isAuthenticated === undefined) {
100
- return null;
101
- }
102
-
103
- return (
104
- <AuthContext.Provider
105
- value={{
106
- signOut,
107
- isAuthenticated,
108
- user,
109
- tokens,
110
- }}
111
- >
112
- {children}
113
- </AuthContext.Provider>
114
- );
115
- };
116
-
117
- export const useAuth = () => {
118
- return React.useContext(AuthContext);
119
- };