forgot password and google registration

This commit is contained in:
Gustavo Fuhr 2022-12-01 17:59:35 -03:00
parent da5dea533e
commit 0440d8b87f
19 changed files with 287 additions and 23 deletions

View File

@ -542,5 +542,17 @@
},
"registation.callback.error.message": {
"defaultMessage": "Beim Überprüfen Ihrer Identität bei Google ist ein Fehler aufgetreten. Sie können es auf der Anmeldeseite erneut versuchen"
},
"registration.callback.back": {
"defaultMessage": "Zurück zur Anmeldung"
},
"registration.callback.sync": {
"defaultMessage": "Konto synchronisieren"
},
"forgot.oauth.message": {
"defaultMessage": "Sie benötigen kein Passwort, bitte melden Sie sich mit Google an"
},
"forgot.oauth.back": {
"defaultMessage": "Zurück zur Anmeldung"
}
}

View File

@ -538,6 +538,18 @@
},
"registation.callback.error.message": {
"defaultMessage": "An error occurred validating your identity with Google, you can try again from the login page"
},
"registration.callback.back": {
"defaultMessage": "Back to login"
},
"registration.callback.sync": {
"defaultMessage": "Sync account"
},
"forgot.oauth.message": {
"defaultMessage": "You dont need password, please login using Google"
},
"forgot.oauth.back": {
"defaultMessage": "Back to login"
}
}

View File

@ -518,5 +518,17 @@
},
"registation.callback.error.message": {
"defaultMessage": "Ocurrió un error al validar tu identidad con Google, puedes volver a intentarlo desde la página de inicio de sesión"
},
"registration.callback.back": {
"defaultMessage": "Volver"
},
"registration.callback.sync": {
"defaultMessage": "Sincronizar cuenta"
},
"forgot.oauth.message": {
"defaultMessage": "No necesitas contraseña, por favor ingresa usando Google"
},
"forgot.oauth.back": {
"defaultMessage": "Volver"
}
}

View File

@ -545,5 +545,17 @@
},
"registation.callback.error.message": {
"defaultMessage": "Une erreur s'est produite lors de la validation de votre identité auprès de Google, vous pouvez réessayer depuis la page de connexion"
},
"registration.callback.back": {
"defaultMessage": "Retour connexion"
},
"registration.callback.sync": {
"defaultMessage": "Compte de synchronisation"
},
"forgot.oauth.message": {
"defaultMessage": "Vous n'avez pas besoin de mot de passe, veuillez vous connecter en utilisant Google"
},
"forgot.oauth.back": {
"defaultMessage": "Retour connexion"
}
}

View File

@ -512,5 +512,17 @@
},
"registation.callback.error.message": {
"defaultMessage": "Произошла ошибка при подтверждении вашей личности в Google. Повторите попытку со страницы входа."
},
"registration.callback.back": {
"defaultMessage": "Вернуться на страницу авторизации"
},
"registration.callback.sync": {
"defaultMessage": "Синхронизировать учетную запись"
},
"forgot.oauth.message": {
"defaultMessage": "Вам не нужен пароль, пожалуйста, войдите с помощью Google"
},
"forgot.oauth.back": {
"defaultMessage": "Вернуться на страницу авторизации"
}
}

View File

@ -539,5 +539,17 @@
},
"registation.callback.error.message": {
"defaultMessage": "使用 Google 验证您的身份时出错,您可以从登录页面重试"
},
"registration.callback.back": {
"defaultMessage": "回到登入"
},
"registration.callback.sync": {
"defaultMessage": "同步账户"
},
"forgot.oauth.message": {
"defaultMessage": "您不需要密码,请使用谷歌登录"
},
"forgot.oauth.back": {
"defaultMessage": "回到登入"
}
}

View File

