AuthRoute.jsx 4.6 KB

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