mirror of
https://github.com/elyby/accounts-frontend.git
synced 2025-02-20 01:08:37 +05:30
#26: incapsulate auth flow rejection logic into a separate component
This commit is contained in:
parent
b0a6740751
commit
4733b79d75
@ -11,7 +11,6 @@ export default class BaseAuthBody extends Component {
|
|||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
clearErrors: PropTypes.func.isRequired,
|
clearErrors: PropTypes.func.isRequired,
|
||||||
resolve: PropTypes.func.isRequired,
|
resolve: PropTypes.func.isRequired,
|
||||||
reject: PropTypes.func.isRequired,
|
|
||||||
auth: PropTypes.shape({
|
auth: PropTypes.shape({
|
||||||
error: PropTypes.string,
|
error: PropTypes.string,
|
||||||
scopes: PropTypes.array
|
scopes: PropTypes.array
|
||||||
|
25
src/components/auth/RejectionLink.jsx
Normal file
25
src/components/auth/RejectionLink.jsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
|
||||||
|
import { FormattedMessage as Message } from 'react-intl';
|
||||||
|
|
||||||
|
export default function RejectionLink(props, context) {
|
||||||
|
return (
|
||||||
|
<a href="#" onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
context.reject();
|
||||||
|
}}>
|
||||||
|
<Message {...props.label} />
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
RejectionLink.displayName = 'RejectionLink';
|
||||||
|
RejectionLink.propTypes = {
|
||||||
|
label: PropTypes.shape({
|
||||||
|
id: PropTypes.string
|
||||||
|
}).isRequired
|
||||||
|
};
|
||||||
|
RejectionLink.contextTypes = {
|
||||||
|
reject: PropTypes.func.isRequired
|
||||||
|
};
|
@ -1,8 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { FormattedMessage as Message } from 'react-intl';
|
|
||||||
|
|
||||||
import { Button } from 'components/ui/form';
|
import { Button } from 'components/ui/form';
|
||||||
|
import RejectionLink from 'components/auth/RejectionLink';
|
||||||
import AuthTitle from 'components/auth/AuthTitle';
|
import AuthTitle from 'components/auth/AuthTitle';
|
||||||
|
|
||||||
import messages from './Activation.intl.json';
|
import messages from './Activation.intl.json';
|
||||||
@ -13,10 +12,6 @@ export default function Activation() {
|
|||||||
Title: () => <AuthTitle title={messages.accountActivationTitle} />,
|
Title: () => <AuthTitle title={messages.accountActivationTitle} />,
|
||||||
Body,
|
Body,
|
||||||
Footer: () => <Button color="blue" label={messages.confirmEmail} />,
|
Footer: () => <Button color="blue" label={messages.confirmEmail} />,
|
||||||
Links: () => (
|
Links: () => <RejectionLink label={messages.didNotReceivedEmail} />
|
||||||
<a href="#">
|
|
||||||
<Message {...messages.didNotReceivedEmail} />
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,17 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { FormattedMessage as Message } from 'react-intl';
|
|
||||||
|
|
||||||
import { Button } from 'components/ui/form';
|
import { Button } from 'components/ui/form';
|
||||||
|
import RejectionLink from 'components/auth/RejectionLink';
|
||||||
import AuthTitle from 'components/auth/AuthTitle';
|
import AuthTitle from 'components/auth/AuthTitle';
|
||||||
|
|
||||||
import Body from './ChangePasswordBody';
|
import Body from './ChangePasswordBody';
|
||||||
import messages from './ChangePassword.intl.json';
|
import messages from './ChangePassword.intl.json';
|
||||||
|
|
||||||
export default function ChangePassword() {
|
export default function ChangePassword() {
|
||||||
const componentsMap = {
|
return {
|
||||||
Title: () => <AuthTitle title={messages.changePasswordTitle} />,
|
Title: () => <AuthTitle title={messages.changePasswordTitle} />,
|
||||||
Body,
|
Body,
|
||||||
Footer: () => <Button color="darkBlue" label={messages.change} />,
|
Footer: () => <Button color="darkBlue" label={messages.change} />,
|
||||||
Links: (props, context) => (
|
Links: () => <RejectionLink label={messages.skipThisStep} />
|
||||||
<a href="#" onClick={(event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
context.reject();
|
|
||||||
}}>
|
|
||||||
<Message {...messages.skipThisStep} />
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
componentsMap.Links.contextTypes = {
|
|
||||||
reject: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
return componentsMap;
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { FormattedMessage as Message } from 'react-intl';
|
|
||||||
|
|
||||||
import { Button } from 'components/ui/form';
|
import { Button } from 'components/ui/form';
|
||||||
|
import RejectionLink from 'components/auth/RejectionLink';
|
||||||
import AuthTitle from 'components/auth/AuthTitle';
|
import AuthTitle from 'components/auth/AuthTitle';
|
||||||
|
|
||||||
import messages from './ForgotPassword.intl.json';
|
import messages from './ForgotPassword.intl.json';
|
||||||
@ -13,10 +12,6 @@ export default function ForgotPassword() {
|
|||||||
Title: () => <AuthTitle title={messages.forgotPasswordTitle} />,
|
Title: () => <AuthTitle title={messages.forgotPasswordTitle} />,
|
||||||
Body,
|
Body,
|
||||||
Footer: () => <Button color="lightViolet" label={messages.sendMail} />,
|
Footer: () => <Button color="lightViolet" label={messages.sendMail} />,
|
||||||
Links: () => (
|
Links: () => <RejectionLink label={messages.contactSupport} />
|
||||||
<a href="/send-message">
|
|
||||||
<Message {...messages.contactSupport} />
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { FormattedMessage as Message } from 'react-intl';
|
|
||||||
import { Link } from 'react-router';
|
|
||||||
|
|
||||||
import { Button } from 'components/ui/form';
|
import { Button } from 'components/ui/form';
|
||||||
|
import RejectionLink from 'components/auth/RejectionLink';
|
||||||
import AuthTitle from 'components/auth/AuthTitle';
|
import AuthTitle from 'components/auth/AuthTitle';
|
||||||
|
|
||||||
import Body from './PasswordBody';
|
import Body from './PasswordBody';
|
||||||
@ -14,10 +12,6 @@ export default function Password() {
|
|||||||
Title: () => <AuthTitle title={messages.passwordTitle} />,
|
Title: () => <AuthTitle title={messages.passwordTitle} />,
|
||||||
Body,
|
Body,
|
||||||
Footer: () => <Button color="green" label={messages.signInButton} />,
|
Footer: () => <Button color="green" label={messages.signInButton} />,
|
||||||
Links: () => (
|
Links: () => <RejectionLink label={messages.forgotPassword} />
|
||||||
<Link to="/forgot-password">
|
|
||||||
<Message {...messages.forgotPassword} />
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,17 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { FormattedMessage as Message } from 'react-intl';
|
|
||||||
|
|
||||||
import { Button } from 'components/ui/form';
|
import { Button } from 'components/ui/form';
|
||||||
|
import RejectionLink from 'components/auth/RejectionLink';
|
||||||
import AuthTitle from 'components/auth/AuthTitle';
|
import AuthTitle from 'components/auth/AuthTitle';
|
||||||
|
|
||||||
import messages from './Permissions.intl.json';
|
import messages from './Permissions.intl.json';
|
||||||
import Body from './PermissionsBody';
|
import Body from './PermissionsBody';
|
||||||
|
|
||||||
export default function Permissions() {
|
export default function Permissions() {
|
||||||
const componentsMap = {
|
return {
|
||||||
Title: () => <AuthTitle title={messages.permissionsTitle} />,
|
Title: () => <AuthTitle title={messages.permissionsTitle} />,
|
||||||
Body,
|
Body,
|
||||||
Footer: () => <Button color="orange" autoFocus label={messages.approve} />,
|
Footer: () => <Button color="orange" autoFocus label={messages.approve} />,
|
||||||
Links: (props, context) => (
|
Links: () => <RejectionLink label={messages.decline} />
|
||||||
<a href="#" onClick={(event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
context.reject();
|
|
||||||
}}>
|
|
||||||
<Message {...messages.decline} />
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
componentsMap.Links.contextTypes = {
|
|
||||||
reject: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
return componentsMap;
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { FormattedMessage as Message } from 'react-intl';
|
|
||||||
|
|
||||||
import { Button } from 'components/ui/form';
|
import { Button } from 'components/ui/form';
|
||||||
|
import RejectionLink from 'components/auth/RejectionLink';
|
||||||
import AuthTitle from 'components/auth/AuthTitle';
|
import AuthTitle from 'components/auth/AuthTitle';
|
||||||
import activationMessages from 'components/auth/activation/Activation.intl.json';
|
import activationMessages from 'components/auth/activation/Activation.intl.json';
|
||||||
|
|
||||||
@ -14,10 +13,6 @@ export default function Register() {
|
|||||||
Title: () => <AuthTitle title={messages.registerTitle} />,
|
Title: () => <AuthTitle title={messages.registerTitle} />,
|
||||||
Body,
|
Body,
|
||||||
Footer: () => <Button color="blue" label={messages.signUpButton} />,
|
Footer: () => <Button color="blue" label={messages.signUpButton} />,
|
||||||
Links: () => (
|
Links: () => <RejectionLink label={activationMessages.didNotReceivedEmail} />
|
||||||
<a href="#">
|
|
||||||
<Message {...activationMessages.didNotReceivedEmail} />
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import ChangePassword from 'components/auth/changePassword/ChangePassword';
|
|||||||
import ForgotPassword from 'components/auth/forgotPassword/ForgotPassword';
|
import ForgotPassword from 'components/auth/forgotPassword/ForgotPassword';
|
||||||
import Finish from 'components/auth/finish/Finish';
|
import Finish from 'components/auth/finish/Finish';
|
||||||
|
|
||||||
|
|
||||||
import authFlow from 'services/authFlow';
|
import authFlow from 'services/authFlow';
|
||||||
|
|
||||||
export default function routesFactory(store) {
|
export default function routesFactory(store) {
|
||||||
@ -46,15 +45,15 @@ export default function routesFactory(store) {
|
|||||||
|
|
||||||
<Route path="oauth" component={OAuthInit} {...startAuthFlow} />
|
<Route path="oauth" component={OAuthInit} {...startAuthFlow} />
|
||||||
|
|
||||||
<Route path="auth" component={AuthPage} {...startAuthFlow}>
|
<Route path="auth" component={AuthPage}>
|
||||||
<Route path="/login" components={new Login()} />
|
<Route path="/login" components={new Login()} {...startAuthFlow} />
|
||||||
<Route path="/password" components={new Password()} />
|
<Route path="/password" components={new Password()} {...startAuthFlow} />
|
||||||
<Route path="/register" components={new Register()} />
|
<Route path="/register" components={new Register()} {...startAuthFlow} />
|
||||||
<Route path="/activation" components={new Activation()} />
|
<Route path="/activation" components={new Activation()} {...startAuthFlow} />
|
||||||
<Route path="/oauth/permissions" components={new Permissions()} />
|
<Route path="/oauth/permissions" components={new Permissions()} {...startAuthFlow} />
|
||||||
<Route path="/oauth/finish" component={Finish} />
|
<Route path="/oauth/finish" component={Finish} {...startAuthFlow} />
|
||||||
<Route path="/change-password" components={new ChangePassword()} />
|
<Route path="/change-password" components={new ChangePassword()} {...startAuthFlow} />
|
||||||
<Route path="/forgot-password" components={new ForgotPassword()} />
|
<Route path="/forgot-password" components={new ForgotPassword()} {...startAuthFlow} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path="profile" component={ProfilePage} {...userOnly}>
|
<Route path="profile" component={ProfilePage} {...userOnly}>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import AbstractState from './AbstractState';
|
import AbstractState from './AbstractState';
|
||||||
import PasswordState from './PasswordState';
|
import PasswordState from './PasswordState';
|
||||||
import ForgotPasswordState from './ForgotPasswordState';
|
|
||||||
|
|
||||||
export default class LoginState extends AbstractState {
|
export default class LoginState extends AbstractState {
|
||||||
enter(context) {
|
enter(context) {
|
||||||
@ -17,8 +16,4 @@ export default class LoginState extends AbstractState {
|
|||||||
context.run('login', payload)
|
context.run('login', payload)
|
||||||
.then(() => context.setState(new PasswordState()));
|
.then(() => context.setState(new PasswordState()));
|
||||||
}
|
}
|
||||||
|
|
||||||
reject(context) {
|
|
||||||
context.setState(new ForgotPasswordState());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -86,12 +86,4 @@ describe('LoginState', () => {
|
|||||||
return promise.catch(mock.verify.bind(mock));
|
return promise.catch(mock.verify.bind(mock));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#reject', () => {
|
|
||||||
it('should transition to forgot password state', () => {
|
|
||||||
expectState(mock, ForgotPasswordState);
|
|
||||||
|
|
||||||
state.reject(context);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user