<commit_before>import React, { Component } from "react";
import { connect } from "react-redux";
import { push } from "react-router-redux";
import PropTypes from "prop-types";

import LoginForm from "./SignInForm";
import Modal from "../../components/Modal";
import ChangePasswordController from "../../components/change-password/ChangePasswordController";
import notifications from "../../utilities/notifications";

import http from "../../utilities/http";
import { errCodes } from "../../utilities/errorCodes";
import user from "../../utilities/api-clients/user";
import cookies from "../../utilities/cookies";
import redirectToMainScreen from "../../utilities/redirectToMainScreen";
import log from "../../utilities/logging/log";

const propTypes = {
    dispatch: PropTypes.func.isRequired,
    isAuthenticated: PropTypes.bool.isRequired,
    rootPath: PropTypes.string.isRequired,
    location: PropTypes.object,
    enableNewSignIn: PropTypes.bool
};

export class LoginController extends Component {
    constructor(props) {
        super(props);

        this.state = {
            validationErrors: {},
            email: {
                value: "",
                errorMsg: ""
            },
            password: {
                value: "",
                errorMsg: "",
                type: "password"
            },
            requestPasswordChange: false,
            isSubmitting: false
        };

        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handlePasswordChangeCancel = this.handlePasswordChangeCancel.bind(this);
        this.handlePasswordChangeSuccess = this.handlePasswordChangeSuccess.bind(this);
    }

    componentWillMount() {
        if (this.props.isAuthenticated) {
            this.props.dispatch(push(`${this.props.rootPath}/collections`));
        }
    }

    postLoginCredentials(body) {
        return http.post("/tokens", body, true, true, true);
    }

    requestLogin(credentials) {
        this.postLoginCredentials(credentials)
            .then(response => {
                // NOTE: ACCESS TOKEN and REFRESH TOKEN will be moved out of here shortly
                const accessToken = response.headers.get("Authorization");
                const refreshToken = response.headers.get("Refresh");
                const userToken = response.headers.get("Id");
                this.handleLogin(accessToken, userToken, refreshToken);
            })
            .catch(error => {
                let stateToSet = {};
                if (error) {
                    stateToSet = this.handleLoginError(error, stateToSet);
                }

                this.setState({
                    ...stateToSet,
                    isSubmitting: false
                });
            });
    }

    handleLoginError(error, stateToSet) {
        const notification = {
            type: "warning",
            isDismissable: true,
            autoDismiss: 15000
        };

        if (error.status != null) {
            if (error.status >= 400 && error.status < 500) {
                let errorContents = { errorsForBody: [], emailMessage: "", passwordMessage: "" };
                let validationErrors = {
                    heading: "Fix the following: "
                };

                if (error.body != null && error.body.errors != null) {
                    error.body.errors.forEach(anError => {
                        errorContents = this.showValidationError(anError, errorContents, notification);
                    });
                } else {
                    this.notifyUnexpectedError(notification);
                }

                validationErrors.body = errorContents.errorsForBody;
                stateToSet = {
                    ...this.state,
                    validationErrors
                };
                stateToSet.email.errorMsg = errorContents.emailMessage;
                stateToSet.password.errorMsg = errorContents.passwordMessage;
                // Temporary code until login work is connected to dp-identity-api
                if (error.status === 417) {
                    stateToSet.requestPasswordChange = true;
                }
                // End of temporary code
            } else {
                this.notifyUnexpectedError(notification);
            }
        } else {
            this.notifyUnexpectedError(notification);
        }

        return stateToSet;
    }

