LoginForm.jsx 21.4 KB
Newer Older
James Calfee's avatar
James Calfee committed
1
/* eslint react/prop-types: 0 */
Iain Maitland's avatar
Iain Maitland committed
2 3
import React, { Component } from 'react';
import PropTypes from 'prop-types';
4
import { Map } from 'immutable';
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
5 6 7
import * as transactionActions from 'app/redux/TransactionReducer';
import * as globalActions from 'app/redux/GlobalReducer';
import * as userActions from 'app/redux/UserReducer';
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
8
import { validate_account_name } from 'app/utils/ChainValidation';
Evan Chou's avatar
Evan Chou committed
9
import { hasCompatibleKeychain } from 'app/utils/SteemKeychain';
10
import runTests from 'app/utils/BrowserTests';
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
11 12 13
import shouldComponentUpdate from 'app/utils/shouldComponentUpdate';
import reactForm from 'app/utils/ReactForm';
import { serverApiRecordEvent } from 'app/utils/ServerApiClient';
valzav's avatar
valzav committed
14 15
import tt from 'counterpart';
import { APP_URL } from 'app/client_config';
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
16
import { PrivateKey, PublicKey } from '@steemit/steem-js/lib/auth/ecc';
17
import { SIGNUP_URL } from 'shared/constants';
James Calfee's avatar
James Calfee committed
18 19 20

class LoginForm extends Component {
    static propTypes = {
21
        // Steemit.
22
        loginError: PropTypes.string,
James Calfee's avatar
James Calfee committed
23 24 25 26
        onCancel: PropTypes.func,
    };

    constructor(props) {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
27
        super();
James Calfee's avatar
James Calfee committed
28 29
        const cryptoTestResult = runTests();
        let cryptographyFailure = false;
30
        this.SignUp = this.SignUp.bind(this);
James Calfee's avatar
James Calfee committed
31
        if (cryptoTestResult !== undefined) {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
32 33 34 35 36
            console.error(
                'CreateAccount - cryptoTestResult: ',
                cryptoTestResult
            );
            cryptographyFailure = true;
James Calfee's avatar
James Calfee committed
37
        }
Evan Chou's avatar
Evan Chou committed
38 39
        const useKeychain = hasCompatibleKeychain();
        this.state = { useKeychain, cryptographyFailure };
James Calfee's avatar
James Calfee committed
40
        this.usernameOnChange = e => {
Mike's avatar
Mike committed
41
            const value = e.target.value.toLowerCase();
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
42
            this.state.username.props.onChange(value);
Mike's avatar
Mike committed
43
        };
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
44 45 46 47 48 49
        this.onCancel = e => {
            if (e.preventDefault) e.preventDefault();
            const { onCancel, loginBroadcastOperation } = this.props;
            const errorCallback =
                loginBroadcastOperation &&
                loginBroadcastOperation.get('errorCallback');
Mike's avatar
Mike committed
50
            if (errorCallback) errorCallback('Canceled');
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
51
            if (onCancel) onCancel();
Mike's avatar
Mike committed
52
        };
James Calfee's avatar
James Calfee committed
53
        this.qrReader = () => {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
54 55 56 57 58
            const { qrReader } = props;
            const { password } = this.state;
            qrReader(data => {
                password.props.onChange(data);
            });
Mike's avatar
Mike committed
59
        };
Evan Chou's avatar
Evan Chou committed
60
        this.initForm(props, useKeychain);
James Calfee's avatar
James Calfee committed
61
    }
James Calfee's avatar
James Calfee committed
62

James Calfee's avatar
James Calfee committed
63
    componentDidMount() {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
64 65 66 67
        if (this.refs.username && !this.refs.username.value)
            this.refs.username.focus();
        if (this.refs.username && this.refs.username.value)
            this.refs.pw.focus();
James Calfee's avatar
James Calfee committed
68
    }
James Calfee's avatar
James Calfee committed
69

Mike's avatar
Mike committed
70
    shouldComponentUpdate = shouldComponentUpdate(this, 'LoginForm');
James Calfee's avatar
James Calfee committed
71

Evan Chou's avatar
Evan Chou committed
72
    initForm(props, useKeychain) {
James Calfee's avatar
James Calfee committed
73 74 75
        reactForm({
            name: 'login',
            instance: this,
76
            fields: ['username', 'password', 'saveLogin:checked'],
James Calfee's avatar
James Calfee committed
77 78
            initialValues: props.initialValues,
            validation: values => ({
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
79 80 81
                username: !values.username
                    ? tt('g.required')
                    : validate_account_name(values.username.split('/')[0]),
Evan Chou's avatar
Evan Chou committed
82 83 84 85 86 87 88
                password: useKeychain
                    ? null
                    : !values.password
                      ? tt('g.required')
                      : PublicKey.fromString(values.password)
                        ? tt('loginform_jsx.you_need_a_private_password_or_key')
                        : null,
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
89 90
            }),
        });
James Calfee's avatar
James Calfee committed
91
    }
James Calfee's avatar
James Calfee committed
92

93
    SignUp() {
94 95
        const opAction = document.getElementsByClassName('OpAction')[0];
        const onType = opAction ? opAction.textContent : 'Login';
96
        serverApiRecordEvent('FreeMoneySignUp', onType);
97
        window.location.href = SIGNUP_URL;
98 99 100
    }

