AuthRoute.jsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import React, { Component } from "react";
  2. import { connect } from "react-redux";
  3. import PropTypes from "prop-types";
  4. import { Redirect, Route } from "react-router-dom";
  5. import { translate } from "react-i18next";
  6. import io from "io";
  7. const renderMergedProps = (component, ...rest) => {
  8. const finalProps = Object.assign({}, ...rest);
  9. return (
  10. React.createElement(component, finalProps)
  11. );
  12. };
  13. const PropsRoute = ({ component, ...rest }) => {
  14. return (
  15. <Route {...rest} render={routeProps => {
  16. return renderMergedProps(component, routeProps, rest);
  17. }}/>
  18. );
  19. };
  20. // Above two functions are from https://github.com/ReactTraining/react-router/issues/4105#issuecomment-289195202
  21. @connect(state => ({
  22. loggedIn: state.user.get("loggedIn"),
  23. role: state.user.get("role"),
  24. authProcessed: state.user.get("authProcessed"),
  25. }))
  26. @translate(["general"], { wait: true })
  27. export default class AuthRoute extends Component {
  28. static propTypes = {
  29. loggedIn: PropTypes.bool,
  30. title: PropTypes.string,
  31. role: PropTypes.string,
  32. auth: PropTypes.string,
  33. authProcessed: PropTypes.bool,
  34. component: PropTypes.oneOfType([
  35. PropTypes.element,
  36. PropTypes.func,
  37. ]),
  38. computedMatch: PropTypes.object,
  39. t: PropTypes.func,
  40. };
  41. static defaultProps = {
  42. loggedIn: false,
  43. title: "Musare",
  44. role: "default",
  45. auth: "ignored",
  46. authProcessed: false,
  47. component: () => {},
  48. computedMatch: {},
  49. t: () => {},
  50. };
  51. constructor(props) {
  52. super(props);
  53. const state = {
  54. stationName: props.computedMatch.params.name,
  55. waitingFor: "",
  56. continue: false,
  57. stationData: null,
  58. receivedStationData: false,
  59. };
  60. const { auth } = props;
  61. if (auth === "ignored") state.continue = true;
  62. else if (auth === "station") {
  63. state.waitingFor = "station";
  64. this.getStationData();
  65. } else state.waitingFor = "auth";
  66. this.state = state;
  67. }
  68. componentWillUpdate(nextProps) {
  69. document.title = `${ nextProps.title } - Musare`;
  70. }
  71. getStationData = () => {
  72. io.getSocket(socket => {
  73. socket.emit("stations.findByName", this.state.stationName, res => {
  74. this.setState({
  75. receivedStationData: true,
  76. stationData: res.data,
  77. });
  78. });
  79. });
  80. };
  81. render() {
  82. const { auth, role, loggedIn, authProcessed, t } = this.props;
  83. const { stationName, waitingFor, receivedStationData, stationData } = this.state;
  84. if (this.state.continue) {
  85. return <PropsRoute props={ this.props } component={ this.props.component }/>
  86. } else if (waitingFor === "station" && receivedStationData) {
  87. if (stationData) {
  88. const props = JSON.parse(JSON.stringify(this.props));
  89. // TODO Replace the above hack with a proper Object.clone
  90. props.stationName = stationName;
  91. props.stationData = stationData;
  92. return <Route props={ props } component={ this.props.component } />;
  93. }
  94. return <Redirect to={ "/" } />;
  95. } else if (waitingFor === "auth" && authProcessed) {
  96. if (auth === "required") {
  97. if (loggedIn) return <Route props={ this.props } component={ this.props.component } />;
  98. return <Redirect to={ "/" } />;
  99. } else if (auth === "disallowed") {
  100. if (!loggedIn) return <Route props={ this.props } component={ this.props.component } />;
  101. return <Redirect to={ "/login" } />;
  102. } else if (auth === "admin") {
  103. if (role === "admin") return <Route props={ this.props } component={ this.props.component } />;
  104. return <Redirect to={ "/" } />;
  105. }
  106. }
  107. return <h1>{ t("general:loading") }</h1>;
  108. }
  109. }