AuthRoute.jsx 4.8 KB

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