    SignIn() {
101 102
        const opAction = document.getElementsByClassName('OpAction')[0];
        const onType = opAction ? opAction.textContent : 'Login';
103
        serverApiRecordEvent('SignIn', onType);
James Calfee's avatar
James Calfee committed
104
    }
105

Evan Chou's avatar
Evan Chou committed
106 107 108 109 110
    onUseKeychainCheckbox = e => {
        const useKeychain = e.target.checked;
        this.setState({ useKeychain });
    };

111
    saveLoginToggle = () => {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
112
        const { saveLogin } = this.state;
113 114 115 116 117
        saveLoginDefault = !saveLoginDefault;
        localStorage.setItem('saveLogin', saveLoginDefault ? 'yes' : 'no');
        saveLogin.props.onChange(saveLoginDefault); // change UI
    };

James Calfee's avatar
James Calfee committed
118
    showChangePassword = () => {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
119 120
        const { username, password } = this.state;
        this.props.showChangePassword(username.value, password.value);
121 122
    };

James Calfee's avatar
James Calfee committed
123
    render() {
124 125
        const loginType = this.props.loginType;

James Calfee's avatar
James Calfee committed
126
        if (!process.env.BROWSER) {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
127 128 129 130 131
            return (
                <div className="row">
                    <div className="column">
                        <p>{'loading'}...</p>
                    </div>
James Calfee's avatar
James Calfee committed
132
                </div>
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
133
            );
James Calfee's avatar
James Calfee committed
134 135
        }
        if (this.state.cryptographyFailure) {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
            return (
                <div className="row">
                    <div className="column">
                        <div className="callout alert">
                            <h4>
                                {tt('loginform_jsx.cryptography_test_failed')}
                            </h4>
                            <p>{tt('loginform_jsx.unable_to_log_you_in')}</p>
                            <p>
                                {tt('loginform_jsx.the_latest_versions_of')}{' '}
                                <a href="https://www.google.com/chrome/">
                                    Chrome
                                </a>{' '}
                                {tt('g.and')}{' '}
                                <a href="https://www.mozilla.org/en-US/firefox/new/">
                                    Firefox
                                </a>{' '}
                                {tt(
                                    'loginform_jsx.are_well_tested_and_known_to_work_with',
                                    { APP_URL }
                                )}
                            </p>
                        </div>
James Calfee's avatar
James Calfee committed
159 160
                    </div>
                </div>
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
161
            );
James Calfee's avatar
James Calfee committed
162 163 164
        }

        if ($STM_Config.read_only_mode) {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
165 166 167 168 169 170 171 172 173
            return (
                <div className="row">
                    <div className="column">
                        <div className="callout alert">
                            <p>
                                {tt('loginform_jsx.due_to_server_maintenance')}
                            </p>
                        </div>
                    </div>
James Calfee's avatar
James Calfee committed
174
                </div>
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
175
            );
James Calfee's avatar
James Calfee committed
176 177
        }

178
        const { loginBroadcastOperation, dispatchSubmit, msg } = this.props;
Evan Chou's avatar
Evan Chou committed
179
        const { username, password, useKeychain, saveLogin } = this.state;
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
180 181
        const { submitting, valid, handleSubmit } = this.state.login;
        const { usernameOnChange, onCancel /*qrReader*/ } = this;
James Calfee's avatar
James Calfee committed
182
        const disabled = submitting || !valid;
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
183 184 185 186 187 188
        const opType = loginBroadcastOperation
            ? loginBroadcastOperation.get('type')
            : null;
        let postType = '';
        if (opType === 'vote') {
            postType = tt('loginform_jsx.login_to_vote');
189 190
        } else if (loginBroadcastOperation) {
            // check for post or comment in operation
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
191 192 193
            postType = loginBroadcastOperation.getIn(['operation', 'title'])
                ? tt('loginform_jsx.login_to_post')
                : tt('g.confirm_password');
194
        }
valzav's avatar
valzav committed
195
        const title = postType ? postType : tt('g.login');
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
196 197 198 199 200 201 202 203 204
        const authType = /^vote|comment/.test(opType)
            ? tt('loginform_jsx.posting')
            : tt('loginform_jsx.active_or_owner');
        const submitLabel = loginBroadcastOperation
            ? tt('g.sign_in')
            : tt('g.login');
        let error =
            password.touched && password.error
                ? password.error
205
                : this.props.loginError;
James Calfee's avatar
James Calfee committed
206
        if (error === 'owner_login_blocked') {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
207 208 209 210 211 212 213 214 215 216 217 218
            error = (
                <span>
                    {tt(
                        'loginform_jsx.this_password_is_bound_to_your_account_owner_key'
                    )}
                    {tt('loginform_jsx.however_you_can_use_it_to')}
                    <a onClick={this.showChangePassword}>
                        {tt('loginform_jsx.update_your_password')}
                    </a>{' '}
                    {tt('loginform_jsx.to_obtain_a_more_secure_set_of_keys')}
                </span>
            );
219
        } else if (error === 'active_login_blocked') {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
220 221 222 223 224 225 226 227 228 229
            error = (
                <span>
                    {tt(
                        'loginform_jsx.this_password_is_bound_to_your_account_active_key'
                    )}{' '}
                    {tt(
                        'loginform_jsx.you_may_use_this_active_key_on_other_more'
                    )}
                </span>
            );
James Calfee's avatar
James Calfee committed
230 231 232 233
        }
        let message = null;
        if (msg) {
            if (msg === 'accountcreated') {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
                message = (
                    <div className="callout primary">
                        <p>
                            {tt(
                                'loginform_jsx.you_account_has_been_successfully_created'
                            )}
                        </p>
                    </div>
                );
            } else if (msg === 'accountrecovered') {
                message = (
                    <div className="callout primary">
                        <p>
                            {tt(
                                'loginform_jsx.you_account_has_been_successfully_recovered'
                            )}
                        </p>
                    </div>
                );
            } else if (msg === 'passwordupdated') {
                message = (
                    <div className="callout primary">
                        <p>
257
                            {tt('loginform_jsx.password_update_success', {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
258 259 260 261 262
                                accountName: username.value,
                            })}
                        </p>
                    </div>
                );
James Calfee's avatar
James Calfee committed
263 264
            }
        }
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
265
        const password_info =
Evan Chou's avatar
Evan Chou committed
266
            !useKeychain && checkPasswordChecksum(password.value) === false
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
267 268
                ? tt('loginform_jsx.password_info')
                : null;
269

270
        const isTransfer =
271 272
            Map.isMap(loginBroadcastOperation) &&
            loginBroadcastOperation.has('type') &&
273 274 275 276 277
            loginBroadcastOperation
                .get('type')
                .toLowerCase()
                .indexOf('transfer') >= 0;

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
        let titleText;
        if (isTransfer) {
            titleText = (
                <h3>
                    <span className="OpAction">
                        {tt('loginform_jsx.sign_transfer')}
                    </span>
                </h3>
            );
        } else if (loginType === 'basic') {
            titleText = <h3>{tt('loginform_jsx.login_to_wallet')}</h3>;
        } else {
            titleText = (
                <h3>
                    {tt('loginform_jsx.returning_users')}
                    <span className="OpAction">{title}</span>
                </h3>
            );
        }
297

298 299 300
        const signupLink = (
            <div className="sign-up">
                <hr />
301
                <p>{tt('loginform_jsx.dont_have_an_account')}</p>
302 303 304 305 306 307 308 309 310 311
                <button
                    type="button"
                    className="button hollow"
                    onClick={this.SignUp}
                >
                    {tt('loginform_jsx.sign_up_get_steem')}
                </button>
            </div>
        );

James Calfee's avatar
James Calfee committed
312
        const form = (
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
313 314 315 316
            <form
                onSubmit={handleSubmit(({ data }) => {
                    // bind redux-form to react-redux
                    console.log('Login\tdispatchSubmit');
Evan Chou's avatar
Evan Chou committed
317 318 319 320 321
                    return dispatchSubmit(
                        data,
                        useKeychain,
                        loginBroadcastOperation
                    );
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
322 323 324
                })}
                onChange={this.props.clearError}
                method="post"
James Calfee's avatar
James Calfee committed
325
            >
326 327
                <div className="input-group">
                    <span className="input-group-label">@</span>
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
328 329 330 331 332 333 334 335 336
                    <input
                        className="input-group-field"
                        type="text"
                        required
                        placeholder={tt('loginform_jsx.enter_your_username')}
                        ref="username"
                        {...username.props}
                        onChange={usernameOnChange}
                        autoComplete="on"
337
                        disabled={submitting || isTransfer}
338
                    />
James Calfee's avatar
James Calfee committed
339
                </div>
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
340 341 342
                {username.touched && username.blur && username.error ? (
                    <div className="error">{username.error}&nbsp;</div>
                ) : null}
James Calfee's avatar
James Calfee committed
343

Evan Chou's avatar
Evan Chou committed
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
                {useKeychain ? (
                    <div>
                        {error && <div className="error">{error}&nbsp;</div>}
                    </div>
                ) : (
                    <div>
                        <input
                            type="password"
                            required
                            ref="pw"
                            placeholder={
                                loginType === 'basic'
                                    ? tt('loginform_jsx.enter_steem_key')
                                    : tt('loginform_jsx.password_or_wif')
                            }
                            {...password.props}
                            autoComplete="on"
                            disabled={submitting}
                        />
                        {error && <div className="error">{error}&nbsp;</div>}
                        {error &&
                            password_info && (
                                <div className="warning">
                                    {password_info}&nbsp;
                                </div>
                            )}
                    </div>
                )}
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
372 373 374 375 376 377 378 379 380 381
                {loginBroadcastOperation && (
                    <div>
                        <div className="info">
                            {tt(
                                'loginform_jsx.this_operation_requires_your_key_or_master_password',
                                { authType }
                            )}
                        </div>
                    </div>
                )}
Evan Chou's avatar
Evan Chou committed
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
                {hasCompatibleKeychain() && (
                    <div>
                        <label
                            className="LoginForm__save-login"
                            htmlFor="useKeychain"
                        >
                            <input
                                id="useKeychain"
                                type="checkbox"
                                checked={useKeychain}
                                onChange={this.onUseKeychainCheckbox}
                                disabled={submitting}
                            />&nbsp;{tt('loginform_jsx.use_keychain')}
                        </label>
                    </div>
                )}
398
                <div>
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
399 400 401 402 403 404 405 406 407 408 409 410 411
                    <label
                        className="LoginForm__save-login"
                        htmlFor="saveLogin"
                    >
                        <input
                            id="saveLogin"
                            type="checkbox"
                            ref="pw"
                            {...saveLogin.props}
                            onChange={this.saveLoginToggle}
                            disabled={submitting}
                        />&nbsp;{tt('loginform_jsx.keep_me_logged_in')}
                    </label>
412
                </div>
Pon Kattera's avatar
Pon Kattera committed
413
                <div className="login-modal-buttons">
414
                    <br />
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
415 416 417 418 419 420
                    <button
                        type="submit"
                        disabled={submitting || disabled}
                        className="button"
                        onClick={this.SignIn}
                    >
James Calfee's avatar
James Calfee committed
421 422
                        {submitLabel}
                    </button>
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
423 424 425 426 427 428 429 430 431 432
                    {this.props.onCancel && (
                        <button
                            type="button float-right"
                            disabled={submitting}
                            className="button hollow"
                            onClick={onCancel}
                        >
                            {tt('g.cancel')}
                        </button>
                    )}
James Calfee's avatar
James Calfee committed
433
                </div>
434
                {!isTransfer && signupLink}
James Calfee's avatar
James Calfee committed
435
            </form>
436
        );
James Calfee's avatar
James Calfee committed
437 438

        return (
valzav's avatar
valzav committed
439 440 441
            <div className="LoginForm row">
                <div className="column">
                    {message}
442
                    {titleText}
valzav's avatar
valzav committed
443 444 445
                    {form}
                </div>
            </div>
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
446
        );
James Calfee's avatar
James Calfee committed
447 448 449
    }
}

Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
450 451
let hasError;
let saveLoginDefault = true;
James Calfee's avatar
James Calfee committed
452
if (process.env.BROWSER) {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
453 454
    const s = localStorage.getItem('saveLogin');
    if (s === 'no') saveLoginDefault = false;
James Calfee's avatar
James Calfee committed
455 456
}

