AuthRoute.jsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. function clone(obj) {
  22. return Object.assign({}, obj);
  23. }
  24. @connect(state => ({
  25. loggedIn: state.user.get("loggedIn"),
  26. role: state.user.get("role"),
  27. authProcessed: state.user.get("authProcessed"),
  28. }))
  29. @translate(["general"], { wait: true })
  30. export default class AuthRoute extends Component {
  31. static propTypes = {
  32. loggedIn: PropTypes.bool,
  33. title: PropTypes.string,
  34. role: PropTypes.string,
  35. auth: PropTypes.string,
  36. authProcessed: PropTypes.bool,
  37. component: PropTypes.oneOfType([
  38. PropTypes.element,
  39. PropTypes.func,
  40. ]),
  41. computedMatch: PropTypes.object,
  42. t: PropTypes.func,
  43. };
  44. static defaultProps = {
  45. loggedIn: false,
  46. title: "Musare",
  47. role: "default",
  48. auth: "ignored",
  49. authProcessed: false,
  50. component: () => {},
  51. computedMatch: {},
  52. t: () => {},
  53. };
  54. constructor(props) {
  55. super(props);
  56. const state = {
  57. stationName: props.computedMatch.params.name,
  58. waitingFor: "",
  59. continue: false,
  60. stationData: null,
  61. receivedStationData: false,
  62. };
  63. const { auth } = props;
  64. let getStationData = false;
  65. if (auth === "ignored") state.continue = true;
  66. else if (auth === "station") {
  67. state.waitingFor = "station";
  68. getStationData = true;
  69. } else state.waitingFor = "auth";
  70. this.state = state;
  71. if (getStationData) this.getStationData();
  72. }
  73. componentWillUpdate(nextProps) {
  74. document.title = `${ nextProps.title } - Musare`;
  75. }
  76. getStationData = () => {
  77. io.getSocket(socket => {
  78. socket.emit("stations.findByName", this.state.stationName, res => {
  79. this.setState({
  80. receivedStationData: true,
  81. stationData: res.data,
  82. });
  83. });
  84. });
  85. };
  86. render() {
  87. const { auth, role, loggedIn, authProcessed, t } = this.props;
  88. const { stationName, waitingFor, receivedStationData, stationData } = this.state;
  89. if (this.state.continue) {
  90. return <PropsRoute props={ this.props } component={ this.props.component }/>
  91. } else if (waitingFor === "station" && receivedStationData) {
  92. if (stationData) {
  93. const props = clone(this.props);
  94. // TODO Replace the above hack with a proper Object.clone
  95. props.stationName = stationName;
  96. props.stationData = stationData;
  97. window.props = props; //TODO Replace
  98. return <Route component={ this.props.component } />;
  99. }
  100. return <Redirect to={ "/" } />;
  101. } else if (waitingFor === "auth" && authProcessed) {
  102. if (auth === "required") {
  103. if (loggedIn) return <Route props={ this.props } component={ this.props.component } />;
  104. return <Redirect to={ "/" } />;
  105. } else if (auth === "disallowed") {
  106. if (!loggedIn) return <Route props={ this.props } component={ this.props.component } />;
  107. return <Redirect to={ "/login" } />;
  108. } else if (auth === "admin") {
  109. if (role === "admin") return <Route props={ this.props } component={ this.props.component } />;
  110. return <Redirect to={ "/" } />;
  111. }
  112. }
  113. return <h1>{ t("general:loading") }</h1>;
  114. }
  115. }