    showValidationError(anError, errorContents, notification) {
        switch (anError.code) {
            case "InvalidEmail":
                errorContents.errorsForBody.push(
                    <p>
                        <a href="javascript:document.getElementById('email').focus()" className={"colour--night-shadz"}>
                            Enter a valid email address
                        </a>
                    </p>
                );
                errorContents.emailMessage = "Enter a valid email address";
                break;
            case "InvalidPassword":
                errorContents.errorsForBody.push(
                    <p>
                        <a href="javascript:document.getElementById('password').focus()" className={"colour--night-shadz"}>
                            Enter a password
                        </a>
                    </p>
                );
                errorContents.passwordMessage = "Enter a password";
                break;
            case "NotAuthorised":
                errorContents.errorsForBody.push(<p>Email address or password are incorrect</p>);
                break;
            case "TooManyFailedAttempts":
                errorContents.errorsForBody.push(<p>You've tried to sign in to your account too many times. Please try again later.</p>);
                break;
            default:
                // Code undefined or different to expected range of errors
                this.notifyUnexpectedError(notification);
        }
        return errorContents;
    }

    notifyUnexpectedError(notification) {
        console.error(errCodes.LOGIN_UNEXPECTED_ERR);
        notification.message = errCodes.LOGIN_UNEXPECTED_ERR;
        notifications.add(notification);
    }

    handleLogin(accessToken, userToken, refreshToken) {
        cookies.add("access_token", accessToken, "/", null, "strict", true);
        cookies.add("user_token", userToken, "/", null, "strict", true);
        cookies.add("refresh_token", userToken, "/tokens/self", null, "strict", true);
        user.getPermissions(this.state.email.value)
            .then(userType => {
                user.setUserState(userType);
                redirectToMainScreen(this.props.location.query.redirect);
            })
            .catch(error => {
                this.setState({ isSubmitting: false });
                notifications.add({
                    type: "warning",
                    message: "Unable to login due to an error getting your account's permissions. Please refresh and try again.",
                    autoDismiss: 8000,
                    isDismissable: true
                });
                log.event("Error getting a user's permissions on login", log.error(error));
                console.error("Error getting a user's permissions on login", error);
            });
    }

    handleSubmit(event) {
        event.preventDefault();<commit_msg>refresh token was storing id, now it stores refresh instead<commit_after>import React, { Component } from "react";
import { connect } from "react-redux";
import { push } from "react-router-redux";
import PropTypes from "prop-types";

import LoginForm from "./SignInForm";
import Modal from "../../components/Modal";
import ChangePasswordController from "../../components/change-password/ChangePasswordController";
import notifications from "../../utilities/notifications";

import http from "../../utilities/http";
import { errCodes } from "../../utilities/errorCodes";
import user from "../../utilities/api-clients/user";
import cookies from "../../utilities/cookies";
import redirectToMainScreen from "../../utilities/redirectToMainScreen";
import log from "../../utilities/logging/log";

const propTypes = {
    dispatch: PropTypes.func.isRequired,
    isAuthenticated: PropTypes.bool.isRequired,
    rootPath: PropTypes.string.isRequired,
    location: PropTypes.object,
    enableNewSignIn: PropTypes.bool
};

export class LoginController extends Component {
    constructor(props) {
        super(props);

        this.state = {
            validationErrors: {},
            email: {
                value: "",
                errorMsg: ""
            },
            password: {
                value: "",
                errorMsg: "",
                type: "password"
            },
            requestPasswordChange: false,
            isSubmitting: false
        };

        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handlePasswordChangeCancel = this.handlePasswordChangeCancel.bind(this);
        this.handlePasswordChangeSuccess = this.handlePasswordChangeSuccess.bind(this);
    }

    componentWillMount() {
        if (this.props.isAuthenticated) {
            this.props.dispatch(push(`${this.props.rootPath}/collections`));
        }
    }

    postLoginCredentials(body) {
        return http.post("/tokens", body, true, true, true);
    }

    requestLogin(credentials) {
        this.postLoginCredentials(credentials)
            .then(response => {
                // NOTE: ACCESS TOKEN and REFRESH TOKEN will be moved out of here shortly
                const accessToken = response.headers.get("Authorization");
                const refreshToken = response.headers.get("Refresh");
                const userToken = response.headers.get("Id");
                this.handleLogin(accessToken, userToken, refreshToken);
            })
            .catch(error => {
                let stateToSet = {};
                if (error) {
                    stateToSet = this.handleLoginError(error, stateToSet);
                }

                this.setState({
                    ...stateToSet,
                    isSubmitting: false
                });
            });
    }

    handleLoginError(error, stateToSet) {
        const notification = {
            type: "warning",
            isDismissable: true,
            autoDismiss: 15000
        };

        if (error.status != null) {
            if (error.status >= 400 && error.status < 500) {
                let errorContents = { errorsForBody: [], emailMessage: "", passwordMessage: "" };
                let validationErrors = {
                    heading: "Fix the following: "
                };

                if (error.body != null && error.body.errors != null) {
                    error.body.errors.forEach(anError => {
                        errorContents = this.showValidationError(anError, errorContents, notification);
                    });
                } else {
                    this.notifyUnexpectedError(notification);
                }

                validationErrors.body = errorContents.errorsForBody;
                stateToSet = {
                    ...this.state,
                    validationErrors
                };
                stateToSet.email.errorMsg = errorContents.emailMessage;
                stateToSet.password.errorMsg = errorContents.passwordMessage;
                // Temporary code until login work is connected to dp-identity-api
                if (error.status === 417) {
                    stateToSet.requestPasswordChange = true;
                }
                // End of temporary code
            } else {
                this.notifyUnexpectedError(notification);
            }
        } else {
            this.notifyUnexpectedError(notification);
        }

        return stateToSet;
    }

    showValidationError(anError, errorContents, notification) {
        switch (anError.code) {
            case "InvalidEmail":
                errorContents.errorsForBody.push(
                    <p>
                        <a href="javascript:document.getElementById('email').focus()" className={"colour--night-shadz"}>
                            Enter a valid email address
                        </a>
                    </p>
                );
                errorContents.emailMessage = "Enter a valid email address";
                break;
            case "InvalidPassword":
                errorContents.errorsForBody.push(
                    <p>
                        <a href="javascript:document.getElementById('password').focus()" className={"colour--night-shadz"}>
                            Enter a password
                        </a>
                    </p>
                );
                errorContents.passwordMessage = "<PASSWORD>";
                break;
            case "NotAuthorised":
                errorContents.errorsForBody.push(<p>Email address or password are incorrect</p>);
                break;
            case "TooManyFailedAttempts":
                errorContents.errorsForBody.push(<p>You've tried to sign in to your account too many times. Please try again later.</p>);
                break;
            default:
                // Code undefined or different to expected range of errors
                this.notifyUnexpectedError(notification);
        }
        return errorContents;
    }

    notifyUnexpectedError(notification) {
        console.error(errCodes.LOGIN_UNEXPECTED_ERR);
        notification.message = errCodes.LOGIN_UNEXPECTED_ERR;
        notifications.add(notification);
    }

    handleLogin(accessToken, userToken, refreshToken) {
        cookies.add("access_token", accessToken, "/", null, "strict", true);
        cookies.add("user_token", userToken, "/", null, "strict", true);
        cookies.add("refresh_token", refreshToken, "/tokens/self", null, "strict", true);
        user.getPermissions(this.state.email.value)
            .then(userType => {
                user.setUserState(userType);
                redirectToMainScreen(this.props.location.query.redirect);
            })
            .catch(error => {
                this.setState({ isSubmitting: false });
                notifications.add({
                    type: "warning",
                    message: "Unable to login due to an error getting your account's permissions. Please refresh and try again.",
                    autoDismiss: 8000,
                    isDismissable: true
                });
                log.event("Error getting a user's permissions on login", log.error(error));
                console.error("Error getting a user's permissions on login", error);
            });
    }

    handleSubmit(event) {
        event.preventDefault();
{'fraction_non_alphanumeric': 0.10586966776736977, 'fraction_numerical': 0.002426039490531707, 'mean_word_length': 1.6845151953690305, 'pattern_counts': {'":': 8, '<': 30, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4029139', 'n_tokens_mistral': 3641, 'n_tokens_neox': 3451, 'n_words': 766}