mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-12-29 08:20:21 +05:30
Remove change password auth panel
This commit is contained in:
parent
cb1a4b7d55
commit
6dcf985936
@ -32,7 +32,6 @@ const changeContextSpringConfig = {stiffness: 500, damping: 20, precision: 0.5};
|
||||
const contexts = [
|
||||
['login', 'password', 'forgotPassword', 'recoverPassword'],
|
||||
['register', 'activation', 'resendActivation'],
|
||||
['changePassword'],
|
||||
['acceptRules'],
|
||||
['permissions']
|
||||
];
|
||||
|
@ -10,6 +10,8 @@ To add new panel you need to:
|
||||
* connect component to `routes`
|
||||
* whatever else you need
|
||||
|
||||
Commit id with example: f4d315c
|
||||
|
||||
# TODO
|
||||
|
||||
This flow must be simplified
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { routeActions } from 'react-router-redux';
|
||||
|
||||
import { updateUser, logout as logoutUser, changePassword as changeUserPassword, acceptRules as userAcceptRules, authenticate } from 'components/user/actions';
|
||||
import { updateUser, logout as logoutUser, acceptRules as userAcceptRules, authenticate } from 'components/user/actions';
|
||||
import authentication from 'services/api/authentication';
|
||||
import oauth from 'services/api/oauth';
|
||||
import signup from 'services/api/signup';
|
||||
@ -35,17 +35,6 @@ export function login({login = '', password = '', rememberMe = false}) {
|
||||
);
|
||||
}
|
||||
|
||||
export function changePassword({
|
||||
password = '',
|
||||
newPassword = '',
|
||||
newRePassword = ''
|
||||
}) {
|
||||
return wrapInLoader((dispatch) =>
|
||||
dispatch(changeUserPassword({password, newPassword, newRePassword, logoutAll: false}))
|
||||
.catch(validationErrorsHandler(dispatch))
|
||||
);
|
||||
}
|
||||
|
||||
export function acceptRules() {
|
||||
return wrapInLoader((dispatch) =>
|
||||
dispatch(userAcceptRules())
|
||||
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"changePasswordTitle": "Change password",
|
||||
"changePasswordMessage": "To enhance the security of your account, please change your password.",
|
||||
"skipThisStep": "Skip password changing",
|
||||
"change": "Change password",
|
||||
"currentPassword": "Enter current password",
|
||||
"newPassword": "Enter new password",
|
||||
"newRePassword": "Repeat new password"
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import factory from 'components/auth/factory';
|
||||
|
||||
import Body from './ChangePasswordBody';
|
||||
import messages from './ChangePassword.intl.json';
|
||||
|
||||
export default factory({
|
||||
title: messages.changePasswordTitle,
|
||||
body: Body,
|
||||
footer: {
|
||||
color: 'darkBlue',
|
||||
label: messages.change
|
||||
},
|
||||
links: {
|
||||
label: messages.skipThisStep
|
||||
}
|
||||
});
|
@ -1,57 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { FormattedMessage as Message } from 'react-intl';
|
||||
|
||||
import { Input } from 'components/ui/form';
|
||||
import icons from 'components/ui/icons.scss';
|
||||
import BaseAuthBody from 'components/auth/BaseAuthBody';
|
||||
|
||||
import styles from './changePassword.scss';
|
||||
import messages from './ChangePassword.intl.json';
|
||||
|
||||
export default class ChangePasswordBody extends BaseAuthBody {
|
||||
static displayName = 'ChangePasswordBody';
|
||||
static panelId = 'changePassword';
|
||||
|
||||
autoFocusField = 'password';
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this.renderErrors()}
|
||||
|
||||
<div className={styles.security}>
|
||||
<span className={icons.lock} />
|
||||
</div>
|
||||
|
||||
<p className={styles.descriptionText}>
|
||||
<Message {...messages.changePasswordMessage} />
|
||||
</p>
|
||||
|
||||
<Input {...this.bindField('password')}
|
||||
icon="key"
|
||||
color="darkBlue"
|
||||
type="password"
|
||||
required
|
||||
placeholder={messages.currentPassword}
|
||||
/>
|
||||
|
||||
<Input {...this.bindField('newPassword')}
|
||||
icon="key"
|
||||
color="darkBlue"
|
||||
type="password"
|
||||
required
|
||||
placeholder={messages.newPassword}
|
||||
/>
|
||||
|
||||
<Input {...this.bindField('newRePassword')}
|
||||
icon="key"
|
||||
color="darkBlue"
|
||||
type="password"
|
||||
required
|
||||
placeholder={messages.newRePassword}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
@import '~components/ui/colors.scss';
|
||||
|
||||
.descriptionText {
|
||||
font-size: 15px;
|
||||
line-height: 1.4;
|
||||
padding-bottom: 8px;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
// TODO: вынести иконки такого типа в какую-то внешнюю структуру?
|
||||
.security {
|
||||
color: #fff;
|
||||
font-size: 90px;
|
||||
line-height: 1;
|
||||
margin-bottom: 15px;
|
||||
}
|
@ -25,8 +25,6 @@ export default class ForgotPasswordBody extends BaseAuthBody {
|
||||
const login = user.email || user.username || '';
|
||||
const isLoginEditShown = this.state.isLoginEdit;
|
||||
|
||||
// TODO: нужно парсить инфу о том, какой кд у отправки кода и во сколько точно можно будет повторить
|
||||
|
||||
return (
|
||||
<div>
|
||||
{this.renderErrors()}
|
||||
|
@ -5,5 +5,8 @@
|
||||
"messageWasSentTo": "The recovery code was sent to your E‑mail {email}.",
|
||||
"enterCodeBelow": "Please enter the code received into the field below:",
|
||||
"enterNewPasswordBelow": "Enter and repeat new password below:",
|
||||
"change": "Change password",
|
||||
"newPassword": "Enter new password",
|
||||
"newRePassword": "Repeat new password",
|
||||
"enterTheCode": "Enter confirmation code"
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import factory from 'components/auth/factory';
|
||||
import changePassword from 'components/auth/changePassword/ChangePassword.intl.json';
|
||||
|
||||
import messages from './RecoverPassword.intl.json';
|
||||
import Body from './RecoverPasswordBody';
|
||||
@ -9,7 +8,7 @@ export default factory({
|
||||
body: Body,
|
||||
footer: {
|
||||
color: 'lightViolet',
|
||||
label: changePassword.change
|
||||
label: messages.change
|
||||
},
|
||||
links: {
|
||||
label: messages.contactSupport
|
||||
|
@ -4,13 +4,11 @@ import { FormattedMessage as Message } from 'react-intl';
|
||||
|
||||
import { Input } from 'components/ui/form';
|
||||
import BaseAuthBody from 'components/auth/BaseAuthBody';
|
||||
import changePassword from 'components/auth/changePassword/ChangePassword.intl.json';
|
||||
|
||||
import styles from './recoverPassword.scss';
|
||||
import messages from './RecoverPassword.intl.json';
|
||||
|
||||
// TODO: activation code field may be decoupled into common component and reused here and in activation panel
|
||||
// TODO: new password fields may be decoupled into common component and reused here and in changePassword panel
|
||||
|
||||
export default class RecoverPasswordBody extends BaseAuthBody {
|
||||
static displayName = 'RecoverPasswordBody';
|
||||
@ -64,7 +62,7 @@ export default class RecoverPasswordBody extends BaseAuthBody {
|
||||
color="lightViolet"
|
||||
type="password"
|
||||
required
|
||||
placeholder={changePassword.newPassword}
|
||||
placeholder={messages.newPassword}
|
||||
/>
|
||||
|
||||
<Input {...this.bindField('newRePassword')}
|
||||
@ -72,7 +70,7 @@ export default class RecoverPasswordBody extends BaseAuthBody {
|
||||
color="lightViolet"
|
||||
type="password"
|
||||
required
|
||||
placeholder={changePassword.newRePassword}
|
||||
placeholder={messages.newRePassword}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -5,7 +5,6 @@
|
||||
"preferencesDescription": "Here you can change the key preferences of your account. Please note that all actions must be confirmed by entering a password.",
|
||||
"mojangPriorityWarning": "A Mojang account with the same nickname was found. According to {rules}, account owner has the right to demand the restoration of control over nickname.",
|
||||
"projectRules": "project rules",
|
||||
"oldHashingAlgoWarning": "Your was hashed with an old hashing algorithm.<br />Please, change password.",
|
||||
"changedAt": "Changed {at}",
|
||||
"disabled": "Disabled",
|
||||
"nickname": "Nickname",
|
||||
|
@ -83,9 +83,6 @@ export default class Profile extends Component {
|
||||
value={<Message {...messages.changedAt} values={{
|
||||
at: (<Relative value={user.passwordChangedAt * 1000} updateInterval={1000} />)
|
||||
}} />}
|
||||
warningMessage={user.shouldChangePassword ? (
|
||||
<HTMLMessage {...messages.oldHashingAlgoWarning} />
|
||||
) : ''}
|
||||
/>
|
||||
|
||||
<ProfileField
|
||||
|
@ -31,7 +31,6 @@ export default class User {
|
||||
isGuest: true,
|
||||
isActive: false,
|
||||
shouldAcceptRules: false, // whether user need to review updated rules
|
||||
shouldChangePassword: false, // TODO: нужно ещё пробросить причину необходимости смены
|
||||
passwordChangedAt: null,
|
||||
hasMojangUsernameCollision: false,
|
||||
};
|
||||
|
@ -69,26 +69,6 @@ export function fetchUserData() {
|
||||
});
|
||||
}
|
||||
|
||||
export function changePassword({
|
||||
password = '',
|
||||
newPassword = '',
|
||||
newRePassword = '',
|
||||
logoutAll = true,
|
||||
}) {
|
||||
return (dispatch) =>
|
||||
accounts.changePassword(
|
||||
{password, newPassword, newRePassword, logoutAll}
|
||||
)
|
||||
.then((resp) => {
|
||||
dispatch(updateUser({
|
||||
shouldChangePassword: false
|
||||
}));
|
||||
|
||||
return resp;
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
export function acceptRules() {
|
||||
return (dispatch) =>
|
||||
accounts.acceptRules()
|
||||
|
@ -31,8 +31,7 @@ class ChangePasswordPage extends Component {
|
||||
sendData: () => accounts.changePassword(form.serialize())
|
||||
}).then(() => {
|
||||
this.props.updateUser({
|
||||
passwordChangedAt: Date.now() / 1000,
|
||||
shouldChangePassword: false
|
||||
passwordChangedAt: Date.now() / 1000
|
||||
});
|
||||
this.context.goToProfile();
|
||||
});
|
||||
|
@ -20,7 +20,6 @@ import Permissions from 'components/auth/permissions/Permissions';
|
||||
import Activation from 'components/auth/activation/Activation';
|
||||
import ResendActivation from 'components/auth/resendActivation/ResendActivation';
|
||||
import Password from 'components/auth/password/Password';
|
||||
import ChangePassword from 'components/auth/changePassword/ChangePassword';
|
||||
import AcceptRules from 'components/auth/acceptRules/AcceptRules';
|
||||
import ForgotPassword from 'components/auth/forgotPassword/ForgotPassword';
|
||||
import RecoverPassword from 'components/auth/recoverPassword/RecoverPassword';
|
||||
@ -62,7 +61,6 @@ export default function routesFactory(store) {
|
||||
<Route path="/oauth/permissions" components={new Permissions()} {...startAuthFlow} />
|
||||
<Route path="/oauth/finish" component={Finish} {...startAuthFlow} />
|
||||
<Route path="/accept-rules" components={new AcceptRules()} {...startAuthFlow} />
|
||||
<Route path="/change-password" components={new ChangePassword()} {...startAuthFlow} />
|
||||
<Route path="/forgot-password" components={new ForgotPassword()} {...startAuthFlow} />
|
||||
<Route path="/recover-password(/:key)" components={new RecoverPassword()} {...startAuthFlow} />
|
||||
</Route>
|
||||
|
@ -5,18 +5,6 @@ export default {
|
||||
return request.get('/api/accounts/current');
|
||||
},
|
||||
|
||||
changePassword({
|
||||
password = '',
|
||||
newPassword = '',
|
||||
newRePassword = '',
|
||||
logoutAll = true
|
||||
}) {
|
||||
return request.post(
|
||||
'/api/accounts/change-password',
|
||||
{password, newPassword, newRePassword, logoutAll}
|
||||
);
|
||||
},
|
||||
|
||||
acceptRules() {
|
||||
return request.post('/api/accounts/accept-rules');
|
||||
},
|
||||
|
@ -144,7 +144,6 @@ export default class AuthFlow {
|
||||
case '/login':
|
||||
case '/password':
|
||||
case '/accept-rules':
|
||||
case '/change-password':
|
||||
case '/oauth/permissions':
|
||||
case '/oauth/finish':
|
||||
this.setState(new LoginState());
|
||||
|
@ -1,20 +0,0 @@
|
||||
import AbstractState from './AbstractState';
|
||||
import CompleteState from './CompleteState';
|
||||
|
||||
export default class ChangePasswordState extends AbstractState {
|
||||
enter(context) {
|
||||
context.navigate('/change-password');
|
||||
}
|
||||
|
||||
resolve(context, payload) {
|
||||
context.run('changePassword', payload)
|
||||
.then(() => context.setState(new CompleteState()));
|
||||
}
|
||||
|
||||
reject(context) {
|
||||
context.run('updateUser', {
|
||||
shouldChangePassword: false
|
||||
});
|
||||
context.setState(new CompleteState());
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ import AbstractState from './AbstractState';
|
||||
import LoginState from './LoginState';
|
||||
import PermissionsState from './PermissionsState';
|
||||
import ActivationState from './ActivationState';
|
||||
import ChangePasswordState from './ChangePasswordState';
|
||||
import AcceptRulesState from './AcceptRulesState';
|
||||
import FinishState from './FinishState';
|
||||
|
||||
@ -22,8 +21,6 @@ export default class CompleteState extends AbstractState {
|
||||
context.setState(new ActivationState());
|
||||
} else if (user.shouldAcceptRules) {
|
||||
context.setState(new AcceptRulesState());
|
||||
} else if (user.shouldChangePassword) {
|
||||
context.setState(new ChangePasswordState());
|
||||
} else if (auth.oauth && auth.oauth.clientId) {
|
||||
if (auth.oauth.code) {
|
||||
context.setState(new FinishState());
|
||||
|
@ -12,8 +12,6 @@ import ActivationState from 'services/authFlow/ActivationState';
|
||||
import ResendActivationState from 'services/authFlow/ResendActivationState';
|
||||
import LoginState from 'services/authFlow/LoginState';
|
||||
|
||||
// TODO: navigate and state switching
|
||||
|
||||
describe('AuthFlow', () => {
|
||||
let flow;
|
||||
let actions;
|
||||
@ -178,7 +176,6 @@ describe('AuthFlow', () => {
|
||||
'/': LoginState,
|
||||
'/login': LoginState,
|
||||
'/password': LoginState,
|
||||
'/change-password': LoginState,
|
||||
'/accept-rules': LoginState,
|
||||
'/oauth/permissions': LoginState,
|
||||
'/oauth/finish': LoginState,
|
||||
|
@ -1,86 +0,0 @@
|
||||
import ChangePasswordState from 'services/authFlow/ChangePasswordState';
|
||||
import CompleteState from 'services/authFlow/CompleteState';
|
||||
|
||||
import { bootstrap, expectState, expectNavigate, expectRun } from './helpers';
|
||||
|
||||
describe('ChangePasswordState', () => {
|
||||
let state;
|
||||
let context;
|
||||
let mock;
|
||||
|
||||
beforeEach(() => {
|
||||
state = new ChangePasswordState();
|
||||
|
||||
const data = bootstrap();
|
||||
context = data.context;
|
||||
mock = data.mock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.verify();
|
||||
});
|
||||
|
||||
describe('#enter', () => {
|
||||
it('should navigate to /change-password', () => {
|
||||
context.getState.returns({
|
||||
user: {isGuest: true}
|
||||
});
|
||||
|
||||
expectNavigate(mock, '/change-password');
|
||||
|
||||
state.enter(context);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#resolve', () => {
|
||||
it('should call changePassword with payload', () => {
|
||||
const payload = {};
|
||||
|
||||
expectRun(
|
||||
mock,
|
||||
'changePassword',
|
||||
sinon.match.same(payload)
|
||||
).returns({then() {}});
|
||||
|
||||
state.resolve(context, payload);
|
||||
});
|
||||
|
||||
it('should transition to complete state on success', () => {
|
||||
const promise = Promise.resolve();
|
||||
|
||||
mock.expects('run').returns(promise);
|
||||
expectState(mock, CompleteState);
|
||||
|
||||
state.resolve(context);
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
||||
it('should NOT transition to complete state on fail', () => {
|
||||
const promise = Promise.reject();
|
||||
|
||||
mock.expects('run').returns(promise);
|
||||
mock.expects('setState').never();
|
||||
|
||||
state.resolve(context);
|
||||
|
||||
return promise.catch(mock.verify.bind(mock));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#reject', () => {
|
||||
it('should transition to complete state and mark that password should not be changed', () => {
|
||||
expectRun(
|
||||
mock,
|
||||
'updateUser',
|
||||
sinon.match({
|
||||
shouldChangePassword: false
|
||||
})
|
||||
);
|
||||
|
||||
expectState(mock, CompleteState);
|
||||
|
||||
state.reject(context);
|
||||
});
|
||||
});
|
||||
});
|
@ -3,7 +3,6 @@ import expect from 'unexpected';
|
||||
import CompleteState from 'services/authFlow/CompleteState';
|
||||
import LoginState from 'services/authFlow/LoginState';
|
||||
import ActivationState from 'services/authFlow/ActivationState';
|
||||
import ChangePasswordState from 'services/authFlow/ChangePasswordState';
|
||||
import AcceptRulesState from 'services/authFlow/AcceptRulesState';
|
||||
import FinishState from 'services/authFlow/FinishState';
|
||||
import PermissionsState from 'services/authFlow/PermissionsState';
|
||||
@ -68,35 +67,6 @@ describe('CompleteState', () => {
|
||||
state.enter(context);
|
||||
});
|
||||
|
||||
it('should transition to change-password if shouldChangePassword', () => {
|
||||
context.getState.returns({
|
||||
user: {
|
||||
shouldChangePassword: true,
|
||||
isActive: true,
|
||||
isGuest: false
|
||||
},
|
||||
auth: {}
|
||||
});
|
||||
|
||||
expectState(mock, ChangePasswordState);
|
||||
|
||||
state.enter(context);
|
||||
});
|
||||
|
||||
it('should transition to activation with higher priority than shouldChangePassword', () => {
|
||||
context.getState.returns({
|
||||
user: {
|
||||
shouldChangePassword: true,
|
||||
isGuest: false
|
||||
},
|
||||
auth: {}
|
||||
});
|
||||
|
||||
expectState(mock, ActivationState);
|
||||
|
||||
state.enter(context);
|
||||
});
|
||||
|
||||
it('should transition to accept-rules if shouldAcceptRules', () => {
|
||||
context.getState.returns({
|
||||
user: {
|
||||
|
Loading…
Reference in New Issue
Block a user