@ -8,6 +8,7 @@ import Client, {
NewUser,
Permission,
Oauth2CallbackResult,
ForgotPasswordResult,
} from '..';
import { LocaleCode } from '../../app-i18n';
@ -126,7 +127,7 @@ class CacheDecoratorClient implements Client {
return this.client.registerNewUser(user);
}
resetPassword(email: string): Promise<void> {
resetPassword(email: string): Promise<ForgotPasswordResult> {
return this.client.resetPassword(email);
}

View File

@ -58,11 +58,14 @@ export type ErrorInfo = {
fields?: Map<string, string>;
};
export type AuthenticationType = 'GOOGLE_OAUTH2' | 'DATABASE' | 'LDAP';
export type AccountInfo = {
firstname: string;
lastname: string;
email: string;
locale?: Locale;
authenticationType: AuthenticationType;
};
export type Permission = {
@ -77,6 +80,10 @@ export type Oauth2CallbackResult = {
syncCode?: string;
};
export type ForgotPasswordResult = {
action: 'EMAIL_SENT' | 'OAUTH2_USER';
};
interface Client {
deleteAccount(): Promise<void>;
importMap(model: ImportMapInfo): Promise<number>;
@ -109,7 +116,7 @@ interface Client {
fetchAccountInfo(): Promise<AccountInfo>;
registerNewUser(user: NewUser): Promise<void>;
resetPassword(email: string): Promise<void>;
resetPassword(email: string): Promise<ForgotPasswordResult>;
processGoogleCallback(code: string): Promise<Oauth2CallbackResult>;
confirmAccountSync(email: string, code: string): Promise<void>;

View File

@ -25,6 +25,7 @@ import Client, {
NewUser,
Permission,
Oauth2CallbackResult,
ForgotPasswordResult,
} from '..';
import { LocaleCode, localeFromStr } from '../../app-i18n';
@ -205,6 +206,7 @@ class MockClient implements Client {
lastname: 'Fulanito',
email: 'test@example.com',
locale: localeFromStr(locale),
authenticationType: 'DATABASE',
});
}
@ -403,9 +405,9 @@ class MockClient implements Client {
return Promise.resolve(this.maps);
}
resetPassword(email: string): Promise<void> {
resetPassword(email: string): Promise<ForgotPasswordResult> {
console.log('email:' + email);
return Promise.resolve();
return Promise.resolve({ action: 'EMAIL_SENT' });
}
wait(ms: number): Promise<number> {

View File

@ -10,6 +10,7 @@ import Client, {
ImportMapInfo,
Permission,
Oauth2CallbackResult,
ForgotPasswordResult,
} from '..';
import { getCsrfToken } from '../../../utils';
import { LocaleCode, localeFromStr } from '../../app-i18n';
@ -263,6 +264,7 @@ export default class RestClient implements Client {
firstname: account.firstname ? account.firstname : '',
email: account.email,
locale: locale ? localeFromStr(locale) : undefined,
authenticationType: account.authenticationType,
});
})
.catch((error) => {
@ -473,8 +475,11 @@ export default class RestClient implements Client {
return new Promise(handler);
}
resetPassword(email: string): Promise<void> {
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
resetPassword(email: string): Promise<ForgotPasswordResult> {
const handler = (
success: (result: ForgotPasswordResult) => void,
reject: (error: ErrorInfo) => void,
) => {
this.axios
.put(
`${this.baseUrl}/service/users/resetPassword?email=${encodeURIComponent(email)}`,
@ -483,9 +488,9 @@ export default class RestClient implements Client {
headers: { 'Content-Type': 'application/json' },
},
)
.then(() => {
// All was ok, let's sent to success page ...;
success();
.then((response) => {
// All was ok, lets return if an email was sent or the user should login with oauth
success({ action: response.data.action });
})
.catch((error) => {
const response = error.response;

View File

@ -383,6 +383,18 @@
"value": "E-Mail"
}
],
"forgot.oauth.back": [
{
"type": 0,
"value": "Zurück zur Anmeldung"
}
],
"forgot.oauth.message": [
{
"type": 0,
"value": "Sie benötigen kein Passwort, bitte melden Sie sich mit Google an"
}
],
"forgot.page-title": [
{
"type": 0,
@ -927,6 +939,12 @@
"value": "Registrierung erfolgreich | WiseMapping"
}
],
"registration.callback.back": [
{
"type": 0,
"value": "Zurück zur Anmeldung"
}
],
"registration.callback.confirm.description": [
{
"type": 0,
@ -939,6 +957,12 @@
"value": "Bestätigen"
}
],
"registration.callback.sync": [
{
"type": 0,
"value": "Konto synchronisieren"
}
],
"registration.callback.waiting.description": [
{
"type": 0,

View File

@ -377,6 +377,18 @@
"value": "Email"
}
],
"forgot.oauth.back": [
{
"type": 0,
"value": "Back to login"
}
],
"forgot.oauth.message": [
{
"type": 0,
"value": "You dont need password, please login using Google"
}
],
"forgot.page-title": [
{
"type": 0,
@ -919,6 +931,12 @@
"value": "Registation Success | WiseMapping"
}
],
"registration.callback.back": [
{
"type": 0,
"value": "Back to login"
}
],
"registration.callback.confirm.description": [
{
"type": 0,
@ -931,6 +949,12 @@
"value": "Confirm"
}
],
"registration.callback.sync": [
{
"type": 0,
"value": "Sync account"
}
],
"registration.callback.waiting.description": [
{
"type": 0,

View File

@ -377,6 +377,18 @@
"value": "Correo electrónico"
}
],
"forgot.oauth.back": [
{
"type": 0,
"value": "Volver"
}
],
"forgot.oauth.message": [
{
"type": 0,
"value": "No necesitas contraseña, por favor ingresa usando Google"
}
],
"forgot.page-title": [
{
"type": 0,
@ -873,6 +885,12 @@
"value": "Éxito de registro | WiseMapping"
}
],
"registration.callback.back": [
{
"type": 0,
"value": "Volver"
}
],
"registration.callback.confirm.description": [
{
"type": 0,
@ -885,6 +903,12 @@
"value": "Confirmación"
}
],
"registration.callback.sync": [
{
"type": 0,
"value": "Sincronizar cuenta"
}
],
"registration.callback.waiting.description": [
{
"type": 0,

View File

@ -375,6 +375,18 @@
"value": "E-mail"
}
],
"forgot.oauth.back": [
{
"type": 0,
"value": "Retour connexion"
}
],
"forgot.oauth.message": [
{
"type": 0,
"value": "Vous n'avez pas besoin de mot de passe, veuillez vous connecter en utilisant Google"
}
],
"forgot.page-title": [
{
"type": 0,
@ -919,6 +931,12 @@
"value": "Inscription réussie | WiseMapping"
}
],
"registration.callback.back": [
{
"type": 0,
"value": "Retour connexion"
}
],
"registration.callback.confirm.description": [
{
"type": 0,
@ -931,6 +949,12 @@
"value": "Confirmer"
}
],
"registration.callback.sync": [
{
"type": 0,
"value": "Compte de synchronisation"
}
],
"registration.callback.waiting.description": [
{
"type": 0,

View File

@ -371,6 +371,18 @@
"value": "Email"
}
],
"forgot.oauth.back": [
{
"type": 0,
"value": "Вернуться на страницу авторизации"
}
],
"forgot.oauth.message": [
{
"type": 0,
"value": "Вам не нужен пароль, пожалуйста, войдите с помощью Google"
}
],
"forgot.page-title": [
{
"type": 0,
@ -867,6 +879,12 @@
"value": "Успешная регистрация | WiseMapping"
}
],
"registration.callback.back": [
{
"type": 0,
"value": "Вернуться на страницу авторизации"
}
],
"registration.callback.confirm.description": [
{
"type": 0,
@ -879,6 +897,12 @@
"value": "Подтверждать"
}
],
"registration.callback.sync": [
{
"type": 0,
"value": "Синхронизировать учетную запись"
}
],
"registration.callback.waiting.description": [
{
"type": 0,

View File

@ -371,6 +371,18 @@
"value": "电子邮件"
}
],
"forgot.oauth.back": [
{
"type": 0,
"value": "回到登入"
}
],
"forgot.oauth.message": [
{
"type": 0,
"value": "您不需要密码,请使用谷歌登录"
}
],
"forgot.page-title": [
{
"type": 0,
@ -915,6 +927,12 @@
"value": "注册成功|WiseMapping"
}
],
"registration.callback.back": [
{
"type": 0,
"value": "回到登入"
}
],
"registration.callback.confirm.description": [
{
"type": 0,
@ -927,6 +945,12 @@
"value": "确认"
}
],
"registration.callback.sync": [
{
"type": 0,
"value": "同步账户"
}
],
"registration.callback.waiting.description": [
{
"type": 0,

View File

@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import { FormattedMessage, useIntl } from 'react-intl';
import Client, { ErrorInfo } from '../../classes/client';
import Client, { ErrorInfo, ForgotPasswordResult } from '../../classes/client';
import Header from '../layout/header';
import Footer from '../layout/footer';
@ -12,22 +12,29 @@ import Input from '../form/input';
import GlobalError from '../form/global-error';
import SubmitButton from '../form/submit-button';
import ReactGA from 'react-ga4';
import { Link as RouterLink } from 'react-router-dom';
import Typography from '@mui/material/Typography';
import { getCsrfToken, getCsrfTokenParameter } from '../../utils';
import { useNavigate } from 'react-router-dom';
import StyledAlert from '../form/global-error/styled';
import { Button } from '@mui/material';
const ForgotPassword = () => {
const [email, setEmail] = useState<string>('');
const [error, setError] = useState<ErrorInfo>();
const [showOauthMessage, setShowOauthMessage] = useState<boolean>(false);
const navigate = useNavigate();
const intl = useIntl();
const service: Client = useSelector(activeInstance);
const mutation = useMutation<void, ErrorInfo, string>(
const mutation = useMutation<ForgotPasswordResult, ErrorInfo, string>(
(email: string) => service.resetPassword(email),
{
onSuccess: () => navigate('/c/forgot-password-success'),
onSuccess: (result) => {
if (result.action === 'EMAIL_SENT') navigate('/c/forgot-password-success');
if (result.action === 'OAUTH2_USER') setShowOauthMessage(true);
},
onError: (error) => {
setError(error);
},
@ -39,6 +46,29 @@ const ForgotPassword = () => {
mutation.mutate(email);
};
if (showOauthMessage) {
return (
<FormContainer>
<Typography>
<FormattedMessage
id="forgot.oauth.message"
defaultMessage="You dont need password, please login using Google."
/>
</Typography>
<Button
color="primary"
size="medium"
variant="contained"
component={RouterLink}
to="/c/login"
disableElevation={true}
>
<FormattedMessage id="forgot.oauth.back" defaultMessage="Back to login" />
</Button>
</FormContainer>
);
}
return (
<FormContainer>
<Typography variant="h4" component="h1">
@ -93,7 +123,7 @@ const ForgotPasswordPage = (): React.ReactElement => {
return (
<div>
<Header type="only-signin" />
<ForgotPassword />
{<ForgotPassword />}
<Footer />
</div>
);

View File

@ -71,16 +71,18 @@ const AccountMenu = (): React.ReactElement => {
<FormattedMessage id="menu.account" defaultMessage="Account" />
</MenuItem>
<MenuItem
onClick={() => {
handleClose(), setAction('change-password');
}}
>
<ListItemIcon>
<LockOpenOutlined fontSize="small" />
</ListItemIcon>
<FormattedMessage id="menu.change-password" defaultMessage="Change password" />
</MenuItem>
{account?.authenticationType !== 'GOOGLE_OAUTH2' && (
<MenuItem
onClick={() => {
handleClose(), setAction('change-password');
}}
>
<ListItemIcon>
<LockOpenOutlined fontSize="small" />
</ListItemIcon>
<FormattedMessage id="menu.change-password" defaultMessage="Change password" />
</MenuItem>
)}
<MenuItem onClick={handleClose}>
<form action="/c/logout" method="POST" id="logoutFrom"></form>

View File

@ -51,6 +51,7 @@ const theme = createTheme({
h4: {
color: '#ffa800',
fontWeight: 600,
marginBottom: '10px',
},
h6: {
fontSize: '25px',