AuthRoute.jsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 { initializeStation } from "actions/station";
  7. import io from "io";
  8. const renderMergedProps = (component, ...rest) => {
  9. const finalProps = Object.assign({}, ...rest);
  10. return (
  11. React.createElement(component, finalProps)
  12. );
  13. };
  14. const PropsRoute = ({ component, ...rest }) => {
  15. return (
  16. <Route {...rest} render={routeProps => {
  17. return renderMergedProps(component, routeProps, rest);
  18. }}/>
  19. );
  20. };
  21. // Above two functions are from https://github.com/ReactTraining/react-router/issues/4105#issuecomment-289195202
  22. function clone(obj) {
  23. return Object.assign({}, obj);
  24. }
  25. @connect(state => ({
  26. loggedIn: state.user.get("loggedIn"),
  27. role: state.user.get("role"),
  28. authProcessed: state.user.get("authProcessed"),
  29. station: {
  30. stationId: state.station.get("id"),
  31. name: state.station.get("name"),
  32. },
  33. }))
  34. @translate(["general"], { wait: true })
  35. export default class AuthRoute extends Component {
  36. static propTypes = {
  37. loggedIn: PropTypes.bool,
  38. title: PropTypes.string,
  39. role: PropTypes.string,
  40. auth: PropTypes.string,
  41. authProcessed: PropTypes.bool,
  42. component: PropTypes.oneOfType([
  43. PropTypes.element,
  44. PropTypes.func,
  45. ]),
  46. computedMatch: PropTypes.object,
  47. t: PropTypes.func,
  48. };
  49. static defaultProps = {
  50. loggedIn: false,
  51. title: "Musare",
  52. role: "default",
  53. auth: "ignored",
  54. authProcessed: false,
  55. component: () => {},
  56. computedMatch: {},
  57. t: () => {},
  58. };
  59. constructor(props) {
  60. super(props);
  61. const state = {
  62. stationName: props.computedMatch.params.name,
  63. waitingFor: "",
  64. continue: false,
  65. stationData: null,
  66. receivedStationData: false,
  67. };
  68. const { auth } = props;
  69. let getStationData = false;
  70. if (auth === "ignored") state.continue = true;
  71. else if (auth === "station") {
  72. state.waitingFor = "station";
  73. getStationData = true;
  74. } else state.waitingFor = "auth";
  75. this.state = state;
  76. if (getStationData) this.getStationData();
  77. }
  78. componentWillUpdate(nextProps) {
  79. document.title = `${ nextProps.title } - Musare`;
  80. }
  81. getStationData = () => {
  82. io.getSocket(socket => {
  83. socket.emit("stations.findByName", this.state.stationName, res => {
  84. if (res.status === "success") {
  85. this.props.dispatch(initializeStation({
  86. //TODO Refactor this to be better optimized
  87. stationId: res.data._id,
  88. name: res.data.name,
  89. displayName: res.data.displayName,
  90. description: res.data.description,
  91. privacy: res.data.privacy,
  92. locked: res.data.locked,
  93. partyMode: res.data.partyMode,
  94. owner: res.data.owner,
  95. privatePlaylist: res.data.privatePlaylist,
  96. type: res.data.type,
  97. paused: res.data.paused,
  98. pausedAt: res.data.pausedAt,
  99. }));
  100. } else {
  101. this.setState({
  102. noStation: true,
  103. });
  104. }
  105. });
  106. });
  107. };
  108. render() {
  109. const { auth, role, loggedIn, authProcessed, t } = this.props;
  110. const { waitingFor, receivedStationData } = this.state;
  111. if (this.state.continue) {
  112. return <PropsRoute props={ this.props } component={ this.props.component }/>
  113. } else if (waitingFor === "station") {
  114. if (this.props.station.stationId) {
  115. // TODO Replace the above hack with a proper Object.clone
  116. return <Route component={ this.props.component } />;
  117. } else if (this.state.noStation) {
  118. return <Redirect to={ "/" } />;
  119. }
  120. } else if (waitingFor === "auth" && authProcessed) {
  121. if (auth === "required") {
  122. if (loggedIn) return <Route props={ this.props } component={ this.props.component } />;
  123. return <Redirect to={ "/" } />;
  124. } else if (auth === "disallowed") {
  125. if (!loggedIn) return <Route props={ this.props } component={ this.props.component } />;
  126. return <Redirect to={ "/login" } />;
  127. } else if (auth === "admin") {
  128. if (role === "admin") return <Route props={ this.props } component={ this.props.component } />;
  129. return <Redirect to={ "/" } />;
  130. }
  131. }
  132. return <h1>{ t("general:loading") }</h1>;
  133. }
  134. }