Advertisement
Guest User

Untitled

a guest
Oct 7th, 2017
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React, { Component } from 'react';
  2. import _ from 'lodash';
  3. import axios from 'axios';
  4. import PropTypes from 'prop-types';
  5. import config from 'config/environment';
  6. import { Link } from 'react-router-dom';
  7. import styles from './login.css';
  8. import Form from '../form/form';
  9. import Section from '../section/section';
  10. import * as CookieHelpers from '../../utils/cookieHelper';
  11. import FormEmail from '../form/formEmail/formEmail';
  12. import FormInput from '../form/formInput/formInput';
  13. import FormButton from '../form/formButton/formButton';
  14. import SignUpSection from './signUpSection';
  15.  
  16. require('./login.css');
  17. const queryString = require('query-string');
  18.  
  19. class Login extends Component {
  20.   state = {
  21.     email: '',
  22.     emailValid: false,
  23.     password: '',
  24.     passwordValid: false,
  25.     authenticated: false,
  26.     errorStatus: -1,
  27.     errorMessage: '',
  28.     error: '',
  29.     sso: null,
  30.     sig: null,
  31.     ssoParamsPresent: false
  32.   };
  33.  
  34.   componentDidMount = () => {
  35.     this.checkForSsoParams();
  36.   };
  37.  
  38.   onEmailChange = (value, valid) => {
  39.     this.setState({ email: value, emailValid: valid });
  40.   };
  41.  
  42.   onPasswordChange = (value, valid) => {
  43.     this.setState({ password: value, passwordValid: valid });
  44.   };
  45.  
  46.   setErrorMessage = (error) => {
  47.     const errorStatus = _.get(error, ['response', 'status'], -1);
  48.     const errorMessage = _.get(error, 'message');
  49.     this.setState({ errorStatus, errorMessage });
  50.   };
  51.  
  52.   setSsoParams = () => {
  53.     const parsed = queryString.parse(location.search);
  54.  
  55.     if (this.state.ssoParamsPresent) {
  56.       this.setState(
  57.         {
  58.           sso: parsed.sso,
  59.           sig: parsed.sig
  60.         },
  61.         this.checkSsoLoggedIn
  62.       );
  63.     }
  64.   };
  65.  
  66.   // SSO Flow:
  67.   //   * Discourse sends us an SSO token and a signature for that token (shared key)
  68.   //     If those params exist we assume we're doing an SSO login.
  69.   //
  70.   //   Scenario: user not logged in
  71.   //     * If the user is not logged in they enter their creds and we pass along the
  72.   //       token and sig to the backend where it's verified
  73.   //     * If we have a succesful login we redirect back to discourse with our payload and sig
  74.   //     * These values are provided by the backend
  75.   //
  76.   //   Scenario: user logged in
  77.   //     * When the login page mounts we check to see if the user is logged in via props
  78.   //     * If the user is logged in AND this is an SSO request we perform a GET request with
  79.   //       the token and sig
  80.   //     * If the users auth token is valid and the token and sig are valid we redirect back
  81.   //       to discourse with our payload and sig
  82.   //     * These values are provided by the backend
  83.   checkForSsoParams = () => {
  84.     const parsed = queryString.parse(location.search);
  85.  
  86.     if (parsed.sso && parsed.sig) {
  87.       this.setState({ ssoParamsPresent: true }, this.setSsoParams);
  88.     }
  89.   };
  90.  
  91.   checkSsoLoggedIn = () => {
  92.     if (this.state.ssoParamsPresent && this.props.isLoggedIn) {
  93.       this.ssoLoggedInRedirect();
  94.     }
  95.   };
  96.  
  97.   ssoLoggedInRedirect = () => {
  98.     axios
  99.       .get(
  100.         `${config.backendUrl}/sessions/sso?sso=${encodeURI(this.state.sso)}&sig=${this.state.sig}`,
  101.         {
  102.           headers: {
  103.             Authorization: `Bearer ${CookieHelpers.authToken()}`
  104.           }
  105.         }
  106.       )
  107.       .then(({ data }) => {
  108.         window.location = data.redirect_to;
  109.       })
  110.       .catch((error) => {
  111.         this.setErrorMessage(error);
  112.       });
  113.   };
  114.  
  115.   isFormValid = () => this.state.emailValid && this.state.passwordValid;
  116.  
  117.   // This is a temp function to ensure we return a URL if the changes to the API
  118.   // aren't in place. It can be removed after operationcode_backend#91 has been deployed
  119.   resolveRedirectUrl = (redirectUrl) => {
  120.     if (redirectUrl) {
  121.       return redirectUrl;
  122.     }
  123.     return '/profile';
  124.   };
  125.  
  126.   handleOnClick = (e) => {
  127.     e.preventDefault();
  128.  
  129.     if (this.isFormValid()) {
  130.       axios
  131.         .post(`${config.backendUrl}/sessions`, {
  132.           user: {
  133.             email: this.state.email,
  134.             password: this.state.password
  135.           },
  136.           sso: this.state.sso,
  137.           sig: this.state.sig
  138.         })
  139.         .then(({ data }) => {
  140.           CookieHelpers.setUserAuthCookie(data);
  141.           this.setState({ authenticated: true });
  142.           this.props.updateRootAuthState((history) => {
  143.             if (this.state.ssoParamsPresent) {
  144.               window.location = data.redirect_to;
  145.             } else {
  146.               history.push(this.resolveRedirectUrl(data.redirect_to));
  147.             }
  148.           });
  149.         })
  150.         .catch((error) => {
  151.           this.setErrorMessage(error);
  152.         });
  153.     }
  154.   };
  155.  
  156.   render() {
  157.     const { errorStatus, errorMessage } = this.state;
  158.     let errorFeedback;
  159.     if (errorStatus === 401) {
  160.       errorFeedback = 'Sorry, you entered an invalid email or password.';
  161.     } else if (errorMessage) {
  162.       errorFeedback = `Login error: ${errorMessage}.`;
  163.     }
  164.  
  165.     return (
  166.       <div className={styles.gridRow}>
  167.         <Section title="Login" theme="white">
  168.           <Form autoComplete>
  169.             <FormEmail id="email" displayName="Email" label="Email" onChange={this.onEmailChange} />
  170.             <FormInput
  171.               id="password"
  172.               displayName="Password"
  173.               label="Password"
  174.               inputType="password"
  175.               onChange={this.onPasswordChange}
  176.             />
  177.             {errorFeedback && <h2 className={styles.loginError}>{errorFeedback}</h2>}
  178.             <FormButton className={styles.Button} text="Login" onClick={this.handleOnClick} />
  179.             <Link className={styles.resetBtn} to="/reset_password">
  180.               Reset Password
  181.             </Link>
  182.           </Form>
  183.         </Section>
  184.  
  185.         <SignUpSection />
  186.       </div>
  187.     );
  188.   }
  189. }
  190.  
  191. Login.propTypes = {
  192.   updateRootAuthState: PropTypes.func,
  193.   isLoggedIn: PropTypes.bool
  194. };
  195.  
  196. Login.defaultProps = {
  197.   updateRootAuthState: () => {},
  198.   isLoggedIn: false
  199. };
  200.  
  201. export default Login;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement