1
/*
2
 * Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
 * the License. A copy of the License is located at
6
 *
7
 *     http://aws.amazon.com/apache2.0/
8
 *
9
 * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
 * and limitations under the License.
12
 */
13

14 1
import * as React from 'react';
15 1
import { I18n, ConsoleLogger as Logger } from '@aws-amplify/core';
16 1
import { Auth } from '@aws-amplify/auth';
17

18 1
import AmplifyTheme from '../Amplify-UI/Amplify-UI-Theme';
19 1
import {
20
	FormSection,
21
	SectionHeader,
22
	SectionBody,
23
	SectionFooter,
24
	RadioRow,
25
	Button,
26
	Toast,
27
} from '../Amplify-UI/Amplify-UI-Components-React';
28

29 1
import { TOTPSetupComp } from './TOTPSetupComp';
30

31 1
const logger = new Logger('SelectMFAType');
32

33
export interface IMFATypes {
34
	SMS: boolean;
35
	TOTP: boolean;
36
	Optional: boolean;
37
}
38

39
export interface ISelectMFATypeProps {
40
	authData;
41
	MFATypes: IMFATypes;
42
	theme?: any;
43
}
44

45
export interface ISelectMFATypeState {
46
	selectMessage: string | null;
47
	showToast?: boolean;
48
	TOTPSetup: boolean;
49
}
50

51 1
export class SelectMFAType extends React.Component<
52
	ISelectMFATypeProps,
53
	ISelectMFATypeState
54
	> {
55
	public inputs: any;
56
	constructor(props) {
57 1
		super(props);
58

59 1
		this.verify = this.verify.bind(this);
60 1
		this.handleInputChange = this.handleInputChange.bind(this);
61

62 1
		this.state = {
63
			TOTPSetup: false,
64
			selectMessage: null,
65
		};
66
	}
67

68 1
	handleInputChange(evt) {
69
		// clear current state
70 1
		this.setState({
71
			TOTPSetup: false,
72
			selectMessage: null,
73
		});
74 1
		this.inputs = {};
75 1
		const { name, value, type, checked } = evt.target;
76
		// @ts-ignore
77 1
		const check_type = ['radio', 'checkbox'].includes(type);
78 1
		this.inputs[value] = check_type ? checked : value;
79
	}
80

81 1
	verify() {
82 1
		logger.debug('mfatypes inputs', this.inputs);
83 1
		if (!this.inputs) {
84 1
			logger.debug('No mfa type selected');
85 1
			return;
86
		}
87 1
		const { TOTP, SMS, NOMFA } = this.inputs;
88 1
		let mfaMethod = null;
89 1
		if (TOTP) {
90 1
			mfaMethod = 'TOTP';
91 1
		} else if (SMS) {
92 1
			mfaMethod = 'SMS';
93 1
		} else if (NOMFA) {
94 1
			mfaMethod = 'NOMFA';
95
		}
96

97 1
		const user = this.props.authData;
98

99 1
		if (!Auth || typeof Auth.setPreferredMFA !== 'function') {
100 0
			throw new Error(
101
				'No Auth module found, please ensure @aws-amplify/auth is imported'
102
			);
103
		}
104

105 1
		Auth.setPreferredMFA(user, mfaMethod)
106
			.then(data => {
107 1
				logger.debug('set preferred mfa success', data);
108 1
				this.setState({
109
					selectMessage: 'Success! Your MFA Type is now: ' + mfaMethod,
110
					showToast: true,
111
				});
112
			})
113
			.catch(err => {
114 1
				const { message } = err;
115 1
				if (
116 1
					message === 'User has not set up software token mfa' ||
117
					message === 'User has not verified software token mfa'
118
				) {
119 1
					this.setState({
120
						TOTPSetup: true,
121
						selectMessage: 'You need to setup TOTP',
122
						showToast: true,
123
					});
124
				} else {
125 0
					logger.debug('set preferred mfa failed', err);
126 0
					this.setState({
127
						selectMessage: 'Failed! You cannot select MFA Type for now!',
128
						showToast: true,
129
					});
130
				}
131
			});
132
	}
133

134 1
	selectView(theme) {
135 1
		const { MFATypes } = this.props;
136 1
		if (!MFATypes || Object.keys(MFATypes).length < 2) {
137 1
			logger.debug('less than 2 mfa types available');
138 1
			return (
139
				<div>
140
					<a>less than 2 mfa types available</a>
141
				</div>
142
			);
143
		}
144 1
		const { SMS, TOTP, Optional } = MFATypes;
145 1
		return (
146
			<FormSection theme={theme}>
147 1
				{this.state.showToast && this.state.selectMessage && (
148
					<Toast
149
						theme={theme}
150 0
						onClose={() => this.setState({ showToast: false })}
151
					>
152
						{I18n.get(this.state.selectMessage)}
153
					</Toast>
154
				)}
155
				<SectionHeader theme={theme}>
156
					{I18n.get('Select MFA Type')}
157
				</SectionHeader>
158
				<SectionBody theme={theme}>
159
					<div>
160
						{SMS ? (
161 1
							<RadioRow
162
								placeholder={I18n.get('SMS')}
163
								theme={theme}
164
								key="sms"
165
								name="MFAType"
166
								value="SMS"
167
								onChange={this.handleInputChange}
168
							/>
169
						) : null}
170
						{TOTP ? (
171 1
							<RadioRow
172
								placeholder={I18n.get('TOTP')}
173
								theme={theme}
174
								key="totp"
175
								name="MFAType"
176
								value="TOTP"
177
								onChange={this.handleInputChange}
178
							/>
179
						) : null}
180
						{Optional ? (
181 1
							<RadioRow
182
								placeholder={I18n.get('No MFA')}
183
								theme={theme}
184
								key="noMFA"
185
								name="MFAType"
186
								value="NOMFA"
187
								onChange={this.handleInputChange}
188
							/>
189
						) : null}
190
					</div>
191
				</SectionBody>
192
				<SectionFooter theme={theme}>
193
					<Button theme={theme} onClick={this.verify}>
194
						{I18n.get('Verify')}
195
					</Button>
196
				</SectionFooter>
197
			</FormSection>
198
		);
199
	}
200

201 1
	render() {
202 1
		const theme = this.props.theme || AmplifyTheme;
203 1
		return (
204
			<div>
205
				{this.selectView(theme)}
206 1
				{this.state.TOTPSetup ? <TOTPSetupComp {...this.props} /> : null}
207
			</div>
208
		);
209
	}
210 1
}
211

212
/**
213
 * @deprecated use named import
214
 */
215 1
export default SelectMFAType;

Read our documentation on viewing source code .

Loading