[FIX] Change password not working on some cases (#4312)
* create iTotp enum * migrate change user profile to method * Fix minor i18n issues * Use saveUserProfileMethod from Services * Catch cancel event from TwoFactor modal Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
parent
bc09527d78
commit
303d127949
|
@ -0,0 +1,5 @@
|
||||||
|
export enum TwoFactorMethods {
|
||||||
|
TOTP = 'totp',
|
||||||
|
EMAIL = 'email',
|
||||||
|
PASSWORD = 'password'
|
||||||
|
}
|
|
@ -71,6 +71,7 @@
|
||||||
"error-remove-last-owner": "This is the last owner. Please set a new owner before removing this one.",
|
"error-remove-last-owner": "This is the last owner. Please set a new owner before removing this one.",
|
||||||
"error-role-in-use": "Cannot delete role because it's in use",
|
"error-role-in-use": "Cannot delete role because it's in use",
|
||||||
"error-role-name-required": "Role name is required",
|
"error-role-name-required": "Role name is required",
|
||||||
|
"error-password-same-as-current": "Entered password same as current password",
|
||||||
"error-the-field-is-required": "The field {{field}} is required.",
|
"error-the-field-is-required": "The field {{field}} is required.",
|
||||||
"error-too-many-requests": "Error, too many requests. Please slow down. You must wait {{seconds}} seconds before trying again.",
|
"error-too-many-requests": "Error, too many requests. Please slow down. You must wait {{seconds}} seconds before trying again.",
|
||||||
"error-user-is-not-activated": "User is not activated",
|
"error-user-is-not-activated": "User is not activated",
|
||||||
|
@ -836,5 +837,6 @@
|
||||||
"Mark_as_unread": "Mark as unread",
|
"Mark_as_unread": "Mark as unread",
|
||||||
"Mark_as_unread_Info": "Display room as unread when there are unread messages",
|
"Mark_as_unread_Info": "Display room as unread when there are unread messages",
|
||||||
"Show_badge_for_mentions": "Show badge for mentions",
|
"Show_badge_for_mentions": "Show badge for mentions",
|
||||||
"Show_badge_for_mentions_Info": "Display badge for direct mentions only"
|
"Show_badge_for_mentions_Info": "Display badge for direct mentions only",
|
||||||
|
"totp-invalid": "Code or password invalid"
|
||||||
}
|
}
|
|
@ -69,6 +69,7 @@
|
||||||
"error-remove-last-owner": "Este é o último proprietário. Por favor, defina um novo proprietário antes de remover este.",
|
"error-remove-last-owner": "Este é o último proprietário. Por favor, defina um novo proprietário antes de remover este.",
|
||||||
"error-role-in-use": "Não é possível remover o papel pois ele está em uso",
|
"error-role-in-use": "Não é possível remover o papel pois ele está em uso",
|
||||||
"error-role-name-required": "Nome do papel é obrigatório",
|
"error-role-name-required": "Nome do papel é obrigatório",
|
||||||
|
"error-password-same-as-current": "Senha digitada coincide com a senha atual",
|
||||||
"error-the-field-is-required": "O campo {{field}} é obrigatório.",
|
"error-the-field-is-required": "O campo {{field}} é obrigatório.",
|
||||||
"error-too-many-requests": "Erro, muitas solicitações. Por favor, diminua a velocidade. Você deve esperar {{seconds}} segundos antes de tentar novamente.",
|
"error-too-many-requests": "Erro, muitas solicitações. Por favor, diminua a velocidade. Você deve esperar {{seconds}} segundos antes de tentar novamente.",
|
||||||
"error-user-is-not-activated": "O usuário não está ativo",
|
"error-user-is-not-activated": "O usuário não está ativo",
|
||||||
|
@ -743,5 +744,6 @@
|
||||||
"sending_email_confirmation": "enviando email de confirmação",
|
"sending_email_confirmation": "enviando email de confirmação",
|
||||||
"Unsupported_format": "Formato não suportado",
|
"Unsupported_format": "Formato não suportado",
|
||||||
"Downloaded_file": "Arquivo baixado",
|
"Downloaded_file": "Arquivo baixado",
|
||||||
"Error_Download_file": "Erro ao baixar o arquivo"
|
"Error_Download_file": "Erro ao baixar o arquivo",
|
||||||
|
"totp-invalid": "Código ou senha inválida"
|
||||||
}
|
}
|
|
@ -918,6 +918,15 @@ export function getUserInfo(userId: string) {
|
||||||
|
|
||||||
export const toggleFavorite = (roomId: string, favorite: boolean) => sdk.post('rooms.favorite', { roomId, favorite });
|
export const toggleFavorite = (roomId: string, favorite: boolean) => sdk.post('rooms.favorite', { roomId, favorite });
|
||||||
|
|
||||||
|
export const saveUserProfileMethod = (
|
||||||
|
params: IProfileParams,
|
||||||
|
customFields = {},
|
||||||
|
twoFactorOptions: {
|
||||||
|
twoFactorCode: string;
|
||||||
|
twoFactorMethod: string;
|
||||||
|
} | null
|
||||||
|
) => sdk.current.methodCall('saveUserProfile', params, customFields, twoFactorOptions);
|
||||||
|
|
||||||
export const deleteOwnAccount = (password: string, confirmRelinquish = false): any =>
|
export const deleteOwnAccount = (password: string, confirmRelinquish = false): any =>
|
||||||
// RC 0.67.0
|
// RC 0.67.0
|
||||||
sdk.post('users.deleteOwnAccount', { password, confirmRelinquish });
|
sdk.post('users.deleteOwnAccount', { password, confirmRelinquish });
|
||||||
|
|
|
@ -41,6 +41,8 @@ import {
|
||||||
IProfileParams,
|
IProfileParams,
|
||||||
IUser
|
IUser
|
||||||
} from '../../definitions';
|
} from '../../definitions';
|
||||||
|
import { twoFactor } from '../../lib/services/twoFactor';
|
||||||
|
import { TwoFactorMethods } from '../../definitions/ITotp';
|
||||||
import { withActionSheet, IActionSheetProvider } from '../../containers/ActionSheet';
|
import { withActionSheet, IActionSheetProvider } from '../../containers/ActionSheet';
|
||||||
import { DeleteAccountActionSheetContent } from './components/DeleteAccountActionSheetContent';
|
import { DeleteAccountActionSheetContent } from './components/DeleteAccountActionSheetContent';
|
||||||
|
|
||||||
|
@ -71,6 +73,10 @@ interface IProfileViewState {
|
||||||
customFields: {
|
customFields: {
|
||||||
[key: string | number]: string;
|
[key: string | number]: string;
|
||||||
};
|
};
|
||||||
|
twoFactorCode: null | {
|
||||||
|
twoFactorCode: string;
|
||||||
|
twoFactorMethod: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProfileView extends React.Component<IProfileViewProps, IProfileViewState> {
|
class ProfileView extends React.Component<IProfileViewProps, IProfileViewState> {
|
||||||
|
@ -113,7 +119,8 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
avatarSuggestions: {},
|
avatarSuggestions: {},
|
||||||
customFields: {}
|
customFields: {},
|
||||||
|
twoFactorCode: null
|
||||||
};
|
};
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
|
@ -194,14 +201,17 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleError = (e: any, func: string, action: string) => {
|
handleError = (e: any, _func: string, action: string) => {
|
||||||
if (e.data && e.data.error.includes('[error-too-many-requests]')) {
|
if (e.data && e.data.error.includes('[error-too-many-requests]')) {
|
||||||
return showErrorAlert(e.data.error);
|
return showErrorAlert(e.data.error);
|
||||||
}
|
}
|
||||||
|
if (I18n.isTranslated(e.error)) {
|
||||||
|
return showErrorAlert(I18n.t(e.error));
|
||||||
|
}
|
||||||
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t(action) }));
|
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t(action) }));
|
||||||
};
|
};
|
||||||
|
|
||||||
submit = async () => {
|
submit = async (): Promise<void> => {
|
||||||
Keyboard.dismiss();
|
Keyboard.dismiss();
|
||||||
|
|
||||||
if (!this.formIsChanged()) {
|
if (!this.formIsChanged()) {
|
||||||
|
@ -210,7 +220,7 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
||||||
|
|
||||||
this.setState({ saving: true });
|
this.setState({ saving: true });
|
||||||
|
|
||||||
const { name, username, email, newPassword, currentPassword, avatar, customFields } = this.state;
|
const { name, username, email, newPassword, currentPassword, avatar, customFields, twoFactorCode } = this.state;
|
||||||
const { user, dispatch } = this.props;
|
const { user, dispatch } = this.props;
|
||||||
const params = {} as IProfileParams;
|
const params = {} as IProfileParams;
|
||||||
|
|
||||||
|
@ -275,9 +285,16 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await Services.saveUserProfile(params, customFields);
|
const twoFactorOptions = params.currentPassword
|
||||||
|
? {
|
||||||
|
twoFactorCode: params.currentPassword,
|
||||||
|
twoFactorMethod: TwoFactorMethods.PASSWORD
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
if (result.success) {
|
const result = await Services.saveUserProfileMethod(params, customFields, twoFactorCode || twoFactorOptions);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
logEvent(events.PROFILE_SAVE_CHANGES);
|
logEvent(events.PROFILE_SAVE_CHANGES);
|
||||||
if (customFields) {
|
if (customFields) {
|
||||||
dispatch(setUser({ customFields, ...params }));
|
dispatch(setUser({ customFields, ...params }));
|
||||||
|
@ -287,10 +304,18 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
||||||
EventEmitter.emit(LISTENER, { message: I18n.t('Profile_saved_successfully') });
|
EventEmitter.emit(LISTENER, { message: I18n.t('Profile_saved_successfully') });
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
this.setState({ saving: false });
|
this.setState({ saving: false, currentPassword: null, twoFactorCode: null });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
|
if (e?.error === 'totp-invalid' && e?.details.method !== TwoFactorMethods.PASSWORD) {
|
||||||
|
try {
|
||||||
|
const code = await twoFactor({ method: e?.details.method, invalid: e?.error === 'totp-invalid' && !!twoFactorCode });
|
||||||
|
return this.setState({ twoFactorCode: code }, () => this.submit());
|
||||||
|
} catch {
|
||||||
|
// cancelled twoFactor modal
|
||||||
|
}
|
||||||
|
}
|
||||||
logEvent(events.PROFILE_SAVE_CHANGES_F);
|
logEvent(events.PROFILE_SAVE_CHANGES_F);
|
||||||
this.setState({ saving: false, currentPassword: null });
|
this.setState({ saving: false, currentPassword: null, twoFactorCode: null });
|
||||||
this.handleError(e, 'saveUserProfile', 'saving_profile');
|
this.handleError(e, 'saveUserProfile', 'saving_profile');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue