Permalink
Find file Copy path
187 lines (171 sloc) 7.3 KB
/*
* Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
import * as React from 'react';
import { I18n, JS, ConsoleLogger as Logger } from '@aws-amplify/core';
import Auth from '@aws-amplify/auth';
import AuthPiece from './AuthPiece';
import { FederatedButtons } from './FederatedSignIn';
import SignUp from './SignUp';
import ForgotPassword from './ForgotPassword';
import {
FormSection,
FormField,
SectionHeader,
SectionBody,
SectionFooter,
Button,
Link,
Hint,
Input,
InputLabel,
SectionFooterPrimaryContent,
SectionFooterSecondaryContent,
} from '../Amplify-UI/Amplify-UI-Components-React';
const logger = new Logger('SignIn');
export default class SignIn extends AuthPiece {
constructor(props) {
super(props);
this.checkContact = this.checkContact.bind(this);
this.signIn = this.signIn.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this._validAuthStates = ['signIn', 'signedOut', 'signedUp'];
this.state = {};
}
componentDidMount() {
window.addEventListener('keydown', this.onKeyDown);
}
componentWillUnmount() {
window.removeEventListener('keydown', this.onKeyDown);
}
onKeyDown(e) {
if (e.keyCode !== 13) return;
const { hide = [] } = this.props;
if (this.props.authState === 'signIn' && !hide.includes(SignIn)) {
this.signIn();
}
}
checkContact(user) {
if (!Auth || typeof Auth.verifiedContact !== 'function') {
throw new Error('No Auth module found, please ensure @aws-amplify/auth is imported');
}
Auth.verifiedContact(user)
.then(data => {
if (!JS.isEmpty(data.verified)) {
this.changeState('signedIn', user);
} else {
user = Object.assign(user, data);
this.changeState('verifyContact', user);
}
});
}
async signIn() {
const { username, password } = this.inputs;
if (!Auth || typeof Auth.signIn !== 'function') {
throw new Error('No Auth module found, please ensure @aws-amplify/auth is imported');
}
this.setState({loading: true});
try {
const user = await Auth.signIn(username, password);
logger.debug(user);
if (user.challengeName === 'SMS_MFA' || user.challengeName === 'SOFTWARE_TOKEN_MFA') {
logger.debug('confirm user with ' + user.challengeName);
this.changeState('confirmSignIn', user);
} else if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
logger.debug('require new password', user.challengeParam);
this.changeState('requireNewPassword', user);
} else if (user.challengeName === 'MFA_SETUP') {
logger.debug('TOTP setup', user.challengeParam);
this.changeState('TOTPSetup', user);
} else {
this.checkContact(user);
}
} catch (err) {
if (err.code === 'UserNotConfirmedException') {
logger.debug('the user is not confirmed');
this.changeState('confirmSignUp', {username});
} else if (err.code === 'PasswordResetRequiredException') {
logger.debug('the user requires a new password');
this.changeState('forgotPassword', {username});
} else {
this.error(err);
}
} finally {
this.setState({loading: false})
}
}
showComponent(theme) {
const { authState, hide = [], federated, onStateChange, onAuthEvent, override=[] } = this.props;
if (hide && hide.includes(SignIn)) { return null; }
const hideSignUp = !override.includes('SignUp') && hide.some(component => component === SignUp);
const hideForgotPassword = !override.includes('ForgotPassword') && hide.some(component => component === ForgotPassword);
return (
<FormSection theme={theme}>
<SectionHeader theme={theme}>{I18n.get('Sign in to your account')}</SectionHeader>
<SectionBody theme={theme}>
<FederatedButtons
federated={federated}
theme={theme}
authState={authState}
onStateChange={onStateChange}
onAuthEvent={onAuthEvent}
/>
<FormField theme={theme}>
<InputLabel theme={theme}>{I18n.get('Username')} *</InputLabel>
<Input
autoFocus
placeholder={I18n.get('Enter your username')}
theme={theme}
key="username"
name="username"
onChange={this.handleInputChange}
/>
</FormField>
<FormField theme={theme}>
<InputLabel theme={theme}>{I18n.get('Password')} *</InputLabel>
<Input
placeholder={I18n.get('Enter your password')}
theme={theme}
key="password"
type="password"
name="password"
onChange={this.handleInputChange}
/>
{
!hideForgotPassword && <Hint theme={theme}>
{I18n.get('Forget your password? ')}
<Link theme={theme} onClick={() => this.changeState('forgotPassword')}>
{I18n.get('Reset password')}
</Link>
</Hint>
}
</FormField>
</SectionBody>
<SectionFooter theme={theme}>
<SectionFooterPrimaryContent theme={theme}>
<Button theme={theme} onClick={this.signIn} disabled={this.state.loading}>
{I18n.get('Sign In')}
</Button>
</SectionFooterPrimaryContent>
{
!hideSignUp && <SectionFooterSecondaryContent theme={theme}>
{I18n.get('No account? ')}
<Link theme={theme} onClick={() => this.changeState('signUp')}>
{I18n.get('Create account')}
</Link>
</SectionFooterSecondaryContent>
}
</SectionFooter>
</FormSection>
);
}
}