James Calfee's avatar
James Calfee committed
457
function urlAccountName() {
458
    let suggestedAccountName = '';
James Calfee's avatar
James Calfee committed
459
    const account_match = window.location.hash.match(/account\=([\w\d\-\.]+)/);
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
460 461 462
    if (account_match && account_match.length > 1)
        suggestedAccountName = account_match[1];
    return suggestedAccountName;
James Calfee's avatar
James Calfee committed
463 464
}

465
function checkPasswordChecksum(password) {
466 467
    // A Steemit generated password is a WIF prefixed with a P ..
    // It is possible to login directly with a WIF
468
    const wif = /^P/.test(password) ? password.substring(1) : password;
469

Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
470 471
    if (!/^5[HJK].{45,}/i.test(wif)) {
        // 51 is the wif length
472
        // not even close
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
473
        return undefined;
474
    }
475

Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
476
    return PrivateKey.isWif(wif);
477 478
}

Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
479
import { connect } from 'react-redux';
James Calfee's avatar
James Calfee committed
480
export default connect(
James Calfee's avatar
James Calfee committed
481
    // mapStateToProps
482 483
    (state, ownProps) => {
        const loginType = ownProps.loginType || state.user.get('login_type');
484
        const loginError = state.user.get('login_error');
485
        const currentUser = state.user.get('current');
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
486 487 488
        const loginBroadcastOperation = state.user.get(
            'loginBroadcastOperation'
        );
James Calfee's avatar
James Calfee committed
489 490
        const initialValues = {
            saveLogin: saveLoginDefault,
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
491
        };
James Calfee's avatar
James Calfee committed
492

493
        // The username input has a value prop, so it should not use initialValues
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
494 495 496 497
        const initialUsername =
            currentUser && currentUser.has('username')
                ? currentUser.get('username')
                : urlAccountName();
498
        const loginDefault = state.user.get('loginDefault');
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
499 500 501 502
        if (loginDefault) {
            const { username, authType } = loginDefault.toJS();
            if (username && authType)
                initialValues.username = username + '/' + authType;
503 504
        } else if (initialUsername) {
            initialValues.username = initialUsername;
James Calfee's avatar
James Calfee committed
505
        }
506 507 508 509
        const offchainUser = state.offchain.get('user');
        if (!initialUsername && offchainUser && offchainUser.get('account')) {
            initialValues.username = offchainUser.get('account');
        }
James Calfee's avatar
James Calfee committed
510 511 512
        let msg = '';
        const msg_match = window.location.hash.match(/msg\=([\w]+)/);
        if (msg_match && msg_match.length > 1) msg = msg_match[1];
513
        hasError = !!loginError;
James Calfee's avatar
James Calfee committed
514
        return {
515 516
            loginType,
            loginError,
James Calfee's avatar
James Calfee committed
517 518
            loginBroadcastOperation,
            initialValues,
519
            initialUsername,
James Calfee's avatar
James Calfee committed
520
            msg,
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
521 522
            offchain_user: state.offchain.get('user'),
        };
James Calfee's avatar
James Calfee committed
523 524 525 526
    },

    // mapDispatchToProps
    dispatch => ({
Evan Chou's avatar
Evan Chou committed
527
        dispatchSubmit: (data, useKeychain, loginBroadcastOperation) => {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
528 529
            const { password, saveLogin } = data;
            const username = data.username.trim().toLowerCase();
James Calfee's avatar
James Calfee committed
530
            if (loginBroadcastOperation) {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
531 532 533 534 535 536 537 538 539 540 541 542
                const {
                    type,
                    operation,
                    successCallback,
                    errorCallback,
                } = loginBroadcastOperation.toJS();
                dispatch(
                    transactionActions.broadcastOperation({
                        type,
                        operation,
                        username,
                        password,
Evan Chou's avatar
Evan Chou committed
543
                        useKeychain,
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
544 545 546 547 548 549 550 551
                        successCallback,
                        errorCallback,
                    })
                );
                dispatch(
                    userActions.usernamePasswordLogin({
                        username,
                        password,
Evan Chou's avatar
Evan Chou committed
552
                        useKeychain,
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
553 554 555 556
                        saveLogin,
                        operationType: type,
                    })
                );
557

558
                dispatch(userActions.closeLogin());
James Calfee's avatar
James Calfee committed
559
            } else {
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
560 561 562 563
                dispatch(
                    userActions.usernamePasswordLogin({
                        username,
                        password,
Evan Chou's avatar
Evan Chou committed
564
                        useKeychain,
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
565 566 567
                        saveLogin,
                    })
                );
James Calfee's avatar
James Calfee committed
568 569
            }
        },
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
570 571 572 573 574 575 576 577 578 579
        clearError: () => {
            if (hasError) dispatch(userActions.loginError({ error: null }));
        },
        qrReader: dataCallback => {
            dispatch(
                globalActions.showDialog({
                    name: 'qr_reader',
                    params: { handleScan: dataCallback },
                })
            );
James Calfee's avatar
James Calfee committed
580 581
        },
        showChangePassword: (username, defaultPassword) => {
582
            dispatch(userActions.closeLogin());
583

Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
584 585 586 587 588 589 590
            dispatch(globalActions.remove({ key: 'changePassword' }));
            dispatch(
                globalActions.showDialog({
                    name: 'changePassword',
                    params: { username, defaultPassword },
                })
            );
James Calfee's avatar
James Calfee committed
591 592
        },
    })
Benjamin Chodoroff's avatar
Benjamin Chodoroff committed
593
)(LoginForm);